mirror of
https://github.com/pion/ice.git
synced 2025-09-27 03:45:54 +08:00
Add more configuration to AgentOptions
This commit is contained in:
@@ -67,3 +67,88 @@ func WithNominationAttribute(attrType uint16) AgentOption {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithIncludeLoopback includes loopback addresses in the candidate list.
|
||||||
|
// By default, loopback addresses are excluded.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// agent, err := NewAgentWithOptions(WithIncludeLoopback())
|
||||||
|
func WithIncludeLoopback() AgentOption {
|
||||||
|
return func(a *Agent) error {
|
||||||
|
a.includeLoopback = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTCPPriorityOffset sets a number which is subtracted from the default (UDP) candidate type preference
|
||||||
|
// for host, srflx and prfx candidate types. It helps to configure relative preference of UDP candidates
|
||||||
|
// against TCP ones. Relay candidates for TCP and UDP are always 0 and not affected by this setting.
|
||||||
|
// When not set, defaultTCPPriorityOffset (27) is used.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// agent, err := NewAgentWithOptions(WithTCPPriorityOffset(50))
|
||||||
|
func WithTCPPriorityOffset(offset uint16) AgentOption {
|
||||||
|
return func(a *Agent) error {
|
||||||
|
a.tcpPriorityOffset = offset
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDisableActiveTCP disables Active TCP candidates.
|
||||||
|
// When TCP is enabled, Active TCP candidates will be created when a new passive TCP remote candidate is added
|
||||||
|
// unless this option is used.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// agent, err := NewAgentWithOptions(WithDisableActiveTCP())
|
||||||
|
func WithDisableActiveTCP() AgentOption {
|
||||||
|
return func(a *Agent) error {
|
||||||
|
a.disableActiveTCP = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBindingRequestHandler sets a handler to allow applications to perform logic on incoming STUN Binding Requests.
|
||||||
|
// This was implemented to allow users to:
|
||||||
|
// - Log incoming Binding Requests for debugging
|
||||||
|
// - Implement draft-thatcher-ice-renomination
|
||||||
|
// - Implement custom CandidatePair switching logic
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// handler := func(m *stun.Message, local, remote Candidate, pair *CandidatePair) bool {
|
||||||
|
// log.Printf("Binding request from %s to %s", remote.Address(), local.Address())
|
||||||
|
// return true // Accept the request
|
||||||
|
// }
|
||||||
|
// agent, err := NewAgentWithOptions(WithBindingRequestHandler(handler))
|
||||||
|
func WithBindingRequestHandler(
|
||||||
|
handler func(m *stun.Message, local, remote Candidate, pair *CandidatePair) bool,
|
||||||
|
) AgentOption {
|
||||||
|
return func(a *Agent) error {
|
||||||
|
a.userBindingRequestHandler = handler
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithEnableUseCandidateCheckPriority enables checking for equal or higher priority when
|
||||||
|
// switching selected candidate pair if the peer requests USE-CANDIDATE and agent is a lite agent.
|
||||||
|
// This is disabled by default, i.e. when peer requests USE-CANDIDATE, the selected pair will be
|
||||||
|
// switched to that irrespective of relative priority between current selected pair
|
||||||
|
// and priority of the pair being switched to.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// agent, err := NewAgentWithOptions(WithEnableUseCandidateCheckPriority())
|
||||||
|
func WithEnableUseCandidateCheckPriority() AgentOption {
|
||||||
|
return func(a *Agent) error {
|
||||||
|
a.enableUseCandidateCheckPriority = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -10,6 +10,46 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// testBooleanOption is a helper function to test boolean agent options.
|
||||||
|
type booleanOptionTest struct {
|
||||||
|
optionFunc func() AgentOption
|
||||||
|
getValue func(*Agent) bool
|
||||||
|
configSetter func(*AgentConfig, bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBooleanOption(t *testing.T, test booleanOptionTest, optionName string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
t.Run("enables "+optionName, func(t *testing.T) {
|
||||||
|
agent, err := NewAgentWithOptions(test.optionFunc())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.True(t, test.getValue(agent))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("default is false", func(t *testing.T) {
|
||||||
|
agent, err := NewAgentWithOptions()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.False(t, test.getValue(agent))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("works with config", func(t *testing.T) {
|
||||||
|
config := &AgentConfig{
|
||||||
|
NetworkTypes: []NetworkType{NetworkTypeUDP4},
|
||||||
|
}
|
||||||
|
test.configSetter(config, true)
|
||||||
|
|
||||||
|
agent, err := NewAgent(config)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.True(t, test.getValue(agent))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestDefaultNominationValueGenerator(t *testing.T) {
|
func TestDefaultNominationValueGenerator(t *testing.T) {
|
||||||
t.Run("generates incrementing values", func(t *testing.T) {
|
t.Run("generates incrementing values", func(t *testing.T) {
|
||||||
generator := DefaultNominationValueGenerator()
|
generator := DefaultNominationValueGenerator()
|
||||||
@@ -108,3 +148,151 @@ func TestWithNominationAttribute(t *testing.T) {
|
|||||||
assert.Equal(t, stun.AttrType(0x0030), agent.nominationAttribute)
|
assert.Equal(t, stun.AttrType(0x0030), agent.nominationAttribute)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWithIncludeLoopback(t *testing.T) {
|
||||||
|
testBooleanOption(t, booleanOptionTest{
|
||||||
|
optionFunc: WithIncludeLoopback,
|
||||||
|
getValue: func(a *Agent) bool { return a.includeLoopback },
|
||||||
|
configSetter: func(c *AgentConfig, v bool) { c.IncludeLoopback = v },
|
||||||
|
}, "loopback addresses")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithTCPPriorityOffset(t *testing.T) {
|
||||||
|
t.Run("sets custom TCP priority offset", func(t *testing.T) {
|
||||||
|
customOffset := uint16(50)
|
||||||
|
agent, err := NewAgentWithOptions(WithTCPPriorityOffset(customOffset))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.Equal(t, customOffset, agent.tcpPriorityOffset)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("default is 27", func(t *testing.T) {
|
||||||
|
agent, err := NewAgentWithOptions()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
// The default is set via initWithDefaults
|
||||||
|
assert.Equal(t, uint16(27), agent.tcpPriorityOffset)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("works with config", func(t *testing.T) {
|
||||||
|
customOffset := uint16(100)
|
||||||
|
config := &AgentConfig{
|
||||||
|
NetworkTypes: []NetworkType{NetworkTypeUDP4},
|
||||||
|
TCPPriorityOffset: &customOffset,
|
||||||
|
}
|
||||||
|
|
||||||
|
agent, err := NewAgent(config)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.Equal(t, customOffset, agent.tcpPriorityOffset)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithDisableActiveTCP(t *testing.T) {
|
||||||
|
testBooleanOption(t, booleanOptionTest{
|
||||||
|
optionFunc: WithDisableActiveTCP,
|
||||||
|
getValue: func(a *Agent) bool { return a.disableActiveTCP },
|
||||||
|
configSetter: func(c *AgentConfig, v bool) { c.DisableActiveTCP = v },
|
||||||
|
}, "active TCP disabling")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithBindingRequestHandler(t *testing.T) {
|
||||||
|
t.Run("sets binding request handler", func(t *testing.T) {
|
||||||
|
handlerCalled := false
|
||||||
|
handler := func(m *stun.Message, local, remote Candidate, pair *CandidatePair) bool {
|
||||||
|
handlerCalled = true
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
agent, err := NewAgentWithOptions(WithBindingRequestHandler(handler))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.NotNil(t, agent.userBindingRequestHandler)
|
||||||
|
|
||||||
|
// Test that the handler is actually the one we set
|
||||||
|
// We can't directly compare functions, but we can call it
|
||||||
|
if agent.userBindingRequestHandler != nil {
|
||||||
|
agent.userBindingRequestHandler(nil, nil, nil, nil)
|
||||||
|
assert.True(t, handlerCalled)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("default is nil", func(t *testing.T) {
|
||||||
|
agent, err := NewAgentWithOptions()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.Nil(t, agent.userBindingRequestHandler)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("works with config", func(t *testing.T) {
|
||||||
|
handlerCalled := false
|
||||||
|
handler := func(m *stun.Message, local, remote Candidate, pair *CandidatePair) bool {
|
||||||
|
handlerCalled = true
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &AgentConfig{
|
||||||
|
NetworkTypes: []NetworkType{NetworkTypeUDP4},
|
||||||
|
BindingRequestHandler: handler,
|
||||||
|
}
|
||||||
|
|
||||||
|
agent, err := NewAgent(config)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.NotNil(t, agent.userBindingRequestHandler)
|
||||||
|
|
||||||
|
if agent.userBindingRequestHandler != nil {
|
||||||
|
agent.userBindingRequestHandler(nil, nil, nil, nil)
|
||||||
|
assert.True(t, handlerCalled)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithEnableUseCandidateCheckPriority(t *testing.T) {
|
||||||
|
testBooleanOption(t, booleanOptionTest{
|
||||||
|
optionFunc: WithEnableUseCandidateCheckPriority,
|
||||||
|
getValue: func(a *Agent) bool { return a.enableUseCandidateCheckPriority },
|
||||||
|
configSetter: func(c *AgentConfig, v bool) { c.EnableUseCandidateCheckPriority = v },
|
||||||
|
}, "use candidate check priority")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultipleConfigOptions(t *testing.T) {
|
||||||
|
t.Run("can apply multiple options", func(t *testing.T) {
|
||||||
|
customOffset := uint16(100)
|
||||||
|
handlerCalled := false
|
||||||
|
handler := func(m *stun.Message, local, remote Candidate, pair *CandidatePair) bool {
|
||||||
|
handlerCalled = true
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
agent, err := NewAgentWithOptions(
|
||||||
|
WithIncludeLoopback(),
|
||||||
|
WithTCPPriorityOffset(customOffset),
|
||||||
|
WithDisableActiveTCP(),
|
||||||
|
WithBindingRequestHandler(handler),
|
||||||
|
WithEnableUseCandidateCheckPriority(),
|
||||||
|
)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer agent.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
assert.True(t, agent.includeLoopback)
|
||||||
|
assert.Equal(t, customOffset, agent.tcpPriorityOffset)
|
||||||
|
assert.True(t, agent.disableActiveTCP)
|
||||||
|
assert.NotNil(t, agent.userBindingRequestHandler)
|
||||||
|
assert.True(t, agent.enableUseCandidateCheckPriority)
|
||||||
|
|
||||||
|
if agent.userBindingRequestHandler != nil {
|
||||||
|
agent.userBindingRequestHandler(nil, nil, nil, nil)
|
||||||
|
assert.True(t, handlerCalled)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user