CreateOffer starts the PeerConnection and generates the localDescription https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer nolint:gocognit,cyclop
(options *OfferOptions)
| 684 | // |
| 685 | //nolint:gocognit,cyclop |
| 686 | func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription, error) { |
| 687 | useIdentity := pc.idpLoginURL != nil |
| 688 | switch { |
| 689 | case useIdentity: |
| 690 | return SessionDescription{}, errIdentityProviderNotImplemented |
| 691 | case pc.isClosed.Load(): |
| 692 | return SessionDescription{}, &rtcerr.InvalidStateError{Err: ErrConnectionClosed} |
| 693 | } |
| 694 | |
| 695 | if options != nil && options.ICERestart { |
| 696 | if err := pc.iceTransport.restart(); err != nil { |
| 697 | return SessionDescription{}, err |
| 698 | } |
| 699 | } |
| 700 | |
| 701 | var ( |
| 702 | descr *sdp.SessionDescription |
| 703 | offer SessionDescription |
| 704 | err error |
| 705 | ) |
| 706 | |
| 707 | // This may be necessary to recompute if, for example, createOffer was called when only an |
| 708 | // audio RTCRtpTransceiver was added to connection, but while performing the in-parallel |
| 709 | // steps to create an offer, a video RTCRtpTransceiver was added, requiring additional |
| 710 | // inspection of video system resources. |
| 711 | count := 0 |
| 712 | pc.mu.Lock() |
| 713 | defer pc.mu.Unlock() |
| 714 | for { |
| 715 | // We cache current transceivers to ensure they aren't |
| 716 | // mutated during offer generation. We later check if they have |
| 717 | // been mutated and recompute the offer if necessary. |
| 718 | currentTransceivers := pc.rtpTransceivers |
| 719 | |
| 720 | // in-parallel steps to create an offer |
| 721 | // https://w3c.github.io/webrtc-pc/#dfn-in-parallel-steps-to-create-an-offer |
| 722 | isPlanB := pc.configuration.SDPSemantics == SDPSemanticsPlanB |
| 723 | if pc.currentRemoteDescription != nil && isPlanB { |
| 724 | isPlanB = descriptionPossiblyPlanB(pc.currentRemoteDescription) |
| 725 | } |
| 726 | |
| 727 | // include unmatched local transceivers |
| 728 | if !isPlanB { //nolint:nestif |
| 729 | // update the greater mid if the remote description provides a greater one |
| 730 | if pc.currentRemoteDescription != nil { |
| 731 | var numericMid int |
| 732 | for _, media := range pc.currentRemoteDescription.parsed.MediaDescriptions { |
| 733 | mid := getMidValue(media) |
| 734 | if mid == "" { |
| 735 | continue |
| 736 | } |
| 737 | numericMid, err = strconv.Atoi(mid) |
| 738 | if err != nil { |
| 739 | continue |
| 740 | } |
| 741 | if numericMid > pc.greaterMid { |
| 742 | pc.greaterMid = numericMid |
| 743 | } |