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  }