github.com/tumi8/quic-go@v0.37.4-tum/integrationtests/self/multiplex_test.go (about) 1 package self_test 2 3 import ( 4 "context" 5 "io" 6 "net" 7 "runtime" 8 "time" 9 10 "github.com/tumi8/quic-go" 11 12 . "github.com/onsi/ginkgo/v2" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("Multiplexing", func() { 17 runServer := func(ln *quic.Listener) { 18 go func() { 19 defer GinkgoRecover() 20 for { 21 conn, err := ln.Accept(context.Background()) 22 if err != nil { 23 return 24 } 25 go func() { 26 defer GinkgoRecover() 27 str, err := conn.OpenStream() 28 Expect(err).ToNot(HaveOccurred()) 29 defer str.Close() 30 _, err = str.Write(PRData) 31 Expect(err).ToNot(HaveOccurred()) 32 }() 33 } 34 }() 35 } 36 37 dial := func(tr *quic.Transport, addr net.Addr) { 38 conn, err := tr.Dial( 39 context.Background(), 40 addr, 41 getTLSClientConfig(), 42 getQuicConfig(nil), 43 ) 44 Expect(err).ToNot(HaveOccurred()) 45 defer conn.CloseWithError(0, "") 46 str, err := conn.AcceptStream(context.Background()) 47 Expect(err).ToNot(HaveOccurred()) 48 data, err := io.ReadAll(str) 49 Expect(err).ToNot(HaveOccurred()) 50 Expect(data).To(Equal(PRData)) 51 } 52 53 Context("multiplexing clients on the same conn", func() { 54 getListener := func() *quic.Listener { 55 ln, err := quic.ListenAddr( 56 "localhost:0", 57 getTLSConfig(), 58 getQuicConfig(nil), 59 ) 60 Expect(err).ToNot(HaveOccurred()) 61 return ln 62 } 63 64 It("multiplexes connections to the same server", func() { 65 server := getListener() 66 runServer(server) 67 defer server.Close() 68 69 addr, err := net.ResolveUDPAddr("udp", "localhost:0") 70 Expect(err).ToNot(HaveOccurred()) 71 conn, err := net.ListenUDP("udp", addr) 72 Expect(err).ToNot(HaveOccurred()) 73 defer conn.Close() 74 tr := &quic.Transport{Conn: conn} 75 76 done1 := make(chan struct{}) 77 done2 := make(chan struct{}) 78 go func() { 79 defer GinkgoRecover() 80 dial(tr, server.Addr()) 81 close(done1) 82 }() 83 go func() { 84 defer GinkgoRecover() 85 dial(tr, server.Addr()) 86 close(done2) 87 }() 88 timeout := 30 * time.Second 89 if debugLog() { 90 timeout = time.Minute 91 } 92 Eventually(done1, timeout).Should(BeClosed()) 93 Eventually(done2, timeout).Should(BeClosed()) 94 }) 95 96 It("multiplexes connections to different servers", func() { 97 server1 := getListener() 98 runServer(server1) 99 defer server1.Close() 100 server2 := getListener() 101 runServer(server2) 102 defer server2.Close() 103 104 addr, err := net.ResolveUDPAddr("udp", "localhost:0") 105 Expect(err).ToNot(HaveOccurred()) 106 conn, err := net.ListenUDP("udp", addr) 107 Expect(err).ToNot(HaveOccurred()) 108 defer conn.Close() 109 tr := &quic.Transport{Conn: conn} 110 111 done1 := make(chan struct{}) 112 done2 := make(chan struct{}) 113 go func() { 114 defer GinkgoRecover() 115 dial(tr, server1.Addr()) 116 close(done1) 117 }() 118 go func() { 119 defer GinkgoRecover() 120 dial(tr, server2.Addr()) 121 close(done2) 122 }() 123 timeout := 30 * time.Second 124 if debugLog() { 125 timeout = time.Minute 126 } 127 Eventually(done1, timeout).Should(BeClosed()) 128 Eventually(done2, timeout).Should(BeClosed()) 129 }) 130 }) 131 132 Context("multiplexing server and client on the same conn", func() { 133 It("connects to itself", func() { 134 addr, err := net.ResolveUDPAddr("udp", "localhost:0") 135 Expect(err).ToNot(HaveOccurred()) 136 conn, err := net.ListenUDP("udp", addr) 137 Expect(err).ToNot(HaveOccurred()) 138 defer conn.Close() 139 tr := &quic.Transport{Conn: conn} 140 server, err := tr.Listen( 141 getTLSConfig(), 142 getQuicConfig(nil), 143 ) 144 Expect(err).ToNot(HaveOccurred()) 145 runServer(server) 146 done := make(chan struct{}) 147 go func() { 148 defer GinkgoRecover() 149 dial(tr, server.Addr()) 150 close(done) 151 }() 152 timeout := 30 * time.Second 153 if debugLog() { 154 timeout = time.Minute 155 } 156 Eventually(done, timeout).Should(BeClosed()) 157 }) 158 159 // This test would require setting of iptables rules, see https://stackoverflow.com/questions/23859164/linux-udp-socket-sendto-operation-not-permitted. 160 if runtime.GOOS != "linux" { 161 It("runs a server and client on the same conn", func() { 162 addr1, err := net.ResolveUDPAddr("udp", "localhost:0") 163 Expect(err).ToNot(HaveOccurred()) 164 conn1, err := net.ListenUDP("udp", addr1) 165 Expect(err).ToNot(HaveOccurred()) 166 defer conn1.Close() 167 tr1 := &quic.Transport{Conn: conn1} 168 169 addr2, err := net.ResolveUDPAddr("udp", "localhost:0") 170 Expect(err).ToNot(HaveOccurred()) 171 conn2, err := net.ListenUDP("udp", addr2) 172 Expect(err).ToNot(HaveOccurred()) 173 defer conn2.Close() 174 tr2 := &quic.Transport{Conn: conn2} 175 176 server1, err := tr1.Listen( 177 getTLSConfig(), 178 getQuicConfig(nil), 179 ) 180 Expect(err).ToNot(HaveOccurred()) 181 runServer(server1) 182 defer server1.Close() 183 184 server2, err := tr2.Listen( 185 getTLSConfig(), 186 getQuicConfig(nil), 187 ) 188 Expect(err).ToNot(HaveOccurred()) 189 runServer(server2) 190 defer server2.Close() 191 192 done1 := make(chan struct{}) 193 done2 := make(chan struct{}) 194 go func() { 195 defer GinkgoRecover() 196 dial(tr2, server1.Addr()) 197 close(done1) 198 }() 199 go func() { 200 defer GinkgoRecover() 201 dial(tr1, server2.Addr()) 202 close(done2) 203 }() 204 timeout := 30 * time.Second 205 if debugLog() { 206 timeout = time.Minute 207 } 208 Eventually(done1, timeout).Should(BeClosed()) 209 Eventually(done2, timeout).Should(BeClosed()) 210 }) 211 } 212 }) 213 })