コード例 #1
0
        public IEnumerator CurrentDirection()
        {
            var config     = GetDefaultConfiguration();
            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);

            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 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();

            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();
        }
コード例 #2
0
    private IEnumerator OnCreateOfferSuccess(RTCPeerConnection pc, RTCSessionDescription desc)
    {
        Debug.Log($"Offer from {GetName(pc)}\n{desc.sdp}");
        Debug.Log($"{GetName(pc)} setLocalDescription start");
        var op = pc.SetLocalDescription(ref desc);

        yield return(op);

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

        var otherPc = GetOtherPc(pc);

        Debug.Log($"{GetName(otherPc)} setRemoteDescription start");
        var op2 = otherPc.SetRemoteDescription(ref desc);

        yield return(op2);

        if (!op2.IsError)
        {
            OnSetRemoteSuccess(otherPc);
        }
        else
        {
            var error = op2.Error;
            OnSetSessionDescriptionError(ref error);
        }
        Debug.Log($"{GetName(otherPc)} createAnswer start");
        // Since the 'remote' side has no media stream we need
        // to pass in the right constraints in order for it to
        // accept the incoming offer of audio and video.

        var op3 = otherPc.CreateAnswer(ref _answerOptions);

        yield return(op3);

        if (!op3.IsError)
        {
            yield return(OnCreateAnswerSuccess(otherPc, op3.Desc));
        }
        else
        {
            OnCreateSessionDescriptionError(op3.Error);
        }
    }
コード例 #3
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);
        }
コード例 #4
0
        private IEnumerator sendDesc(RTCSdpType type)
        {
            RTCSessionDescriptionAsyncOperation opCreate = null;

            if (type == RTCSdpType.Offer)
            {
                OnLogEvent.Invoke("CreateOffer()", "");
                opCreate = peer.CreateOffer(ref offerOption);
            }
            else
            {
                OnLogEvent.Invoke("CreateAnswer()", "");
                opCreate = peer.CreateAnswer(ref answerOptions);
            }

            yield return(opCreate);

            if (opCreate.IsError)
            {
                OnErrorEvent.Invoke($"Create {opCreate.Desc.type}", opCreate.Error.message);
                yield break;
            }
            else
            {
                OnLogEvent.Invoke($"Create {opCreate.Desc.type}", "");
            }

            if (opCreate.Desc.sdp == null)
            {
                OnErrorEvent.Invoke("opCreate.Desc.sdp is null", "");
                yield break;
            }
            else
            {
                OnLogEvent.Invoke($"SetLocalDescription {type}", $"{opCreate.Desc.sdp.Substring(0, 10)} ...");
            }
            var desc  = opCreate.Desc;
            var opSet = peer.SetLocalDescription(ref desc);

            yield return(opSet);

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

            OnLogEvent.Invoke($"Send {type}", "");
            signaling.SendDesc(streamId, desc.type.ToString().ToLower(), desc.sdp);
        }
コード例 #5
0
    IEnumerator OnCreateOfferSuccess(RTCSessionDescription desc)
    {
        Debug.Log($"Offer from pc1\n{desc.sdp}");
        Debug.Log("pc1 setLocalDescription start");
        var op = pc1.SetLocalDescription(ref desc);

        yield return(op);

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

        Debug.Log("pc2 setRemoteDescription start");
        var op2 = pc2.SetRemoteDescription(ref desc);

        yield return(op2);

        if (!op2.IsError)
        {
            OnSetRemoteSuccess(pc2);
        }
        else
        {
            var error = op2.Error;
            OnSetSessionDescriptionError(ref error);
        }
        Debug.Log("pc2 createAnswer start");
        // Since the 'remote' side has no media stream we need
        // to pass in the right constraints in order for it to
        // accept the incoming offer of audio and video.

        var op3 = pc2.CreateAnswer(ref AnswerOptions);

        yield return(op3);

        if (!op3.IsError)
        {
            yield return(OnCreateAnswerSuccess(op3.Desc));
        }
        else
        {
            OnCreateSessionDescriptionError(op3.Error);
        }
    }
コード例 #6
0
        private IEnumerator OnCreateOfferSuccess(RTCPeerConnection pc, RTCSessionDescription desc)
        {
            Debug.Log($"Offer from {GetName(pc)}\n{desc.sdp}");
            Debug.Log($"{GetName(pc)} setLocalDescription start");
            var op = pc.SetLocalDescription(ref desc);

            yield return(op);

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

            var otherPc = GetOtherPc(pc);

            Debug.Log($"{GetName(otherPc)} setRemoteDescription start");
            var op2 = otherPc.SetRemoteDescription(ref desc);

            yield return(op2);

            if (!op2.IsError)
            {
                OnSetRemoteSuccess(otherPc);
            }
            else
            {
                var error = op2.Error;
                OnSetSessionDescriptionError(ref error);
            }

            Debug.Log($"{GetName(otherPc)} createAnswer start");
            var op3 = otherPc.CreateAnswer();

            yield return(op3);

            if (!op3.IsError)
            {
                yield return(OnCreateAnswerSuccess(otherPc, op3.Desc));
            }
            else
            {
                OnCreateSessionDescriptionError(op3.Error);
            }
        }
コード例 #7
0
    private IEnumerator createDesc(RTCSdpType type)
    {
        RTCSessionDescriptionAsyncOperation opCreate;

        if (type == RTCSdpType.Offer)
        {
            opCreate = peer.CreateOffer(ref offerOptions);
        }
        else
        {
            opCreate = peer.CreateAnswer(ref answerOptions);
        }

        yield return(opCreate);

        if (opCreate.IsError)
        {
            log(LogLevel.Error, $"Create {opCreate.Desc.type}: {opCreate.Error.message}");
            yield break;
        }
        else
        {
            log(LogLevel.Log, $"Create {opCreate.Desc.type}");
        }

        if (opCreate.Desc.sdp == null)
        {
            log(LogLevel.Error, $"opCreate.Desc.sdp is null");
            yield break;
        }
        else
        {
            log(LogLevel.Log, $"SetLocalDescription {type}: {opCreate.Desc.sdp}");
        }
        var desc  = opCreate.Desc;
        var opSet = peer.SetLocalDescription(ref desc);

        yield return(opSet);

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

        log(LogLevel.Log, $">>> Send \"takeConfiguration\" Command ({type}: '{desc.sdp.Substring(0, 10)} ...')");
        signaling.SendDesc(streamId, desc.type.ToString().ToLower(), desc.sdp);
    }
コード例 #8
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();
        }
コード例 #9
0
    private IEnumerator OnCreateOfferSuccess(RTCPeerConnection pc, RTCSessionDescription desc)
    {
        Debug.Log("setLocalDescription start");
        var op = pc.SetLocalDescription(ref desc);

        yield return(op);

        if (!op.IsError)
        {
            OnSetLocalSuccess(pc);
        }
        else
        {
            var error = op.Error;
            OnSetSessionDescriptionError(ref error);
        }
    }
        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();
        }
        public IEnumerator PeerConnection_SetLocalDescription()
        {
            var             peer    = new RTCPeerConnection();
            RTCOfferOptions options = default;
            var             op      = peer.CreateOffer(ref options);

            yield return(op);

            Assert.True(op.isDone);
            Assert.False(op.isError);
            var op2 = peer.SetLocalDescription(ref op.desc);

            yield return(op2);

            Assert.True(op2.isDone);
            Assert.False(op2.isError);
            peer.Close();
        }
コード例 #12
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);
        }
コード例 #13
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);
        }
コード例 #14
0
    IEnumerator SetDescription(RTCSessionDescription desc, Side side)
    {
        Debug.Log($"[Set {side} {desc.type}]");

        var op = side == Side.Local ? localConnection.SetLocalDescription(ref desc) : localConnection.SetRemoteDescription(ref desc);

        yield return(op);

        if (op.IsError)
        {
            Debug.LogError(op.Error.message);
        }
        else if (desc.type == RTCSdpType.Offer)
        {
            StartCoroutine(CreateDescription(RTCSdpType.Answer));
        }
        else if (side == Side.Local && desc.type == RTCSdpType.Answer)
        {
            SendDescription(ref desc);
        }
    }
コード例 #15
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();
        }
コード例 #16
0
    IEnumerator OnCreateAnswerSuccess(RTCPeerConnection pc, RTCSessionDescription desc)
    {
        Debug.Log($"Answer from {GetName(pc)}:\n{desc.sdp}");
        Debug.Log($"{GetName(pc)} setLocalDescription start");
        var op = pc.SetLocalDescription(ref desc);

        yield return(op);

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

        var otherPc = GetOtherPc(pc);

        Debug.Log($"{GetName(otherPc)} setRemoteDescription start");

        var op2 = otherPc.SetRemoteDescription(ref desc);

        yield return(op2);

        if (!op2.IsError)
        {
            OnSetRemoteSuccess(otherPc);

            StartCoroutine(CheckActualCodec());
        }
        else
        {
            var error = op2.Error;
            OnSetSessionDescriptionError(ref error);
        }
    }
コード例 #17
0
        public IEnumerator CreateAnswer()
        {
            var config = GetConfiguration();

            var peer1 = new RTCPeerConnection(ref config);
            var peer2 = new RTCPeerConnection(ref config);
            var conf  = new RTCDataChannelInit(true);

            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);

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

            peer1.Close();
            peer2.Close();
            peer1.Dispose();
            peer2.Dispose();
        }
コード例 #18
0
        public IEnumerator SetLocalDescriptionFailed()
        {
            var peer   = new RTCPeerConnection();
            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 = peer.AddTrack(track, stream);

            var op = peer.CreateOffer();

            yield return(op);

            Assert.True(op.IsDone);
            Assert.False(op.IsError);
            var desc = op.Desc;

            // change sdp to cannot parse
            desc.sdp = desc.sdp.Replace("a=mid:0", "a=mid:10");
            var op2 = peer.SetLocalDescription(ref desc);

            yield return(op2);

            Assert.True(op2.IsDone);
            Assert.True(op2.IsError);
            Assert.IsNotEmpty(op2.Error.message);
            Assert.That(peer.RemoveTrack(sender), Is.EqualTo(RTCErrorType.None));
            track.Dispose();
            stream.Dispose();
            peer.Close();
            peer.Dispose();
            Object.DestroyImmediate(source.clip);
            Object.DestroyImmediate(obj);
        }
        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));
        }
コード例 #20
0
        void OnOffer(ISignaling signaling, DescData e)
        {
            RTCSessionDescription _desc;

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

            if (m_mapConnectionIdAndPeer.ContainsKey(connectionId))
            {
                return;
            }
            var pc = new RTCPeerConnection();

            m_mapConnectionIdAndPeer.Add(e.connectionId, pc);

            pc.OnDataChannel = new DelegateOnDataChannel(channel => { OnDataChannel(pc, channel); });
            pc.SetConfiguration(ref m_conf);
            pc.OnIceCandidate = new DelegateOnIceCandidate(candidate =>
            {
                signaling.SendCandidate(e.connectionId, candidate);
            });
            pc.OnIceConnectionChange = new DelegateOnIceConnectionChange(state =>
            {
                if (state == RTCIceConnectionState.Disconnected)
                {
                    pc.Close();
                    m_mapConnectionIdAndPeer.Remove(e.connectionId);
                }
            });
            //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 m_listVideoStreamTrack)
            {
                pc.AddTrack(track);
            }
            foreach (var track in m_audioStream.GetTracks())
            {
                pc.AddTrack(track);
            }

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

            while (op.MoveNext())
            {
            }
            if (op.IsError)
            {
                Debug.LogError($"Network Error: {op.Error}");
                return;
            }

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

            while (opLocalDesc.MoveNext())
            {
            }
            if (opLocalDesc.IsError)
            {
                Debug.LogError($"Network Error: {opLocalDesc.Error}");
                return;
            }

            signaling.SendAnswer(connectionId, desc);
        }
コード例 #21
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);
        }
コード例 #22
0
        public IEnumerator IceConnectionStateChange()
        {
            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);

            peer1.OnIceCandidate = candidate => { peer2.AddIceCandidate(ref candidate); };
            peer2.OnIceCandidate = candidate => { peer1.AddIceCandidate(ref candidate); };

            MediaStream stream = Audio.CaptureStream();

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

            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 op7 = new WaitUntilWithTimeout(
                () => peer1.IceConnectionState == RTCIceConnectionState.Connected ||
                peer1.IceConnectionState == RTCIceConnectionState.Completed, 5000);

            yield return(op7);

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

            yield return(op8);

            Assert.True(op8.IsCompleted);

            stream.Dispose();
            peer1.Close();
            peer2.Close();
        }
コード例 #23
0
        public IEnumerator AddIceCandidate()
        {
            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);

            var peer1ReceiveCandidateQueue = new Queue <RTCIceCandidate>();
            var peer2ReceiveCandidateQueue = new Queue <RTCIceCandidate>();

            peer1.OnIceCandidate = candidate => { peer2ReceiveCandidateQueue.Enqueue(candidate); };
            peer2.OnIceCandidate = candidate => { peer1ReceiveCandidateQueue.Enqueue(candidate); };

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

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

            peer1.AddTrack(track);

            var op1 = peer1.CreateOffer();

            yield return(op1);

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

            yield return(op2);

            yield return(new WaitUntil(() => peer2ReceiveCandidateQueue.Any()));

            Assert.That(peer2.AddIceCandidate(peer2ReceiveCandidateQueue.Peek()), Is.False);

            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            Assert.That(peer2.AddIceCandidate(peer2ReceiveCandidateQueue.Dequeue()), Is.True);

            var op4 = peer2.CreateAnswer();

            yield return(op4);

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

            yield return(op5);

            yield return(new WaitUntil(() => peer1ReceiveCandidateQueue.Any()));

            Assert.That(peer1.AddIceCandidate(peer1ReceiveCandidateQueue.Peek()), Is.False);

            var op6 = peer1.SetRemoteDescription(ref desc);

            yield return(op6);

            Assert.That(peer1.AddIceCandidate(peer1ReceiveCandidateQueue.Dequeue()), Is.True);

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

            yield return(op7);

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

            yield return(op8);

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

            foreach (var candidate in peer1ReceiveCandidateQueue)
            {
                Assert.That(peer1.AddIceCandidate(candidate), Is.True);
            }

            peer1ReceiveCandidateQueue.Clear();

            foreach (var candidate in peer2ReceiveCandidateQueue)
            {
                Assert.That(peer2.AddIceCandidate(candidate), Is.True);
            }

            peer2ReceiveCandidateQueue.Clear();

            track.Dispose();
            peer1.Close();
            peer2.Close();
            Object.DestroyImmediate(source.clip);
            Object.DestroyImmediate(obj);
        }
コード例 #24
0
        public IEnumerator PeerConnectionStateChange()
        {
            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);

            RTCPeerConnectionState state1    = default;
            RTCPeerConnectionState state2    = default;
            RTCIceConnectionState  iceState1 = default;
            RTCIceConnectionState  iceState2 = default;

            peer1.OnIceCandidate          = candidate => { peer2.AddIceCandidate(candidate); };
            peer2.OnIceCandidate          = candidate => { peer1.AddIceCandidate(candidate); };
            peer1.OnConnectionStateChange = state => { state1 = state; };
            peer2.OnConnectionStateChange = state => { state2 = state; };
            peer1.OnIceConnectionChange   = state => { iceState1 = state; };
            peer2.OnIceConnectionChange   = state => { iceState2 = state; };

            Assert.That(state1, Is.EqualTo(RTCPeerConnectionState.New));
            Assert.That(state2, Is.EqualTo(RTCPeerConnectionState.New));

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

            source.clip = AudioClip.Create("test", 480, 2, 48000, false);
            AudioStreamTrack track1 = new AudioStreamTrack(source);

            peer1.AddTrack(track1);

            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);

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

            yield return(op5);

            var op6 = peer1.SetRemoteDescription(ref desc);

            yield return(op6);

            var op7 = new WaitUntilWithTimeout(() =>
                                               state1 == RTCPeerConnectionState.Connected &&
                                               state2 == RTCPeerConnectionState.Connected, 5000);

            yield return(op7);

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

            var op8 = new WaitUntilWithTimeout(() =>
                                               (iceState1 == RTCIceConnectionState.Connected || iceState1 == RTCIceConnectionState.Completed) &&
                                               (iceState2 == RTCIceConnectionState.Connected || iceState2 == RTCIceConnectionState.Completed)
                                               , 5000);

            yield return(op8);

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

            peer1.Close();

            var op9 = new WaitUntilWithTimeout(() =>
                                               state1 == RTCPeerConnectionState.Closed &&
                                               iceState2 == RTCIceConnectionState.Disconnected, 5000);

            yield return(op9);

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

            track1.Dispose();
            peer2.Close();
            Object.DestroyImmediate(source.clip);
            Object.DestroyImmediate(obj);
        }
コード例 #25
0
    public IEnumerator DataChannel_EventsAreSentToOther()
    {
        RTCConfiguration config = default;

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

        peer1.OnIceCandidate = new DelegateOnIceCandidate(candidate => { peer2.AddIceCandidate(ref candidate); });
        peer2.OnIceCandidate = new DelegateOnIceCandidate(candidate => { peer1.AddIceCandidate(ref candidate); });
        peer2.OnDataChannel  = new DelegateOnDataChannel(channel => { channel2 = channel; });

        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);

        yield return(new WaitUntil(() => peer1.IceConnectionState == RTCIceConnectionState.Connected || peer1.IceConnectionState == RTCIceConnectionState.Completed));

        yield return(new WaitUntil(() => peer2.IceConnectionState == RTCIceConnectionState.Connected || peer2.IceConnectionState == RTCIceConnectionState.Completed));

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

        Assert.AreEqual(channel1.Label, channel2.Label);
        Assert.AreEqual(channel1.Id, channel2.Id);

        string message1 = "hello";
        string message2 = null;

        channel2.OnMessage = new DelegateOnMessage(bytes => { message2 = System.Text.Encoding.UTF8.GetString(bytes); });
        channel1.Send(message1);
        yield return(new WaitUntil(() => !string.IsNullOrEmpty(message2)));

        Assert.AreEqual(message1, message2);

        byte[] message3 = { 1, 2, 3 };
        byte[] message4 = null;
        channel2.OnMessage = new DelegateOnMessage(bytes => { message4 = bytes; });
        channel1.Send(message3);
        yield return(new WaitUntil(() => message4 != null));

        Assert.AreEqual(message3, message4);

        peer1.Close();
        peer2.Close();
    }
コード例 #26
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();
        }
コード例 #27
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();
        }
コード例 #28
0
        private static IEnumerator SignalingPeers(RTCPeerConnection offerPc, RTCPeerConnection answerPc)
        {
            offerPc.OnIceCandidate  = candidate => answerPc.AddIceCandidate(candidate);
            answerPc.OnIceCandidate = candidate => offerPc.AddIceCandidate(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);
        }
コード例 #29
0
        public IEnumerator EventsAreSentToOther()
        {
            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 channel2 = null;

            peer1.OnIceCandidate = candidate => { peer2.AddIceCandidate(candidate); };
            peer2.OnIceCandidate = candidate => { peer1.AddIceCandidate(candidate); };
            peer2.OnDataChannel  = channel => { channel2 = channel; };

            var  channel1       = peer1.CreateDataChannel("data");
            bool channel1Opened = false;
            bool channel1Closed = false;

            channel1.OnOpen  = () => { channel1Opened = true; };
            channel1.OnClose = () => { channel1Closed = true; };

            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 op7 = new WaitUntilWithTimeout(
                () => peer1.IceConnectionState == RTCIceConnectionState.Connected ||
                peer1.IceConnectionState == RTCIceConnectionState.Completed, 5000);

            yield return(op7);

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

            yield return(op8);

            Assert.True(op8.IsCompleted);
            var op9 = new WaitUntilWithTimeout(() => channel2 != null, 5000);

            yield return(op9);

            Assert.True(op9.IsCompleted);

            Assert.True(channel1Opened);
            Assert.AreEqual(channel1.Label, channel2.Label);
            Assert.AreEqual(channel1.Id, channel2.Id);

            const string message1 = "hello";
            string       message2 = null;

            channel2.OnMessage = bytes => { message2 = System.Text.Encoding.UTF8.GetString(bytes); };
            channel1.Send(message1);
            var op10 = new WaitUntilWithTimeout(() => !string.IsNullOrEmpty(message2), 5000);

            yield return(op10);

            Assert.True(op10.IsCompleted);
            Assert.AreEqual(message1, message2);

            byte[] message3 = { 1, 2, 3 };
            byte[] message4 = null;
            channel2.OnMessage = bytes => { message4 = bytes; };
            channel1.Send(message3);
            var op11 = new WaitUntilWithTimeout(() => message4 != null, 5000);

            yield return(op11);

            Assert.True(op11.IsCompleted);
            Assert.AreEqual(message3, message4);

            channel1.Close();
            var op12 = new WaitUntilWithTimeout(() => channel1Closed, 5000);

            yield return(op12);

            Assert.True(op12.IsCompleted);

            channel2.Close();
            peer1.Close();
            peer2.Close();
        }
コード例 #30
0
        void OnOffer(ISignaling signaling, DescData e)
        {
            RTCSessionDescription _desc;

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

            if (m_mapConnectionIdAndPeer.ContainsKey(connectionId))
            {
                return;
            }
            var pc = new RTCPeerConnection();

            m_mapConnectionIdAndPeer.Add(e.connectionId, pc);

            pc.OnDataChannel = new DelegateOnDataChannel(channel => { OnDataChannel(pc, channel); });
            pc.SetConfiguration(ref m_conf);
            pc.OnIceCandidate = new DelegateOnIceCandidate(candidate =>
            {
                signaling.SendCandidate(e.connectionId, candidate);
            });
            pc.OnIceConnectionChange = new DelegateOnIceConnectionChange(state =>
            {
                if (state == RTCIceConnectionState.Disconnected)
                {
                    pc.Close();
                    m_mapConnectionIdAndPeer.Remove(e.connectionId);
                }
            });

            pc.SetRemoteDescription(ref _desc);
            foreach (var track in m_listVideoStreamTrack.Concat(m_audioStream.GetTracks()))
            {
                RTCRtpSender sender = pc.AddTrack(track);
                if (!m_mapTrackAndSenderList.TryGetValue(track, out List <RTCRtpSender> list))
                {
                    list = new List <RTCRtpSender>();
                    m_mapTrackAndSenderList.Add(track, list);
                }
                list.Add(sender);
            }

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

            while (op.MoveNext())
            {
            }
            if (op.IsError)
            {
                Debug.LogError($"Network Error: {op.Error}");
                return;
            }

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

            while (opLocalDesc.MoveNext())
            {
            }
            if (opLocalDesc.IsError)
            {
                Debug.LogError($"Network Error: {opLocalDesc.Error}");
                return;
            }

            signaling.SendAnswer(connectionId, desc);
        }