/// <summary> /// Attempts to place a new outgoing call. /// </summary> /// <param name="sipCallDescriptor">A call descriptor containing the information about how /// and where to place the call.</param> /// <param name="mediaSession">The media session used for this call</param> public async Task InitiateCall(SIPCallDescriptor sipCallDescriptor, IMediaSession mediaSession) { m_uac = new SIPClientUserAgent(m_transport); m_uac.CallTrying += ClientCallTryingHandler; m_uac.CallRinging += ClientCallRingingHandler; m_uac.CallAnswered += ClientCallAnsweredHandler; m_uac.CallFailed += ClientCallFailedHandler; SIPEndPoint serverEndPoint = m_uac.GetCallDestination(sipCallDescriptor); if (serverEndPoint != null) { MediaSession = mediaSession; MediaSession.SessionMediaChanged += MediaSessionOnSessionMediaChanged; var sdp = await MediaSession.CreateOffer(serverEndPoint.Address).ConfigureAwait(false); sipCallDescriptor.Content = sdp; m_uac.Call(sipCallDescriptor); } else { ClientCallFailed?.Invoke(m_uac, $"Could not resolve destination when placing call to {sipCallDescriptor.Uri}."); CallEnded(); } }
/// <summary> /// Attempts to place a new outgoing call. /// </summary> /// <param name="sipCallDescriptor">A call descriptor containing the information about how /// and where to place the call.</param> /// <param name="mediaSession">The media session used for this call</param> public async Task InitiateCallAsync(SIPCallDescriptor sipCallDescriptor, IMediaSession mediaSession) { m_cts = new CancellationTokenSource(); m_uac = new SIPClientUserAgent(m_transport); m_uac.CallTrying += ClientCallTryingHandler; m_uac.CallRinging += ClientCallRingingHandler; m_uac.CallAnswered += ClientCallAnsweredHandler; m_uac.CallFailed += ClientCallFailedHandler; // Can be DNS lookups involved in getting the call destination. SIPEndPoint serverEndPoint = await Task.Run <SIPEndPoint>(() => { return(m_uac.GetCallDestination(sipCallDescriptor)); }).ConfigureAwait(false); if (serverEndPoint != null) { MediaSession = mediaSession; MediaSession.OnRtpEvent += OnRemoteRtpEvent; //MediaSession.OnRtpClosed += (reason) => Hangup(); MediaSession.OnRtpClosed += (reason) => { if (!MediaSession.IsClosed) { logger.LogWarning($"RTP channel was closed with reason {reason}."); } }; RTCOfferOptions offerOptions = new RTCOfferOptions { RemoteSignallingAddress = serverEndPoint.Address }; var sdp = await mediaSession.createOffer(offerOptions).ConfigureAwait(false); mediaSession.setLocalDescription(new RTCSessionDescription { sdp = sdp, type = RTCSdpType.offer }); if (mediaSession.localDescription == null) { ClientCallFailed?.Invoke(m_uac, $"Could not create a local SDP offer."); CallEnded(); } else { sipCallDescriptor.Content = mediaSession.localDescription.sdp.ToString(); // This initiates the call but does not wait for an answer. m_uac.Call(sipCallDescriptor); } } else { ClientCallFailed?.Invoke(m_uac, $"Could not resolve destination when placing call to {sipCallDescriptor.Uri}."); CallEnded(); } }
/// <summary> /// Attempts to place a new outgoing call. /// </summary> /// <param name="sipCallDescriptor">A call descriptor containing the information about how /// and where to place the call.</param> /// <param name="mediaSession">The media session used for this call</param> public async Task InitiateCallAsync(SIPCallDescriptor sipCallDescriptor, IMediaSession mediaSession) { m_cts = new CancellationTokenSource(); m_uac = new SIPClientUserAgent(m_transport); m_uac.CallTrying += ClientCallTryingHandler; m_uac.CallRinging += ClientCallRingingHandler; m_uac.CallAnswered += ClientCallAnsweredHandler; m_uac.CallFailed += ClientCallFailedHandler; // Can be DNS lookups involved in getting the call destination. SIPEndPoint serverEndPoint = await Task.Run <SIPEndPoint>(() => { return(m_uac.GetCallDestination(sipCallDescriptor)); }).ConfigureAwait(false); if (serverEndPoint != null) { MediaSession = mediaSession; MediaSession.OnRtpEvent += OnRemoteRtpEvent; //MediaSession.OnRtpClosed += (reason) => Hangup(); MediaSession.OnRtpClosed += (reason) => { if (!MediaSession.IsClosed) { logger.LogWarning($"RTP channel was closed with reason {reason}."); } }; var sdpAnnounceAddress = NetServices.GetLocalAddressForRemote(serverEndPoint.Address); var sdp = mediaSession.CreateOffer(sdpAnnounceAddress); if (sdp == null) { ClientCallFailed?.Invoke(m_uac, $"Could not generate an offer.", null); CallEnded(); } else { sipCallDescriptor.Content = sdp.ToString(); // This initiates the call but does not wait for an answer. m_uac.Call(sipCallDescriptor); } } else { ClientCallFailed?.Invoke(m_uac, $"Could not resolve destination when placing call to {sipCallDescriptor.Uri}.", null); CallEnded(); } }
/// <summary> /// Event handler for a client call (one initiated by us) being answered. /// </summary> /// <param name="uac">The client user agent used to initiate the call.</param> /// <param name="sipResponse">The INVITE success response.</param> private async Task ClientCallAnsweredHandlerAsync(ISIPClientUserAgent uac, SIPResponse sipResponse) { if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode <= 299) { // Only set the remote RTP end point if there hasn't already been a packet received on it. await MediaSession.OfferAnswered(sipResponse.Body).ConfigureAwait(false); Dialogue.DialogueState = SIPDialogueStateEnum.Confirmed; logger.LogInformation($"Call attempt to {m_uac.CallDescriptor.Uri} was answered."); ClientCallAnswered?.Invoke(uac, sipResponse); } else { logger.LogDebug($"Call attempt was answered with failure response {sipResponse.ShortDescription}."); ClientCallFailed?.Invoke(uac, sipResponse.ReasonPhrase); CallEnded(); } }
/// <summary> /// Event handler for a client call (one initiated by us) failing. /// </summary> /// <param name="uac">The client user agent used to initiate the call.</param> /// <param name="errorMessage">An error message indicating the reason for the failure.</param> private void ClientCallFailedHandler(ISIPClientUserAgent uac, string errorMessage) { logger.LogWarning($"Call attempt to {m_uac.CallDescriptor.Uri} failed with {errorMessage}."); ClientCallFailed?.Invoke(uac, errorMessage); }