github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/integrationtests/self/stateless_reset_test.go (about) 1 package self_test 2 3 import ( 4 "context" 5 "crypto/rand" 6 "fmt" 7 "net" 8 "sync/atomic" 9 "time" 10 11 "github.com/danielpfeifer02/quic-go-prio-packs" 12 quicproxy "github.com/danielpfeifer02/quic-go-prio-packs/integrationtests/tools/proxy" 13 14 . "github.com/onsi/ginkgo/v2" 15 . "github.com/onsi/gomega" 16 ) 17 18 var _ = Describe("Stateless Resets", func() { 19 connIDLens := []int{0, 10} 20 21 for i := range connIDLens { 22 connIDLen := connIDLens[i] 23 24 It(fmt.Sprintf("sends and recognizes stateless resets, for %d byte connection IDs", connIDLen), func() { 25 var statelessResetKey quic.StatelessResetKey 26 rand.Read(statelessResetKey[:]) 27 28 c, err := net.ListenUDP("udp", nil) 29 Expect(err).ToNot(HaveOccurred()) 30 tr := &quic.Transport{ 31 Conn: c, 32 StatelessResetKey: &statelessResetKey, 33 ConnectionIDLength: connIDLen, 34 } 35 defer tr.Close() 36 ln, err := tr.Listen(getTLSConfig(), getQuicConfig(nil)) 37 Expect(err).ToNot(HaveOccurred()) 38 serverPort := ln.Addr().(*net.UDPAddr).Port 39 40 closeServer := make(chan struct{}) 41 42 go func() { 43 defer GinkgoRecover() 44 conn, err := ln.Accept(context.Background()) 45 Expect(err).ToNot(HaveOccurred()) 46 str, err := conn.OpenStream() 47 Expect(err).ToNot(HaveOccurred()) 48 _, err = str.Write([]byte("foobar")) 49 Expect(err).ToNot(HaveOccurred()) 50 <-closeServer 51 Expect(ln.Close()).To(Succeed()) 52 Expect(tr.Close()).To(Succeed()) 53 }() 54 55 var drop atomic.Bool 56 proxy, err := quicproxy.NewQuicProxy("localhost:0", &quicproxy.Opts{ 57 RemoteAddr: fmt.Sprintf("localhost:%d", serverPort), 58 DropPacket: func(quicproxy.Direction, []byte) bool { 59 return drop.Load() 60 }, 61 }) 62 Expect(err).ToNot(HaveOccurred()) 63 defer proxy.Close() 64 65 addr, err := net.ResolveUDPAddr("udp", "localhost:0") 66 Expect(err).ToNot(HaveOccurred()) 67 udpConn, err := net.ListenUDP("udp", addr) 68 Expect(err).ToNot(HaveOccurred()) 69 defer udpConn.Close() 70 cl := &quic.Transport{ 71 Conn: udpConn, 72 ConnectionIDLength: connIDLen, 73 } 74 defer cl.Close() 75 conn, err := cl.Dial( 76 context.Background(), 77 &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: proxy.LocalPort()}, 78 getTLSClientConfig(), 79 getQuicConfig(&quic.Config{MaxIdleTimeout: 2 * time.Second}), 80 ) 81 Expect(err).ToNot(HaveOccurred()) 82 str, err := conn.AcceptStream(context.Background()) 83 Expect(err).ToNot(HaveOccurred()) 84 data := make([]byte, 6) 85 _, err = str.Read(data) 86 Expect(err).ToNot(HaveOccurred()) 87 Expect(data).To(Equal([]byte("foobar"))) 88 89 // make sure that the CONNECTION_CLOSE is dropped 90 drop.Store(true) 91 close(closeServer) 92 time.Sleep(100 * time.Millisecond) 93 94 // We need to create a new Transport here, since the old one is still sending out 95 // CONNECTION_CLOSE packets for (recently) closed connections). 96 tr2 := &quic.Transport{ 97 Conn: c, 98 ConnectionIDLength: connIDLen, 99 StatelessResetKey: &statelessResetKey, 100 } 101 defer tr2.Close() 102 ln2, err := tr2.Listen(getTLSConfig(), getQuicConfig(nil)) 103 Expect(err).ToNot(HaveOccurred()) 104 drop.Store(false) 105 106 acceptStopped := make(chan struct{}) 107 go func() { 108 defer GinkgoRecover() 109 _, err := ln2.Accept(context.Background()) 110 Expect(err).To(HaveOccurred()) 111 close(acceptStopped) 112 }() 113 114 // Trigger something (not too small) to be sent, so that we receive the stateless reset. 115 // If the client already sent another packet, it might already have received a packet. 116 _, serr := str.Write([]byte("Lorem ipsum dolor sit amet.")) 117 if serr == nil { 118 _, serr = str.Read([]byte{0}) 119 } 120 Expect(serr).To(HaveOccurred()) 121 Expect(serr).To(BeAssignableToTypeOf(&quic.StatelessResetError{})) 122 Expect(ln2.Close()).To(Succeed()) 123 Eventually(acceptStopped).Should(BeClosed()) 124 }) 125 } 126 })