예제 #1
0
        /// <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();
            }
        }
예제 #2
0
        /// <summary>
        /// Attempts to place a new outgoing call.
        /// </summary>
        /// <param name="dst">The destination SIP URI to call.</param>
        /// <param name="username">Optional Username if authentication is required.</param>
        /// <param name="password">Optional. Password if authentication is required.</param>
        /// <param name="mediaSession">The RTP session for the call.</param>
        public async Task <bool> Call(string dst, string username, string password, IMediaSession mediaSession)
        {
            if (!SIPURI.TryParse(dst, out var dstUri))
            {
                throw new ApplicationException("The destination was not recognised as a valid SIP URI.");
            }

            SIPCallDescriptor callDescriptor = new SIPCallDescriptor(
                username ?? SIPConstants.SIP_DEFAULT_USERNAME,
                password,
                dstUri.ToString(),
                SIPConstants.SIP_DEFAULT_FROMURI,
                dstUri.CanonicalAddress,
                null, null, null,
                SIPCallDirection.Out,
                SDP.SDP_MIME_CONTENTTYPE,
                null,
                null);

            await InitiateCall(callDescriptor, mediaSession);

            TaskCompletionSource <bool> callResult = new TaskCompletionSource <bool>();

            ClientCallAnswered += (uac, resp) => Task.Run(() => callResult.SetResult(true));
            ClientCallFailed   += (uac, errorMessage) => Task.Run(() => callResult.SetResult(false));

            return(await callResult.Task);
        }
예제 #3
0
        /// <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();
            }
        }
예제 #4
0
파일: Bot.cs 프로젝트: salujamanish/teams
        /// <summary>
        /// Incoming call handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="CollectionEventArgs{TEntity}"/> instance containing the event data.</param>
        private void CallsOnIncoming(ICallCollection sender, CollectionEventArgs <ICall> args)
        {
            args.AddedResources.ForEach(call =>
            {
                IMediaSession mediaSession = Guid.TryParse(call.Id, out Guid callId)
                    ? this.CreateLocalMediaSession(callId)
                    : this.CreateLocalMediaSession();

                // Answer call and start video playback
                call?.AnswerAsync(mediaSession).ForgetAndLogExceptionAsync(
                    call.GraphLogger,
                    $"Answering call {call.Id} with scenario {call.ScenarioId}.");
            });
        }
예제 #5
0
        /// <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();
            }
        }
예제 #6
0
        /// <summary>
        /// Attempts to place a new outgoing call AND waits for the call to be answered or fail.
        /// Use <see cref="InitiateCallAsync(SIPCallDescriptor, IMediaSession)"/> to start a call without
        /// waiting for it to complete and monitor <see cref="ClientCallAnsweredHandler"/> and
        /// <see cref="ClientCallFailedHandler"/> to detect an answer or failure.
        /// </summary>
        /// <param name="callDescriptor">The full descriptor for the call destination. Allows customising
        /// of additional options above the standard username, password and destination URI.</param>
        /// <param name="mediaSession">The RTP session for the call.</param>
        public async Task <bool> Call(SIPCallDescriptor callDescriptor, IMediaSession mediaSession)
        {
            TaskCompletionSource <bool> callResult = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            await InitiateCallAsync(callDescriptor, mediaSession).ConfigureAwait(false);

            ClientCallAnswered += (uac, resp) =>
            {
                callResult.TrySetResult(true);
            };
            ClientCallFailed += (uac, errorMessage) =>
            {
                callResult.TrySetResult(false);
            };

            return(callResult.Task.Result);
        }
예제 #7
0
        /// <summary>
        /// Answers the call request contained in the user agent server parameter. Note the
        /// <see cref="AcceptCall(SIPRequest)"/> method should be used to create the user agent server.
        /// Any existing call will be hungup.
        /// </summary>
        /// <param name="uas">The user agent server holding the pending call to answer.</param>
        /// <param name="mediaSession">The media session used for this call</param>
        /// <param name="customHeaders">Custom SIP-Headers to use in Answer.</param>
        public async Task Answer(SIPServerUserAgent uas, IMediaSession mediaSession, string[] customHeaders)
        {
            // This call is now taking over any existing call.
            if (IsCallActive)
            {
                Hangup();
            }
            else if (uas.IsCancelled)
            {
                logger.LogDebug("The incoming call has been cancelled.");
                mediaSession?.Close("call cancelled");
            }
            else
            {
                m_cts = new CancellationTokenSource();
                var sipRequest = uas.ClientTransaction.TransactionRequest;

                MediaSession             = mediaSession;
                MediaSession.OnRtpEvent += OnRemoteRtpEvent;
                //MediaSession.OnRtpClosed += (reason) => Hangup();
                MediaSession.OnRtpClosed += (reason) =>
                {
                    if (!MediaSession.IsClosed)
                    {
                        logger.LogWarning($"RTP channel was closed with reason {reason}.");
                    }
                };

                SDP remoteSdp = SDP.ParseSDPDescription(sipRequest.Body);
                MediaSession.setRemoteDescription(new RTCSessionDescription {
                    sdp = remoteSdp, type = RTCSdpType.offer
                });;

                var sdpAnswer = await MediaSession.createAnswer(null).ConfigureAwait(false);

                MediaSession.setLocalDescription(new RTCSessionDescription {
                    sdp = sdpAnswer, type = RTCSdpType.answer
                });

                await MediaSession.Start().ConfigureAwait(false);

                m_uas = uas;
                m_uas.Answer(m_sdpContentType, sdpAnswer.ToString(), null, SIPDialogueTransferModesEnum.Default, customHeaders);
                Dialogue.DialogueState = SIPDialogueStateEnum.Confirmed;
            }
        }
예제 #8
0
        /// <summary>
        /// Incoming call handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="CollectionEventArgs{TEntity}"/> instance containing the event data.</param>
        private void CallsOnIncoming(ICallCollection sender, CollectionEventArgs <ICall> args)
        {
            args.AddedResources.ForEach(call =>
            {
                // Get the compliance recording parameters.

                // The context associated with the incoming call.
                IncomingContext incomingContext =
                    call.Resource.IncomingContext;

                // The RP participant.
                string observedParticipantId =
                    incomingContext.ObservedParticipantId;

                // If the observed participant is a delegate.
                IdentitySet onBehalfOfIdentity =
                    incomingContext.OnBehalfOf;

                // If a transfer occured, the transferor.
                IdentitySet transferorIdentity =
                    incomingContext.Transferor;

                string countryCode        = null;
                EndpointType?endpointType = null;

                // Note: this should always be true for CR calls.
                if (incomingContext.ObservedParticipantId == incomingContext.SourceParticipantId)
                {
                    // The dynamic location of the RP.
                    countryCode = call.Resource.Source.CountryCode;

                    // The type of endpoint being used.
                    endpointType = call.Resource.Source.EndpointType;
                }

                IMediaSession mediaSession = Guid.TryParse(call.Id, out Guid callId)
                    ? this.CreateLocalMediaSession(callId)
                    : this.CreateLocalMediaSession();

                // Answer call
                call?.AnswerAsync(mediaSession).ForgetAndLogExceptionAsync(
                    call.GraphLogger,
                    $"Answering call {call.Id} with scenario {call.ScenarioId}.");
            });
        }
예제 #9
0
        /// <summary>
        /// Answers the call request contained in the user agent server parameter. Note the
        /// <see cref="AcceptCall(SIPRequest)"/> method should be used to create the user agent server.
        /// Any existing call will be hungup.
        /// </summary>
        /// <param name="uas">The user agent server holding the pending call to answer.</param>
        /// <param name="mediaSession">The media session used for this call</param>
        public async Task Answer(SIPServerUserAgent uas, IMediaSession mediaSession)
        {
            // This call is now taking over any existing call.
            if (IsCallActive)
            {
                Hangup();
            }

            var sipRequest = uas.ClientTransaction.TransactionRequest;

            MediaSession = mediaSession;
            MediaSession.SessionMediaChanged += MediaSessionOnSessionMediaChanged;
            MediaSession.OnRtpClosed         += (reason) => Hangup();

            var sdpAnswer = await MediaSession.AnswerOffer(sipRequest.Body).ConfigureAwait(false);

            m_uas = uas;
            m_uas.Answer(m_sdpContentType, sdpAnswer, null, SIPDialogueTransferModesEnum.Default);
            Dialogue.DialogueState = SIPDialogueStateEnum.Confirmed;
        }
예제 #10
0
        /// <summary>
        /// Attempts to place a new outgoing call AND waits for the call to be answered or fail.
        /// Use <see cref="InitiateCallAsync(SIPCallDescriptor, IMediaSession)"/> to start a call without
        /// waiting for it to complete and monitor <see cref="ClientCallAnsweredHandler"/> and
        /// <see cref="ClientCallFailedHandler"/> to detect an answer or failure.
        /// </summary>
        /// <param name="dst">The destination SIP URI to call.</param>
        /// <param name="username">Optional Username if authentication is required.</param>
        /// <param name="password">Optional. Password if authentication is required.</param>
        /// <param name="mediaSession">The RTP session for the call.</param>
        public Task <bool> Call(string dst, string username, string password, IMediaSession mediaSession)
        {
            if (!SIPURI.TryParse(dst, out var dstUri))
            {
                throw new ApplicationException("The destination was not recognised as a valid SIP URI.");
            }

            SIPCallDescriptor callDescriptor = new SIPCallDescriptor(
                username ?? SIPConstants.SIP_DEFAULT_USERNAME,
                password,
                dstUri.ToString(),
                SIPConstants.SIP_DEFAULT_FROMURI,
                dstUri.CanonicalAddress,
                null, null, null,
                SIPCallDirection.Out,
                SDP.SDP_MIME_CONTENTTYPE,
                null,
                null);

            return(Call(callDescriptor, mediaSession));
        }
예제 #11
0
        /// <summary>
        /// Answers the call request contained in the user agent server parameter. Note the
        /// <see cref="AcceptCall(SIPRequest)"/> method should be used to create the user agent server.
        /// Any existing call will be hungup.
        /// </summary>
        /// <param name="uas">The user agent server holding the pending call to answer.</param>
        /// <param name="mediaSession">The media session used for this call</param>
        /// <param name="customHeaders">Custom SIP-Headers to use in Answer.</param>
        public async Task Answer(SIPServerUserAgent uas, IMediaSession mediaSession, string[] customHeaders)
        {
            // This call is now taking over any existing call.
            if (IsCallActive)
            {
                Hangup();
            }
            else if (uas.IsCancelled)
            {
                logger.LogDebug("The incoming call has been cancelled.");
                mediaSession?.Close("call cancelled");
            }
            else
            {
                m_cts = new CancellationTokenSource();
                var sipRequest = uas.ClientTransaction.TransactionRequest;

                MediaSession             = mediaSession;
                MediaSession.OnRtpEvent += OnRemoteRtpEvent;
                //MediaSession.OnRtpClosed += (reason) => Hangup();
                MediaSession.OnRtpClosed += (reason) =>
                {
                    if (!MediaSession.IsClosed)
                    {
                        logger.LogWarning($"RTP channel was closed with reason {reason}.");
                    }
                };

                string sdp = null;

                if (!String.IsNullOrEmpty(sipRequest.Body))
                {
                    // The SDP offer was included in the INVITE request.
                    SDP remoteSdp = SDP.ParseSDPDescription(sipRequest.Body);
                    MediaSession.setRemoteDescription(new RTCSessionDescription {
                        sdp = remoteSdp, type = RTCSdpType.offer
                    });

                    var sdpAnswer = await MediaSession.createAnswer(null).ConfigureAwait(false);

                    if (sdpAnswer == null)
                    {
                        logger.LogWarning($"Could not generate an SDP answer.");
                        m_uas.Reject(SIPResponseStatusCodesEnum.NotAcceptable, null);
                        return;
                    }
                    else
                    {
                        MediaSession.setLocalDescription(new RTCSessionDescription {
                            sdp = sdpAnswer, type = RTCSdpType.answer
                        });
                        sdp = sdpAnswer.ToString();
                    }
                }
                else
                {
                    // No SDP offer was included in the INVITE request need to wait for the ACK.
                    RTCOfferOptions offerOptions = new RTCOfferOptions {
                        RemoteSignallingAddress = sipRequest.RemoteSIPEndPoint.GetIPEndPoint().Address
                    };
                    var sdpOffer = await MediaSession.createOffer(offerOptions).ConfigureAwait(false);

                    if (sdpOffer == null)
                    {
                        // This shouldn't occur unless we're unable to create an audio/video track.
                        logger.LogWarning($"Could not generate an SDP answer.");
                        m_uas.Reject(SIPResponseStatusCodesEnum.NotAcceptable, null);
                        return;
                    }
                    else
                    {
                        MediaSession.setLocalDescription(new RTCSessionDescription {
                            sdp = sdpOffer, type = RTCSdpType.offer
                        });
                        sdp = sdpOffer.ToString();
                    }
                }

                m_uas = uas;

                // In cases where the initial INVITE did not contain an SDP offer the action sequence is:
                // - INVITE with no SDP offer received,
                // - Reply with OK and an SDP offer,
                // - Wait for ACK with SDP answer.
                TaskCompletionSource <SIPDialogue> dialogueCreatedTcs = new TaskCompletionSource <SIPDialogue>(TaskCreationOptions.RunContinuationsAsynchronously);
                m_uas.OnDialogueCreated += (dialogue) => dialogueCreatedTcs.TrySetResult(dialogue);

                m_uas.Answer(m_sdpContentType, sdp, null, SIPDialogueTransferModesEnum.Default, customHeaders);

                await Task.WhenAny(dialogueCreatedTcs.Task, Task.Delay(WAIT_DIALOG_TIMEOUT)).ConfigureAwait(false);

                if (Dialogue != null)
                {
                    if (MediaSession.remoteDescription == null || MediaSession.remoteDescription.sdp == null)
                    {
                        // If the initial INVITE did not contain an offer then the remote description will not yet be set.
                        var remoteSDP = SDP.ParseSDPDescription(Dialogue.RemoteSDP);
                        MediaSession.setRemoteDescription(new RTCSessionDescription {
                            sdp = remoteSDP, type = RTCSdpType.answer
                        });
                    }

                    Dialogue.DialogueState = SIPDialogueStateEnum.Confirmed;

                    await MediaSession.Start().ConfigureAwait(false);
                }
                else
                {
                    logger.LogWarning("The attempt to answer a call failed as the dialog was not created. The likely cause is the ACK not being received in time.");

                    MediaSession.Close("dialog creation failed");
                    Hangup();
                }
            }
        }
예제 #12
0
 /// <summary>
 /// Answers the call request contained in the user agent server parameter. Note the
 /// <see cref="AcceptCall(SIPRequest)"/> method should be used to create the user agent server.
 /// Any existing call will be hungup.
 /// </summary>
 /// <param name="uas">The user agent server holding the pending call to answer.</param>
 /// <param name="mediaSession">The media session used for this call</param>
 public async Task Answer(SIPServerUserAgent uas, IMediaSession mediaSession)
 {
     await Answer(uas, mediaSession, null).ConfigureAwait(false);
 }
예제 #13
0
        /// <summary>
        /// Answers the call request contained in the user agent server parameter. Note the
        /// <see cref="AcceptCall(SIPRequest)"/> method should be used to create the user agent server.
        /// Any existing call will be hungup.
        /// </summary>
        /// <param name="uas">The user agent server holding the pending call to answer.</param>
        /// <param name="mediaSession">The media session used for this call</param>
        /// <param name="customHeaders">Custom SIP-Headers to use in Answer.</param>
        /// <returns>True if the call was successfully answered or false if there was a problem
        /// such as incompatible codecs.</returns>
        public async Task <bool> Answer(SIPServerUserAgent uas, IMediaSession mediaSession, string[] customHeaders)
        {
            // This call is now taking over any existing call.
            if (IsCallActive)
            {
                Hangup();
            }

            if (uas.IsCancelled)
            {
                logger.LogDebug("The incoming call has been cancelled.");
                mediaSession?.Close("call cancelled");
                return(false);
            }
            else
            {
                m_cts = new CancellationTokenSource();
                var sipRequest = uas.ClientTransaction.TransactionRequest;

                MediaSession              = mediaSession;
                MediaSession.OnRtpEvent  += OnRemoteRtpEvent;
                MediaSession.OnRtpClosed += (reason) =>
                {
                    if (!MediaSession.IsClosed)
                    {
                        logger.LogWarning($"RTP channel was closed with reason {reason}.");
                    }
                };

                string sdp = null;

                if (!String.IsNullOrEmpty(sipRequest.Body))
                {
                    // The SDP offer was included in the INVITE request.
                    SDP remoteSdp       = SDP.ParseSDPDescription(sipRequest.Body);
                    var setRemoteResult = MediaSession.SetRemoteDescription(remoteSdp);

                    if (setRemoteResult != SetDescriptionResultEnum.OK)
                    {
                        logger.LogWarning($"Error setting remote description from INVITE {setRemoteResult}.");
                        uas.Reject(SIPResponseStatusCodesEnum.NotAcceptable, setRemoteResult.ToString());
                        MediaSession.Close("sdp offer not acceptable");
                        Hangup();

                        return(false);
                    }
                    else
                    {
                        var sdpAnswer = MediaSession.CreateAnswer(null);
                        sdp = sdpAnswer.ToString();
                    }
                }
                else
                {
                    // No SDP offer was included in the INVITE request need to wait for the ACK.
                    var sdpAnnounceAddress = NetServices.GetLocalAddressForRemote(sipRequest.RemoteSIPEndPoint.GetIPEndPoint().Address);
                    var sdpOffer           = MediaSession.CreateOffer(sdpAnnounceAddress);
                    sdp = sdpOffer.ToString();
                }

                m_uas = uas;

                // In cases where the initial INVITE did not contain an SDP offer the action sequence is:
                // - INVITE with no SDP offer received,
                // - Reply with OK and an SDP offer,
                // - Wait for ACK with SDP answer.
                TaskCompletionSource <SIPDialogue> dialogueCreatedTcs = new TaskCompletionSource <SIPDialogue>(TaskCreationOptions.RunContinuationsAsynchronously);
                m_uas.OnDialogueCreated += (dialogue) => dialogueCreatedTcs.TrySetResult(dialogue);

                m_uas.Answer(m_sdpContentType, sdp, null, SIPDialogueTransferModesEnum.Default, customHeaders);

                await Task.WhenAny(dialogueCreatedTcs.Task, Task.Delay(WAIT_DIALOG_TIMEOUT)).ConfigureAwait(false);

                if (Dialogue != null)
                {
                    if (MediaSession.RemoteDescription == null)
                    {
                        // If the initial INVITE did not contain an offer then the remote description will not yet be set.
                        var remoteSDP       = SDP.ParseSDPDescription(Dialogue.RemoteSDP);
                        var setRemoteResult = MediaSession.SetRemoteDescription(remoteSDP);

                        if (setRemoteResult != SetDescriptionResultEnum.OK)
                        {
                            // Failed to set the remote SDP from the ACK request. Only option is to hangup.
                            logger.LogWarning($"Error setting remote description from ACK {setRemoteResult}.");
                            MediaSession.Close(setRemoteResult.ToString());
                            Hangup();

                            return(false);
                        }
                        else
                        {
                            // SDP from the ACK request was accepted. Start the RTP session.
                            Dialogue.DialogueState = SIPDialogueStateEnum.Confirmed;
                            await MediaSession.Start().ConfigureAwait(false);

                            return(true);
                        }
                    }
                    else
                    {
                        Dialogue.DialogueState = SIPDialogueStateEnum.Confirmed;
                        await MediaSession.Start().ConfigureAwait(false);

                        return(true);
                    }
                }
                else
                {
                    logger.LogWarning("The attempt to answer a call failed as the dialog was not created. The likely cause is the ACK not being received in time.");

                    MediaSession.Close("dialog creation failed");
                    Hangup();

                    return(false);
                }
            }
        }
예제 #14
0
 /// <summary>
 /// Answers the call request contained in the user agent server parameter. Note the
 /// <see cref="AcceptCall(SIPRequest)"/> method should be used to create the user agent server.
 /// Any existing call will be hungup.
 /// </summary>
 /// <param name="uas">The user agent server holding the pending call to answer.</param>
 /// <param name="mediaSession">The media session used for this call</param>
 public Task <bool> Answer(SIPServerUserAgent uas, IMediaSession mediaSession)
 {
     return(Answer(uas, mediaSession, null));
 }
예제 #15
0
 /// <summary>
 /// Answers the call request contained in the user agent server parameter. Note the
 /// <see cref="AcceptCall(SIPRequest)"/> method should be used to create the user agent server.
 /// Any existing call will be hungup.
 /// </summary>
 /// <param name="uas">The user agent server holding the pending call to answer.</param>
 /// <param name="mediaSession">The media session used for this call</param>
 public async Task Answer(SIPServerUserAgent uas, IMediaSession mediaSession)
 {
     await Answer(uas, mediaSession, null);
 }