Files
ice/udp_mux_multi_test.go
cnderrauber 04a6027e93 Use MultiUDPMux to implement listen any address
In #475, import low-level API (ReadMsgUDP) to determine
destination interface for packets received by UDPConn listen
at any(unspecified) address, to fix msg received by incorrect
candidate that shared same ufrags. But the api has compatibility
issues, also not reliable in some special network cases like
AWS/ECS.
So this pr revert that change, and make UDPMuxDefault not
accept Conn listen at unspecified address. Also provide a
NewMultiUDPMuxFromPort helper function to create a MultiUDPMux
to listen at all addresses.
For ice gather, it will use UDPMux's listen address to generate
canidates instead of create it from interfaces.
2022-10-10 20:22:30 +08:00

154 lines
3.6 KiB
Go

//go:build !js
// +build !js
package ice
import (
"net"
"strings"
"sync"
"testing"
"time"
"github.com/pion/transport/test"
"github.com/stretchr/testify/require"
)
func TestMultiUDPMux(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
lim := test.TimeOut(time.Second * 30)
defer lim.Stop()
conn1, err := net.ListenUDP(udp, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)})
require.NoError(t, err)
conn2, err := net.ListenUDP(udp, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)})
require.NoError(t, err)
conn3, err := net.ListenUDP(udp, &net.UDPAddr{IP: net.IPv6loopback})
if err != nil {
// ipv6 is not supported on this machine
t.Log("ipv6 is not supported on this machine")
}
muxes := []UDPMux{}
muxV41, err := NewUDPMuxDefault(UDPMuxParams{UDPConn: conn1})
require.NoError(t, err)
muxes = append(muxes, muxV41)
muxV42, err := NewUDPMuxDefault(UDPMuxParams{UDPConn: conn2})
require.NoError(t, err)
muxes = append(muxes, muxV42)
if conn3 != nil {
muxV6, v6err := NewUDPMuxDefault(UDPMuxParams{UDPConn: conn3})
require.NoError(t, v6err)
muxes = append(muxes, muxV6)
}
udpMuxMulti := NewMultiUDPMuxDefault(muxes...)
defer func() {
_ = udpMuxMulti.Close()
_ = conn1.Close()
_ = conn2.Close()
}()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag1", udp)
}()
wg.Add(1)
go func() {
defer wg.Done()
testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag2", "udp4")
}()
// skip ipv6 test on i386
const ptrSize = 32 << (^uintptr(0) >> 63)
if ptrSize != 32 {
testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag3", "udp6")
}
wg.Wait()
require.NoError(t, udpMuxMulti.Close())
// can't create more connections
_, err = udpMuxMulti.GetConn("failufrag", conn1.LocalAddr())
require.Error(t, err)
}
func testMultiUDPMuxConnections(t *testing.T, udpMuxMulti *MultiUDPMuxDefault, ufrag string, network string) {
addrs := udpMuxMulti.GetListenAddresses()
pktConns := make([]net.PacketConn, 0, len(addrs))
for _, addr := range addrs {
udpAddr, ok := addr.(*net.UDPAddr)
require.True(t, ok)
if network == "udp4" && udpAddr.IP.To4() == nil {
continue
} else if network == "udp6" && udpAddr.IP.To4() != nil {
continue
}
c, err := udpMuxMulti.GetConn(ufrag, addr)
require.NoError(t, err, "error retrieving muxed connection for ufrag")
pktConns = append(pktConns, c)
}
defer func() {
for _, c := range pktConns {
_ = c.Close()
}
}()
// Try talking with each PacketConn
for _, pktConn := range pktConns {
remoteConn, err := net.DialUDP(network, nil, pktConn.LocalAddr().(*net.UDPAddr))
require.NoError(t, err, "error dialing test udp connection")
testMuxConnectionPair(t, pktConn, remoteConn, ufrag)
}
}
func TestUnspecifiedUDPMux(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
lim := test.TimeOut(time.Second * 30)
defer lim.Stop()
muxPort := 7778
udpMuxMulti, err := NewMultiUDPMuxFromPort(muxPort, UDPMuxFromPortWithInterfaceFilter(func(s string) bool {
return !strings.Contains(s, "docker")
}))
require.NoError(t, err)
require.GreaterOrEqual(t, len(udpMuxMulti.muxs), 1, "at least have 1 muxs")
defer func() {
_ = udpMuxMulti.Close()
}()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag1", udp)
}()
wg.Add(1)
go func() {
defer wg.Done()
testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag2", "udp4")
}()
// skip ipv6 test on i386
const ptrSize = 32 << (^uintptr(0) >> 63)
if ptrSize != 32 {
testMultiUDPMuxConnections(t, udpMuxMulti, "ufrag3", "udp6")
}
wg.Wait()
require.NoError(t, udpMuxMulti.Close())
}