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  })