Move URL type to pion/stun.URI

This commit is contained in:
Steffen Vogel
2023-05-10 12:45:24 +02:00
parent 6c82312fcd
commit ca9de18fd6
16 changed files with 153 additions and 377 deletions

View File

@@ -105,7 +105,7 @@ type Agent struct {
selectedPair atomic.Value // *CandidatePair
urls []*URL
urls []*stun.URI
networkTypes []NetworkType
buf *packetio.Buffer

View File

@@ -8,6 +8,7 @@ import (
"time"
"github.com/pion/logging"
"github.com/pion/stun"
"github.com/pion/transport/v2"
"golang.org/x/net/proxy"
)
@@ -54,7 +55,7 @@ func defaultCandidateTypes() []CandidateType {
// AgentConfig collects the arguments to ice.Agent construction into
// a single structure, for future-proofness of the interface
type AgentConfig struct {
Urls []*URL
Urls []*stun.URI
// PortMin and PortMax are optional. Leave them 0 for the default UDP port allocation strategy.
PortMin uint16

View File

@@ -301,11 +301,11 @@ func TestConnectivityLite(t *testing.T) {
lim := test.TimeOut(time.Second * 30)
defer lim.Stop()
stunServerURL := &URL{
stunServerURL := &stun.URI{
Scheme: SchemeTypeSTUN,
Host: "1.2.3.4",
Port: 3478,
Proto: ProtoTypeUDP,
Proto: stun.ProtoTypeUDP,
}
natType := &vnet.NATType{
@@ -320,7 +320,7 @@ func TestConnectivityLite(t *testing.T) {
bNotifier, bConnected := onConnected()
cfg0 := &AgentConfig{
Urls: []*URL{stunServerURL},
Urls: []*stun.URI{stunServerURL},
NetworkTypes: supportedNetworkTypes(),
MulticastDNSMode: MulticastDNSModeDisabled,
Net: v.net0,
@@ -331,7 +331,7 @@ func TestConnectivityLite(t *testing.T) {
require.NoError(t, aAgent.OnConnectionStateChange(aNotifier))
cfg1 := &AgentConfig{
Urls: []*URL{},
Urls: []*stun.URI{},
Lite: true,
CandidateTypes: []CandidateType{CandidateTypeHost},
NetworkTypes: supportedNetworkTypes(),
@@ -548,7 +548,7 @@ func TestConnectionStateCallback(t *testing.T) {
KeepaliveInterval := time.Duration(0)
cfg := &AgentConfig{
Urls: []*URL{},
Urls: []*stun.URI{},
NetworkTypes: supportedNetworkTypes(),
DisconnectedTimeout: &disconnectedDuration,
FailedTimeout: &failedDuration,
@@ -1330,7 +1330,7 @@ func TestCloseInConnectionStateCallback(t *testing.T) {
CheckInterval := 500 * time.Millisecond
cfg := &AgentConfig{
Urls: []*URL{},
Urls: []*stun.URI{},
NetworkTypes: supportedNetworkTypes(),
DisconnectedTimeout: &disconnectedDuration,
FailedTimeout: &failedDuration,
@@ -1382,7 +1382,7 @@ func TestRunTaskInConnectionStateCallback(t *testing.T) {
CheckInterval := 50 * time.Millisecond
cfg := &AgentConfig{
Urls: []*URL{},
Urls: []*stun.URI{},
NetworkTypes: supportedNetworkTypes(),
DisconnectedTimeout: &oneSecond,
FailedTimeout: &oneSecond,
@@ -1427,7 +1427,7 @@ func TestRunTaskInSelectedCandidatePairChangeCallback(t *testing.T) {
CheckInterval := 50 * time.Millisecond
cfg := &AgentConfig{
Urls: []*URL{},
Urls: []*stun.URI{},
NetworkTypes: supportedNetworkTypes(),
DisconnectedTimeout: &oneSecond,
FailedTimeout: &oneSecond,

View File

@@ -12,6 +12,7 @@ import (
"testing"
"time"
"github.com/pion/stun"
"github.com/pion/transport/v2/test"
"github.com/pion/turn/v2"
"github.com/stretchr/testify/assert"
@@ -47,14 +48,14 @@ func TestRelayOnlyConnection(t *testing.T) {
cfg := &AgentConfig{
NetworkTypes: supportedNetworkTypes(),
Urls: []*URL{
Urls: []*stun.URI{
{
Scheme: SchemeTypeTURN,
Scheme: stun.SchemeTypeTURN,
Host: "127.0.0.1",
Username: "username",
Password: "password",
Port: serverPort,
Proto: ProtoTypeUDP,
Proto: stun.ProtoTypeUDP,
},
},
CandidateTypes: []CandidateType{CandidateTypeRelay},

View File

@@ -12,6 +12,7 @@ import (
"testing"
"time"
"github.com/pion/stun"
"github.com/pion/transport/v2/test"
"github.com/pion/turn/v2"
"github.com/stretchr/testify/assert"
@@ -43,7 +44,7 @@ func TestServerReflexiveOnlyConnection(t *testing.T) {
cfg := &AgentConfig{
NetworkTypes: []NetworkType{NetworkTypeUDP4},
Urls: []*URL{
Urls: []*stun.URI{
{
Scheme: SchemeTypeSTUN,
Host: "127.0.0.1",

View File

@@ -226,7 +226,7 @@ func connectWithVNet(aAgent, bAgent *Agent) (*Conn, *Conn) {
}
type agentTestConfig struct {
urls []*URL
urls []*stun.URI
nat1To1IPCandidateType CandidateType
}
@@ -305,20 +305,20 @@ func TestConnectivityVNet(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
stunServerURL := &URL{
Scheme: SchemeTypeSTUN,
stunServerURL := &stun.URI{
Scheme: stun.SchemeTypeSTUN,
Host: vnetSTUNServerIP,
Port: vnetSTUNServerPort,
Proto: ProtoTypeUDP,
Proto: stun.ProtoTypeUDP,
}
turnServerURL := &URL{
Scheme: SchemeTypeTURN,
turnServerURL := &stun.URI{
Scheme: stun.SchemeTypeTURN,
Host: vnetSTUNServerIP,
Port: vnetSTUNServerPort,
Username: "user",
Password: "pass",
Proto: ProtoTypeUDP,
Proto: stun.ProtoTypeUDP,
}
t.Run("Full-cone NATs on both ends", func(t *testing.T) {
@@ -339,12 +339,12 @@ func TestConnectivityVNet(t *testing.T) {
log.Debug("Connecting...")
a0TestConfig := &agentTestConfig{
urls: []*URL{
urls: []*stun.URI{
stunServerURL,
},
}
a1TestConfig := &agentTestConfig{
urls: []*URL{
urls: []*stun.URI{
stunServerURL,
},
}
@@ -376,13 +376,13 @@ func TestConnectivityVNet(t *testing.T) {
log.Debug("Connecting...")
a0TestConfig := &agentTestConfig{
urls: []*URL{
urls: []*stun.URI{
stunServerURL,
turnServerURL,
},
}
a1TestConfig := &agentTestConfig{
urls: []*URL{
urls: []*stun.URI{
stunServerURL,
},
}
@@ -416,11 +416,11 @@ func TestConnectivityVNet(t *testing.T) {
log.Debug("Connecting...")
a0TestConfig := &agentTestConfig{
urls: []*URL{},
urls: []*stun.URI{},
nat1To1IPCandidateType: CandidateTypeHost, // Use 1:1 NAT IP as a host candidate
}
a1TestConfig := &agentTestConfig{
urls: []*URL{},
urls: []*stun.URI{},
}
ca, cb := pipeWithVNet(v, a0TestConfig, a1TestConfig)
@@ -452,11 +452,11 @@ func TestConnectivityVNet(t *testing.T) {
log.Debug("Connecting...")
a0TestConfig := &agentTestConfig{
urls: []*URL{},
urls: []*stun.URI{},
nat1To1IPCandidateType: CandidateTypeServerReflexive, // Use 1:1 NAT IP as a srflx candidate
}
a1TestConfig := &agentTestConfig{
urls: []*URL{},
urls: []*stun.URI{},
}
ca, cb := pipeWithVNet(v, a0TestConfig, a1TestConfig)

View File

@@ -124,8 +124,6 @@ var (
errReadingStreamingPacket = errors.New("error reading streaming packet")
errWriting = errors.New("error writing to")
errClosingConnection = errors.New("error closing connection")
errMissingProtocolScheme = errors.New("missing protocol scheme")
errTooManyColonsAddr = errors.New("too many colons in address")
errRead = errors.New("unexpected error trying to read")
errUnknownRole = errors.New("unknown role")
errICEWriteSTUNMessage = errors.New("the ICE conn can't write STUN messages")

View File

@@ -17,6 +17,7 @@ import (
"github.com/pion/ice/v2/internal/fakenet"
stunx "github.com/pion/ice/v2/internal/stun"
"github.com/pion/logging"
"github.com/pion/stun"
"github.com/pion/turn/v2"
)
@@ -376,7 +377,7 @@ func (a *Agent) gatherCandidatesSrflxMapped(ctx context.Context, networkTypes []
}
}
func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*URL, networkTypes []NetworkType) { //nolint:gocognit
func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*stun.URI, networkTypes []NetworkType) { //nolint:gocognit
var wg sync.WaitGroup
defer wg.Wait()
@@ -393,7 +394,7 @@ func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*URL, ne
continue
}
wg.Add(1)
go func(url URL, network string, localAddr *net.UDPAddr) {
go func(url stun.URI, network string, localAddr *net.UDPAddr) {
defer wg.Done()
hostPort := fmt.Sprintf("%s:%d", url.Host, url.Port)
@@ -444,7 +445,7 @@ func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*URL, ne
}
}
func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkTypes []NetworkType) { //nolint:gocognit
func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*stun.URI, networkTypes []NetworkType) { //nolint:gocognit
var wg sync.WaitGroup
defer wg.Wait()
@@ -455,7 +456,7 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkT
for i := range urls {
wg.Add(1)
go func(url URL, network string) {
go func(url stun.URI, network string) {
defer wg.Done()
hostPort := fmt.Sprintf("%s:%d", url.Host, url.Port)
@@ -518,14 +519,14 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkT
}
}
func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //nolint:gocognit
func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { //nolint:gocognit
var wg sync.WaitGroup
defer wg.Wait()
network := NetworkTypeUDP4.String()
for i := range urls {
switch {
case urls[i].Scheme != SchemeTypeTURN && urls[i].Scheme != SchemeTypeTURNS:
case urls[i].Scheme != stun.SchemeTypeTURN && urls[i].Scheme != stun.SchemeTypeTURNS:
continue
case urls[i].Username == "":
a.log.Errorf("Failed to gather relay candidates: %v", ErrUsernameEmpty)
@@ -536,7 +537,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
}
wg.Add(1)
go func(url URL) {
go func(url stun.URI) {
defer wg.Done()
turnServerAddr := fmt.Sprintf("%s:%d", url.Host, url.Port)
var (
@@ -548,7 +549,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
)
switch {
case url.Proto == ProtoTypeUDP && url.Scheme == SchemeTypeTURN:
case url.Proto == stun.ProtoTypeUDP && url.Scheme == stun.SchemeTypeTURN:
if locConn, err = a.net.ListenPacket(network, "0.0.0.0:0"); err != nil {
a.log.Warnf("Failed to listen %s: %v", network, err)
return
@@ -557,8 +558,8 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
relAddr = locConn.LocalAddr().(*net.UDPAddr).IP.String() //nolint:forcetypeassert
relPort = locConn.LocalAddr().(*net.UDPAddr).Port //nolint:forcetypeassert
relayProtocol = udp
case a.proxyDialer != nil && url.Proto == ProtoTypeTCP &&
(url.Scheme == SchemeTypeTURN || url.Scheme == SchemeTypeTURNS):
case a.proxyDialer != nil && url.Proto == stun.ProtoTypeTCP &&
(url.Scheme == stun.SchemeTypeTURN || url.Scheme == stun.SchemeTypeTURNS):
conn, connectErr := a.proxyDialer.Dial(NetworkTypeTCP4.String(), turnServerAddr)
if connectErr != nil {
a.log.Warnf("Failed to dial TCP address %s via proxy dialer: %v", turnServerAddr, connectErr)
@@ -567,14 +568,14 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
relAddr = conn.LocalAddr().(*net.TCPAddr).IP.String() //nolint:forcetypeassert
relPort = conn.LocalAddr().(*net.TCPAddr).Port //nolint:forcetypeassert
if url.Scheme == SchemeTypeTURN {
if url.Scheme == stun.SchemeTypeTURN {
relayProtocol = tcp
} else if url.Scheme == SchemeTypeTURNS {
} else if url.Scheme == stun.SchemeTypeTURNS {
relayProtocol = "tls"
}
locConn = turn.NewSTUNConn(conn)
case url.Proto == ProtoTypeTCP && url.Scheme == SchemeTypeTURN:
case url.Proto == stun.ProtoTypeTCP && url.Scheme == stun.SchemeTypeTURN:
tcpAddr, connectErr := a.net.ResolveTCPAddr(NetworkTypeTCP4.String(), turnServerAddr)
if connectErr != nil {
a.log.Warnf("Failed to resolve TCP address %s: %v", turnServerAddr, connectErr)
@@ -591,7 +592,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
relPort = conn.LocalAddr().(*net.TCPAddr).Port //nolint:forcetypeassert
relayProtocol = tcp
locConn = turn.NewSTUNConn(conn)
case url.Proto == ProtoTypeUDP && url.Scheme == SchemeTypeTURNS:
case url.Proto == stun.ProtoTypeUDP && url.Scheme == stun.SchemeTypeTURNS:
udpAddr, connectErr := a.net.ResolveUDPAddr(network, turnServerAddr)
if connectErr != nil {
a.log.Warnf("Failed to resolve UDP address %s: %v", turnServerAddr, connectErr)
@@ -617,7 +618,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
relPort = conn.LocalAddr().(*net.UDPAddr).Port //nolint:forcetypeassert
relayProtocol = "dtls"
locConn = &fakenet.PacketConn{Conn: conn}
case url.Proto == ProtoTypeTCP && url.Scheme == SchemeTypeTURNS:
case url.Proto == stun.ProtoTypeTCP && url.Scheme == stun.SchemeTypeTURNS:
tcpAddr, resolvErr := a.net.ResolveTCPAddr(NetworkTypeTCP4.String(), turnServerAddr)
if resolvErr != nil {
a.log.Warnf("Failed to resolve relay address %s: %v", turnServerAddr, resolvErr)

View File

@@ -224,16 +224,16 @@ func TestSTUNConcurrency(t *testing.T) {
})
assert.NoError(t, err)
urls := []*URL{}
urls := []*stun.URI{}
for i := 0; i <= 10; i++ {
urls = append(urls, &URL{
Scheme: SchemeTypeSTUN,
urls = append(urls, &stun.URI{
Scheme: stun.SchemeTypeSTUN,
Host: "127.0.0.1",
Port: serverPort + 1,
})
}
urls = append(urls, &URL{
Scheme: SchemeTypeSTUN,
urls = append(urls, &stun.URI{
Scheme: stun.SchemeTypeSTUN,
Host: "127.0.0.1",
Port: serverPort,
})
@@ -284,7 +284,7 @@ func TestTURNConcurrency(t *testing.T) {
lim := test.TimeOut(time.Second * 30)
defer lim.Stop()
runTest := func(protocol ProtoType, scheme SchemeType, packetConn net.PacketConn, listener net.Listener, serverPort int) {
runTest := func(protocol stun.ProtoType, scheme stun.SchemeType, packetConn net.PacketConn, listener net.Listener, serverPort int) {
packetConnConfigs := []turn.PacketConnConfig{}
if packetConn != nil {
packetConnConfigs = append(packetConnConfigs, turn.PacketConnConfig{
@@ -309,9 +309,9 @@ func TestTURNConcurrency(t *testing.T) {
})
assert.NoError(t, err)
urls := []*URL{}
urls := []*stun.URI{}
for i := 0; i <= 10; i++ {
urls = append(urls, &URL{
urls = append(urls, &stun.URI{
Scheme: scheme,
Host: "127.0.0.1",
Username: "username",
@@ -320,7 +320,7 @@ func TestTURNConcurrency(t *testing.T) {
Port: serverPort + 1 + i,
})
}
urls = append(urls, &URL{
urls = append(urls, &stun.URI{
Scheme: scheme,
Host: "127.0.0.1",
Username: "username",
@@ -356,7 +356,7 @@ func TestTURNConcurrency(t *testing.T) {
serverListener, err := net.ListenPacket("udp", "127.0.0.1:"+strconv.Itoa(serverPort))
assert.NoError(t, err)
runTest(ProtoTypeUDP, SchemeTypeTURN, serverListener, nil, serverPort)
runTest(stun.ProtoTypeUDP, stun.SchemeTypeTURN, serverListener, nil, serverPort)
})
t.Run("TCP Relay", func(t *testing.T) {
@@ -364,7 +364,7 @@ func TestTURNConcurrency(t *testing.T) {
serverListener, err := net.Listen("tcp", "127.0.0.1:"+strconv.Itoa(serverPort))
assert.NoError(t, err)
runTest(ProtoTypeTCP, SchemeTypeTURN, nil, serverListener, serverPort)
runTest(stun.ProtoTypeTCP, stun.SchemeTypeTURN, nil, serverListener, serverPort)
})
t.Run("TLS Relay", func(t *testing.T) {
@@ -377,7 +377,7 @@ func TestTURNConcurrency(t *testing.T) {
})
assert.NoError(t, err)
runTest(ProtoTypeTCP, SchemeTypeTURNS, nil, serverListener, serverPort)
runTest(stun.ProtoTypeTCP, stun.SchemeTypeTURNS, nil, serverListener, serverPort)
})
t.Run("DTLS Relay", func(t *testing.T) {
@@ -390,7 +390,7 @@ func TestTURNConcurrency(t *testing.T) {
})
assert.NoError(t, err)
runTest(ProtoTypeUDP, SchemeTypeTURNS, nil, serverListener, serverPort)
runTest(stun.ProtoTypeUDP, stun.SchemeTypeTURNS, nil, serverListener, serverPort)
})
}
@@ -418,17 +418,17 @@ func TestSTUNTURNConcurrency(t *testing.T) {
})
assert.NoError(t, err)
urls := []*URL{}
urls := []*stun.URI{}
for i := 0; i <= 10; i++ {
urls = append(urls, &URL{
Scheme: SchemeTypeSTUN,
urls = append(urls, &stun.URI{
Scheme: stun.SchemeTypeSTUN,
Host: "127.0.0.1",
Port: serverPort + 1,
})
}
urls = append(urls, &URL{
Scheme: SchemeTypeTURN,
Proto: ProtoTypeUDP,
urls = append(urls, &stun.URI{
Scheme: stun.SchemeTypeTURN,
Proto: stun.ProtoTypeUDP,
Host: "127.0.0.1",
Port: serverPort,
Username: "username",
@@ -490,9 +490,9 @@ func TestTURNSrflx(t *testing.T) {
})
assert.NoError(t, err)
urls := []*URL{{
Scheme: SchemeTypeTURN,
Proto: ProtoTypeUDP,
urls := []*stun.URI{{
Scheme: stun.SchemeTypeTURN,
Proto: stun.ProtoTypeUDP,
Host: "127.0.0.1",
Port: serverPort,
Username: "username",
@@ -574,13 +574,13 @@ func TestTURNProxyDialer(t *testing.T) {
a, err := NewAgent(&AgentConfig{
CandidateTypes: []CandidateType{CandidateTypeRelay},
NetworkTypes: supportedNetworkTypes(),
Urls: []*URL{
Urls: []*stun.URI{
{
Scheme: SchemeTypeTURN,
Scheme: stun.SchemeTypeTURN,
Host: "127.0.0.1",
Username: "username",
Password: "password",
Proto: ProtoTypeTCP,
Proto: stun.ProtoTypeTCP,
Port: 5000,
},
},
@@ -782,9 +782,9 @@ func TestUniversalUDPMuxUsage(t *testing.T) {
}
numSTUNS := 3
urls := []*URL{}
urls := []*stun.URI{}
for i := 0; i < numSTUNS; i++ {
urls = append(urls, &URL{
urls = append(urls, &stun.URI{
Scheme: SchemeTypeSTUN,
Host: "127.0.0.1",
Port: 3478 + i,

View File

@@ -14,6 +14,7 @@ import (
"testing"
"github.com/pion/logging"
"github.com/pion/stun"
"github.com/pion/transport/v2/test"
"github.com/pion/transport/v2/vnet"
"github.com/stretchr/testify/assert"
@@ -445,13 +446,13 @@ func TestVNetGather_TURNConnectionLeak(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
turnServerURL := &URL{
Scheme: SchemeTypeTURN,
turnServerURL := &stun.URI{
Scheme: stun.SchemeTypeTURN,
Host: vnetSTUNServerIP,
Port: vnetSTUNServerPort,
Username: "user",
Password: "pass",
Proto: ProtoTypeUDP,
Proto: stun.ProtoTypeUDP,
}
// buildVNet with a Symmetric NATs for both LANs
@@ -467,7 +468,7 @@ func TestVNetGather_TURNConnectionLeak(t *testing.T) {
defer v.close()
cfg0 := &AgentConfig{
Urls: []*URL{
Urls: []*stun.URI{
turnServerURL,
},
NetworkTypes: supportedNetworkTypes(),
@@ -480,7 +481,7 @@ func TestVNetGather_TURNConnectionLeak(t *testing.T) {
return
}
aAgent.gatherCandidatesRelay(context.Background(), []*URL{turnServerURL})
aAgent.gatherCandidatesRelay(context.Background(), []*stun.URI{turnServerURL})
// Assert relay conn leak on close.
assert.NoError(t, aAgent.Close())
}

10
ice.go
View File

@@ -8,8 +8,11 @@ type ConnectionState int
// List of supported States
const (
// ConnectionStateUnknown represents an unknown state
ConnectionStateUnknown = iota
// ConnectionStateNew ICE agent is gathering addresses
ConnectionStateNew = iota + 1
ConnectionStateNew
// ConnectionStateChecking ICE agent has been given local and remote candidates, and is attempting to find a match
ConnectionStateChecking
@@ -55,8 +58,11 @@ func (c ConnectionState) String() string {
type GatheringState int
const (
// GatheringStateUnknown represents an unknown state
GatheringStateUnknown GatheringState = iota
// GatheringStateNew indicates candidate gathering is not yet started
GatheringStateNew GatheringState = iota + 1
GatheringStateNew
// GatheringStateGathering indicates candidate gathering is ongoing
GatheringStateGathering

View File

@@ -14,7 +14,7 @@ func TestConnectedState_String(t *testing.T) {
connectionState ConnectionState
expectedString string
}{
{ConnectionState(Unknown), "Invalid"},
{ConnectionStateUnknown, "Invalid"},
{ConnectionStateNew, "New"},
{ConnectionStateChecking, "Checking"},
{ConnectionStateConnected, "Connected"},
@@ -38,7 +38,7 @@ func TestGatheringState_String(t *testing.T) {
gatheringState GatheringState
expectedString string
}{
{GatheringState(Unknown), ErrUnknownType.Error()},
{GatheringStateUnknown, ErrUnknownType.Error()},
{GatheringStateNew, "new"},
{GatheringStateGathering, "gathering"},
{GatheringStateComplete, "complete"},

View File

@@ -13,6 +13,7 @@ import (
"testing"
"time"
"github.com/pion/stun"
"github.com/pion/transport/v2/test"
)
@@ -228,7 +229,7 @@ func connect(aAgent, bAgent *Agent) (*Conn, *Conn) {
}
func pipe(defaultConfig *AgentConfig) (*Conn, *Conn) {
var urls []*URL
var urls []*stun.URI
aNotifier, aConnected := onConnected()
bNotifier, bConnected := onConnected()
@@ -261,7 +262,7 @@ func pipe(defaultConfig *AgentConfig) (*Conn, *Conn) {
}
func pipeWithTimeout(disconnectTimeout time.Duration, iceKeepalive time.Duration) (*Conn, *Conn) {
var urls []*URL
var urls []*stun.URI
aNotifier, aConnected := onConnected()
bNotifier, bConnected := onConnected()

View File

@@ -12,6 +12,7 @@ import (
"testing"
"time"
"github.com/pion/stun"
"github.com/pion/transport/v2/test"
"github.com/pion/transport/v2/vnet"
"github.com/stretchr/testify/assert"
@@ -37,11 +38,11 @@ func TestRemoteLocalAddr(t *testing.T) {
}
defer v.close()
stunServerURL := &URL{
Scheme: SchemeTypeSTUN,
stunServerURL := &stun.URI{
Scheme: stun.SchemeTypeSTUN,
Host: vnetSTUNServerIP,
Port: vnetSTUNServerPort,
Proto: ProtoTypeUDP,
Proto: stun.ProtoTypeUDP,
}
t.Run("Disconnected Returns nil", func(t *testing.T) {
@@ -58,10 +59,10 @@ func TestRemoteLocalAddr(t *testing.T) {
t.Run("Remote/Local Pair Match between Agents", func(t *testing.T) {
ca, cb := pipeWithVNet(v,
&agentTestConfig{
urls: []*URL{stunServerURL},
urls: []*stun.URI{stunServerURL},
},
&agentTestConfig{
urls: []*URL{stunServerURL},
urls: []*stun.URI{stunServerURL},
},
)

254
url.go
View File

@@ -3,228 +3,80 @@
package ice
import (
"errors"
"net"
"net/url"
"strconv"
import "github.com/pion/stun"
type (
// URL represents a STUN (rfc7064) or TURN (rfc7065) URI
//
// Deprecated: Please use pion/stun.URI
URL = stun.URI
// ProtoType indicates the transport protocol type that is used in the ice.URL
// structure.
//
// Deprecated: TPlease use pion/stun.ProtoType
ProtoType = stun.ProtoType
// SchemeType indicates the type of server used in the ice.URL structure.
//
// Deprecated: Please use pion/stun.SchemeType
SchemeType = stun.SchemeType
)
// SchemeType indicates the type of server used in the ice.URL structure.
type SchemeType int
// Unknown defines default public constant to use for "enum" like struct
// comparisons when no value was defined.
const Unknown = iota
const (
// SchemeTypeSTUN indicates the URL represents a STUN server.
SchemeTypeSTUN SchemeType = iota + 1
//
// Deprecated: Please use pion/stun.SchemeTypeSTUN
SchemeTypeSTUN = stun.SchemeTypeSTUN
// SchemeTypeSTUNS indicates the URL represents a STUNS (secure) server.
SchemeTypeSTUNS
//
// Deprecated: Please use pion/stun.SchemeTypeSTUNS
SchemeTypeSTUNS = stun.SchemeTypeSTUNS
// SchemeTypeTURN indicates the URL represents a TURN server.
SchemeTypeTURN
//
// Deprecated: Please use pion/stun.SchemeTypeTURN
SchemeTypeTURN = stun.SchemeTypeTURN
// SchemeTypeTURNS indicates the URL represents a TURNS (secure) server.
SchemeTypeTURNS
//
// Deprecated: Please use pion/stun.SchemeTypeTURNS
SchemeTypeTURNS = stun.SchemeTypeTURNS
)
// NewSchemeType defines a procedure for creating a new SchemeType from a raw
// string naming the scheme type.
func NewSchemeType(raw string) SchemeType {
switch raw {
case "stun":
return SchemeTypeSTUN
case "stuns":
return SchemeTypeSTUNS
case "turn":
return SchemeTypeTURN
case "turns":
return SchemeTypeTURNS
default:
return SchemeType(Unknown)
}
}
func (t SchemeType) String() string {
switch t {
case SchemeTypeSTUN:
return "stun"
case SchemeTypeSTUNS:
return "stuns"
case SchemeTypeTURN:
return "turn"
case SchemeTypeTURNS:
return "turns"
default:
return ErrUnknownType.Error()
}
}
// ProtoType indicates the transport protocol type that is used in the ice.URL
// structure.
type ProtoType int
const (
// ProtoTypeUDP indicates the URL uses a UDP transport.
ProtoTypeUDP ProtoType = iota + 1
//
// Deprecated: Please use pion/stun.ProtoTypeUDP
ProtoTypeUDP = stun.ProtoTypeUDP
// ProtoTypeTCP indicates the URL uses a TCP transport.
ProtoTypeTCP
//
// Deprecated: Please use pion/stun.ProtoTypeTCP
ProtoTypeTCP = stun.ProtoTypeTCP
)
// NewProtoType defines a procedure for creating a new ProtoType from a raw
// string naming the transport protocol type.
func NewProtoType(raw string) ProtoType {
switch raw {
case "udp":
return ProtoTypeUDP
case "tcp":
return ProtoTypeTCP
default:
return ProtoType(Unknown)
}
}
func (t ProtoType) String() string {
switch t {
case ProtoTypeUDP:
return "udp"
case ProtoTypeTCP:
return "tcp"
default:
return ErrUnknownType.Error()
}
}
// URL represents a STUN (rfc7064) or TURN (rfc7065) URL
type URL struct {
Scheme SchemeType
Host string
Port int
Username string
Password string
Proto ProtoType
}
// Unknown represents and unknown ProtoType or SchemeType
//
// Deprecated: Please use pion/stun.SchemeTypeUnknown or pion/stun.ProtoTypeUnknown
const Unknown = 0
// ParseURL parses a STUN or TURN urls following the ABNF syntax described in
// https://tools.ietf.org/html/rfc7064 and https://tools.ietf.org/html/rfc7065
// respectively.
func ParseURL(raw string) (*URL, error) { //nolint:gocognit
rawParts, err := url.Parse(raw)
if err != nil {
return nil, err
}
//
// Deprecated: Please use pion/stun.ParseURI
var ParseURL = stun.ParseURI //nolint:gochecknoglobals
var u URL
u.Scheme = NewSchemeType(rawParts.Scheme)
if u.Scheme == SchemeType(Unknown) {
return nil, ErrSchemeType
}
// NewSchemeType defines a procedure for creating a new SchemeType from a raw
// string naming the scheme type.
//
// Deprecated: Please use pion/stun.NewSchemeType
var NewSchemeType = stun.NewSchemeType //nolint:gochecknoglobals
var rawPort string
if u.Host, rawPort, err = net.SplitHostPort(rawParts.Opaque); err != nil {
var e *net.AddrError
if errors.As(err, &e) {
if e.Err == "missing port in address" {
nextRawURL := u.Scheme.String() + ":" + rawParts.Opaque
switch {
case u.Scheme == SchemeTypeSTUN || u.Scheme == SchemeTypeTURN:
nextRawURL += ":3478"
if rawParts.RawQuery != "" {
nextRawURL += "?" + rawParts.RawQuery
}
return ParseURL(nextRawURL)
case u.Scheme == SchemeTypeSTUNS || u.Scheme == SchemeTypeTURNS:
nextRawURL += ":5349"
if rawParts.RawQuery != "" {
nextRawURL += "?" + rawParts.RawQuery
}
return ParseURL(nextRawURL)
}
}
}
return nil, err
}
if u.Host == "" {
return nil, ErrHost
}
if u.Port, err = strconv.Atoi(rawPort); err != nil {
return nil, ErrPort
}
switch u.Scheme {
case SchemeTypeSTUN:
qArgs, err := url.ParseQuery(rawParts.RawQuery)
if err != nil || len(qArgs) > 0 {
return nil, ErrSTUNQuery
}
u.Proto = ProtoTypeUDP
case SchemeTypeSTUNS:
qArgs, err := url.ParseQuery(rawParts.RawQuery)
if err != nil || len(qArgs) > 0 {
return nil, ErrSTUNQuery
}
u.Proto = ProtoTypeTCP
case SchemeTypeTURN:
proto, err := parseProto(rawParts.RawQuery)
if err != nil {
return nil, err
}
u.Proto = proto
if u.Proto == ProtoType(Unknown) {
u.Proto = ProtoTypeUDP
}
case SchemeTypeTURNS:
proto, err := parseProto(rawParts.RawQuery)
if err != nil {
return nil, err
}
u.Proto = proto
if u.Proto == ProtoType(Unknown) {
u.Proto = ProtoTypeTCP
}
}
return &u, nil
}
func parseProto(raw string) (ProtoType, error) {
qArgs, err := url.ParseQuery(raw)
if err != nil || len(qArgs) > 1 {
return ProtoType(Unknown), ErrInvalidQuery
}
var proto ProtoType
if rawProto := qArgs.Get("transport"); rawProto != "" {
if proto = NewProtoType(rawProto); proto == ProtoType(0) {
return ProtoType(Unknown), ErrProtoType
}
return proto, nil
}
if len(qArgs) > 0 {
return ProtoType(Unknown), ErrInvalidQuery
}
return proto, nil
}
func (u URL) String() string {
rawURL := u.Scheme.String() + ":" + net.JoinHostPort(u.Host, strconv.Itoa(u.Port))
if u.Scheme == SchemeTypeTURN || u.Scheme == SchemeTypeTURNS {
rawURL += "?transport=" + u.Proto.String()
}
return rawURL
}
// IsSecure returns whether the this URL's scheme describes secure scheme or not.
func (u URL) IsSecure() bool {
return u.Scheme == SchemeTypeSTUNS || u.Scheme == SchemeTypeTURNS
}
// NewProtoType defines a procedure for creating a new ProtoType from a raw
// string naming the transport protocol type.
//
// Deprecated: Please use pion/stun.NewProtoType
var NewProtoType = stun.NewProtoType //nolint:gochecknoglobals

View File

@@ -1,87 +0,0 @@
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package ice
import (
"errors"
"fmt"
"net"
"net/url"
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseURL(t *testing.T) {
t.Run("Success", func(t *testing.T) {
testCases := []struct {
rawURL string
expectedURLString string
expectedScheme SchemeType
expectedSecure bool
expectedHost string
expectedPort int
expectedProto ProtoType
}{
{"stun:google.de", "stun:google.de:3478", SchemeTypeSTUN, false, "google.de", 3478, ProtoTypeUDP},
{"stun:google.de:1234", "stun:google.de:1234", SchemeTypeSTUN, false, "google.de", 1234, ProtoTypeUDP},
{"stuns:google.de", "stuns:google.de:5349", SchemeTypeSTUNS, true, "google.de", 5349, ProtoTypeTCP},
{"stun:[::1]:123", "stun:[::1]:123", SchemeTypeSTUN, false, "::1", 123, ProtoTypeUDP},
{"turn:google.de", "turn:google.de:3478?transport=udp", SchemeTypeTURN, false, "google.de", 3478, ProtoTypeUDP},
{"turns:google.de", "turns:google.de:5349?transport=tcp", SchemeTypeTURNS, true, "google.de", 5349, ProtoTypeTCP},
{"turn:google.de?transport=udp", "turn:google.de:3478?transport=udp", SchemeTypeTURN, false, "google.de", 3478, ProtoTypeUDP},
{"turns:google.de?transport=tcp", "turns:google.de:5349?transport=tcp", SchemeTypeTURNS, true, "google.de", 5349, ProtoTypeTCP},
}
for i, testCase := range testCases {
url, err := ParseURL(testCase.rawURL)
assert.Nil(t, err, "testCase: %d %v", i, testCase)
if err != nil {
return
}
assert.Equal(t, testCase.expectedScheme, url.Scheme, "testCase: %d %v", i, testCase)
assert.Equal(t, testCase.expectedURLString, url.String(), "testCase: %d %v", i, testCase)
assert.Equal(t, testCase.expectedSecure, url.IsSecure(), "testCase: %d %v", i, testCase)
assert.Equal(t, testCase.expectedHost, url.Host, "testCase: %d %v", i, testCase)
assert.Equal(t, testCase.expectedPort, url.Port, "testCase: %d %v", i, testCase)
assert.Equal(t, testCase.expectedProto, url.Proto, "testCase: %d %v", i, testCase)
}
})
t.Run("Failure", func(t *testing.T) {
testCases := []struct {
rawURL string
expectedErr error
}{
{"", ErrSchemeType},
{":::", errMissingProtocolScheme},
{"stun:[::1]:123:", errTooManyColonsAddr},
{"stun:[::1]:123a", ErrPort},
{"google.de", ErrSchemeType},
{"stun:", ErrHost},
{"stun:google.de:abc", ErrPort},
{"stun:google.de?transport=udp", ErrSTUNQuery},
{"stuns:google.de?transport=udp", ErrSTUNQuery},
{"turn:google.de?trans=udp", ErrInvalidQuery},
{"turns:google.de?trans=udp", ErrInvalidQuery},
{"turns:google.de?transport=udp&another=1", ErrInvalidQuery},
{"turn:google.de?transport=ip", ErrProtoType},
}
for i, testCase := range testCases {
_, err := ParseURL(testCase.rawURL)
var (
urlError *url.Error
addrError *net.AddrError
)
switch {
case errors.As(err, &urlError):
err = urlError.Err
case errors.As(err, &addrError):
err = fmt.Errorf(addrError.Err) //nolint:goerr113
}
assert.EqualError(t, err, testCase.expectedErr.Error(), "testCase: %d %v", i, testCase)
}
})
}