agent_config.go 11 KB

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