diff --git a/agent.go b/agent.go index 9cb14b2..c7f5037 100644 --- a/agent.go +++ b/agent.go @@ -908,7 +908,16 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr) return } - prflxCandidate, err := NewCandidatePeerReflexive(networkType.String(), ip.String(), port, local.Component(), "", 0) + prflxCandidateConfig := CandidatePeerReflexiveConfig{ + Network: networkType.String(), + Address: ip.String(), + Port: port, + Component: local.Component(), + RelAddr: "", + RelPort: 0, + } + + prflxCandidate, err := NewCandidatePeerReflexive(&prflxCandidateConfig) if err != nil { a.log.Errorf("Failed to create new remote prflx candidate (%s)", err) return diff --git a/agent_test.go b/agent_test.go index 01f07e7..20d926e 100644 --- a/agent_test.go +++ b/agent_test.go @@ -61,50 +61,63 @@ func TestPairPriority(t *testing.T) { t.Fatalf("Failed to create agent: %s", err) } - hostLocal, err := NewCandidateHost( - "udp", - "192.168.1.1", 19216, - 1, - ) + hostConfig := &CandidateHostConfig{ + Network: "udp", + Address: "192.168.1.1", + Port: 19216, + Component: 1, + } + hostLocal, err := NewCandidateHost(hostConfig) if err != nil { t.Fatalf("Failed to construct local host candidate: %s", err) } - relayRemote, err := NewCandidateRelay( - "udp", - "1.2.3.4", 12340, - 1, - "4.3.2.1", 43210, - ) + relayConfig := &CandidateRelayConfig{ + Network: "udp", + Address: "1.2.3.4", + Port: 12340, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43210, + } + relayRemote, err := NewCandidateRelay(relayConfig) if err != nil { t.Fatalf("Failed to construct remote relay candidate: %s", err) } - srflxRemote, err := NewCandidateServerReflexive( - "udp", - "10.10.10.2", 19218, - 1, - "4.3.2.1", 43212, - ) + srflxConfig := &CandidateServerReflexiveConfig{ + Network: "udp", + Address: "10.10.10.2", + Port: 19218, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43212, + } + srflxRemote, err := NewCandidateServerReflexive(srflxConfig) if err != nil { t.Fatalf("Failed to construct remote srflx candidate: %s", err) } - prflxRemote, err := NewCandidatePeerReflexive( - "udp", - "10.10.10.2", 19217, - 1, - "4.3.2.1", 43211, - ) + prflxConfig := &CandidatePeerReflexiveConfig{ + Network: "udp", + Address: "10.10.10.2", + Port: 19217, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43211, + } + prflxRemote, err := NewCandidatePeerReflexive(prflxConfig) if err != nil { t.Fatalf("Failed to construct remote prflx candidate: %s", err) } - hostRemote, err := NewCandidateHost( - "udp", - "1.2.3.5", 12350, - 1, - ) + hostConfig = &CandidateHostConfig{ + Network: "udp", + Address: "1.2.3.5", + Port: 12350, + Component: 1, + } + hostRemote, err := NewCandidateHost(hostConfig) if err != nil { t.Fatalf("Failed to construct remote host candidate: %s", err) } @@ -143,21 +156,26 @@ func TestOnSelectedCandidatePairChange(t *testing.T) { t.Fatalf("Failed to set agent OnCandidatePairChange callback: %s", err) } - hostLocal, err := NewCandidateHost( - "udp", - "192.168.1.1", 19216, - 1, - ) + hostConfig := &CandidateHostConfig{ + Network: "udp", + Address: "192.168.1.1", + Port: 19216, + Component: 1, + } + hostLocal, err := NewCandidateHost(hostConfig) if err != nil { t.Fatalf("Failed to construct local host candidate: %s", err) } - relayRemote, err := NewCandidateRelay( - "udp", - "1.2.3.4", 12340, - 1, - "4.3.2.1", 43210, - ) + relayConfig := &CandidateRelayConfig{ + Network: "udp", + Address: "1.2.3.4", + Port: 12340, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43210, + } + relayRemote, err := NewCandidateRelay(relayConfig) if err != nil { t.Fatalf("Failed to construct remote relay candidate: %s", err) } @@ -204,7 +222,14 @@ func TestHandlePeerReflexive(t *testing.T) { var config AgentConfig runAgentTest(t, &config, func(a *Agent) { a.selector = &controllingSelector{agent: a, log: a.log} - local, err := NewCandidateHost("udp", "192.168.0.2", 777, 1) + + hostConfig := CandidateHostConfig{ + Network: "udp", + Address: "192.168.0.2", + Port: 777, + Component: 1, + } + local, err := NewCandidateHost(&hostConfig) local.conn = &mockPacketConn{} if err != nil { t.Fatalf("failed to create a new candidate: %v", err) @@ -262,7 +287,14 @@ func TestHandlePeerReflexive(t *testing.T) { var config AgentConfig runAgentTest(t, &config, func(a *Agent) { a.selector = &controllingSelector{agent: a, log: a.log} - local, err := NewCandidateHost("tcp", "192.168.0.2", 777, 1) + + hostConfig := CandidateHostConfig{ + Network: "tcp", + Address: "192.168.0.2", + Port: 777, + Component: 1, + } + local, err := NewCandidateHost(&hostConfig) if err != nil { t.Fatalf("failed to create a new candidate: %v", err) } @@ -292,7 +324,13 @@ func TestHandlePeerReflexive(t *testing.T) { {tID, &net.UDPAddr{}, false}, } - local, err := NewCandidateHost("udp", "192.168.0.2", 777, 1) + hostConfig := CandidateHostConfig{ + Network: "udp", + Address: "192.168.0.2", + Port: 777, + Component: 1, + } + local, err := NewCandidateHost(&hostConfig) local.conn = &mockPacketConn{} if err != nil { t.Fatalf("failed to create a new candidate: %v", err) @@ -371,7 +409,13 @@ func TestInboundValidity(t *testing.T) { } remote := &net.UDPAddr{IP: net.ParseIP("172.17.0.3"), Port: 999} - local, err := NewCandidateHost("udp", "192.168.0.2", 777, 1) + hostConfig := CandidateHostConfig{ + Network: "udp", + Address: "192.168.0.2", + Port: 777, + Component: 1, + } + local, err := NewCandidateHost(&hostConfig) local.conn = &mockPacketConn{} if err != nil { t.Fatalf("failed to create a new candidate: %v", err) @@ -462,7 +506,13 @@ func TestInboundValidity(t *testing.T) { t.Fatalf("Error constructing ice.Agent") } - local, err := NewCandidateHost("udp", "192.168.0.2", 777, 1) + hostConfig := CandidateHostConfig{ + Network: "udp", + Address: "192.168.0.2", + Port: 777, + Component: 1, + } + local, err := NewCandidateHost(&hostConfig) local.conn = &mockPacketConn{} if err != nil { t.Fatalf("failed to create a new candidate: %v", err) @@ -627,50 +677,63 @@ func TestCandidatePairStats(t *testing.T) { t.Fatalf("Failed to create agent: %s", err) } - hostLocal, err := NewCandidateHost( - "udp", - "192.168.1.1", 19216, - 1, - ) + hostConfig := &CandidateHostConfig{ + Network: "udp", + Address: "192.168.1.1", + Port: 19216, + Component: 1, + } + hostLocal, err := NewCandidateHost(hostConfig) if err != nil { t.Fatalf("Failed to construct local host candidate: %s", err) } - relayRemote, err := NewCandidateRelay( - "udp", - "1.2.3.4", 2340, - 1, - "4.3.2.1", 43210, - ) + relayConfig := &CandidateRelayConfig{ + Network: "udp", + Address: "1.2.3.4", + Port: 2340, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43210, + } + relayRemote, err := NewCandidateRelay(relayConfig) if err != nil { t.Fatalf("Failed to construct remote relay candidate: %s", err) } - srflxRemote, err := NewCandidateServerReflexive( - "udp", - "10.10.10.2", 19218, - 1, - "4.3.2.1", 43212, - ) + srflxConfig := &CandidateServerReflexiveConfig{ + Network: "udp", + Address: "10.10.10.2", + Port: 19218, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43212, + } + srflxRemote, err := NewCandidateServerReflexive(srflxConfig) if err != nil { t.Fatalf("Failed to construct remote srflx candidate: %s", err) } - prflxRemote, err := NewCandidatePeerReflexive( - "udp", - "10.10.10.2", 19217, - 1, - "4.3.2.1", 43211, - ) + prflxConfig := &CandidatePeerReflexiveConfig{ + Network: "udp", + Address: "10.10.10.2", + Port: 19217, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43211, + } + prflxRemote, err := NewCandidatePeerReflexive(prflxConfig) if err != nil { t.Fatalf("Failed to construct remote prflx candidate: %s", err) } - hostRemote, err := NewCandidateHost( - "udp", - "1.2.3.5", 12350, - 1, - ) + hostConfig = &CandidateHostConfig{ + Network: "udp", + Address: "1.2.3.5", + Port: 12350, + Component: 1, + } + hostRemote, err := NewCandidateHost(hostConfig) if err != nil { t.Fatalf("Failed to construct remote host candidate: %s", err) } @@ -746,21 +809,26 @@ func TestLocalCandidateStats(t *testing.T) { t.Fatalf("Failed to create agent: %s", err) } - hostLocal, err := NewCandidateHost( - "udp", - "192.168.1.1", 19216, - 1, - ) + hostConfig := &CandidateHostConfig{ + Network: "udp", + Address: "192.168.1.1", + Port: 19216, + Component: 1, + } + hostLocal, err := NewCandidateHost(hostConfig) if err != nil { t.Fatalf("Failed to construct local host candidate: %s", err) } - srflxLocal, err := NewCandidateServerReflexive( - "udp", - "192.168.1.1", 19217, - 1, - "4.3.2.1", 43212, - ) + srflxConfig := &CandidateServerReflexiveConfig{ + Network: "udp", + Address: "192.168.1.1", + Port: 19217, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43212, + } + srflxLocal, err := NewCandidateServerReflexive(srflxConfig) if err != nil { t.Fatalf("Failed to construct local srflx candidate: %s", err) } @@ -821,41 +889,52 @@ func TestRemoteCandidateStats(t *testing.T) { t.Fatalf("Failed to create agent: %s", err) } - relayRemote, err := NewCandidateRelay( - "udp", - "1.2.3.4", 12340, - 1, - "4.3.2.1", 43210, - ) + relayConfig := &CandidateRelayConfig{ + Network: "udp", + Address: "1.2.3.4", + Port: 12340, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43210, + } + relayRemote, err := NewCandidateRelay(relayConfig) if err != nil { t.Fatalf("Failed to construct remote relay candidate: %s", err) } - srflxRemote, err := NewCandidateServerReflexive( - "udp", - "10.10.10.2", 19218, - 1, - "4.3.2.1", 43212, - ) + srflxConfig := &CandidateServerReflexiveConfig{ + Network: "udp", + Address: "10.10.10.2", + Port: 19218, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43212, + } + srflxRemote, err := NewCandidateServerReflexive(srflxConfig) if err != nil { t.Fatalf("Failed to construct remote srflx candidate: %s", err) } - prflxRemote, err := NewCandidatePeerReflexive( - "udp", - "10.10.10.2", 19217, - 1, - "4.3.2.1", 43211, - ) + prflxConfig := &CandidatePeerReflexiveConfig{ + Network: "udp", + Address: "10.10.10.2", + Port: 19217, + Component: 1, + RelAddr: "4.3.2.1", + RelPort: 43211, + } + prflxRemote, err := NewCandidatePeerReflexive(prflxConfig) if err != nil { t.Fatalf("Failed to construct remote prflx candidate: %s", err) } - hostRemote, err := NewCandidateHost( - "udp", - "1.2.3.5", 12350, - 1, - ) + hostConfig := &CandidateHostConfig{ + Network: "udp", + Address: "1.2.3.5", + Port: 12350, + Component: 1, + } + hostRemote, err := NewCandidateHost(hostConfig) if err != nil { t.Fatalf("Failed to construct remote host candidate: %s", err) } diff --git a/candidate_host.go b/candidate_host.go index e8b766a..6a80198 100644 --- a/candidate_host.go +++ b/candidate_host.go @@ -12,26 +12,40 @@ type CandidateHost struct { network string } +// CandidateHostConfig is the config required to create a new CandidateHost +type CandidateHostConfig struct { + CandidateID string + Network string + Address string + Port int + Component uint16 +} + // NewCandidateHost creates a new host candidate -func NewCandidateHost(network string, address string, port int, component uint16) (*CandidateHost, error) { - candidateID, err := generateCandidateID() - if err != nil { - return nil, err +func NewCandidateHost(config *CandidateHostConfig) (*CandidateHost, error) { + candidateID := config.CandidateID + + if candidateID == "" { + var err error + candidateID, err = generateCandidateID() + if err != nil { + return nil, err + } } c := &CandidateHost{ candidateBase: candidateBase{ id: candidateID, - address: address, + address: config.Address, candidateType: CandidateTypeHost, - component: component, - port: port, + component: config.Component, + port: config.Port, }, - network: network, + network: config.Network, } - if !strings.HasSuffix(address, ".local") { - ip := net.ParseIP(address) + if !strings.HasSuffix(config.Address, ".local") { + ip := net.ParseIP(config.Address) if ip == nil { return nil, ErrAddressParseFailed } diff --git a/candidate_peer_reflexive.go b/candidate_peer_reflexive.go index b5a5162..b9417c2 100644 --- a/candidate_peer_reflexive.go +++ b/candidate_peer_reflexive.go @@ -1,3 +1,5 @@ +// Package ice ... +//nolint:dupl package ice import "net" @@ -7,21 +9,36 @@ type CandidatePeerReflexive struct { candidateBase } +// CandidatePeerReflexiveConfig is the config required to create a new CandidatePeerReflexive +type CandidatePeerReflexiveConfig struct { + CandidateID string + Network string + Address string + Port int + Component uint16 + RelAddr string + RelPort int +} + // NewCandidatePeerReflexive creates a new peer reflective candidate -func NewCandidatePeerReflexive(network string, address string, port int, component uint16, relAddr string, relPort int) (*CandidatePeerReflexive, error) { - ip := net.ParseIP(address) +func NewCandidatePeerReflexive(config *CandidatePeerReflexiveConfig) (*CandidatePeerReflexive, error) { + ip := net.ParseIP(config.Address) if ip == nil { return nil, ErrAddressParseFailed } - networkType, err := determineNetworkType(network, ip) + networkType, err := determineNetworkType(config.Network, ip) if err != nil { return nil, err } - candidateID, err := generateCandidateID() - if err != nil { - return nil, err + candidateID := config.CandidateID + if candidateID == "" { + var err error + candidateID, err = generateCandidateID() + if err != nil { + return nil, err + } } return &CandidatePeerReflexive{ @@ -29,13 +46,13 @@ func NewCandidatePeerReflexive(network string, address string, port int, compone id: candidateID, networkType: networkType, candidateType: CandidateTypePeerReflexive, - address: address, - port: port, - resolvedAddr: &net.UDPAddr{IP: ip, Port: port}, - component: component, + address: config.Address, + port: config.Port, + resolvedAddr: &net.UDPAddr{IP: ip, Port: config.Port}, + component: config.Component, relatedAddress: &CandidateRelatedAddress{ - Address: relAddr, - Port: relPort, + Address: config.RelAddr, + Port: config.RelPort, }, }, }, nil diff --git a/candidate_relay.go b/candidate_relay.go index 7a983e1..7192377 100644 --- a/candidate_relay.go +++ b/candidate_relay.go @@ -17,19 +17,35 @@ type CandidateRelay struct { permissions map[string]*turnc.Permission } +// CandidateRelayConfig is the config required to create a new CandidateRelay +type CandidateRelayConfig struct { + CandidateID string + Network string + Address string + Port int + Component uint16 + RelAddr string + RelPort int +} + // NewCandidateRelay creates a new relay candidate -func NewCandidateRelay(network string, address string, port int, component uint16, relAddr string, relPort int) (*CandidateRelay, error) { - ip := net.ParseIP(address) +func NewCandidateRelay(config *CandidateRelayConfig) (*CandidateRelay, error) { + candidateID := config.CandidateID + + if candidateID == "" { + var err error + candidateID, err = generateCandidateID() + if err != nil { + return nil, err + } + } + + ip := net.ParseIP(config.Address) if ip == nil { return nil, ErrAddressParseFailed } - networkType, err := determineNetworkType(network, ip) - if err != nil { - return nil, err - } - - candidateID, err := generateCandidateID() + networkType, err := determineNetworkType(config.Network, ip) if err != nil { return nil, err } @@ -39,13 +55,13 @@ func NewCandidateRelay(network string, address string, port int, component uint1 id: candidateID, networkType: networkType, candidateType: CandidateTypeRelay, - address: address, - port: port, - resolvedAddr: &net.UDPAddr{IP: ip, Port: port}, - component: component, + address: config.Address, + port: config.Port, + resolvedAddr: &net.UDPAddr{IP: ip, Port: config.Port}, + component: config.Component, relatedAddress: &CandidateRelatedAddress{ - Address: relAddr, - Port: relPort, + Address: config.RelAddr, + Port: config.RelPort, }, }, permissions: map[string]*turnc.Permission{}, diff --git a/candidate_server_reflexive.go b/candidate_server_reflexive.go index c7ca3e2..e50e5e3 100644 --- a/candidate_server_reflexive.go +++ b/candidate_server_reflexive.go @@ -7,21 +7,35 @@ type CandidateServerReflexive struct { candidateBase } +// CandidateServerReflexiveConfig is the config required to create a new CandidateServerReflexive +type CandidateServerReflexiveConfig struct { + CandidateID string + Network string + Address string + Port int + Component uint16 + RelAddr string + RelPort int +} + // NewCandidateServerReflexive creates a new server reflective candidate -func NewCandidateServerReflexive(network string, address string, port int, component uint16, relAddr string, relPort int) (*CandidateServerReflexive, error) { - ip := net.ParseIP(address) +func NewCandidateServerReflexive(config *CandidateServerReflexiveConfig) (*CandidateServerReflexive, error) { + ip := net.ParseIP(config.Address) if ip == nil { return nil, ErrAddressParseFailed } - networkType, err := determineNetworkType(network, ip) + networkType, err := determineNetworkType(config.Network, ip) if err != nil { return nil, err } - candidateID, err := generateCandidateID() - if err != nil { - return nil, err + candidateID := config.CandidateID + if candidateID == "" { + candidateID, err = generateCandidateID() + if err != nil { + return nil, err + } } return &CandidateServerReflexive{ @@ -29,13 +43,13 @@ func NewCandidateServerReflexive(network string, address string, port int, compo id: candidateID, networkType: networkType, candidateType: CandidateTypeServerReflexive, - address: address, - port: port, - resolvedAddr: &net.UDPAddr{IP: ip, Port: port}, - component: component, + address: config.Address, + port: config.Port, + resolvedAddr: &net.UDPAddr{IP: ip, Port: config.Port}, + component: config.Component, relatedAddress: &CandidateRelatedAddress{ - Address: relAddr, - Port: relPort, + Address: config.RelAddr, + Port: config.RelPort, }, }, }, nil diff --git a/gather.go b/gather.go index 5f8d16e..ad7a7c5 100644 --- a/gather.go +++ b/gather.go @@ -182,7 +182,15 @@ func (a *Agent) gatherCandidatesLocal(networkTypes []NetworkType) { } port := conn.LocalAddr().(*net.UDPAddr).Port - c, err := NewCandidateHost(network, address, port, ComponentRTP) + + hostConfig := CandidateHostConfig{ + Network: network, + Address: address, + Port: port, + Component: ComponentRTP, + } + + c, err := NewCandidateHost(&hostConfig) if err != nil { a.log.Warnf("Failed to create host candidate: %s %s %d: %v\n", network, ip, port, err) return @@ -249,7 +257,16 @@ func (a *Agent) gatherCandidatesSrflx(urls []*URL, networkTypes []NetworkType) { port := xoraddr.Port relIP := laddr.IP.String() relPort := laddr.Port - c, err := NewCandidateServerReflexive(network, ip.String(), port, ComponentRTP, relIP, relPort) + + srflxConfig := CandidateServerReflexiveConfig{ + Network: network, + Address: ip.String(), + Port: port, + Component: ComponentRTP, + RelAddr: relIP, + RelPort: relPort, + } + c, err := NewCandidateServerReflexive(&srflxConfig) if err != nil { a.log.Warnf("Failed to create server reflexive candidate: %s %s %d: %v\n", network, ip, port, err) continue @@ -314,7 +331,15 @@ func (a *Agent) gatherCandidatesRelay(urls []*URL) error { ip := allocation.Relayed().IP port := allocation.Relayed().Port - candidate, err := NewCandidateRelay(network, ip.String(), port, ComponentRTP, laddr.IP.String(), laddr.Port) + relayConfig := CandidateRelayConfig{ + Network: network, + Address: ip.String(), + Port: port, + Component: ComponentRTP, + RelAddr: laddr.IP.String(), + RelPort: laddr.Port, + } + candidate, err := NewCandidateRelay(&relayConfig) if err != nil { a.log.Warnf("Failed to create server reflexive candidate: %s %s %d: %v\n", network, ip, port, err) continue diff --git a/transport_test.go b/transport_test.go index d365888..401e7d6 100644 --- a/transport_test.go +++ b/transport_test.go @@ -331,14 +331,40 @@ func pipeWithTimeout(iceTimeout time.Duration, iceKeepalive time.Duration) (*Con } func copyCandidate(o Candidate) (c Candidate) { + candidateID := o.ID() var err error switch orig := o.(type) { case *CandidateHost: - c, err = NewCandidateHost(udp, orig.address, orig.port, orig.component) + config := CandidateHostConfig{ + CandidateID: candidateID, + Network: udp, + Address: orig.address, + Port: orig.port, + Component: orig.component, + } + c, err = NewCandidateHost(&config) case *CandidateServerReflexive: - c, err = NewCandidateServerReflexive(udp, orig.address, orig.port, orig.component, orig.relatedAddress.Address, orig.relatedAddress.Port) + config := CandidateServerReflexiveConfig{ + CandidateID: candidateID, + Network: udp, + Address: orig.address, + Port: orig.port, + Component: orig.component, + RelAddr: orig.relatedAddress.Address, + RelPort: orig.relatedAddress.Port, + } + c, err = NewCandidateServerReflexive(&config) case *CandidateRelay: - c, err = NewCandidateRelay(udp, orig.address, orig.port, orig.component, orig.relatedAddress.Address, orig.relatedAddress.Port) + config := CandidateRelayConfig{ + CandidateID: candidateID, + Network: udp, + Address: orig.address, + Port: orig.port, + Component: orig.component, + RelAddr: orig.relatedAddress.Address, + RelPort: orig.relatedAddress.Port, + } + c, err = NewCandidateRelay(&config) default: panic("Tried to copy unsupported candidate type") }