mirror of
https://github.com/pion/ice.git
synced 2025-10-07 00:12:47 +08:00
Update CI configs to v0.4.7
Update lint scripts and CI configs.
This commit is contained in:
@@ -3,6 +3,80 @@ linters-settings:
|
|||||||
check-shadowing: true
|
check-shadowing: true
|
||||||
misspell:
|
misspell:
|
||||||
locale: US
|
locale: US
|
||||||
|
exhaustive:
|
||||||
|
default-signifies-exhaustive: true
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers
|
||||||
|
- bodyclose # checks whether HTTP response body is closed successfully
|
||||||
|
- deadcode # Finds unused code
|
||||||
|
- depguard # Go linter that checks if package imports are in a list of acceptable packages
|
||||||
|
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
|
||||||
|
- dupl # Tool for code clone detection
|
||||||
|
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
|
||||||
|
- exhaustive # check exhaustiveness of enum switch statements
|
||||||
|
- exportloopref # checks for pointers to enclosing loop variables
|
||||||
|
- gci # Gci control golang package import order and make it always deterministic.
|
||||||
|
- gochecknoglobals # Checks that no globals are present in Go code
|
||||||
|
- gochecknoinits # Checks that no init functions are present in Go code
|
||||||
|
- gocognit # Computes and checks the cognitive complexity of functions
|
||||||
|
- goconst # Finds repeated strings that could be replaced by a constant
|
||||||
|
- gocritic # The most opinionated Go source code linter
|
||||||
|
- godox # Tool for detection of FIXME, TODO and other comment keywords
|
||||||
|
- goerr113 # Golang linter to check the errors handling expressions
|
||||||
|
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
|
||||||
|
- gofumpt # Gofumpt checks whether code was gofumpt-ed.
|
||||||
|
- goheader # Checks is file header matches to pattern
|
||||||
|
- goimports # Goimports does everything that gofmt does. Additionally it checks unused imports
|
||||||
|
- golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
|
||||||
|
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations.
|
||||||
|
- goprintffuncname # Checks that printf-like functions are named with `f` at the end
|
||||||
|
- gosec # Inspects source code for security problems
|
||||||
|
- gosimple # Linter for Go source code that specializes in simplifying a code
|
||||||
|
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
|
||||||
|
- ineffassign # Detects when assignments to existing variables are not used
|
||||||
|
- misspell # Finds commonly misspelled English words in comments
|
||||||
|
- nakedret # Finds naked returns in functions greater than a specified function length
|
||||||
|
- noctx # noctx finds sending http request without context.Context
|
||||||
|
- scopelint # Scopelint checks for unpinned variables in go programs
|
||||||
|
- staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks
|
||||||
|
- structcheck # Finds unused struct fields
|
||||||
|
- stylecheck # Stylecheck is a replacement for golint
|
||||||
|
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code
|
||||||
|
- unconvert # Remove unnecessary type conversions
|
||||||
|
- unparam # Reports unused function parameters
|
||||||
|
- unused # Checks Go code for unused constants, variables, functions and types
|
||||||
|
- varcheck # Finds unused global variables and constants
|
||||||
|
- whitespace # Tool for detection of leading and trailing whitespace
|
||||||
|
disable:
|
||||||
|
- funlen # Tool for detection of long functions
|
||||||
|
- gocyclo # Computes and checks the cyclomatic complexity of functions
|
||||||
|
- godot # Check if comments end in a period
|
||||||
|
- gomnd # An analyzer to detect magic numbers.
|
||||||
|
- lll # Reports long lines
|
||||||
|
- maligned # Tool to detect Go structs that would take less memory if their fields were sorted
|
||||||
|
- nestif # Reports deeply nested if statements
|
||||||
|
- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity
|
||||||
|
- nolintlint # Reports ill-formed or insufficient nolint directives
|
||||||
|
- prealloc # Finds slice declarations that could potentially be preallocated
|
||||||
|
- rowserrcheck # checks whether Err of rows is checked successfully
|
||||||
|
- sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed.
|
||||||
|
- testpackage # linter that makes you use a separate _test package
|
||||||
|
- wsl # Whitespace Linter - Forces you to use empty lines!
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
# Allow complex tests, better to be self contained
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- gocognit
|
||||||
|
|
||||||
|
# Allow complex main function in examples
|
||||||
|
- path: examples
|
||||||
|
text: "of func `main` is high"
|
||||||
|
linters:
|
||||||
|
- gocognit
|
||||||
|
|
||||||
run:
|
run:
|
||||||
skip-dirs-use-default: false
|
skip-dirs-use-default: false
|
||||||
|
@@ -58,6 +58,7 @@ Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contribu
|
|||||||
* [Sidney San Martín](https://github.com/s4y)
|
* [Sidney San Martín](https://github.com/s4y)
|
||||||
* [JooYoung Lim](https://github.com/DevRockstarZ)
|
* [JooYoung Lim](https://github.com/DevRockstarZ)
|
||||||
* [Kory Miller](https://github.com/korymiller1489)
|
* [Kory Miller](https://github.com/korymiller1489)
|
||||||
|
* [ZHENK](https://github.com/scorpionknifes)
|
||||||
|
|
||||||
### License
|
### License
|
||||||
MIT License - see [LICENSE](LICENSE) for full text
|
MIT License - see [LICENSE](LICENSE) for full text
|
||||||
|
7
agent.go
7
agent.go
@@ -224,7 +224,7 @@ func (a *Agent) taskLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewAgent creates a new Agent
|
// NewAgent creates a new Agent
|
||||||
func NewAgent(config *AgentConfig) (*Agent, error) {
|
func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit
|
||||||
var err error
|
var err error
|
||||||
if config.PortMax < config.PortMin {
|
if config.PortMax < config.PortMin {
|
||||||
return nil, ErrPort
|
return nil, ErrPort
|
||||||
@@ -748,7 +748,7 @@ func (a *Agent) resolveAndAddMulticastCandidate(c *CandidateHost) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ip, _, _, _ := parseAddr(src)
|
ip, _, _, _ := parseAddr(src) //nolint:dogsled
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
a.log.Warnf("Failed to discover mDNS candidate %s: failed to parse IP", c.Address())
|
a.log.Warnf("Failed to discover mDNS candidate %s: failed to parse IP", c.Address())
|
||||||
return
|
return
|
||||||
@@ -1009,7 +1009,7 @@ func (a *Agent) handleInboundBindingSuccess(id [stun.TransactionIDSize]byte) (bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handleInbound processes STUN traffic from a remote candidate
|
// handleInbound processes STUN traffic from a remote candidate
|
||||||
func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr) {
|
func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr) { //nolint:gocognit
|
||||||
var err error
|
var err error
|
||||||
if m == nil || local == nil {
|
if m == nil || local == nil {
|
||||||
return
|
return
|
||||||
@@ -1074,7 +1074,6 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr)
|
|||||||
Component: local.Component(),
|
Component: local.Component(),
|
||||||
RelAddr: "",
|
RelAddr: "",
|
||||||
RelPort: 0,
|
RelPort: 0,
|
||||||
// TODO set TCPType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prflxCandidate, err := NewCandidatePeerReflexive(&prflxCandidateConfig)
|
prflxCandidate, err := NewCandidatePeerReflexive(&prflxCandidateConfig)
|
||||||
|
@@ -42,9 +42,9 @@ const (
|
|||||||
maxBindingRequestTimeout = 4000 * time.Millisecond
|
maxBindingRequestTimeout = 4000 * time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func defaultCandidateTypes() []CandidateType {
|
||||||
defaultCandidateTypes = []CandidateType{CandidateTypeHost, CandidateTypeServerReflexive, CandidateTypeRelay}
|
return []CandidateType{CandidateTypeHost, CandidateTypeServerReflexive, CandidateTypeRelay}
|
||||||
)
|
}
|
||||||
|
|
||||||
// AgentConfig collects the arguments to ice.Agent construction into
|
// AgentConfig collects the arguments to ice.Agent construction into
|
||||||
// a single structure, for future-proofness of the interface
|
// a single structure, for future-proofness of the interface
|
||||||
@@ -202,7 +202,7 @@ func (config *AgentConfig) initWithDefaults(a *Agent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.CandidateTypes == nil || len(config.CandidateTypes) == 0 {
|
if config.CandidateTypes == nil || len(config.CandidateTypes) == 0 {
|
||||||
a.candidateTypes = defaultCandidateTypes
|
a.candidateTypes = defaultCandidateTypes()
|
||||||
} else {
|
} else {
|
||||||
a.candidateTypes = config.CandidateTypes
|
a.candidateTypes = config.CandidateTypes
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ package ice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -39,7 +40,6 @@ func TestPairSearch(t *testing.T) {
|
|||||||
|
|
||||||
var config AgentConfig
|
var config AgentConfig
|
||||||
a, err := NewAgent(&config)
|
a, err := NewAgent(&config)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error constructing ice.Agent")
|
t.Fatalf("Error constructing ice.Agent")
|
||||||
}
|
}
|
||||||
@@ -208,13 +208,13 @@ type BadAddr struct{}
|
|||||||
func (ba *BadAddr) Network() string {
|
func (ba *BadAddr) Network() string {
|
||||||
return "xxx"
|
return "xxx"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ba *BadAddr) String() string {
|
func (ba *BadAddr) String() string {
|
||||||
return "yyy"
|
return "yyy"
|
||||||
}
|
}
|
||||||
|
|
||||||
func runAgentTest(t *testing.T, config *AgentConfig, task func(ctx context.Context, a *Agent)) {
|
func runAgentTest(t *testing.T, config *AgentConfig, task func(ctx context.Context, a *Agent)) {
|
||||||
a, err := NewAgent(config)
|
a, err := NewAgent(config)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error constructing ice.Agent")
|
t.Fatalf("Error constructing ice.Agent")
|
||||||
}
|
}
|
||||||
@@ -255,7 +255,7 @@ func TestHandlePeerReflexive(t *testing.T) {
|
|||||||
|
|
||||||
msg, err := stun.Build(stun.BindingRequest, stun.TransactionID,
|
msg, err := stun.Build(stun.BindingRequest, stun.TransactionID,
|
||||||
stun.NewUsername(a.localUfrag+":"+a.remoteUfrag),
|
stun.NewUsername(a.localUfrag+":"+a.remoteUfrag),
|
||||||
UseCandidate,
|
UseCandidate(),
|
||||||
AttrControlling(a.tieBreaker),
|
AttrControlling(a.tieBreaker),
|
||||||
PriorityAttr(local.Priority()),
|
PriorityAttr(local.Priority()),
|
||||||
stun.NewShortTermIntegrity(a.localPwd),
|
stun.NewShortTermIntegrity(a.localPwd),
|
||||||
@@ -325,7 +325,7 @@ func TestHandlePeerReflexive(t *testing.T) {
|
|||||||
runAgentTest(t, &config, func(ctx context.Context, a *Agent) {
|
runAgentTest(t, &config, func(ctx context.Context, a *Agent) {
|
||||||
a.selector = &controllingSelector{agent: a, log: a.log}
|
a.selector = &controllingSelector{agent: a, log: a.log}
|
||||||
tID := [stun.TransactionIDSize]byte{}
|
tID := [stun.TransactionIDSize]byte{}
|
||||||
copy(tID[:], []byte("ABC"))
|
copy(tID[:], "ABC")
|
||||||
a.pendingBindingRequests = []bindingRequest{
|
a.pendingBindingRequests = []bindingRequest{
|
||||||
{time.Now(), tID, &net.UDPAddr{}, false},
|
{time.Now(), tID, &net.UDPAddr{}, false},
|
||||||
}
|
}
|
||||||
@@ -392,7 +392,7 @@ func TestConnectivityOnStartup(t *testing.T) {
|
|||||||
|
|
||||||
KeepaliveInterval := time.Hour
|
KeepaliveInterval := time.Hour
|
||||||
cfg0 := &AgentConfig{
|
cfg0 := &AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
Net: net0,
|
Net: net0,
|
||||||
|
|
||||||
@@ -405,7 +405,7 @@ func TestConnectivityOnStartup(t *testing.T) {
|
|||||||
require.NoError(t, aAgent.OnConnectionStateChange(aNotifier))
|
require.NoError(t, aAgent.OnConnectionStateChange(aNotifier))
|
||||||
|
|
||||||
cfg1 := &AgentConfig{
|
cfg1 := &AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
Net: net1,
|
Net: net1,
|
||||||
KeepaliveInterval: &KeepaliveInterval,
|
KeepaliveInterval: &KeepaliveInterval,
|
||||||
@@ -498,7 +498,7 @@ func TestConnectivityLite(t *testing.T) {
|
|||||||
|
|
||||||
cfg0 := &AgentConfig{
|
cfg0 := &AgentConfig{
|
||||||
Urls: []*URL{stunServerURL},
|
Urls: []*URL{stunServerURL},
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
Net: v.net0,
|
Net: v.net0,
|
||||||
}
|
}
|
||||||
@@ -511,7 +511,7 @@ func TestConnectivityLite(t *testing.T) {
|
|||||||
Urls: []*URL{},
|
Urls: []*URL{},
|
||||||
Lite: true,
|
Lite: true,
|
||||||
CandidateTypes: []CandidateType{CandidateTypeHost},
|
CandidateTypes: []CandidateType{CandidateTypeHost},
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
Net: v.net1,
|
Net: v.net1,
|
||||||
}
|
}
|
||||||
@@ -666,7 +666,7 @@ func TestInboundValidity(t *testing.T) {
|
|||||||
|
|
||||||
remote := &net.UDPAddr{IP: net.ParseIP("172.17.0.3"), Port: 999}
|
remote := &net.UDPAddr{IP: net.ParseIP("172.17.0.3"), Port: 999}
|
||||||
tID := [stun.TransactionIDSize]byte{}
|
tID := [stun.TransactionIDSize]byte{}
|
||||||
copy(tID[:], []byte("ABC"))
|
copy(tID[:], "ABC")
|
||||||
msg, err := stun.Build(stun.BindingSuccess, stun.NewTransactionIDSetter(tID),
|
msg, err := stun.Build(stun.BindingSuccess, stun.NewTransactionIDSetter(tID),
|
||||||
stun.NewShortTermIntegrity(a.remotePwd),
|
stun.NewShortTermIntegrity(a.remotePwd),
|
||||||
stun.Fingerprint,
|
stun.Fingerprint,
|
||||||
@@ -693,19 +693,19 @@ func TestInvalidAgentStarts(t *testing.T) {
|
|||||||
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if _, err = a.Dial(ctx, "", "bar"); err != nil && err != ErrRemoteUfragEmpty {
|
if _, err = a.Dial(ctx, "", "bar"); err != nil && !errors.Is(err, ErrRemoteUfragEmpty) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = a.Dial(ctx, "foo", ""); err != nil && err != ErrRemotePwdEmpty {
|
if _, err = a.Dial(ctx, "foo", ""); err != nil && !errors.Is(err, ErrRemotePwdEmpty) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = a.Dial(ctx, "foo", "bar"); err != nil && err != ErrCanceledByCaller {
|
if _, err = a.Dial(ctx, "foo", "bar"); err != nil && !errors.Is(err, ErrCanceledByCaller) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = a.Dial(context.TODO(), "foo", "bar"); err != nil && err != ErrMultipleStart {
|
if _, err = a.Dial(context.TODO(), "foo", "bar"); err != nil && !errors.Is(err, ErrMultipleStart) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -726,7 +726,7 @@ func TestConnectionStateCallback(t *testing.T) {
|
|||||||
|
|
||||||
cfg := &AgentConfig{
|
cfg := &AgentConfig{
|
||||||
Urls: []*URL{},
|
Urls: []*URL{},
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
DisconnectedTimeout: &disconnectedDuration,
|
DisconnectedTimeout: &disconnectedDuration,
|
||||||
FailedTimeout: &failedDuration,
|
FailedTimeout: &failedDuration,
|
||||||
KeepaliveInterval: &KeepaliveInterval,
|
KeepaliveInterval: &KeepaliveInterval,
|
||||||
@@ -786,7 +786,7 @@ func TestInvalidGather(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = a.GatherCandidates()
|
err = a.GatherCandidates()
|
||||||
if err != ErrNoOnCandidateHandler {
|
if !errors.Is(err, ErrNoOnCandidateHandler) {
|
||||||
t.Fatal("trickle GatherCandidates succeeded without OnCandidate")
|
t.Fatal("trickle GatherCandidates succeeded without OnCandidate")
|
||||||
}
|
}
|
||||||
assert.NoError(t, a.Close())
|
assert.NoError(t, a.Close())
|
||||||
@@ -1161,7 +1161,7 @@ func TestInitExtIPMapping(t *testing.T) {
|
|||||||
NAT1To1IPCandidateType: CandidateTypeHost,
|
NAT1To1IPCandidateType: CandidateTypeHost,
|
||||||
CandidateTypes: []CandidateType{CandidateTypeRelay},
|
CandidateTypes: []CandidateType{CandidateTypeRelay},
|
||||||
})
|
})
|
||||||
if err != ErrIneffectiveNAT1To1IPMappingHost {
|
if !errors.Is(err, ErrIneffectiveNAT1To1IPMappingHost) {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1172,7 +1172,7 @@ func TestInitExtIPMapping(t *testing.T) {
|
|||||||
NAT1To1IPCandidateType: CandidateTypeServerReflexive,
|
NAT1To1IPCandidateType: CandidateTypeServerReflexive,
|
||||||
CandidateTypes: []CandidateType{CandidateTypeRelay},
|
CandidateTypes: []CandidateType{CandidateTypeRelay},
|
||||||
})
|
})
|
||||||
if err != ErrIneffectiveNAT1To1IPMappingSrflx {
|
if !errors.Is(err, ErrIneffectiveNAT1To1IPMappingSrflx) {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1183,7 +1183,7 @@ func TestInitExtIPMapping(t *testing.T) {
|
|||||||
NAT1To1IPCandidateType: CandidateTypeHost,
|
NAT1To1IPCandidateType: CandidateTypeHost,
|
||||||
MulticastDNSMode: MulticastDNSModeQueryAndGather,
|
MulticastDNSMode: MulticastDNSModeQueryAndGather,
|
||||||
})
|
})
|
||||||
if err != ErrMulticastDNSWithNAT1To1IPMapping {
|
if !errors.Is(err, ErrMulticastDNSWithNAT1To1IPMapping) {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1192,7 +1192,7 @@ func TestInitExtIPMapping(t *testing.T) {
|
|||||||
NAT1To1IPs: []string{"bad.2.3.4"}, // bad IP
|
NAT1To1IPs: []string{"bad.2.3.4"}, // bad IP
|
||||||
NAT1To1IPCandidateType: CandidateTypeHost,
|
NAT1To1IPCandidateType: CandidateTypeHost,
|
||||||
})
|
})
|
||||||
if err != ErrInvalidNAT1To1IPMapping {
|
if !errors.Is(err, ErrInvalidNAT1To1IPMapping) {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1269,7 +1269,7 @@ func TestConnectionStateFailedDeleteAllCandidates(t *testing.T) {
|
|||||||
KeepaliveInterval := time.Duration(0)
|
KeepaliveInterval := time.Duration(0)
|
||||||
|
|
||||||
cfg := &AgentConfig{
|
cfg := &AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
DisconnectedTimeout: &oneSecond,
|
DisconnectedTimeout: &oneSecond,
|
||||||
FailedTimeout: &oneSecond,
|
FailedTimeout: &oneSecond,
|
||||||
KeepaliveInterval: &KeepaliveInterval,
|
KeepaliveInterval: &KeepaliveInterval,
|
||||||
@@ -1496,7 +1496,7 @@ func TestCloseInConnectionStateCallback(t *testing.T) {
|
|||||||
|
|
||||||
cfg := &AgentConfig{
|
cfg := &AgentConfig{
|
||||||
Urls: []*URL{},
|
Urls: []*URL{},
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
DisconnectedTimeout: &disconnectedDuration,
|
DisconnectedTimeout: &disconnectedDuration,
|
||||||
FailedTimeout: &failedDuration,
|
FailedTimeout: &failedDuration,
|
||||||
KeepaliveInterval: &KeepaliveInterval,
|
KeepaliveInterval: &KeepaliveInterval,
|
||||||
@@ -1547,7 +1547,7 @@ func TestRunTaskInConnectionStateCallback(t *testing.T) {
|
|||||||
|
|
||||||
cfg := &AgentConfig{
|
cfg := &AgentConfig{
|
||||||
Urls: []*URL{},
|
Urls: []*URL{},
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
DisconnectedTimeout: &oneSecond,
|
DisconnectedTimeout: &oneSecond,
|
||||||
FailedTimeout: &oneSecond,
|
FailedTimeout: &oneSecond,
|
||||||
KeepaliveInterval: &KeepaliveInterval,
|
KeepaliveInterval: &KeepaliveInterval,
|
||||||
@@ -1591,7 +1591,7 @@ func TestRunTaskInSelectedCandidatePairChangeCallback(t *testing.T) {
|
|||||||
|
|
||||||
cfg := &AgentConfig{
|
cfg := &AgentConfig{
|
||||||
Urls: []*URL{},
|
Urls: []*URL{},
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
DisconnectedTimeout: &oneSecond,
|
DisconnectedTimeout: &oneSecond,
|
||||||
FailedTimeout: &oneSecond,
|
FailedTimeout: &oneSecond,
|
||||||
KeepaliveInterval: &KeepaliveInterval,
|
KeepaliveInterval: &KeepaliveInterval,
|
||||||
|
@@ -156,6 +156,8 @@ func (c *candidateBase) LocalPreference() uint16 {
|
|||||||
return 4
|
return 4
|
||||||
case TCPTypeSimultaneousOpen:
|
case TCPTypeSimultaneousOpen:
|
||||||
return 2
|
return 2
|
||||||
|
case TCPTypeUnspecified:
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
case CandidateTypePeerReflexive, CandidateTypeServerReflexive:
|
case CandidateTypePeerReflexive, CandidateTypeServerReflexive:
|
||||||
switch c.tcpType {
|
switch c.tcpType {
|
||||||
@@ -165,9 +167,12 @@ func (c *candidateBase) LocalPreference() uint16 {
|
|||||||
return 4
|
return 4
|
||||||
case TCPTypePassive:
|
case TCPTypePassive:
|
||||||
return 2
|
return 2
|
||||||
|
case TCPTypeUnspecified:
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
case CandidateTypeUnspecified:
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -295,7 +300,7 @@ func (c *candidateBase) close() error {
|
|||||||
func (c *candidateBase) writeTo(raw []byte, dst Candidate) (int, error) {
|
func (c *candidateBase) writeTo(raw []byte, dst Candidate) (int, error) {
|
||||||
n, err := c.conn.WriteTo(raw, dst.addr())
|
n, err := c.conn.WriteTo(raw, dst.addr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, fmt.Errorf("failed to send packet: %v", err)
|
return n, fmt.Errorf("%w: %v", errSendPacket, err)
|
||||||
}
|
}
|
||||||
c.seen(true)
|
c.seen(true)
|
||||||
return n, nil
|
return n, nil
|
||||||
@@ -410,7 +415,7 @@ func (c candidateBase) Marshal() string {
|
|||||||
func UnmarshalCandidate(raw string) (Candidate, error) {
|
func UnmarshalCandidate(raw string) (Candidate, error) {
|
||||||
split := strings.Fields(raw)
|
split := strings.Fields(raw)
|
||||||
if len(split) < 8 {
|
if len(split) < 8 {
|
||||||
return nil, fmt.Errorf("attribute not long enough to be ICE candidate (%d)", len(split))
|
return nil, fmt.Errorf("%w (%d)", errAttributeTooShortICECandidate, len(split))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Foundation
|
// Foundation
|
||||||
@@ -419,7 +424,7 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||||||
// Component
|
// Component
|
||||||
rawComponent, err := strconv.ParseUint(split[1], 10, 16)
|
rawComponent, err := strconv.ParseUint(split[1], 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not parse component: %v", err)
|
return nil, fmt.Errorf("%w: %v", errParseComponent, err)
|
||||||
}
|
}
|
||||||
component := uint16(rawComponent)
|
component := uint16(rawComponent)
|
||||||
|
|
||||||
@@ -429,7 +434,7 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||||||
// Priority
|
// Priority
|
||||||
priorityRaw, err := strconv.ParseUint(split[3], 10, 32)
|
priorityRaw, err := strconv.ParseUint(split[3], 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not parse priority: %v", err)
|
return nil, fmt.Errorf("%w: %v", errParsePriority, err)
|
||||||
}
|
}
|
||||||
priority := uint32(priorityRaw)
|
priority := uint32(priorityRaw)
|
||||||
|
|
||||||
@@ -439,7 +444,7 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||||||
// Port
|
// Port
|
||||||
rawPort, err := strconv.ParseUint(split[5], 10, 16)
|
rawPort, err := strconv.ParseUint(split[5], 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not parse port: %v", err)
|
return nil, fmt.Errorf("%w: %v", errParsePort, err)
|
||||||
}
|
}
|
||||||
port := int(rawPort)
|
port := int(rawPort)
|
||||||
typ := split[7]
|
typ := split[7]
|
||||||
@@ -453,7 +458,7 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||||||
|
|
||||||
if split[0] == "raddr" {
|
if split[0] == "raddr" {
|
||||||
if len(split) < 4 {
|
if len(split) < 4 {
|
||||||
return nil, fmt.Errorf("could not parse related addresses: incorrect length")
|
return nil, fmt.Errorf("%w: incorrect length", errParseRelatedAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RelatedAddress
|
// RelatedAddress
|
||||||
@@ -462,12 +467,12 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||||||
// RelatedPort
|
// RelatedPort
|
||||||
rawRelatedPort, parseErr := strconv.ParseUint(split[3], 10, 16)
|
rawRelatedPort, parseErr := strconv.ParseUint(split[3], 10, 16)
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return nil, fmt.Errorf("could not parse port: %v", parseErr)
|
return nil, fmt.Errorf("%w: %v", errParsePort, parseErr)
|
||||||
}
|
}
|
||||||
relatedPort = int(rawRelatedPort)
|
relatedPort = int(rawRelatedPort)
|
||||||
} else if split[0] == "tcptype" {
|
} else if split[0] == "tcptype" {
|
||||||
if len(split) < 2 {
|
if len(split) < 2 {
|
||||||
return nil, fmt.Errorf("could not parse typtype: incorrect length")
|
return nil, fmt.Errorf("%w: incorrect length", errParseTypType)
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpType = NewTCPType(split[1])
|
tcpType = NewTCPType(split[1])
|
||||||
@@ -476,15 +481,15 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||||||
|
|
||||||
switch typ {
|
switch typ {
|
||||||
case "host":
|
case "host":
|
||||||
return NewCandidateHost(&CandidateHostConfig{"", protocol, address, port, uint16(component), priority, foundation, tcpType})
|
return NewCandidateHost(&CandidateHostConfig{"", protocol, address, port, component, priority, foundation, tcpType})
|
||||||
case "srflx":
|
case "srflx":
|
||||||
return NewCandidateServerReflexive(&CandidateServerReflexiveConfig{"", protocol, address, port, uint16(component), priority, foundation, relatedAddress, relatedPort})
|
return NewCandidateServerReflexive(&CandidateServerReflexiveConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort})
|
||||||
case "prflx":
|
case "prflx":
|
||||||
return NewCandidatePeerReflexive(&CandidatePeerReflexiveConfig{"", protocol, address, port, uint16(component), priority, foundation, relatedAddress, relatedPort})
|
return NewCandidatePeerReflexive(&CandidatePeerReflexiveConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort})
|
||||||
case "relay":
|
case "relay":
|
||||||
return NewCandidateRelay(&CandidateRelayConfig{"", protocol, address, port, uint16(component), priority, foundation, relatedAddress, relatedPort, nil})
|
return NewCandidateRelay(&CandidateRelayConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort, nil})
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("Unknown candidate typ(%s)", typ)
|
return nil, fmt.Errorf("%w (%s)", errUnknownCandidateTyp, typ)
|
||||||
}
|
}
|
||||||
|
@@ -35,8 +35,9 @@ func NewCandidatePeerReflexive(config *CandidatePeerReflexiveConfig) (*Candidate
|
|||||||
}
|
}
|
||||||
|
|
||||||
candidateID := config.CandidateID
|
candidateID := config.CandidateID
|
||||||
|
candidateIDGenerator := newCandidateIDGenerator()
|
||||||
if candidateID == "" {
|
if candidateID == "" {
|
||||||
candidateID = globalCandidateIDGenerator.Generate()
|
candidateID = candidateIDGenerator.Generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CandidatePeerReflexive{
|
return &CandidatePeerReflexive{
|
||||||
|
@@ -42,7 +42,7 @@ func TestRelayOnlyConnection(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
cfg := &AgentConfig{
|
cfg := &AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
Urls: []*URL{
|
Urls: []*URL{
|
||||||
{
|
{
|
||||||
Scheme: SchemeTypeTURN,
|
Scheme: SchemeTypeTURN,
|
||||||
|
@@ -212,7 +212,8 @@ func TestCandidateMarshal(t *testing.T) {
|
|||||||
marshaled string
|
marshaled string
|
||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
{&CandidateHost{
|
{
|
||||||
|
&CandidateHost{
|
||||||
candidateBase{
|
candidateBase{
|
||||||
networkType: NetworkTypeUDP6,
|
networkType: NetworkTypeUDP6,
|
||||||
candidateType: CandidateTypeHost,
|
candidateType: CandidateTypeHost,
|
||||||
@@ -226,7 +227,8 @@ func TestCandidateMarshal(t *testing.T) {
|
|||||||
"750 1 udp 500 fcd9:e3b8:12ce:9fc5:74a5:c6bb:d8b:e08a 53987 typ host",
|
"750 1 udp 500 fcd9:e3b8:12ce:9fc5:74a5:c6bb:d8b:e08a 53987 typ host",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{&CandidateHost{
|
{
|
||||||
|
&CandidateHost{
|
||||||
candidateBase{
|
candidateBase{
|
||||||
networkType: NetworkTypeUDP4,
|
networkType: NetworkTypeUDP4,
|
||||||
candidateType: CandidateTypeHost,
|
candidateType: CandidateTypeHost,
|
||||||
@@ -238,7 +240,8 @@ func TestCandidateMarshal(t *testing.T) {
|
|||||||
"4273957277 1 udp 2130706431 10.0.75.1 53634 typ host",
|
"4273957277 1 udp 2130706431 10.0.75.1 53634 typ host",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{&CandidateServerReflexive{
|
{
|
||||||
|
&CandidateServerReflexive{
|
||||||
candidateBase{
|
candidateBase{
|
||||||
networkType: NetworkTypeUDP4,
|
networkType: NetworkTypeUDP4,
|
||||||
candidateType: CandidateTypeServerReflexive,
|
candidateType: CandidateTypeServerReflexive,
|
||||||
@@ -250,7 +253,8 @@ func TestCandidateMarshal(t *testing.T) {
|
|||||||
"647372371 1 udp 1694498815 191.228.238.68 53991 typ srflx raddr 192.168.0.274 rport 53991",
|
"647372371 1 udp 1694498815 191.228.238.68 53991 typ srflx raddr 192.168.0.274 rport 53991",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{&CandidateRelay{
|
{
|
||||||
|
&CandidateRelay{
|
||||||
candidateBase{
|
candidateBase{
|
||||||
networkType: NetworkTypeUDP4,
|
networkType: NetworkTypeUDP4,
|
||||||
candidateType: CandidateTypeRelay,
|
candidateType: CandidateTypeRelay,
|
||||||
@@ -263,7 +267,8 @@ func TestCandidateMarshal(t *testing.T) {
|
|||||||
"848194626 1 udp 16777215 50.0.0.1 5000 typ relay raddr 192.168.0.1 rport 5001",
|
"848194626 1 udp 16777215 50.0.0.1 5000 typ relay raddr 192.168.0.1 rport 5001",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{&CandidateHost{
|
{
|
||||||
|
&CandidateHost{
|
||||||
candidateBase{
|
candidateBase{
|
||||||
networkType: NetworkTypeTCP4,
|
networkType: NetworkTypeTCP4,
|
||||||
candidateType: CandidateTypeHost,
|
candidateType: CandidateTypeHost,
|
||||||
@@ -276,7 +281,8 @@ func TestCandidateMarshal(t *testing.T) {
|
|||||||
"1052353102 1 tcp 2128609279 192.168.0.196 0 typ host tcptype active",
|
"1052353102 1 tcp 2128609279 192.168.0.196 0 typ host tcptype active",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{&CandidateHost{
|
{
|
||||||
|
&CandidateHost{
|
||||||
candidateBase{
|
candidateBase{
|
||||||
networkType: NetworkTypeUDP4,
|
networkType: NetworkTypeUDP4,
|
||||||
candidateType: CandidateTypeHost,
|
candidateType: CandidateTypeHost,
|
||||||
@@ -285,7 +291,8 @@ func TestCandidateMarshal(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
"1380287402 1 udp 2130706431 e2494022-4d9a-4c1e-a750-cc48d4f8d6ee.local 60542 typ host", false},
|
"1380287402 1 udp 2130706431 e2494022-4d9a-4c1e-a750-cc48d4f8d6ee.local 60542 typ host", false,
|
||||||
|
},
|
||||||
|
|
||||||
// Invalid candidates
|
// Invalid candidates
|
||||||
{nil, "", true},
|
{nil, "", true},
|
||||||
|
@@ -2,32 +2,41 @@ package ice
|
|||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
var (
|
func hostCandidate() *CandidateHost {
|
||||||
hostCandidate = &CandidateHost{
|
return &CandidateHost{
|
||||||
candidateBase: candidateBase{
|
candidateBase: candidateBase{
|
||||||
candidateType: CandidateTypeHost,
|
candidateType: CandidateTypeHost,
|
||||||
component: ComponentRTP,
|
component: ComponentRTP,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
prflxCandidate = &CandidatePeerReflexive{
|
}
|
||||||
|
|
||||||
|
func prflxCandidate() *CandidatePeerReflexive {
|
||||||
|
return &CandidatePeerReflexive{
|
||||||
candidateBase: candidateBase{
|
candidateBase: candidateBase{
|
||||||
candidateType: CandidateTypePeerReflexive,
|
candidateType: CandidateTypePeerReflexive,
|
||||||
component: ComponentRTP,
|
component: ComponentRTP,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
srflxCandidate = &CandidateServerReflexive{
|
}
|
||||||
|
|
||||||
|
func srflxCandidate() *CandidateServerReflexive {
|
||||||
|
return &CandidateServerReflexive{
|
||||||
candidateBase: candidateBase{
|
candidateBase: candidateBase{
|
||||||
candidateType: CandidateTypeServerReflexive,
|
candidateType: CandidateTypeServerReflexive,
|
||||||
component: ComponentRTP,
|
component: ComponentRTP,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
relayCandidate = &CandidateRelay{
|
}
|
||||||
|
|
||||||
|
func relayCandidate() *CandidateRelay {
|
||||||
|
return &CandidateRelay{
|
||||||
candidateBase: candidateBase{
|
candidateBase: candidateBase{
|
||||||
candidateType: CandidateTypeRelay,
|
candidateType: CandidateTypeRelay,
|
||||||
component: ComponentRTP,
|
component: ComponentRTP,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
func TestCandidatePairPriority(t *testing.T) {
|
func TestCandidatePairPriority(t *testing.T) {
|
||||||
for _, test := range []struct {
|
for _, test := range []struct {
|
||||||
@@ -36,64 +45,64 @@ func TestCandidatePairPriority(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Pair: newCandidatePair(
|
Pair: newCandidatePair(
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
WantPriority: 9151314440652587007,
|
WantPriority: 9151314440652587007,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pair: newCandidatePair(
|
Pair: newCandidatePair(
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
WantPriority: 9151314440652587007,
|
WantPriority: 9151314440652587007,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pair: newCandidatePair(
|
Pair: newCandidatePair(
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
prflxCandidate,
|
prflxCandidate(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
WantPriority: 7998392936314175488,
|
WantPriority: 7998392936314175488,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pair: newCandidatePair(
|
Pair: newCandidatePair(
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
prflxCandidate,
|
prflxCandidate(),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
WantPriority: 7998392936314175487,
|
WantPriority: 7998392936314175487,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pair: newCandidatePair(
|
Pair: newCandidatePair(
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
srflxCandidate,
|
srflxCandidate(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
WantPriority: 7277816996102668288,
|
WantPriority: 7277816996102668288,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pair: newCandidatePair(
|
Pair: newCandidatePair(
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
srflxCandidate,
|
srflxCandidate(),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
WantPriority: 7277816996102668287,
|
WantPriority: 7277816996102668287,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pair: newCandidatePair(
|
Pair: newCandidatePair(
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
relayCandidate,
|
relayCandidate(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
WantPriority: 72057593987596288,
|
WantPriority: 72057593987596288,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pair: newCandidatePair(
|
Pair: newCandidatePair(
|
||||||
hostCandidate,
|
hostCandidate(),
|
||||||
relayCandidate,
|
relayCandidate(),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
WantPriority: 72057593987596287,
|
WantPriority: 72057593987596287,
|
||||||
@@ -106,8 +115,8 @@ func TestCandidatePairPriority(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCandidatePairEquality(t *testing.T) {
|
func TestCandidatePairEquality(t *testing.T) {
|
||||||
pairA := newCandidatePair(hostCandidate, srflxCandidate, true)
|
pairA := newCandidatePair(hostCandidate(), srflxCandidate(), true)
|
||||||
pairB := newCandidatePair(hostCandidate, srflxCandidate, false)
|
pairB := newCandidatePair(hostCandidate(), srflxCandidate(), false)
|
||||||
|
|
||||||
if !pairA.Equal(pairB) {
|
if !pairA.Equal(pairB) {
|
||||||
t.Fatalf("Expected %v to equal %v", pairA, pairB)
|
t.Fatalf("Expected %v to equal %v", pairA, pairB)
|
||||||
|
@@ -23,6 +23,8 @@ func (c CandidateType) String() string {
|
|||||||
return "prflx"
|
return "prflx"
|
||||||
case CandidateTypeRelay:
|
case CandidateTypeRelay:
|
||||||
return "relay"
|
return "relay"
|
||||||
|
case CandidateTypeUnspecified:
|
||||||
|
return "Unknown candidate type"
|
||||||
}
|
}
|
||||||
return "Unknown candidate type"
|
return "Unknown candidate type"
|
||||||
}
|
}
|
||||||
@@ -41,6 +43,8 @@ func (c CandidateType) Preference() uint16 {
|
|||||||
return 110
|
return 110
|
||||||
case CandidateTypeServerReflexive:
|
case CandidateTypeServerReflexive:
|
||||||
return 100
|
return 100
|
||||||
|
case CandidateTypeRelay, CandidateTypeUnspecified:
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@@ -228,7 +228,7 @@ func pipeWithVNet(v *virtualNet, a0TestConfig, a1TestConfig *agentTestConfig) (*
|
|||||||
|
|
||||||
cfg0 := &AgentConfig{
|
cfg0 := &AgentConfig{
|
||||||
Urls: a0TestConfig.urls,
|
Urls: a0TestConfig.urls,
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
NAT1To1IPs: nat1To1IPs,
|
NAT1To1IPs: nat1To1IPs,
|
||||||
NAT1To1IPCandidateType: a0TestConfig.nat1To1IPCandidateType,
|
NAT1To1IPCandidateType: a0TestConfig.nat1To1IPCandidateType,
|
||||||
@@ -251,7 +251,7 @@ func pipeWithVNet(v *virtualNet, a0TestConfig, a1TestConfig *agentTestConfig) (*
|
|||||||
}
|
}
|
||||||
cfg1 := &AgentConfig{
|
cfg1 := &AgentConfig{
|
||||||
Urls: a1TestConfig.urls,
|
Urls: a1TestConfig.urls,
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
NAT1To1IPs: nat1To1IPs,
|
NAT1To1IPs: nat1To1IPs,
|
||||||
NAT1To1IPCandidateType: a1TestConfig.nat1To1IPCandidateType,
|
NAT1To1IPCandidateType: a1TestConfig.nat1To1IPCandidateType,
|
||||||
@@ -491,7 +491,7 @@ func TestDisconnectedToConnected(t *testing.T) {
|
|||||||
|
|
||||||
// Create two agents and connect them
|
// Create two agents and connect them
|
||||||
controllingAgent, err := NewAgent(&AgentConfig{
|
controllingAgent, err := NewAgent(&AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
Net: net0,
|
Net: net0,
|
||||||
DisconnectedTimeout: &disconnectTimeout,
|
DisconnectedTimeout: &disconnectTimeout,
|
||||||
@@ -501,7 +501,7 @@ func TestDisconnectedToConnected(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
controlledAgent, err := NewAgent(&AgentConfig{
|
controlledAgent, err := NewAgent(&AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
Net: net1,
|
Net: net1,
|
||||||
DisconnectedTimeout: &disconnectTimeout,
|
DisconnectedTimeout: &disconnectTimeout,
|
||||||
@@ -594,14 +594,14 @@ func TestWriteUseValidPair(t *testing.T) {
|
|||||||
|
|
||||||
// Create two agents and connect them
|
// Create two agents and connect them
|
||||||
controllingAgent, err := NewAgent(&AgentConfig{
|
controllingAgent, err := NewAgent(&AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
Net: net0,
|
Net: net0,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
controlledAgent, err := NewAgent(&AgentConfig{
|
controlledAgent, err := NewAgent(&AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
Net: net1,
|
Net: net1,
|
||||||
})
|
})
|
||||||
|
21
errors.go
21
errors.go
@@ -108,4 +108,25 @@ var (
|
|||||||
|
|
||||||
// ErrTCPRemoteAddrAlreadyExists indicates we already have the connection with same remote addr.
|
// ErrTCPRemoteAddrAlreadyExists indicates we already have the connection with same remote addr.
|
||||||
ErrTCPRemoteAddrAlreadyExists = errors.New("conn with same remote addr already exists")
|
ErrTCPRemoteAddrAlreadyExists = errors.New("conn with same remote addr already exists")
|
||||||
|
|
||||||
|
errSendPacket = errors.New("failed to send packet")
|
||||||
|
errAttributeTooShortICECandidate = errors.New("attribute not long enough to be ICE candidate")
|
||||||
|
errParseComponent = errors.New("could not parse component")
|
||||||
|
errParsePriority = errors.New("could not parse priority")
|
||||||
|
errParsePort = errors.New("could not parse port")
|
||||||
|
errParseRelatedAddr = errors.New("could not parse related addresses")
|
||||||
|
errParseTypType = errors.New("could not parse typtype")
|
||||||
|
errUnknownCandidateTyp = errors.New("unknown candidate typ")
|
||||||
|
errGetXorMappedAddrResponse = errors.New("failed to get XOR-MAPPED-ADDRESS response")
|
||||||
|
errConnectionAddrAlreadyExist = errors.New("connection with same remote address already exists")
|
||||||
|
errReadingStreamingPacket = errors.New("error reading streaming packet")
|
||||||
|
errWriting = errors.New("error writing to")
|
||||||
|
errClosingConnection = errors.New("error closing connection")
|
||||||
|
errDetermineNetworkType = errors.New("unable to determine networkType")
|
||||||
|
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")
|
||||||
|
errMismatchUsername = errors.New("username mismatch")
|
||||||
|
errICEWriteSTUNMessage = errors.New("the ICE conn can't write STUN messages")
|
||||||
)
|
)
|
||||||
|
@@ -65,7 +65,7 @@ type externalIPMapper struct {
|
|||||||
candidateType CandidateType
|
candidateType CandidateType
|
||||||
}
|
}
|
||||||
|
|
||||||
func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIPMapper, error) {
|
func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIPMapper, error) { //nolint:gocognit
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
14
gather.go
14
gather.go
@@ -3,6 +3,7 @@ package ice
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -112,6 +113,7 @@ func (a *Agent) gatherCandidates(ctx context.Context) {
|
|||||||
a.gatherCandidatesRelay(ctx, a.urls)
|
a.gatherCandidatesRelay(ctx, a.urls)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
case CandidateTypePeerReflexive, CandidateTypeUnspecified:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Block until all STUN and TURN URLs have been gathered (or timed out)
|
// Block until all STUN and TURN URLs have been gathered (or timed out)
|
||||||
@@ -122,7 +124,7 @@ func (a *Agent) gatherCandidates(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []NetworkType) {
|
func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []NetworkType) { //nolint:gocognit
|
||||||
networks := map[string]struct{}{}
|
networks := map[string]struct{}{}
|
||||||
for _, networkType := range networkTypes {
|
for _, networkType := range networkTypes {
|
||||||
if networkType.IsTCP() {
|
if networkType.IsTCP() {
|
||||||
@@ -162,20 +164,18 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ
|
|||||||
switch network {
|
switch network {
|
||||||
case tcp:
|
case tcp:
|
||||||
// Handle ICE TCP passive mode
|
// Handle ICE TCP passive mode
|
||||||
// TODO active mode
|
|
||||||
// TODO S-O mode
|
|
||||||
|
|
||||||
a.log.Debugf("GetConn by ufrag: %s\n", a.localUfrag)
|
a.log.Debugf("GetConn by ufrag: %s\n", a.localUfrag)
|
||||||
conn, err = a.tcpMux.GetConnByUfrag(a.localUfrag)
|
conn, err = a.tcpMux.GetConnByUfrag(a.localUfrag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != ErrTCPMuxNotInitialized {
|
if !errors.Is(err, ErrTCPMuxNotInitialized) {
|
||||||
a.log.Warnf("error getting tcp conn by ufrag: %s %s %s\n", network, ip, a.localUfrag)
|
a.log.Warnf("error getting tcp conn by ufrag: %s %s %s\n", network, ip, a.localUfrag)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
port = conn.LocalAddr().(*net.TCPAddr).Port
|
port = conn.LocalAddr().(*net.TCPAddr).Port
|
||||||
tcpType = TCPTypePassive
|
tcpType = TCPTypePassive
|
||||||
// TODO is there a way to verify that the listen address is even
|
// is there a way to verify that the listen address is even
|
||||||
// accessible from the current interface.
|
// accessible from the current interface.
|
||||||
case udp:
|
case udp:
|
||||||
conn, err = listenUDPInPortRange(a.net, a.log, int(a.portmax), int(a.portmin), network, &net.UDPAddr{IP: ip, Port: 0})
|
conn, err = listenUDPInPortRange(a.net, a.log, int(a.portmax), int(a.portmin), network, &net.UDPAddr{IP: ip, Port: 0})
|
||||||
@@ -332,11 +332,11 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) {
|
func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //nolint:gocognit
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
defer wg.Wait()
|
defer wg.Wait()
|
||||||
|
|
||||||
network := NetworkTypeUDP4.String() // TODO IPv6
|
network := NetworkTypeUDP4.String()
|
||||||
for i := range urls {
|
for i := range urls {
|
||||||
switch {
|
switch {
|
||||||
case urls[i].Scheme != SchemeTypeTURN && urls[i].Scheme != SchemeTypeTURNS:
|
case urls[i].Scheme != SchemeTypeTURN && urls[i].Scheme != SchemeTypeTURNS:
|
||||||
|
@@ -127,7 +127,7 @@ func TestSTUNConcurrency(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
a, err := NewAgent(&AgentConfig{
|
a, err := NewAgent(&AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
Urls: urls,
|
Urls: urls,
|
||||||
CandidateTypes: []CandidateType{CandidateTypeHost, CandidateTypeServerReflexive},
|
CandidateTypes: []CandidateType{CandidateTypeHost, CandidateTypeServerReflexive},
|
||||||
TCPMux: NewTCPMuxDefault(
|
TCPMux: NewTCPMuxDefault(
|
||||||
@@ -212,7 +212,7 @@ func TestTURNConcurrency(t *testing.T) {
|
|||||||
a, err := NewAgent(&AgentConfig{
|
a, err := NewAgent(&AgentConfig{
|
||||||
CandidateTypes: []CandidateType{CandidateTypeRelay},
|
CandidateTypes: []CandidateType{CandidateTypeRelay},
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
Urls: urls,
|
Urls: urls,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -252,7 +252,7 @@ func TestTURNConcurrency(t *testing.T) {
|
|||||||
assert.NoError(t, genErr)
|
assert.NoError(t, genErr)
|
||||||
|
|
||||||
serverPort := randomPort(t)
|
serverPort := randomPort(t)
|
||||||
serverListener, err := tls.Listen("tcp", "127.0.0.1:"+strconv.Itoa(serverPort), &tls.Config{
|
serverListener, err := tls.Listen("tcp", "127.0.0.1:"+strconv.Itoa(serverPort), &tls.Config{ //nolint:gosec
|
||||||
Certificates: []tls.Certificate{certificate},
|
Certificates: []tls.Certificate{certificate},
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -316,7 +316,7 @@ func TestSTUNTURNConcurrency(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
a, err := NewAgent(&AgentConfig{
|
a, err := NewAgent(&AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
Urls: urls,
|
Urls: urls,
|
||||||
CandidateTypes: []CandidateType{CandidateTypeServerReflexive, CandidateTypeRelay},
|
CandidateTypes: []CandidateType{CandidateTypeServerReflexive, CandidateTypeRelay},
|
||||||
})
|
})
|
||||||
@@ -380,7 +380,7 @@ func TestTURNSrflx(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
a, err := NewAgent(&AgentConfig{
|
a, err := NewAgent(&AgentConfig{
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
Urls: urls,
|
Urls: urls,
|
||||||
CandidateTypes: []CandidateType{CandidateTypeServerReflexive, CandidateTypeRelay},
|
CandidateTypes: []CandidateType{CandidateTypeServerReflexive, CandidateTypeRelay},
|
||||||
})
|
})
|
||||||
|
@@ -4,6 +4,7 @@ package ice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -131,7 +132,7 @@ func TestVNetGather(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err = listenUDPInPortRange(a.net, a.log, 4999, 5000, udp, &net.UDPAddr{IP: ip, Port: 0})
|
_, err = listenUDPInPortRange(a.net, a.log, 4999, 5000, udp, &net.UDPAddr{IP: ip, Port: 0})
|
||||||
if err != ErrPort {
|
if !errors.Is(err, ErrPort) {
|
||||||
t.Fatal("listenUDP with invalid port range did not return ErrPort")
|
t.Fatal("listenUDP with invalid port range did not return ErrPort")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,7 +444,7 @@ func TestVNetGather_TURNConnectionLeak(t *testing.T) {
|
|||||||
Urls: []*URL{
|
Urls: []*URL{
|
||||||
turnServerURL,
|
turnServerURL,
|
||||||
},
|
},
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
MulticastDNSMode: MulticastDNSModeDisabled,
|
MulticastDNSMode: MulticastDNSModeDisabled,
|
||||||
NAT1To1IPs: []string{vnetGlobalIPA},
|
NAT1To1IPs: []string{vnetGlobalIPA},
|
||||||
Net: v.net0,
|
Net: v.net0,
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
package ice
|
package ice
|
||||||
|
|
||||||
import "github.com/pion/stun"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/pion/stun"
|
||||||
|
)
|
||||||
|
|
||||||
// tiebreaker is common helper for ICE-{CONTROLLED,CONTROLLING}
|
// tiebreaker is common helper for ICE-{CONTROLLED,CONTROLLING}
|
||||||
// and represents the so-called tiebreaker number.
|
// and represents the so-called tiebreaker number.
|
||||||
@@ -11,7 +15,7 @@ const tiebreakerSize = 8 // 64 bit
|
|||||||
// AddToAs adds tiebreaker value to m as t attribute.
|
// AddToAs adds tiebreaker value to m as t attribute.
|
||||||
func (a tiebreaker) AddToAs(m *stun.Message, t stun.AttrType) error {
|
func (a tiebreaker) AddToAs(m *stun.Message, t stun.AttrType) error {
|
||||||
v := make([]byte, tiebreakerSize)
|
v := make([]byte, tiebreakerSize)
|
||||||
bin.PutUint64(v, uint64(a))
|
binary.BigEndian.PutUint64(v, uint64(a))
|
||||||
m.Add(t, v)
|
m.Add(t, v)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -25,7 +29,7 @@ func (a *tiebreaker) GetFromAs(m *stun.Message, t stun.AttrType) error {
|
|||||||
if err = stun.CheckSize(t, len(v), tiebreakerSize); err != nil {
|
if err = stun.CheckSize(t, len(v), tiebreakerSize); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*a = tiebreaker(bin.Uint64(v))
|
*a = tiebreaker(binary.BigEndian.Uint64(v))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
package ice
|
package ice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pion/stun"
|
"github.com/pion/stun"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestControlled_GetFrom(t *testing.T) {
|
func TestControlled_GetFrom(t *testing.T) { //nolint:dupl
|
||||||
m := new(stun.Message)
|
m := new(stun.Message)
|
||||||
var c AttrControlled
|
var c AttrControlled
|
||||||
if err := c.GetFrom(m); err != stun.ErrAttributeNotFound {
|
if err := c.GetFrom(m); !errors.Is(err, stun.ErrAttributeNotFound) {
|
||||||
t.Error("unexpected error")
|
t.Error("unexpected error")
|
||||||
}
|
}
|
||||||
if err := m.Build(stun.BindingRequest, &c); err != nil {
|
if err := m.Build(stun.BindingRequest, &c); err != nil {
|
||||||
@@ -36,10 +37,10 @@ func TestControlled_GetFrom(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestControlling_GetFrom(t *testing.T) {
|
func TestControlling_GetFrom(t *testing.T) { //nolint:dupl
|
||||||
m := new(stun.Message)
|
m := new(stun.Message)
|
||||||
var c AttrControlling
|
var c AttrControlling
|
||||||
if err := c.GetFrom(m); err != stun.ErrAttributeNotFound {
|
if err := c.GetFrom(m); !errors.Is(err, stun.ErrAttributeNotFound) {
|
||||||
t.Error("unexpected error")
|
t.Error("unexpected error")
|
||||||
}
|
}
|
||||||
if err := m.Build(stun.BindingRequest, &c); err != nil {
|
if err := m.Build(stun.BindingRequest, &c); err != nil {
|
||||||
@@ -70,14 +71,14 @@ func TestControl_GetFrom(t *testing.T) {
|
|||||||
t.Run("Blank", func(t *testing.T) {
|
t.Run("Blank", func(t *testing.T) {
|
||||||
m := new(stun.Message)
|
m := new(stun.Message)
|
||||||
var c AttrControl
|
var c AttrControl
|
||||||
if err := c.GetFrom(m); err != stun.ErrAttributeNotFound {
|
if err := c.GetFrom(m); !errors.Is(err, stun.ErrAttributeNotFound) {
|
||||||
t.Error("unexpected error")
|
t.Error("unexpected error")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Controlling", func(t *testing.T) {
|
t.Run("Controlling", func(t *testing.T) { //nolint:dupl
|
||||||
m := new(stun.Message)
|
m := new(stun.Message)
|
||||||
var c AttrControl
|
var c AttrControl
|
||||||
if err := c.GetFrom(m); err != stun.ErrAttributeNotFound {
|
if err := c.GetFrom(m); !errors.Is(err, stun.ErrAttributeNotFound) {
|
||||||
t.Error("unexpected error")
|
t.Error("unexpected error")
|
||||||
}
|
}
|
||||||
c.Role = Controlling
|
c.Role = Controlling
|
||||||
@@ -105,10 +106,10 @@ func TestControl_GetFrom(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
t.Run("Controlled", func(t *testing.T) {
|
t.Run("Controlled", func(t *testing.T) { //nolint:dupl
|
||||||
m := new(stun.Message)
|
m := new(stun.Message)
|
||||||
var c AttrControl
|
var c AttrControl
|
||||||
if err := c.GetFrom(m); err != stun.ErrAttributeNotFound {
|
if err := c.GetFrom(m); !errors.Is(err, stun.ErrAttributeNotFound) {
|
||||||
t.Error("unexpected error")
|
t.Error("unexpected error")
|
||||||
}
|
}
|
||||||
c.Role = Controlled
|
c.Role = Controlled
|
||||||
|
@@ -11,12 +11,14 @@ const (
|
|||||||
tcp = "tcp"
|
tcp = "tcp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var supportedNetworkTypes = []NetworkType{
|
func supportedNetworkTypes() []NetworkType {
|
||||||
|
return []NetworkType{
|
||||||
NetworkTypeUDP4,
|
NetworkTypeUDP4,
|
||||||
NetworkTypeUDP6,
|
NetworkTypeUDP6,
|
||||||
NetworkTypeTCP4,
|
NetworkTypeTCP4,
|
||||||
NetworkTypeTCP6,
|
NetworkTypeTCP6,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkType represents the type of network
|
// NetworkType represents the type of network
|
||||||
type NetworkType int
|
type NetworkType int
|
||||||
@@ -124,5 +126,5 @@ func determineNetworkType(network string, ip net.IP) (NetworkType, error) {
|
|||||||
return NetworkTypeTCP6, nil
|
return NetworkTypeTCP6, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return NetworkType(0), fmt.Errorf("unable to determine networkType from %s %s", network, ip)
|
return NetworkType(0), fmt.Errorf("%w from %s %s", errDetermineNetworkType, network, ip)
|
||||||
}
|
}
|
||||||
|
10
priority.go
10
priority.go
@@ -1,6 +1,10 @@
|
|||||||
package ice
|
package ice
|
||||||
|
|
||||||
import "github.com/pion/stun"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/pion/stun"
|
||||||
|
)
|
||||||
|
|
||||||
// PriorityAttr represents PRIORITY attribute.
|
// PriorityAttr represents PRIORITY attribute.
|
||||||
type PriorityAttr uint32
|
type PriorityAttr uint32
|
||||||
@@ -10,7 +14,7 @@ const prioritySize = 4 // 32 bit
|
|||||||
// AddTo adds PRIORITY attribute to message.
|
// AddTo adds PRIORITY attribute to message.
|
||||||
func (p PriorityAttr) AddTo(m *stun.Message) error {
|
func (p PriorityAttr) AddTo(m *stun.Message) error {
|
||||||
v := make([]byte, prioritySize)
|
v := make([]byte, prioritySize)
|
||||||
bin.PutUint32(v, uint32(p))
|
binary.BigEndian.PutUint32(v, uint32(p))
|
||||||
m.Add(stun.AttrPriority, v)
|
m.Add(stun.AttrPriority, v)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -24,6 +28,6 @@ func (p *PriorityAttr) GetFrom(m *stun.Message) error {
|
|||||||
if err = stun.CheckSize(stun.AttrPriority, len(v), prioritySize); err != nil {
|
if err = stun.CheckSize(stun.AttrPriority, len(v), prioritySize); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*p = PriorityAttr(bin.Uint32(v))
|
*p = PriorityAttr(binary.BigEndian.Uint32(v))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
package ice
|
package ice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pion/stun"
|
"github.com/pion/stun"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPriority_GetFrom(t *testing.T) {
|
func TestPriority_GetFrom(t *testing.T) { //nolint:dupl
|
||||||
m := new(stun.Message)
|
m := new(stun.Message)
|
||||||
var p PriorityAttr
|
var p PriorityAttr
|
||||||
if err := p.GetFrom(m); err != stun.ErrAttributeNotFound {
|
if err := p.GetFrom(m); !errors.Is(err, stun.ErrAttributeNotFound) {
|
||||||
t.Error("unexpected error")
|
t.Error("unexpected error")
|
||||||
}
|
}
|
||||||
if err := m.Build(stun.BindingRequest, &p); err != nil {
|
if err := m.Build(stun.BindingRequest, &p); err != nil {
|
||||||
|
6
rand.go
6
rand.go
@@ -14,8 +14,10 @@ const (
|
|||||||
// Seeding random generator each time limits number of generated sequence to 31-bits,
|
// Seeding random generator each time limits number of generated sequence to 31-bits,
|
||||||
// and causes collision on low time accuracy environments.
|
// and causes collision on low time accuracy environments.
|
||||||
// Use global random generator seeded by crypto grade random.
|
// Use global random generator seeded by crypto grade random.
|
||||||
var globalMathRandomGenerator = randutil.NewMathRandomGenerator()
|
var (
|
||||||
var globalCandidateIDGenerator = candidateIDGenerator{globalMathRandomGenerator}
|
globalMathRandomGenerator = randutil.NewMathRandomGenerator() //nolint:gochecknoglobals
|
||||||
|
globalCandidateIDGenerator = candidateIDGenerator{globalMathRandomGenerator} //nolint:gochecknoglobals
|
||||||
|
)
|
||||||
|
|
||||||
// candidateIDGenerator is a random candidate ID generator.
|
// candidateIDGenerator is a random candidate ID generator.
|
||||||
// Candidate ID is used in SDP and always shared to the other peer.
|
// Candidate ID is used in SDP and always shared to the other peer.
|
||||||
|
6
role.go
6
role.go
@@ -1,6 +1,8 @@
|
|||||||
package ice
|
package ice
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
// Role represents ICE agent role, which can be controlling or controlled.
|
// Role represents ICE agent role, which can be controlling or controlled.
|
||||||
type Role byte
|
type Role byte
|
||||||
@@ -19,7 +21,7 @@ func (r *Role) UnmarshalText(text []byte) error {
|
|||||||
case "controlled":
|
case "controlled":
|
||||||
*r = Controlled
|
*r = Controlled
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown role %q", text)
|
return fmt.Errorf("%w %q", errUnknownRole, text)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -73,13 +73,12 @@ func (s *controllingSelector) nominatePair(pair *candidatePair) {
|
|||||||
// request.
|
// request.
|
||||||
msg, err := stun.Build(stun.BindingRequest, stun.TransactionID,
|
msg, err := stun.Build(stun.BindingRequest, stun.TransactionID,
|
||||||
stun.NewUsername(s.agent.remoteUfrag+":"+s.agent.localUfrag),
|
stun.NewUsername(s.agent.remoteUfrag+":"+s.agent.localUfrag),
|
||||||
UseCandidate,
|
UseCandidate(),
|
||||||
AttrControlling(s.agent.tieBreaker),
|
AttrControlling(s.agent.tieBreaker),
|
||||||
PriorityAttr(pair.local.Priority()),
|
PriorityAttr(pair.local.Priority()),
|
||||||
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
||||||
stun.Fingerprint,
|
stun.Fingerprint,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Error(err.Error())
|
s.log.Error(err.Error())
|
||||||
return
|
return
|
||||||
@@ -152,7 +151,6 @@ func (s *controllingSelector) PingCandidate(local, remote Candidate) {
|
|||||||
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
||||||
stun.Fingerprint,
|
stun.Fingerprint,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Error(err.Error())
|
s.log.Error(err.Error())
|
||||||
return
|
return
|
||||||
@@ -188,7 +186,6 @@ func (s *controlledSelector) PingCandidate(local, remote Candidate) {
|
|||||||
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
||||||
stun.Fingerprint,
|
stun.Fingerprint,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Error(err.Error())
|
s.log.Error(err.Error())
|
||||||
return
|
return
|
||||||
@@ -198,6 +195,7 @@ func (s *controlledSelector) PingCandidate(local, remote Candidate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remote Candidate, remoteAddr net.Addr) {
|
func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remote Candidate, remoteAddr net.Addr) {
|
||||||
|
// nolint:godox
|
||||||
// TODO according to the standard we should specifically answer a failed nomination:
|
// TODO according to the standard we should specifically answer a failed nomination:
|
||||||
// https://tools.ietf.org/html/rfc8445#section-7.3.1.5
|
// https://tools.ietf.org/html/rfc8445#section-7.3.1.5
|
||||||
// If the controlled agent does not accept the request from the
|
// If the controlled agent does not accept the request from the
|
||||||
@@ -278,6 +276,7 @@ type liteSelector struct {
|
|||||||
// A lite selector should not contact candidates
|
// A lite selector should not contact candidates
|
||||||
func (s *liteSelector) ContactCandidates() {
|
func (s *liteSelector) ContactCandidates() {
|
||||||
if _, ok := s.pairCandidateSelector.(*controllingSelector); ok {
|
if _, ok := s.pairCandidateSelector.(*controllingSelector); ok {
|
||||||
|
// nolint:godox
|
||||||
// pion/ice#96
|
// pion/ice#96
|
||||||
// TODO: implement lite controlling agent. For now falling back to full agent.
|
// TODO: implement lite controlling agent. For now falling back to full agent.
|
||||||
// This only happens if both peers are lite. See RFC 8445 S6.1.1 and S6.2
|
// This only happens if both peers are lite. See RFC 8445 S6.1.1 and S6.2
|
||||||
|
6
stun.go
6
stun.go
@@ -1,22 +1,18 @@
|
|||||||
package ice
|
package ice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/pion/stun"
|
"github.com/pion/stun"
|
||||||
)
|
)
|
||||||
|
|
||||||
// bin is shorthand for BigEndian.
|
|
||||||
var bin = binary.BigEndian
|
|
||||||
|
|
||||||
func assertInboundUsername(m *stun.Message, expectedUsername string) error {
|
func assertInboundUsername(m *stun.Message, expectedUsername string) error {
|
||||||
var username stun.Username
|
var username stun.Username
|
||||||
if err := username.GetFrom(m); err != nil {
|
if err := username.GetFrom(m); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if string(username) != expectedUsername {
|
if string(username) != expectedUsername {
|
||||||
return fmt.Errorf("username mismatch expected(%x) actual(%x)", expectedUsername, string(username))
|
return fmt.Errorf("%w expected(%x) actual(%x)", errMismatchUsername, expectedUsername, string(username))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@@ -159,7 +159,6 @@ func (m *TCPMuxDefault) handleConn(conn net.Conn) {
|
|||||||
buf := make([]byte, receiveMTU)
|
buf := make([]byte, receiveMTU)
|
||||||
|
|
||||||
n, err := readStreamingPacket(conn, buf)
|
n, err := readStreamingPacket(conn, buf)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.params.Logger.Warnf("Error reading first packet: %s", err)
|
m.params.Logger.Warnf("Error reading first packet: %s", err)
|
||||||
return
|
return
|
||||||
@@ -254,7 +253,7 @@ const streamingPacketHeaderLen = 2
|
|||||||
// | LENGTH | RTP or RTCP packet ... |
|
// | LENGTH | RTP or RTCP packet ... |
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
func readStreamingPacket(conn net.Conn, buf []byte) (int, error) {
|
func readStreamingPacket(conn net.Conn, buf []byte) (int, error) {
|
||||||
var header = make([]byte, streamingPacketHeaderLen)
|
header := make([]byte, streamingPacketHeaderLen)
|
||||||
var bytesRead, n int
|
var bytesRead, n int
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -288,7 +287,6 @@ func writeStreamingPacket(conn net.Conn, buf []byte) (int, error) {
|
|||||||
copy(bufferCopy[2:], buf)
|
copy(bufferCopy[2:], buf)
|
||||||
|
|
||||||
n, err := conn.Write(bufferCopy)
|
n, err := conn.Write(bufferCopy)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@@ -12,8 +12,10 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ TCPMux = &TCPMuxDefault{}
|
var (
|
||||||
var _ TCPMux = &invalidTCPMux{}
|
_ TCPMux = &TCPMuxDefault{}
|
||||||
|
_ TCPMux = &invalidTCPMux{}
|
||||||
|
)
|
||||||
|
|
||||||
func TestTCPMux_Recv(t *testing.T) {
|
func TestTCPMux_Recv(t *testing.T) {
|
||||||
report := test.CheckRoutines(t)
|
report := test.CheckRoutines(t)
|
||||||
|
@@ -62,7 +62,7 @@ func (t *tcpPacketConn) AddConn(conn net.Conn, firstPacketData []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := t.conns[conn.RemoteAddr().String()]; ok {
|
if _, ok := t.conns[conn.RemoteAddr().String()]; ok {
|
||||||
return fmt.Errorf("connection with same remote address already exists: %s", conn.RemoteAddr().String())
|
return fmt.Errorf("%w: %s", errConnectionAddrAlreadyExist, conn.RemoteAddr().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
t.conns[conn.RemoteAddr().String()] = conn
|
t.conns[conn.RemoteAddr().String()] = conn
|
||||||
@@ -85,9 +85,8 @@ func (t *tcpPacketConn) startReading(conn net.Conn) {
|
|||||||
for {
|
for {
|
||||||
n, err := readStreamingPacket(conn, buf)
|
n, err := readStreamingPacket(conn, buf)
|
||||||
// t.params.Logger.Infof("readStreamingPacket read %d bytes", n)
|
// t.params.Logger.Infof("readStreamingPacket read %d bytes", n)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.params.Logger.Infof("Error reading streaming packet: %s\n", err)
|
t.params.Logger.Infof("%w: %s\n", errReadingStreamingPacket, err)
|
||||||
t.handleRecv(streamingPacket{nil, conn.RemoteAddr(), err})
|
t.handleRecv(streamingPacket{nil, conn.RemoteAddr(), err})
|
||||||
t.removeConn(conn)
|
t.removeConn(conn)
|
||||||
return
|
return
|
||||||
@@ -168,7 +167,7 @@ func (t *tcpPacketConn) WriteTo(buf []byte, raddr net.Addr) (n int, err error) {
|
|||||||
|
|
||||||
n, err = writeStreamingPacket(conn, buf)
|
n, err = writeStreamingPacket(conn, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.params.Logger.Tracef("Error writing to %s\n", raddr)
|
t.params.Logger.Tracef("%w %s\n", errWriting, raddr)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +177,7 @@ func (t *tcpPacketConn) WriteTo(buf []byte, raddr net.Addr) (n int, err error) {
|
|||||||
func (t *tcpPacketConn) closeAndLogError(closer io.Closer) {
|
func (t *tcpPacketConn) closeAndLogError(closer io.Closer) {
|
||||||
err := closer.Close()
|
err := closer.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.params.Logger.Warnf("Error closing connection: %s", err)
|
t.params.Logger.Warnf("%w: %s", errClosingConnection, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@ package ice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net"
|
"net"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -55,7 +54,6 @@ func (a *Agent) connect(ctx context.Context, isControlling bool, remoteUfrag, re
|
|||||||
case <-a.done:
|
case <-a.done:
|
||||||
return nil, a.getErr()
|
return nil, a.getErr()
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
// TODO: Stop connectivity checks?
|
|
||||||
return nil, ErrCanceledByCaller
|
return nil, ErrCanceledByCaller
|
||||||
case <-a.onConnected:
|
case <-a.onConnected:
|
||||||
}
|
}
|
||||||
@@ -85,7 +83,7 @@ func (c *Conn) Write(p []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if stun.IsMessage(p) {
|
if stun.IsMessage(p) {
|
||||||
return 0, errors.New("the ICE conn can't write STUN messages")
|
return 0, errICEWriteSTUNMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
pair := c.agent.getSelectedPair()
|
pair := c.agent.getSelectedPair()
|
||||||
@@ -111,8 +109,6 @@ func (c *Conn) Close() error {
|
|||||||
return c.agent.Close()
|
return c.agent.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Maybe just switch to using io.ReadWriteCloser?
|
|
||||||
|
|
||||||
// LocalAddr returns the local address of the current selected pair or nil if there is none.
|
// LocalAddr returns the local address of the current selected pair or nil if there is none.
|
||||||
func (c *Conn) LocalAddr() net.Addr {
|
func (c *Conn) LocalAddr() net.Addr {
|
||||||
pair := c.agent.getSelectedPair()
|
pair := c.agent.getSelectedPair()
|
||||||
|
@@ -4,7 +4,6 @@ package ice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -82,7 +81,6 @@ func TestTimeout(t *testing.T) {
|
|||||||
t.Run("WithoutDisconnectTimeout", func(t *testing.T) {
|
t.Run("WithoutDisconnectTimeout", func(t *testing.T) {
|
||||||
ca, cb := pipe(nil)
|
ca, cb := pipe(nil)
|
||||||
err := cb.Close()
|
err := cb.Close()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// we should never get here.
|
// we should never get here.
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -94,7 +92,6 @@ func TestTimeout(t *testing.T) {
|
|||||||
t.Run("WithDisconnectTimeout", func(t *testing.T) {
|
t.Run("WithDisconnectTimeout", func(t *testing.T) {
|
||||||
ca, cb := pipeWithTimeout(5*time.Second, 3*time.Second)
|
ca, cb := pipeWithTimeout(5*time.Second, 3*time.Second)
|
||||||
err := cb.Close()
|
err := cb.Close()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// we should never get here.
|
// we should never get here.
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -254,7 +251,7 @@ func pipe(defaultConfig *AgentConfig) (*Conn, *Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg.Urls = urls
|
cfg.Urls = urls
|
||||||
cfg.NetworkTypes = supportedNetworkTypes
|
cfg.NetworkTypes = supportedNetworkTypes()
|
||||||
|
|
||||||
aAgent, err := NewAgent(cfg)
|
aAgent, err := NewAgent(cfg)
|
||||||
check(err)
|
check(err)
|
||||||
@@ -285,7 +282,7 @@ func pipeWithTimeout(disconnectTimeout time.Duration, iceKeepalive time.Duration
|
|||||||
Urls: urls,
|
Urls: urls,
|
||||||
DisconnectedTimeout: &disconnectTimeout,
|
DisconnectedTimeout: &disconnectTimeout,
|
||||||
KeepaliveInterval: &iceKeepalive,
|
KeepaliveInterval: &iceKeepalive,
|
||||||
NetworkTypes: supportedNetworkTypes,
|
NetworkTypes: supportedNetworkTypes(),
|
||||||
}
|
}
|
||||||
|
|
||||||
aAgent, err := NewAgent(cfg)
|
aAgent, err := NewAgent(cfg)
|
||||||
@@ -397,7 +394,7 @@ func TestConnStats(t *testing.T) {
|
|||||||
go func() {
|
go func() {
|
||||||
buf := make([]byte, 10)
|
buf := make([]byte, 10)
|
||||||
if _, err := cb.Read(buf); err != nil {
|
if _, err := cb.Read(buf); err != nil {
|
||||||
panic(errors.New("unexpected error trying to read"))
|
panic(errRead)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
4
url.go
4
url.go
@@ -6,8 +6,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Migrate address parsing to STUN/TURN
|
|
||||||
|
|
||||||
// SchemeType indicates the type of server used in the ice.URL structure.
|
// SchemeType indicates the type of server used in the ice.URL structure.
|
||||||
type SchemeType int
|
type SchemeType int
|
||||||
|
|
||||||
@@ -110,7 +108,7 @@ type URL struct {
|
|||||||
// ParseURL parses a STUN or TURN urls following the ABNF syntax described in
|
// 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
|
// https://tools.ietf.org/html/rfc7064 and https://tools.ietf.org/html/rfc7065
|
||||||
// respectively.
|
// respectively.
|
||||||
func ParseURL(raw string) (*URL, error) {
|
func ParseURL(raw string) (*URL, error) { //nolint:gocognit
|
||||||
rawParts, err := url.Parse(raw)
|
rawParts, err := url.Parse(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package ice
|
package ice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -52,8 +51,8 @@ func TestParseURL(t *testing.T) {
|
|||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
{"", ErrSchemeType},
|
{"", ErrSchemeType},
|
||||||
{":::", errors.New("missing protocol scheme")},
|
{":::", errMissingProtocolScheme},
|
||||||
{"stun:[::1]:123:", errors.New("too many colons in address")},
|
{"stun:[::1]:123:", errTooManyColonsAddr},
|
||||||
{"stun:[::1]:123a", ErrPort},
|
{"stun:[::1]:123a", ErrPort},
|
||||||
{"google.de", ErrSchemeType},
|
{"google.de", ErrSchemeType},
|
||||||
{"stun:", ErrHost},
|
{"stun:", ErrHost},
|
||||||
@@ -72,7 +71,7 @@ func TestParseURL(t *testing.T) {
|
|||||||
case *url.Error:
|
case *url.Error:
|
||||||
err = e.Err
|
err = e.Err
|
||||||
case *net.AddrError:
|
case *net.AddrError:
|
||||||
err = fmt.Errorf("%v", e.Err)
|
err = fmt.Errorf(e.Err) //nolint:goerr113
|
||||||
}
|
}
|
||||||
assert.EqualError(t, err, testCase.expectedErr.Error(), "testCase: %d %v", i, testCase)
|
assert.EqualError(t, err, testCase.expectedErr.Error(), "testCase: %d %v", i, testCase)
|
||||||
}
|
}
|
||||||
|
@@ -18,4 +18,6 @@ func (UseCandidateAttr) IsSet(m *stun.Message) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UseCandidate is shorthand for UseCandidateAttr.
|
// UseCandidate is shorthand for UseCandidateAttr.
|
||||||
var UseCandidate UseCandidateAttr
|
func UseCandidate() UseCandidateAttr {
|
||||||
|
return UseCandidateAttr{}
|
||||||
|
}
|
||||||
|
@@ -8,17 +8,17 @@ import (
|
|||||||
|
|
||||||
func TestUseCandidateAttr_AddTo(t *testing.T) {
|
func TestUseCandidateAttr_AddTo(t *testing.T) {
|
||||||
m := new(stun.Message)
|
m := new(stun.Message)
|
||||||
if UseCandidate.IsSet(m) {
|
if UseCandidate().IsSet(m) {
|
||||||
t.Error("should not be set")
|
t.Error("should not be set")
|
||||||
}
|
}
|
||||||
if err := m.Build(stun.BindingRequest, UseCandidate); err != nil {
|
if err := m.Build(stun.BindingRequest, UseCandidate()); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
m1 := new(stun.Message)
|
m1 := new(stun.Message)
|
||||||
if _, err := m1.Write(m.Raw); err != nil {
|
if _, err := m1.Write(m.Raw); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
if !UseCandidate.IsSet(m1) {
|
if !UseCandidate().IsSet(m1) {
|
||||||
t.Error("should be set")
|
t.Error("should be set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
util.go
5
util.go
@@ -16,6 +16,7 @@ type atomicError struct{ v atomic.Value }
|
|||||||
func (a *atomicError) Store(err error) {
|
func (a *atomicError) Store(err error) {
|
||||||
a.v.Store(struct{ error }{err})
|
a.v.Store(struct{ error }{err})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *atomicError) Load() error {
|
func (a *atomicError) Load() error {
|
||||||
err, _ := a.v.Load().(struct{ error })
|
err, _ := a.v.Load().(struct{ error })
|
||||||
return err.error
|
return err.error
|
||||||
@@ -105,7 +106,7 @@ func getXORMappedAddr(conn net.PacketConn, serverAddr net.Addr, deadline time.Du
|
|||||||
}
|
}
|
||||||
var addr stun.XORMappedAddress
|
var addr stun.XORMappedAddress
|
||||||
if err = addr.GetFrom(resp); err != nil {
|
if err = addr.GetFrom(resp); err != nil {
|
||||||
return nil, fmt.Errorf("failed to get XOR-MAPPED-ADDRESS response: %v", err)
|
return nil, fmt.Errorf("%w: %v", errGetXorMappedAddrResponse, err)
|
||||||
}
|
}
|
||||||
return &addr, nil
|
return &addr, nil
|
||||||
}
|
}
|
||||||
@@ -131,7 +132,7 @@ func stunRequest(read func([]byte) (int, error), write func([]byte) (int, error)
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func localInterfaces(vnet *vnet.Net, interfaceFilter func(string) bool, networkTypes []NetworkType) ([]net.IP, error) {
|
func localInterfaces(vnet *vnet.Net, interfaceFilter func(string) bool, networkTypes []NetworkType) ([]net.IP, error) { //nolint:gocognit
|
||||||
ips := []net.IP{}
|
ips := []net.IP{}
|
||||||
ifaces, err := vnet.Interfaces()
|
ifaces, err := vnet.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user