From 19cf46d73686d62bf8383b42b9d6fe1e5b057795 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Wed, 6 Mar 2019 14:40:00 +0900 Subject: [PATCH] add an integration test for stateless resets --- integrationtests/self/stateless_reset_test.go | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 integrationtests/self/stateless_reset_test.go diff --git a/integrationtests/self/stateless_reset_test.go b/integrationtests/self/stateless_reset_test.go new file mode 100644 index 00000000..2a565830 --- /dev/null +++ b/integrationtests/self/stateless_reset_test.go @@ -0,0 +1,106 @@ +package self + +import ( + "crypto/tls" + "fmt" + "math/rand" + "net" + "time" + + quic "github.com/lucas-clemente/quic-go" + quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy" + "github.com/lucas-clemente/quic-go/internal/testdata" + "github.com/lucas-clemente/quic-go/internal/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Stateless Resets", func() { + connIDLens := []int{0, 10} + + for i := range connIDLens { + connIDLen := connIDLens[i] + + It(fmt.Sprintf("sends and recognizes stateless resets, for %d byte connection IDs", connIDLen), func() { + statelessResetKey := make([]byte, 32) + rand.Read(statelessResetKey) + serverConfig := &quic.Config{StatelessResetKey: statelessResetKey} + + ln, err := quic.ListenAddr("localhost:0", testdata.GetTLSConfig(), serverConfig) + Expect(err).ToNot(HaveOccurred()) + serverPort := ln.Addr().(*net.UDPAddr).Port + + closeServer := make(chan struct{}) + + go func() { + defer GinkgoRecover() + sess, err := ln.Accept() + Expect(err).ToNot(HaveOccurred()) + str, err := sess.OpenStream() + Expect(err).ToNot(HaveOccurred()) + _, err = str.Write([]byte("foobar")) + Expect(err).ToNot(HaveOccurred()) + <-closeServer + ln.Close() + }() + + drop := utils.AtomicBool{} + + proxy, err := quicproxy.NewQuicProxy("localhost:0", &quicproxy.Opts{ + RemoteAddr: fmt.Sprintf("localhost:%d", serverPort), + DropPacket: func(d quicproxy.Direction, p uint64) bool { + return drop.Get() + }, + }) + Expect(err).ToNot(HaveOccurred()) + defer proxy.Close() + + sess, err := quic.DialAddr( + fmt.Sprintf("localhost:%d", proxy.LocalPort()), + &tls.Config{RootCAs: testdata.GetRootCA()}, + &quic.Config{ + ConnectionIDLength: connIDLen, + IdleTimeout: 2 * time.Second, + }, + ) + Expect(err).ToNot(HaveOccurred()) + str, err := sess.AcceptStream() + Expect(err).ToNot(HaveOccurred()) + data := make([]byte, 6) + _, err = str.Read(data) + Expect(err).ToNot(HaveOccurred()) + Expect(data).To(Equal([]byte("foobar"))) + + // make sure that the CONNECTION_CLOSE is dropped + drop.Set(true) + close(closeServer) + time.Sleep(100 * time.Millisecond) + + ln2, err := quic.ListenAddr( + fmt.Sprintf("localhost:%d", serverPort), + testdata.GetTLSConfig(), + serverConfig, + ) + Expect(err).ToNot(HaveOccurred()) + drop.Set(false) + + acceptStopped := make(chan struct{}) + go func() { + defer GinkgoRecover() + _, err := ln2.Accept() + Expect(err).To(HaveOccurred()) + close(acceptStopped) + }() + + // trigger something (not too small) to be sent, + // so that we receive the stateless reset + _, err = str.Write([]byte("Lorem ipsum dolor sit amet.")) + Expect(err).ToNot(HaveOccurred()) + _, err = str.Read([]byte{0}) + Expect(err).To(MatchError("INTERNAL_ERROR: received a stateless reset")) + + Expect(ln2.Close()).To(Succeed()) + Eventually(acceptStopped).Should(BeClosed()) + }) + } +})