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(); }
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); }
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(); }
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"); } }
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"); }
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(); } }
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)); } }
/// <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; } }
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()); }
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); } }
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(); }
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"); } }); }
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); }
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; }
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"); } }
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); } }
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); }
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); }
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(); }
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); }
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}"); } }
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); }
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); }
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)); }
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))); } }
/// <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(); }
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(); }
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); }