github.com/pion/webrtc/v4@v4.0.1/peerconnection.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  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"errors"
    14  	"fmt"
    15  	"io"
    16  	"strconv"
    17  	"strings"
    18  	"sync"
    19  	"sync/atomic"
    20  	"time"
    21  
    22  	"github.com/pion/ice/v4"
    23  	"github.com/pion/interceptor"
    24  	"github.com/pion/logging"
    25  	"github.com/pion/rtcp"
    26  	"github.com/pion/sdp/v3"
    27  	"github.com/pion/srtp/v3"
    28  	"github.com/pion/webrtc/v4/internal/util"
    29  	"github.com/pion/webrtc/v4/pkg/rtcerr"
    30  )
    31  
    32  // PeerConnection represents a WebRTC connection that establishes a
    33  // peer-to-peer communications with another PeerConnection instance in a
    34  // browser, or to another endpoint implementing the required protocols.
    35  type PeerConnection struct {
    36  	statsID string
    37  	mu      sync.RWMutex
    38  
    39  	sdpOrigin sdp.Origin
    40  
    41  	// ops is an operations queue which will ensure the enqueued actions are
    42  	// executed in order. It is used for asynchronously, but serially processing
    43  	// remote and local descriptions
    44  	ops *operations
    45  
    46  	configuration Configuration
    47  
    48  	currentLocalDescription  *SessionDescription
    49  	pendingLocalDescription  *SessionDescription
    50  	currentRemoteDescription *SessionDescription
    51  	pendingRemoteDescription *SessionDescription
    52  	signalingState           SignalingState
    53  	iceConnectionState       atomic.Value // ICEConnectionState
    54  	connectionState          atomic.Value // PeerConnectionState
    55  
    56  	idpLoginURL *string
    57  
    58  	isClosed                                *atomicBool
    59  	isGracefullyClosingOrClosed             bool
    60  	isCloseDone                             chan struct{}
    61  	isGracefulCloseDone                     chan struct{}
    62  	isNegotiationNeeded                     *atomicBool
    63  	updateNegotiationNeededFlagOnEmptyChain *atomicBool
    64  
    65  	lastOffer  string
    66  	lastAnswer string
    67  
    68  	// a value containing the last known greater mid value
    69  	// we internally generate mids as numbers. Needed since JSEP
    70  	// requires that when reusing a media section a new unique mid
    71  	// should be defined (see JSEP 3.4.1).
    72  	greaterMid int
    73  
    74  	rtpTransceivers        []*RTPTransceiver
    75  	nonMediaBandwidthProbe atomic.Value // RTPReceiver
    76  
    77  	onSignalingStateChangeHandler     func(SignalingState)
    78  	onICEConnectionStateChangeHandler atomic.Value // func(ICEConnectionState)
    79  	onConnectionStateChangeHandler    atomic.Value // func(PeerConnectionState)
    80  	onTrackHandler                    func(*TrackRemote, *RTPReceiver)
    81  	onDataChannelHandler              func(*DataChannel)
    82  	onNegotiationNeededHandler        atomic.Value // func()
    83  
    84  	iceGatherer   *ICEGatherer
    85  	iceTransport  *ICETransport
    86  	dtlsTransport *DTLSTransport
    87  	sctpTransport *SCTPTransport
    88  
    89  	// A reference to the associated API state used by this connection
    90  	api *API
    91  	log logging.LeveledLogger
    92  
    93  	interceptorRTCPWriter interceptor.RTCPWriter
    94  }
    95  
    96  // NewPeerConnection creates a PeerConnection with the default codecs and interceptors.
    97  //
    98  // If you wish to customize the set of available codecs and/or the set of active interceptors,
    99  // create an API with a custom MediaEngine and/or interceptor.Registry,
   100  // then call API.NewPeerConnection() instead of this function.
   101  func NewPeerConnection(configuration Configuration) (*PeerConnection, error) {
   102  	api := NewAPI()
   103  	return api.NewPeerConnection(configuration)
   104  }
   105  
   106  // NewPeerConnection creates a new PeerConnection with the provided configuration against the received API object
   107  func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, error) {
   108  	// https://w3c.github.io/webrtc-pc/#constructor (Step #2)
   109  	// Some variables defined explicitly despite their implicit zero values to
   110  	// allow better readability to understand what is happening.
   111  
   112  	pc := &PeerConnection{
   113  		statsID: fmt.Sprintf("PeerConnection-%d", time.Now().UnixNano()),
   114  		configuration: Configuration{
   115  			ICEServers:           []ICEServer{},
   116  			ICETransportPolicy:   ICETransportPolicyAll,
   117  			BundlePolicy:         BundlePolicyBalanced,
   118  			RTCPMuxPolicy:        RTCPMuxPolicyRequire,
   119  			Certificates:         []Certificate{},
   120  			ICECandidatePoolSize: 0,
   121  		},
   122  		isClosed:                                &atomicBool{},
   123  		isCloseDone:                             make(chan struct{}),
   124  		isGracefulCloseDone:                     make(chan struct{}),
   125  		isNegotiationNeeded:                     &atomicBool{},
   126  		updateNegotiationNeededFlagOnEmptyChain: &atomicBool{},
   127  		lastOffer:                               "",
   128  		lastAnswer:                              "",
   129  		greaterMid:                              -1,
   130  		signalingState:                          SignalingStateStable,
   131  
   132  		api: api,
   133  		log: api.settingEngine.LoggerFactory.NewLogger("pc"),
   134  	}
   135  	pc.ops = newOperations(pc.updateNegotiationNeededFlagOnEmptyChain, pc.onNegotiationNeeded)
   136  
   137  	pc.iceConnectionState.Store(ICEConnectionStateNew)
   138  	pc.connectionState.Store(PeerConnectionStateNew)
   139  
   140  	i, err := api.interceptorRegistry.Build("")
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	pc.api = &API{
   146  		settingEngine: api.settingEngine,
   147  		interceptor:   i,
   148  	}
   149  
   150  	if api.settingEngine.disableMediaEngineCopy {
   151  		pc.api.mediaEngine = api.mediaEngine
   152  	} else {
   153  		pc.api.mediaEngine = api.mediaEngine.copy()
   154  	}
   155  
   156  	if err = pc.initConfiguration(configuration); err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	pc.iceGatherer, err = pc.createICEGatherer()
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	// Create the ice transport
   166  	iceTransport := pc.createICETransport()
   167  	pc.iceTransport = iceTransport
   168  
   169  	// Create the DTLS transport
   170  	dtlsTransport, err := pc.api.NewDTLSTransport(pc.iceTransport, pc.configuration.Certificates)
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  	pc.dtlsTransport = dtlsTransport
   175  
   176  	// Create the SCTP transport
   177  	pc.sctpTransport = pc.api.NewSCTPTransport(pc.dtlsTransport)
   178  
   179  	// Wire up the on datachannel handler
   180  	pc.sctpTransport.OnDataChannel(func(d *DataChannel) {
   181  		pc.mu.RLock()
   182  		handler := pc.onDataChannelHandler
   183  		pc.mu.RUnlock()
   184  		if handler != nil {
   185  			handler(d)
   186  		}
   187  	})
   188  
   189  	pc.interceptorRTCPWriter = pc.api.interceptor.BindRTCPWriter(interceptor.RTCPWriterFunc(pc.writeRTCP))
   190  
   191  	return pc, nil
   192  }
   193  
   194  // initConfiguration defines validation of the specified Configuration and
   195  // its assignment to the internal configuration variable. This function differs
   196  // from its SetConfiguration counterpart because most of the checks do not
   197  // include verification statements related to the existing state. Thus the
   198  // function describes only minor verification of some the struct variables.
   199  func (pc *PeerConnection) initConfiguration(configuration Configuration) error {
   200  	if configuration.PeerIdentity != "" {
   201  		pc.configuration.PeerIdentity = configuration.PeerIdentity
   202  	}
   203  
   204  	// https://www.w3.org/TR/webrtc/#constructor (step #3)
   205  	if len(configuration.Certificates) > 0 {
   206  		now := time.Now()
   207  		for _, x509Cert := range configuration.Certificates {
   208  			if !x509Cert.Expires().IsZero() && now.After(x509Cert.Expires()) {
   209  				return &rtcerr.InvalidAccessError{Err: ErrCertificateExpired}
   210  			}
   211  			pc.configuration.Certificates = append(pc.configuration.Certificates, x509Cert)
   212  		}
   213  	} else {
   214  		sk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   215  		if err != nil {
   216  			return &rtcerr.UnknownError{Err: err}
   217  		}
   218  		certificate, err := GenerateCertificate(sk)
   219  		if err != nil {
   220  			return err
   221  		}
   222  		pc.configuration.Certificates = []Certificate{*certificate}
   223  	}
   224  
   225  	if configuration.BundlePolicy != BundlePolicyUnknown {
   226  		pc.configuration.BundlePolicy = configuration.BundlePolicy
   227  	}
   228  
   229  	if configuration.RTCPMuxPolicy != RTCPMuxPolicyUnknown {
   230  		pc.configuration.RTCPMuxPolicy = configuration.RTCPMuxPolicy
   231  	}
   232  
   233  	if configuration.ICECandidatePoolSize != 0 {
   234  		pc.configuration.ICECandidatePoolSize = configuration.ICECandidatePoolSize
   235  	}
   236  
   237  	pc.configuration.ICETransportPolicy = configuration.ICETransportPolicy
   238  	pc.configuration.SDPSemantics = configuration.SDPSemantics
   239  
   240  	sanitizedICEServers := configuration.getICEServers()
   241  	if len(sanitizedICEServers) > 0 {
   242  		for _, server := range sanitizedICEServers {
   243  			if err := server.validate(); err != nil {
   244  				return err
   245  			}
   246  		}
   247  		pc.configuration.ICEServers = sanitizedICEServers
   248  	}
   249  
   250  	return nil
   251  }
   252  
   253  // OnSignalingStateChange sets an event handler which is invoked when the
   254  // peer connection's signaling state changes
   255  func (pc *PeerConnection) OnSignalingStateChange(f func(SignalingState)) {
   256  	pc.mu.Lock()
   257  	defer pc.mu.Unlock()
   258  	pc.onSignalingStateChangeHandler = f
   259  }
   260  
   261  func (pc *PeerConnection) onSignalingStateChange(newState SignalingState) {
   262  	pc.mu.RLock()
   263  	handler := pc.onSignalingStateChangeHandler
   264  	pc.mu.RUnlock()
   265  
   266  	pc.log.Infof("signaling state changed to %s", newState)
   267  	if handler != nil {
   268  		go handler(newState)
   269  	}
   270  }
   271  
   272  // OnDataChannel sets an event handler which is invoked when a data
   273  // channel message arrives from a remote peer.
   274  func (pc *PeerConnection) OnDataChannel(f func(*DataChannel)) {
   275  	pc.mu.Lock()
   276  	defer pc.mu.Unlock()
   277  	pc.onDataChannelHandler = f
   278  }
   279  
   280  // OnNegotiationNeeded sets an event handler which is invoked when
   281  // a change has occurred which requires session negotiation
   282  func (pc *PeerConnection) OnNegotiationNeeded(f func()) {
   283  	pc.onNegotiationNeededHandler.Store(f)
   284  }
   285  
   286  // onNegotiationNeeded enqueues negotiationNeededOp if necessary
   287  // caller of this method should hold `pc.mu` lock
   288  // https://www.w3.org/TR/webrtc/#dfn-update-the-negotiation-needed-flag
   289  func (pc *PeerConnection) onNegotiationNeeded() {
   290  	// 4.7.3.1 If the length of connection.[[Operations]] is not 0, then set
   291  	// connection.[[UpdateNegotiationNeededFlagOnEmptyChain]] to true, and abort these steps.
   292  	if !pc.ops.IsEmpty() {
   293  		pc.updateNegotiationNeededFlagOnEmptyChain.set(true)
   294  		return
   295  	}
   296  	pc.ops.Enqueue(pc.negotiationNeededOp)
   297  }
   298  
   299  // https://www.w3.org/TR/webrtc/#dfn-update-the-negotiation-needed-flag
   300  func (pc *PeerConnection) negotiationNeededOp() {
   301  	// 4.7.3.2.1 If connection.[[IsClosed]] is true, abort these steps.
   302  	if pc.isClosed.get() {
   303  		return
   304  	}
   305  
   306  	// 4.7.3.2.2 If the length of connection.[[Operations]] is not 0,
   307  	// then set connection.[[UpdateNegotiationNeededFlagOnEmptyChain]] to
   308  	// true, and abort these steps.
   309  	if !pc.ops.IsEmpty() {
   310  		pc.updateNegotiationNeededFlagOnEmptyChain.set(true)
   311  		return
   312  	}
   313  
   314  	// 4.7.3.2.3 If connection's signaling state is not "stable", abort these steps.
   315  	if pc.SignalingState() != SignalingStateStable {
   316  		return
   317  	}
   318  
   319  	// 4.7.3.2.4 If the result of checking if negotiation is needed is false,
   320  	// clear the negotiation-needed flag by setting connection.[[NegotiationNeeded]]
   321  	// to false, and abort these steps.
   322  	if !pc.checkNegotiationNeeded() {
   323  		pc.isNegotiationNeeded.set(false)
   324  		return
   325  	}
   326  
   327  	// 4.7.3.2.5 If connection.[[NegotiationNeeded]] is already true, abort these steps.
   328  	if pc.isNegotiationNeeded.get() {
   329  		return
   330  	}
   331  
   332  	// 4.7.3.2.6 Set connection.[[NegotiationNeeded]] to true.
   333  	pc.isNegotiationNeeded.set(true)
   334  
   335  	// 4.7.3.2.7 Fire an event named negotiationneeded at connection.
   336  	if handler, ok := pc.onNegotiationNeededHandler.Load().(func()); ok && handler != nil {
   337  		handler()
   338  	}
   339  }
   340  
   341  func (pc *PeerConnection) checkNegotiationNeeded() bool { //nolint:gocognit
   342  	// To check if negotiation is needed for connection, perform the following checks:
   343  	// Skip 1, 2 steps
   344  	// Step 3
   345  	pc.mu.Lock()
   346  	defer pc.mu.Unlock()
   347  
   348  	localDesc := pc.currentLocalDescription
   349  	remoteDesc := pc.currentRemoteDescription
   350  
   351  	if localDesc == nil {
   352  		return true
   353  	}
   354  
   355  	pc.sctpTransport.lock.Lock()
   356  	lenDataChannel := len(pc.sctpTransport.dataChannels)
   357  	pc.sctpTransport.lock.Unlock()
   358  
   359  	if lenDataChannel != 0 && haveDataChannel(localDesc) == nil {
   360  		return true
   361  	}
   362  
   363  	for _, t := range pc.rtpTransceivers {
   364  		// https://www.w3.org/TR/webrtc/#dfn-update-the-negotiation-needed-flag
   365  		// Step 5.1
   366  		// if t.stopping && !t.stopped {
   367  		// 	return true
   368  		// }
   369  		m := getByMid(t.Mid(), localDesc)
   370  		// Step 5.2
   371  		if !t.stopped && m == nil {
   372  			return true
   373  		}
   374  		if !t.stopped && m != nil {
   375  			// Step 5.3.1
   376  			if t.Direction() == RTPTransceiverDirectionSendrecv || t.Direction() == RTPTransceiverDirectionSendonly {
   377  				descMsid, okMsid := m.Attribute(sdp.AttrKeyMsid)
   378  				sender := t.Sender()
   379  				if sender == nil {
   380  					return true
   381  				}
   382  				track := sender.Track()
   383  				if track == nil {
   384  					// Situation when sender's track is nil could happen when
   385  					// a) replaceTrack(nil) is called
   386  					// b) removeTrack() is called, changing the transceiver's direction to inactive
   387  					// As t.Direction() in this branch is either sendrecv or sendonly, we believe (a) option is the case
   388  					// As calling replaceTrack does not require renegotiation, we skip check for this transceiver
   389  					continue
   390  				}
   391  				if !okMsid || descMsid != track.StreamID()+" "+track.ID() {
   392  					return true
   393  				}
   394  			}
   395  			switch localDesc.Type {
   396  			case SDPTypeOffer:
   397  				// Step 5.3.2
   398  				rm := getByMid(t.Mid(), remoteDesc)
   399  				if rm == nil {
   400  					return true
   401  				}
   402  
   403  				if getPeerDirection(m) != t.Direction() && getPeerDirection(rm) != t.Direction().Revers() {
   404  					return true
   405  				}
   406  			case SDPTypeAnswer:
   407  				// Step 5.3.3
   408  				if _, ok := m.Attribute(t.Direction().String()); !ok {
   409  					return true
   410  				}
   411  			default:
   412  			}
   413  		}
   414  		// Step 5.4
   415  		if t.stopped && t.Mid() != "" {
   416  			if getByMid(t.Mid(), localDesc) != nil || getByMid(t.Mid(), remoteDesc) != nil {
   417  				return true
   418  			}
   419  		}
   420  	}
   421  	// Step 6
   422  	return false
   423  }
   424  
   425  // OnICECandidate sets an event handler which is invoked when a new ICE
   426  // candidate is found.
   427  // ICE candidate gathering only begins when SetLocalDescription or
   428  // SetRemoteDescription is called.
   429  // Take note that the handler will be called with a nil pointer when
   430  // gathering is finished.
   431  func (pc *PeerConnection) OnICECandidate(f func(*ICECandidate)) {
   432  	pc.iceGatherer.OnLocalCandidate(f)
   433  }
   434  
   435  // OnICEGatheringStateChange sets an event handler which is invoked when the
   436  // ICE candidate gathering state has changed.
   437  func (pc *PeerConnection) OnICEGatheringStateChange(f func(ICEGatheringState)) {
   438  	pc.iceGatherer.OnStateChange(
   439  		func(gathererState ICEGathererState) {
   440  			switch gathererState {
   441  			case ICEGathererStateGathering:
   442  				f(ICEGatheringStateGathering)
   443  			case ICEGathererStateComplete:
   444  				f(ICEGatheringStateComplete)
   445  			default:
   446  				// Other states ignored
   447  			}
   448  		})
   449  }
   450  
   451  // OnTrack sets an event handler which is called when remote track
   452  // arrives from a remote peer.
   453  func (pc *PeerConnection) OnTrack(f func(*TrackRemote, *RTPReceiver)) {
   454  	pc.mu.Lock()
   455  	defer pc.mu.Unlock()
   456  	pc.onTrackHandler = f
   457  }
   458  
   459  func (pc *PeerConnection) onTrack(t *TrackRemote, r *RTPReceiver) {
   460  	pc.mu.RLock()
   461  	handler := pc.onTrackHandler
   462  	pc.mu.RUnlock()
   463  
   464  	pc.log.Debugf("got new track: %+v", t)
   465  	if t != nil {
   466  		if handler != nil {
   467  			go handler(t, r)
   468  		} else {
   469  			pc.log.Warnf("OnTrack unset, unable to handle incoming media streams")
   470  		}
   471  	}
   472  }
   473  
   474  // OnICEConnectionStateChange sets an event handler which is called
   475  // when an ICE connection state is changed.
   476  func (pc *PeerConnection) OnICEConnectionStateChange(f func(ICEConnectionState)) {
   477  	pc.onICEConnectionStateChangeHandler.Store(f)
   478  }
   479  
   480  func (pc *PeerConnection) onICEConnectionStateChange(cs ICEConnectionState) {
   481  	pc.iceConnectionState.Store(cs)
   482  	pc.log.Infof("ICE connection state changed: %s", cs)
   483  	if handler, ok := pc.onICEConnectionStateChangeHandler.Load().(func(ICEConnectionState)); ok && handler != nil {
   484  		handler(cs)
   485  	}
   486  }
   487  
   488  // OnConnectionStateChange sets an event handler which is called
   489  // when the PeerConnectionState has changed
   490  func (pc *PeerConnection) OnConnectionStateChange(f func(PeerConnectionState)) {
   491  	pc.onConnectionStateChangeHandler.Store(f)
   492  }
   493  
   494  func (pc *PeerConnection) onConnectionStateChange(cs PeerConnectionState) {
   495  	pc.connectionState.Store(cs)
   496  	pc.log.Infof("peer connection state changed: %s", cs)
   497  	if handler, ok := pc.onConnectionStateChangeHandler.Load().(func(PeerConnectionState)); ok && handler != nil {
   498  		go handler(cs)
   499  	}
   500  }
   501  
   502  // SetConfiguration updates the configuration of this PeerConnection object.
   503  func (pc *PeerConnection) SetConfiguration(configuration Configuration) error { //nolint:gocognit
   504  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-setconfiguration (step #2)
   505  	if pc.isClosed.get() {
   506  		return &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
   507  	}
   508  
   509  	// https://www.w3.org/TR/webrtc/#set-the-configuration (step #3)
   510  	if configuration.PeerIdentity != "" {
   511  		if configuration.PeerIdentity != pc.configuration.PeerIdentity {
   512  			return &rtcerr.InvalidModificationError{Err: ErrModifyingPeerIdentity}
   513  		}
   514  		pc.configuration.PeerIdentity = configuration.PeerIdentity
   515  	}
   516  
   517  	// https://www.w3.org/TR/webrtc/#set-the-configuration (step #4)
   518  	if len(configuration.Certificates) > 0 {
   519  		if len(configuration.Certificates) != len(pc.configuration.Certificates) {
   520  			return &rtcerr.InvalidModificationError{Err: ErrModifyingCertificates}
   521  		}
   522  
   523  		for i, certificate := range configuration.Certificates {
   524  			if !pc.configuration.Certificates[i].Equals(certificate) {
   525  				return &rtcerr.InvalidModificationError{Err: ErrModifyingCertificates}
   526  			}
   527  		}
   528  		pc.configuration.Certificates = configuration.Certificates
   529  	}
   530  
   531  	// https://www.w3.org/TR/webrtc/#set-the-configuration (step #5)
   532  	if configuration.BundlePolicy != BundlePolicyUnknown {
   533  		if configuration.BundlePolicy != pc.configuration.BundlePolicy {
   534  			return &rtcerr.InvalidModificationError{Err: ErrModifyingBundlePolicy}
   535  		}
   536  		pc.configuration.BundlePolicy = configuration.BundlePolicy
   537  	}
   538  
   539  	// https://www.w3.org/TR/webrtc/#set-the-configuration (step #6)
   540  	if configuration.RTCPMuxPolicy != RTCPMuxPolicyUnknown {
   541  		if configuration.RTCPMuxPolicy != pc.configuration.RTCPMuxPolicy {
   542  			return &rtcerr.InvalidModificationError{Err: ErrModifyingRTCPMuxPolicy}
   543  		}
   544  		pc.configuration.RTCPMuxPolicy = configuration.RTCPMuxPolicy
   545  	}
   546  
   547  	// https://www.w3.org/TR/webrtc/#set-the-configuration (step #7)
   548  	if configuration.ICECandidatePoolSize != 0 {
   549  		if pc.configuration.ICECandidatePoolSize != configuration.ICECandidatePoolSize &&
   550  			pc.LocalDescription() != nil {
   551  			return &rtcerr.InvalidModificationError{Err: ErrModifyingICECandidatePoolSize}
   552  		}
   553  		pc.configuration.ICECandidatePoolSize = configuration.ICECandidatePoolSize
   554  	}
   555  
   556  	// https://www.w3.org/TR/webrtc/#set-the-configuration (step #8)
   557  	pc.configuration.ICETransportPolicy = configuration.ICETransportPolicy
   558  
   559  	// https://www.w3.org/TR/webrtc/#set-the-configuration (step #11)
   560  	if len(configuration.ICEServers) > 0 {
   561  		// https://www.w3.org/TR/webrtc/#set-the-configuration (step #11.3)
   562  		for _, server := range configuration.ICEServers {
   563  			if err := server.validate(); err != nil {
   564  				return err
   565  			}
   566  		}
   567  		pc.configuration.ICEServers = configuration.ICEServers
   568  	}
   569  	return nil
   570  }
   571  
   572  // GetConfiguration returns a Configuration object representing the current
   573  // configuration of this PeerConnection object. The returned object is a
   574  // copy and direct mutation on it will not take affect until SetConfiguration
   575  // has been called with Configuration passed as its only argument.
   576  // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-getconfiguration
   577  func (pc *PeerConnection) GetConfiguration() Configuration {
   578  	return pc.configuration
   579  }
   580  
   581  func (pc *PeerConnection) getStatsID() string {
   582  	pc.mu.RLock()
   583  	defer pc.mu.RUnlock()
   584  	return pc.statsID
   585  }
   586  
   587  // hasLocalDescriptionChanged returns whether local media (rtpTransceivers) has changed
   588  // caller of this method should hold `pc.mu` lock
   589  func (pc *PeerConnection) hasLocalDescriptionChanged(desc *SessionDescription) bool {
   590  	for _, t := range pc.rtpTransceivers {
   591  		m := getByMid(t.Mid(), desc)
   592  		if m == nil {
   593  			return true
   594  		}
   595  
   596  		if getPeerDirection(m) != t.Direction() {
   597  			return true
   598  		}
   599  	}
   600  	return false
   601  }
   602  
   603  // CreateOffer starts the PeerConnection and generates the localDescription
   604  // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer
   605  func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription, error) { //nolint:gocognit
   606  	useIdentity := pc.idpLoginURL != nil
   607  	switch {
   608  	case useIdentity:
   609  		return SessionDescription{}, errIdentityProviderNotImplemented
   610  	case pc.isClosed.get():
   611  		return SessionDescription{}, &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
   612  	}
   613  
   614  	if options != nil && options.ICERestart {
   615  		if err := pc.iceTransport.restart(); err != nil {
   616  			return SessionDescription{}, err
   617  		}
   618  	}
   619  
   620  	var (
   621  		d     *sdp.SessionDescription
   622  		offer SessionDescription
   623  		err   error
   624  	)
   625  
   626  	// This may be necessary to recompute if, for example, createOffer was called when only an
   627  	// audio RTCRtpTransceiver was added to connection, but while performing the in-parallel
   628  	// steps to create an offer, a video RTCRtpTransceiver was added, requiring additional
   629  	// inspection of video system resources.
   630  	count := 0
   631  	pc.mu.Lock()
   632  	defer pc.mu.Unlock()
   633  	for {
   634  		// We cache current transceivers to ensure they aren't
   635  		// mutated during offer generation. We later check if they have
   636  		// been mutated and recompute the offer if necessary.
   637  		currentTransceivers := pc.rtpTransceivers
   638  
   639  		// in-parallel steps to create an offer
   640  		// https://w3c.github.io/webrtc-pc/#dfn-in-parallel-steps-to-create-an-offer
   641  		isPlanB := pc.configuration.SDPSemantics == SDPSemanticsPlanB
   642  		if pc.currentRemoteDescription != nil && isPlanB {
   643  			isPlanB = descriptionPossiblyPlanB(pc.currentRemoteDescription)
   644  		}
   645  
   646  		// include unmatched local transceivers
   647  		if !isPlanB {
   648  			// update the greater mid if the remote description provides a greater one
   649  			if pc.currentRemoteDescription != nil {
   650  				var numericMid int
   651  				for _, media := range pc.currentRemoteDescription.parsed.MediaDescriptions {
   652  					mid := getMidValue(media)
   653  					if mid == "" {
   654  						continue
   655  					}
   656  					numericMid, err = strconv.Atoi(mid)
   657  					if err != nil {
   658  						continue
   659  					}
   660  					if numericMid > pc.greaterMid {
   661  						pc.greaterMid = numericMid
   662  					}
   663  				}
   664  			}
   665  			for _, t := range currentTransceivers {
   666  				if mid := t.Mid(); mid != "" {
   667  					numericMid, errMid := strconv.Atoi(mid)
   668  					if errMid == nil {
   669  						if numericMid > pc.greaterMid {
   670  							pc.greaterMid = numericMid
   671  						}
   672  					}
   673  					continue
   674  				}
   675  				pc.greaterMid++
   676  				err = t.SetMid(strconv.Itoa(pc.greaterMid))
   677  				if err != nil {
   678  					return SessionDescription{}, err
   679  				}
   680  			}
   681  		}
   682  
   683  		if pc.currentRemoteDescription == nil {
   684  			d, err = pc.generateUnmatchedSDP(currentTransceivers, useIdentity)
   685  		} else {
   686  			d, err = pc.generateMatchedSDP(currentTransceivers, useIdentity, true /*includeUnmatched */, connectionRoleFromDtlsRole(defaultDtlsRoleOffer))
   687  		}
   688  
   689  		if err != nil {
   690  			return SessionDescription{}, err
   691  		}
   692  
   693  		updateSDPOrigin(&pc.sdpOrigin, d)
   694  		sdpBytes, err := d.Marshal()
   695  		if err != nil {
   696  			return SessionDescription{}, err
   697  		}
   698  
   699  		offer = SessionDescription{
   700  			Type:   SDPTypeOffer,
   701  			SDP:    string(sdpBytes),
   702  			parsed: d,
   703  		}
   704  
   705  		// Verify local media hasn't changed during offer
   706  		// generation. Recompute if necessary
   707  		if isPlanB || !pc.hasLocalDescriptionChanged(&offer) {
   708  			break
   709  		}
   710  		count++
   711  		if count >= 128 {
   712  			return SessionDescription{}, errExcessiveRetries
   713  		}
   714  	}
   715  
   716  	pc.lastOffer = offer.SDP
   717  	return offer, nil
   718  }
   719  
   720  func (pc *PeerConnection) createICEGatherer() (*ICEGatherer, error) {
   721  	g, err := pc.api.NewICEGatherer(ICEGatherOptions{
   722  		ICEServers:      pc.configuration.getICEServers(),
   723  		ICEGatherPolicy: pc.configuration.ICETransportPolicy,
   724  	})
   725  	if err != nil {
   726  		return nil, err
   727  	}
   728  
   729  	return g, nil
   730  }
   731  
   732  // Update the PeerConnectionState given the state of relevant transports
   733  // https://www.w3.org/TR/webrtc/#rtcpeerconnectionstate-enum
   734  func (pc *PeerConnection) updateConnectionState(iceConnectionState ICEConnectionState, dtlsTransportState DTLSTransportState) {
   735  	connectionState := PeerConnectionStateNew
   736  	switch {
   737  	// The RTCPeerConnection object's [[IsClosed]] slot is true.
   738  	case pc.isClosed.get():
   739  		connectionState = PeerConnectionStateClosed
   740  
   741  	// Any of the RTCIceTransports or RTCDtlsTransports are in a "failed" state.
   742  	case iceConnectionState == ICEConnectionStateFailed || dtlsTransportState == DTLSTransportStateFailed:
   743  		connectionState = PeerConnectionStateFailed
   744  
   745  	// Any of the RTCIceTransports or RTCDtlsTransports are in the "disconnected"
   746  	// state and none of them are in the "failed" or "connecting" or "checking" state.  */
   747  	case iceConnectionState == ICEConnectionStateDisconnected:
   748  		connectionState = PeerConnectionStateDisconnected
   749  
   750  	// None of the previous states apply and all RTCIceTransports are in the "new" or "closed" state,
   751  	// and all RTCDtlsTransports are in the "new" or "closed" state, or there are no transports.
   752  	case (iceConnectionState == ICEConnectionStateNew || iceConnectionState == ICEConnectionStateClosed) &&
   753  		(dtlsTransportState == DTLSTransportStateNew || dtlsTransportState == DTLSTransportStateClosed):
   754  		connectionState = PeerConnectionStateNew
   755  
   756  	// None of the previous states apply and any RTCIceTransport is in the "new" or "checking" state or
   757  	// any RTCDtlsTransport is in the "new" or "connecting" state.
   758  	case (iceConnectionState == ICEConnectionStateNew || iceConnectionState == ICEConnectionStateChecking) ||
   759  		(dtlsTransportState == DTLSTransportStateNew || dtlsTransportState == DTLSTransportStateConnecting):
   760  		connectionState = PeerConnectionStateConnecting
   761  
   762  	// All RTCIceTransports and RTCDtlsTransports are in the "connected", "completed" or "closed"
   763  	// state and all RTCDtlsTransports are in the "connected" or "closed" state.
   764  	case (iceConnectionState == ICEConnectionStateConnected || iceConnectionState == ICEConnectionStateCompleted || iceConnectionState == ICEConnectionStateClosed) &&
   765  		(dtlsTransportState == DTLSTransportStateConnected || dtlsTransportState == DTLSTransportStateClosed):
   766  		connectionState = PeerConnectionStateConnected
   767  	}
   768  
   769  	if pc.connectionState.Load() == connectionState {
   770  		return
   771  	}
   772  
   773  	pc.onConnectionStateChange(connectionState)
   774  }
   775  
   776  func (pc *PeerConnection) createICETransport() *ICETransport {
   777  	t := pc.api.NewICETransport(pc.iceGatherer)
   778  	t.internalOnConnectionStateChangeHandler.Store(func(state ICETransportState) {
   779  		var cs ICEConnectionState
   780  		switch state {
   781  		case ICETransportStateNew:
   782  			cs = ICEConnectionStateNew
   783  		case ICETransportStateChecking:
   784  			cs = ICEConnectionStateChecking
   785  		case ICETransportStateConnected:
   786  			cs = ICEConnectionStateConnected
   787  		case ICETransportStateCompleted:
   788  			cs = ICEConnectionStateCompleted
   789  		case ICETransportStateFailed:
   790  			cs = ICEConnectionStateFailed
   791  		case ICETransportStateDisconnected:
   792  			cs = ICEConnectionStateDisconnected
   793  		case ICETransportStateClosed:
   794  			cs = ICEConnectionStateClosed
   795  		default:
   796  			pc.log.Warnf("OnConnectionStateChange: unhandled ICE state: %s", state)
   797  			return
   798  		}
   799  		pc.onICEConnectionStateChange(cs)
   800  		pc.updateConnectionState(cs, pc.dtlsTransport.State())
   801  	})
   802  
   803  	return t
   804  }
   805  
   806  // CreateAnswer starts the PeerConnection and generates the localDescription
   807  func (pc *PeerConnection) CreateAnswer(*AnswerOptions) (SessionDescription, error) {
   808  	useIdentity := pc.idpLoginURL != nil
   809  	remoteDesc := pc.RemoteDescription()
   810  	switch {
   811  	case remoteDesc == nil:
   812  		return SessionDescription{}, &rtcerr.InvalidStateError{Err: ErrNoRemoteDescription}
   813  	case useIdentity:
   814  		return SessionDescription{}, errIdentityProviderNotImplemented
   815  	case pc.isClosed.get():
   816  		return SessionDescription{}, &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
   817  	case pc.signalingState.Get() != SignalingStateHaveRemoteOffer && pc.signalingState.Get() != SignalingStateHaveLocalPranswer:
   818  		return SessionDescription{}, &rtcerr.InvalidStateError{Err: ErrIncorrectSignalingState}
   819  	}
   820  
   821  	connectionRole := connectionRoleFromDtlsRole(pc.api.settingEngine.answeringDTLSRole)
   822  	if connectionRole == sdp.ConnectionRole(0) {
   823  		connectionRole = connectionRoleFromDtlsRole(defaultDtlsRoleAnswer)
   824  
   825  		// If one of the agents is lite and the other one is not, the lite agent must be the controlled agent.
   826  		// If both or neither agents are lite the offering agent is controlling.
   827  		// RFC 8445 S6.1.1
   828  		if isIceLiteSet(remoteDesc.parsed) && !pc.api.settingEngine.candidates.ICELite {
   829  			connectionRole = connectionRoleFromDtlsRole(DTLSRoleServer)
   830  		}
   831  	}
   832  	pc.mu.Lock()
   833  	defer pc.mu.Unlock()
   834  
   835  	d, err := pc.generateMatchedSDP(pc.rtpTransceivers, useIdentity, false /*includeUnmatched */, connectionRole)
   836  	if err != nil {
   837  		return SessionDescription{}, err
   838  	}
   839  
   840  	updateSDPOrigin(&pc.sdpOrigin, d)
   841  	sdpBytes, err := d.Marshal()
   842  	if err != nil {
   843  		return SessionDescription{}, err
   844  	}
   845  
   846  	desc := SessionDescription{
   847  		Type:   SDPTypeAnswer,
   848  		SDP:    string(sdpBytes),
   849  		parsed: d,
   850  	}
   851  	pc.lastAnswer = desc.SDP
   852  	return desc, nil
   853  }
   854  
   855  // 4.4.1.6 Set the SessionDescription
   856  func (pc *PeerConnection) setDescription(sd *SessionDescription, op stateChangeOp) error { //nolint:gocognit
   857  	switch {
   858  	case pc.isClosed.get():
   859  		return &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
   860  	case NewSDPType(sd.Type.String()) == SDPTypeUnknown:
   861  		return &rtcerr.TypeError{Err: fmt.Errorf("%w: '%d' is not a valid enum value of type SDPType", errPeerConnSDPTypeInvalidValue, sd.Type)}
   862  	}
   863  
   864  	nextState, err := func() (SignalingState, error) {
   865  		pc.mu.Lock()
   866  		defer pc.mu.Unlock()
   867  
   868  		cur := pc.SignalingState()
   869  		setLocal := stateChangeOpSetLocal
   870  		setRemote := stateChangeOpSetRemote
   871  		newSDPDoesNotMatchOffer := &rtcerr.InvalidModificationError{Err: errSDPDoesNotMatchOffer}
   872  		newSDPDoesNotMatchAnswer := &rtcerr.InvalidModificationError{Err: errSDPDoesNotMatchAnswer}
   873  
   874  		var nextState SignalingState
   875  		var err error
   876  		switch op {
   877  		case setLocal:
   878  			switch sd.Type {
   879  			// stable->SetLocal(offer)->have-local-offer
   880  			case SDPTypeOffer:
   881  				if sd.SDP != pc.lastOffer {
   882  					return nextState, newSDPDoesNotMatchOffer
   883  				}
   884  				nextState, err = checkNextSignalingState(cur, SignalingStateHaveLocalOffer, setLocal, sd.Type)
   885  				if err == nil {
   886  					pc.pendingLocalDescription = sd
   887  				}
   888  			// have-remote-offer->SetLocal(answer)->stable
   889  			// have-local-pranswer->SetLocal(answer)->stable
   890  			case SDPTypeAnswer:
   891  				if sd.SDP != pc.lastAnswer {
   892  					return nextState, newSDPDoesNotMatchAnswer
   893  				}
   894  				nextState, err = checkNextSignalingState(cur, SignalingStateStable, setLocal, sd.Type)
   895  				if err == nil {
   896  					pc.currentLocalDescription = sd
   897  					pc.currentRemoteDescription = pc.pendingRemoteDescription
   898  					pc.pendingRemoteDescription = nil
   899  					pc.pendingLocalDescription = nil
   900  				}
   901  			case SDPTypeRollback:
   902  				nextState, err = checkNextSignalingState(cur, SignalingStateStable, setLocal, sd.Type)
   903  				if err == nil {
   904  					pc.pendingLocalDescription = nil
   905  				}
   906  			// have-remote-offer->SetLocal(pranswer)->have-local-pranswer
   907  			case SDPTypePranswer:
   908  				if sd.SDP != pc.lastAnswer {
   909  					return nextState, newSDPDoesNotMatchAnswer
   910  				}
   911  				nextState, err = checkNextSignalingState(cur, SignalingStateHaveLocalPranswer, setLocal, sd.Type)
   912  				if err == nil {
   913  					pc.pendingLocalDescription = sd
   914  				}
   915  			default:
   916  				return nextState, &rtcerr.OperationError{Err: fmt.Errorf("%w: %s(%s)", errPeerConnStateChangeInvalid, op, sd.Type)}
   917  			}
   918  		case setRemote:
   919  			switch sd.Type {
   920  			// stable->SetRemote(offer)->have-remote-offer
   921  			case SDPTypeOffer:
   922  				nextState, err = checkNextSignalingState(cur, SignalingStateHaveRemoteOffer, setRemote, sd.Type)
   923  				if err == nil {
   924  					pc.pendingRemoteDescription = sd
   925  				}
   926  			// have-local-offer->SetRemote(answer)->stable
   927  			// have-remote-pranswer->SetRemote(answer)->stable
   928  			case SDPTypeAnswer:
   929  				nextState, err = checkNextSignalingState(cur, SignalingStateStable, setRemote, sd.Type)
   930  				if err == nil {
   931  					pc.currentRemoteDescription = sd
   932  					pc.currentLocalDescription = pc.pendingLocalDescription
   933  					pc.pendingRemoteDescription = nil
   934  					pc.pendingLocalDescription = nil
   935  				}
   936  			case SDPTypeRollback:
   937  				nextState, err = checkNextSignalingState(cur, SignalingStateStable, setRemote, sd.Type)
   938  				if err == nil {
   939  					pc.pendingRemoteDescription = nil
   940  				}
   941  			// have-local-offer->SetRemote(pranswer)->have-remote-pranswer
   942  			case SDPTypePranswer:
   943  				nextState, err = checkNextSignalingState(cur, SignalingStateHaveRemotePranswer, setRemote, sd.Type)
   944  				if err == nil {
   945  					pc.pendingRemoteDescription = sd
   946  				}
   947  			default:
   948  				return nextState, &rtcerr.OperationError{Err: fmt.Errorf("%w: %s(%s)", errPeerConnStateChangeInvalid, op, sd.Type)}
   949  			}
   950  		default:
   951  			return nextState, &rtcerr.OperationError{Err: fmt.Errorf("%w: %q", errPeerConnStateChangeUnhandled, op)}
   952  		}
   953  
   954  		return nextState, err
   955  	}()
   956  
   957  	if err == nil {
   958  		pc.signalingState.Set(nextState)
   959  		if pc.signalingState.Get() == SignalingStateStable {
   960  			pc.isNegotiationNeeded.set(false)
   961  			pc.mu.Lock()
   962  			pc.onNegotiationNeeded()
   963  			pc.mu.Unlock()
   964  		}
   965  		pc.onSignalingStateChange(nextState)
   966  	}
   967  	return err
   968  }
   969  
   970  // SetLocalDescription sets the SessionDescription of the local peer
   971  func (pc *PeerConnection) SetLocalDescription(desc SessionDescription) error {
   972  	if pc.isClosed.get() {
   973  		return &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
   974  	}
   975  
   976  	haveLocalDescription := pc.currentLocalDescription != nil
   977  
   978  	// JSEP 5.4
   979  	if desc.SDP == "" {
   980  		switch desc.Type {
   981  		case SDPTypeAnswer, SDPTypePranswer:
   982  			desc.SDP = pc.lastAnswer
   983  		case SDPTypeOffer:
   984  			desc.SDP = pc.lastOffer
   985  		default:
   986  			return &rtcerr.InvalidModificationError{
   987  				Err: fmt.Errorf("%w: %s", errPeerConnSDPTypeInvalidValueSetLocalDescription, desc.Type),
   988  			}
   989  		}
   990  	}
   991  
   992  	desc.parsed = &sdp.SessionDescription{}
   993  	if err := desc.parsed.UnmarshalString(desc.SDP); err != nil {
   994  		return err
   995  	}
   996  	if err := pc.setDescription(&desc, stateChangeOpSetLocal); err != nil {
   997  		return err
   998  	}
   999  
  1000  	currentTransceivers := append([]*RTPTransceiver{}, pc.GetTransceivers()...)
  1001  
  1002  	weAnswer := desc.Type == SDPTypeAnswer
  1003  	remoteDesc := pc.RemoteDescription()
  1004  	if weAnswer && remoteDesc != nil {
  1005  		_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, false)
  1006  		if err := pc.startRTPSenders(currentTransceivers); err != nil {
  1007  			return err
  1008  		}
  1009  		pc.configureRTPReceivers(haveLocalDescription, remoteDesc, currentTransceivers)
  1010  		pc.ops.Enqueue(func() {
  1011  			pc.startRTP(haveLocalDescription, remoteDesc, currentTransceivers)
  1012  		})
  1013  	}
  1014  
  1015  	if pc.iceGatherer.State() == ICEGathererStateNew {
  1016  		return pc.iceGatherer.Gather()
  1017  	}
  1018  	return nil
  1019  }
  1020  
  1021  // LocalDescription returns PendingLocalDescription if it is not null and
  1022  // otherwise it returns CurrentLocalDescription. This property is used to
  1023  // determine if SetLocalDescription has already been called.
  1024  // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-localdescription
  1025  func (pc *PeerConnection) LocalDescription() *SessionDescription {
  1026  	if pendingLocalDescription := pc.PendingLocalDescription(); pendingLocalDescription != nil {
  1027  		return pendingLocalDescription
  1028  	}
  1029  	return pc.CurrentLocalDescription()
  1030  }
  1031  
  1032  // SetRemoteDescription sets the SessionDescription of the remote peer
  1033  func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { //nolint:gocognit,gocyclo
  1034  	if pc.isClosed.get() {
  1035  		return &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
  1036  	}
  1037  
  1038  	isRenegotiation := pc.currentRemoteDescription != nil
  1039  
  1040  	if _, err := desc.Unmarshal(); err != nil {
  1041  		return err
  1042  	}
  1043  	if err := pc.setDescription(&desc, stateChangeOpSetRemote); err != nil {
  1044  		return err
  1045  	}
  1046  
  1047  	if err := pc.api.mediaEngine.updateFromRemoteDescription(*desc.parsed); err != nil {
  1048  		return err
  1049  	}
  1050  
  1051  	// Disable RTX/FEC on RTPSenders if the remote didn't support it
  1052  	for _, sender := range pc.GetSenders() {
  1053  		sender.configureRTXAndFEC()
  1054  	}
  1055  
  1056  	var t *RTPTransceiver
  1057  	localTransceivers := append([]*RTPTransceiver{}, pc.GetTransceivers()...)
  1058  	detectedPlanB := descriptionIsPlanB(pc.RemoteDescription(), pc.log)
  1059  	if pc.configuration.SDPSemantics != SDPSemanticsUnifiedPlan {
  1060  		detectedPlanB = descriptionPossiblyPlanB(pc.RemoteDescription())
  1061  	}
  1062  
  1063  	weOffer := desc.Type == SDPTypeAnswer
  1064  
  1065  	if !weOffer && !detectedPlanB {
  1066  		for _, media := range pc.RemoteDescription().parsed.MediaDescriptions {
  1067  			midValue := getMidValue(media)
  1068  			if midValue == "" {
  1069  				return errPeerConnRemoteDescriptionWithoutMidValue
  1070  			}
  1071  
  1072  			if media.MediaName.Media == mediaSectionApplication {
  1073  				continue
  1074  			}
  1075  
  1076  			kind := NewRTPCodecType(media.MediaName.Media)
  1077  			direction := getPeerDirection(media)
  1078  			if kind == 0 || direction == RTPTransceiverDirectionUnknown {
  1079  				continue
  1080  			}
  1081  
  1082  			t, localTransceivers = findByMid(midValue, localTransceivers)
  1083  			if t == nil {
  1084  				t, localTransceivers = satisfyTypeAndDirection(kind, direction, localTransceivers)
  1085  			} else if direction == RTPTransceiverDirectionInactive {
  1086  				if err := t.Stop(); err != nil {
  1087  					return err
  1088  				}
  1089  			}
  1090  
  1091  			switch {
  1092  			case t == nil:
  1093  				receiver, err := pc.api.NewRTPReceiver(kind, pc.dtlsTransport)
  1094  				if err != nil {
  1095  					return err
  1096  				}
  1097  
  1098  				localDirection := RTPTransceiverDirectionRecvonly
  1099  				if direction == RTPTransceiverDirectionRecvonly {
  1100  					localDirection = RTPTransceiverDirectionSendonly
  1101  				} else if direction == RTPTransceiverDirectionInactive {
  1102  					localDirection = RTPTransceiverDirectionInactive
  1103  				}
  1104  
  1105  				t = newRTPTransceiver(receiver, nil, localDirection, kind, pc.api)
  1106  				pc.mu.Lock()
  1107  				pc.addRTPTransceiver(t)
  1108  				pc.mu.Unlock()
  1109  
  1110  				// if transceiver is create by remote sdp, set prefer codec same as remote peer
  1111  				if codecs, err := codecsFromMediaDescription(media); err == nil {
  1112  					filteredCodecs := []RTPCodecParameters{}
  1113  					for _, codec := range codecs {
  1114  						if c, matchType := codecParametersFuzzySearch(codec, pc.api.mediaEngine.getCodecsByKind(kind)); matchType == codecMatchExact {
  1115  							// if codec match exact, use payloadtype register to mediaengine
  1116  							codec.PayloadType = c.PayloadType
  1117  							filteredCodecs = append(filteredCodecs, codec)
  1118  						}
  1119  					}
  1120  					_ = t.SetCodecPreferences(filteredCodecs)
  1121  				}
  1122  
  1123  			case direction == RTPTransceiverDirectionRecvonly:
  1124  				if t.Direction() == RTPTransceiverDirectionSendrecv {
  1125  					t.setDirection(RTPTransceiverDirectionSendonly)
  1126  				} else if t.Direction() == RTPTransceiverDirectionRecvonly {
  1127  					t.setDirection(RTPTransceiverDirectionInactive)
  1128  				}
  1129  			case direction == RTPTransceiverDirectionSendrecv:
  1130  				if t.Direction() == RTPTransceiverDirectionSendonly {
  1131  					t.setDirection(RTPTransceiverDirectionSendrecv)
  1132  				} else if t.Direction() == RTPTransceiverDirectionInactive {
  1133  					t.setDirection(RTPTransceiverDirectionRecvonly)
  1134  				}
  1135  			case direction == RTPTransceiverDirectionSendonly:
  1136  				if t.Direction() == RTPTransceiverDirectionInactive {
  1137  					t.setDirection(RTPTransceiverDirectionRecvonly)
  1138  				}
  1139  			}
  1140  
  1141  			if t.Mid() == "" {
  1142  				if err := t.SetMid(midValue); err != nil {
  1143  					return err
  1144  				}
  1145  			}
  1146  		}
  1147  	}
  1148  
  1149  	remoteUfrag, remotePwd, candidates, err := extractICEDetails(desc.parsed, pc.log)
  1150  	if err != nil {
  1151  		return err
  1152  	}
  1153  
  1154  	if isRenegotiation && pc.iceTransport.haveRemoteCredentialsChange(remoteUfrag, remotePwd) {
  1155  		// An ICE Restart only happens implicitly for a SetRemoteDescription of type offer
  1156  		if !weOffer {
  1157  			if err = pc.iceTransport.restart(); err != nil {
  1158  				return err
  1159  			}
  1160  		}
  1161  
  1162  		if err = pc.iceTransport.setRemoteCredentials(remoteUfrag, remotePwd); err != nil {
  1163  			return err
  1164  		}
  1165  	}
  1166  
  1167  	for i := range candidates {
  1168  		if err = pc.iceTransport.AddRemoteCandidate(&candidates[i]); err != nil {
  1169  			return err
  1170  		}
  1171  	}
  1172  
  1173  	currentTransceivers := append([]*RTPTransceiver{}, pc.GetTransceivers()...)
  1174  
  1175  	if isRenegotiation {
  1176  		if weOffer {
  1177  			_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true)
  1178  			if err = pc.startRTPSenders(currentTransceivers); err != nil {
  1179  				return err
  1180  			}
  1181  			pc.configureRTPReceivers(true, &desc, currentTransceivers)
  1182  			pc.ops.Enqueue(func() {
  1183  				pc.startRTP(true, &desc, currentTransceivers)
  1184  			})
  1185  		}
  1186  		return nil
  1187  	}
  1188  
  1189  	remoteIsLite := isIceLiteSet(desc.parsed)
  1190  
  1191  	fingerprint, fingerprintHash, err := extractFingerprint(desc.parsed)
  1192  	if err != nil {
  1193  		return err
  1194  	}
  1195  
  1196  	iceRole := ICERoleControlled
  1197  	// If one of the agents is lite and the other one is not, the lite agent must be the controlled agent.
  1198  	// If both or neither agents are lite the offering agent is controlling.
  1199  	// RFC 8445 S6.1.1
  1200  	if (weOffer && remoteIsLite == pc.api.settingEngine.candidates.ICELite) || (remoteIsLite && !pc.api.settingEngine.candidates.ICELite) {
  1201  		iceRole = ICERoleControlling
  1202  	}
  1203  
  1204  	// Start the networking in a new routine since it will block until
  1205  	// the connection is actually established.
  1206  	if weOffer {
  1207  		_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true)
  1208  		if err := pc.startRTPSenders(currentTransceivers); err != nil {
  1209  			return err
  1210  		}
  1211  
  1212  		pc.configureRTPReceivers(false, &desc, currentTransceivers)
  1213  	}
  1214  
  1215  	pc.ops.Enqueue(func() {
  1216  		pc.startTransports(iceRole, dtlsRoleFromRemoteSDP(desc.parsed), remoteUfrag, remotePwd, fingerprint, fingerprintHash)
  1217  		if weOffer {
  1218  			pc.startRTP(false, &desc, currentTransceivers)
  1219  		}
  1220  	})
  1221  	return nil
  1222  }
  1223  
  1224  func (pc *PeerConnection) configureReceiver(incoming trackDetails, receiver *RTPReceiver) {
  1225  	receiver.configureReceive(trackDetailsToRTPReceiveParameters(&incoming))
  1226  
  1227  	// set track id and label early so they can be set as new track information
  1228  	// is received from the SDP.
  1229  	for i := range receiver.tracks {
  1230  		receiver.tracks[i].track.mu.Lock()
  1231  		receiver.tracks[i].track.id = incoming.id
  1232  		receiver.tracks[i].track.streamID = incoming.streamID
  1233  		receiver.tracks[i].track.mu.Unlock()
  1234  	}
  1235  }
  1236  
  1237  func (pc *PeerConnection) startReceiver(incoming trackDetails, receiver *RTPReceiver) {
  1238  	if err := receiver.startReceive(trackDetailsToRTPReceiveParameters(&incoming)); err != nil {
  1239  		pc.log.Warnf("RTPReceiver Receive failed %s", err)
  1240  		return
  1241  	}
  1242  
  1243  	for _, t := range receiver.Tracks() {
  1244  		if t.SSRC() == 0 || t.RID() != "" {
  1245  			return
  1246  		}
  1247  
  1248  		if pc.api.settingEngine.fireOnTrackBeforeFirstRTP {
  1249  			pc.onTrack(t, receiver)
  1250  			return
  1251  		}
  1252  		go func(track *TrackRemote) {
  1253  			b := make([]byte, pc.api.settingEngine.getReceiveMTU())
  1254  			n, _, err := track.peek(b)
  1255  			if err != nil {
  1256  				pc.log.Warnf("Could not determine PayloadType for SSRC %d (%s)", track.SSRC(), err)
  1257  				return
  1258  			}
  1259  
  1260  			if err = track.checkAndUpdateTrack(b[:n]); err != nil {
  1261  				pc.log.Warnf("Failed to set codec settings for track SSRC %d (%s)", track.SSRC(), err)
  1262  				return
  1263  			}
  1264  
  1265  			pc.onTrack(track, receiver)
  1266  		}(t)
  1267  	}
  1268  }
  1269  
  1270  func setRTPTransceiverCurrentDirection(answer *SessionDescription, currentTransceivers []*RTPTransceiver, weOffer bool) error {
  1271  	currentTransceivers = append([]*RTPTransceiver{}, currentTransceivers...)
  1272  	for _, media := range answer.parsed.MediaDescriptions {
  1273  		midValue := getMidValue(media)
  1274  		if midValue == "" {
  1275  			return errPeerConnRemoteDescriptionWithoutMidValue
  1276  		}
  1277  
  1278  		if media.MediaName.Media == mediaSectionApplication {
  1279  			continue
  1280  		}
  1281  
  1282  		var t *RTPTransceiver
  1283  		t, currentTransceivers = findByMid(midValue, currentTransceivers)
  1284  
  1285  		if t == nil {
  1286  			return fmt.Errorf("%w: %q", errPeerConnTranscieverMidNil, midValue)
  1287  		}
  1288  
  1289  		direction := getPeerDirection(media)
  1290  		if direction == RTPTransceiverDirectionUnknown {
  1291  			continue
  1292  		}
  1293  
  1294  		// reverse direction if it was a remote answer
  1295  		if weOffer {
  1296  			switch direction {
  1297  			case RTPTransceiverDirectionSendonly:
  1298  				direction = RTPTransceiverDirectionRecvonly
  1299  			case RTPTransceiverDirectionRecvonly:
  1300  				direction = RTPTransceiverDirectionSendonly
  1301  			default:
  1302  			}
  1303  		}
  1304  
  1305  		// If a transceiver is created by applying a remote description that has recvonly transceiver,
  1306  		// it will have no sender. In this case, the transceiver's current direction is set to inactive so
  1307  		// that the transceiver can be reused by next AddTrack.
  1308  		if !weOffer && direction == RTPTransceiverDirectionSendonly && t.Sender() == nil {
  1309  			direction = RTPTransceiverDirectionInactive
  1310  		}
  1311  
  1312  		t.setCurrentDirection(direction)
  1313  	}
  1314  	return nil
  1315  }
  1316  
  1317  func runIfNewReceiver(
  1318  	incomingTrack trackDetails,
  1319  	transceivers []*RTPTransceiver,
  1320  	f func(incomingTrack trackDetails, receiver *RTPReceiver),
  1321  ) bool {
  1322  	for _, t := range transceivers {
  1323  		if t.Mid() != incomingTrack.mid {
  1324  			continue
  1325  		}
  1326  
  1327  		receiver := t.Receiver()
  1328  		if (incomingTrack.kind != t.Kind()) ||
  1329  			(t.Direction() != RTPTransceiverDirectionRecvonly && t.Direction() != RTPTransceiverDirectionSendrecv) ||
  1330  			receiver == nil ||
  1331  			(receiver.haveReceived()) {
  1332  			continue
  1333  		}
  1334  
  1335  		f(incomingTrack, receiver)
  1336  		return true
  1337  	}
  1338  
  1339  	return false
  1340  }
  1341  
  1342  // configureRTPReceivers opens knows inbound SRTP streams from the RemoteDescription
  1343  func (pc *PeerConnection) configureRTPReceivers(isRenegotiation bool, remoteDesc *SessionDescription, currentTransceivers []*RTPTransceiver) { //nolint:gocognit
  1344  	incomingTracks := trackDetailsFromSDP(pc.log, remoteDesc.parsed)
  1345  
  1346  	if isRenegotiation {
  1347  		for _, t := range currentTransceivers {
  1348  			receiver := t.Receiver()
  1349  			if receiver == nil {
  1350  				continue
  1351  			}
  1352  
  1353  			tracks := t.Receiver().Tracks()
  1354  			if len(tracks) == 0 {
  1355  				continue
  1356  			}
  1357  
  1358  			mid := t.Mid()
  1359  			receiverNeedsStopped := false
  1360  			for _, track := range tracks {
  1361  				func(t *TrackRemote) {
  1362  					t.mu.Lock()
  1363  					defer t.mu.Unlock()
  1364  
  1365  					if t.rid != "" {
  1366  						if details := trackDetailsForRID(incomingTracks, mid, t.rid); details != nil {
  1367  							t.id = details.id
  1368  							t.streamID = details.streamID
  1369  							return
  1370  						}
  1371  					} else if t.ssrc != 0 {
  1372  						if details := trackDetailsForSSRC(incomingTracks, t.ssrc); details != nil {
  1373  							t.id = details.id
  1374  							t.streamID = details.streamID
  1375  							return
  1376  						}
  1377  					}
  1378  
  1379  					receiverNeedsStopped = true
  1380  				}(track)
  1381  			}
  1382  
  1383  			if !receiverNeedsStopped {
  1384  				continue
  1385  			}
  1386  
  1387  			if err := receiver.Stop(); err != nil {
  1388  				pc.log.Warnf("Failed to stop RtpReceiver: %s", err)
  1389  				continue
  1390  			}
  1391  
  1392  			receiver, err := pc.api.NewRTPReceiver(receiver.kind, pc.dtlsTransport)
  1393  			if err != nil {
  1394  				pc.log.Warnf("Failed to create new RtpReceiver: %s", err)
  1395  				continue
  1396  			}
  1397  			t.setReceiver(receiver)
  1398  		}
  1399  	}
  1400  
  1401  	localTransceivers := append([]*RTPTransceiver{}, currentTransceivers...)
  1402  
  1403  	// Ensure we haven't already started a transceiver for this ssrc
  1404  	filteredTracks := append([]trackDetails{}, incomingTracks...)
  1405  	for _, incomingTrack := range incomingTracks {
  1406  		// If we already have a TrackRemote for a given SSRC don't handle it again
  1407  		for _, t := range localTransceivers {
  1408  			if receiver := t.Receiver(); receiver != nil {
  1409  				for _, track := range receiver.Tracks() {
  1410  					for _, ssrc := range incomingTrack.ssrcs {
  1411  						if ssrc == track.SSRC() {
  1412  							filteredTracks = filterTrackWithSSRC(filteredTracks, track.SSRC())
  1413  						}
  1414  					}
  1415  				}
  1416  			}
  1417  		}
  1418  	}
  1419  
  1420  	for _, incomingTrack := range filteredTracks {
  1421  		_ = runIfNewReceiver(incomingTrack, localTransceivers, pc.configureReceiver)
  1422  	}
  1423  }
  1424  
  1425  // startRTPReceivers opens knows inbound SRTP streams from the RemoteDescription
  1426  func (pc *PeerConnection) startRTPReceivers(remoteDesc *SessionDescription, currentTransceivers []*RTPTransceiver) {
  1427  	incomingTracks := trackDetailsFromSDP(pc.log, remoteDesc.parsed)
  1428  	if len(incomingTracks) == 0 {
  1429  		return
  1430  	}
  1431  
  1432  	localTransceivers := append([]*RTPTransceiver{}, currentTransceivers...)
  1433  
  1434  	unhandledTracks := incomingTracks[:0]
  1435  	for _, incomingTrack := range incomingTracks {
  1436  		trackHandled := runIfNewReceiver(incomingTrack, localTransceivers, pc.startReceiver)
  1437  		if !trackHandled {
  1438  			unhandledTracks = append(unhandledTracks, incomingTrack)
  1439  		}
  1440  	}
  1441  
  1442  	remoteIsPlanB := false
  1443  	switch pc.configuration.SDPSemantics {
  1444  	case SDPSemanticsPlanB:
  1445  		remoteIsPlanB = true
  1446  	case SDPSemanticsUnifiedPlanWithFallback:
  1447  		remoteIsPlanB = descriptionPossiblyPlanB(pc.RemoteDescription())
  1448  	default:
  1449  		// none
  1450  	}
  1451  
  1452  	if remoteIsPlanB {
  1453  		for _, incomingTrack := range unhandledTracks {
  1454  			t, err := pc.AddTransceiverFromKind(incomingTrack.kind, RTPTransceiverInit{
  1455  				Direction: RTPTransceiverDirectionSendrecv,
  1456  			})
  1457  			if err != nil {
  1458  				pc.log.Warnf("Could not add transceiver for remote SSRC %d: %s", incomingTrack.ssrcs[0], err)
  1459  				continue
  1460  			}
  1461  			pc.configureReceiver(incomingTrack, t.Receiver())
  1462  			pc.startReceiver(incomingTrack, t.Receiver())
  1463  		}
  1464  	}
  1465  }
  1466  
  1467  // startRTPSenders starts all outbound RTP streams
  1468  func (pc *PeerConnection) startRTPSenders(currentTransceivers []*RTPTransceiver) error {
  1469  	for _, transceiver := range currentTransceivers {
  1470  		if sender := transceiver.Sender(); sender != nil && sender.isNegotiated() && !sender.hasSent() {
  1471  			err := sender.Send(sender.GetParameters())
  1472  			if err != nil {
  1473  				return err
  1474  			}
  1475  		}
  1476  	}
  1477  
  1478  	return nil
  1479  }
  1480  
  1481  // Start SCTP subsystem
  1482  func (pc *PeerConnection) startSCTP() {
  1483  	// Start sctp
  1484  	if err := pc.sctpTransport.Start(SCTPCapabilities{
  1485  		MaxMessageSize: 0,
  1486  	}); err != nil {
  1487  		pc.log.Warnf("Failed to start SCTP: %s", err)
  1488  		if err = pc.sctpTransport.Stop(); err != nil {
  1489  			pc.log.Warnf("Failed to stop SCTPTransport: %s", err)
  1490  		}
  1491  
  1492  		return
  1493  	}
  1494  }
  1495  
  1496  func (pc *PeerConnection) handleUndeclaredSSRC(ssrc SSRC, remoteDescription *SessionDescription) (handled bool, err error) {
  1497  	if len(remoteDescription.parsed.MediaDescriptions) != 1 {
  1498  		return false, nil
  1499  	}
  1500  
  1501  	onlyMediaSection := remoteDescription.parsed.MediaDescriptions[0]
  1502  	streamID := ""
  1503  	id := ""
  1504  	hasRidAttribute := false
  1505  	hasSSRCAttribute := false
  1506  
  1507  	for _, a := range onlyMediaSection.Attributes {
  1508  		switch a.Key {
  1509  		case sdp.AttrKeyMsid:
  1510  			if split := strings.Split(a.Value, " "); len(split) == 2 {
  1511  				streamID = split[0]
  1512  				id = split[1]
  1513  			}
  1514  		case sdp.AttrKeySSRC:
  1515  			hasSSRCAttribute = true
  1516  		case sdpAttributeRid:
  1517  			hasRidAttribute = true
  1518  		}
  1519  	}
  1520  
  1521  	if hasRidAttribute {
  1522  		return false, nil
  1523  	} else if hasSSRCAttribute {
  1524  		return false, errPeerConnSingleMediaSectionHasExplicitSSRC
  1525  	}
  1526  
  1527  	incoming := trackDetails{
  1528  		ssrcs:    []SSRC{ssrc},
  1529  		kind:     RTPCodecTypeVideo,
  1530  		streamID: streamID,
  1531  		id:       id,
  1532  	}
  1533  	if onlyMediaSection.MediaName.Media == RTPCodecTypeAudio.String() {
  1534  		incoming.kind = RTPCodecTypeAudio
  1535  	}
  1536  
  1537  	t, err := pc.AddTransceiverFromKind(incoming.kind, RTPTransceiverInit{
  1538  		Direction: RTPTransceiverDirectionSendrecv,
  1539  	})
  1540  	if err != nil {
  1541  		// nolint
  1542  		return false, fmt.Errorf("%w: %d: %s", errPeerConnRemoteSSRCAddTransceiver, ssrc, err)
  1543  	}
  1544  
  1545  	pc.configureReceiver(incoming, t.Receiver())
  1546  	pc.startReceiver(incoming, t.Receiver())
  1547  	return true, nil
  1548  }
  1549  
  1550  // Chrome sends probing traffic on SSRC 0. This reads the packets to ensure that we properly
  1551  // generate TWCC reports for it. Since this isn't actually media we don't pass this to the user
  1552  func (pc *PeerConnection) handleNonMediaBandwidthProbe() {
  1553  	nonMediaBandwidthProbe, err := pc.api.NewRTPReceiver(RTPCodecTypeVideo, pc.dtlsTransport)
  1554  	if err != nil {
  1555  		pc.log.Errorf("handleNonMediaBandwidthProbe failed to create RTPReceiver: %v", err)
  1556  		return
  1557  	}
  1558  
  1559  	if err = nonMediaBandwidthProbe.Receive(RTPReceiveParameters{
  1560  		Encodings: []RTPDecodingParameters{{RTPCodingParameters: RTPCodingParameters{}}},
  1561  	}); err != nil {
  1562  		pc.log.Errorf("handleNonMediaBandwidthProbe failed to start RTPReceiver: %v", err)
  1563  		return
  1564  	}
  1565  
  1566  	pc.nonMediaBandwidthProbe.Store(nonMediaBandwidthProbe)
  1567  	b := make([]byte, pc.api.settingEngine.getReceiveMTU())
  1568  	for {
  1569  		if _, _, err = nonMediaBandwidthProbe.readRTP(b, nonMediaBandwidthProbe.Track()); err != nil {
  1570  			pc.log.Tracef("handleNonMediaBandwidthProbe read exiting: %v", err)
  1571  			return
  1572  		}
  1573  	}
  1574  }
  1575  
  1576  func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) error { //nolint:gocognit
  1577  	remoteDescription := pc.RemoteDescription()
  1578  	if remoteDescription == nil {
  1579  		return errPeerConnRemoteDescriptionNil
  1580  	}
  1581  
  1582  	// If a SSRC already exists in the RemoteDescription don't perform heuristics upon it
  1583  	for _, track := range trackDetailsFromSDP(pc.log, remoteDescription.parsed) {
  1584  		if track.repairSsrc != nil && ssrc == *track.repairSsrc {
  1585  			return nil
  1586  		}
  1587  		for _, trackSsrc := range track.ssrcs {
  1588  			if ssrc == trackSsrc {
  1589  				return nil
  1590  			}
  1591  		}
  1592  	}
  1593  
  1594  	// If the remote SDP was only one media section the ssrc doesn't have to be explicitly declared
  1595  	if handled, err := pc.handleUndeclaredSSRC(ssrc, remoteDescription); handled || err != nil {
  1596  		return err
  1597  	}
  1598  
  1599  	midExtensionID, audioSupported, videoSupported := pc.api.mediaEngine.getHeaderExtensionID(RTPHeaderExtensionCapability{sdp.SDESMidURI})
  1600  	if !audioSupported && !videoSupported {
  1601  		return errPeerConnSimulcastMidRTPExtensionRequired
  1602  	}
  1603  
  1604  	streamIDExtensionID, audioSupported, videoSupported := pc.api.mediaEngine.getHeaderExtensionID(RTPHeaderExtensionCapability{sdp.SDESRTPStreamIDURI})
  1605  	if !audioSupported && !videoSupported {
  1606  		return errPeerConnSimulcastStreamIDRTPExtensionRequired
  1607  	}
  1608  
  1609  	repairStreamIDExtensionID, _, _ := pc.api.mediaEngine.getHeaderExtensionID(RTPHeaderExtensionCapability{sdesRepairRTPStreamIDURI})
  1610  
  1611  	b := make([]byte, pc.api.settingEngine.getReceiveMTU())
  1612  
  1613  	i, err := rtpStream.Read(b)
  1614  	if err != nil {
  1615  		return err
  1616  	}
  1617  
  1618  	if i < 4 {
  1619  		return errRTPTooShort
  1620  	}
  1621  
  1622  	payloadType := PayloadType(b[1] & 0x7f)
  1623  	params, err := pc.api.mediaEngine.getRTPParametersByPayloadType(payloadType)
  1624  	if err != nil {
  1625  		return err
  1626  	}
  1627  
  1628  	streamInfo := createStreamInfo("", ssrc, 0, 0, params.Codecs[0].PayloadType, 0, 0, params.Codecs[0].RTPCodecCapability, params.HeaderExtensions)
  1629  	readStream, interceptor, rtcpReadStream, rtcpInterceptor, err := pc.dtlsTransport.streamsForSSRC(ssrc, *streamInfo)
  1630  	if err != nil {
  1631  		return err
  1632  	}
  1633  
  1634  	var mid, rid, rsid string
  1635  	var paddingOnly bool
  1636  	for readCount := 0; readCount <= simulcastProbeCount; readCount++ {
  1637  		if mid == "" || (rid == "" && rsid == "") {
  1638  			// skip padding only packets for probing
  1639  			if paddingOnly {
  1640  				readCount--
  1641  			}
  1642  
  1643  			i, _, err := interceptor.Read(b, nil)
  1644  			if err != nil {
  1645  				return err
  1646  			}
  1647  
  1648  			if _, paddingOnly, err = handleUnknownRTPPacket(b[:i], uint8(midExtensionID), uint8(streamIDExtensionID), uint8(repairStreamIDExtensionID), &mid, &rid, &rsid); err != nil {
  1649  				return err
  1650  			}
  1651  
  1652  			continue
  1653  		}
  1654  
  1655  		for _, t := range pc.GetTransceivers() {
  1656  			receiver := t.Receiver()
  1657  			if t.Mid() != mid || receiver == nil {
  1658  				continue
  1659  			}
  1660  
  1661  			if rsid != "" {
  1662  				receiver.mu.Lock()
  1663  				defer receiver.mu.Unlock()
  1664  				return receiver.receiveForRtx(SSRC(0), rsid, streamInfo, readStream, interceptor, rtcpReadStream, rtcpInterceptor)
  1665  			}
  1666  
  1667  			track, err := receiver.receiveForRid(rid, params, streamInfo, readStream, interceptor, rtcpReadStream, rtcpInterceptor)
  1668  			if err != nil {
  1669  				return err
  1670  			}
  1671  			pc.onTrack(track, receiver)
  1672  			return nil
  1673  		}
  1674  	}
  1675  
  1676  	pc.api.interceptor.UnbindRemoteStream(streamInfo)
  1677  	return errPeerConnSimulcastIncomingSSRCFailed
  1678  }
  1679  
  1680  // undeclaredMediaProcessor handles RTP/RTCP packets that don't match any a:ssrc lines
  1681  func (pc *PeerConnection) undeclaredMediaProcessor() {
  1682  	go pc.undeclaredRTPMediaProcessor()
  1683  	go pc.undeclaredRTCPMediaProcessor()
  1684  }
  1685  
  1686  func (pc *PeerConnection) undeclaredRTPMediaProcessor() {
  1687  	var simulcastRoutineCount uint64
  1688  	for {
  1689  		srtpSession, err := pc.dtlsTransport.getSRTPSession()
  1690  		if err != nil {
  1691  			pc.log.Warnf("undeclaredMediaProcessor failed to open SrtpSession: %v", err)
  1692  			return
  1693  		}
  1694  
  1695  		srtcpSession, err := pc.dtlsTransport.getSRTCPSession()
  1696  		if err != nil {
  1697  			pc.log.Warnf("undeclaredMediaProcessor failed to open SrtcpSession: %v", err)
  1698  			return
  1699  		}
  1700  
  1701  		srtpReadStream, ssrc, err := srtpSession.AcceptStream()
  1702  		if err != nil {
  1703  			pc.log.Warnf("Failed to accept RTP %v", err)
  1704  			return
  1705  		}
  1706  
  1707  		// open accompanying srtcp stream
  1708  		srtcpReadStream, err := srtcpSession.OpenReadStream(ssrc)
  1709  		if err != nil {
  1710  			pc.log.Warnf("Failed to open RTCP stream for %d: %v", ssrc, err)
  1711  			return
  1712  		}
  1713  
  1714  		if pc.isClosed.get() {
  1715  			if err = srtpReadStream.Close(); err != nil {
  1716  				pc.log.Warnf("Failed to close RTP stream %v", err)
  1717  			}
  1718  			if err = srtcpReadStream.Close(); err != nil {
  1719  				pc.log.Warnf("Failed to close RTCP stream %v", err)
  1720  			}
  1721  			continue
  1722  		}
  1723  
  1724  		pc.dtlsTransport.storeSimulcastStream(srtpReadStream, srtcpReadStream)
  1725  
  1726  		if ssrc == 0 {
  1727  			go pc.handleNonMediaBandwidthProbe()
  1728  			continue
  1729  		}
  1730  
  1731  		if atomic.AddUint64(&simulcastRoutineCount, 1) >= simulcastMaxProbeRoutines {
  1732  			atomic.AddUint64(&simulcastRoutineCount, ^uint64(0))
  1733  			pc.log.Warn(ErrSimulcastProbeOverflow.Error())
  1734  			continue
  1735  		}
  1736  
  1737  		go func(rtpStream io.Reader, ssrc SSRC) {
  1738  			if err := pc.handleIncomingSSRC(rtpStream, ssrc); err != nil {
  1739  				pc.log.Errorf(incomingUnhandledRTPSsrc, ssrc, err)
  1740  			}
  1741  			atomic.AddUint64(&simulcastRoutineCount, ^uint64(0))
  1742  		}(srtpReadStream, SSRC(ssrc))
  1743  	}
  1744  }
  1745  
  1746  func (pc *PeerConnection) undeclaredRTCPMediaProcessor() {
  1747  	var unhandledStreams []*srtp.ReadStreamSRTCP
  1748  	defer func() {
  1749  		for _, s := range unhandledStreams {
  1750  			_ = s.Close()
  1751  		}
  1752  	}()
  1753  	for {
  1754  		srtcpSession, err := pc.dtlsTransport.getSRTCPSession()
  1755  		if err != nil {
  1756  			pc.log.Warnf("undeclaredMediaProcessor failed to open SrtcpSession: %v", err)
  1757  			return
  1758  		}
  1759  
  1760  		stream, ssrc, err := srtcpSession.AcceptStream()
  1761  		if err != nil {
  1762  			pc.log.Warnf("Failed to accept RTCP %v", err)
  1763  			return
  1764  		}
  1765  		pc.log.Warnf("Incoming unhandled RTCP ssrc(%d), OnTrack will not be fired", ssrc)
  1766  		unhandledStreams = append(unhandledStreams, stream)
  1767  	}
  1768  }
  1769  
  1770  // RemoteDescription returns pendingRemoteDescription if it is not null and
  1771  // otherwise it returns currentRemoteDescription. This property is used to
  1772  // determine if setRemoteDescription has already been called.
  1773  // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-remotedescription
  1774  func (pc *PeerConnection) RemoteDescription() *SessionDescription {
  1775  	pc.mu.RLock()
  1776  	defer pc.mu.RUnlock()
  1777  
  1778  	if pc.pendingRemoteDescription != nil {
  1779  		return pc.pendingRemoteDescription
  1780  	}
  1781  	return pc.currentRemoteDescription
  1782  }
  1783  
  1784  // AddICECandidate accepts an ICE candidate string and adds it
  1785  // to the existing set of candidates.
  1786  func (pc *PeerConnection) AddICECandidate(candidate ICECandidateInit) error {
  1787  	if pc.RemoteDescription() == nil {
  1788  		return &rtcerr.InvalidStateError{Err: ErrNoRemoteDescription}
  1789  	}
  1790  
  1791  	candidateValue := strings.TrimPrefix(candidate.Candidate, "candidate:")
  1792  
  1793  	var iceCandidate *ICECandidate
  1794  	if candidateValue != "" {
  1795  		candidate, err := ice.UnmarshalCandidate(candidateValue)
  1796  		if err != nil {
  1797  			if errors.Is(err, ice.ErrUnknownCandidateTyp) || errors.Is(err, ice.ErrDetermineNetworkType) {
  1798  				pc.log.Warnf("Discarding remote candidate: %s", err)
  1799  				return nil
  1800  			}
  1801  			return err
  1802  		}
  1803  
  1804  		c, err := newICECandidateFromICE(candidate)
  1805  		if err != nil {
  1806  			return err
  1807  		}
  1808  		iceCandidate = &c
  1809  	}
  1810  
  1811  	return pc.iceTransport.AddRemoteCandidate(iceCandidate)
  1812  }
  1813  
  1814  // ICEConnectionState returns the ICE connection state of the
  1815  // PeerConnection instance.
  1816  func (pc *PeerConnection) ICEConnectionState() ICEConnectionState {
  1817  	if state, ok := pc.iceConnectionState.Load().(ICEConnectionState); ok {
  1818  		return state
  1819  	}
  1820  	return ICEConnectionState(0)
  1821  }
  1822  
  1823  // GetSenders returns the RTPSender that are currently attached to this PeerConnection
  1824  func (pc *PeerConnection) GetSenders() (result []*RTPSender) {
  1825  	pc.mu.Lock()
  1826  	defer pc.mu.Unlock()
  1827  
  1828  	for _, transceiver := range pc.rtpTransceivers {
  1829  		if sender := transceiver.Sender(); sender != nil {
  1830  			result = append(result, sender)
  1831  		}
  1832  	}
  1833  	return result
  1834  }
  1835  
  1836  // GetReceivers returns the RTPReceivers that are currently attached to this PeerConnection
  1837  func (pc *PeerConnection) GetReceivers() (receivers []*RTPReceiver) {
  1838  	pc.mu.Lock()
  1839  	defer pc.mu.Unlock()
  1840  
  1841  	for _, transceiver := range pc.rtpTransceivers {
  1842  		if receiver := transceiver.Receiver(); receiver != nil {
  1843  			receivers = append(receivers, receiver)
  1844  		}
  1845  	}
  1846  	return
  1847  }
  1848  
  1849  // GetTransceivers returns the RtpTransceiver that are currently attached to this PeerConnection
  1850  func (pc *PeerConnection) GetTransceivers() []*RTPTransceiver {
  1851  	pc.mu.Lock()
  1852  	defer pc.mu.Unlock()
  1853  
  1854  	return pc.rtpTransceivers
  1855  }
  1856  
  1857  // AddTrack adds a Track to the PeerConnection
  1858  func (pc *PeerConnection) AddTrack(track TrackLocal) (*RTPSender, error) {
  1859  	if pc.isClosed.get() {
  1860  		return nil, &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
  1861  	}
  1862  
  1863  	pc.mu.Lock()
  1864  	defer pc.mu.Unlock()
  1865  	for _, t := range pc.rtpTransceivers {
  1866  		currentDirection := t.getCurrentDirection()
  1867  		// According to https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-addtrack, if the
  1868  		// transceiver can be reused only if it's currentDirection never be sendrecv or sendonly.
  1869  		// But that will cause sdp inflate. So we only check currentDirection's current value,
  1870  		// that's worked for all browsers.
  1871  		if !t.stopped && t.kind == track.Kind() && t.Sender() == nil &&
  1872  			!(currentDirection == RTPTransceiverDirectionSendrecv || currentDirection == RTPTransceiverDirectionSendonly) {
  1873  			sender, err := pc.api.NewRTPSender(track, pc.dtlsTransport)
  1874  			if err == nil {
  1875  				err = t.SetSender(sender, track)
  1876  				if err != nil {
  1877  					_ = sender.Stop()
  1878  					t.setSender(nil)
  1879  				}
  1880  			}
  1881  			if err != nil {
  1882  				return nil, err
  1883  			}
  1884  			pc.onNegotiationNeeded()
  1885  			return sender, nil
  1886  		}
  1887  	}
  1888  
  1889  	transceiver, err := pc.newTransceiverFromTrack(RTPTransceiverDirectionSendrecv, track)
  1890  	if err != nil {
  1891  		return nil, err
  1892  	}
  1893  	pc.addRTPTransceiver(transceiver)
  1894  	return transceiver.Sender(), nil
  1895  }
  1896  
  1897  // RemoveTrack removes a Track from the PeerConnection
  1898  func (pc *PeerConnection) RemoveTrack(sender *RTPSender) (err error) {
  1899  	if pc.isClosed.get() {
  1900  		return &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
  1901  	}
  1902  
  1903  	var transceiver *RTPTransceiver
  1904  	pc.mu.Lock()
  1905  	defer pc.mu.Unlock()
  1906  	for _, t := range pc.rtpTransceivers {
  1907  		if t.Sender() == sender {
  1908  			transceiver = t
  1909  			break
  1910  		}
  1911  	}
  1912  	if transceiver == nil {
  1913  		return &rtcerr.InvalidAccessError{Err: ErrSenderNotCreatedByConnection}
  1914  	} else if err = sender.Stop(); err == nil {
  1915  		err = transceiver.setSendingTrack(nil)
  1916  		if err == nil {
  1917  			pc.onNegotiationNeeded()
  1918  		}
  1919  	}
  1920  	return
  1921  }
  1922  
  1923  func (pc *PeerConnection) newTransceiverFromTrack(direction RTPTransceiverDirection, track TrackLocal, init ...RTPTransceiverInit) (t *RTPTransceiver, err error) {
  1924  	var (
  1925  		r *RTPReceiver
  1926  		s *RTPSender
  1927  	)
  1928  	switch direction {
  1929  	case RTPTransceiverDirectionSendrecv:
  1930  		r, err = pc.api.NewRTPReceiver(track.Kind(), pc.dtlsTransport)
  1931  		if err != nil {
  1932  			return
  1933  		}
  1934  		s, err = pc.api.NewRTPSender(track, pc.dtlsTransport)
  1935  	case RTPTransceiverDirectionSendonly:
  1936  		s, err = pc.api.NewRTPSender(track, pc.dtlsTransport)
  1937  	default:
  1938  		err = errPeerConnAddTransceiverFromTrackSupport
  1939  	}
  1940  	if err != nil {
  1941  		return
  1942  	}
  1943  
  1944  	// Allow RTPTransceiverInit to override SSRC
  1945  	if s != nil && len(s.trackEncodings) == 1 &&
  1946  		len(init) == 1 && len(init[0].SendEncodings) == 1 && init[0].SendEncodings[0].SSRC != 0 {
  1947  		s.trackEncodings[0].ssrc = init[0].SendEncodings[0].SSRC
  1948  	}
  1949  
  1950  	return newRTPTransceiver(r, s, direction, track.Kind(), pc.api), nil
  1951  }
  1952  
  1953  // AddTransceiverFromKind Create a new RtpTransceiver and adds it to the set of transceivers.
  1954  func (pc *PeerConnection) AddTransceiverFromKind(kind RTPCodecType, init ...RTPTransceiverInit) (t *RTPTransceiver, err error) {
  1955  	if pc.isClosed.get() {
  1956  		return nil, &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
  1957  	}
  1958  
  1959  	direction := RTPTransceiverDirectionSendrecv
  1960  	if len(init) > 1 {
  1961  		return nil, errPeerConnAddTransceiverFromKindOnlyAcceptsOne
  1962  	} else if len(init) == 1 {
  1963  		direction = init[0].Direction
  1964  	}
  1965  	switch direction {
  1966  	case RTPTransceiverDirectionSendonly, RTPTransceiverDirectionSendrecv:
  1967  		codecs := pc.api.mediaEngine.getCodecsByKind(kind)
  1968  		if len(codecs) == 0 {
  1969  			return nil, ErrNoCodecsAvailable
  1970  		}
  1971  		track, err := NewTrackLocalStaticSample(codecs[0].RTPCodecCapability, util.MathRandAlpha(16), util.MathRandAlpha(16))
  1972  		if err != nil {
  1973  			return nil, err
  1974  		}
  1975  		t, err = pc.newTransceiverFromTrack(direction, track, init...)
  1976  		if err != nil {
  1977  			return nil, err
  1978  		}
  1979  	case RTPTransceiverDirectionRecvonly:
  1980  		receiver, err := pc.api.NewRTPReceiver(kind, pc.dtlsTransport)
  1981  		if err != nil {
  1982  			return nil, err
  1983  		}
  1984  		t = newRTPTransceiver(receiver, nil, RTPTransceiverDirectionRecvonly, kind, pc.api)
  1985  	default:
  1986  		return nil, errPeerConnAddTransceiverFromKindSupport
  1987  	}
  1988  	pc.mu.Lock()
  1989  	pc.addRTPTransceiver(t)
  1990  	pc.mu.Unlock()
  1991  	return t, nil
  1992  }
  1993  
  1994  // AddTransceiverFromTrack Create a new RtpTransceiver(SendRecv or SendOnly) and add it to the set of transceivers.
  1995  func (pc *PeerConnection) AddTransceiverFromTrack(track TrackLocal, init ...RTPTransceiverInit) (t *RTPTransceiver, err error) {
  1996  	if pc.isClosed.get() {
  1997  		return nil, &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
  1998  	}
  1999  
  2000  	direction := RTPTransceiverDirectionSendrecv
  2001  	if len(init) > 1 {
  2002  		return nil, errPeerConnAddTransceiverFromTrackOnlyAcceptsOne
  2003  	} else if len(init) == 1 {
  2004  		direction = init[0].Direction
  2005  	}
  2006  
  2007  	t, err = pc.newTransceiverFromTrack(direction, track, init...)
  2008  	if err == nil {
  2009  		pc.mu.Lock()
  2010  		pc.addRTPTransceiver(t)
  2011  		pc.mu.Unlock()
  2012  	}
  2013  	return
  2014  }
  2015  
  2016  // CreateDataChannel creates a new DataChannel object with the given label
  2017  // and optional DataChannelInit used to configure properties of the
  2018  // underlying channel such as data reliability.
  2019  func (pc *PeerConnection) CreateDataChannel(label string, options *DataChannelInit) (*DataChannel, error) {
  2020  	// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #2)
  2021  	if pc.isClosed.get() {
  2022  		return nil, &rtcerr.InvalidStateError{Err: ErrConnectionClosed}
  2023  	}
  2024  
  2025  	params := &DataChannelParameters{
  2026  		Label:   label,
  2027  		Ordered: true,
  2028  	}
  2029  
  2030  	// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #19)
  2031  	if options != nil {
  2032  		params.ID = options.ID
  2033  	}
  2034  
  2035  	if options != nil {
  2036  		// Ordered indicates if data is allowed to be delivered out of order. The
  2037  		// default value of true, guarantees that data will be delivered in order.
  2038  		// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #9)
  2039  		if options.Ordered != nil {
  2040  			params.Ordered = *options.Ordered
  2041  		}
  2042  
  2043  		// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #7)
  2044  		if options.MaxPacketLifeTime != nil {
  2045  			params.MaxPacketLifeTime = options.MaxPacketLifeTime
  2046  		}
  2047  
  2048  		// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #8)
  2049  		if options.MaxRetransmits != nil {
  2050  			params.MaxRetransmits = options.MaxRetransmits
  2051  		}
  2052  
  2053  		// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #10)
  2054  		if options.Protocol != nil {
  2055  			params.Protocol = *options.Protocol
  2056  		}
  2057  
  2058  		// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #11)
  2059  		if len(params.Protocol) > 65535 {
  2060  			return nil, &rtcerr.TypeError{Err: ErrProtocolTooLarge}
  2061  		}
  2062  
  2063  		// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #12)
  2064  		if options.Negotiated != nil {
  2065  			params.Negotiated = *options.Negotiated
  2066  		}
  2067  	}
  2068  
  2069  	d, err := pc.api.newDataChannel(params, nil, pc.log)
  2070  	if err != nil {
  2071  		return nil, err
  2072  	}
  2073  
  2074  	// https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #16)
  2075  	if d.maxPacketLifeTime != nil && d.maxRetransmits != nil {
  2076  		return nil, &rtcerr.TypeError{Err: ErrRetransmitsOrPacketLifeTime}
  2077  	}
  2078  
  2079  	pc.sctpTransport.lock.Lock()
  2080  	pc.sctpTransport.dataChannels = append(pc.sctpTransport.dataChannels, d)
  2081  	if d.ID() != nil {
  2082  		pc.sctpTransport.dataChannelIDsUsed[*d.ID()] = struct{}{}
  2083  	}
  2084  	pc.sctpTransport.dataChannelsRequested++
  2085  	pc.sctpTransport.lock.Unlock()
  2086  
  2087  	// If SCTP already connected open all the channels
  2088  	if pc.sctpTransport.State() == SCTPTransportStateConnected {
  2089  		if err = d.open(pc.sctpTransport); err != nil {
  2090  			return nil, err
  2091  		}
  2092  	}
  2093  
  2094  	pc.mu.Lock()
  2095  	pc.onNegotiationNeeded()
  2096  	pc.mu.Unlock()
  2097  
  2098  	return d, nil
  2099  }
  2100  
  2101  // SetIdentityProvider is used to configure an identity provider to generate identity assertions
  2102  func (pc *PeerConnection) SetIdentityProvider(string) error {
  2103  	return errPeerConnSetIdentityProviderNotImplemented
  2104  }
  2105  
  2106  // WriteRTCP sends a user provided RTCP packet to the connected peer. If no peer is connected the
  2107  // packet is discarded. It also runs any configured interceptors.
  2108  func (pc *PeerConnection) WriteRTCP(pkts []rtcp.Packet) error {
  2109  	_, err := pc.interceptorRTCPWriter.Write(pkts, make(interceptor.Attributes))
  2110  	return err
  2111  }
  2112  
  2113  func (pc *PeerConnection) writeRTCP(pkts []rtcp.Packet, _ interceptor.Attributes) (int, error) {
  2114  	return pc.dtlsTransport.WriteRTCP(pkts)
  2115  }
  2116  
  2117  // Close ends the PeerConnection.
  2118  func (pc *PeerConnection) Close() error {
  2119  	return pc.close(false /* shouldGracefullyClose */)
  2120  }
  2121  
  2122  // GracefulClose ends the PeerConnection. It also waits
  2123  // for any goroutines it started to complete. This is only safe to call outside of
  2124  // PeerConnection callbacks or if in a callback, in its own goroutine.
  2125  func (pc *PeerConnection) GracefulClose() error {
  2126  	return pc.close(true /* shouldGracefullyClose */)
  2127  }
  2128  
  2129  func (pc *PeerConnection) close(shouldGracefullyClose bool) error {
  2130  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #1)
  2131  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #2)
  2132  
  2133  	pc.mu.Lock()
  2134  	// A lock in this critical section is needed because pc.isClosed and
  2135  	// pc.isGracefullyClosingOrClosed are related to each other in that we
  2136  	// want to make graceful and normal closure one time operations in order
  2137  	// to avoid any double closure errors from cropping up. However, there are
  2138  	// some overlapping close cases when both normal and graceful close are used
  2139  	// that should be idempotent, but be cautioned when writing new close behavior
  2140  	// to preserve this property.
  2141  	isAlreadyClosingOrClosed := pc.isClosed.swap(true)
  2142  	isAlreadyGracefullyClosingOrClosed := pc.isGracefullyClosingOrClosed
  2143  	if shouldGracefullyClose && !isAlreadyGracefullyClosingOrClosed {
  2144  		pc.isGracefullyClosingOrClosed = true
  2145  	}
  2146  	pc.mu.Unlock()
  2147  
  2148  	if isAlreadyClosingOrClosed {
  2149  		if !shouldGracefullyClose {
  2150  			return nil
  2151  		}
  2152  		// Even if we're already closing, it may not be graceful:
  2153  		// If we are not the ones doing the closing, we just wait for the graceful close
  2154  		// to happen and then return.
  2155  		if isAlreadyGracefullyClosingOrClosed {
  2156  			<-pc.isGracefulCloseDone
  2157  			return nil
  2158  		}
  2159  		// Otherwise we need to go through the graceful closure flow once the
  2160  		// normal closure is done since there are extra steps to take with a
  2161  		// graceful close.
  2162  		<-pc.isCloseDone
  2163  	} else {
  2164  		defer close(pc.isCloseDone)
  2165  	}
  2166  
  2167  	if shouldGracefullyClose {
  2168  		defer close(pc.isGracefulCloseDone)
  2169  	}
  2170  
  2171  	// Try closing everything and collect the errors
  2172  	// Shutdown strategy:
  2173  	// 1. All Conn close by closing their underlying Conn.
  2174  	// 2. A Mux stops this chain. It won't close the underlying
  2175  	//    Conn if one of the endpoints is closed down. To
  2176  	//    continue the chain the Mux has to be closed.
  2177  	closeErrs := make([]error, 4)
  2178  
  2179  	doGracefulCloseOps := func() []error {
  2180  		if !shouldGracefullyClose {
  2181  			return nil
  2182  		}
  2183  
  2184  		// these are all non-canon steps
  2185  		var gracefulCloseErrors []error
  2186  		if pc.iceTransport != nil {
  2187  			gracefulCloseErrors = append(gracefulCloseErrors, pc.iceTransport.GracefulStop())
  2188  		}
  2189  
  2190  		pc.ops.GracefulClose()
  2191  
  2192  		pc.sctpTransport.lock.Lock()
  2193  		for _, d := range pc.sctpTransport.dataChannels {
  2194  			gracefulCloseErrors = append(gracefulCloseErrors, d.GracefulClose())
  2195  		}
  2196  		pc.sctpTransport.lock.Unlock()
  2197  		return gracefulCloseErrors
  2198  	}
  2199  
  2200  	if isAlreadyClosingOrClosed {
  2201  		return util.FlattenErrs(doGracefulCloseOps())
  2202  	}
  2203  
  2204  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #3)
  2205  	pc.signalingState.Set(SignalingStateClosed)
  2206  
  2207  	closeErrs = append(closeErrs, pc.api.interceptor.Close())
  2208  
  2209  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #4)
  2210  	pc.mu.Lock()
  2211  	for _, t := range pc.rtpTransceivers {
  2212  		if !t.stopped {
  2213  			closeErrs = append(closeErrs, t.Stop())
  2214  		}
  2215  	}
  2216  	if nonMediaBandwidthProbe, ok := pc.nonMediaBandwidthProbe.Load().(*RTPReceiver); ok {
  2217  		closeErrs = append(closeErrs, nonMediaBandwidthProbe.Stop())
  2218  	}
  2219  	pc.mu.Unlock()
  2220  
  2221  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #5)
  2222  	pc.sctpTransport.lock.Lock()
  2223  	for _, d := range pc.sctpTransport.dataChannels {
  2224  		d.setReadyState(DataChannelStateClosed)
  2225  	}
  2226  	pc.sctpTransport.lock.Unlock()
  2227  
  2228  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #6)
  2229  	if pc.sctpTransport != nil {
  2230  		closeErrs = append(closeErrs, pc.sctpTransport.Stop())
  2231  	}
  2232  
  2233  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #7)
  2234  	closeErrs = append(closeErrs, pc.dtlsTransport.Stop())
  2235  
  2236  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #8, #9, #10)
  2237  	if pc.iceTransport != nil && !shouldGracefullyClose {
  2238  		// we will stop gracefully in doGracefulCloseOps
  2239  		closeErrs = append(closeErrs, pc.iceTransport.Stop())
  2240  	}
  2241  
  2242  	// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #11)
  2243  	pc.updateConnectionState(pc.ICEConnectionState(), pc.dtlsTransport.State())
  2244  
  2245  	closeErrs = append(closeErrs, doGracefulCloseOps()...)
  2246  
  2247  	return util.FlattenErrs(closeErrs)
  2248  }
  2249  
  2250  // addRTPTransceiver appends t into rtpTransceivers
  2251  // and fires onNegotiationNeeded;
  2252  // caller of this method should hold `pc.mu` lock
  2253  func (pc *PeerConnection) addRTPTransceiver(t *RTPTransceiver) {
  2254  	pc.rtpTransceivers = append(pc.rtpTransceivers, t)
  2255  	pc.onNegotiationNeeded()
  2256  }
  2257  
  2258  // CurrentLocalDescription represents the local description that was
  2259  // successfully negotiated the last time the PeerConnection transitioned
  2260  // into the stable state plus any local candidates that have been generated
  2261  // by the ICEAgent since the offer or answer was created.
  2262  func (pc *PeerConnection) CurrentLocalDescription() *SessionDescription {
  2263  	pc.mu.Lock()
  2264  	defer pc.mu.Unlock()
  2265  
  2266  	localDescription := pc.currentLocalDescription
  2267  	iceGather := pc.iceGatherer
  2268  	iceGatheringState := pc.ICEGatheringState()
  2269  	return populateLocalCandidates(localDescription, iceGather, iceGatheringState)
  2270  }
  2271  
  2272  // PendingLocalDescription represents a local description that is in the
  2273  // process of being negotiated plus any local candidates that have been
  2274  // generated by the ICEAgent since the offer or answer was created. If the
  2275  // PeerConnection is in the stable state, the value is null.
  2276  func (pc *PeerConnection) PendingLocalDescription() *SessionDescription {
  2277  	pc.mu.Lock()
  2278  	defer pc.mu.Unlock()
  2279  
  2280  	localDescription := pc.pendingLocalDescription
  2281  	iceGather := pc.iceGatherer
  2282  	iceGatheringState := pc.ICEGatheringState()
  2283  	return populateLocalCandidates(localDescription, iceGather, iceGatheringState)
  2284  }
  2285  
  2286  // CurrentRemoteDescription represents the last remote description that was
  2287  // successfully negotiated the last time the PeerConnection transitioned
  2288  // into the stable state plus any remote candidates that have been supplied
  2289  // via AddICECandidate() since the offer or answer was created.
  2290  func (pc *PeerConnection) CurrentRemoteDescription() *SessionDescription {
  2291  	pc.mu.RLock()
  2292  	defer pc.mu.RUnlock()
  2293  
  2294  	return pc.currentRemoteDescription
  2295  }
  2296  
  2297  // PendingRemoteDescription represents a remote description that is in the
  2298  // process of being negotiated, complete with any remote candidates that
  2299  // have been supplied via AddICECandidate() since the offer or answer was
  2300  // created. If the PeerConnection is in the stable state, the value is
  2301  // null.
  2302  func (pc *PeerConnection) PendingRemoteDescription() *SessionDescription {
  2303  	pc.mu.RLock()
  2304  	defer pc.mu.RUnlock()
  2305  
  2306  	return pc.pendingRemoteDescription
  2307  }
  2308  
  2309  // SignalingState attribute returns the signaling state of the
  2310  // PeerConnection instance.
  2311  func (pc *PeerConnection) SignalingState() SignalingState {
  2312  	return pc.signalingState.Get()
  2313  }
  2314  
  2315  // ICEGatheringState attribute returns the ICE gathering state of the
  2316  // PeerConnection instance.
  2317  func (pc *PeerConnection) ICEGatheringState() ICEGatheringState {
  2318  	if pc.iceGatherer == nil {
  2319  		return ICEGatheringStateNew
  2320  	}
  2321  
  2322  	switch pc.iceGatherer.State() {
  2323  	case ICEGathererStateNew:
  2324  		return ICEGatheringStateNew
  2325  	case ICEGathererStateGathering:
  2326  		return ICEGatheringStateGathering
  2327  	default:
  2328  		return ICEGatheringStateComplete
  2329  	}
  2330  }
  2331  
  2332  // ConnectionState attribute returns the connection state of the
  2333  // PeerConnection instance.
  2334  func (pc *PeerConnection) ConnectionState() PeerConnectionState {
  2335  	if state, ok := pc.connectionState.Load().(PeerConnectionState); ok {
  2336  		return state
  2337  	}
  2338  	return PeerConnectionState(0)
  2339  }
  2340  
  2341  // GetStats return data providing statistics about the overall connection
  2342  func (pc *PeerConnection) GetStats() StatsReport {
  2343  	var (
  2344  		dataChannelsAccepted  uint32
  2345  		dataChannelsClosed    uint32
  2346  		dataChannelsOpened    uint32
  2347  		dataChannelsRequested uint32
  2348  	)
  2349  	statsCollector := newStatsReportCollector()
  2350  	statsCollector.Collecting()
  2351  
  2352  	pc.mu.Lock()
  2353  	if pc.iceGatherer != nil {
  2354  		pc.iceGatherer.collectStats(statsCollector)
  2355  	}
  2356  	if pc.iceTransport != nil {
  2357  		pc.iceTransport.collectStats(statsCollector)
  2358  	}
  2359  
  2360  	pc.sctpTransport.lock.Lock()
  2361  	dataChannels := append([]*DataChannel{}, pc.sctpTransport.dataChannels...)
  2362  	dataChannelsAccepted = pc.sctpTransport.dataChannelsAccepted
  2363  	dataChannelsOpened = pc.sctpTransport.dataChannelsOpened
  2364  	dataChannelsRequested = pc.sctpTransport.dataChannelsRequested
  2365  	pc.sctpTransport.lock.Unlock()
  2366  
  2367  	for _, d := range dataChannels {
  2368  		state := d.ReadyState()
  2369  		if state != DataChannelStateConnecting && state != DataChannelStateOpen {
  2370  			dataChannelsClosed++
  2371  		}
  2372  
  2373  		d.collectStats(statsCollector)
  2374  	}
  2375  	pc.sctpTransport.collectStats(statsCollector)
  2376  
  2377  	stats := PeerConnectionStats{
  2378  		Timestamp:             statsTimestampNow(),
  2379  		Type:                  StatsTypePeerConnection,
  2380  		ID:                    pc.statsID,
  2381  		DataChannelsAccepted:  dataChannelsAccepted,
  2382  		DataChannelsClosed:    dataChannelsClosed,
  2383  		DataChannelsOpened:    dataChannelsOpened,
  2384  		DataChannelsRequested: dataChannelsRequested,
  2385  	}
  2386  
  2387  	statsCollector.Collect(stats.ID, stats)
  2388  
  2389  	certificates := pc.configuration.Certificates
  2390  	for _, certificate := range certificates {
  2391  		if err := certificate.collectStats(statsCollector); err != nil {
  2392  			continue
  2393  		}
  2394  	}
  2395  	pc.mu.Unlock()
  2396  
  2397  	pc.api.mediaEngine.collectStats(statsCollector)
  2398  
  2399  	return statsCollector.Ready()
  2400  }
  2401  
  2402  // Start all transports. PeerConnection now has enough state
  2403  func (pc *PeerConnection) startTransports(iceRole ICERole, dtlsRole DTLSRole, remoteUfrag, remotePwd, fingerprint, fingerprintHash string) {
  2404  	// Start the ice transport
  2405  	err := pc.iceTransport.Start(
  2406  		pc.iceGatherer,
  2407  		ICEParameters{
  2408  			UsernameFragment: remoteUfrag,
  2409  			Password:         remotePwd,
  2410  			ICELite:          false,
  2411  		},
  2412  		&iceRole,
  2413  	)
  2414  	if err != nil {
  2415  		pc.log.Warnf("Failed to start manager: %s", err)
  2416  		return
  2417  	}
  2418  
  2419  	pc.dtlsTransport.internalOnCloseHandler = func() {
  2420  		if pc.isClosed.get() {
  2421  			return
  2422  		}
  2423  
  2424  		pc.log.Info("Closing PeerConnection from DTLS CloseNotify")
  2425  		go func() {
  2426  			if pcClosErr := pc.Close(); pcClosErr != nil {
  2427  				pc.log.Warnf("Failed to close PeerConnection from DTLS CloseNotify: %s", pcClosErr)
  2428  			}
  2429  		}()
  2430  	}
  2431  
  2432  	// Start the dtls transport
  2433  	err = pc.dtlsTransport.Start(DTLSParameters{
  2434  		Role:         dtlsRole,
  2435  		Fingerprints: []DTLSFingerprint{{Algorithm: fingerprintHash, Value: fingerprint}},
  2436  	})
  2437  	pc.updateConnectionState(pc.ICEConnectionState(), pc.dtlsTransport.State())
  2438  	if err != nil {
  2439  		pc.log.Warnf("Failed to start manager: %s", err)
  2440  		return
  2441  	}
  2442  }
  2443  
  2444  // nolint: gocognit
  2445  func (pc *PeerConnection) startRTP(isRenegotiation bool, remoteDesc *SessionDescription, currentTransceivers []*RTPTransceiver) {
  2446  	if !isRenegotiation {
  2447  		pc.undeclaredMediaProcessor()
  2448  	}
  2449  
  2450  	pc.startRTPReceivers(remoteDesc, currentTransceivers)
  2451  	if haveApplicationMediaSection(remoteDesc.parsed) {
  2452  		pc.startSCTP()
  2453  	}
  2454  }
  2455  
  2456  // generateUnmatchedSDP generates an SDP that doesn't take remote state into account
  2457  // This is used for the initial call for CreateOffer
  2458  func (pc *PeerConnection) generateUnmatchedSDP(transceivers []*RTPTransceiver, useIdentity bool) (*sdp.SessionDescription, error) {
  2459  	d, err := sdp.NewJSEPSessionDescription(useIdentity)
  2460  	if err != nil {
  2461  		return nil, err
  2462  	}
  2463  	d.Attributes = append(d.Attributes, sdp.Attribute{Key: sdp.AttrKeyMsidSemantic, Value: "WMS*"})
  2464  
  2465  	iceParams, err := pc.iceGatherer.GetLocalParameters()
  2466  	if err != nil {
  2467  		return nil, err
  2468  	}
  2469  
  2470  	candidates, err := pc.iceGatherer.GetLocalCandidates()
  2471  	if err != nil {
  2472  		return nil, err
  2473  	}
  2474  
  2475  	isPlanB := pc.configuration.SDPSemantics == SDPSemanticsPlanB
  2476  	mediaSections := []mediaSection{}
  2477  
  2478  	// Needed for pc.sctpTransport.dataChannelsRequested
  2479  	pc.sctpTransport.lock.Lock()
  2480  	defer pc.sctpTransport.lock.Unlock()
  2481  
  2482  	if isPlanB {
  2483  		video := make([]*RTPTransceiver, 0)
  2484  		audio := make([]*RTPTransceiver, 0)
  2485  
  2486  		for _, t := range transceivers {
  2487  			if t.kind == RTPCodecTypeVideo {
  2488  				video = append(video, t)
  2489  			} else if t.kind == RTPCodecTypeAudio {
  2490  				audio = append(audio, t)
  2491  			}
  2492  			if sender := t.Sender(); sender != nil {
  2493  				sender.setNegotiated()
  2494  			}
  2495  		}
  2496  
  2497  		if len(video) > 0 {
  2498  			mediaSections = append(mediaSections, mediaSection{id: "video", transceivers: video})
  2499  		}
  2500  		if len(audio) > 0 {
  2501  			mediaSections = append(mediaSections, mediaSection{id: "audio", transceivers: audio})
  2502  		}
  2503  
  2504  		if pc.sctpTransport.dataChannelsRequested != 0 {
  2505  			mediaSections = append(mediaSections, mediaSection{id: "data", data: true})
  2506  		}
  2507  	} else {
  2508  		for _, t := range transceivers {
  2509  			if sender := t.Sender(); sender != nil {
  2510  				sender.setNegotiated()
  2511  			}
  2512  			mediaSections = append(mediaSections, mediaSection{id: t.Mid(), transceivers: []*RTPTransceiver{t}})
  2513  		}
  2514  
  2515  		if pc.sctpTransport.dataChannelsRequested != 0 {
  2516  			mediaSections = append(mediaSections, mediaSection{id: strconv.Itoa(len(mediaSections)), data: true})
  2517  		}
  2518  	}
  2519  
  2520  	dtlsFingerprints, err := pc.configuration.Certificates[0].GetFingerprints()
  2521  	if err != nil {
  2522  		return nil, err
  2523  	}
  2524  
  2525  	return populateSDP(d, isPlanB, dtlsFingerprints, pc.api.settingEngine.sdpMediaLevelFingerprints, pc.api.settingEngine.candidates.ICELite, true, pc.api.mediaEngine, connectionRoleFromDtlsRole(defaultDtlsRoleOffer), candidates, iceParams, mediaSections, pc.ICEGatheringState(), nil)
  2526  }
  2527  
  2528  // generateMatchedSDP generates a SDP and takes the remote state into account
  2529  // this is used everytime we have a RemoteDescription
  2530  // nolint: gocyclo
  2531  func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, useIdentity bool, includeUnmatched bool, connectionRole sdp.ConnectionRole) (*sdp.SessionDescription, error) { //nolint:gocognit
  2532  	d, err := sdp.NewJSEPSessionDescription(useIdentity)
  2533  	if err != nil {
  2534  		return nil, err
  2535  	}
  2536  	d.Attributes = append(d.Attributes, sdp.Attribute{Key: sdp.AttrKeyMsidSemantic, Value: "WMS*"})
  2537  
  2538  	iceParams, err := pc.iceGatherer.GetLocalParameters()
  2539  	if err != nil {
  2540  		return nil, err
  2541  	}
  2542  
  2543  	candidates, err := pc.iceGatherer.GetLocalCandidates()
  2544  	if err != nil {
  2545  		return nil, err
  2546  	}
  2547  
  2548  	var t *RTPTransceiver
  2549  	remoteDescription := pc.currentRemoteDescription
  2550  	if pc.pendingRemoteDescription != nil {
  2551  		remoteDescription = pc.pendingRemoteDescription
  2552  	}
  2553  	isExtmapAllowMixed := isExtMapAllowMixedSet(remoteDescription.parsed)
  2554  	localTransceivers := append([]*RTPTransceiver{}, transceivers...)
  2555  
  2556  	detectedPlanB := descriptionIsPlanB(remoteDescription, pc.log)
  2557  	if pc.configuration.SDPSemantics != SDPSemanticsUnifiedPlan {
  2558  		detectedPlanB = descriptionPossiblyPlanB(remoteDescription)
  2559  	}
  2560  
  2561  	mediaSections := []mediaSection{}
  2562  	alreadyHaveApplicationMediaSection := false
  2563  	for _, media := range remoteDescription.parsed.MediaDescriptions {
  2564  		midValue := getMidValue(media)
  2565  		if midValue == "" {
  2566  			return nil, errPeerConnRemoteDescriptionWithoutMidValue
  2567  		}
  2568  
  2569  		if media.MediaName.Media == mediaSectionApplication {
  2570  			mediaSections = append(mediaSections, mediaSection{id: midValue, data: true})
  2571  			alreadyHaveApplicationMediaSection = true
  2572  			continue
  2573  		}
  2574  
  2575  		kind := NewRTPCodecType(media.MediaName.Media)
  2576  		direction := getPeerDirection(media)
  2577  		if kind == 0 || direction == RTPTransceiverDirectionUnknown {
  2578  			continue
  2579  		}
  2580  
  2581  		sdpSemantics := pc.configuration.SDPSemantics
  2582  
  2583  		switch {
  2584  		case sdpSemantics == SDPSemanticsPlanB || sdpSemantics == SDPSemanticsUnifiedPlanWithFallback && detectedPlanB:
  2585  			if !detectedPlanB {
  2586  				return nil, &rtcerr.TypeError{Err: fmt.Errorf("%w: Expected PlanB, but RemoteDescription is UnifiedPlan", ErrIncorrectSDPSemantics)}
  2587  			}
  2588  			// If we're responding to a plan-b offer, then we should try to fill up this
  2589  			// media entry with all matching local transceivers
  2590  			mediaTransceivers := []*RTPTransceiver{}
  2591  			for {
  2592  				// keep going until we can't get any more
  2593  				t, localTransceivers = satisfyTypeAndDirection(kind, direction, localTransceivers)
  2594  				if t == nil {
  2595  					if len(mediaTransceivers) == 0 {
  2596  						t = &RTPTransceiver{kind: kind, api: pc.api, codecs: pc.api.mediaEngine.getCodecsByKind(kind)}
  2597  						t.setDirection(RTPTransceiverDirectionInactive)
  2598  						mediaTransceivers = append(mediaTransceivers, t)
  2599  					}
  2600  					break
  2601  				}
  2602  				if sender := t.Sender(); sender != nil {
  2603  					sender.setNegotiated()
  2604  				}
  2605  				mediaTransceivers = append(mediaTransceivers, t)
  2606  			}
  2607  			mediaSections = append(mediaSections, mediaSection{id: midValue, transceivers: mediaTransceivers})
  2608  		case sdpSemantics == SDPSemanticsUnifiedPlan || sdpSemantics == SDPSemanticsUnifiedPlanWithFallback:
  2609  			if detectedPlanB {
  2610  				return nil, &rtcerr.TypeError{Err: fmt.Errorf("%w: Expected UnifiedPlan, but RemoteDescription is PlanB", ErrIncorrectSDPSemantics)}
  2611  			}
  2612  			t, localTransceivers = findByMid(midValue, localTransceivers)
  2613  			if t == nil {
  2614  				return nil, fmt.Errorf("%w: %q", errPeerConnTranscieverMidNil, midValue)
  2615  			}
  2616  			if sender := t.Sender(); sender != nil {
  2617  				sender.setNegotiated()
  2618  			}
  2619  			mediaTransceivers := []*RTPTransceiver{t}
  2620  
  2621  			extensions, _ := rtpExtensionsFromMediaDescription(media)
  2622  			mediaSections = append(mediaSections, mediaSection{id: midValue, transceivers: mediaTransceivers, matchExtensions: extensions, rids: getRids(media)})
  2623  		}
  2624  	}
  2625  
  2626  	var bundleGroup *string
  2627  	// If we are offering also include unmatched local transceivers
  2628  	if includeUnmatched {
  2629  		if !detectedPlanB {
  2630  			for _, t := range localTransceivers {
  2631  				if sender := t.Sender(); sender != nil {
  2632  					sender.setNegotiated()
  2633  				}
  2634  				mediaSections = append(mediaSections, mediaSection{id: t.Mid(), transceivers: []*RTPTransceiver{t}})
  2635  			}
  2636  		}
  2637  
  2638  		if pc.sctpTransport.dataChannelsRequested != 0 && !alreadyHaveApplicationMediaSection {
  2639  			if detectedPlanB {
  2640  				mediaSections = append(mediaSections, mediaSection{id: "data", data: true})
  2641  			} else {
  2642  				mediaSections = append(mediaSections, mediaSection{id: strconv.Itoa(len(mediaSections)), data: true})
  2643  			}
  2644  		}
  2645  	} else if remoteDescription != nil {
  2646  		groupValue, _ := remoteDescription.parsed.Attribute(sdp.AttrKeyGroup)
  2647  		groupValue = strings.TrimLeft(groupValue, "BUNDLE")
  2648  		bundleGroup = &groupValue
  2649  	}
  2650  
  2651  	if pc.configuration.SDPSemantics == SDPSemanticsUnifiedPlanWithFallback && detectedPlanB {
  2652  		pc.log.Info("Plan-B Offer detected; responding with Plan-B Answer")
  2653  	}
  2654  
  2655  	dtlsFingerprints, err := pc.configuration.Certificates[0].GetFingerprints()
  2656  	if err != nil {
  2657  		return nil, err
  2658  	}
  2659  
  2660  	return populateSDP(d, detectedPlanB, dtlsFingerprints, pc.api.settingEngine.sdpMediaLevelFingerprints, pc.api.settingEngine.candidates.ICELite, isExtmapAllowMixed, pc.api.mediaEngine, connectionRole, candidates, iceParams, mediaSections, pc.ICEGatheringState(), bundleGroup)
  2661  }
  2662  
  2663  func (pc *PeerConnection) setGatherCompleteHandler(handler func()) {
  2664  	pc.iceGatherer.onGatheringCompleteHandler.Store(handler)
  2665  }
  2666  
  2667  // SCTP returns the SCTPTransport for this PeerConnection
  2668  //
  2669  // The SCTP transport over which SCTP data is sent and received. If SCTP has not been negotiated, the value is nil.
  2670  // https://www.w3.org/TR/webrtc/#attributes-15
  2671  func (pc *PeerConnection) SCTP() *SCTPTransport {
  2672  	return pc.sctpTransport
  2673  }