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