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