github.com/pion/webrtc/v4@v4.0.1/settingengine.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 //go:build !js 5 // +build !js 6 7 package webrtc 8 9 import ( 10 "context" 11 "crypto/x509" 12 "io" 13 "net" 14 "time" 15 16 "github.com/pion/dtls/v3" 17 dtlsElliptic "github.com/pion/dtls/v3/pkg/crypto/elliptic" 18 "github.com/pion/dtls/v3/pkg/protocol/handshake" 19 "github.com/pion/ice/v4" 20 "github.com/pion/logging" 21 "github.com/pion/stun/v3" 22 "github.com/pion/transport/v3" 23 "github.com/pion/transport/v3/packetio" 24 "golang.org/x/net/proxy" 25 ) 26 27 // SettingEngine allows influencing behavior in ways that are not 28 // supported by the WebRTC API. This allows us to support additional 29 // use-cases without deviating from the WebRTC API elsewhere. 30 type SettingEngine struct { 31 ephemeralUDP struct { 32 PortMin uint16 33 PortMax uint16 34 } 35 detach struct { 36 DataChannels bool 37 } 38 timeout struct { 39 ICEDisconnectedTimeout *time.Duration 40 ICEFailedTimeout *time.Duration 41 ICEKeepaliveInterval *time.Duration 42 ICEHostAcceptanceMinWait *time.Duration 43 ICESrflxAcceptanceMinWait *time.Duration 44 ICEPrflxAcceptanceMinWait *time.Duration 45 ICERelayAcceptanceMinWait *time.Duration 46 ICESTUNGatherTimeout *time.Duration 47 } 48 candidates struct { 49 ICELite bool 50 ICENetworkTypes []NetworkType 51 InterfaceFilter func(string) bool 52 IPFilter func(net.IP) bool 53 NAT1To1IPs []string 54 NAT1To1IPCandidateType ICECandidateType 55 MulticastDNSMode ice.MulticastDNSMode 56 MulticastDNSHostName string 57 UsernameFragment string 58 Password string 59 IncludeLoopbackCandidate bool 60 } 61 replayProtection struct { 62 DTLS *uint 63 SRTP *uint 64 SRTCP *uint 65 } 66 dtls struct { 67 insecureSkipHelloVerify bool 68 disableInsecureSkipVerify bool 69 retransmissionInterval time.Duration 70 ellipticCurves []dtlsElliptic.Curve 71 connectContextMaker func() (context.Context, func()) 72 extendedMasterSecret dtls.ExtendedMasterSecretType 73 clientAuth *dtls.ClientAuthType 74 clientCAs *x509.CertPool 75 rootCAs *x509.CertPool 76 keyLogWriter io.Writer 77 customCipherSuites func() []dtls.CipherSuite 78 clientHelloMessageHook func(handshake.MessageClientHello) handshake.Message 79 serverHelloMessageHook func(handshake.MessageServerHello) handshake.Message 80 certificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message 81 } 82 sctp struct { 83 maxReceiveBufferSize uint32 84 enableZeroChecksum bool 85 rtoMax time.Duration 86 } 87 sdpMediaLevelFingerprints bool 88 answeringDTLSRole DTLSRole 89 disableCertificateFingerprintVerification bool 90 disableSRTPReplayProtection bool 91 disableSRTCPReplayProtection bool 92 net transport.Net 93 BufferFactory func(packetType packetio.BufferPacketType, ssrc uint32) io.ReadWriteCloser 94 LoggerFactory logging.LoggerFactory 95 iceTCPMux ice.TCPMux 96 iceUDPMux ice.UDPMux 97 iceProxyDialer proxy.Dialer 98 iceDisableActiveTCP bool 99 iceBindingRequestHandler func(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool 100 disableMediaEngineCopy bool 101 srtpProtectionProfiles []dtls.SRTPProtectionProfile 102 receiveMTU uint 103 iceMaxBindingRequests *uint16 104 fireOnTrackBeforeFirstRTP bool 105 } 106 107 // getReceiveMTU returns the configured MTU. If SettingEngine's MTU is configured to 0 it returns the default 108 func (e *SettingEngine) getReceiveMTU() uint { 109 if e.receiveMTU != 0 { 110 return e.receiveMTU 111 } 112 113 return receiveMTU 114 } 115 116 // DetachDataChannels enables detaching data channels. When enabled 117 // data channels have to be detached in the OnOpen callback using the 118 // DataChannel.Detach method. 119 func (e *SettingEngine) DetachDataChannels() { 120 e.detach.DataChannels = true 121 } 122 123 // SetSRTPProtectionProfiles allows the user to override the default SRTP Protection Profiles 124 // The default srtp protection profiles are provided by the function `defaultSrtpProtectionProfiles` 125 func (e *SettingEngine) SetSRTPProtectionProfiles(profiles ...dtls.SRTPProtectionProfile) { 126 e.srtpProtectionProfiles = profiles 127 } 128 129 // SetICETimeouts sets the behavior around ICE Timeouts 130 // 131 // disconnectedTimeout: 132 // 133 // Duration without network activity before an Agent is considered disconnected. Default is 5 Seconds 134 // 135 // failedTimeout: 136 // 137 // Duration without network activity before an Agent is considered failed after disconnected. Default is 25 Seconds 138 // 139 // keepAliveInterval: 140 // 141 // How often the ICE Agent sends extra traffic if there is no activity, if media is flowing no traffic will be sent. Default is 2 seconds 142 func (e *SettingEngine) SetICETimeouts(disconnectedTimeout, failedTimeout, keepAliveInterval time.Duration) { 143 e.timeout.ICEDisconnectedTimeout = &disconnectedTimeout 144 e.timeout.ICEFailedTimeout = &failedTimeout 145 e.timeout.ICEKeepaliveInterval = &keepAliveInterval 146 } 147 148 // SetHostAcceptanceMinWait sets the ICEHostAcceptanceMinWait 149 func (e *SettingEngine) SetHostAcceptanceMinWait(t time.Duration) { 150 e.timeout.ICEHostAcceptanceMinWait = &t 151 } 152 153 // SetSrflxAcceptanceMinWait sets the ICESrflxAcceptanceMinWait 154 func (e *SettingEngine) SetSrflxAcceptanceMinWait(t time.Duration) { 155 e.timeout.ICESrflxAcceptanceMinWait = &t 156 } 157 158 // SetPrflxAcceptanceMinWait sets the ICEPrflxAcceptanceMinWait 159 func (e *SettingEngine) SetPrflxAcceptanceMinWait(t time.Duration) { 160 e.timeout.ICEPrflxAcceptanceMinWait = &t 161 } 162 163 // SetRelayAcceptanceMinWait sets the ICERelayAcceptanceMinWait 164 func (e *SettingEngine) SetRelayAcceptanceMinWait(t time.Duration) { 165 e.timeout.ICERelayAcceptanceMinWait = &t 166 } 167 168 // SetSTUNGatherTimeout sets the ICESTUNGatherTimeout 169 func (e *SettingEngine) SetSTUNGatherTimeout(t time.Duration) { 170 e.timeout.ICESTUNGatherTimeout = &t 171 } 172 173 // SetEphemeralUDPPortRange limits the pool of ephemeral ports that 174 // ICE UDP connections can allocate from. This affects both host candidates, 175 // and the local address of server reflexive candidates. 176 // 177 // When portMin and portMax are left to the 0 default value, pion/ice candidate 178 // gatherer replaces them and uses 1 for portMin and 65535 for portMax. 179 func (e *SettingEngine) SetEphemeralUDPPortRange(portMin, portMax uint16) error { 180 if portMax < portMin { 181 return ice.ErrPort 182 } 183 184 e.ephemeralUDP.PortMin = portMin 185 e.ephemeralUDP.PortMax = portMax 186 return nil 187 } 188 189 // SetLite configures whether or not the ice agent should be a lite agent 190 func (e *SettingEngine) SetLite(lite bool) { 191 e.candidates.ICELite = lite 192 } 193 194 // SetNetworkTypes configures what types of candidate networks are supported 195 // during local and server reflexive gathering. 196 func (e *SettingEngine) SetNetworkTypes(candidateTypes []NetworkType) { 197 e.candidates.ICENetworkTypes = candidateTypes 198 } 199 200 // SetInterfaceFilter sets the filtering functions when gathering ICE candidates 201 // This can be used to exclude certain network interfaces from ICE. Which may be 202 // useful if you know a certain interface will never succeed, or if you wish to reduce 203 // the amount of information you wish to expose to the remote peer 204 func (e *SettingEngine) SetInterfaceFilter(filter func(string) bool) { 205 e.candidates.InterfaceFilter = filter 206 } 207 208 // SetIPFilter sets the filtering functions when gathering ICE candidates 209 // This can be used to exclude certain ip from ICE. Which may be 210 // useful if you know a certain ip will never succeed, or if you wish to reduce 211 // the amount of information you wish to expose to the remote peer 212 func (e *SettingEngine) SetIPFilter(filter func(net.IP) bool) { 213 e.candidates.IPFilter = filter 214 } 215 216 // SetNAT1To1IPs sets a list of external IP addresses of 1:1 (D)NAT 217 // and a candidate type for which the external IP address is used. 218 // This is useful when you host a server using Pion on an AWS EC2 instance 219 // which has a private address, behind a 1:1 DNAT with a public IP (e.g. 220 // Elastic IP). In this case, you can give the public IP address so that 221 // Pion will use the public IP address in its candidate instead of the private 222 // IP address. The second argument, candidateType, is used to tell Pion which 223 // type of candidate should use the given public IP address. 224 // Two types of candidates are supported: 225 // 226 // ICECandidateTypeHost: 227 // 228 // The public IP address will be used for the host candidate in the SDP. 229 // 230 // ICECandidateTypeSrflx: 231 // 232 // A server reflexive candidate with the given public IP address will be added to the SDP. 233 // 234 // Please note that if you choose ICECandidateTypeHost, then the private IP address 235 // won't be advertised with the peer. Also, this option cannot be used along with mDNS. 236 // 237 // If you choose ICECandidateTypeSrflx, it simply adds a server reflexive candidate 238 // with the public IP. The host candidate is still available along with mDNS 239 // capabilities unaffected. Also, you cannot give STUN server URL at the same time. 240 // It will result in an error otherwise. 241 func (e *SettingEngine) SetNAT1To1IPs(ips []string, candidateType ICECandidateType) { 242 e.candidates.NAT1To1IPs = ips 243 e.candidates.NAT1To1IPCandidateType = candidateType 244 } 245 246 // SetIncludeLoopbackCandidate enable pion to gather loopback candidates, it is useful 247 // for some VM have public IP mapped to loopback interface 248 func (e *SettingEngine) SetIncludeLoopbackCandidate(include bool) { 249 e.candidates.IncludeLoopbackCandidate = include 250 } 251 252 // SetAnsweringDTLSRole sets the DTLS role that is selected when offering 253 // The DTLS role controls if the WebRTC Client as a client or server. This 254 // may be useful when interacting with non-compliant clients or debugging issues. 255 // 256 // DTLSRoleActive: 257 // 258 // Act as DTLS Client, send the ClientHello and starts the handshake 259 // 260 // DTLSRolePassive: 261 // 262 // Act as DTLS Server, wait for ClientHello 263 func (e *SettingEngine) SetAnsweringDTLSRole(role DTLSRole) error { 264 if role != DTLSRoleClient && role != DTLSRoleServer { 265 return errSettingEngineSetAnsweringDTLSRole 266 } 267 268 e.answeringDTLSRole = role 269 return nil 270 } 271 272 // SetNet sets the Net instance that is passed to pion/ice 273 // 274 // Net is an network interface layer for Pion, allowing users to replace 275 // Pions network stack with a custom implementation. 276 func (e *SettingEngine) SetNet(net transport.Net) { 277 e.net = net 278 } 279 280 // SetICEMulticastDNSMode controls if pion/ice queries and generates mDNS ICE Candidates 281 func (e *SettingEngine) SetICEMulticastDNSMode(multicastDNSMode ice.MulticastDNSMode) { 282 e.candidates.MulticastDNSMode = multicastDNSMode 283 } 284 285 // SetMulticastDNSHostName sets a static HostName to be used by pion/ice instead of generating one on startup 286 // 287 // This should only be used for a single PeerConnection. Having multiple PeerConnections with the same HostName will cause 288 // undefined behavior 289 func (e *SettingEngine) SetMulticastDNSHostName(hostName string) { 290 e.candidates.MulticastDNSHostName = hostName 291 } 292 293 // SetICECredentials sets a staic uFrag/uPwd to be used by pion/ice 294 // 295 // This is useful if you want to do signalless WebRTC session, or having a reproducible environment with static credentials 296 func (e *SettingEngine) SetICECredentials(usernameFragment, password string) { 297 e.candidates.UsernameFragment = usernameFragment 298 e.candidates.Password = password 299 } 300 301 // DisableCertificateFingerprintVerification disables fingerprint verification after DTLS Handshake has finished 302 func (e *SettingEngine) DisableCertificateFingerprintVerification(isDisabled bool) { 303 e.disableCertificateFingerprintVerification = isDisabled 304 } 305 306 // SetDTLSReplayProtectionWindow sets a replay attack protection window size of DTLS connection. 307 func (e *SettingEngine) SetDTLSReplayProtectionWindow(n uint) { 308 e.replayProtection.DTLS = &n 309 } 310 311 // SetSRTPReplayProtectionWindow sets a replay attack protection window size of SRTP session. 312 func (e *SettingEngine) SetSRTPReplayProtectionWindow(n uint) { 313 e.disableSRTPReplayProtection = false 314 e.replayProtection.SRTP = &n 315 } 316 317 // SetSRTCPReplayProtectionWindow sets a replay attack protection window size of SRTCP session. 318 func (e *SettingEngine) SetSRTCPReplayProtectionWindow(n uint) { 319 e.disableSRTCPReplayProtection = false 320 e.replayProtection.SRTCP = &n 321 } 322 323 // DisableSRTPReplayProtection disables SRTP replay protection. 324 func (e *SettingEngine) DisableSRTPReplayProtection(isDisabled bool) { 325 e.disableSRTPReplayProtection = isDisabled 326 } 327 328 // DisableSRTCPReplayProtection disables SRTCP replay protection. 329 func (e *SettingEngine) DisableSRTCPReplayProtection(isDisabled bool) { 330 e.disableSRTCPReplayProtection = isDisabled 331 } 332 333 // SetSDPMediaLevelFingerprints configures the logic for DTLS Fingerprint insertion 334 // If true, fingerprints will be inserted in the sdp at the fingerprint 335 // level, instead of the session level. This helps with compatibility with 336 // some webrtc implementations. 337 func (e *SettingEngine) SetSDPMediaLevelFingerprints(sdpMediaLevelFingerprints bool) { 338 e.sdpMediaLevelFingerprints = sdpMediaLevelFingerprints 339 } 340 341 // SetICETCPMux enables ICE-TCP when set to a non-nil value. Make sure that 342 // NetworkTypeTCP4 or NetworkTypeTCP6 is enabled as well. 343 func (e *SettingEngine) SetICETCPMux(tcpMux ice.TCPMux) { 344 e.iceTCPMux = tcpMux 345 } 346 347 // SetICEUDPMux allows ICE traffic to come through a single UDP port, drastically 348 // simplifying deployments where ports will need to be opened/forwarded. 349 // UDPMux should be started prior to creating PeerConnections. 350 func (e *SettingEngine) SetICEUDPMux(udpMux ice.UDPMux) { 351 e.iceUDPMux = udpMux 352 } 353 354 // SetICEProxyDialer sets the proxy dialer interface based on golang.org/x/net/proxy. 355 func (e *SettingEngine) SetICEProxyDialer(d proxy.Dialer) { 356 e.iceProxyDialer = d 357 } 358 359 // SetICEMaxBindingRequests sets the maximum amount of binding requests 360 // that can be sent on a candidate before it is considered invalid. 361 func (e *SettingEngine) SetICEMaxBindingRequests(d uint16) { 362 e.iceMaxBindingRequests = &d 363 } 364 365 // DisableActiveTCP disables using active TCP for ICE. Active TCP is enabled by default 366 func (e *SettingEngine) DisableActiveTCP(isDisabled bool) { 367 e.iceDisableActiveTCP = isDisabled 368 } 369 370 // DisableMediaEngineCopy stops the MediaEngine from being copied. This allows a user to modify 371 // the MediaEngine after the PeerConnection has been constructed. This is useful if you wish to 372 // modify codecs after signaling. Make sure not to share MediaEngines between PeerConnections. 373 func (e *SettingEngine) DisableMediaEngineCopy(isDisabled bool) { 374 e.disableMediaEngineCopy = isDisabled 375 } 376 377 // SetReceiveMTU sets the size of read buffer that copies incoming packets. This is optional. 378 // Leave this 0 for the default receiveMTU 379 func (e *SettingEngine) SetReceiveMTU(receiveMTU uint) { 380 e.receiveMTU = receiveMTU 381 } 382 383 // SetDTLSRetransmissionInterval sets the retranmission interval for DTLS. 384 func (e *SettingEngine) SetDTLSRetransmissionInterval(interval time.Duration) { 385 e.dtls.retransmissionInterval = interval 386 } 387 388 // SetDTLSInsecureSkipHelloVerify sets the skip HelloVerify flag for DTLS. 389 // If true and when acting as DTLS server, will allow client to skip hello verify phase and 390 // receive ServerHello after initial ClientHello. This will mean faster connect times, 391 // but will have lower DoS attack resistance. 392 func (e *SettingEngine) SetDTLSInsecureSkipHelloVerify(skip bool) { 393 e.dtls.insecureSkipHelloVerify = skip 394 } 395 396 // SetDTLSDisableInsecureSkipVerify sets the disable skip insecure verify flag for DTLS. 397 // This controls whether a client verifies the server's certificate chain and host name. 398 func (e *SettingEngine) SetDTLSDisableInsecureSkipVerify(disable bool) { 399 e.dtls.disableInsecureSkipVerify = disable 400 } 401 402 // SetDTLSEllipticCurves sets the elliptic curves for DTLS. 403 func (e *SettingEngine) SetDTLSEllipticCurves(ellipticCurves ...dtlsElliptic.Curve) { 404 e.dtls.ellipticCurves = ellipticCurves 405 } 406 407 // SetDTLSConnectContextMaker sets the context used during the DTLS Handshake. 408 // It can be used to extend or reduce the timeout on the DTLS Handshake. 409 // If nil, the default dtls.ConnectContextMaker is used. It can be implemented as following. 410 // 411 // func ConnectContextMaker() (context.Context, func()) { 412 // return context.WithTimeout(context.Background(), 30*time.Second) 413 // } 414 func (e *SettingEngine) SetDTLSConnectContextMaker(connectContextMaker func() (context.Context, func())) { 415 e.dtls.connectContextMaker = connectContextMaker 416 } 417 418 // SetDTLSExtendedMasterSecret sets the extended master secret type for DTLS. 419 func (e *SettingEngine) SetDTLSExtendedMasterSecret(extendedMasterSecret dtls.ExtendedMasterSecretType) { 420 e.dtls.extendedMasterSecret = extendedMasterSecret 421 } 422 423 // SetDTLSClientAuth sets the client auth type for DTLS. 424 func (e *SettingEngine) SetDTLSClientAuth(clientAuth dtls.ClientAuthType) { 425 e.dtls.clientAuth = &clientAuth 426 } 427 428 // SetDTLSClientCAs sets the client CA certificate pool for DTLS certificate verification. 429 func (e *SettingEngine) SetDTLSClientCAs(clientCAs *x509.CertPool) { 430 e.dtls.clientCAs = clientCAs 431 } 432 433 // SetDTLSRootCAs sets the root CA certificate pool for DTLS certificate verification. 434 func (e *SettingEngine) SetDTLSRootCAs(rootCAs *x509.CertPool) { 435 e.dtls.rootCAs = rootCAs 436 } 437 438 // SetDTLSKeyLogWriter sets the destination of the TLS key material for debugging. 439 // Logging key material compromises security and should only be use for debugging. 440 func (e *SettingEngine) SetDTLSKeyLogWriter(writer io.Writer) { 441 e.dtls.keyLogWriter = writer 442 } 443 444 // SetSCTPMaxReceiveBufferSize sets the maximum receive buffer size. 445 // Leave this 0 for the default maxReceiveBufferSize. 446 func (e *SettingEngine) SetSCTPMaxReceiveBufferSize(maxReceiveBufferSize uint32) { 447 e.sctp.maxReceiveBufferSize = maxReceiveBufferSize 448 } 449 450 // EnableSCTPZeroChecksum controls the zero checksum feature in SCTP. 451 // This removes the need to checksum every incoming/outgoing packet and will reduce 452 // latency and CPU usage. This feature is not backwards compatible so is disabled by default 453 func (e *SettingEngine) EnableSCTPZeroChecksum(isEnabled bool) { 454 e.sctp.enableZeroChecksum = isEnabled 455 } 456 457 // SetDTLSCustomerCipherSuites allows the user to specify a list of DTLS CipherSuites. 458 // This allow usage of Ciphers that are reserved for private usage. 459 func (e *SettingEngine) SetDTLSCustomerCipherSuites(customCipherSuites func() []dtls.CipherSuite) { 460 e.dtls.customCipherSuites = customCipherSuites 461 } 462 463 // SetDTLSClientHelloMessageHook if not nil, is called when a DTLS Client Hello message is sent 464 // from a client. The returned handshake message replaces the original message. 465 func (e *SettingEngine) SetDTLSClientHelloMessageHook(hook func(handshake.MessageClientHello) handshake.Message) { 466 e.dtls.clientHelloMessageHook = hook 467 } 468 469 // SetDTLSServerHelloMessageHook if not nil, is called when a DTLS Server Hello message is sent 470 // from a client. The returned handshake message replaces the original message. 471 func (e *SettingEngine) SetDTLSServerHelloMessageHook(hook func(handshake.MessageServerHello) handshake.Message) { 472 e.dtls.serverHelloMessageHook = hook 473 } 474 475 // SetDTLSCertificateRequestMessageHook if not nil, is called when a DTLS Certificate Request message is sent 476 // from a client. The returned handshake message replaces the original message. 477 func (e *SettingEngine) SetDTLSCertificateRequestMessageHook(hook func(handshake.MessageCertificateRequest) handshake.Message) { 478 e.dtls.certificateRequestMessageHook = hook 479 } 480 481 // SetSCTPRTOMax sets the maximum retransmission timeout. 482 // Leave this 0 for the default timeout. 483 func (e *SettingEngine) SetSCTPRTOMax(rtoMax time.Duration) { 484 e.sctp.rtoMax = rtoMax 485 } 486 487 // SetICEBindingRequestHandler sets a callback that is fired on a STUN BindingRequest 488 // This allows users to do things like 489 // - Log incoming Binding Requests for debugging 490 // - Implement draft-thatcher-ice-renomination 491 // - Implement custom CandidatePair switching logic 492 func (e *SettingEngine) SetICEBindingRequestHandler(bindingRequestHandler func(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool) { 493 e.iceBindingRequestHandler = bindingRequestHandler 494 } 495 496 // SetFireOnTrackBeforeFirstRTP sets if firing the OnTrack event should happen 497 // before any RTP packets are received. Setting this to true will 498 // have the Track's Codec and PayloadTypes be initially set to their 499 // zero values in the OnTrack handler. 500 // Note: This does not yet affect simulcast tracks. 501 func (e *SettingEngine) SetFireOnTrackBeforeFirstRTP(fireOnTrackBeforeFirstRTP bool) { 502 e.fireOnTrackBeforeFirstRTP = fireOnTrackBeforeFirstRTP 503 }