diff --git a/gather.go b/gather.go index 7d11565..77ce51a 100644 --- a/gather.go +++ b/gather.go @@ -7,7 +7,6 @@ import ( "sync" "time" - "github.com/pion/stun" "github.com/pion/transport/vnet" "github.com/pion/turn/v2" ) @@ -470,58 +469,3 @@ func (a *Agent) gatherCandidatesRelay(urls []*URL) error { return nil } - -// getXORMappedAddr initiates a stun requests to serverAddr using conn, reads the response and returns -// the XORMappedAddress returned by the stun server. -// -// Adapted from stun v0.2. -func getXORMappedAddr(conn net.PacketConn, serverAddr net.Addr, deadline time.Duration) (*stun.XORMappedAddress, error) { - if deadline > 0 { - if err := conn.SetReadDeadline(time.Now().Add(deadline)); err != nil { - return nil, err - } - } - defer func() { - if deadline > 0 { - _ = conn.SetReadDeadline(time.Time{}) - } - }() - resp, err := stunRequest( - func(p []byte) (int, error) { - n, _, errr := conn.ReadFrom(p) - return n, errr - }, - func(b []byte) (int, error) { - return conn.WriteTo(b, serverAddr) - }, - ) - if err != nil { - return nil, err - } - var addr stun.XORMappedAddress - if err = addr.GetFrom(resp); err != nil { - return nil, fmt.Errorf("failed to get XOR-MAPPED-ADDRESS response: %v", err) - } - return &addr, nil -} - -func stunRequest(read func([]byte) (int, error), write func([]byte) (int, error)) (*stun.Message, error) { - req, err := stun.Build(stun.BindingRequest, stun.TransactionID) - if err != nil { - return nil, err - } - if _, err = write(req.Raw); err != nil { - return nil, err - } - const maxMessageSize = 1280 - bs := make([]byte, maxMessageSize) - n, err := read(bs) - if err != nil { - return nil, err - } - res := &stun.Message{Raw: bs[:n]} - if err := res.Decode(); err != nil { - return nil, err - } - return res, nil -} diff --git a/gather_test.go b/gather_test.go index 2bd0831..40e9bea 100644 --- a/gather_test.go +++ b/gather_test.go @@ -14,47 +14,28 @@ import ( func TestListenUDP(t *testing.T) { a, err := NewAgent(&AgentConfig{}) - if err != nil { - t.Fatalf("Failed to create agent: %s", err) - } + assert.NoError(t, err) localIPs, err := a.localInterfaces([]NetworkType{NetworkTypeUDP4}) - if len(localIPs) == 0 { - t.Fatal("localInterfaces found no interfaces, unable to test") - } else if err != nil { - t.Fatal(err) - } + assert.NotEqual(t, len(localIPs), 0, "localInterfaces found no interfaces, unable to test") + assert.NoError(t, err) ip := localIPs[0] conn, err := a.listenUDP(0, 0, udp, &net.UDPAddr{IP: ip, Port: 0}) - if err != nil { - t.Fatalf("listenUDP error with no port restriction %v", err) - } else if conn == nil { - t.Fatalf("listenUDP error with no port restriction return a nil conn") - } + assert.NoError(t, err, "listenUDP error with no port restriction") + assert.NotNil(t, conn, "listenUDP error with no port restriction return a nil conn") _, err = a.listenUDP(4999, 5000, udp, &net.UDPAddr{IP: ip, Port: 0}) - if err == nil { - t.Fatal("listenUDP with invalid port range did not fail") - } - if err != ErrPort { - t.Fatal("listenUDP with invalid port range did not return ErrPort") - } + assert.Equal(t, err, ErrPort, "listenUDP with invalid port range did not return ErrPort") conn, err = a.listenUDP(5000, 5000, udp, &net.UDPAddr{IP: ip, Port: 0}) - if err != nil { - t.Fatalf("listenUDP error with no port restriction %v", err) - } else if conn == nil { - t.Fatalf("listenUDP error with no port restriction return a nil conn") - } + assert.NoError(t, err, "listenUDP error with no port restriction") + assert.NotNil(t, conn, "listenUDP error with no port restriction return a nil conn") _, port, err := net.SplitHostPort(conn.LocalAddr().String()) - if err != nil { - t.Fatal(err) - } else if port != "5000" { - t.Fatalf("listenUDP with port restriction of 5000 listened on incorrect port (%s)", port) - } + assert.NoError(t, err) + assert.Equal(t, port, "5000", "listenUDP with port restriction of 5000 listened on incorrect port") portMin := 5100 portMax := 5109 @@ -63,11 +44,8 @@ func TestListenUDP(t *testing.T) { portRange := make([]int, 0, total) for i := 0; i < total; i++ { conn, err = a.listenUDP(portMax, portMin, udp, &net.UDPAddr{IP: ip, Port: 0}) - if err != nil { - t.Fatalf("listenUDP error with no port restriction %v", err) - } else if conn == nil { - t.Fatalf("listenUDP error with no port restriction return a nil conn") - } + assert.NoError(t, err, "listenUDP error with no port restriction") + assert.NotNil(t, conn, "listenUDP error with no port restriction return a nil conn") _, port, err = net.SplitHostPort(conn.LocalAddr().String()) if err != nil { @@ -88,12 +66,7 @@ func TestListenUDP(t *testing.T) { t.Fatalf("listenUDP with port restriction [%d, %d], got:%v, want:%v", portMin, portMax, result, portRange) } _, err = a.listenUDP(portMax, portMin, udp, &net.UDPAddr{IP: ip, Port: 0}) - if err == nil { - t.Fatalf("listenUDP with port restriction [%d, %d], should return error", portMin, portMax) - } - if err != ErrPort { - t.Fatalf("listenUDP with port restriction [%d, %d], did not return ErrPort", portMin, portMax) - } + assert.Equal(t, err, ErrPort, "listenUDP with port restriction [%d, %d], did not return ErrPort", portMin, portMax) assert.NoError(t, a.Close()) } diff --git a/util.go b/util.go index d659ff3..d9afff0 100644 --- a/util.go +++ b/util.go @@ -6,6 +6,8 @@ import ( "net" "sync/atomic" "time" + + "github.com/pion/stun" ) type atomicError struct{ v atomic.Value } @@ -87,3 +89,58 @@ func generateRandString(prefix, sufix string) (string, error) { return fmt.Sprintf("%s%X-%X-%X-%X-%X%s", prefix, b[0:4], b[4:6], b[6:8], b[8:10], b[10:], sufix), nil } + +// getXORMappedAddr initiates a stun requests to serverAddr using conn, reads the response and returns +// the XORMappedAddress returned by the stun server. +// +// Adapted from stun v0.2. +func getXORMappedAddr(conn net.PacketConn, serverAddr net.Addr, deadline time.Duration) (*stun.XORMappedAddress, error) { + if deadline > 0 { + if err := conn.SetReadDeadline(time.Now().Add(deadline)); err != nil { + return nil, err + } + } + defer func() { + if deadline > 0 { + _ = conn.SetReadDeadline(time.Time{}) + } + }() + resp, err := stunRequest( + func(p []byte) (int, error) { + n, _, errr := conn.ReadFrom(p) + return n, errr + }, + func(b []byte) (int, error) { + return conn.WriteTo(b, serverAddr) + }, + ) + if err != nil { + return nil, err + } + var addr stun.XORMappedAddress + if err = addr.GetFrom(resp); err != nil { + return nil, fmt.Errorf("failed to get XOR-MAPPED-ADDRESS response: %v", err) + } + return &addr, nil +} + +func stunRequest(read func([]byte) (int, error), write func([]byte) (int, error)) (*stun.Message, error) { + req, err := stun.Build(stun.BindingRequest, stun.TransactionID) + if err != nil { + return nil, err + } + if _, err = write(req.Raw); err != nil { + return nil, err + } + const maxMessageSize = 1280 + bs := make([]byte, maxMessageSize) + n, err := read(bs) + if err != nil { + return nil, err + } + res := &stun.Message{Raw: bs[:n]} + if err := res.Decode(); err != nil { + return nil, err + } + return res, nil +}