udp_mux_multi_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. //go:build !js
  4. // +build !js
  5. package ice
  6. import (
  7. "net"
  8. "strings"
  9. "sync"
  10. "testing"
  11. "time"
  12. "github.com/pion/transport/v2/test"
  13. "github.com/stretchr/testify/require"
  14. )
  15. func TestMultiUDPMux(t *testing.T) {
  16. report := test.CheckRoutines(t)
  17. defer report()
  18. lim := test.TimeOut(time.Second * 30)
  19. defer lim.Stop()
  20. conn1, err := net.ListenUDP(udp, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)})
  21. require.NoError(t, err)
  22. conn2, err := net.ListenUDP(udp, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)})
  23. require.NoError(t, err)
  24. conn3, err := net.ListenUDP(udp, &net.UDPAddr{IP: net.IPv6loopback})
  25. if err != nil {
  26. // IPv6 is not supported on this machine
  27. t.Log("ipv6 is not supported on this machine")
  28. }
  29. muxes := []UDPMux{}
  30. muxV41 := NewUDPMuxDefault(UDPMuxParams{UDPConn: conn1})
  31. muxes = append(muxes, muxV41)
  32. muxV42 := NewUDPMuxDefault(UDPMuxParams{UDPConn: conn2})
  33. muxes = append(muxes, muxV42)
  34. if conn3 != nil {
  35. muxV6 := NewUDPMuxDefault(UDPMuxParams{UDPConn: conn3})
  36. muxes = append(muxes, muxV6)
  37. }
  38. udpMuxMulti := NewMultiUDPMuxDefault(muxes...)
  39. defer func() {
  40. _ = udpMuxMulti.Close()
  41. _ = conn1.Close()
  42. _ = conn2.Close()
  43. }()
  44. wg := sync.WaitGroup{}
  45. wg.Add(1)
  46. go func() {
  47. defer wg.Done()
  48. testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag1", udp)
  49. }()
  50. wg.Add(1)
  51. go func() {
  52. defer wg.Done()
  53. testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag2", udp4)
  54. }()
  55. // Skip ipv6 test on i386
  56. const ptrSize = 32 << (^uintptr(0) >> 63)
  57. if ptrSize != 32 {
  58. testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag3", udp6)
  59. }
  60. wg.Wait()
  61. require.NoError(t, udpMuxMulti.Close())
  62. // Can't create more connections
  63. _, err = udpMuxMulti.GetConn("failufrag", conn1.LocalAddr())
  64. require.Error(t, err)
  65. }
  66. func testMultiUDPMuxConnections(t *testing.T, udpMuxMulti *MultiUDPMuxDefault, ufrag string, network string) {
  67. addrs := udpMuxMulti.GetListenAddresses()
  68. pktConns := make([]net.PacketConn, 0, len(addrs))
  69. for _, addr := range addrs {
  70. udpAddr, ok := addr.(*net.UDPAddr)
  71. require.True(t, ok)
  72. if network == udp4 && udpAddr.IP.To4() == nil {
  73. continue
  74. } else if network == udp6 && udpAddr.IP.To4() != nil {
  75. continue
  76. }
  77. c, err := udpMuxMulti.GetConn(ufrag, addr)
  78. require.NoError(t, err, "error retrieving muxed connection for ufrag")
  79. pktConns = append(pktConns, c)
  80. }
  81. defer func() {
  82. for _, c := range pktConns {
  83. _ = c.Close()
  84. }
  85. }()
  86. // Try talking with each PacketConn
  87. for _, pktConn := range pktConns {
  88. remoteConn, err := net.DialUDP(network, nil, pktConn.LocalAddr().(*net.UDPAddr))
  89. require.NoError(t, err, "error dialing test UDP connection")
  90. testMuxConnectionPair(t, pktConn, remoteConn, ufrag)
  91. }
  92. }
  93. func TestUnspecifiedUDPMux(t *testing.T) {
  94. report := test.CheckRoutines(t)
  95. defer report()
  96. lim := test.TimeOut(time.Second * 30)
  97. defer lim.Stop()
  98. muxPort := 7778
  99. udpMuxMulti, err := NewMultiUDPMuxFromPort(muxPort, UDPMuxFromPortWithInterfaceFilter(func(s string) bool {
  100. defaultDockerBridgeNetwork := strings.Contains(s, "docker")
  101. customDockerBridgeNetwork := strings.Contains(s, "br-")
  102. return !defaultDockerBridgeNetwork && !customDockerBridgeNetwork
  103. }))
  104. require.NoError(t, err)
  105. require.GreaterOrEqual(t, len(udpMuxMulti.muxes), 1, "at least have 1 muxes")
  106. defer func() {
  107. _ = udpMuxMulti.Close()
  108. }()
  109. wg := sync.WaitGroup{}
  110. wg.Add(1)
  111. go func() {
  112. defer wg.Done()
  113. testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag1", udp)
  114. }()
  115. wg.Add(1)
  116. go func() {
  117. defer wg.Done()
  118. testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag2", udp4)
  119. }()
  120. // Skip IPv6 test on i386
  121. const ptrSize = 32 << (^uintptr(0) >> 63)
  122. if ptrSize != 32 {
  123. testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag3", udp6)
  124. }
  125. wg.Wait()
  126. require.NoError(t, udpMuxMulti.Close())
  127. }