Ejemplo n.º 1
0
        private static async Task WebSocketMessageReceived(WebSocketContext context, RTCPeerConnection pc, string message)
        {
            try
            {
                if (pc.localDescription == null)
                {
                    //logger.LogDebug("Offer SDP: " + message);
                    logger.LogDebug("Offer SDP received.");

                    // Add local media tracks depending on what was offered. Also add local tracks with the same media ID as
                    // the remote tracks so that the media announcement in the SDP answer are in the same order.
                    SDP remoteSdp = SDP.ParseSDPDescription(message);
                    pc.setRemoteDescription(new RTCSessionDescriptionInit {
                        sdp = message, type = RTCSdpType.offer
                    });

                    var answer = pc.createAnswer(null);
                    await pc.setLocalDescription(answer);

                    context.WebSocket.Send(answer.sdp);
                }
                else if (pc.remoteDescription == null)
                {
                    logger.LogDebug("Answer SDP: " + message);
                    pc.setRemoteDescription(new RTCSessionDescriptionInit {
                        sdp = message, type = RTCSdpType.answer
                    });
                }
                else
                {
                    logger.LogDebug("ICE Candidate: " + message);

                    if (string.IsNullOrWhiteSpace(message) || message.Trim().ToLower() == SDP.END_ICE_CANDIDATES_ATTRIBUTE)
                    {
                        logger.LogDebug("End of candidates message received.");
                    }
                    else
                    {
                        var candInit = Newtonsoft.Json.JsonConvert.DeserializeObject <RTCIceCandidateInit>(message);
                        pc.addIceCandidate(candInit);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception WebSocketMessageReceived. " + excp.Message);
            }
        }
Ejemplo n.º 2
0
        public void AddIceCandidate(IceCandidateArgs args)
        {
            Console.WriteLine("Add ice candidate");
            if (args.ConnectionId != ConnectionId)
            {
                throw new Exception();
            }

            _peerConnection.addIceCandidate(new RTCIceCandidateInit
            {
                candidate        = args.CandidateDto.Candidate,
                sdpMid           = args.CandidateDto.SdpMid,
                sdpMLineIndex    = (ushort)args.CandidateDto.SdpMLineIndex,
                usernameFragment = args.CandidateDto.UsernameFragment
            });
        }
Ejemplo n.º 3
0
 private static void WebSocketMessageReceived(RTCPeerConnection pc, string message)
 {
     if (pc.remoteDescription == null)
     {
         logger.LogDebug("Answer SDP: " + message);
         pc.setRemoteDescription(new RTCSessionDescriptionInit {
             sdp = message, type = RTCSdpType.answer
         });
     }
     else
     {
         logger.LogDebug("ICE Candidate: " + message);
         pc.addIceCandidate(new RTCIceCandidateInit {
             candidate = message
         });
     }
 }
Ejemplo n.º 4
0
 private static async Task WebSocketMessageReceived(RTCPeerConnection peerConnection, string message)
 {
     try
     {
         if (peerConnection.remoteDescription == null)
         {
             logger.LogDebug("Answer SDP: " + message);
             await peerConnection.setRemoteDescription(new RTCSessionDescriptionInit { sdp = message, type = RTCSdpType.answer });
         }
         else
         {
             logger.LogDebug("ICE Candidate: " + message);
             await peerConnection.addIceCandidate(new RTCIceCandidateInit { candidate = message });
         }
     }
     catch (Exception excp)
     {
         logger.LogError("Exception WebSocketMessageReceived. " + excp.Message);
     }
 }
Ejemplo n.º 5
0
        private void DoProcessMessage(Message message)
        {
            switch (message.type)
            {
            case "Offer":
                // var offer = JsonUtility.FromJson<RTCSessionDescriptionInit>(message.args);
                if (RTCSessionDescriptionInit.TryParse(message.args, out RTCSessionDescriptionInit offer))
                {
                    Debug.Log($"Got remote SDP, type {offer.type}");

                    var result = rtcPeerConnection.setRemoteDescription(offer);
                    if (result != SetDescriptionResultEnum.OK)
                    {
                        Debug.Log($"Failed to set remote description, {result}.");
                        rtcPeerConnection.Close("Failed to set remote description");
                    }
                    else
                    {
                        if (rtcPeerConnection.signalingState == RTCSignalingState.have_remote_offer)
                        {
                            var answerSdp = rtcPeerConnection.createAnswer();
                            rtcPeerConnection.setLocalDescription(answerSdp);

                            Debug.Log($"Sending SDP answer");

                            Send("Offer", answerSdp.toJSON());
                        }
                    }
                }
                break;

            case "IceCandidate":
                if (RTCIceCandidateInit.TryParse(message.args, out RTCIceCandidateInit candidate))
                {
                    Debug.Log($"Got remote Ice Candidate, uri {candidate.candidate}");
                    rtcPeerConnection.addIceCandidate(candidate);
                }
                break;
            }
        }
Ejemplo n.º 6
0
        private static async Task WebSocketMessageReceived(WebSocketContext context, RTCPeerConnection pc, string message)
        {
            try
            {
                if (pc.localDescription == null)
                {
                    //logger.LogDebug("Offer SDP: " + message);
                    logger.LogDebug("Offer SDP received.");

                    // Add local media tracks depending on what was offered. Also add local tracks with the same media ID as
                    // the remote tracks so that the media announcement in the SDP answer are in the same order.
                    SDP remoteSdp = SDP.ParseSDPDescription(message);

                    foreach (var ann in remoteSdp.Media)
                    {
                        MediaStreamTrack track = new MediaStreamTrack(ann.Media, false, ann.MediaFormats.Values.ToList(), MediaStreamStatusEnum.RecvOnly);
                        pc.addTrack(track);
                    }

                    pc.setRemoteDescription(new RTCSessionDescriptionInit {
                        sdp = message, type = RTCSdpType.offer
                    });

                    var answer = pc.createAnswer(null);
                    await pc.setLocalDescription(answer);

                    Console.WriteLine(answer.sdp);

                    context.WebSocket.Send(answer.sdp);
                }
                else if (pc.remoteDescription == null)
                {
                    logger.LogDebug("Answer SDP: " + message);
                    var result = pc.setRemoteDescription(new RTCSessionDescriptionInit {
                        sdp = message, type = RTCSdpType.answer
                    });
                    if (result != SetDescriptionResultEnum.OK)
                    {
                        logger.LogWarning($"Failed to set remote description {result}.");
                    }
                }
                else
                {
                    logger.LogDebug("ICE Candidate: " + message);

                    if (string.IsNullOrWhiteSpace(message) || message.Trim().ToLower() == SDP.END_ICE_CANDIDATES_ATTRIBUTE)
                    {
                        logger.LogDebug("End of candidates message received.");
                    }
                    else
                    {
                        var candInit = Newtonsoft.Json.JsonConvert.DeserializeObject <RTCIceCandidateInit>(message);
                        pc.addIceCandidate(candInit);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception WebSocketMessageReceived. " + excp.Message);
            }
        }
Ejemplo n.º 7
0
        private static async Task WebSocketMessageReceived(WebSocketContext context, RTCPeerConnection pc, string message)
        {
            try
            {
                if (pc.localDescription == null)
                {
                    //logger.LogDebug("Offer SDP: " + message);
                    logger.LogDebug("Offer SDP received.");

                    // Add local media tracks depending on what was offered. Also add local tracks with the same media ID as
                    // the remote tracks so that the media announcement in the SDP answer are in the same order.
                    var offerInit = JsonConvert.DeserializeObject <RTCSessionDescriptionInit>(message, new Newtonsoft.Json.Converters.StringEnumConverter());

                    logger.LogDebug(SDP.ParseSDPDescription(offerInit.sdp).ToString());

                    var res = pc.setRemoteDescription(offerInit);

                    if (res != SetDescriptionResultEnum.OK)
                    {
                        // No point continuing. Something will need to change and then try again.
                        pc.Close("failed to set remote sdp");
                    }
                    else
                    {
                        var answer = pc.createAnswer(_answerOptions);
                        await pc.setLocalDescription(answer);

                        context.WebSocket.Send(JsonConvert.SerializeObject(answer, new Newtonsoft.Json.Converters.StringEnumConverter()));
                    }
                }
                else if (pc.remoteDescription == null)
                {
                    logger.LogDebug("Answer SDP received:");

                    var answerInit = JsonConvert.DeserializeObject <RTCSessionDescriptionInit>(message, new Newtonsoft.Json.Converters.StringEnumConverter());

                    logger.LogDebug(SDP.ParseSDPDescription(answerInit.sdp).ToString());

                    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
                {
                    logger.LogDebug("ICE Candidate: " + message);

                    if (string.IsNullOrWhiteSpace(message) || message.Trim().ToLower() == SDP.END_ICE_CANDIDATES_ATTRIBUTE)
                    {
                        logger.LogDebug("End of candidates message received.");
                    }
                    else
                    {
                        var candInit = Newtonsoft.Json.JsonConvert.DeserializeObject <RTCIceCandidateInit>(message);

                        if (_acceptIceTypes.Count > 0 && !_acceptIceTypes.Any(x => x == RTCIceCandidate.Parse(candInit.candidate).type))
                        {
                            logger.LogDebug($"Ignoring remote ICE candidate as type not in accept list.");
                        }
                        else
                        {
                            pc.addIceCandidate(candInit);
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception WebSocketMessageReceived. " + excp.Message);
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection

            // https://github.com/cjb/serverless-webrtc

            // https://github.com/XSockets/WebRTC


            // jsc when was the last time we tried p2p?
            // var peer = new PeerConnection(iceServers, optional); where iceServers = null this is working without internet
            // http://stackoverflow.com/questions/19675165/whether-stun-server-is-needed-within-lan-for-webrtc

            //var peer = new PeerConnection(iceServers, optional);
            // https://www.webrtc-experiment.com/docs/WebRTC-PeerConnection.html
            // http://stackoverflow.com/questions/12848013/what-is-the-replacement-for-the-deprecated-peerconnection-api
            // http://docs.webplatform.org/wiki/apis/webrtc/RTCPeerConnection
            // http://w3schools.invisionzone.com/index.php?showtopic=46661
            // http://www.html5rocks.com/en/tutorials/webrtc/basics/#toc-rtcpeerconnection



            // IDL dictionary looks like C# PrimaryCnstructor concept does it not
            ////var d = new RTCSessionDescription(
            ////    new
            ////{

            ////}
            ////);


            //    02000002 TestPeerConnection.Application
            //    script: error JSC1000: You tried to instance a class which seems to be marked as native.
            //    script: error JSC1000: type has no callable constructor: [ScriptCoreLib.JavaScript.DOM.RTCPeerConnection]
            //Void.ctor()

            // Uncaught ReferenceError: RTCPeerConnection is not defined
            // wtf?


            // {{ RTCPeerConnection = undefined }}
            //new IHTMLPre { new { w.RTCPeerConnection } }.AttachToDocument();
            // {{ webkitRTCPeerConnection = function RTCPeerConnection() { [native code] } }}
            //new IHTMLPre { new { w.webkitRTCPeerConnection } }.AttachToDocument();

            // wtf chrome? stop prefixing
            var w = Native.window as dynamic;

            Console.WriteLine(new { w.RTCPeerConnection });

            w.RTCPeerConnection = w.webkitRTCPeerConnection;
            // Uncaught TypeError: Failed to construct 'RTCPeerConnection': 1 argument required, but only 0 present.

            // http://stackoverflow.com/questions/22470291/rtcdatachannels-readystate-is-not-open

            // after Chrome 31, you can use SCTP based data channels.
            // http://stackoverflow.com/questions/21585681/send-image-data-over-rtc-data-channel
            // https://code.google.com/p/chromium/issues/detail?id=295771
            // https://gist.github.com/shacharz/9661930



            // http://chimera.labs.oreilly.com/books/1230000000545/ch18.html#_tracking_ice_gathering_and_connectivity_status
            var peer = new RTCPeerConnection(
                new { iceServers = new object[0] },
                null

                // https://groups.google.com/forum/#!topic/discuss-webrtc/y2A97iCByTU

                //constraints: new {
                //    optional = new[]
                //    {
                //        new {  RtpDataChannels = true }
                //    }
                //}
                );

            // how the hell cann I connect two p2p?
            // i see we need to do data

            //peer.setLocalDescription
            // https://groups.google.com/forum/#!topic/discuss-webrtc/zK_5yUqiqsE
            // X:\jsc.svn\examples\javascript\xml\VBDisplayServerDebuggerPresence\VBDisplayServerDebuggerPresence\ApplicationWebService.vb
            // https://code.google.com/p/webrtc/source/browse/trunk/samples/js/base/adapter.js
            // http://www.webrtc.org/faq-recent-topics

            // http://stackoverflow.com/questions/14134090/how-is-a-webrtc-peer-connection-established

            peer.onicecandidate = new Action <RTCPeerConnectionIceEvent>(
                (RTCPeerConnectionIceEvent e) =>
            {
                if (e.candidate != null)
                {
                    new IHTMLPre {
                        "onicecandidate: " + new { e.candidate.candidate }
                    }.AttachToDocument();



                    peer.addIceCandidate(e.candidate,
                                         new Action(
                                             delegate
                    {
                        new IHTMLPre {
                            "addIceCandidate"
                        }.AttachToDocument();
                    }
                                             ));
                }
            }
                );

            // http://stackoverflow.com/questions/15484729/why-doesnt-onicecandidate-work
            // http://www.skylinetechnologies.com/Blog/Article/48/Peer-to-Peer-Media-Streaming-with-WebRTC-and-SignalR.aspx

            peer.createOffer(
                new Action <RTCSessionDescription>(
                    (RTCSessionDescription x) =>
            {
                new IHTMLPre {
                    "after createOffer " + new { x.sdp }
                }.AttachToDocument();

                peer.setLocalDescription(x,
                                         new Action(
                                             delegate
                {
                    // // send the offer to a server that can negotiate with a remote client
                    new IHTMLPre {
                        "after setLocalDescription "
                    }.AttachToDocument();
                }
                                             )
                                         );

                peer.setRemoteDescription(x,
                                          new Action(
                                              delegate
                {
                    // // send the offer to a server that can negotiate with a remote client
                    new IHTMLPre {
                        "after setRemoteDescription "
                    }.AttachToDocument();
                }
                                              )
                                          );
            }
                    )
                );



            peer.createAnswer(
                new Action <RTCSessionDescription>(
                    (RTCSessionDescription x) =>
            {
                new IHTMLPre {
                    "after createAnswer " + new { x.sdp }
                }.AttachToDocument();
            }
                    ));


            // https://groups.google.com/forum/#!topic/discuss-webrtc/wbcgYMrIii4
            // https://groups.google.com/forum/#!msg/discuss-webrtc/wbcgYMrIii4/aZ12cENVTxEJ
            // http://blog.printf.net/articles/2013/05/17/webrtc-without-a-signaling-server/

            //peer.onconn

            // https://github.com/cjb/serverless-webrtc/blob/master/js/serverless-webrtc.js
            peer.ondatachannel = new Action <RTCDataChannelEvent>(
                (RTCDataChannelEvent e) =>
            {
                //Console.WriteLine("ondatachannel");
                new IHTMLPre {
                    "ondatachannel"
                }.AttachToDocument();

                var c = e.channel;

                c.onmessage = new Action <MessageEvent>(
                    (MessageEvent ee) =>
                {
                    new IHTMLPre {
                        new { ee.data }
                    }.AttachToDocument();
                }
                    );
            }
                );

            // jsc cant the idl generator understand optinal?
            RTCDataChannel dc = peer.createDataChannel("label1", null);


            // {{ id = 65535, label = label1, readyState = connecting }}
            new IHTMLPre {
                new { dc.id, dc.label, dc.readyState }
            }.AttachToDocument();

            new IHTMLButton {
                "awaiting to open..."
            }.AttachToDocument().With(
                button =>
            {
                // !!! can our IDL compiler generate events and async at the same time?
                dc.onopen = new Action <IEvent>(
                    async ee =>
                {
                    button.innerText = "send";

                    while (true)
                    {
                        await button.async.onclick;

                        new IHTMLPre {
                            "send"
                        }.AttachToDocument();

                        // Failed to execute 'send' on 'RTCDataChannel': RTCDataChannel.readyState is not 'open'
                        dc.send("data to send");
                    }
                }
                    );
            }
                );

            //connection.createOffer
        }