IEnumerator GotAnswerCoroutine(string connectionId, RTCPeerConnection pc, string sdp) { var desc = new RTCSessionDescription(); desc.type = RTCSdpType.Answer; desc.sdp = sdp; var opRemoteSdp = pc.SetRemoteDescription(ref desc); yield return(opRemoteSdp); if (opRemoteSdp.IsError) { Debug.LogError($"Network Error: {opRemoteSdp.Error.message}"); } onGotAnswer?.Invoke(connectionId, sdp); }
public ARDSessionDescriptionMessage(RTCSessionDescription description) { Description = description; if (Description.Type.Equals("offer", StringComparison.Ordinal)) { Type = ARDSignalingMessageType.Offer; } else if (Description.Type.Equals("answer", StringComparison.Ordinal)) { Type = ARDSignalingMessageType.Answer; } else { System.Diagnostics.Debug.WriteLine($"Unexpected type: {Type}"); } }
public async Task <ICallInfo> PlaceCallAsync(CallConfiguration config) { Debug.Assert(_peerId == -1); if (PeerConnection != null) { Debug.WriteLine("[Error] We only support connection to one peer at a time."); return(null); } if (CreatePeerConnection()) { string selectedAudioCodecName = (string)_localSettings.Values["SelectedAudioCodecName"]; string selectedVideoCodecName = (string)_localSettings.Values["SelectedVideoCodecName"]; _peerId = PeerId; var offerOptions = new RTCOfferOptions(); offerOptions.OfferToReceiveAudio = true; offerOptions.OfferToReceiveVideo = true; IRTCSessionDescription offer = await PeerConnection.CreateOffer(offerOptions); // Alter sdp to force usage of selected codecs string modifiedSdp = offer.Sdp; SdpUtils.SelectCodec(ref modifiedSdp, selectedAudioCodecName, "audio"); SdpUtils.SelectCodec(ref modifiedSdp, selectedVideoCodecName, "video"); RTCSessionDescriptionInit sdpInit = new RTCSessionDescriptionInit(); sdpInit.Sdp = modifiedSdp; sdpInit.Type = offer.SdpType; var modifiedOffer = new RTCSessionDescription(sdpInit); await PeerConnection.SetLocalDescription(modifiedOffer); Debug.WriteLine($"Sending offer: {modifiedOffer.Sdp}"); string jsonString = SdpToJsonString(modifiedOffer); CallInfo callInfo = new CallInfo(); callInfo.SetCall(new Call()); callInfo.SetSdp(modifiedSdp); callInfo.SetJsonString(jsonString); OnSendMessageToRemotePeer.Invoke(this, jsonString); return(callInfo); } return(null); }
public Task HandleAsync( IRemoteDevice remoteDevice, Guid?peerConnectionId, RTCSessionDescription offer, TransceiverMetadata[] transceivers) { Require.NotNull(offer.Sdp); Require.NotNull(offer.Type); // Ensure the user has logged in var deviceData = remoteDevice.GetCustomData(); if (null == deviceData.User) { throw new UnauthorizedAccessException(); } // Get or create new PeerConnection, depending on the client's requests IPeerConnection peerConnection = null; if (peerConnectionId != null) { peerConnection = deviceData.PeerConnections.First(p => p.Id == peerConnectionId.Value); } else { if (deviceData.PeerConnections.Count > 3) { throw new InvalidOperationException($"Max 3 PeerConnection allowed per device"); } peerConnection = CreatePeerConnection(remoteDevice, deviceData.User); } // Save deviceData.PeerConnections.Add(peerConnection); remoteDevice.SetCustomData(deviceData); // Let the negotiation service handle the rest // Notes - queue transceiver metadata first before queuing the remote sdp, // so at the time processing remote sdp (which has remote transceivers) // we know transceviers' metadata inhand. // Fail to do so will cause errors. _negotiationService.EnqueueRemoteTransceiverMetadata(peerConnection, transceivers); _negotiationService.EnqueueRemoteOffer(peerConnection, offer); return(Task.CompletedTask); }
private IEnumerator OnCreateOfferSuccess(RTCPeerConnection pc, RTCSessionDescription desc) { Debug.Log("setLocalDescription start"); var op = pc.SetLocalDescription(ref desc); yield return(op); if (!op.IsError) { OnSetLocalSuccess(pc); } else { var error = op.Error; OnSetSessionDescriptionError(ref error); } }
/// <summary> /// Sets relevant properties for this session based on the SDP from the remote party. /// </summary> /// <param name="sessionDescription">The session description from the remote call party.</param> public override void setRemoteDescription(RTCSessionDescription sessionDescription) { base.setRemoteDescription(sessionDescription); var connAddr = IPAddress.Parse(sessionDescription.sdp.Connection.ConnectionAddress); foreach (var announcement in sessionDescription.sdp.Media) { var annAddr = connAddr; if (announcement.Connection != null) { annAddr = IPAddress.Parse(announcement.Connection.ConnectionAddress); } if (announcement.Media == SDPMediaTypesEnum.audio) { var connRtpEndPoint = new IPEndPoint(annAddr, announcement.Port); var connRtcpEndPoint = new IPEndPoint(annAddr, announcement.Port + 1); SetDestination(SDPMediaTypesEnum.audio, connRtpEndPoint, connRtcpEndPoint); foreach (var mediaFormat in announcement.MediaFormats) { if (mediaFormat.FormatAttribute?.StartsWith(TELEPHONE_EVENT_ATTRIBUTE) == true) { if (!int.TryParse(mediaFormat.FormatID, out var remoteRtpEventPayloadID)) { //logger.LogWarning("The media format on the telephone event attribute was not a valid integer."); } else { base.RemoteRtpEventPayloadID = remoteRtpEventPayloadID; } break; } } } else if (announcement.Media == SDPMediaTypesEnum.video) { var connRtpEndPoint = new IPEndPoint(annAddr, announcement.Port); var connRtcpEndPoint = new IPEndPoint(annAddr, announcement.Port + 1); SetDestination(SDPMediaTypesEnum.video, connRtpEndPoint, connRtcpEndPoint); } } }
IEnumerator OnCreateAnswerSuccess(RTCSessionDescription desc) { Debug.Log($"Answer created:\n{desc.sdp}"); Debug.Log("setLocalDescription start"); var op = peerConnection.SetLocalDescription(ref desc); yield return(op); if (!op.IsError) { OnSetLocalSuccess(desc, false); } else { var error = op.Error; OnSetSessionDescriptionError(ref error); } }
IEnumerator proccessAnswer(string sdp) { //string pattern = @"(a=fmtp:\d+ .*level-asymmetry-allowed=.*)\r\n"; //sdp = Regex.Replace(sdp, pattern, "$1;x-google-start-bitrate=16000;x-google-max-bitrate=160000\r\n"); RTCSessionDescription answer = default; answer.type = RTCSdpType.Answer; answer.sdp = sdp; Debug.Log($"set remote answer: {sdp}"); var ret = pc.SetRemoteDescription(ref answer); yield return(ret); if (ret.isError) { Debug.Log($"processAnser error:{ret.error}"); } }
IEnumerator HandleAnswer(RTCSessionDescription desc) { Debug.Log($"HandleAnswer\n{desc.sdp}"); Debug.Log("setRemoteDescription start"); var op = peerConnection.SetRemoteDescription(ref desc); yield return(op); if (!op.IsError) { OnSetRemoteSuccess(); } else { var error = op.Error; OnSetSessionDescriptionError(ref error); } }
public void CallUser(string targetEmail, RTCSessionDescription offer) { var targetUser = Users.Where(x => x.Email == targetEmail).FirstOrDefault(); var sourceUser = Users.Where(x => x.Email == Context.User.Identity.Name).FirstOrDefault(); if (targetUser == null || sourceUser == null) { #warning display error to user return; } else { //targetUser.UserStatus = OnlineUserStatus.Busy; //sourceUser.UserStatus = OnlineUserStatus.Busy; SendUserList(Users); SendOffer(targetUser, sourceUser, offer); } }
private void HandleAnswer(string room, string sdp) { Debug.Log("HandleAnswer"); if (room != roomName) { Debug.LogError("Wrong room name " + room); return; } if (!isCaller) { Debug.LogWarning("Not a caller, can't handle 'answer'"); return; } RTCSessionDescription desc = new RTCSessionDescription { type = RTCSdpType.Answer, sdp = sdp }; StartCoroutine(HandleAnswer(desc)); }
private IEnumerator OnCreateOfferSuccess(RTCSessionDescription desc) { Debug.Log("OnCreateOfferSuccess"); Debug.Log($"Offer from pc\n{desc.sdp}"); Debug.Log("pc setLocalDescription start"); var op = peerConnection.SetLocalDescription(ref desc); yield return(op); if (!op.IsError) { OnSetLocalSuccess(desc, true); } else { var error = op.Error; OnSetSessionDescriptionError(ref error); } }
private async void signaller_ReceivedOffer(object sender, RTCSessionDescription offer) { if (this.peerConnection != null) { return; } this.peerConnection = await this.buildPeerConnection(this.mediaOptions); await this.peerConnection.SetRemoteDescription(offer); var answer = await this.peerConnection.CreateAnswer(new RTCAnswerOptions()); await this.peerConnection.SetLocalDescription(answer); await this.signaller.SendAnswer((RTCSessionDescription)answer); this.peerConnection.OnIceCandidate += this.peerConnection_OnIceCandidate; }
public void SetRemoteSessionDescription(RTCSessionDescription description, Callback callback) { if (callback is null) { throw new ArgumentNullException(nameof(callback)); } MustNotDisposed(); _peerConnectionImpl.SetRemoteSessionDescription( description.Type, description.Sdp, new Callback().OnSuccess(delegate { try { // TODO: move this, // AddPeerConnection() should be called right after the peer connection // factory returns the newly created PeerConnection. // // To accomplish this, make sure VideoRouter listens to PeerConnection's track events, // because when PeerConnection has just been created, it has no track, however // SetRemoteSessionDescription() above adds track after the PeerConnection is added to the router. if (Interlocked.CompareExchange( ref _addedToRouterState, (int)AddedToRouterState.Added, (int)AddedToRouterState.NotAdded) == (int)AddedToRouterState.NotAdded) { // As per webRTC example, the answerer will SetRemoteSessionDescription() first, // then followed by AddTrack(); // // and AddPeerConnectionAsync() will call AddTrack() under the hood, // therefore we call AddPeerConnectionAsync() right after SetRemoteSessionDescription(); _videoRouter.AddPeerConnection(Device, this); } callback.Success(); } catch (Exception ex) { _logger.Error(ex); callback.Error(ex.Message); } }).OnError(msg => callback.Error(msg))); }
public static ARDSignalingMessage MessageFromJSONString(string json) { var values = JsonConvert.DeserializeObject <Dictionary <string, string> >(json); ARDSignalingMessage message = new ARDSignalingMessage(); if (values.ContainsKey("type")) { var type = values["type"] ?? ""; switch (type) { case "candidate": int.TryParse(values["label"], out int label); RTCIceCandidate candidate = new RTCIceCandidate(values["id"], label, values["candidate"]); message = new ARDICECandidateMessage(candidate); break; case "offer": RTCSessionDescription description = new RTCSessionDescription(RTCSdpType.Offer, values["sdp"]); message = new ARDSessionDescriptionMessage(description); break; case "answer": description = new RTCSessionDescription(RTCSdpType.Answer, values["sdp"]); message = new ARDSessionDescriptionMessage(description); break; case "bye": message = new ARDByeMessage(); break; default: System.Diagnostics.Debug.WriteLine($"ARDSignalingMessage unexpected type: {type}"); break; } } else { System.Diagnostics.Debug.WriteLine($"ARDSignalingMessage invalid json: {json}"); } return(message); }
public ARDSessionDescriptionMessage(RTCSessionDescription description) { Description = description; switch (Description.Type) { case RTCSdpType.Offer: Type = ARDSignalingMessageType.Offer; break; case RTCSdpType.PrAnswer: break; case RTCSdpType.Answer: Type = ARDSignalingMessageType.Answer; break; default: System.Diagnostics.Debug.WriteLine($"ARDSessionDescriptionMessage unexpected type: {Type}"); break; } }
IEnumerator SetDescription(RTCSessionDescription desc, Side side) { Debug.Log($"[Set {side} {desc.type}]"); var op = side == Side.Local ? localConnection.SetLocalDescription(ref desc) : localConnection.SetRemoteDescription(ref desc); yield return(op); if (op.IsError) { Debug.LogError(op.Error.message); } else if (desc.type == RTCSdpType.Offer) { StartCoroutine(CreateDescription(RTCSdpType.Answer)); } else if (side == Side.Local && desc.type == RTCSdpType.Answer) { SendDescription(ref desc); } }
IEnumerator setDesc(string id, Side side, RTCSessionDescription desc) { var pc = pcs[id]; Debug.Log($"[Set {side} {desc.type}] id:{id}"); var op = side == Side.Local ? pc.SetLocalDescription(ref desc) : pc.SetRemoteDescription(ref desc); yield return(op); if (op.IsError) { Debug.LogError(op.Error.message); } else if (desc.type == RTCSdpType.Offer) { StartCoroutine(createDesc(id, RTCSdpType.Answer)); } else if (side == Side.Local && desc.type == RTCSdpType.Answer) { signalingServer.Send(id, ref desc); } }
public void DidCreateSessionDescription(RTCPeerConnection peerConnection, RTCSessionDescription sdp, NSError error) { // dispatch_async(dispatch_get_main_queue(), if (error != null) { System.Diagnostics.Debug.WriteLine($"Failed to create session description. Error: {error}"); Disconnect(); // NSDictionary *userInfo = @{ // NSLocalizedDescriptionKey: @"Failed to create session description.", // }; // NSError *sdpError = // [[NSError alloc] initWithDomain:kARDAppClientErrorDomain // code:kARDAppClientErrorCreateSDP // userInfo:userInfo]; _delegate.DidError(this, error); return; } _peerConnection.SetLocalDescriptionWithDelegate(this, sdp); ARDSessionDescriptionMessage message = new ARDSessionDescriptionMessage(sdp); SendSignalingMessage(message).Wait(); }
IEnumerator HandleOffer(string sdp) { Debug.Log("HandleOffer start"); Debug.Log("setRemoteDescription start"); var desc = new RTCSessionDescription { sdp = sdp, type = RTCSdpType.Offer }; var op = peerConnection.SetRemoteDescription(ref desc); yield return(op); if (!op.IsError) { OnSetRemoteSuccess(); yield return(StartCoroutine(CreateAnswer())); } else { var error = op.Error; OnSetSessionDescriptionError(ref error); } }
private async void signaller_ReceivedOffer(object sender, RTCSessionDescription offer) { Logger.Log("Received offer"); if (this.peerConnection != null) { return; } this.peerConnection = await this.createPeerConnection(); await this.peerConnection.SetRemoteDescription(offer); var answer = await this.peerConnection.CreateAnswer(); await this.peerConnection.SetLocalDescription(answer); await this.signaller.SendAnswer(answer); await this.reconfigureLocalStream(); await this.submitIceCandidatesAsync(); }
public async Task CreatOffer(long uid, long fromUid) //此时是发起方的操作 { RTCSessionDescription offer; if (fromUid == 0) { offer = await CurrentRoom.Pub.CreateOffer(); await CurrentRoom.Pub.SetLocalDescription(offer); } else { offer = await CurrentRoom.Recvs[fromUid].CreateOffer(); await CurrentRoom.Recvs[fromUid].SetLocalDescription(offer); } var m = new GetAnswerModel(); m.offer = offer.Sdp; m.uid = uid; m.fromUid = fromUid; var answerSdp = await SendOffer(m); if (answerSdp != "") { var answer = new RTCSessionDescription(); answer.Type = RTCSdpType.Answer; answer.Sdp = answerSdp; if (fromUid == 0) { await CurrentRoom.Pub.SetRemoteDescription(answer); } else { await CurrentRoom.Recvs[fromUid].SetRemoteDescription(answer); } } }
IEnumerator OnAnswer(ISignaling signaling, DescData e) { if (!m_mapConnectionIdAndPeer.TryGetValue(e.connectionId, out var pc)) { Debug.Log($"connectiondId:{e.connectionId}, peerConnection not exist"); yield break; } var desc = new RTCSessionDescription(); desc.type = RTCSdpType.Answer; desc.sdp = e.sdp; var opRemoteSdp = pc.SetRemoteDescription(ref desc); yield return(opRemoteSdp); if (opRemoteSdp.IsError) { Debug.LogError($"Network Error: {opRemoteSdp.Error.message}"); yield break; } }
IEnumerator OnCreateAnswerSuccess(RTCPeerConnection pc, RTCSessionDescription desc) { Debug.Log($"Answer from {GetName(pc)}:\n{desc.sdp}"); Debug.Log($"{GetName(pc)} setLocalDescription start"); var op = pc.SetLocalDescription(ref desc); yield return(op); if (!op.IsError) { OnSetLocalSuccess(pc); } else { var error = op.Error; OnSetSessionDescriptionError(ref error); } var otherPc = GetOtherPc(pc); Debug.Log($"{GetName(otherPc)} setRemoteDescription start"); var op2 = otherPc.SetRemoteDescription(ref desc); yield return(op2); if (!op2.IsError) { OnSetRemoteSuccess(otherPc); StartCoroutine(CheckActualCodec()); } else { var error = op2.Error; OnSetSessionDescriptionError(ref error); } }
private IEnumerator setRemoteDesc(RTCSdpType type, string sdp) { var desc = new RTCSessionDescription { type = type, sdp = sdp }; log(LogLevel.Log, $"SetRemoteDescription {type}"); var opSetDesc = peer.SetRemoteDescription(ref desc); yield return(opSetDesc); if (opSetDesc.IsError) { log(LogLevel.Error, $"SetRemoteDescription {type}: {opSetDesc.Error.message}"); yield break; } if (type == RTCSdpType.Offer) { yield return(StartCoroutine(createDesc(RTCSdpType.Answer))); } }
public static string AsJSON(this RTCSessionDescription rtcSessionDescription) { return(JsonConvert.SerializeObject(new { type = rtcSessionDescription.Type, sdp = rtcSessionDescription.Description })); }
static Callback SetLocalSessionDescriptionObserver(Callback completionCallback, IPeerConnection peerConnection, RTCSessionDescription offer) => new Callback() .OnError(completionCallback) .OnSuccess(delegate { // Generate transceiver metadata and send along with the offer. try { var transceivers = peerConnection.Room.VideoRouter.GetLocalTransceiverMetadata(peerConnection); peerConnection.Device.EnqueueOffer(peerConnection.Id, peerConnection.LastOfferId, offer, transceivers); _logger.Debug($"[Renegotiation Step 1/3] Offer generated and sent for {peerConnection}."); } catch (Exception ex) { completionCallback.Error($"{nameof(IRemoteDevice.EnqueueOffer)} failed: {ex.Message}"); if (!(ex is ObjectDisposedException)) { _logger.Error(ex); } return; } _logger.Debug($"[Renegotiation Step 2/3] Local offer set for {peerConnection}."); completionCallback.Success(); });
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(); }
public void setRemoteDescription(RTCSessionDescription sessionDescription) { remoteDescription = sessionDescription; }
public void setLocalDescription(RTCSessionDescription sessionDescription) { localDescription = sessionDescription; }
public void SetLocalDescription(RTCSessionDescription description) { }
public void SetLocalDescription(RTCSessionDescription description, Action successCallback) { }
public void SetRemoteDescription(RTCSessionDescription description) { }
public void SetRemoteDescription(RTCSessionDescription description, Action successCallback) { }
public void SetRemoteDescription(RTCSessionDescription description, Action successCallback, RTCPeerConnectionErrorCallback failureCallback) { }