void HandleSdp(string message)
        {
            var msg = JsonConvert.DeserializeObject <dynamic>(message);

            if (msg.sdp != null)
            {
                var sdp = msg.sdp;
                if (sdp.type != null && sdp.type != "answer")
                {
                    throw new Exception("Not an answer");
                }
                string sdpAns = sdp.sdp;
                Console.WriteLine($"received answer:\n{sdpAns}");
                var res = SDPMessage.New(out SDPMessage sdpMsg);
                SDPMessage.ParseBuffer(ASCIIEncoding.Default.GetBytes(sdpAns), (uint)sdpAns.Length, sdpMsg);
                var answer  = WebRTCSessionDescription.New(WebRTCSDPType.Answer, sdpMsg);
                var promise = new Promise();
                _webRtc.Emit("set-remote-description", answer, promise);
            }
            else if (msg.ice != null)
            {
                var    ice           = msg.ice;
                string candidate     = ice.candidate;
                uint   sdpMLineIndex = ice.sdpMLineIndex;
                _webRtc.Emit("add-ice-candidate", sdpMLineIndex, candidate);
            }
        }
        void SendSdpOffer(WebRTCSessionDescription offer)
        {
            var text = offer.Sdp.AsText();
            var obj  = new { sdp = new { type = "offer", sdp = text } };
            var json = JsonConvert.SerializeObject(obj);

            json.PrintYellow();

            _conn.SendAsync(json, (b) => Console.WriteLine($"Send offer completed {b}"));
        }
        void OnOfferCreated(Promise promise)
        {
            var res   = promise.Wait();
            var reply = promise.RetrieveReply();
            var gval  = reply.GetValue("offer");
            WebRTCSessionDescription offer = (WebRTCSessionDescription)gval.Val;

            promise = new Promise();
            _webRtc.Emit("set-local-description", offer, promise);
            promise.Interrupt();
            SendSdpOffer(offer);
        }
Exemple #4
0
        private ResonanceActionResult <WebRTCOfferResponse> OnWebRTCOfferRequest(WebRTCOfferRequest request)
        {
            if (request.ChannelName != ChannelName)
            {
                return(null);
            }

            try
            {
                Logger.LogInformation("Offer received...");

                if (!_connectionInitialized)
                {
                    InitConnection();
                }

                Logger.LogInformation("Setting remote description...");
                var result = _connection.setRemoteDescription(request.Offer.ToSessionDescription());

                if (result != SetDescriptionResultEnum.OK)
                {
                    throw new Exception("Error setting remote description.");
                }

                if (request.Offer.InternalType == RTCSdpType.offer)
                {
                    Logger.LogInformation("Creating answer...");
                    var answer = _connection.createAnswer(null);

                    Logger.LogInformation("Setting local description...");
                    _connection.setLocalDescription(answer).GetAwaiter().GetResult();

                    Logger.LogInformation("Sending answer response...");
                    return(new ResonanceActionResult <WebRTCOfferResponse>(
                               new WebRTCOfferResponse()
                    {
                        ChannelName = ChannelName,
                        Answer = WebRTCSessionDescription.FromSessionDescription(answer)
                    }));
                }
                else
                {
                    Logger.LogError($"Invalid offer type received '{request.Offer.InternalType}'.");
                }

                throw new Exception("Invalid offer request.");
            }
            catch (Exception ex)
            {
                FailConnection(ex);
                throw ex;
            }
        }
        private Task <WebRTCSessionDescription> CreateAnswer(WebRTCSessionDescription offer)
        {
            TaskCompletionSource <WebRTCSessionDescription> completion = new TaskCompletionSource <WebRTCSessionDescription>();

            ManagedConductor.OnCallbackSdp del = null;

            bool completed = false;

            del = (sdp) =>
            {
                if (!completed)
                {
                    completed = true;
                    _conductor.OnSuccessAnswer -= del;
                    completion.SetResult(new WebRTCSessionDescription()
                    {
                        Sdp = sdp, InternalType = RTCSdpType.answer
                    });
                }
            };

            _conductor.OnSuccessAnswer += del;

            TimeoutTask.StartNew(() =>
            {
                if (!completed)
                {
                    completed = true;
                    completion.SetException(new TimeoutException("The answer was not created within the given time."));
                }
            }, TimeSpan.FromSeconds(10));

            _conductor.OnOfferRequest(offer.Sdp);

            return(completion.Task);
        }
Exemple #6
0
        private async void OnConnectionStateChanged(RTCPeerConnectionState state)
        {
            if (state == RTCPeerConnectionState.failed)
            {
                if (!_connectionCompleted)
                {
                    if (!_rolesReversed)
                    {
                        Logger.LogInformation("First connection attempt failed. Reversing roles...");

                        _rolesReversed        = true;
                        _canSendIceCandidates = false;

                        DisposeConnection();
                        InitConnection();

                        if (Role == WebRTCAdapterRole.Accept)
                        {
                            try
                            {
                                Logger.LogInformation("Creating offer...");

                                RTCSessionDescriptionInit offer = _connection.createOffer(new RTCOfferOptions());

                                Logger.LogInformation("Setting local description...");
                                await _connection.setLocalDescription(offer);

                                Logger.LogInformation("Sending offer request...");

                                var response = await _signalingTransporter.SendRequestAsync <WebRTCOfferRequest, WebRTCOfferResponse>(new WebRTCOfferRequest()
                                {
                                    ChannelName = ChannelName,
                                    Offer       = WebRTCSessionDescription.FromSessionDescription(offer)
                                }, new ResonanceRequestConfig()
                                {
                                    Timeout = TimeSpan.FromSeconds(10)
                                });

                                if (response.Answer.InternalType == RTCSdpType.answer)
                                {
                                    var result = _connection.setRemoteDescription(response.Answer.ToSessionDescription());

                                    if (result != SetDescriptionResultEnum.OK)
                                    {
                                        throw new Exception("Error setting the remote description.");
                                    }
                                }
                                else
                                {
                                    Logger.LogError($"Invalid answer type received '{response.Answer.InternalType}'.");
                                }

                                FlushIceCandidates();
                            }
                            catch (Exception ex)
                            {
                                FailConnection(ex);
                            }
                        }
                    }
                    else
                    {
                        FailConnection(new Exception("Second connection attempt failed."));
                    }
                }
                else
                {
                    OnFailed(new ResonanceWebRTCChannelClosedException("The WebRTC connection has failed."));
                }
            }
        }
Exemple #7
0
        protected override Task OnConnect()
        {
            //SIPSorcery.LogFactory.Set(Resonance.ResonanceGlobalSettings.Default.LoggerFactory);

            _connectionInitialized    = false;
            _rolesReversed            = false;
            _connectionCompleted      = false;
            _receivedSegments         = new List <byte[]>();
            _expectedSegments         = 0;
            _expectedSegmentsCheckSum = null;
            _incomingQueue            = new ProducerConsumerQueue <byte[]>();

            _connectionCompletionSource = new TaskCompletionSource <object>();

            Logger.LogInformation("Initializing adapter with role '{Role}'.", Role);

            Task.Factory.StartNew(async() =>
            {
                try
                {
                    Thread.Sleep(50);

                    if (Role == WebRTCAdapterRole.Accept)
                    {
                        if (_offerRequest != null)
                        {
                            Logger.LogInformation("Adapter initialized by an offer request. Sending answer...");
                            var response = OnWebRTCOfferRequest(_offerRequest);
                            _signalingTransporter.SendResponse(response.Response, _offerRequestToken);
                        }
                        else
                        {
                            Logger.LogInformation("Waiting for offer...");
                        }
                    }
                    else
                    {
                        InitConnection();

                        Logger.LogInformation("Creating offer...");
                        RTCSessionDescriptionInit offer = _connection.createOffer(new RTCOfferOptions());

                        Logger.LogInformation("Setting local description...");
                        await _connection.setLocalDescription(offer);

                        Logger.LogInformation("Sending offer request...");
                        var response = await _signalingTransporter.SendRequestAsync <WebRTCOfferRequest, WebRTCOfferResponse>(new WebRTCOfferRequest()
                        {
                            ChannelName = ChannelName,
                            Offer       = WebRTCSessionDescription.FromSessionDescription(offer)
                        }, new ResonanceRequestConfig()
                        {
                            Timeout = TimeSpan.FromSeconds(30)
                        });

                        if (response.Answer.InternalType == RTCSdpType.answer)
                        {
                            Logger.LogInformation("Answer received, setting remove description...");

                            var result = _connection.setRemoteDescription(response.Answer.ToSessionDescription());

                            if (result != SetDescriptionResultEnum.OK)
                            {
                                throw new Exception("Error setting the remote description.");
                            }
                        }
                        else
                        {
                            Logger.LogError($"Invalid answer type received '{response.Answer.InternalType}'.");
                        }

                        FlushIceCandidates();
                    }
                }
                catch (Exception ex)
                {
                    FailConnection(ex);
                }
            });

            return(_connectionCompletionSource.Task);
        }