コード例 #1
0
        public void SetRemoteDescriptionThrowException()
        {
            var peer = new RTCPeerConnection();
            RTCSessionDescription empty = new RTCSessionDescription();

            Assert.Throws <ArgumentException>(() => peer.SetRemoteDescription(ref empty));

            RTCSessionDescription invalid = new RTCSessionDescription {
                sdp = "this is invalid parameter"
            };

            Assert.Throws <RTCErrorException>(() => peer.SetRemoteDescription(ref invalid));

            peer.Dispose();
        }
コード例 #2
0
        public IEnumerator UnitySetUp()
        {
            WebRTC.WebRTC.Initialize();

            RTCConfiguration config     = default;
            RTCIceCandidate  candidate_ = null;

            config.iceServers = new[] { new RTCIceServer {
                                            urls = new[] { "stun:stun.l.google.com:19302" }
                                        } };

            var peer1 = new RTCPeerConnection(ref config);
            var peer2 = new RTCPeerConnection(ref config);

            peer1.OnIceCandidate = candidate => { candidate_ = candidate; };

            MediaStream stream = WebRTC.Audio.CaptureStream();

            peer1.AddTrack(stream.GetTracks().First());

            RTCOfferOptions offerOptions = new RTCOfferOptions();
            var             op1          = peer1.CreateOffer(ref offerOptions);

            yield return(op1);

            m_DescOffer = op1.Desc;
            var op2 = peer1.SetLocalDescription(ref m_DescOffer);

            yield return(op2);

            var op3 = peer2.SetRemoteDescription(ref m_DescOffer);

            yield return(op3);

            RTCAnswerOptions answerOptions = new RTCAnswerOptions();
            var op4 = peer2.CreateAnswer(ref answerOptions);

            yield return(op4);

            m_DescAnswer = op4.Desc;
            var op5 = peer2.SetLocalDescription(ref m_DescAnswer);

            yield return(op5);

            var op6 = peer1.SetRemoteDescription(ref m_DescAnswer);

            yield return(op6);

            yield return(new WaitUntil(() => candidate_ != null));

            m_candidate = candidate_;

            stream.Dispose();
            peer1.Close();
            peer2.Close();

            m_Context  = SynchronizationContext.Current;
            signaling1 = CreateSignaling(m_SignalingType, m_Context);
            signaling2 = CreateSignaling(m_SignalingType, m_Context);
        }
コード例 #3
0
        public IEnumerator CreateAnswer()
        {
            var config = GetDefaultConfiguration();

            var peer1 = new RTCPeerConnection(ref config);
            var peer2 = new RTCPeerConnection(ref config);

            peer1.CreateDataChannel("data");

            var op1 = peer1.CreateOffer();

            yield return(op1);

            var desc = op1.Desc;
            var op2  = peer1.SetLocalDescription(ref desc);

            yield return(op2);

            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            var op4 = peer2.CreateAnswer();

            yield return(op4);

            Assert.True(op4.IsDone);
            Assert.False(op4.IsError);

            peer1.Close();
            peer2.Close();
            peer1.Dispose();
            peer2.Dispose();
        }
コード例 #4
0
    private IEnumerator OnOffer(RTCSessionDescription desc)
    {
        Debug.Log("OnOffer");
        Debug.Log("SetRemoteDescription start");
        var op = pc.SetRemoteDescription(ref desc);

        yield return(op);

        if (!op.IsError)
        {
            Debug.Log("SetRemoteDescription succeed");
        }
        else
        {
            Debug.Log("SetLocalDescription failed");
        }

        var op1 = pc.CreateAnswer(ref _answerOptions);

        yield return(op1);

        if (!op1.IsError)
        {
            Debug.Log("CreateAnswer succeed");
            yield return(OnCreateAnswerSuccess(op1.Desc));
        }
        else
        {
            Debug.Log("CreateAnswer failed");
        }
    }
コード例 #5
0
    private IEnumerator SetAnswer()
    {
        var answer = new RTCSessionDescription {
            type = RTCSdpType.Answer, sdp = answerSdpInput.text
        };

        Debug.Log($"Modified Answer from RemotePeerConnection\n{answer.sdp}");

        var opLocal = pcRemote.SetLocalDescription(ref answer);

        yield return(opLocal);

        if (opLocal.IsError)
        {
            OnSetSessionDescriptionError(opLocal.Error);
            yield break;
        }

        Debug.Log("Set Local session description success on RemotePeerConnection");

        var opRemote = pcLocal.SetRemoteDescription(ref answer);

        yield return(opRemote);

        if (opRemote.IsError)
        {
            OnSetSessionDescriptionError(opRemote.Error);
            yield break;
        }

        Debug.Log("Set Remote session description success on LocalPeerConnection");
    }
コード例 #6
0
        private IEnumerator setRemoteDesc(RTCSdpType type, string sdp)
        {
            var desc = new RTCSessionDescription
            {
                type = type,
                sdp  = sdp
            };

            OnLogEvent.Invoke($"SetRemoteDescription {type}", "");
            var opSetDesc = peer.SetRemoteDescription(ref desc);

            yield return(opSetDesc);

            if (opSetDesc.IsError)
            {
                OnErrorEvent.Invoke($"SetRemoteDescription {type}", opSetDesc.Error.message);
                yield break;
            }

            if (type == RTCSdpType.Offer)
            {
                yield return(CoroutineHandler.StartStaticCoroutine(sendDesc(RTCSdpType.Answer)));
            }
            else
            {
                OnOpen.Invoke();
            }
        }
コード例 #7
0
        IEnumerator GetOffer()
        {
            var op = signaling.GetOffer(sessionId, lastTimeGetOfferRequest);

            yield return(op);

            if (op.webRequest.isNetworkError)
            {
                Debug.LogError($"Network Error: {op.webRequest.error}");
                yield break;
            }
            var date = DateTimeExtension.ParseHttpDate(op.webRequest.GetResponseHeader("Date"));

            lastTimeGetOfferRequest = date.ToJsMilliseconds();

            var obj = op.webRequest.DownloadHandlerJson <OfferResDataList>().GetObject();

            if (obj == null)
            {
                yield break;
            }
            foreach (var offer in obj.offers)
            {
                RTCSessionDescription _desc;
                _desc.type = RTCSdpType.Offer;
                _desc.sdp  = offer.sdp;
                var connectionId = offer.connectionId;
                if (pcs.ContainsKey(connectionId))
                {
                    continue;
                }
                var pc = new RTCPeerConnection();
                pc.OnStatsDelivered = (data) => Debug.Log(data);

                pcs.Add(offer.connectionId, pc);
                pc.OnDataChannel = new DelegateOnDataChannel(channel => { OnDataChannel(pc, channel); });
                pc.SetConfiguration(ref conf);
                pc.OnIceCandidate        = new DelegateOnIceCandidate(candidate => { StartCoroutine(OnIceCandidate(offer.connectionId, candidate)); });
                pc.OnIceConnectionChange = new DelegateOnIceConnectionChange(state =>
                {
                    if (state == RTCIceConnectionState.Disconnected)
                    {
                        pc.Close();
                    }
                });
                //make video bit rate starts at 16000kbits, and 160000kbits at max.
                string pattern = @"(a=fmtp:\d+ .*level-asymmetry-allowed=.*)\r\n";
                _desc.sdp = Regex.Replace(_desc.sdp, pattern, "$1;x-google-start-bitrate=16000;x-google-max-bitrate=160000\r\n");
                pc.SetRemoteDescription(ref _desc);
                foreach (var track in videoStream.GetTracks())
                {
                    pc.AddTrack(track);
                }
                foreach (var track in audioStream.GetTracks())
                {
                    pc.AddTrack(track);
                }
                StartCoroutine(Answer(connectionId));
            }
        }
コード例 #8
0
    /// <summary>
    /// Process JSON messages received from the remote peer. The only messages will be the SDP answer and
    /// ICE candidates.
    /// </summary>
    private void OnMessage(string jsonStr, RTCPeerConnection pc)
    {
        var msgType = JsonRTC.TryGetType(jsonStr);

        Debug.WriteLine($"JSON message type {msgType}.");

        switch (msgType)
        {
        case JsonRTC.JsonMessageType.IceCandidate:
            if (JsonRTC.TryParseIceCandidate(jsonStr, out var iceCandidateInit))
            {
                Debug.WriteLine($"Got remote ICE candidate, {iceCandidateInit.candidate}.");
                _pc.AddIceCandidate(ref iceCandidateInit);
            }
            break;

        case JsonRTC.JsonMessageType.SdpDescription:
            if (JsonRTC.TryParseDescription(jsonStr, out var desc))
            {
                Debug.WriteLine($"Got remote SDP, type {desc.type}.");
                Debug.WriteLine(desc.sdp);
                var  setRemoteOp = _pc.SetRemoteDescription(ref desc);
                bool isDone      = setRemoteOp.MoveNext();
                Debug.WriteLine($"Set remote description is done {isDone}, error {setRemoteOp.IsError}, signalling state {pc.SignalingState}.");
            }
            break;

        default:
            Debug.WriteLine($"node-dss could not parse JSON message. {jsonStr}");
            break;
        }
    }
コード例 #9
0
        private async void NewElement_AnswerRequested(object sender, SdpEventArgs e)
        {
            await _peerConnection.SetRemoteDescription(e.Sdp.ToRTCSessionDescription());

            Debug.WriteLine("AnswerRequested SetRemoteDescription complete");

            var answerDesc = await _peerConnection.CreateAnswer();

            Debug.WriteLine("AnswerRequested CreateAnswer complete");

            await _peerConnection.SetLocalDescription(answerDesc);

            Debug.WriteLine("AnswerRequested SetLocalDescription complete");

            Element.SendAnswerRecived(answerDesc.ToWebRTCSDP());
        }
コード例 #10
0
    IEnumerator OnCreateAnswerSuccess(RTCSessionDescription desc)
    {
        Debug.Log($"Answer from pc2:\n{desc.sdp}");
        Debug.Log("pc2 setLocalDescription start");
        var op = pc2.SetLocalDescription(ref desc);

        yield return(op);

        if (!op.IsError)
        {
            OnSetLocalSuccess(pc2);
        }
        else
        {
            var error = op.Error;
            OnSetSessionDescriptionError(ref error);
        }

        Debug.Log("pc1 setRemoteDescription start");

        var op2 = pc1.SetRemoteDescription(ref desc);

        yield return(op2);

        if (!op2.IsError)
        {
            OnSetRemoteSuccess(pc1);
        }
        else
        {
            var error = op2.Error;
            OnSetSessionDescriptionError(ref error);
        }
    }
コード例 #11
0
        public IEnumerator CurrentDirection()
        {
            var config     = GetConfiguration();
            var peer1      = new RTCPeerConnection(ref config);
            var peer2      = new RTCPeerConnection(ref config);
            var audioTrack = new AudioStreamTrack("audio");

            var transceiver1 = peer1.AddTransceiver(TrackKind.Audio);

            transceiver1.Direction = RTCRtpTransceiverDirection.RecvOnly;
            Assert.IsNull(transceiver1.CurrentDirection);

            RTCOfferOptions options1 = new RTCOfferOptions {
                offerToReceiveAudio = true
            };
            RTCAnswerOptions options2 = default;
            var op1 = peer1.CreateOffer(ref options1);

            yield return(op1);

            var desc = op1.Desc;
            var op2  = peer1.SetLocalDescription(ref desc);

            yield return(op2);

            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            var transceiver2 = peer2.GetTransceivers().First(x => x.Receiver.Track.Kind == TrackKind.Audio);

            Assert.True(transceiver2.Sender.ReplaceTrack(audioTrack));
            transceiver2.Direction = RTCRtpTransceiverDirection.SendOnly;

            var op4 = peer2.CreateAnswer(ref options2);

            yield return(op4);

            desc = op4.Desc;
            var op5 = peer2.SetLocalDescription(ref desc);

            yield return(op5);

            var op6 = peer1.SetRemoteDescription(ref desc);

            yield return(op6);

            Assert.AreEqual(transceiver1.CurrentDirection, RTCRtpTransceiverDirection.RecvOnly);
            Assert.AreEqual(transceiver2.CurrentDirection, RTCRtpTransceiverDirection.SendOnly);

            audioTrack.Dispose();
            peer1.Close();
            peer2.Close();
            peer1.Dispose();
            peer2.Dispose();
        }
コード例 #12
0
 void RecieveOffer()
 {
     if (_rtcType != RTCTYPE.ANSWER)
     {
         return;
     }
     //var offer = ConvertText2desc(_recieveSDPText, true);
     RecieveSDP((offer) => {
         try
         {
             Debug.Log($"recieve offer");
             localConnection.SetRemoteDescription(ref offer);
             StartCoroutine(CreateAnswer());
         }
         catch
         {
             Debug.Log("cant offer recieve");
         }
     });
 }
コード例 #13
0
        private static IEnumerator SignalingPeers(RTCPeerConnection offerPc, RTCPeerConnection answerPc)
        {
            offerPc.OnIceCandidate = candidate => answerPc.AddIceCandidate(ref candidate);
            answerPc.OnIceCandidate = candidate => offerPc.AddIceCandidate(ref candidate);

            var offerOption = new RTCOfferOptions {offerToReceiveVideo = true};
            var answerOption = new RTCAnswerOptions {iceRestart = false};

            var pc1CreateOffer = offerPc.CreateOffer(ref offerOption);
            yield return pc1CreateOffer;
            Assert.False(pc1CreateOffer.IsError);
            var offerDesc = pc1CreateOffer.Desc;

            var pc1SetLocalDescription = offerPc.SetLocalDescription(ref offerDesc);
            yield return pc1SetLocalDescription;
            Assert.False(pc1SetLocalDescription.IsError);

            var pc2SetRemoteDescription = answerPc.SetRemoteDescription(ref offerDesc);
            yield return pc2SetRemoteDescription;
            Assert.False(pc2SetRemoteDescription.IsError);

            var pc2CreateAnswer = answerPc.CreateAnswer(ref answerOption);
            yield return pc2CreateAnswer;
            Assert.False(pc2CreateAnswer.IsError);
            var answerDesc = pc2CreateAnswer.Desc;

            var pc2SetLocalDescription = answerPc.SetLocalDescription(ref answerDesc);
            yield return pc2SetLocalDescription;
            Assert.False(pc2SetLocalDescription.IsError);

            var pc1SetRemoteDescription = offerPc.SetRemoteDescription(ref answerDesc);
            yield return pc1SetRemoteDescription;
            Assert.False(pc1SetRemoteDescription.IsError);

            var waitConnectOfferPc = new WaitUntilWithTimeout(() =>
                offerPc.IceConnectionState == RTCIceConnectionState.Connected ||
                offerPc.IceConnectionState == RTCIceConnectionState.Completed, 5000);
            yield return waitConnectOfferPc;
            Assert.True(waitConnectOfferPc.IsCompleted);

            var waitConnectAnswerPc = new WaitUntilWithTimeout(() =>
                answerPc.IceConnectionState == RTCIceConnectionState.Connected ||
                answerPc.IceConnectionState == RTCIceConnectionState.Completed, 5000);
            yield return waitConnectAnswerPc;
            Assert.True(waitConnectAnswerPc.IsCompleted);

            var checkSenders = new WaitUntilWithTimeout(() => offerPc.GetSenders().Any(), 5000);
            yield return checkSenders;
            Assert.True(checkSenders.IsCompleted);

            var checkReceivers = new WaitUntilWithTimeout(() => answerPc.GetReceivers().Any(), 5000);
            yield return checkReceivers;
            Assert.True(checkReceivers.IsCompleted);
        }
コード例 #14
0
        IEnumerator Negotiate(RTCPeerConnection peer1, RTCPeerConnection peer2)
        {
            if (negotiating)
            {
                Debug.LogError("Negotiating");
                yield break;
            }
            negotiating = true;
            var op1 = peer1.CreateOffer();

            yield return(op1);

            Assert.That(op1.IsError, Is.False, op1.Error.message);
            var desc = op1.Desc;
            var op2  = peer1.SetLocalDescription(ref desc);

            yield return(op2);

            Assert.That(op2.IsError, Is.False, op2.Error.message);

            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            Assert.That(op3.IsError, Is.False, op3.Error.message);
            var op4 = peer2.CreateAnswer();

            yield return(op4);

            Assert.That(op4.IsError, Is.False, op4.Error.message);
            desc = op4.Desc;
            var op5 = peer2.SetLocalDescription(ref desc);

            yield return(op5);

            Assert.That(op5.IsError, Is.False, op5.Error.message);

            var op6 = peer1.SetRemoteDescription(ref desc);

            yield return(op6);

            Assert.That(op6.IsError, Is.False, op6.Error.message);

            var op7 = new WaitUntilWithTimeout(() =>
                                               peers[0].SignalingState == RTCSignalingState.Stable &&
                                               peers[1].SignalingState == RTCSignalingState.Stable, 5000);

            yield return(op7);

            Assert.That(op7.IsCompleted, Is.True);

            IsTestFinished = true;
            negotiating    = false;
        }
コード例 #15
0
    private IEnumerator OfferAnswerProcess(RTCSessionDescription description)
    {
        var isStable =
            pc.SignalingState == RTCSignalingState.Stable ||
            (pc.SignalingState == RTCSignalingState.HaveLocalOffer && srdAnswerPending);

        ignoreOffer =
            description.type == RTCSdpType.Offer && !polite && (makingOffer || !isStable);
        if (ignoreOffer)
        {
            Debug.Log($"{this} glare - ignoring offer");
            yield break;
        }

        yield return(new WaitWhile(() => makingOffer));

        srdAnswerPending = description.type == RTCSdpType.Answer;
        Debug.Log($"{this} SRD {description.type} SignalingState {pc.SignalingState}");
        var op1 = pc.SetRemoteDescription(ref description);

        yield return(op1);

        Assert.IsFalse(op1.IsError, $"{this} {op1.Error.message}");

        srdAnswerPending = false;
        if (description.type == RTCSdpType.Offer)
        {
            Assert.AreEqual(pc.RemoteDescription.type, RTCSdpType.Offer, $"{this} SRD worked");
            Assert.AreEqual(pc.SignalingState, RTCSignalingState.HaveRemoteOffer, $"{this} Remote offer");
            Debug.Log($"{this} SLD to get back to stable");
            sldGetBackStable = true;

            var op2 = pc.SetLocalDescription();
            yield return(op2);

            Assert.IsFalse(op2.IsError, $"{this} {op2.Error.message}");

            Assert.AreEqual(pc.LocalDescription.type, RTCSdpType.Answer, $"{this} onmessage SLD worked");
            Assert.AreEqual(pc.SignalingState, RTCSignalingState.Stable,
                            $"{this} onmessage not racing with negotiationneeded");
            sldGetBackStable = false;

            var answer = new Message {
                description = pc.LocalDescription
            };
            parent.PostMessage(this, answer);
        }
        else
        {
            Assert.AreEqual(pc.RemoteDescription.type, RTCSdpType.Answer, $"{this} Answer was set");
            Assert.AreEqual(pc.SignalingState, RTCSignalingState.Stable, $"{this} answered");
        }
    }
コード例 #16
0
    IEnumerator HandleOffer(string sdp)
    {
        Debug.Log("HandleOffer start");
        Debug.Log("setRemoteDescription start");
        var desc = new RTCSessionDescription {
            sdp = sdp, type = RTCSdpType.Offer
        };
        var op = peerConnection.SetRemoteDescription(ref desc);

        yield return(op);

        if (!op.IsError)
        {
            OnSetRemoteSuccess();
            yield return(StartCoroutine(CreateAnswer()));
        }
        else
        {
            var error = op.Error;
            OnSetSessionDescriptionError(ref error);
        }
    }
コード例 #17
0
        IEnumerator OnOffer(ISignaling signaling, DescData e)
        {
            var connectionId     = e.connectionId;
            RTCPeerConnection pc = null;

            if (!m_mapConnectionIdAndPeer.TryGetValue(connectionId, out pc))
            {
                pc = CreatePeerConnection(signaling, connectionId, false);
            }

            RTCSessionDescription _desc;

            _desc.type = RTCSdpType.Offer;
            _desc.sdp  = e.sdp;

            var opRemoteDesc = pc.SetRemoteDescription(ref _desc);

            yield return(opRemoteDesc);

            if (opRemoteDesc.IsError)
            {
                Debug.LogError($"Network Error: {opRemoteDesc.Error.message}");
                yield break;
            }

            AddTracks(connectionId, pc);

            RTCAnswerOptions options = default;
            var op = pc.CreateAnswer(ref options);

            yield return(op);

            if (op.IsError)
            {
                Debug.LogError($"Network Error: {op.Error.message}");
                yield break;
            }

            var desc        = op.Desc;
            var opLocalDesc = pc.SetLocalDescription(ref desc);

            yield return(opLocalDesc);

            if (opLocalDesc.IsError)
            {
                Debug.LogError($"Network Error: {opLocalDesc.Error.message}");
                yield break;
            }

            signaling.SendAnswer(connectionId, desc);
        }
コード例 #18
0
        IEnumerator GotAnswerCoroutine(string connectionId, RTCPeerConnection pc, string sdp)
        {
            var desc = new RTCSessionDescription();

            desc.type = RTCSdpType.Answer;
            desc.sdp  = sdp;
            var opRemoteSdp = pc.SetRemoteDescription(ref desc);

            yield return(opRemoteSdp);

            if (opRemoteSdp.IsError)
            {
                Debug.LogError($"Network Error: {opRemoteSdp.Error.message}");
            }
            onGotAnswer?.Invoke(connectionId, sdp);
        }
コード例 #19
0
        public IEnumerator SetRemoteDescription()
        {
            var config   = GetConfiguration();
            var peer1    = new RTCPeerConnection(ref config);
            var peer2    = new RTCPeerConnection(ref config);
            var conf     = new RTCDataChannelInit(true);
            var channel1 = peer1.CreateDataChannel("data", ref conf);

            RTCOfferOptions  options1 = default;
            RTCAnswerOptions options2 = default;
            var op1 = peer1.CreateOffer(ref options1);

            yield return(op1);

            var desc = op1.Desc;
            var op2  = peer1.SetLocalDescription(ref desc);

            yield return(op2);

            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            var op4 = peer2.CreateAnswer(ref options2);

            yield return(op4);

            desc = op4.Desc;
            var op5 = peer2.SetLocalDescription(ref desc);

            yield return(op5);

            var op6 = peer1.SetRemoteDescription(ref desc);

            yield return(op6);

            var desc2 = peer1.RemoteDescription;

            Assert.AreEqual(desc.sdp, desc2.sdp);
            Assert.AreEqual(desc.type, desc2.type);

            channel1.Dispose();
            peer1.Close();
            peer2.Close();
            peer1.Dispose();
            peer2.Dispose();
        }
        public IEnumerator PeerConnection_SetRemoteDescription()
        {
            RTCConfiguration config = default;

            config.iceServers = new[] { new RTCIceServer {
                                            urls = new[] { "stun:stun.l.google.com:19302" }
                                        } };
            var            peer1    = new RTCPeerConnection(ref config);
            var            peer2    = new RTCPeerConnection(ref config);
            RTCDataChannel channel1 = null;

            var conf = new RTCDataChannelInit(true);

            channel1 = peer1.CreateDataChannel("data", ref conf);

            RTCOfferOptions  options1 = default;
            RTCAnswerOptions options2 = default;
            var op1 = peer1.CreateOffer(ref options1);

            yield return(op1);

            var op2 = peer1.SetLocalDescription(ref op1.desc);

            yield return(op2);

            var op3 = peer2.SetRemoteDescription(ref op1.desc);

            yield return(op3);

            var op4 = peer2.CreateAnswer(ref options2);

            yield return(op4);

            var op5 = peer2.SetLocalDescription(ref op4.desc);

            yield return(op5);

            var op6 = peer1.SetRemoteDescription(ref op4.desc);

            yield return(op6);

            channel1.Dispose();
            peer1.Dispose();
            peer2.Dispose();
        }
コード例 #21
0
        IEnumerator GotOfferCoroutine(string connectionId, RTCPeerConnection pc, string sdp)
        {
            RTCSessionDescription _desc;

            _desc.type = RTCSdpType.Offer;
            _desc.sdp  = sdp;

            var opRemoteDesc = pc.SetRemoteDescription(ref _desc);

            yield return(opRemoteDesc);

            if (opRemoteDesc.IsError)
            {
                Debug.LogError($"Network Error: {opRemoteDesc.Error.message}");
                yield break;
            }
            onGotOffer?.Invoke(connectionId, sdp);
        }
コード例 #22
0
    IEnumerator proccessAnswer(string sdp)
    {
        //string pattern = @"(a=fmtp:\d+ .*level-asymmetry-allowed=.*)\r\n";
        //sdp = Regex.Replace(sdp, pattern, "$1;x-google-start-bitrate=16000;x-google-max-bitrate=160000\r\n");
        RTCSessionDescription answer = default;

        answer.type = RTCSdpType.Answer;
        answer.sdp  = sdp;
        Debug.Log($"set remote answer: {sdp}");
        var ret = pc.SetRemoteDescription(ref answer);

        yield return(ret);

        if (ret.isError)
        {
            Debug.Log($"processAnser error:{ret.error}");
        }
    }
コード例 #23
0
        public IEnumerator SetRemoteDescriptionFailed()
        {
            var config = GetDefaultConfiguration();
            var peer1  = new RTCPeerConnection(ref config);
            var peer2  = new RTCPeerConnection(ref config);

            var stream = new MediaStream();
            var obj    = new GameObject("audio");
            var source = obj.AddComponent <AudioSource>();

            source.clip = AudioClip.Create("test", 480, 2, 48000, false);
            var track  = new AudioStreamTrack(source);
            var sender = peer1.AddTrack(track, stream);

            var op1 = peer1.CreateOffer();

            yield return(op1);

            var desc = op1.Desc;
            var op2  = peer1.SetLocalDescription(ref desc);

            yield return(op2);

            // change sdp to cannot parse
            desc.sdp = desc.sdp.Replace("a=mid:0", "a=mid:10");
            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            Assert.True(op3.IsDone);
            Assert.True(op3.IsError);
            Assert.IsNotEmpty(op3.Error.message);

            peer1.RemoveTrack(sender);
            track.Dispose();
            stream.Dispose();
            peer1.Close();
            peer2.Close();
            peer1.Dispose();
            peer2.Dispose();
            Object.DestroyImmediate(source.clip);
            Object.DestroyImmediate(obj);
        }
コード例 #24
0
        private IEnumerator SignalingOffer(RTCPeerConnection @from, RTCPeerConnection to)
        {
            var op1 = @from.CreateOffer();

            yield return(op1);

            var desc = op1.Desc;
            var op2  = @from.SetLocalDescription(ref desc);

            yield return(op2);

            var op3 = to.SetRemoteDescription(ref desc);

            yield return(op3);

            var op4 = to.CreateAnswer();

            yield return(op4);

            desc = op4.Desc;
            var op5 = to.SetLocalDescription(ref desc);

            yield return(op5);

            var op6 = @from.SetRemoteDescription(ref desc);

            yield return(op6);

            var op7 = new WaitUntilWithTimeout(
                () => @from.IceConnectionState == RTCIceConnectionState.Connected ||
                @from.IceConnectionState == RTCIceConnectionState.Completed, 5000);

            yield return(op7);

            Assert.That(op7.IsCompleted, Is.True);
            var op8 = new WaitUntilWithTimeout(
                () => to.IceConnectionState == RTCIceConnectionState.Connected ||
                to.IceConnectionState == RTCIceConnectionState.Completed, 5000);

            yield return(op8);

            Assert.That(op8.IsCompleted, Is.True);
        }
コード例 #25
0
        public IEnumerator SetRemoteDescriptionFailed()
        {
            var config = GetConfiguration();
            var peer1  = new RTCPeerConnection(ref config);
            var peer2  = new RTCPeerConnection(ref config);

            var stream = new MediaStream();
            var track  = new AudioStreamTrack("audio");
            var sender = peer1.AddTrack(track, stream);

            RTCOfferOptions options1 = default;
            var             op1      = peer1.CreateOffer(ref options1);

            yield return(op1);

            var desc = op1.Desc;
            var op2  = peer1.SetLocalDescription(ref desc);

            yield return(op2);

            // change sdp to cannot parse
            desc.sdp = desc.sdp.Replace("m=audio", "m=audiable");
            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            Assert.True(op3.IsDone);
            Assert.True(op3.IsError);
            Assert.IsNotEmpty(op3.Error.message);

            peer1.RemoveTrack(sender);
            track.Dispose();
            stream.Dispose();
            peer1.Close();
            peer2.Close();
            peer1.Dispose();
            peer2.Dispose();
        }
        private static IEnumerator NegotiationPeer(RTCPeerConnection localPeer, RTCPeerConnection remotePeer)
        {
            var opCreateOffer = localPeer.CreateOffer();

            yield return(opCreateOffer);

            if (opCreateOffer.IsError)
            {
                OnCreateSessionDescriptionError(opCreateOffer.Error);
                yield break;
            }

            var offerDesc = opCreateOffer.Desc;

            yield return(localPeer.SetLocalDescription(ref offerDesc));

            Debug.Log($"Offer from LocalPeer \n {offerDesc.sdp}");
            yield return(remotePeer.SetRemoteDescription(ref offerDesc));

            var opCreateAnswer = remotePeer.CreateAnswer();

            yield return(opCreateAnswer);

            if (opCreateAnswer.IsError)
            {
                OnCreateSessionDescriptionError(opCreateAnswer.Error);
                yield break;
            }

            var answerDesc = opCreateAnswer.Desc;

            yield return(remotePeer.SetLocalDescription(ref answerDesc));

            Debug.Log($"Answer from RemotePeer \n {answerDesc.sdp}");
            yield return(localPeer.SetRemoteDescription(ref answerDesc));
        }
コード例 #27
0
    private IEnumerator setRemoteDesc(RTCSdpType type, string sdp)
    {
        var desc = new RTCSessionDescription
        {
            type = type,
            sdp  = sdp
        };

        log(LogLevel.Log, $"SetRemoteDescription {type}");
        var opSetDesc = peer.SetRemoteDescription(ref desc);

        yield return(opSetDesc);

        if (opSetDesc.IsError)
        {
            log(LogLevel.Error, $"SetRemoteDescription {type}: {opSetDesc.Error.message}");
            yield break;
        }

        if (type == RTCSdpType.Offer)
        {
            yield return(StartCoroutine(createDesc(RTCSdpType.Answer)));
        }
    }
コード例 #28
0
        /// <summary>
        /// Handler for Signaller's OnMessageFromPeer event.
        /// </summary>
        /// <param name="peerId">ID of the peer.</param>
        /// <param name="message">Message from the peer.</param>
        private void Signaller_OnMessageFromPeer(int peerId, string message)
        {
            Task.Run(async() =>
            {
                Debug.Assert(_peerId == peerId || _peerId == -1);
                Debug.Assert(message.Length > 0);

                if (_peerId != peerId && _peerId != -1)
                {
                    Debug.WriteLine("[Error] Conductor: Received a message from unknown peer while already in a conversation with a different peer.");
                    return;
                }

                JsonObject jMessage;
                if (!JsonObject.TryParse(message, out jMessage))
                {
                    Debug.WriteLine("[Error] Conductor: Received unknown message." + message);
                    return;
                }

                string type = jMessage.ContainsKey(kSessionDescriptionTypeName) ? jMessage.GetNamedString(kSessionDescriptionTypeName) : null;
#if ORTCLIB
                bool created = false;
#endif
                if (_peerConnection == null)
                {
                    if (!IsNullOrEmpty(type))
                    {
                        // Create the peer connection only when call is
                        // about to get initiated. Otherwise ignore the
                        // messages from peers which could be a result
                        // of old (but not yet fully closed) connections.
                        if (type == "offer" || type == "answer" || type == "json")
                        {
                            Debug.Assert(_peerId == -1);
                            _peerId = peerId;

                            IEnumerable <Peer> enumerablePeer = Peers.Where(x => x.Id == peerId);
                            Peer = enumerablePeer.First();
#if ORTCLIB
                            created        = true;
                            _signalingMode = Helper.SignalingModeForClientName(Peer.Name);
#endif
                            _connectToPeerCancelationTokenSource = new CancellationTokenSource();
                            _connectToPeerTask = CreatePeerConnection(_connectToPeerCancelationTokenSource.Token);
                            bool connectResult = await _connectToPeerTask;
                            _connectToPeerTask = null;
                            _connectToPeerCancelationTokenSource.Dispose();
                            if (!connectResult)
                            {
                                Debug.WriteLine("[Error] Conductor: Failed to initialize our PeerConnection instance");
                                await Signaller.SignOut();
                                return;
                            }
                            else if (_peerId != peerId)
                            {
                                Debug.WriteLine("[Error] Conductor: Received a message from unknown peer while already in a conversation with a different peer.");
                                return;
                            }
                        }
                    }
                    else
                    {
                        Debug.WriteLine("[Warn] Conductor: Received an untyped message after closing peer connection.");
                        return;
                    }
                }

                if (_peerConnection != null && !IsNullOrEmpty(type))
                {
                    if (type == "offer-loopback")
                    {
                        // Loopback not supported
                        Debug.Assert(false);
                    }
                    string sdp = null;
#if ORTCLIB
                    if (jMessage.ContainsKey(kSessionDescriptionJsonName))
                    {
                        var containerObject = new JsonObject {
                            { kSessionDescriptionJsonName, jMessage.GetNamedObject(kSessionDescriptionJsonName) }
                        };
                        sdp = containerObject.Stringify();
                    }
                    else if (jMessage.ContainsKey(kSessionDescriptionSdpName))
                    {
                        sdp = jMessage.GetNamedString(kSessionDescriptionSdpName);
                    }
#else
                    sdp = jMessage.ContainsKey(kSessionDescriptionSdpName) ? jMessage.GetNamedString(kSessionDescriptionSdpName) : null;
#endif
                    if (IsNullOrEmpty(sdp))
                    {
                        Debug.WriteLine("[Error] Conductor: Can't parse received session description message.");
                        return;
                    }

#if ORTCLIB
                    RTCSessionDescriptionSignalingType messageType = RTCSessionDescriptionSignalingType.SdpOffer;
                    switch (type)
                    {
                    case "json": messageType = RTCSessionDescriptionSignalingType.Json; break;

                    case "offer": messageType = RTCSessionDescriptionSignalingType.SdpOffer; break;

                    case "answer": messageType = RTCSessionDescriptionSignalingType.SdpAnswer; break;

                    case "pranswer": messageType = RTCSessionDescriptionSignalingType.SdpPranswer; break;

                    default: Debug.Assert(false, type); break;
                    }
#else
                    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;
                    }
#endif
                    Debug.WriteLine("Conductor: Received session description: " + message);
                    await _peerConnection.SetRemoteDescription(new RTCSessionDescription(messageType, sdp));

#if ORTCLIB
                    if ((messageType == RTCSessionDescriptionSignalingType.SdpOffer) ||
                        ((created) && (messageType == RTCSessionDescriptionSignalingType.Json)))
#else
                    if (messageType == RTCSdpType.Offer)
#endif
                    {
                        var answer = await _peerConnection.CreateAnswer();
                        await _peerConnection.SetLocalDescription(answer);
                        // Send answer
                        SendSdp(answer);
#if ORTCLIB
                        OrtcStatsManager.Instance.StartCallWatch(SessionId, false);
#endif
                    }
                }
                else
                {
                    RTCIceCandidate candidate = null;
#if ORTCLIB
                    if (RTCPeerConnectionSignalingMode.Json != _signalingMode)
#endif
                    {
                        var sdpMid = jMessage.ContainsKey(kCandidateSdpMidName)
                            ? jMessage.GetNamedString(kCandidateSdpMidName)
                            : null;
                        var sdpMlineIndex = jMessage.ContainsKey(kCandidateSdpMlineIndexName)
                            ? jMessage.GetNamedNumber(kCandidateSdpMlineIndexName)
                            : -1;
                        var sdp = jMessage.ContainsKey(kCandidateSdpName)
                            ? jMessage.GetNamedString(kCandidateSdpName)
                            : null;
                        //TODO: Check is this proper condition ((String.IsNullOrEmpty(sdpMid) && (sdpMlineIndex == -1)) || String.IsNullOrEmpty(sdp))
                        if (IsNullOrEmpty(sdpMid) || sdpMlineIndex == -1 || IsNullOrEmpty(sdp))
                        {
                            Debug.WriteLine("[Error] Conductor: Can't parse received message.\n" + message);
                            return;
                        }
#if ORTCLIB
                        candidate = IsNullOrEmpty(sdpMid) ? RTCIceCandidate.FromSdpStringWithMLineIndex(sdp, (ushort)sdpMlineIndex) : RTCIceCandidate.FromSdpStringWithMid(sdp, sdpMid);
#else
                        candidate = new RTCIceCandidate(sdp, sdpMid, (ushort)sdpMlineIndex);
#endif
                    }
#if ORTCLIB
                    else
                    {
                        candidate = RTCIceCandidate.FromJsonString(message);
                    }
                    _peerConnection?.AddIceCandidate(candidate);
#else
                    await _peerConnection.AddIceCandidate(candidate);
#endif


                    Debug.WriteLine("Conductor: Received candidate : " + message);
                }
            }).Wait();
        }
コード例 #29
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();
        }
コード例 #30
0
        public IEnumerator Signaling()
        {
            offerPc.OnIceCandidate  = candidate => answerPc.AddIceCandidate(candidate);
            answerPc.OnIceCandidate = candidate => offerPc.AddIceCandidate(candidate);

            var pc1CreateOffer = offerPc.CreateOffer();

            yield return(pc1CreateOffer);

            Assert.That(pc1CreateOffer.IsError, Is.False, () => $"Failed {nameof(pc1CreateOffer)}, error:{pc1CreateOffer.Error.message}");
            var offerDesc = pc1CreateOffer.Desc;

            var pc1SetLocalDescription = offerPc.SetLocalDescription(ref offerDesc);

            yield return(pc1SetLocalDescription);

            Assert.That(pc1SetLocalDescription.IsError, Is.False, () => $"Failed {nameof(pc1SetLocalDescription)}, error:{pc1SetLocalDescription.Error.message}");

            var pc2SetRemoteDescription = answerPc.SetRemoteDescription(ref offerDesc);

            yield return(pc2SetRemoteDescription);

            Assert.That(pc2SetRemoteDescription.IsError, Is.False, () => $"Failed {nameof(pc2SetRemoteDescription)}, error:{pc2SetRemoteDescription.Error.message}");

            var pc2CreateAnswer = answerPc.CreateAnswer();

            yield return(pc2CreateAnswer);

            Assert.That(pc2CreateAnswer.IsError, Is.False, () => $"Failed {nameof(pc2CreateAnswer)}, error:{pc2CreateAnswer.Error.message}");
            var answerDesc = pc2CreateAnswer.Desc;

            var pc2SetLocalDescription = answerPc.SetLocalDescription(ref answerDesc);

            yield return(pc2SetLocalDescription);

            Assert.That(pc2SetLocalDescription.IsError, Is.False, () => $"Failed {nameof(pc2SetLocalDescription)}, error:{pc2SetLocalDescription.Error.message}");

            var pc1SetRemoteDescription = offerPc.SetRemoteDescription(ref answerDesc);

            yield return(pc1SetRemoteDescription);

            Assert.That(pc1SetRemoteDescription.IsError, Is.False, () => $"Failed {nameof(pc1SetRemoteDescription)}, error:{pc1SetRemoteDescription.Error.message}");

            var waitConnectOfferPc = new WaitUntilWithTimeout(() =>
                                                              offerPc.IceConnectionState == RTCIceConnectionState.Connected ||
                                                              offerPc.IceConnectionState == RTCIceConnectionState.Completed, 5000);

            yield return(waitConnectOfferPc);

            Assert.That(waitConnectOfferPc.IsCompleted, Is.True);

            var waitConnectAnswerPc = new WaitUntilWithTimeout(() =>
                                                               answerPc.IceConnectionState == RTCIceConnectionState.Connected ||
                                                               answerPc.IceConnectionState == RTCIceConnectionState.Completed, 5000);

            yield return(waitConnectAnswerPc);

            Assert.That(waitConnectAnswerPc.IsCompleted, Is.True);

            var checkSenders = new WaitUntilWithTimeout(() => offerPc.GetSenders().Any(), 5000);

            yield return(checkSenders);

            Assert.That(checkSenders.IsCompleted, Is.True);

            var checkReceivers = new WaitUntilWithTimeout(() => answerPc.GetReceivers().Any(), 5000);

            yield return(checkReceivers);

            Assert.That(checkReceivers.IsCompleted, Is.True);
        }