public async Task <string> HandleUpdatedRemoteOffer(string sdp) { Logger.Debug("PeerChannel", "HandleUpdatedRemoteOffer"); var sdpInit = new RTCSessionDescriptionInit() { Type = RTCSdpType.Offer, Sdp = sdp, }; Logger.Debug("PeerChannel", "SetRemoteOffer - SetRemoteDescription"); await Conn.SetRemoteDescription(new RTCSessionDescription(sdpInit)); var opts = new RTCAnswerOptions(); Logger.Debug("PeerChannel", "SetRemoteOffer - CreateAnswer"); var answer = await Conn.CreateAnswer(opts); Logger.Debug("PeerChannel", answer.Sdp); await Conn.SetLocalDescription(answer); Logger.Debug("PeerChannel", "local description set"); return(answer.Sdp); }
IEnumerator SendAnswerCoroutine(string connectionId, RTCPeerConnection 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); }
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); }
IEnumerator Answer(string connectionId) { RTCAnswerOptions options = default; var pc = pcs[connectionId]; var op = pc.CreateAnswer(ref options); yield return(op); if (op.isError) { Debug.LogError($"Network Error: {op.error}"); yield break; } var opLocalDesc = pc.SetLocalDescription(ref op.desc); yield return(opLocalDesc); if (opLocalDesc.isError) { Debug.LogError($"Network Error: {opLocalDesc.error}"); yield break; } var op3 = signaling.PostAnswer(this.sessionId, connectionId, op.desc.sdp); yield return(op3); if (op3.webRequest.isNetworkError) { Debug.LogError($"Network Error: {op3.webRequest.error}"); yield break; } }
public Task <RTCSessionDescriptionInit> CreateAnswer(RTCAnswerOptions options) { var tcs = new TaskCompletionSource <RTCSessionDescriptionInit>(); ((Webrtc.PeerConnection)NativeObject).CreateAnswer( new SdpObserverProxy(tcs), new Webrtc.MediaConstraints() /*NativeDefaultMediaConstraints*/); return(tcs.Task); }
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(); }
public async Task <RTCSessionDescriptionInit> CreateAnswer(RTCAnswerOptions options = null) { var jsObjectRef = await JsRuntime.CallJsMethodAsync <JsObjectRef>(NativeObject, "createAnswer", options); var descriptor = JsRuntime.GetJsPropertyValue <RTCSessionDescriptionInit>(jsObjectRef, null); JsRuntime.DeleteJsObjectRef(jsObjectRef.JsObjectRefId); return(descriptor); }
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); }
public async Task <string> HandleInitialRemoteOffer(string sdp) { Logger.Debug("PeerChannel", "HandleInitialRemoteOffer"); if (Conn == null) { Logger.Debug("PeerChannel", "should initialize beforehand"); return(string.Empty); } var sdpInit = new RTCSessionDescriptionInit() { Type = RTCSdpType.Offer, Sdp = sdp, }; Logger.Debug("PeerChannel", "SetRemoteOffer - SetRemoteDescription"); await Conn.SetRemoteDescription(new RTCSessionDescription(sdpInit)); if (mediaOption.VideoUpstreamEnabled) { Logger.Debug("PeerChannel", "video upstream setting"); if (screen != null) { await screen.StartCaptureAsync(); } SetupVideoTrack(); } if (mediaOption.AudioUpstreamEnabled) { Logger.Debug("PeerChannel", "audio upstream setting"); SetupAudioTrack(); } var opts = new RTCAnswerOptions(); Logger.Debug("PeerChannel", "SetRemoteOffer - CreateAnswer"); var answer = await Conn.CreateAnswer(opts); Logger.Debug("PeerChannel", answer.Sdp); await Conn.SetLocalDescription(answer); Logger.Debug("PeerChannel", "local description set"); return(answer.Sdp); }
public async Task <RTCSessionDescriptionInit> CreateAnswer(RTCAnswerOptions options) { var tcs = new TaskCompletionSource <RTCSessionDescriptionInit>(); ((Webrtc.PeerConnection)NativeObject).CreateAnswer( new SdpObserverProxy(tcs), new Webrtc.MediaConstraints() /*NativeDefaultMediaConstraints*/); var answer = await tcs.Task; // Android DOES NOT expose 'Type'!!! Set it manually here. answer.Type = RTCSdpType.Answer; return(answer); }
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); }
public Task <RTCSessionDescriptionInit> CreateAnswer(RTCAnswerOptions options) { var tcs = new TaskCompletionSource <RTCSessionDescriptionInit>(); ((Webrtc.RTCPeerConnection)NativeObject).AnswerForConstraints( new Webrtc.RTCMediaConstraints(null, null),////NativeDefaultRTCMediaConstraints, (nativeSessionDescription, err) => { if (err != null) { tcs.SetException(new Exception($"{err.LocalizedDescription}")); } tcs.SetResult(nativeSessionDescription.FromNative()); }); return(tcs.Task); }
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 CreateAnswerFailed() { var config = GetConfiguration(); var peer = new RTCPeerConnection(ref config); RTCAnswerOptions options = default; var op = peer.CreateAnswer(ref options); yield return(op); Assert.True(op.IsDone); // This is failed Assert.True(op.IsError); peer.Close(); peer.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(); }
public Task <SDP> createAnswer(RTCAnswerOptions options) { SDP answerSdp = new SDP(IPAddress.Loopback); answerSdp.SessionId = Crypto.GetRandomInt(5).ToString(); answerSdp.Connection = new SDPConnectionInformation(IPAddress.Loopback); SDPMediaAnnouncement audioAnnouncement = new SDPMediaAnnouncement( SDPMediaTypesEnum.audio, 1234, new List <SDPMediaFormat> { new SDPMediaFormat(SDPMediaFormatsEnum.PCMU) }); audioAnnouncement.Transport = RTP_MEDIA_PROFILE; answerSdp.Media.Add(audioAnnouncement); return(Task.FromResult(answerSdp)); }
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(); }
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(); }
private static async Task RunCommand(Options options, bool noOptions) { // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. //ManualResetEvent exitMre = new ManualResetEvent(false); AddConsoleLogger(); // Start MDNS server. var mdnsServer = new ServiceDiscovery(); if (options.StunServer != null) { string[] fields = options.StunServer.Split(';'); _stunServer = new RTCIceServer { urls = fields[0], username = fields.Length > 1 ? fields[1] : null, credential = fields.Length > 2 ? fields[2] : null, credentialType = RTCIceCredentialType.password }; } _relayOnly = options.RelayOnly; if (!string.IsNullOrEmpty(options.IceTypes)) { options.IceTypes.Split().ToList().ForEach(x => { if (Enum.TryParse <RTCIceCandidateType>(x, out var iceType)) { _iceTypes.Add(iceType); } }); if (!_iceTypes.Any(x => x == RTCIceCandidateType.host)) { _offerOptions = new RTCOfferOptions { X_ExcludeIceCandidates = true }; _answerOptions = new RTCAnswerOptions { X_ExcludeIceCandidates = true }; } } if (!string.IsNullOrEmpty(options.AcceptIceTypes)) { options.AcceptIceTypes.Split().ToList().ForEach(x => { if (Enum.TryParse <RTCIceCandidateType>(x, out var iceType)) { _acceptIceTypes.Add(iceType); } }); } if (options.UseWebSocket || options.UseSecureWebSocket || noOptions) { // Start web socket. Console.WriteLine("Starting web socket server..."); _webSocketServer = new WebSocketServer(IPAddress.Any, WEBSOCKET_PORT, options.UseSecureWebSocket); if (options.UseSecureWebSocket) { _webSocketServer.SslConfiguration.ServerCertificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(LOCALHOST_CERTIFICATE_PATH); _webSocketServer.SslConfiguration.CheckCertificateRevocation = false; } //_webSocketServer.Log.Level = WebSocketSharp.LogLevel.Debug; _webSocketServer.AddWebSocketService <WebRtcClient>("/sendoffer", (client) => { client.WebSocketOpened += SendOffer; client.OnMessageReceived += WebSocketMessageReceived; }); _webSocketServer.AddWebSocketService <WebRtcClient>("/receiveoffer", (client) => { client.WebSocketOpened += ReceiveOffer; client.OnMessageReceived += WebSocketMessageReceived; }); _webSocketServer.Start(); Console.WriteLine($"Waiting for browser web socket connection to {_webSocketServer.Address}:{_webSocketServer.Port}..."); } else if (options.CreateJsonOffer) { var pc = Createpc(null, _stunServer, _relayOnly); var offerSdp = pc.createOffer(null); await pc.setLocalDescription(offerSdp); Console.WriteLine(offerSdp.sdp); var offerJson = JsonConvert.SerializeObject(offerSdp, new Newtonsoft.Json.Converters.StringEnumConverter()); var offerBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(offerJson)); Console.WriteLine(offerBase64); string remoteAnswerB64 = null; while (string.IsNullOrWhiteSpace(remoteAnswerB64)) { Console.Write("Remote Answer => "); remoteAnswerB64 = Console.ReadLine(); } string remoteAnswer = Encoding.UTF8.GetString(Convert.FromBase64String(remoteAnswerB64)); Console.WriteLine(remoteAnswer); RTCSessionDescriptionInit answerInit = JsonConvert.DeserializeObject <RTCSessionDescriptionInit>(remoteAnswer); Console.WriteLine($"Remote answer: {answerInit.sdp}"); var res = pc.setRemoteDescription(answerInit); if (res != SetDescriptionResultEnum.OK) { // No point continuing. Something will need to change and then try again. pc.Close("failed to set remote sdp"); } } else if (options.NodeDssServer != null) { _nodeDssUri = new Uri(options.NodeDssServer); _nodeDssclient = new HttpClient(); Console.WriteLine($"node-dss server successfully set to {_nodeDssUri}."); } _ = Task.Run(() => ProcessInput(exitCts)); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); Console.WriteLine(); Console.WriteLine("Exiting..."); _peerConnection?.Close("application exit"); _webSocketServer?.Stop(); Task.Delay(1000).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(); }
IEnumerator OnOffer(ISignaling signaling, DescData e) { var connectionId = e.connectionId; if (m_mapConnectionIdAndPeer.ContainsKey(connectionId)) { Debug.LogError($"connection:{connectionId} peerConnection already exist"); yield break; } var 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; } // ToDo: need webrtc package version 2.3 // foreach (var transceiver in pc.GetTransceivers() // .Where(x => x.Receiver.Track.Kind == TrackKind.Video) // .Select((x, index) => new {x, index}) // .Take(m_listVideoStreamTrack.Count)) // { // RTCRtpSender sender = transceiver.x.Sender; // VideoStreamTrack track = m_listVideoStreamTrack[transceiver.index]; // transceiver.x.Sender.ReplaceTrack(track); // transceiver.x.Direction = RTCRtpTransceiverDirection.SendOnly; // // if (!m_mapTrackAndSenderList.TryGetValue(track, out List<RTCRtpSender> list)) // { // list = new List<RTCRtpSender>(); // m_mapTrackAndSenderList.Add(track, list); // } // // list.Add(sender); // } foreach (var track in m_listVideoStreamTrack) { 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); } foreach (var track in 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); 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); }
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); }
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(); }
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(); }
private static async Task RunCommand(Options options, bool noOptions) { // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. //ManualResetEvent exitMre = new ManualResetEvent(false); logger = AddConsoleLogger(); // Start MDNS server. var mdnsServer = new ServiceDiscovery(); if (options.StunServer != null) { string[] fields = options.StunServer.Split(';'); _stunServer = new RTCIceServer { urls = fields[0], username = fields.Length > 1 ? fields[1] : null, credential = fields.Length > 2 ? fields[2] : null, credentialType = RTCIceCredentialType.password }; } _relayOnly = options.RelayOnly; if (!string.IsNullOrEmpty(options.IceTypes)) { options.IceTypes.Split().ToList().ForEach(x => { if (Enum.TryParse <RTCIceCandidateType>(x, out var iceType)) { _iceTypes.Add(iceType); } }); if (!_iceTypes.Any(x => x == RTCIceCandidateType.host)) { _offerOptions = new RTCOfferOptions { X_ExcludeIceCandidates = true }; _answerOptions = new RTCAnswerOptions { X_ExcludeIceCandidates = true }; } } if (!string.IsNullOrEmpty(options.AcceptIceTypes)) { options.AcceptIceTypes.Split().ToList().ForEach(x => { if (Enum.TryParse <RTCIceCandidateType>(x, out var iceType)) { _acceptIceTypes.Add(iceType); } }); } if (options.UseWebSocket || options.UseSecureWebSocket || noOptions) { // Start web socket. Console.WriteLine("Starting web socket server..."); _webSocketServer = new WebSocketServer(IPAddress.Any, WEBSOCKET_PORT, options.UseSecureWebSocket); if (options.UseSecureWebSocket) { _webSocketServer.SslConfiguration.ServerCertificate = new X509Certificate2(LOCALHOST_CERTIFICATE_PATH); _webSocketServer.SslConfiguration.CheckCertificateRevocation = false; } _webSocketServer.AddWebSocketService <WebRTCWebSocketPeer>("/", (peer) => { peer.OfferOptions = _offerOptions; if (_acceptIceTypes != null && _acceptIceTypes.Count > 0) { peer.FilterRemoteICECandidates = (init) => _acceptIceTypes.Any(x => x == RTCIceCandidate.Parse(init.candidate).type); } peer.CreatePeerConnection = CreatePeerConnection; }); _webSocketServer.Start(); Console.WriteLine($"Waiting for browser web socket connection to {_webSocketServer.Address}:{_webSocketServer.Port}..."); } else if (!string.IsNullOrWhiteSpace(options.WebSocketServer)) { // We are the client for a web socket server. The JSON signalling exchange still occurs the same way as when the web socket // server option is used except that as the web socket client we receive the SDP offer from the server. WebRTCWebSocketClient wsockClient = new WebRTCWebSocketClient(options.WebSocketServer, CreatePeerConnection); await wsockClient.Start(exitCts.Token); Console.WriteLine("web socket client started."); } else if (options.CreateJsonOffer) { var pc = await Createpc(null, _stunServer, _relayOnly); var offerSdp = pc.createOffer(null); await pc.setLocalDescription(offerSdp); Console.WriteLine(offerSdp.sdp); var offerJson = JsonConvert.SerializeObject(offerSdp, new Newtonsoft.Json.Converters.StringEnumConverter()); var offerBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(offerJson)); Console.WriteLine(offerBase64); string remoteAnswerB64 = null; while (string.IsNullOrWhiteSpace(remoteAnswerB64)) { Console.Write("Remote Answer => "); remoteAnswerB64 = Console.ReadLine(); } string remoteAnswer = Encoding.UTF8.GetString(Convert.FromBase64String(remoteAnswerB64)); Console.WriteLine(remoteAnswer); RTCSessionDescriptionInit answerInit = JsonConvert.DeserializeObject <RTCSessionDescriptionInit>(remoteAnswer); Console.WriteLine($"Remote answer: {answerInit.sdp}"); var res = pc.setRemoteDescription(answerInit); if (res != SetDescriptionResultEnum.OK) { // No point continuing. Something will need to change and then try again. pc.Close("failed to set remote sdp"); } } else if (options.RestServer != null) { string[] fields = options.RestServer.Split(';'); if (fields.Length < 3) { throw new ArgumentException("The 'rest' option must contain 3 semi-colon separated fields, e.g. --rest=https://localhost:5001/api/webrtcsignal;myid;theirid."); } var webrtcRestPeer = new WebRTCRestSignalingPeer(fields[0], fields[1], fields[2], CreatePeerConnection); webrtcRestPeer.OfferOptions = _offerOptions; webrtcRestPeer.AnswerOptions = _answerOptions; if (_acceptIceTypes != null && _acceptIceTypes.Count > 0) { webrtcRestPeer.FilterRemoteICECandidates = (init) => _acceptIceTypes.Any(x => x == RTCIceCandidate.Parse(init.candidate).type); } await webrtcRestPeer.Start(exitCts); } _ = Task.Run(() => ProcessInput(exitCts)); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); Console.WriteLine(); Console.WriteLine("Exiting..."); _peerConnection?.Close("application exit"); _webSocketServer?.Stop(); Task.Delay(1000).Wait(); }
IEnumerator Start() { RTCConfiguration config = default; config.iceServers = new[] { new RTCIceServer { urls = new[] { "stun:stun.l.google.com:19302" } } }; peers[0] = new RTCPeerConnection(ref config); peers[1] = new RTCPeerConnection(ref config); dataChannels[peers[0]] = new List <RTCDataChannel>(); dataChannels[peers[1]] = new List <RTCDataChannel>(); RTCDataChannel channel = peers[0].CreateDataChannel("data"); dataChannels[peers[0]].Add(channel); peers[0].OnIceCandidate = candidate => { Assert.NotNull(candidate); Assert.NotNull(candidate.Candidate); peers[1].AddIceCandidate(candidate); }; peers[1].OnIceCandidate = candidate => { Assert.NotNull(candidate); Assert.NotNull(candidate.Candidate); peers[0].AddIceCandidate(candidate); }; peers[1].OnTrack = e => { Assert.NotNull(e); Assert.NotNull(e.Track); Assert.NotNull(e.Receiver); Assert.NotNull(e.Transceiver); peers[1].AddTrack(e.Track); }; peers[0].OnDataChannel = e => { if (peers[0].ConnectionState == RTCPeerConnectionState.Connected) { dataChannels[peers[0]].Add(e); } }; peers[1].OnDataChannel = e => { if (peers[1].ConnectionState == RTCPeerConnectionState.Connected) { dataChannels[peers[1]].Add(e); } }; if (m_stream != null) { foreach (var track in m_stream.GetTracks()) { peers[0].AddTrack(track, m_stream); } } RTCOfferOptions options1 = default; RTCAnswerOptions options2 = default; var op1 = peers[0].CreateOffer(ref options1); yield return(op1); Assert.False(op1.IsError); var desc = op1.Desc; var op2 = peers[0].SetLocalDescription(ref desc); yield return(op2); Assert.False(op2.IsError); desc.sdp = ReplaceOfferSdpForHardwareEncodeTest(desc.sdp); var op3 = peers[1].SetRemoteDescription(ref desc); yield return(op3); Assert.False(op3.IsError); var op4 = peers[1].CreateAnswer(ref options2); yield return(op4); Assert.False(op4.IsError); desc = op4.Desc; var op5 = peers[1].SetLocalDescription(ref desc); yield return(op5); Assert.False(op5.IsError); desc.sdp = ReplaceAnswerSdpForHardwareEncodeTest(desc.sdp); var op6 = peers[0].SetRemoteDescription(ref desc); yield return(op6); Assert.False(op6.IsError); var op7 = new WaitUntilWithTimeout(() => peers[0].IceConnectionState == RTCIceConnectionState.Connected || peers[0].IceConnectionState == RTCIceConnectionState.Completed, 5000); yield return(op7); Assert.True(op7.IsCompleted); var op8 = new WaitUntilWithTimeout(() => peers[1].IceConnectionState == RTCIceConnectionState.Connected || peers[1].IceConnectionState == RTCIceConnectionState.Completed, 5000); yield return(op8); Assert.True(op8.IsCompleted); if (m_stream != null) { var op9 = new WaitUntilWithTimeout(() => GetPeerSenders(0).Any(), 5000); yield return(op9); Assert.True(op9.IsCompleted); } IsTestFinished = true; }
IEnumerator Start() { RTCConfiguration config = default; config.iceServers = new[] { new RTCIceServer { urls = new[] { "stun:stun.l.google.com:19302" } } }; var pc1Senders = new List <RTCRtpSender>(); var pc2Senders = new List <RTCRtpSender>(); 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); }; peer2.OnTrack = e => { pc2Senders.Add(peer2.AddTrack(e.Track)); }; foreach (var track in _stream.GetTracks()) { pc1Senders.Add(peer1.AddTrack(track)); } 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); 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(op7.IsCompleted); var op9 = new WaitUntilWithTimeout(() => pc2Senders.Count > 0, 5000); yield return(op9); Assert.True(op9.IsCompleted); foreach (var sender in pc1Senders) { peer1.RemoveTrack(sender); } foreach (var sender in pc2Senders) { peer2.RemoveTrack(sender); } pc1Senders.Clear(); peer1.Close(); peer2.Close(); _isFinished = true; }
public IEnumerator MediaStreamTest_AddAndRemoveMediaStream() { var camObj = new GameObject("Camera"); var cam = camObj.AddComponent <Camera>(); RTCConfiguration config = default; config.iceServers = new RTCIceServer[] { new RTCIceServer { urls = new string[] { "stun:stun.l.google.com:19302" } } }; if (!WebRTC.HWEncoderSupport) { Assert.Pass("Test environment does not support HW encoding"); } var pc1Senders = new List <RTCRtpSender>(); var pc2Senders = new List <RTCRtpSender>(); var peer1 = new RTCPeerConnection(ref config); var peer2 = new RTCPeerConnection(ref config); peer1.OnIceCandidate = new DelegateOnIceCandidate(candidate => { peer2.AddIceCandidate(ref candidate); }); peer2.OnIceCandidate = new DelegateOnIceCandidate(candidate => { peer1.AddIceCandidate(ref candidate); }); peer2.OnTrack = new DelegateOnTrack(e => { pc2Senders.Add(peer2.AddTrack(e.Track)); }); foreach (var track in cam.CaptureStream(1280, 720).GetTracks()) { pc1Senders.Add(peer1.AddTrack(track)); } var conf = new RTCDataChannelInit(true); 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(() => pc2Senders.Count > 0)); foreach (var sender in pc1Senders) { peer1.RemoveTrack(sender); } foreach (var sender in pc2Senders) { peer2.RemoveTrack(sender); } pc1Senders.Clear(); GameObject.DestroyImmediate(camObj); peer1.Close(); peer2.Close(); }
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); }
private IEnumerator StartCreationWorkflow(RTCPeerConnection peer) { var offerOptions = new RTCOfferOptions { iceRestart = false, offerToReceiveAudio = true, offerToReceiveVideo = false }; var op1 = peer.CreateOffer(ref offerOptions); yield return(op1); if (op1.isError) { OnSetSessionDescriptionError(ref op1.error, "CreateOffer"); yield break; } var op1desc = op1.desc; DebugUtility.Log(LoggerTags.Online, "Success to call CreateOffer. DESC.type : {0}, DESC.sdp : {0}", op1desc.type, op1desc.sdp); var op2 = peer.SetLocalDescription(ref op1desc); yield return(op2); if (op2.isError) { OnSetSessionDescriptionError(ref op2.error, "SetLocalDescription"); yield break; } DebugUtility.Log(LoggerTags.Online, "Success to call SetLocalDescription."); var op3 = peer.SetRemoteDescription(ref op1desc); yield return(op3); if (op3.isError) { OnSetSessionDescriptionError(ref op3.error, "SetRemoteDescription"); yield break; } DebugUtility.Log(LoggerTags.Online, "Success to call SetRemoteDescription."); RTCAnswerOptions answerOptions = new RTCAnswerOptions { iceRestart = false, }; var op4 = peer.CreateAnswer(ref answerOptions); if (op4.isError) { OnSetSessionDescriptionError(ref op4.error, "CreateAnswer"); yield break; } var op4desc = op4.desc; DebugUtility.Log(LoggerTags.Online, "Success to call CreateAnswer. DESC.type : {0}, DESC.sdp : {0}", op4desc.type, op4desc.sdp); var op5 = peer.SetLocalDescription(ref op4desc); if (op5.isError) { OnSetSessionDescriptionError(ref op4.error, "SetLocalDescription"); yield break; } DebugUtility.Log(LoggerTags.Online, "Success to call SetLocalDescription."); var op6 = peer.SetRemoteDescription(ref op4desc); if (op6.isError) { OnSetSessionDescriptionError(ref op4.error, "SetRemoteDescription"); yield break; } DebugUtility.Log(LoggerTags.Online, "Success to call SetRemoteDescription."); }