forked from quic-go/quic-go
add an integration test corrupts packets
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
quic "github.com/lucas-clemente/quic-go"
|
quic "github.com/lucas-clemente/quic-go"
|
||||||
@@ -30,6 +31,7 @@ var _ = Describe("MITM test", func() {
|
|||||||
proxy *quicproxy.QuicProxy
|
proxy *quicproxy.QuicProxy
|
||||||
serverConn, clientConn *net.UDPConn
|
serverConn, clientConn *net.UDPConn
|
||||||
serverSess quic.Session
|
serverSess quic.Session
|
||||||
|
serverConfig *quic.Config
|
||||||
)
|
)
|
||||||
|
|
||||||
startServerAndProxy := func(delayCb quicproxy.DelayCallback, dropCb quicproxy.DropCallback) {
|
startServerAndProxy := func(delayCb quicproxy.DelayCallback, dropCb quicproxy.DropCallback) {
|
||||||
@@ -37,14 +39,7 @@ var _ = Describe("MITM test", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
serverConn, err = net.ListenUDP("udp", addr)
|
serverConn, err = net.ListenUDP("udp", addr)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
ln, err := quic.Listen(
|
ln, err := quic.Listen(serverConn, getTLSConfig(), serverConfig)
|
||||||
serverConn,
|
|
||||||
getTLSConfig(),
|
|
||||||
&quic.Config{
|
|
||||||
Versions: []protocol.VersionNumber{version},
|
|
||||||
ConnectionIDLength: connIDLen,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
go func() {
|
go func() {
|
||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
@@ -67,6 +62,10 @@ var _ = Describe("MITM test", func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
|
serverConfig = &quic.Config{
|
||||||
|
Versions: []protocol.VersionNumber{version},
|
||||||
|
ConnectionIDLength: connIDLen,
|
||||||
|
}
|
||||||
addr, err := net.ResolveUDPAddr("udp", "localhost:0")
|
addr, err := net.ResolveUDPAddr("udp", "localhost:0")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
clientConn, err = net.ListenUDP("udp", addr)
|
clientConn, err = net.ListenUDP("udp", addr)
|
||||||
@@ -164,7 +163,6 @@ var _ = Describe("MITM test", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("duplicating packets", func() {
|
|
||||||
runTest := func(dropCb quicproxy.DropCallback) {
|
runTest := func(dropCb quicproxy.DropCallback) {
|
||||||
startServerAndProxy(nil, dropCb)
|
startServerAndProxy(nil, dropCb)
|
||||||
raddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("localhost:%d", proxy.LocalPort()))
|
raddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("localhost:%d", proxy.LocalPort()))
|
||||||
@@ -188,6 +186,7 @@ var _ = Describe("MITM test", func() {
|
|||||||
Expect(sess.Close()).To(Succeed())
|
Expect(sess.Close()).To(Succeed())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context("duplicating packets", func() {
|
||||||
It("downloads a message when packets are duplicated towards the server", func() {
|
It("downloads a message when packets are duplicated towards the server", func() {
|
||||||
dropCb := func(dir quicproxy.Direction, raw []byte) bool {
|
dropCb := func(dir quicproxy.Direction, raw []byte) bool {
|
||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
@@ -212,6 +211,60 @@ var _ = Describe("MITM test", func() {
|
|||||||
runTest(dropCb)
|
runTest(dropCb)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("corrupting packets", func() {
|
||||||
|
const interval = 10 // corrupt every 10th packet (stochastically)
|
||||||
|
const idleTimeout = time.Second
|
||||||
|
|
||||||
|
var numCorrupted int32
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
numCorrupted = 0
|
||||||
|
serverConfig.IdleTimeout = idleTimeout
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
num := atomic.LoadInt32(&numCorrupted)
|
||||||
|
fmt.Fprintf(GinkgoWriter, "Corrupted %d packets.", num)
|
||||||
|
Expect(num).To(BeNumerically(">=", 1))
|
||||||
|
// If the packet containing the CONNECTION_CLOSE is corrupted,
|
||||||
|
// we have to wait for the session to time out.
|
||||||
|
Eventually(serverSess.Context().Done(), 3*idleTimeout).Should(BeClosed())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("downloads a message when packet are corrupted towards the server", func() {
|
||||||
|
dropCb := func(dir quicproxy.Direction, raw []byte) bool {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
if dir == quicproxy.DirectionIncoming && mrand.Intn(interval) == 0 {
|
||||||
|
pos := mrand.Intn(len(raw))
|
||||||
|
raw[pos] = byte(mrand.Intn(256))
|
||||||
|
_, err := clientConn.WriteTo(raw, serverConn.LocalAddr())
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
atomic.AddInt32(&numCorrupted, 1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
runTest(dropCb)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("downloads a message when packet are corrupted towards the client", func() {
|
||||||
|
dropCb := func(dir quicproxy.Direction, raw []byte) bool {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
isRetry := raw[0]&0xc0 == 0xc0 // don't corrupt Retry packets
|
||||||
|
if dir == quicproxy.DirectionOutgoing && mrand.Intn(interval) == 0 && !isRetry {
|
||||||
|
pos := mrand.Intn(len(raw))
|
||||||
|
raw[pos] = byte(mrand.Intn(256))
|
||||||
|
_, err := serverConn.WriteTo(raw, clientConn.LocalAddr())
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
atomic.AddInt32(&numCorrupted, 1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
runTest(dropCb)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user