Esempio n. 1
0
        public async Task <ICallInfo> PlaceCallAsync(CallConfiguration config)
        {
            Debug.Assert(_peerId == -1);

            if (PeerConnection != null)
            {
                Debug.WriteLine("[Error] We only support connection to one peer at a time.");
                return(null);
            }

            if (CreatePeerConnection())
            {
                string selectedAudioCodecName = (string)_localSettings.Values["SelectedAudioCodecName"];
                string selectedVideoCodecName = (string)_localSettings.Values["SelectedVideoCodecName"];

                _peerId = PeerId;

                var offerOptions = new RTCOfferOptions();
                offerOptions.OfferToReceiveAudio = true;
                offerOptions.OfferToReceiveVideo = true;
                IRTCSessionDescription offer = await PeerConnection.CreateOffer(offerOptions);

                // Alter sdp to force usage of selected codecs
                string modifiedSdp = offer.Sdp;
                SdpUtils.SelectCodec(ref modifiedSdp, selectedAudioCodecName, "audio");
                SdpUtils.SelectCodec(ref modifiedSdp, selectedVideoCodecName, "video");
                RTCSessionDescriptionInit sdpInit = new RTCSessionDescriptionInit();
                sdpInit.Sdp  = modifiedSdp;
                sdpInit.Type = offer.SdpType;
                var modifiedOffer = new RTCSessionDescription(sdpInit);
                await PeerConnection.SetLocalDescription(modifiedOffer);

                Debug.WriteLine($"Sending offer: {modifiedOffer.Sdp}");

                string jsonString = SdpToJsonString(modifiedOffer);

                CallInfo callInfo = new CallInfo();
                callInfo.SetCall(new Call());
                callInfo.SetSdp(modifiedSdp);
                callInfo.SetJsonString(jsonString);

                OnSendMessageToRemotePeer.Invoke(this, jsonString);

                return(callInfo);
            }
            return(null);
        }
Esempio n. 2
0
        /// <summary>
        /// Called when WebRTC detects another ICE candidate.
        /// This candidate needs to be sent to the other peer.
        /// </summary>
        /// <param name="Event">Details about RTCPeerConnectionIceEvent</param>
        private void PeerConnection_OnIceCandidate(IRTCPeerConnectionIceEvent Event)
        {
            if (Event.Candidate == null)
            {
                return;
            }

            double index = (double)Event.Candidate.SdpMLineIndex;

            JsonObject json = null;

            json = new JsonObject
            {
                { NegotiationAtributes.SdpMid, JsonValue.CreateStringValue(Event.Candidate.SdpMid) },
                { NegotiationAtributes.SdpMLineIndex, JsonValue.CreateNumberValue(index) },
                { NegotiationAtributes.Candidate, JsonValue.CreateStringValue(Event.Candidate.Candidate) }
            };

            Debug.WriteLine($"Send ice candidate:\n{json.Stringify()}");

            OnSendMessageToRemotePeer.Invoke(this, json.Stringify());
        }
Esempio n. 3
0
        public void MessageFromPeerTaskRun(int peerId, string content)
        {
            PeerId = peerId;

            Task.Run(async() =>
            {
                Debug.Assert(_peerId == PeerId || _peerId == -1);
                Debug.Assert(content.Length > 0);

                if (_peerId != PeerId && _peerId != -1)
                {
                    Debug.WriteLine("Received a message from unknown peer " +
                                    "while already in a conversation with a different peer.");

                    return;
                }

                if (!JsonObject.TryParse(content, out JsonObject jMessage))
                {
                    Debug.WriteLine($"Received unknown message: {content}");
                    return;
                }

                string type = jMessage.ContainsKey(NegotiationAtributes.Type)
                       ? jMessage.GetNamedString(NegotiationAtributes.Type)
                       : null;

                if (PeerConnection == null)
                {
                    if (!string.IsNullOrEmpty(type))
                    {
                        // Create the peer connection only when call is
                        // about to get initiated. Otherwise ignore the
                        // message from peers which could be result
                        // of old (but not yet fully closed) connections.
                        if (type == "offer" || type == "answer" || type == "json")
                        {
                            Debug.Assert(_peerId == -1);
                            _peerId = PeerId;

                            if (!CreatePeerConnection())
                            {
                                Debug.WriteLine("Failed to initialize our PeerConnection instance");

                                OnSignedOut.Invoke(this, null);
                                return;
                            }
                            else if (_peerId != PeerId)
                            {
                                Debug.WriteLine("Received a message from unknown peer while already " +
                                                "in a conversation with a different peer.");

                                return;
                            }
                        }
                    }
                    else
                    {
                        Debug.WriteLine("[Warn] Received an untyped message after closing peer connection.");
                        return;
                    }
                }

                if (PeerConnection != null && !string.IsNullOrEmpty(type))
                {
                    if (type == "offer-loopback")
                    {
                        // Loopback not supported
                        Debug.Assert(false);
                    }

                    string sdp = null;

                    sdp = jMessage.ContainsKey(NegotiationAtributes.Sdp)
                          ? jMessage.GetNamedString(NegotiationAtributes.Sdp)
                          : null;

                    if (string.IsNullOrEmpty(sdp))
                    {
                        Debug.WriteLine("[Error] Can't parse received session description message.");
                        return;
                    }

                    Debug.WriteLine($"Received session description:\n{content}");

                    RTCSdpType messageType = RTCSdpType.Offer;
                    switch (type)
                    {
                    case "offer": messageType = RTCSdpType.Offer; break;

                    case "answer": messageType = RTCSdpType.Answer; break;

                    case "pranswer": messageType = RTCSdpType.Pranswer; break;

                    default: Debug.Assert(false, type); break;
                    }

                    var sdpInit     = new RTCSessionDescriptionInit();
                    sdpInit.Sdp     = sdp;
                    sdpInit.Type    = messageType;
                    var description = new RTCSessionDescription(sdpInit);

                    await PeerConnection.SetRemoteDescription(description);

                    if (messageType == RTCSdpType.Offer)
                    {
                        var answerOptions             = new RTCAnswerOptions();
                        IRTCSessionDescription answer = await PeerConnection.CreateAnswer(answerOptions);
                        await PeerConnection.SetLocalDescription(answer);
                        string jsonString = SdpToJsonString(answer);
                        // Send answer
                        OnSendMessageToRemotePeer.Invoke(this, jsonString);
                    }
                }
                else
                {
                    RTCIceCandidate candidate = null;

                    string sdpMid = jMessage.ContainsKey(NegotiationAtributes.SdpMid)
                           ? jMessage.GetNamedString(NegotiationAtributes.SdpMid)
                           : null;

                    double sdpMLineIndex = jMessage.ContainsKey(NegotiationAtributes.SdpMLineIndex)
                           ? jMessage.GetNamedNumber(NegotiationAtributes.SdpMLineIndex)
                           : -1;

                    string sdpCandidate = jMessage.ContainsKey(NegotiationAtributes.Candidate)
                           ? jMessage.GetNamedString(NegotiationAtributes.Candidate)
                           : null;

                    if (string.IsNullOrEmpty(sdpMid) || sdpMLineIndex == -1 || string.IsNullOrEmpty(sdpCandidate))
                    {
                        Debug.WriteLine($"[Error] Can't parse received message.\n{content}");
                        return;
                    }

                    var candidateInit           = new RTCIceCandidateInit();
                    candidateInit.Candidate     = sdpCandidate;
                    candidateInit.SdpMid        = sdpMid;
                    candidateInit.SdpMLineIndex = (ushort)sdpMLineIndex;
                    candidate = new RTCIceCandidate(candidateInit);

                    await PeerConnection.AddIceCandidate(candidate);

                    Debug.WriteLine($"Receiving ice candidate:\n{content}");
                }
            }).Wait();
        }