-
Notifications
You must be signed in to change notification settings - Fork 0
/
agent_config.go
316 lines (256 loc) · 11.5 KB
/
agent_config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package ice
import (
"net"
"time"
"github.com/pion/logging"
"github.com/pion/stun/v2"
"github.com/pion/transport/v3"
"golang.org/x/net/proxy"
)
const (
// defaultCheckInterval is the interval at which the agent performs candidate checks in the connecting phase
defaultCheckInterval = 200 * time.Millisecond
// keepaliveInterval used to keep candidates alive
defaultKeepaliveInterval = 2 * time.Second
// defaultDisconnectedTimeout is the default time till an Agent transitions disconnected
defaultDisconnectedTimeout = 5 * time.Second
// defaultFailedTimeout is the default time till an Agent transitions to failed after disconnected
defaultFailedTimeout = 25 * time.Second
// defaultHostAcceptanceMinWait is the wait time before nominating a host candidate
defaultHostAcceptanceMinWait = 0
// defaultSrflxAcceptanceMinWait is the wait time before nominating a srflx candidate
defaultSrflxAcceptanceMinWait = 500 * time.Millisecond
// defaultPrflxAcceptanceMinWait is the wait time before nominating a prflx candidate
defaultPrflxAcceptanceMinWait = 1000 * time.Millisecond
// defaultRelayAcceptanceMinWait is the wait time before nominating a relay candidate
defaultRelayAcceptanceMinWait = 2000 * time.Millisecond
// defaultSTUNGatherTimeout is the wait time for STUN responses
defaultSTUNGatherTimeout = 5 * time.Second
// defaultMaxBindingRequests is the maximum number of binding requests before considering a pair failed
defaultMaxBindingRequests = 7
// TCPPriorityOffset is a number which is subtracted from the default (UDP) candidate type preference
// for host, srflx and prfx candidate types.
defaultTCPPriorityOffset = 27
// maxBufferSize is the number of bytes that can be buffered before we start to error
maxBufferSize = 1000 * 1000 // 1MB
// maxBindingRequestTimeout is the wait time before binding requests can be deleted
maxBindingRequestTimeout = 4000 * time.Millisecond
)
func defaultCandidateTypes() []CandidateType {
return []CandidateType{CandidateTypeHost, CandidateTypeServerReflexive, CandidateTypeRelay}
}
// AgentConfig collects the arguments to ice.Agent construction into
// a single structure, for future-proofness of the interface
type AgentConfig struct {
Urls []*stun.URI
// PortMin and PortMax are optional. Leave them 0 for the default UDP port allocation strategy.
PortMin uint16
PortMax uint16
// LocalUfrag and LocalPwd values used to perform connectivity
// checks. The values MUST be unguessable, with at least 128 bits of
// random number generator output used to generate the password, and
// at least 24 bits of output to generate the username fragment.
LocalUfrag string
LocalPwd string
// MulticastDNSMode controls mDNS behavior for the ICE agent
MulticastDNSMode MulticastDNSMode
// MulticastDNSHostName controls the hostname for this agent. If none is specified a random one will be generated
MulticastDNSHostName string
// DisconnectedTimeout defaults to 5 seconds when this property is nil.
// If the duration is 0, the ICE Agent will never go to disconnected
DisconnectedTimeout *time.Duration
// FailedTimeout defaults to 25 seconds when this property is nil.
// If the duration is 0, we will never go to failed.
FailedTimeout *time.Duration
// KeepaliveInterval determines how often should we send ICE
// keepalives (should be less then connectiontimeout above)
// when this is nil, it defaults to 10 seconds.
// A keepalive interval of 0 means we never send keepalive packets
KeepaliveInterval *time.Duration
// CheckInterval controls how often our task loop runs when in the
// connecting state.
CheckInterval *time.Duration
// NetworkTypes is an optional configuration for disabling or enabling
// support for specific network types.
NetworkTypes []NetworkType
// CandidateTypes is an optional configuration for disabling or enabling
// support for specific candidate types.
CandidateTypes []CandidateType
LoggerFactory logging.LoggerFactory
// MaxBindingRequests is the max amount of binding requests the agent will send
// over a candidate pair for validation or nomination, if after MaxBindingRequests
// the candidate is yet to answer a binding request or a nomination we set the pair as failed
MaxBindingRequests *uint16
// Lite agents do not perform connectivity check and only provide host candidates.
Lite bool
// NAT1To1IPCandidateType is used along with NAT1To1IPs to specify which candidate type
// the 1:1 NAT IP addresses should be mapped to.
// If unspecified or CandidateTypeHost, NAT1To1IPs are used to replace host candidate IPs.
// If CandidateTypeServerReflexive, it will insert a srflx candidate (as if it was derived
// from a STUN server) with its port number being the one for the actual host candidate.
// Other values will result in an error.
NAT1To1IPCandidateType CandidateType
// NAT1To1IPs contains a list of public IP addresses that are to be used as a host
// candidate or srflx candidate. This is used typically for servers that are behind
// 1:1 D-NAT (e.g. AWS EC2 instances) and to eliminate the need of server reflexive
// candidate gathering.
NAT1To1IPs []string
// HostAcceptanceMinWait specify a minimum wait time before selecting host candidates
HostAcceptanceMinWait *time.Duration
// SrflxAcceptanceMinWait specify a minimum wait time before selecting srflx candidates
SrflxAcceptanceMinWait *time.Duration
// PrflxAcceptanceMinWait specify a minimum wait time before selecting prflx candidates
PrflxAcceptanceMinWait *time.Duration
// RelayAcceptanceMinWait specify a minimum wait time before selecting relay candidates
RelayAcceptanceMinWait *time.Duration
// STUNGatherTimeout specify a minimum wait time for STUN responses
STUNGatherTimeout *time.Duration
// Net is the our abstracted network interface for internal development purpose only
// (see https://github.com/pion/transport)
Net transport.Net
// InterfaceFilter is a function that you can use in order to whitelist or blacklist
// the interfaces which are used to gather ICE candidates.
InterfaceFilter func(string) bool
// IPFilter is a function that you can use in order to whitelist or blacklist
// the ips which are used to gather ICE candidates.
IPFilter func(net.IP) bool
// InsecureSkipVerify controls if self-signed certificates are accepted when connecting
// to TURN servers via TLS or DTLS
InsecureSkipVerify bool
// TCPMux will be used for multiplexing incoming TCP connections for ICE TCP.
// Currently only passive candidates are supported. This functionality is
// experimental and the API might change in the future.
TCPMux TCPMux
// UDPMux is used for multiplexing multiple incoming UDP connections on a single port
// when this is set, the agent ignores PortMin and PortMax configurations and will
// defer to UDPMux for incoming connections
UDPMux UDPMux
// UDPMuxSrflx is used for multiplexing multiple incoming UDP connections of server reflexive candidates
// on a single port when this is set, the agent ignores PortMin and PortMax configurations and will
// defer to UDPMuxSrflx for incoming connections
// It embeds UDPMux to do the actual connection multiplexing
UDPMuxSrflx UniversalUDPMux
// Proxy Dialer is a dialer that should be implemented by the user based on golang.org/x/net/proxy
// dial interface in order to support corporate proxies
ProxyDialer proxy.Dialer
// Deprecated: AcceptAggressiveNomination always enabled.
AcceptAggressiveNomination bool
// Include loopback addresses in the candidate list.
IncludeLoopback bool
// TCPPriorityOffset is 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 this is nil, defaultTCPPriorityOffset is used.
TCPPriorityOffset *uint16
// DisableActiveTCP can be used to disable Active TCP candidates. Otherwise when TCP is enabled
// Active TCP candidates will be created when a new passive TCP remote candidate is added.
DisableActiveTCP bool
// BindingRequestHandler allows 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
BindingRequestHandler func(m *stun.Message, local, remote Candidate, pair *CandidatePair) bool
}
// initWithDefaults populates an agent and falls back to defaults if fields are unset
func (config *AgentConfig) initWithDefaults(a *Agent) {
if config.MaxBindingRequests == nil {
a.maxBindingRequests = defaultMaxBindingRequests
} else {
a.maxBindingRequests = *config.MaxBindingRequests
}
if config.HostAcceptanceMinWait == nil {
a.hostAcceptanceMinWait = defaultHostAcceptanceMinWait
} else {
a.hostAcceptanceMinWait = *config.HostAcceptanceMinWait
}
if config.SrflxAcceptanceMinWait == nil {
a.srflxAcceptanceMinWait = defaultSrflxAcceptanceMinWait
} else {
a.srflxAcceptanceMinWait = *config.SrflxAcceptanceMinWait
}
if config.PrflxAcceptanceMinWait == nil {
a.prflxAcceptanceMinWait = defaultPrflxAcceptanceMinWait
} else {
a.prflxAcceptanceMinWait = *config.PrflxAcceptanceMinWait
}
if config.RelayAcceptanceMinWait == nil {
a.relayAcceptanceMinWait = defaultRelayAcceptanceMinWait
} else {
a.relayAcceptanceMinWait = *config.RelayAcceptanceMinWait
}
if config.STUNGatherTimeout == nil {
a.stunGatherTimeout = defaultSTUNGatherTimeout
} else {
a.stunGatherTimeout = *config.STUNGatherTimeout
}
if config.TCPPriorityOffset == nil {
a.tcpPriorityOffset = defaultTCPPriorityOffset
} else {
a.tcpPriorityOffset = *config.TCPPriorityOffset
}
if config.DisconnectedTimeout == nil {
a.disconnectedTimeout = defaultDisconnectedTimeout
} else {
a.disconnectedTimeout = *config.DisconnectedTimeout
}
if config.FailedTimeout == nil {
a.failedTimeout = defaultFailedTimeout
} else {
a.failedTimeout = *config.FailedTimeout
}
if config.KeepaliveInterval == nil {
a.keepaliveInterval = defaultKeepaliveInterval
} else {
a.keepaliveInterval = *config.KeepaliveInterval
}
if config.CheckInterval == nil {
a.checkInterval = defaultCheckInterval
} else {
a.checkInterval = *config.CheckInterval
}
if config.CandidateTypes == nil || len(config.CandidateTypes) == 0 {
a.candidateTypes = defaultCandidateTypes()
} else {
a.candidateTypes = config.CandidateTypes
}
}
func (config *AgentConfig) initExtIPMapping(a *Agent) error {
var err error
a.extIPMapper, err = newExternalIPMapper(config.NAT1To1IPCandidateType, config.NAT1To1IPs)
if err != nil {
return err
}
if a.extIPMapper == nil {
return nil // This may happen when config.NAT1To1IPs is an empty array
}
if a.extIPMapper.candidateType == CandidateTypeHost {
if a.mDNSMode == MulticastDNSModeQueryAndGather {
return ErrMulticastDNSWithNAT1To1IPMapping
}
candiHostEnabled := false
for _, candiType := range a.candidateTypes {
if candiType == CandidateTypeHost {
candiHostEnabled = true
break
}
}
if !candiHostEnabled {
return ErrIneffectiveNAT1To1IPMappingHost
}
} else if a.extIPMapper.candidateType == CandidateTypeServerReflexive {
candiSrflxEnabled := false
for _, candiType := range a.candidateTypes {
if candiType == CandidateTypeServerReflexive {
candiSrflxEnabled = true
break
}
}
if !candiSrflxEnabled {
return ErrIneffectiveNAT1To1IPMappingSrflx
}
}
return nil
}