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 }