private static void SDPAnswerReceived(WebRtcSession webRtcSession, string sdpAnswer) { try { logger.LogDebug("Answer SDP: " + sdpAnswer); var answerSDP = SDP.ParseSDPDescription(sdpAnswer); webRtcSession.SdpSessionID = answerSDP.SessionId; webRtcSession.RemoteIceUser = answerSDP.IceUfrag; webRtcSession.RemoteIcePassword = answerSDP.IcePwd; // All browsers seem to have gone to trickling ICE candidates now but just // in case one or more are given we can start the STUN dance immediately. if (answerSDP.IceCandidates != null) { foreach (var iceCandidate in answerSDP.IceCandidates) { webRtcSession.AppendRemoteIceCandidate(iceCandidate); } } OnTestPatternSampleReady += (timestamp, sample) => { try { webRtcSession.SendMedia(SDPMediaTypesEnum.video, timestamp, sample); } catch (Exception sendExcp) { logger.LogWarning("Exception OnTestPatternSampleReady. " + sendExcp.Message); webRtcSession.Close(); } }; } catch (Exception excp) { logger.LogError("Exception SDPAnswerReceived. " + excp.Message); } }
public override void Start() { _server = new WebSocketServer(IPAddress.Any, _serverPort, true); var path = System.IO.Path.Combine(Application.streamingAssetsPath, "Certs", "localhost.pfx.bin"); byte[] content = UnityEngine.Windows.File.ReadAllBytes(path); _server.SslConfiguration.ServerCertificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(content); _server.SslConfiguration.CheckCertificateRevocation = false; _server.AddWebSocketService <WebRtcSession>("/", newSession => { Debug.Log("Incoming connection ..."); if (_session != null) { Debug.Log("Another session is running. Ignore request"); return; } newSession.MessageReceived += MessageReceived; newSession.SocketOpen += () => { Debug.Log("Socket open!"); ClientConnected?.Invoke(); }; newSession.SocketClosed += () => { Debug.Log("Socket closed!"); _session = null; }; newSession.ConnectionError += (errorMessage) => { Debug.LogWarning(errorMessage); newSession.Context.WebSocket.Close(); // OnClose is only triggered when the connection was established before // unsetting _session in case SocketClosed was not fired. _session = null; }; _session = newSession; }); _server.Start(); Debug.Log($"Waiting for browser web socket connection to {_server.Address}:{_server.Port}..."); }
/// <summary> /// Sets up the WebRTC connection by starting a new <see cref="System.Threading.Task"/>. /// </summary> /// <param name="session">Created session for the client.</param> /// <param name="context">Context of the user connection.</param> /// <param name="jsonMessage">Retrieved WebSocket message as Json.</param> private void SetupWebRTCConnection(WebRtcSession session, IWebSocketConnection context, JsonData jsonMessage) { using (ManualResetEvent manualResetEvent = new ManualResetEvent(false)) { Task task = Task.Factory.StartNew(() => { WebRtcNative.InitializeSSL(); using (session.WebRtc) { foreach (string stunServer in stunServers) { session.WebRtc.AddServerConfig(stunServer, string.Empty, string.Empty); } if (session.WebRtc.InitializePeerConnection()) { manualResetEvent.Set(); while (!session.Cancel.Token.IsCancellationRequested && session.WebRtc.ProcessMessages(1000)) { //UnityEngine.Debug.Log("."); } session.WebRtc.ProcessMessages(1000); } else { context.Close(); } } }, session.Cancel.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); if (manualResetEvent.WaitOne(9999)) { InitWebRTCCallbacks(session, context, jsonMessage); } } }
/// <summary> /// Hands the socket handle to the DTLS context and waits for the handshake to complete. /// </summary> /// <param name="webRtcSession">The WebRTC session to perform the DTLS handshake on.</param> private static int DoDtlsHandshake(WebRtcSession webRtcSession) { logger.LogDebug("DoDtlsHandshake started."); if (!File.Exists(DTLS_CERTIFICATE_PATH)) { throw new ApplicationException($"The DTLS certificate file could not be found at {DTLS_CERTIFICATE_PATH}."); } else if (!File.Exists(DTLS_KEY_PATH)) { throw new ApplicationException($"The DTLS key file could not be found at {DTLS_KEY_PATH}."); } var dtls = new DtlsHandshake(DTLS_CERTIFICATE_PATH, DTLS_KEY_PATH); webRtcSession.OnClose += (reason) => dtls.Shutdown(); int res = dtls.DoHandshakeAsServer((ulong)webRtcSession.RtpSession.RtpChannel.RtpSocket.Handle); logger.LogDebug("DtlsContext initialisation result=" + res); if (dtls.IsHandshakeComplete()) { logger.LogDebug("DTLS negotiation complete."); var srtpSendContext = new Srtp(dtls, false); var srtpReceiveContext = new Srtp(dtls, true); webRtcSession.RtpSession.SetSecurityContext( srtpSendContext.ProtectRTP, srtpReceiveContext.UnprotectRTP, srtpSendContext.ProtectRTCP, srtpReceiveContext.UnprotectRTCP); } return(res); }
private static async Task <WebRtcSession> SendSDPOffer(WebSocketContext context) { logger.LogDebug($"Web socket client connection from {context.UserEndPoint}."); var webRtcSession = new WebRtcSession(DTLS_CERTIFICATE_FINGERPRINT, null, _supportedVideoFormats, null); webRtcSession.VideoStreamStatus = MediaStreamStatusEnum.SendOnly; webRtcSession.RtpSession.OnReceiveReport += RtpSession_OnReceiveReport; webRtcSession.RtpSession.OnSendReport += RtpSession_OnSendReport; logger.LogDebug($"Sending SDP offer to client {context.UserEndPoint}."); webRtcSession.OnClose += (reason) => { logger.LogDebug($"WebRTCSession was closed with reason {reason}."); OnTestPatternSampleReady -= webRtcSession.SendMedia; }; await webRtcSession.Initialise(DoDtlsHandshake, null); context.WebSocket.Send(webRtcSession.SDP.ToString()); return(webRtcSession); }
private void PublishRemoteFeed(bool publishAudio) { { if (true) { session = new WebRtcSession(); { using (var go = new ManualResetEvent(false)) { var t = Task.Factory.StartNew(() => { ManagedConductor.InitializeSSL(); using (session.WebRtc) { session.WebRtc.AddServerConfig("stun:stun.l.google.com:19302", string.Empty, string.Empty); session.WebRtc.AddServerConfig("stun:stun.anyfirewall.com:3478", string.Empty, string.Empty); session.WebRtc.AddServerConfig("stun:stun.stunprotocol.org:3478", string.Empty, string.Empty); // session.WebRtc.AddServerConfig("turn:192.168.0.100:3478", "test", "test"); session.WebRtc.SetAudio(publishAudio); //if (!Form.checkBoxVirtualCam.Checked) { if (!string.IsNullOrEmpty(Form.videoDevice)) { var vok = session.WebRtc.OpenVideoCaptureDevice(Form.videoDevice); Trace.WriteLine($"OpenVideoCaptureDevice: {vok}, {Form.videoDevice}"); } if (!string.IsNullOrEmpty(Form.videoDevice_2)) { var vok_2 = session.WebRtc.OpenVideoCaptureDevice(Form.videoDevice_2); Trace.WriteLine($"OpenVideoCaptureDevice: {vok_2}, {Form.videoDevice_2}"); } } var ok = session.WebRtc.InitializePeerConnection(); if (ok) { session.WebRtc.OnSuccessAnswer += async delegate(string sdp) { var result = await client.CreateAnswer(false, false); if (result != null && (result.janus.Equals(Commands.SuccessCommand) || result.janus.Equals(Commands.AckCommand))) { } }; go.Set(); while (!session.Cancel.Token.IsCancellationRequested && session.WebRtc.ProcessMessages(1000)) { Debug.Write("."); } session.WebRtc.ProcessMessages(1000); } else { Debug.WriteLine("InitializePeerConnection failed"); //context.Close(); } } }, session.Cancel.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); if (go.WaitOne(9999)) { session.WebRtc.OnIceCandidate += async delegate(string sdp_mid, int sdp_mline_index, string sdp) { //var result = await client.PollingEventMessage(); //if(result != null && result.janus.Equals(Commands.ErrorCommand)) // todo: check session //{ // InitAndAttach(); await client.SendCandidate(sdp_mid, sdp_mline_index, sdp); //} }; session.WebRtc.OnSuccessAnswer += async delegate(string sdp) { Debug.WriteLine("OnSuccessAnswer failed"); }; session.WebRtc.OnFailure += delegate(string error) { Trace.WriteLine($"OnFailure: {error}"); }; session.WebRtc.OnError += delegate { Trace.WriteLine("OnError"); }; session.WebRtc.OnDataMessage += delegate(string dmsg) { Trace.WriteLine($"OnDataMessage: {dmsg}"); }; session.WebRtc.OnDataBinaryMessage += delegate(byte[] dmsg) { Trace.WriteLine($"OnDataBinaryMessage: {dmsg.Length}"); }; unsafe { session.WebRtc.OnRenderRemote += delegate(byte *frame_buffer, uint w, uint h) { OnRenderRemote(frame_buffer, w, h); }; session.WebRtc.OnRenderLocal += delegate(byte *frame_buffer, uint w, uint h) { OnRenderLocal(frame_buffer, w, h); }; } } } } //} } } }
private void PublishOwnFeed(bool publishAudio) { { if (true) { session = new WebRtcSession(); { using (var go = new ManualResetEvent(false)) { var t = Task.Factory.StartNew(() => { ManagedConductor.InitializeSSL(); using (session.WebRtc) { session.WebRtc.AddServerConfig("stun:stun.l.google.com:19302", string.Empty, string.Empty); session.WebRtc.AddServerConfig("stun:stun.anyfirewall.com:3478", string.Empty, string.Empty); session.WebRtc.AddServerConfig("stun:stun.stunprotocol.org:3478", string.Empty, string.Empty); // session.WebRtc.AddServerConfig("turn:192.168.0.100:3478", "test", "test"); session.WebRtc.SetAudio(publishAudio); //if (!Form.checkBoxVirtualCam.Checked) { if (!string.IsNullOrEmpty(Form.videoDevice)) { var vok = session.WebRtc.OpenVideoCaptureDevice(Form.videoDevice); Trace.WriteLine($"OpenVideoCaptureDevice: {vok}, {Form.videoDevice}"); } if (!string.IsNullOrEmpty(Form.videoDevice_2)) { var vok_2 = session.WebRtc.OpenVideoCaptureDevice(Form.videoDevice_2); Trace.WriteLine($"OpenVideoCaptureDevice: {vok_2}, {Form.videoDevice_2}"); } } var ok = session.WebRtc.InitializePeerConnection(); if (ok) { session.WebRtc.OnSuccessOffer += async delegate(string sdp) { // string deviceid = null; if (Form.Devices != null) { foreach (string deviceid in Form.Devices) { Console.WriteLine(deviceid); audioDevice audiodevice = new audioDevice(true); videoDevice videodevice = new videoDevice(true, deviceid); var result = await client.CreateOffer(sdp, audiodevice, videodevice); if (result != null && (result.janus.Equals(Commands.SuccessCommand) || result.janus.Equals(Commands.AckCommand))) { // continue; Console.WriteLine("Offer send successfully"); } else if (result.janus.Equals(Commands.ErrorCommand)) { // InitAndAttach(); Console.WriteLine("Reconnecting again"); } /* * media_1 = new Media(true, true, deviceId, "123", "232"); * var Result = await client.CreateOffer(sdp, media_1); * * if (Result != null && (Result.janus.Equals(Commands.SuccessCommand) || Result.janus.Equals(Commands.AckCommand))) * { * Console.WriteLine("Offer send successfully"); * } * else if (Result.janus.Equals(Commands.ErrorCommand)) * { * InitAndAttach(); * Console.WriteLine("Reconnecting again"); * } */ } } else if (Form.Devices == null) { return; } }; session.WebRtc.CreateOffer(); go.Set(); // javascript side makes the offer in this demo // session.WebRtc.CreateDataChannel("msgDataChannel"); while (!session.Cancel.Token.IsCancellationRequested && session.WebRtc.ProcessMessages(1000)) { Debug.Write("."); } session.WebRtc.ProcessMessages(1000); } else { Debug.WriteLine("InitializePeerConnection failed"); //context.Close(); } } }, session.Cancel.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); if (go.WaitOne(9999)) { session.WebRtc.OnIceCandidate += async delegate(string sdp_mid, int sdp_mline_index, string sdp) { // todo: check session await client.SendCandidate(sdp_mid, sdp_mline_index, sdp); var result = await client.PollingEventMessage(); if (result != null && result.janus.Equals(Commands.ErrorCommand)) { InitAndAttach(); } }; session.WebRtc.OnSuccessAnswer += async delegate(string sdp) { Debug.WriteLine("OnSuccessAnswer failed"); }; session.WebRtc.OnFailure += delegate(string error) { Trace.WriteLine($"OnFailure: {error}"); }; session.WebRtc.OnError += delegate { Trace.WriteLine("OnError"); }; session.WebRtc.OnDataMessage += delegate(string dmsg) { Trace.WriteLine($"OnDataMessage: {dmsg}"); }; session.WebRtc.OnDataBinaryMessage += delegate(byte[] dmsg) { Trace.WriteLine($"OnDataBinaryMessage: {dmsg.Length}"); }; unsafe { session.WebRtc.OnRenderRemote += delegate(byte *frame_buffer, uint w, uint h) { OnRenderRemote(frame_buffer, w, h); }; session.WebRtc.OnRenderLocal += delegate(byte *frame_buffer, uint w, uint h) { OnRenderLocal(frame_buffer, w, h); }; } } } } //} } } }
protected override async void OnOpen() { base.OnOpen(); WebRtcSession = await WebSocketOpened(this.Context); }
private void PublishOwnFeed(bool publishAudio) { { if (true) { session = new WebRtcSession(); { using (var go = new ManualResetEvent(false)) { var t = Task.Factory.StartNew(() => { ManagedConductor.InitializeSSL(); using (session.WebRtc) { session.WebRtc.AddServerConfig("stun:stun.l.google.com:19302", string.Empty, string.Empty); session.WebRtc.AddServerConfig("stun:stun.anyfirewall.com:3478", string.Empty, string.Empty); session.WebRtc.AddServerConfig("stun:stun.stunprotocol.org:3478", string.Empty, string.Empty); //session.WebRtc.AddServerConfig("turn:192.168.0.100:3478", "test", "test"); session.WebRtc.SetAudio(publishAudio); //if (!Form.checkBoxVirtualCam.Checked) { if (!string.IsNullOrEmpty(Form.videoDevice)) { var vok = session.WebRtc.OpenVideoCaptureDevice(Form.videoDevice); Trace.WriteLine($"OpenVideoCaptureDevice: {vok}, {Form.videoDevice}"); } } //else //{ // session.WebRtc.SetVideoCapturer(MainForm.screenWidth, // MainForm.screenHeight, // MainForm.captureFps, // MainForm.barCodeScreen); //} var ok = session.WebRtc.InitializePeerConnection(); if (ok) { session.WebRtc.OnSuccessOffer += async delegate(string sdp) { var result = await client.CreateOffer(sdp, true, true); if (result != null && (result.janus.Equals(Commands.SuccessCommand) || result.janus.Equals(Commands.AckCommand))) { //result = await client.CreateOffer(sdp, true, true); } }; session.WebRtc.CreateOffer(); go.Set(); // javascript side makes the offer in this demo //session.WebRtc.CreateDataChannel("msgDataChannel"); while (!session.Cancel.Token.IsCancellationRequested && session.WebRtc.ProcessMessages(1000)) { Debug.Write("."); } session.WebRtc.ProcessMessages(1000); } else { Debug.WriteLine("InitializePeerConnection failed"); //context.Close(); } } }, session.Cancel.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); if (go.WaitOne(9999)) { session.WebRtc.OnIceCandidate += async delegate(string sdp_mid, int sdp_mline_index, string sdp) { //if (context.IsAvailable) // todo: check session { //JsonData j = new JsonData(); //j["command"] = "OnIceCandidate"; //j["sdp_mid"] = sdp_mid; //j["sdp_mline_index"] = sdp_mline_index; //j["sdp"] = sdp; await client.SendCandidate(sdp_mid, sdp_mline_index, sdp); //context.Send(j.ToJson()); } }; session.WebRtc.OnSuccessAnswer += delegate(string sdp) { Debug.WriteLine("OnSuccessAnswer failed"); //if (context.IsAvailable) //{ // JsonData j = new JsonData(); // j["command"] = "OnSuccessAnswer"; // j["sdp"] = sdp; // context.Send(j.ToJson()); //} }; session.WebRtc.OnFailure += delegate(string error) { Trace.WriteLine($"OnFailure: {error}"); }; session.WebRtc.OnError += delegate { Trace.WriteLine("OnError"); }; session.WebRtc.OnDataMessage += delegate(string dmsg) { Trace.WriteLine($"OnDataMessage: {dmsg}"); }; session.WebRtc.OnDataBinaryMessage += delegate(byte[] dmsg) { Trace.WriteLine($"OnDataBinaryMessage: {dmsg.Length}"); }; unsafe { session.WebRtc.OnRenderRemote += delegate(byte *frame_buffer, uint w, uint h) { OnRenderRemote(frame_buffer, w, h); }; session.WebRtc.OnRenderLocal += delegate(byte *frame_buffer, uint w, uint h) { OnRenderLocal(frame_buffer, w, h); }; } //var d = msgJson["desc"]; //var s = d["sdp"].ToString(); //session.WebRtc.OnOfferRequest(s); } } } } } }