コード例 #1
0
        private SIPResponse GetCancelResponse(SIPRequest sipRequest, SIPResponseStatusCodesEnum sipResponseCode)
        {
            try
            {
                SIPResponse cancelResponse = new SIPResponse(sipResponseCode, null, sipRequest.LocalSIPEndPoint);

                SIPHeader requestHeader = sipRequest.Header;
                cancelResponse.Header = new SIPHeader(requestHeader.From, requestHeader.To, requestHeader.CSeq, requestHeader.CallId);
                cancelResponse.Header.CSeqMethod = SIPMethodsEnum.CANCEL;
                cancelResponse.Header.Vias = requestHeader.Vias;
                cancelResponse.Header.MaxForwards = Int32.MinValue;

                return cancelResponse;
            }
            catch (Exception excp)
            {
                logger.Error("Exception GetCancelResponse. " + excp.Message);
                throw excp;
            }
        }
コード例 #2
0
ファイル: SIPCallDispatcher.cs プロジェクト: xycui/sipsorcery
        public void Respond(SIPRequest sipRequest, SIPResponseStatusCodesEnum statusCode, string reason)
        {
            SIPResponse errorResponse = SIPTransport.GetResponse(sipRequest, statusCode, reason);

            m_sipTransport.SendResponse(m_outboundProxy, errorResponse);
        }
コード例 #3
0
        public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders)
        {
            try
            {
                if (m_uasTransaction.TransactionFinalResponse == null)
                {
                    if ((int)failureStatus < 400)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS Reject was passed an invalid response status of " + (int)failureStatus + ", ignoring.", m_owner));
                    }
                    else
                    {
                        if (UASStateChanged != null)
                        {
                            UASStateChanged(this, failureStatus, reasonPhrase);
                        }

                        string failureReason = (!reasonPhrase.IsNullOrBlank()) ? " and " + reasonPhrase : null;

                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call failed with a response status of " + (int)failureStatus + failureReason + ".", m_owner));
                        SIPResponse failureResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, failureStatus, reasonPhrase);

                        if (customHeaders != null && customHeaders.Length > 0)
                        {
                            foreach (string header in customHeaders)
                            {
                                failureResponse.Header.UnknownHeaders.Add(header);
                            }
                        }

                        m_uasTransaction.SendFinalResponse(failureResponse);
                    }
                }
                else
                {
                    logger.Warn("SIPServerUserAgent Reject fired on already answered call.");
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPServerUserAgent Reject. " + excp.Message);
            }
        }
コード例 #4
0
ファイル: SIPTransport.cs プロジェクト: sipsorcery/sipsorcery
        /// <summary>
        /// Used to create a SIP response when it was not possible to parse the incoming SIP request.
        /// </summary>
        public SIPResponse GetResponse(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponseStatusCodesEnum responseCode, string reasonPhrase)
        {
            try
            {
                if (localSIPEndPoint == null)
                {
                    localSIPEndPoint = GetDefaultSIPEndPoint();
                }

                SIPResponse response = new SIPResponse(responseCode, reasonPhrase, localSIPEndPoint);
                SIPSchemesEnum sipScheme = (localSIPEndPoint.Protocol == SIPProtocolsEnum.tls) ? SIPSchemesEnum.sips : SIPSchemesEnum.sip;
                SIPFromHeader from = new SIPFromHeader(null, new SIPURI(sipScheme, localSIPEndPoint), null);
                SIPToHeader to = new SIPToHeader(null, new SIPURI(sipScheme, localSIPEndPoint), null);
                int cSeq = 1;
                string callId = CallProperties.CreateNewCallId();
                response.Header = new SIPHeader(from, to, cSeq, callId);
                response.Header.CSeqMethod = SIPMethodsEnum.NONE;
                response.Header.Vias.PushViaHeader(new SIPViaHeader(new SIPEndPoint(localSIPEndPoint.Protocol, remoteEndPoint.GetIPEndPoint()), CallProperties.CreateBranchId()));
                response.Header.MaxForwards = Int32.MinValue;
                response.Header.Allow = ALLOWED_SIP_METHODS;

                return response;
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTransport GetResponse. " + excp.Message);
                throw;
            }
        }
コード例 #5
0
        /// <summary>
        /// Handler for processing incoming SIP requests.
        /// </summary>
        /// <param name="localSIPEndPoint">The end point the request was received on.</param>
        /// <param name="remoteEndPoint">The end point the request came from.</param>
        /// <param name="sipRequest">The SIP request received.</param>
        private static async Task SIPTransportRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest)
        {
            try
            {
                if (sipRequest.Method == SIPMethodsEnum.BYE)
                {
                    throw new NotImplementedException();
                }
                else if (sipRequest.Method == SIPMethodsEnum.CANCEL)
                {
                    throw new NotImplementedException();
                }
                else if (sipRequest.Method == SIPMethodsEnum.INVITE)
                {
                    throw new NotImplementedException();
                }
                else if (sipRequest.Method == SIPMethodsEnum.OPTIONS)
                {
                    SIPResponse optionsResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                    await _sipTransport.SendResponseAsync(optionsResponse);
                }
                else if (sipRequest.Method == SIPMethodsEnum.REGISTER)
                {
                    SIPResponse tryingResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Trying, null);
                    await _sipTransport.SendResponseAsync(tryingResponse);

                    SIPResponseStatusCodesEnum registerResponse = SIPResponseStatusCodesEnum.Ok;

                    if (sipRequest.Header.Contact != null && sipRequest.Header.Contact.Count > 0)
                    {
                        int expiry                = sipRequest.Header.Contact[0].Expires > 0 ? sipRequest.Header.Contact[0].Expires : sipRequest.Header.Expires;
                        var sipAccount            = new SIPAccount(null, sipRequest.Header.From.FromURI.Host, sipRequest.Header.From.FromURI.User, null, null);
                        SIPAccountBinding binding = new SIPAccountBinding(sipAccount, sipRequest.Header.Contact[0].ContactURI, remoteEndPoint, localSIPEndPoint, expiry);

                        if (_sipRegistrations.ContainsKey(sipAccount.SIPUsername))
                        {
                            _sipRegistrations.Remove(sipAccount.SIPUsername);
                        }

                        _sipRegistrations.Add(sipAccount.SIPUsername, binding);

                        logger.LogDebug("Registered contact for " + sipAccount.SIPUsername + " as " + binding.RegisteredContact.ToString() + ".");
                    }
                    else
                    {
                        registerResponse = SIPResponseStatusCodesEnum.BadRequest;
                    }

                    SIPNonInviteTransaction registerTransaction = new SIPNonInviteTransaction(_sipTransport, sipRequest, null);
                    SIPResponse             okResponse          = SIPResponse.GetResponse(sipRequest, registerResponse, null);
                    registerTransaction.SendResponse(okResponse);
                }
                else
                {
                    logger.LogDebug("SIP " + sipRequest.Method + " request received but no processing has been set up for it, rejecting.");
                }
            }
            catch (NotImplementedException)
            {
                logger.LogDebug(sipRequest.Method + " request processing not implemented for " + sipRequest.URI.ToParameterlessString() + " from " + remoteEndPoint + ".");

                SIPResponse notImplResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotImplemented, null);
                await _sipTransport.SendResponseAsync(notImplResponse);
            }
        }
コード例 #6
0
 public void AnswerNonInvite(SIPResponseStatusCodesEnum answerStatus, string reasonPhrase, string[] customHeaders, string contentType, string body)
 {
     throw new NotImplementedException();
 }
コード例 #7
0
 public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody)
 {
     throw new NotImplementedException();
 }
コード例 #8
0
 public SIPValidationException(SIPValidationFieldsEnum sipErrorField, SIPResponseStatusCodesEnum responseErrorCode, string message)
     : base(message)
 {
     SIPErrorField        = sipErrorField;
     SIPResponseErrorCode = responseErrorCode;
 }
コード例 #9
0
        public void Answered(int answerStatusCode, SIPResponseStatusCodesEnum answerStatus, string answerReason)
        {
            try
            {
                IsAnswered = true;
                AnswerTime = DateTimeOffset.UtcNow;
                AnswerStatus = (int)answerStatus;
                AnswerReasonPhrase = answerReason;

                CDRAnswered(this);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPCDR Answered. " + excp.Message);
            }
        }
コード例 #10
0
 public void Progress(SIPResponseStatusCodesEnum progressStatus, string progressReason)
 {
     InProgress = true;
     ProgressTime = DateTimeOffset.UtcNow;
     ProgressStatus = (int)progressStatus;
     ProgressReasonPhrase = progressReason;
 }
コード例 #11
0
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     NoRingTimeout.Invoke(this);
     logger.Debug("SIPB2BUserAgent Redirect.");
     //m_uas.Redirect(redirectCode, redirectURI);
 }
コード例 #12
0
        private void CallProgress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody, ISIPClientUserAgent uac)
        {
            try
            {
                Log("Progress response of " + progressStatus + " received on CallBack Dial" + ".");

                if (m_firstLegDialogue != null && !progressBody.IsNullOrBlank() && !m_firstLegEarlyMediaSet)
                {
                    m_firstLegEarlyMediaSet = true;
                    // The first leg is up and a call on the second leg has some early media that can be passed on.
                    //m_callManager.ReInvite(m_firstLegDialogue, progressBody);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception CallbackApp. " + excp.Message);
            }
        }
コード例 #13
0
 public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders)
 {
     Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, m_transaction.TransactionRequest.Method + " request failed with a response status of " + (int)failureStatus + " " + reasonPhrase + ".", m_owner));
     SIPResponse failureResponse = SIPTransport.GetResponse(m_transaction.TransactionRequest, failureStatus, reasonPhrase);
     m_transaction.SendFinalResponse(failureResponse);
 }
コード例 #14
0
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     throw new NotImplementedException();
 }
コード例 #15
0
 public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody)
 {
     throw new NotImplementedException();
 }
コード例 #16
0
ファイル: SIPNotifierCore.cs プロジェクト: xycui/sipsorcery
        private void Subscribe(SIPTransaction subscribeTransaction)
        {
            try
            {
                SIPRequest sipRequest      = subscribeTransaction.TransactionRequest;
                string     fromUser        = sipRequest.Header.From.FromURI.User;
                string     fromHost        = sipRequest.Header.From.FromURI.Host;
                string     canonicalDomain = GetCanonicalDomain_External(fromHost, true);

                if (canonicalDomain == null)
                {
                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Warn, "Subscribe request for " + fromHost + " rejected as no matching domain found.", null));
                    SIPResponse noDomainResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced");
                    subscribeTransaction.SendFinalResponse(noDomainResponse);
                    return;
                }

                SIPAccount sipAccount = m_sipAssetPersistor.Get(s => s.SIPUsername == fromUser && s.SIPDomain == canonicalDomain);
                SIPRequestAuthenticationResult authenticationResult = SIPRequestAuthenticator_External(subscribeTransaction.LocalSIPEndPoint, subscribeTransaction.RemoteEndPoint, sipRequest, sipAccount, FireProxyLogEvent);

                if (!authenticationResult.Authenticated)
                {
                    // 401 Response with a fresh nonce needs to be sent.
                    SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null);
                    authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                    subscribeTransaction.SendFinalResponse(authReqdResponse);

                    if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Warn, "Forbidden " + fromUser + "@" + canonicalDomain + " does not exist, " + sipRequest.Header.ProxyReceivedFrom.ToString() + ", " + sipRequest.Header.UserAgent + ".", null));
                    }
                    else
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Authentication required for " + fromUser + "@" + canonicalDomain + " from " + subscribeTransaction.RemoteEndPoint + ".", sipAccount.Owner));
                    }
                    return;
                }
                else
                {
                    if (sipRequest.Header.To.ToTag != null)
                    {
                        // Request is to renew an existing subscription.
                        SIPResponseStatusCodesEnum errorResponse = SIPResponseStatusCodesEnum.None;
                        string errorResponseReason = null;

                        string sessionID = m_subscriptionsManager.RenewSubscription(sipRequest, out errorResponse, out errorResponseReason);
                        if (errorResponse != SIPResponseStatusCodesEnum.None)
                        {
                            // A subscription renewal attempt failed
                            SIPResponse renewalErrorResponse = SIPTransport.GetResponse(sipRequest, errorResponse, errorResponseReason);
                            subscribeTransaction.SendFinalResponse(renewalErrorResponse);
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription renewal failed for event type " + sipRequest.Header.Event + " " + sipRequest.URI.ToString() + ", " + errorResponse + " " + errorResponseReason + ".", sipAccount.Owner));
                        }
                        else if (sipRequest.Header.Expires == 0)
                        {
                            // Existing subscription was closed.
                            SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                            subscribeTransaction.SendFinalResponse(okResponse);
                        }
                        else
                        {
                            // Existing subscription was found.
                            SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                            subscribeTransaction.SendFinalResponse(okResponse);
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeRenew, "Subscription renewal for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + " and expiry " + sipRequest.Header.Expires + ".", sipAccount.Owner));
                            m_subscriptionsManager.SendFullStateNotify(sessionID);
                        }
                    }
                    else
                    {
                        // Authenticated but the this is a new subscription request and authorisation to subscribe to the requested resource also needs to be checked.
                        SIPURI canonicalResourceURI    = sipRequest.URI.CopyOf();
                        string resourceCanonicalDomain = GetCanonicalDomain_External(canonicalResourceURI.Host, true);
                        canonicalResourceURI.Host = resourceCanonicalDomain;
                        SIPAccount resourceSIPAccount = null;

                        if (resourceCanonicalDomain == null)
                        {
                            SIPResponse notFoundResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotFound, "Domain " + resourceCanonicalDomain + " not serviced");
                            subscribeTransaction.SendFinalResponse(notFoundResponse);
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", domain not serviced.", sipAccount.Owner));
                            return;
                        }

                        if (canonicalResourceURI.User != m_wildcardUser)
                        {
                            resourceSIPAccount = m_sipAssetPersistor.Get(s => s.SIPUsername == canonicalResourceURI.User && s.SIPDomain == canonicalResourceURI.Host);

                            if (resourceSIPAccount == null)
                            {
                                SIPResponse notFoundResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotFound, "Requested resource does not exist");
                                subscribeTransaction.SendFinalResponse(notFoundResponse);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", SIP account does not exist.", sipAccount.Owner));
                                return;
                            }
                        }

                        // Check the owner permissions on the requesting and subscribed resources.
                        bool   authorised = false;
                        string adminID    = null;

                        if (canonicalResourceURI.User == m_wildcardUser || sipAccount.Owner == resourceSIPAccount.Owner)
                        {
                            authorised = true;
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to common owner.", sipAccount.Owner));
                        }
                        else
                        {
                            // Lookup the customer record for the requestor and check the administrative level on it.
                            Customer requestingCustomer = GetCustomer_External(c => c.CustomerUsername == sipAccount.Owner);
                            adminID = requestingCustomer.AdminId;
                            if (!resourceSIPAccount.AdminMemberId.IsNullOrBlank() && requestingCustomer.AdminId == resourceSIPAccount.AdminMemberId)
                            {
                                authorised = true;
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to requestor admin permissions for domain " + resourceSIPAccount.AdminMemberId + ".", sipAccount.Owner));
                            }
                            else if (requestingCustomer.AdminId == m_topLevelAdminID)
                            {
                                authorised = true;
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to requestor having top level admin permissions.", sipAccount.Owner));
                            }
                        }

                        if (authorised)
                        {
                            // Request is to create a new subscription.
                            SIPResponseStatusCodesEnum errorResponse = SIPResponseStatusCodesEnum.None;
                            string errorResponseReason = null;
                            string toTag     = CallProperties.CreateNewTag();
                            string sessionID = m_subscriptionsManager.SubscribeClient(sipAccount.Owner, adminID, sipRequest, toTag, canonicalResourceURI, out errorResponse, out errorResponseReason);

                            if (errorResponse != SIPResponseStatusCodesEnum.None)
                            {
                                SIPResponse subscribeErrorResponse = SIPTransport.GetResponse(sipRequest, errorResponse, errorResponseReason);
                                subscribeTransaction.SendFinalResponse(subscribeErrorResponse);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", " + errorResponse + " " + errorResponseReason + ".", sipAccount.Owner));
                            }
                            else
                            {
                                SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                                okResponse.Header.To.ToTag = toTag;
                                okResponse.Header.Expires  = sipRequest.Header.Expires;
                                okResponse.Header.Contact  = new List <SIPContactHeader>()
                                {
                                    new SIPContactHeader(null, new SIPURI(SIPSchemesEnum.sip, subscribeTransaction.LocalSIPEndPoint))
                                };
                                subscribeTransaction.SendFinalResponse(okResponse);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "Subscription accepted for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + " and expiry " + sipRequest.Header.Expires + ".", sipAccount.Owner));

                                if (sessionID != null)
                                {
                                    m_subscriptionsManager.SendFullStateNotify(sessionID);
                                }
                            }
                        }
                        else
                        {
                            SIPResponse forbiddenResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Requested resource not authorised");
                            subscribeTransaction.SendFinalResponse(forbiddenResponse);
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", requesting account " + sipAccount.Owner + " was not authorised.", sipAccount.Owner));
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception notifiercore subscribing. " + excp.Message + "\r\n" + subscribeTransaction.TransactionRequest.ToString());
                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Error, "Exception notifiercore subscribing. " + excp.Message, null));
                SIPResponse errorResponse = SIPTransport.GetResponse(subscribeTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                subscribeTransaction.SendFinalResponse(errorResponse);
            }
        }
コード例 #17
0
        private void CallProgress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody, ISIPClientUserAgent uac)
        {
            SIPResponse progressResponse = new SIPResponse(progressStatus, reasonPhrase, null);

            CallRinging(this, progressResponse);
        }
コード例 #18
0
        private void SendNotifyRequestForRefer(SIPRequest referRequest, SIPDialogue referDialogue, SIPEndPoint localEndPoint, SIPResponseStatusCodesEnum responseCode, string responseReason)
        {
            try
            {
                //logger.Debug("Sending NOTIFY for refer subscription to " + referDialogue.RemoteTarget.ToParameterlessString() + ", status " + responseCode + " " + responseReason + ".");

                referDialogue.CSeq++;
                m_sipDialoguePersistor.UpdateProperty(referDialogue.Id, "CSeq", referDialogue.CSeq);

                SIPRequest notifyTryingRequest = GetNotifyRequest(referRequest, referDialogue, new SIPResponse(responseCode, responseReason, null), localEndPoint);
                SIPEndPoint forwardEndPoint = null;
                SIPDNSLookupResult lookupResult = m_sipTransport.GetRequestEndPoint(notifyTryingRequest, m_outboundProxy, false);
                if (lookupResult.LookupError != null)
                {
                    logger.Warn("SendNotifyRequestForRefer Failed to resolve " + lookupResult.URI.Host + ".");
                }
                else
                {
                    forwardEndPoint = lookupResult.GetSIPEndPoint();
                }

                SIPNonInviteTransaction notifyTryingTransaction = m_sipTransport.CreateNonInviteTransaction(notifyTryingRequest, forwardEndPoint, localEndPoint, m_outboundProxy);
                notifyTryingTransaction.SendReliableRequest();
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendNotifyRequestForRefer. " + excp.Message);
            }
        }
コード例 #19
0
        public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders)
        {
            logger.Warn("SIPTransferServerUserAgent Reject called with " + failureStatus + " " + reasonPhrase + ".");

            UASStateChanged?.Invoke(this, failureStatus, reasonPhrase);
        }
コード例 #20
0
 public SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum errorResponse, SIPAuthenticationHeader authenticationRequiredHeader)
 {
     Authenticated = false;
     ErrorResponse = errorResponse;
     AuthenticationRequiredHeader = authenticationRequiredHeader;
 }
コード例 #21
0
        private RegisterResultEnum Register(SIPTransaction registerTransaction)
        {
            try
            {
                SIPRequest  sipRequest      = registerTransaction.TransactionRequest;
                SIPURI      registerURI     = sipRequest.URI;
                SIPToHeader toHeader        = sipRequest.Header.To;
                string      toUser          = toHeader.ToURI.User;
                string      canonicalDomain = toHeader.ToURI.Host;
                int         requestedExpiry = GetRequestedExpiry(sipRequest);

                if (canonicalDomain == null)
                {
                    SIPResponse noDomainResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden,
                                                                    "Domain not serviced");
                    registerTransaction.SendFinalResponse(noDomainResponse);
                    return(RegisterResultEnum.DomainNotServiced);
                }

                SIPAccount sipAccount = new SIPAccount
                {
                    Id          = Guid.NewGuid(),
                    Owner       = "admin",
                    SIPUsername = toUser,
                    SIPDomain   = canonicalDomain
                };
                SIPRequestAuthenticationResult authenticationResult =
                    _sipRequestAuthenticator_External?.Invoke(registerTransaction.LocalSIPEndPoint,
                                                              registerTransaction.RemoteEndPoint, sipRequest, sipAccount);

                if (!_needAuthentication)
                {
                    SIPResponse okRes = GetOkResponse(sipRequest);

                    registerTransaction.SendFinalResponse(okRes);


                    if (requestedExpiry > 0)
                    {
                        CacheDeviceItem(sipRequest);

                        RegisterReceived?.Invoke(sipRequest, _localSipAccount);
                    }

                    if (requestedExpiry == 0)
                    {
                        RemoveDeviceItem(sipRequest);
                        UnRegisterReceived?.Invoke(sipRequest, _localSipAccount);
                    }


                    return(RegisterResultEnum.AuthenticationRequired);
                }

                if (!authenticationResult.Authenticated)
                {
                    // 401 Response with a fresh nonce needs to be sent.
                    SIPResponse authReqdResponse =
                        SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null);
                    authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                    registerTransaction.SendFinalResponse(authReqdResponse);

                    if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                    {
                        return(RegisterResultEnum.Forbidden);
                    }
                    else
                    {
                        return(RegisterResultEnum.AuthenticationRequired);
                    }
                }
                else
                {
                    if (sipRequest.Header.Contact == null || sipRequest.Header.Contact.Count == 0)
                    {
                        SIPResponse okResponse = GetOkResponse(sipRequest);

                        registerTransaction.SendFinalResponse(okResponse);


                        if (requestedExpiry > 0)
                        {
                            CacheDeviceItem(sipRequest);
                            RegisterReceived?.Invoke(sipRequest, _localSipAccount);
                        }

                        if (requestedExpiry == 0)
                        {
                            RemoveDeviceItem(sipRequest);
                            UnRegisterReceived?.Invoke(sipRequest, _localSipAccount);
                        }
                    }
                    else
                    {
                        SIPEndPoint uacRemoteEndPoint = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedFrom) ??
                                                        registerTransaction.RemoteEndPoint;
                        SIPEndPoint proxySIPEndPoint            = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedOn);
                        SIPEndPoint registrarEndPoint           = registerTransaction.LocalSIPEndPoint;
                        SIPResponseStatusCodesEnum updateResult = SIPResponseStatusCodesEnum.Ok;
                        DateTime startTime = DateTime.Now;
                        TimeSpan duration  = DateTime.Now.Subtract(startTime);

                        if (updateResult == SIPResponseStatusCodesEnum.Ok)
                        {
                            string proxySocketStr = (proxySIPEndPoint != null)
                                ? " (proxy=" + proxySIPEndPoint.ToString() + ")"
                                : null;
                            SIPResponse okResponse = GetOkResponse(sipRequest);
                            registerTransaction.SendFinalResponse(okResponse);
                            if (requestedExpiry > 0)
                            {
                                CacheDeviceItem(sipRequest);
                                RegisterReceived?.Invoke(sipRequest, _localSipAccount);
                            }

                            if (requestedExpiry == 0)
                            {
                                RemoveDeviceItem(sipRequest);
                                UnRegisterReceived?.Invoke(sipRequest, _localSipAccount);
                            }
                        }
                        else
                        {
                            sipRequest.Header.Contact[0].Expires = m_minimumBindingExpiry;
                            SIPResponse okResponse = GetOkResponse(sipRequest);
                            registerTransaction.SendFinalResponse(okResponse);
                        }
                    }

                    return(RegisterResultEnum.Authenticated);
                }
            }
            catch (Exception excp)
            {
                string regErrorMessage = "Exception registrarcore registering. " + excp.Message + "\r\n" +
                                         registerTransaction.TransactionRequest.ToString();
                logger.Error(regErrorMessage);

                try
                {
                    SIPResponse errorResponse = GetErrorResponse(registerTransaction.TransactionRequest,
                                                                 SIPResponseStatusCodesEnum.InternalServerError, null);
                    registerTransaction.SendFinalResponse(errorResponse);
                }
                catch
                {
                }

                return(RegisterResultEnum.Error);
            }
        }
コード例 #22
0
        /// <summary>
        /// Helper method for dynamic proxy runtime script.
        /// </summary>
        /// <param name="responseCode"></param>
        /// <param name="localEndPoint"></param>
        /// <param name="remoteEndPoint"></param>
        /// <param name="sipRequest"></param>
        public void Respond(SIPRequest sipRequest, SIPResponseStatusCodesEnum responseCode, string reasonPhrase)
        {
            SIPResponse response = SIPTransport.GetResponse(sipRequest, responseCode, reasonPhrase);

            m_sipTransport.SendResponse(response);
        }
コード例 #23
0
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     Redirect(redirectCode, redirectURI, null);
 }
コード例 #24
0
        /// <summary>
        /// Updates the bindings list for a registrar's address-of-records.
        /// </summary>
        /// <param name="proxyEndPoint">If the request arrived at this registrar via a proxy then this will contain the end point of the proxy.</param>
        /// <param name="uacRecvdEndPoint">The public end point the UAC REGISTER request was deemded to have originated from.</param>
        /// <param name="registrarEndPoint">The registrar end point the registration request was received on.</param>
        /// <param name="maxAllowedExpiry">The maximum allowed expiry that can be granted to this binding request.</param>
        /// <returns>If the binding update was successful the expiry time for it is returned otherwise 0.</returns>
        public List <SIPRegistrarBinding> UpdateBindings(
            SIPAccount sipAccount,
            SIPEndPoint proxySIPEndPoint,
            SIPEndPoint remoteSIPEndPoint,
            SIPEndPoint registrarSIPEndPoint,
            List <SIPContactHeader> contactHeaders,
            string callId,
            int cseq,
            //int contactHeaderExpiresValue,
            int expiresHeaderValue,
            string userAgent,
            out SIPResponseStatusCodesEnum responseStatus,
            out string responseMessage)
        {
            //logger.Debug("UpdateBinding " + bindingURI.ToString() + ".");

            int maxAllowedExpiry = (m_userAgentConfigs != null) ? m_userAgentConfigs.GetMaxAllowedExpiry(userAgent) : SIPUserAgentConfiguration.DEFAULT_MAX_EXPIRY_SECONDS;

            responseMessage = null;
            string sipAccountAOR = sipAccount.SIPUsername + "@" + sipAccount.SIPDomain;

            responseStatus = SIPResponseStatusCodesEnum.Ok;

            try
            {
                userAgent = (userAgent != null && userAgent.Length > MAX_USERAGENT_LENGTH) ? userAgent.Substring(0, MAX_USERAGENT_LENGTH) : userAgent;

                List <SIPRegistrarBinding> bindings = m_bindingsPersistor.Get(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue);

                foreach (SIPContactHeader contactHeader in contactHeaders)
                {
                    SIPURI bindingURI = contactHeader.ContactURI.CopyOf();
                    int    contactHeaderExpiresValue = contactHeader.Expires;
                    int    bindingExpiry             = 0;

                    if (bindingURI.Host == m_sipRegisterRemoveAll)
                    {
                        if (contactHeaders.Count > 1)
                        {
                            // If a register request specifies remove all it cannot contain any other binding requests.
                            FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingRemoval, "Remove all bindings requested for " + sipAccountAOR + " but mutliple bindings specified, rejecting as a bad request.", sipAccount.SIPUsername));
                            responseStatus = SIPResponseStatusCodesEnum.BadRequest;
                            break;
                        }

                        #region Process remove all bindings.

                        if (expiresHeaderValue == 0)
                        {
                            // Removing all bindings for user.
                            FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingRemoval, "Remove all bindings requested for " + sipAccountAOR + ".", sipAccount.SIPUsername));

                            // Mark all the current bindings as expired.
                            if (bindings != null && bindings.Count > 0)
                            {
                                for (int index = 0; index < bindings.Count; index++)
                                {
                                    bindings[index].RemovalReason = SIPBindingRemovalReason.ClientExpiredAll;
                                    bindings[index].Expiry        = 0;
                                    m_bindingsPersistor.Update(bindings[index]);

                                    // Remove the NAT keep-alive job if present.
                                    if (m_natKeepAliveJobs.ContainsKey(bindings[index].RemoteSIPSocket))
                                    {
                                        m_natKeepAliveJobs[bindings[index].RemoteSIPSocket].CancelJob();
                                    }
                                }
                            }

                            FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));

                            responseStatus = SIPResponseStatusCodesEnum.Ok;
                        }
                        else
                        {
                            // Remove all header cannot be present with other headers and must have an Expiry equal to 0.
                            responseStatus = SIPResponseStatusCodesEnum.BadRequest;
                        }

                        #endregion
                    }
                    else
                    {
                        int requestedExpiry = (contactHeaderExpiresValue != -1) ? contactHeaderExpiresValue : expiresHeaderValue;
                        requestedExpiry = (requestedExpiry == -1) ? maxAllowedExpiry : requestedExpiry;   // This will happen if the Expires header and the Expiry on the Contact are both missing.
                        bindingExpiry   = (requestedExpiry > maxAllowedExpiry) ? maxAllowedExpiry : requestedExpiry;
                        bindingExpiry   = (bindingExpiry < MINIMUM_EXPIRY_SECONDS) ? MINIMUM_EXPIRY_SECONDS : bindingExpiry;

                        bindingURI.Parameters.Remove(m_sipExpiresParameterKey);

                        SIPRegistrarBinding binding = GetBindingForContactURI(bindings, bindingURI.ToString());

                        if (binding != null)
                        {
                            if (requestedExpiry <= 0)
                            {
                                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingExpired, "Binding expired by client for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ".", sipAccount.SIPUsername));
                                bindings.Remove(binding);
                                m_bindingsPersistor.Delete(binding);
                                bindingExpiry = 0;

                                FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));

                                // Remove the NAT keep-alive job if present.
                                if (m_natKeepAliveJobs.ContainsKey(binding.RemoteSIPSocket))
                                {
                                    m_natKeepAliveJobs[binding.RemoteSIPSocket].CancelJob();
                                }
                            }
                            else
                            {
                                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Registrar, "Binding update request for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ", expiry requested " + requestedExpiry + "s granted " + bindingExpiry + "s.", sipAccount.Owner));
                                binding.RefreshBinding(bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, sipAccount.DontMangleEnabled);

                                DateTime startTime = DateTime.Now;
                                m_bindingsPersistor.Update(binding);
                                TimeSpan duration = DateTime.Now.Subtract(startTime);
                                //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database update time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null));
                                FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));

                                // Add a NAT keep-alive job if required.
                                if (sipAccount.SendNATKeepAlives && proxySIPEndPoint != null)
                                {
                                    AddNATKeepAliveJob(sipAccount, remoteSIPEndPoint, proxySIPEndPoint, binding, bindingExpiry);
                                }
                            }
                        }
                        else
                        {
                            if (requestedExpiry > 0)
                            {
                                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "New binding request for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ", expiry requested " + requestedExpiry + "s granted " + bindingExpiry + "s.", sipAccount.Owner));

                                if (bindings.Count >= m_maxBindingsPerAccount)
                                {
                                    // Need to remove the oldest binding to stay within limit.
                                    //SIPRegistrarBinding oldestBinding = m_bindingsPersistor.Get(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue).OrderBy(x => x.LastUpdateUTC).Last();
                                    SIPRegistrarBinding oldestBinding = bindings.OrderBy(x => x.LastUpdate).Last();
                                    FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "Binding limit exceeded for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + " removing oldest binding to stay within limit of " + m_maxBindingsPerAccount + ".", sipAccount.Owner));
                                    m_bindingsPersistor.Delete(oldestBinding);

                                    if (m_natKeepAliveJobs.ContainsKey(binding.RemoteSIPSocket))
                                    {
                                        m_natKeepAliveJobs[binding.RemoteSIPSocket].CancelJob();
                                    }
                                }

                                SIPRegistrarBinding newBinding = new SIPRegistrarBinding(sipAccount, bindingURI, callId, cseq, userAgent, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, bindingExpiry);
                                DateTime            startTime  = DateTime.Now;
                                bindings.Add(newBinding);
                                m_bindingsPersistor.Add(newBinding);
                                TimeSpan duration = DateTime.Now.Subtract(startTime);
                                //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database add time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null));

                                // Add a NAT keep-alive job if required.
                                if (sipAccount.SendNATKeepAlives && proxySIPEndPoint != null)
                                {
                                    AddNATKeepAliveJob(sipAccount, remoteSIPEndPoint, proxySIPEndPoint, newBinding, bindingExpiry);
                                }

                                FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));
                            }
                            else
                            {
                                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingFailed, "New binding received for " + sipAccountAOR + " with expired contact," + bindingURI.ToString() + " no update.", sipAccount.Owner));
                                bindingExpiry = 0;
                            }
                        }

                        responseStatus = SIPResponseStatusCodesEnum.Ok;
                    }
                }

                return(bindings);
            }
            catch (Exception excp)
            {
                logger.Error("Exception UpdateBinding. " + excp.Message);
                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, "Registrar error updating binding: " + excp.Message + " Binding not updated.", sipAccount.SIPUsername));
                responseStatus = SIPResponseStatusCodesEnum.InternalServerError;
                return(null);
            }
        }
コード例 #25
0
ファイル: SIPCDR.cs プロジェクト: sipsorcery/sipsorcery
        public void Answered(int answerStatusCode, SIPResponseStatusCodesEnum answerStatus, string answerReason, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint)
        {
            try
            {
                IsAnswered = true;
                AnswerTime = DateTimeOffset.UtcNow;
                AnswerStatus = (int)answerStatus;
                AnswerReasonPhrase = answerReason;
                AnsweredAt = DateTime.Now;

                if (localEndPoint != null)
                {
                    LocalSIPEndPoint = localEndPoint;
                }

                if (remoteEndPoint != null)
                {
                    RemoteEndPoint = remoteEndPoint;
                }

                CDRAnswered(this);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPCDR Answered. " + excp);
            }
        }
コード例 #26
0
 public SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum errorResponse, SIPAuthenticationHeader authenticationRequiredHeader)
 {
     Authenticated = false;
     ErrorResponse = errorResponse;
     AuthenticationRequiredHeader = authenticationRequiredHeader;
 }
コード例 #27
0
        public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody)
        {
            try
            {
                if (!IsUASAnswered)
                {
                    if ((int)progressStatus >= 200)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call was passed an invalid response status of " + (int)progressStatus + ", ignoring.", m_owner));
                    }
                    else
                    {
                        if (UASStateChanged != null)
                        {
                            UASStateChanged(this, progressStatus, reasonPhrase);
                        }

                        // Allow all Trying responses through as some may contain additional useful information on the call state for the caller.
                        // Also if the response is a 183 Session Progress with audio forward it.
                        if (m_uasTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding && progressStatus != SIPResponseStatusCodesEnum.Trying &&
                            !(progressStatus == SIPResponseStatusCodesEnum.SessionProgress && progressBody != null))
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call ignoring progress response with status of " + (int)progressStatus + " as already in " + m_uasTransaction.TransactionState + ".", m_owner));
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call progressing with " + progressStatus + ".", m_owner));
                            SIPResponse progressResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, progressStatus, reasonPhrase);

                            if (progressResponse.Status != SIPResponseStatusCodesEnum.Trying)
                            {
                                progressResponse.Header.To.ToTag = m_uasTransaction.LocalTag;
                            }

                            if (!m_gruu.IsNullOrBlank())
                            {
                                // wenn wir das wieder löschen muss die gruu im contact header manuell rein!
                                progressResponse.Header.To.ToURI.Parameters.Set(SIPCallDescriptor.GRUU_KEY, m_gruu);
                            }

                            if (!progressBody.IsNullOrBlank())
                            {
                                progressResponse.Body = progressBody;
                                progressResponse.Header.ContentType = progressContentType;
                                progressResponse.Header.ContentLength = progressBody.Length;
                            }

                            //added contact header for RFC 4235 compliance
                            progressResponse.Header.Contact = SIPContactHeader.ParseContactHeader("<" + m_uasTransaction.TransactionRequest.Header.To.ToURI.ToString() + ">");

                            if (customHeaders != null && customHeaders.Length > 0)
                            {
                                foreach (string header in customHeaders)
                                {
                                    progressResponse.Header.UnknownHeaders.Add(header);
                                }
                            }

                            m_uasTransaction.SendInformationalResponse(progressResponse);
                        }
                    }
                }
                else
                {
                    logger.Warn("SIPServerUserAgent Progress fired on already answered call.");
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPServerUserAgent Progress. " + excp.Message);
            }
        }
コード例 #28
0
        public void CallAnswered(SIPResponseStatusCodesEnum answeredStatus, string reasonPhrase, string toTag, string[] customHeaders, string answeredContentType, string answeredBody, SIPDialogue answeredDialogue, SIPDialogueTransferModesEnum uasTransferMode)
        {
            try
            {
                if (!m_isAnswered)
                {
                    m_isAnswered = true;
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Answering client call with a response status of " + (int)answeredStatus + ".", Owner));

                    SIPDialogue uasDialogue = m_sipServerUserAgent.Answer(answeredContentType, answeredBody, toTag, answeredDialogue, uasTransferMode);

                    if (!m_sipServerUserAgent.IsB2B && answeredDialogue != null)
                    {
                        if (uasDialogue != null)
                        {
                            // Duplicate switchboard dialogue settings.
                            uasDialogue.SwitchboardDescription = answeredDialogue.SwitchboardDescription;
                            uasDialogue.SwitchboardCallerDescription = answeredDialogue.SwitchboardCallerDescription;
                            uasDialogue.SwitchboardOwner = answeredDialogue.SwitchboardOwner;

                            // Record the now established call with the call manager for in dialogue management and hangups.
                            CreateBridge_External(uasDialogue, answeredDialogue, m_dialPlan.Owner);
                        }
                        else
                        {
                            logger.Warn("Failed to get a SIPDialogue from UAS.Answer.");
                        }
                    }
                }
                else
                {
                    logger.Warn("DialPlanContext CallAnswered fired on already answered call.");
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception DialPlanContext CallAnswered. " + excp.Message);
            }
            finally
            {
                DialPlanExecutionFinished();
            }
        }
コード例 #29
0
ファイル: ForkCall.cs プロジェクト: sipsorcery/sipsorcery
        private void UACCallAnswered(ISIPClientUserAgent answeredUAC, SIPResponse answeredResponse)
        {
            try
            {
                // Remove the current call from the pending list.
                lock (m_switchCalls)
                {
                    m_switchCalls.Remove(answeredUAC);
                }

                if (m_switchCallTransactions != null && answeredUAC.ServerTransaction != null)
                {
                    m_switchCallTransactions.Add(answeredUAC.ServerTransaction);
                }

                if (answeredResponse != null && answeredResponse.StatusCode >= 200 && answeredResponse.StatusCode <= 299)
                {
                    #region 2xx final response.

                    if (!m_callAnswered && !m_commandCancelled)
                    {
                        // This is the first call we've got an answer on.
                        m_callAnswered = true;
                        m_answeredUAC = answeredUAC;
                        AnsweredSIPResponse = answeredResponse;

                        SIPDialogueTransferModesEnum uasTransferMode = SIPDialogueTransferModesEnum.Default;
                        if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.NotAllowed)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                            uasTransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                        }
                        else if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.BlindPlaceCall)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.BlindPlaceCall;
                            uasTransferMode = SIPDialogueTransferModesEnum.BlindPlaceCall;
                        }
                        else if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.PassThru)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.PassThru;
                            uasTransferMode = SIPDialogueTransferModesEnum.PassThru;
                        }
                        /*else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Caller)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                            uasTransferMode = SIPDialogueTransferModesEnum.Allowed;
                        }
                        else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Callee)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.Allowed;
                            uasTransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                        }
                        else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Both)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.Allowed;
                            uasTransferMode = SIPDialogueTransferModesEnum.Allowed;
                        }*/

                        if (CallAnswered != null)
                        {
                            logger.Debug("Transfer mode=" + m_answeredUAC.CallDescriptor.TransferMode + ".");
                            CallAnswered(answeredResponse.Status, answeredResponse.ReasonPhrase, null, null, answeredResponse.Header.ContentType, answeredResponse.Body, answeredUAC.SIPDialogue, uasTransferMode);
                        }

                        // Cancel/hangup and other calls on this leg that are still around.
                        CancelNotRequiredCallLegs(CallCancelCause.NormalClearing);
                    }
                    else
                    {
                        // Call already answered or cancelled, hangup (send BYE).
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg " + answeredUAC.CallDescriptor.Uri + " answered but call was already answered or cancelled, hanging up.", m_username));
                        SIPDialogue sipDialogue = new SIPDialogue(answeredUAC.ServerTransaction, m_username, m_adminMemberId);
                        sipDialogue.Hangup(m_sipTransport, m_outboundProxySocket);
                    }

                    #endregion

                    CallLegCompleted();
                }
                else if (answeredUAC.SIPDialogue != null)
                {
                    // Google Voice calls create the dialogue without using a SIP response.
                    if (!m_callAnswered && !m_commandCancelled)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg for Google Voice call to " + answeredUAC.CallDescriptor.Uri + " answered.", m_username));

                        // This is the first call we've got an answer on.
                        m_callAnswered = true;
                        m_answeredUAC = answeredUAC;

                        if (CallAnswered != null)
                        {
                            CallAnswered(SIPResponseStatusCodesEnum.Ok, null, null, null, answeredUAC.SIPDialogue.ContentType, answeredUAC.SIPDialogue.RemoteSDP, answeredUAC.SIPDialogue, SIPDialogueTransferModesEnum.NotAllowed);
                        }

                        // Cancel/hangup and other calls on this leg that are still around.
                        CancelNotRequiredCallLegs(CallCancelCause.NormalClearing);
                    }
                    else
                    {
                        // Call already answered or cancelled, hangup (send BYE).
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg for Google Voice call to " + answeredUAC.CallDescriptor.Uri + " answered but call was already answered or cancelled, hanging up.", m_username));
                        answeredUAC.SIPDialogue.Hangup(m_sipTransport, m_outboundProxySocket);
                    }
                }
                else if (answeredResponse != null && answeredResponse.StatusCode >= 300 && answeredResponse.StatusCode <= 399)
                {
                    ProcessRedirect(answeredUAC, answeredResponse);
                }
                else if (answeredResponse != null)
                {
                    // This call leg failed, record the failure status and reason.
                    m_lastFailureStatus = answeredResponse.Status;
                    m_lastFailureReason = answeredResponse.ReasonPhrase;

                    if (m_switchCallTransactions != null && answeredUAC.ServerTransaction != null)
                    {
                        m_switchCallTransactions.Add(answeredUAC.ServerTransaction);
                    }

                    CallLegCompleted();
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception ForkCall UACCallAnswered. " + excp);
            }
        }
コード例 #30
0
 public void CallFailed(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders)
 {
     try
     {
         if (!m_isAnswered)
         {
             m_isAnswered = true;
             if ((int)failureStatus >= 300 && (int)failureStatus <= 399)
             {
                 SIPURI redirectURI = SIPURI.ParseSIPURIRelaxed(customHeaders[0]);
                 m_sipServerUserAgent.Redirect(failureStatus, redirectURI);
             }
             else
             {
                 m_sipServerUserAgent.Reject(failureStatus, reasonPhrase, customHeaders);
             }
         }
     }
     catch (Exception excp)
     {
         logger.Error("Exception DialPlanContext CallFailed. " + excp.Message);
     }
     finally
     {
         DialPlanExecutionFinished();
     }
 }
コード例 #31
0
        private SIPResponse GetErrorResponse(SIPRequest sipRequest, SIPResponseStatusCodesEnum errorResponseCode, string errorMessage)
        {
            try
            {
                SIPResponse errorResponse = SIPTransport.GetResponse(sipRequest, errorResponseCode, null);
                if (errorMessage != null)
                {
                    errorResponse.ReasonPhrase = errorMessage;
                }

                SIPHeader requestHeader = sipRequest.Header;
                SIPHeader errorHeader = new SIPHeader(requestHeader.Contact, requestHeader.From, requestHeader.To, requestHeader.CSeq, requestHeader.CallId);

                if (errorHeader.To.ToTag == null || errorHeader.To.ToTag.Trim().Length == 0)
                {
                    errorHeader.To.ToTag = CallProperties.CreateNewTag();
                }

                errorHeader.CSeqMethod = requestHeader.CSeqMethod;
                errorHeader.Vias = requestHeader.Vias;
                errorHeader.Server = m_serverAgent;
                errorHeader.MaxForwards = Int32.MinValue;

                errorResponse.Header = errorHeader;

                return errorResponse;
            }
            catch (Exception excp)
            {
                logger.Error("Exception GetErrorResponse. " + excp.Message);
                throw excp;
            }
        }
コード例 #32
0
        public void CallProgress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody, ISIPClientUserAgent uac)
        {
            if (!m_isAnswered)
            {
                m_sipServerUserAgent.Progress(progressStatus, reasonPhrase, customHeaders, progressContentType, progressBody);

                if (uac != null && uac.CallDescriptor.RequestCallerDetails && CallerCRMDetails != null)
                {
                    if (CallerCRMDetails.Pending && !m_uacWaitingForCallDetails.Contains(uac) && !m_uacCallDetailsSent.Contains(uac))
                    {
                        m_uacWaitingForCallDetails.Add(uac);
                    }
                    else if (!CallerCRMDetails.Pending && !m_uacCallDetailsSent.Contains(uac))
                    {
                        // Send the call details to the client user agent.
                        uac.Update(CallerCRMDetails);
                    }
                }
            }
        }
コード例 #33
0
        /// <summary>
        /// Updates the bindings list for a registrar's address-of-records.
        /// </summary>
        /// <param name="proxyEndPoint">If the request arrived at this registrar via a proxy then this will contain the end point of the proxy.</param>
        /// <param name="uacRecvdEndPoint">The public end point the UAC REGISTER request was deemded to have originated from.</param>
        /// <param name="registrarEndPoint">The registrar end point the registration request was received on.</param>
        /// <param name="maxAllowedExpiry">The maximum allowed expiry that can be granted to this binding request.</param>
        /// <returns>If the binding update was successful the expiry time for it is returned otherwise 0.</returns>
        public List<SIPRegistrarBinding> UpdateBindings(
            SIPAccount sipAccount,
            SIPEndPoint proxySIPEndPoint,
            SIPEndPoint remoteSIPEndPoint,
            SIPEndPoint registrarSIPEndPoint,
            List<SIPContactHeader> contactHeaders,
            string callId,
            int cseq,
            //int contactHeaderExpiresValue,
            int expiresHeaderValue,
            string userAgent,
            out SIPResponseStatusCodesEnum responseStatus,
            out string responseMessage)
        {
            //logger.Debug("UpdateBinding " + bindingURI.ToString() + ".");

            int maxAllowedExpiry = m_userAgentConfigs.GetMaxAllowedExpiry(userAgent);
            responseMessage = null;
            string sipAccountAOR = sipAccount.SIPUsername + "@" + sipAccount.SIPDomain;
            responseStatus = SIPResponseStatusCodesEnum.Ok;

            try
            {
                userAgent = (userAgent != null && userAgent.Length > MAX_USERAGENT_LENGTH) ? userAgent.Substring(0, MAX_USERAGENT_LENGTH) : userAgent;

                List<SIPRegistrarBinding> bindings = m_bindingsPersistor.Get(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue);

                foreach (SIPContactHeader contactHeader in contactHeaders)
                {
                    SIPURI bindingURI = contactHeader.ContactURI.CopyOf();
                    int contactHeaderExpiresValue = contactHeader.Expires;
                    int bindingExpiry = 0;

                    if (bindingURI.Host == m_sipRegisterRemoveAll)
                    {
                        if (contactHeaders.Count > 1)
                        {
                            // If a register request specifies remove all it cannot contain any other binding requests.
                            FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingRemoval, "Remove all bindings requested for " + sipAccountAOR + " but mutliple bindings specified, rejecting as a bad request.", sipAccount.SIPUsername));
                            responseStatus = SIPResponseStatusCodesEnum.BadRequest;
                            break;
                        }

                        #region Process remove all bindings.

                        if (expiresHeaderValue == 0)
                        {
                            // Removing all bindings for user.
                            FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingRemoval, "Remove all bindings requested for " + sipAccountAOR + ".", sipAccount.SIPUsername));

                            // Mark all the current bindings as expired.
                            if (bindings != null && bindings.Count > 0)
                            {
                                for (int index = 0; index < bindings.Count; index++)
                                {
                                    bindings[index].RemovalReason = SIPBindingRemovalReason.ClientExpiredAll;
                                    bindings[index].Expiry = 0;
                                    m_bindingsPersistor.Update(bindings[index]);

                                    // Remove the NAT keep-alive job if present.
                                    if (m_natKeepAliveJobs.ContainsKey(bindings[index].RemoteSIPSocket))
                                    {
                                        m_natKeepAliveJobs[bindings[index].RemoteSIPSocket].CancelJob();
                                    }
                                }
                            }

                            FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));

                            responseStatus = SIPResponseStatusCodesEnum.Ok;
                        }
                        else
                        {
                            // Remove all header cannot be present with other headers and must have an Expiry equal to 0.
                            responseStatus = SIPResponseStatusCodesEnum.BadRequest;
                        }

                        #endregion
                    }
                    else
                    {
                        int requestedExpiry = (contactHeaderExpiresValue != -1) ? contactHeaderExpiresValue : expiresHeaderValue;
                        requestedExpiry = (requestedExpiry == -1) ? maxAllowedExpiry : requestedExpiry;   // This will happen if the Expires header and the Expiry on the Contact are both missing.
                        bindingExpiry = (requestedExpiry > maxAllowedExpiry) ? maxAllowedExpiry : requestedExpiry;
                        bindingExpiry = (bindingExpiry < MINIMUM_EXPIRY_SECONDS) ? MINIMUM_EXPIRY_SECONDS : bindingExpiry;

                        bindingURI.Parameters.Remove(m_sipExpiresParameterKey);

                        SIPRegistrarBinding binding = GetBindingForContactURI(bindings, bindingURI.ToString());

                        if (binding != null)
                        {
                            if (requestedExpiry <= 0)
                            {
                                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingExpired, "Binding expired by client for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ".", sipAccount.SIPUsername));
                                bindings.Remove(binding);
                                m_bindingsPersistor.Delete(binding);
                                bindingExpiry = 0;

                                FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));

                                // Remove the NAT keep-alive job if present.
                                if (m_natKeepAliveJobs.ContainsKey(binding.RemoteSIPSocket))
                                {
                                    m_natKeepAliveJobs[binding.RemoteSIPSocket].CancelJob();
                                }
                            }
                            else
                            {
                                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Registrar, "Binding update request for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ", expiry requested " + requestedExpiry + "s granted " + bindingExpiry + "s.", sipAccount.Owner));
                                binding.RefreshBinding(bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, sipAccount.DontMangleEnabled);

                                DateTime startTime = DateTime.Now;
                                m_bindingsPersistor.Update(binding);
                                TimeSpan duration = DateTime.Now.Subtract(startTime);
                                //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database update time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null));
                                FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));

                                // Add a NAT keep-alive job if required.
                                if (sipAccount.SendNATKeepAlives && proxySIPEndPoint != null)
                                {
                                    AddNATKeepAliveJob(sipAccount, remoteSIPEndPoint, proxySIPEndPoint, binding, bindingExpiry);
                                }
                            }
                        }
                        else
                        {
                            if (requestedExpiry > 0)
                            {
                                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "New binding request for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ", expiry requested " + requestedExpiry + "s granted " + bindingExpiry + "s.", sipAccount.Owner));

                                if (bindings.Count >= m_maxBindingsPerAccount)
                                {
                                    // Need to remove the oldest binding to stay within limit.
                                    //SIPRegistrarBinding oldestBinding = m_bindingsPersistor.Get(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue).OrderBy(x => x.LastUpdateUTC).Last();
                                    SIPRegistrarBinding oldestBinding = bindings.OrderBy(x => x.LastUpdate).Last();
                                    FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "Binding limit exceeded for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + " removing oldest binding to stay within limit of " + m_maxBindingsPerAccount + ".", sipAccount.Owner));
                                    m_bindingsPersistor.Delete(oldestBinding);

                                    if (m_natKeepAliveJobs.ContainsKey(binding.RemoteSIPSocket))
                                    {
                                        m_natKeepAliveJobs[binding.RemoteSIPSocket].CancelJob();
                                    }
                                }

                                SIPRegistrarBinding newBinding = new SIPRegistrarBinding(sipAccount, bindingURI, callId, cseq, userAgent, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, bindingExpiry);
                                DateTime startTime = DateTime.Now;
                                bindings.Add(newBinding);
                                m_bindingsPersistor.Add(newBinding);
                                TimeSpan duration = DateTime.Now.Subtract(startTime);
                                //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database add time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null));

                                // Add a NAT keep-alive job if required.
                                if (sipAccount.SendNATKeepAlives && proxySIPEndPoint != null)
                                {
                                    AddNATKeepAliveJob(sipAccount, remoteSIPEndPoint, proxySIPEndPoint, newBinding, bindingExpiry);
                                }

                                FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));
                            }
                            else
                            {
                                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingFailed, "New binding received for " + sipAccountAOR + " with expired contact," + bindingURI.ToString() + " no update.", sipAccount.Owner));
                                bindingExpiry = 0;
                            }
                        }

                        responseStatus = SIPResponseStatusCodesEnum.Ok;
                    }
                }

                return bindings;
            }
            catch (Exception excp)
            {
                logger.Error("Exception UpdateBinding. " + excp.Message);
                FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, "Registrar error updating binding: " + excp.Message + " Binding not updated.", sipAccount.SIPUsername));
                responseStatus = SIPResponseStatusCodesEnum.InternalServerError;
                return null;
            }
        }
コード例 #34
0
        private RegisterResultEnum Register(SIPTransaction registerTransaction)
        {
            try
            {
                SIPRequest  sipRequest      = registerTransaction.TransactionRequest;
                SIPURI      registerURI     = sipRequest.URI;
                SIPToHeader toHeader        = sipRequest.Header.To;
                string      toUser          = toHeader.ToURI.User;
                string      canonicalDomain = (m_strictRealmHandling) ? GetCanonicalDomain_External(toHeader.ToURI.Host, true) : toHeader.ToURI.Host;
                int         requestedExpiry = GetRequestedExpiry(sipRequest);

                if (canonicalDomain == null)
                {
                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Register request for " + toHeader.ToURI.Host + " rejected as no matching domain found.", null));
                    SIPResponse noDomainResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced");
                    registerTransaction.SendFinalResponse(noDomainResponse);
                    return(RegisterResultEnum.DomainNotServiced);
                }

                SIPAccountAsset sipAccountAsset = GetSIPAccount_External(s => s.SIPUsername == toUser && s.SIPDomain == canonicalDomain);
                SIPRequestAuthenticationResult authenticationResult = SIPRequestAuthenticator_External(registerTransaction.LocalSIPEndPoint, registerTransaction.RemoteEndPoint, sipRequest, sipAccountAsset.SIPAccount, FireProxyLogEvent);

                if (!authenticationResult.Authenticated)
                {
                    // 401 Response with a fresh nonce needs to be sent.
                    SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null);
                    authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                    registerTransaction.SendFinalResponse(authReqdResponse);

                    if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Forbidden " + toUser + "@" + canonicalDomain + " does not exist, " + sipRequest.Header.ProxyReceivedFrom + ", " + sipRequest.Header.UserAgent + ".", null));
                        return(RegisterResultEnum.Forbidden);
                    }
                    else
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Registrar, "Authentication required for " + toUser + "@" + canonicalDomain + " from " + sipRequest.Header.ProxyReceivedFrom + ".", toUser));
                        return(RegisterResultEnum.AuthenticationRequired);
                    }
                }
                else
                {
                    // Authenticated.
                    //if (!sipRequest.Header.UserAgent.IsNullOrBlank() && !m_switchboarduserAgentPrefix.IsNullOrBlank() && sipRequest.Header.UserAgent.StartsWith(m_switchboarduserAgentPrefix))
                    //{
                    //    // Check that the switchboard user is authorised.
                    //    var customer = CustomerPersistor_External.Get(x => x.CustomerUsername == sipAccount.Owner);
                    //    if (!(customer.ServiceLevel == CustomerServiceLevels.Switchboard.ToString() || customer.ServiceLevel == CustomerServiceLevels.Gold.ToString()))
                    //    {
                    //        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Register request for switchboard from " + toHeader.ToURI.Host + " rejected as not correct service level.", sipAccount.Owner));
                    //        SIPResponse payReqdResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.PaymentRequired, "You need to purchase a Switchboard service");
                    //        registerTransaction.SendFinalResponse(payReqdResponse);
                    //        return RegisterResultEnum.SwitchboardPaymentRequired;
                    //    }
                    //}

                    if (sipRequest.Header.Contact == null || sipRequest.Header.Contact.Count == 0)
                    {
                        // No contacts header to update bindings with, return a list of the current bindings.
                        List <SIPRegistrarBinding> bindings = m_registrarBindingsManager.GetBindings(sipAccountAsset.Id);
                        //List<SIPContactHeader> contactsList = m_registrarBindingsManager.GetContactHeader(); // registration.GetContactHeader(true, null);
                        if (bindings != null)
                        {
                            sipRequest.Header.Contact = GetContactHeader(bindings);
                        }

                        SIPResponse okResponse = GetOkResponse(sipRequest);
                        registerTransaction.SendFinalResponse(okResponse);
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Empty registration request successful for " + toUser + "@" + canonicalDomain + " from " + sipRequest.Header.ProxyReceivedFrom + ".", toUser));
                    }
                    else
                    {
                        SIPEndPoint uacRemoteEndPoint = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedFrom) ?? registerTransaction.RemoteEndPoint;
                        SIPEndPoint proxySIPEndPoint  = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedOn);
                        SIPEndPoint registrarEndPoint = registerTransaction.LocalSIPEndPoint;

                        SIPResponseStatusCodesEnum updateResult = SIPResponseStatusCodesEnum.Ok;
                        string updateMessage = null;

                        DateTime startTime = DateTime.Now;

                        List <SIPRegistrarBinding> bindingsList = m_registrarBindingsManager.UpdateBindings(
                            sipAccountAsset.SIPAccount,
                            proxySIPEndPoint,
                            uacRemoteEndPoint,
                            registrarEndPoint,
                            //sipRequest.Header.Contact[0].ContactURI.CopyOf(),
                            sipRequest.Header.Contact,
                            sipRequest.Header.CallId,
                            sipRequest.Header.CSeq,
                            //sipRequest.Header.Contact[0].Expires,
                            sipRequest.Header.Expires,
                            sipRequest.Header.UserAgent,
                            out updateResult,
                            out updateMessage);

                        //int bindingExpiry = GetBindingExpiry(bindingsList, sipRequest.Header.Contact[0].ContactURI.ToString());
                        TimeSpan duration = DateTime.Now.Subtract(startTime);
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding update time for " + toUser + "@" + canonicalDomain + " took " + duration.TotalMilliseconds + "ms.", null));

                        if (updateResult == SIPResponseStatusCodesEnum.Ok)
                        {
                            string proxySocketStr = (proxySIPEndPoint != null) ? " (proxy=" + proxySIPEndPoint.ToString() + ")" : null;

                            int bindingCount = 1;
                            foreach (SIPRegistrarBinding binding in bindingsList)
                            {
                                string bindingIndex = (bindingsList.Count == 1) ? String.Empty : " (" + bindingCount + ")";
                                //FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Registration successful for " + toUser + "@" + canonicalDomain + " from " + uacRemoteEndPoint + proxySocketStr + ", binding " + binding.ContactSIPURI.ToParameterlessString() + ";expiry=" + binding.Expiry + bindingIndex + ".", toUser));
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Registration successful for " + toUser + "@" + canonicalDomain + " from " + uacRemoteEndPoint + ", binding " + binding.ContactSIPURI.ToParameterlessString() + ";expiry=" + binding.Expiry + bindingIndex + ".", toUser));
                                //FireProxyLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, toUser, uacRemoteEndPoint, sipAccount.Id.ToString()));
                                bindingCount++;
                            }

                            // The standard states that the Ok response should contain the list of current bindings but that breaks some UAs. As a
                            // compromise the list is returned with the Contact that UAC sent as the first one in the list.
                            bool contactListSupported = m_userAgentConfigs.GetUserAgentContactListSupport(sipRequest.Header.UserAgent);
                            if (contactListSupported)
                            {
                                sipRequest.Header.Contact = GetContactHeader(bindingsList);
                            }
                            else
                            {
                                // Some user agents can't match the contact header if the expiry is added to it.
                                sipRequest.Header.Contact[0].Expires = GetBindingExpiry(bindingsList, sipRequest.Header.Contact[0].ContactURI.ToString());;
                            }

                            SIPResponse okResponse = GetOkResponse(sipRequest);

                            // If a request was made for a switchboard token and a certificate is available to sign the tokens then generate it.
                            //if (sipRequest.Header.SwitchboardTokenRequest > 0 && m_switchbboardRSAProvider != null)
                            //{
                            //    SwitchboardToken token = new SwitchboardToken(sipRequest.Header.SwitchboardTokenRequest, sipAccount.Owner, uacRemoteEndPoint.Address.ToString());

                            //    lock (m_switchbboardRSAProvider)
                            //    {
                            //        token.SignedHash = Convert.ToBase64String(m_switchbboardRSAProvider.SignHash(Crypto.GetSHAHash(token.GetHashString()), null));
                            //    }

                            //    string tokenXML = token.ToXML(true);
                            //    logger.Debug("Switchboard token set for " + sipAccount.Owner + " with expiry of " + token.Expiry + "s.");
                            //    okResponse.Header.SwitchboardToken = Crypto.SymmetricEncrypt(sipAccount.SIPPassword, sipRequest.Header.AuthenticationHeader.SIPDigest.Nonce, tokenXML);
                            //}

                            registerTransaction.SendFinalResponse(okResponse);
                        }
                        else
                        {
                            // The binding update failed even though the REGISTER request was authorised. This is probably due to a
                            // temporary problem connecting to the bindings data store. Send Ok but set the binding expiry to the minimum so
                            // that the UA will try again as soon as possible.
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, "Registration request successful but binding update failed for " + toUser + "@" + canonicalDomain + " from " + registerTransaction.RemoteEndPoint + ".", toUser));
                            sipRequest.Header.Contact[0].Expires = m_minimumBindingExpiry;
                            SIPResponse okResponse = GetOkResponse(sipRequest);
                            registerTransaction.SendFinalResponse(okResponse);
                        }
                    }

                    return(RegisterResultEnum.Authenticated);
                }
            }
            catch (Exception excp)
            {
                string regErrorMessage = "Exception registrarcore registering. " + excp.Message + "\r\n" + registerTransaction.TransactionRequest.ToString();
                logger.Error(regErrorMessage);
                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, regErrorMessage, null));

                try
                {
                    SIPResponse errorResponse = GetErrorResponse(registerTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                    registerTransaction.SendFinalResponse(errorResponse);
                }
                catch { }

                return(RegisterResultEnum.Error);
            }
        }
コード例 #35
0
 public SIPValidationException(SIPValidationFieldsEnum sipErrorField, string message)
     : base(message)
 {
     SIPErrorField        = sipErrorField;
     SIPResponseErrorCode = SIPResponseStatusCodesEnum.BadRequest;
 }
コード例 #36
0
        /// <summary>
        /// Attempts to renew an existing subscription.
        /// </summary>
        /// <returns>The session ID if the renewal was successful or null if it wasn't.</returns>
        public string RenewSubscription(SIPRequest subscribeRequest, out SIPResponseStatusCodesEnum errorResponse, out string errorReason)
        {
            errorResponse = SIPResponseStatusCodesEnum.None;
            errorReason   = null;

            try
            {
                int    expiry  = subscribeRequest.Header.Expires;
                string toTag   = subscribeRequest.Header.To.ToTag;
                string fromTag = subscribeRequest.Header.From.FromTag;
                string callID  = subscribeRequest.Header.CallId;
                int    cseq    = subscribeRequest.Header.CSeq;

                // Check for an existing subscription.
                SIPEventSubscription existingSubscription = (from sub in m_subscriptions.Values where sub.SubscriptionDialogue.CallId == callID select sub).FirstOrDefault();

                if (existingSubscription != null)
                {
                    if (expiry == 0)
                    {
                        // Subsciption is being cancelled.
                        StopSubscription(existingSubscription);
                        return(null);
                    }
                    else if (cseq > existingSubscription.SubscriptionDialogue.RemoteCSeq)
                    {
                        logger.Debug("Renewing subscription for " + existingSubscription.SessionID + " and " + existingSubscription.SubscriptionDialogue.Owner + ".");
                        existingSubscription.SubscriptionDialogue.RemoteCSeq = cseq;
                        //existingSubscription.ProxySendFrom = (!subscribeRequest.Header.ProxyReceivedOn.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(subscribeRequest.Header.ProxyReceivedOn) : null;

                        string extensionResult = m_publisher.ExtendSession(m_notificationsAddress, existingSubscription.SessionID, expiry);
                        if (extensionResult != null)
                        {
                            // One or more of the monitor servers could not extend the session. Close all the existing sessions and re-create.
                            MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Monitor session extension for " + existingSubscription.SubscriptionEventPackage.ToString() + " " + existingSubscription.ResourceURI.ToString() + " failed. " + extensionResult, existingSubscription.SubscriptionDialogue.Owner));
                            m_publisher.CloseSession(m_notificationsAddress, existingSubscription.SessionID);

                            // Need to re-establish the sessions with the notification servers.
                            string subscribeError = null;
                            string sessionID      = Guid.NewGuid().ToString();
                            m_publisher.Subscribe(existingSubscription.SubscriptionDialogue.Owner, existingSubscription.SubscriptionDialogue.AdminMemberId, m_notificationsAddress, sessionID, SIPMonitorClientTypesEnum.Machine.ToString(), existingSubscription.MonitorFilter, expiry, null, out subscribeError);

                            if (subscribeError != null)
                            {
                                throw new ApplicationException(subscribeError);
                            }
                            else
                            {
                                lock (m_subscriptions)
                                {
                                    m_subscriptions.Remove(existingSubscription.SessionID);
                                    existingSubscription.SessionID = sessionID;
                                    m_subscriptions.Add(sessionID, existingSubscription);
                                }
                                MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "Monitor session recreated for " + existingSubscription.SubscriptionEventPackage.ToString() + " " + existingSubscription.ResourceURI.ToString() + ".", existingSubscription.SubscriptionDialogue.Owner));
                            }
                        }

                        MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeRenew, "Monitor session successfully renewed for " + existingSubscription.SubscriptionEventPackage.ToString() + " " + existingSubscription.ResourceURI.ToString() + ".", existingSubscription.SubscriptionDialogue.Owner));

                        return(existingSubscription.SessionID);
                    }
                    else
                    {
                        throw new ApplicationException("A duplicate SUBSCRIBE request was received by NotifierSubscriptionsManager.");
                    }
                }
                else
                {
                    //throw new ApplicationException("No existing subscription could be found for a subscribe renewal request.");
                    errorResponse = SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist;
                    errorReason   = "Subscription dialog not found";
                    return(null);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception RenewSubscription. " + excp.Message);
                throw;
            }
        }
コード例 #37
0
        /// <summary>
        /// Updates the bindings list for a registrar's address-of-records.
        /// </summary>
        /// <param name="proxyEndPoint">If the request arrived at this registrar via a proxy then this will contain the end point of the proxy.</param>
        /// <param name="uacRecvdEndPoint">The public end point the UAC REGISTER request was deemded to have originated from.</param>
        /// <param name="registrarEndPoint">The registrar end point the registration request was received on.</param>
        /// <param name="maxAllowedExpiry">The maximum allowed expiry that can be granted to this binding request.</param>
        /// <returns>If the binding update was successful the expiry time for it is returned otherwise 0.</returns>
        public List <SIPRegistrarBinding> UpdateBindings(
            SIPAccount sipAccount,
            SIPEndPoint proxySIPEndPoint,
            SIPEndPoint remoteSIPEndPoint,
            SIPEndPoint registrarSIPEndPoint,
            List <SIPContactHeader> contactHeaders,
            string callId,
            int cseq,
            int expiresHeaderValue,
            string userAgent,
            out SIPResponseStatusCodesEnum responseStatus,
            out string responseMessage)
        {
            //logger.Debug("UpdateBinding " + bindingURI.ToString() + ".");

            int maxAllowedExpiry = DEFAULT_MAX_EXPIRY_SECONDS;

            responseMessage = null;
            string sipAccountAOR = sipAccount.AOR;

            responseStatus = SIPResponseStatusCodesEnum.Ok;

            try
            {
                userAgent = (userAgent != null && userAgent.Length > MAX_USERAGENT_LENGTH) ? userAgent.Substring(0, MAX_USERAGENT_LENGTH) : userAgent;

                List <SIPRegistrarBinding> bindings = m_registrarBindingDataLayer.GetForSIPAccount(sipAccount.ID);

                foreach (SIPContactHeader contactHeader in contactHeaders)
                {
                    SIPURI bindingURI = contactHeader.ContactURI.CopyOf();
                    int    contactHeaderExpiresValue = contactHeader.Expires;
                    int    bindingExpiry             = 0;

                    if (bindingURI.Host == m_sipRegisterRemoveAll)
                    {
                        if (contactHeaders.Count > 1)
                        {
                            // If a register request specifies remove all it cannot contain any other binding requests.
                            Logger.LogDebug("Remove all bindings requested for " + sipAccountAOR + " but mutliple bindings specified, rejecting as a bad request.");
                            responseStatus = SIPResponseStatusCodesEnum.BadRequest;
                            break;
                        }

                        #region Process remove all bindings.

                        if (expiresHeaderValue == 0)
                        {
                            // Removing all bindings for user.
                            Logger.LogDebug("Remove all bindings requested for " + sipAccountAOR + ".");

                            // Mark all the current bindings as expired.
                            if (bindings != null && bindings.Count > 0)
                            {
                                for (int index = 0; index < bindings.Count; index++)
                                {
                                    //bindings[index].RemovalReason = SIPBindingRemovalReason.ClientExpiredAll;
                                    bindings[index].Expiry = 0;
                                    //m_bindingsPersistor.Update(bindings[index]);
                                }
                            }

                            //FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));

                            responseStatus = SIPResponseStatusCodesEnum.Ok;
                        }
                        else
                        {
                            // Remove all header cannot be present with other headers and must have an Expiry equal to 0.
                            responseStatus = SIPResponseStatusCodesEnum.BadRequest;
                        }

                        #endregion
                    }
                    else
                    {
                        int requestedExpiry = (contactHeaderExpiresValue != -1) ? contactHeaderExpiresValue : expiresHeaderValue;
                        requestedExpiry = (requestedExpiry == -1) ? maxAllowedExpiry : requestedExpiry;   // This will happen if the Expires header and the Expiry on the Contact are both missing.
                        bindingExpiry   = (requestedExpiry > maxAllowedExpiry) ? maxAllowedExpiry : requestedExpiry;
                        bindingExpiry   = (bindingExpiry < MINIMUM_EXPIRY_SECONDS) ? MINIMUM_EXPIRY_SECONDS : bindingExpiry;

                        bindingURI.Parameters.Remove(m_sipExpiresParameterKey);

                        //SIPRegistrarBinding binding = GetBindingForContactURI(bindings, bindingURI.ToString());
                        SIPRegistrarBinding binding = bindings.Where(x => x.ContactURI == bindingURI.ToString()).FirstOrDefault();

                        if (binding != null)
                        {
                            if (requestedExpiry <= 0)
                            {
                                Logger.LogDebug($"Binding expired by client for {sipAccountAOR} from {remoteSIPEndPoint}.");
                                bindings.Remove(binding);
                                m_registrarBindingDataLayer.Delete(binding.ID);
                                bindingExpiry = 0;
                            }
                            else
                            {
                                Logger.LogDebug($"Binding update request for {sipAccountAOR} from {remoteSIPEndPoint}, expiry requested {requestedExpiry}s granted {bindingExpiry}s.");
                                //binding.RefreshBinding(bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, sipAccount.DontMangleEnabled);
                                //binding.RefreshBinding(bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, false);

                                //DateTime startTime = DateTime.Now;
                                //m_bindingsPersistor.Update(binding);
                                //m_registrarBindingDataLayer.Update(binding);
                                m_registrarBindingDataLayer.RefreshBinding(binding.ID, bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, false);
                                //TimeSpan duration = DateTime.Now.Subtract(startTime);
                                //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database update time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null));
                                //FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR)));
                            }
                        }
                        else
                        {
                            if (requestedExpiry > 0)
                            {
                                Logger.LogDebug($"New binding request for {sipAccountAOR} from {remoteSIPEndPoint}, expiry requested {requestedExpiry}s granted {bindingExpiry}s.");

                                if (bindings.Count >= m_maxBindingsPerAccount)
                                {
                                    // Need to remove the oldest binding to stay within limit.
                                    SIPRegistrarBinding oldestBinding = bindings.OrderBy(x => x.LastUpdate).Last();
                                    Logger.LogDebug($"Binding limit exceeded for {sipAccountAOR} from {remoteSIPEndPoint} removing oldest binding to stay within limit of {m_maxBindingsPerAccount}.");
                                    m_registrarBindingDataLayer.Delete(oldestBinding.ID);
                                }

                                SIPRegistrarBinding newBinding = new SIPRegistrarBinding(sipAccount, bindingURI, callId, cseq, userAgent,
                                                                                         remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, bindingExpiry);
                                m_registrarBindingDataLayer.Add(newBinding);
                            }
                            else
                            {
                                Logger.LogDebug($"New binding received for {sipAccountAOR} with expired contact, {bindingURI} no update.");
                                bindingExpiry = 0;
                            }
                        }

                        responseStatus = SIPResponseStatusCodesEnum.Ok;
                    }
                }

                return(m_registrarBindingDataLayer.GetForSIPAccount(sipAccount.ID));
            }
            catch (Exception excp)
            {
                Logger.LogError("Exception UpdateBinding. " + excp);
                responseStatus = SIPResponseStatusCodesEnum.InternalServerError;
                return(null);
            }
        }
コード例 #38
0
        public string SubscribeClient(
            string owner,
            string adminID,
            SIPRequest subscribeRequest,
            string toTag,
            SIPURI canonicalResourceURI,
            out SIPResponseStatusCodesEnum errorResponse,
            out string errorReason)
        {
            try
            {
                errorResponse = SIPResponseStatusCodesEnum.None;
                errorReason   = null;

                SIPURI          resourceURI  = subscribeRequest.URI.CopyOf();
                SIPEventPackage eventPackage = SIPEventPackage.Parse(subscribeRequest.Header.Event);
                int             expiry       = subscribeRequest.Header.Expires;

                if (!(eventPackage == SIPEventPackage.Dialog || eventPackage == SIPEventPackage.Presence))
                {
                    throw new ApplicationException("Event package " + eventPackage.ToString() + " is not supported by the subscriptions manager.");
                }
                else
                {
                    if (expiry > 0)
                    {
                        string      subscribeError    = null;
                        string      sessionID         = Guid.NewGuid().ToString();
                        SIPDialogue subscribeDialogue = new SIPDialogue(subscribeRequest, owner, adminID, toTag);

                        if (eventPackage == SIPEventPackage.Dialog)
                        {
                            string monitorFilter = "dialog " + canonicalResourceURI.ToString();
                            if (!subscribeRequest.Body.IsNullOrBlank())
                            {
                                monitorFilter += " and " + subscribeRequest.Body;
                            }

                            m_publisher.Subscribe(owner, adminID, m_notificationsAddress, sessionID, SIPMonitorClientTypesEnum.Machine.ToString(), monitorFilter, expiry, null, out subscribeError);

                            if (subscribeError != null)
                            {
                                throw new ApplicationException(subscribeError);
                            }
                            else
                            {
                                SIPDialogEventSubscription subscription = new SIPDialogEventSubscription(MonitorLogEvent_External, sessionID, resourceURI, canonicalResourceURI, monitorFilter, subscribeDialogue, expiry, GetDialogues_External, GetDialogue_External);
                                m_subscriptions.Add(sessionID, subscription);
                                MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "New dialog subscription created for " + resourceURI.ToString() + ", expiry " + expiry + "s.", owner));
                            }
                        }
                        else if (eventPackage == SIPEventPackage.Presence)
                        {
                            string monitorFilter = "presence " + canonicalResourceURI.ToString();
                            m_publisher.Subscribe(owner, adminID, m_notificationsAddress, sessionID, SIPMonitorClientTypesEnum.Machine.ToString(), monitorFilter, expiry, null, out subscribeError);

                            if (subscribeError != null)
                            {
                                throw new ApplicationException(subscribeError);
                            }
                            else
                            {
                                bool switchboardAccountsOnly = subscribeRequest.Body == SIPPresenceEventSubscription.SWITCHBOARD_FILTER;
                                SIPPresenceEventSubscription subscription =
                                    new SIPPresenceEventSubscription(MonitorLogEvent_External, sessionID, resourceURI,
                                                                     canonicalResourceURI, monitorFilter, subscribeDialogue, expiry,
                                                                     m_sipAssetPersistor.Get, m_sipAssetPersistor.GetProperty,
                                                                     GetSIPRegistrarBindingsCount_External, switchboardAccountsOnly);
                                m_subscriptions.Add(sessionID, subscription);
                                MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "New presence subscription created for " + resourceURI.ToString() + ", expiry " + expiry + "s.", owner));
                            }
                        }

                        return(sessionID);
                    }

                    return(null);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception NotifierSubscriptionsManager SubscribeClient. " + excp.Message);
                throw;
            }
        }
コード例 #39
0
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     NoRingTimeout.Invoke(this);
     throw new NotImplementedException("SIPTransferServerUserAgent Redirect");
 }
コード例 #40
0
ファイル: SIPResponse.cs プロジェクト: soitgoes/sipsorcery
        /// <summary>
        /// Used to create a SIP response for a request when it was not possible to parse the incoming SIP request.
        /// The response generated by this method may or may not make it back to the requester. Because the SIP
        /// request could not be parsed there are no Via headers available and without those the return network
        /// path is missing. Instead a new Via header is generated that may get through if the requester is only
        /// one SIP hop away.
        /// </summary>
        /// <param name="localSIPEndPoint">The local SIP end point the request was received on.</param>
        /// <param name="remoteSIPEndPoint">The remote SIP end point the request was received on.</param>
        /// <param name="responseCode">The response code to set on the response.</param>
        /// <param name="reasonPhrase">Optional reason phrase to set on the response (keep short).</param>
        public static SIPResponse GetResponse(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteSIPEndPoint, SIPResponseStatusCodesEnum responseCode, string reasonPhrase)
        {
            try
            {
                SIPResponse response = new SIPResponse(responseCode, reasonPhrase);
                response.SetSendFromHints(localSIPEndPoint);
                SIPSchemesEnum sipScheme = (localSIPEndPoint.Protocol == SIPProtocolsEnum.tls) ? SIPSchemesEnum.sips : SIPSchemesEnum.sip;
                SIPFromHeader  from      = new SIPFromHeader(null, new SIPURI(sipScheme, localSIPEndPoint), null);
                SIPToHeader    to        = new SIPToHeader(null, new SIPURI(sipScheme, localSIPEndPoint), null);
                int            cSeq      = 1;
                string         callId    = CallProperties.CreateNewCallId();
                response.Header            = new SIPHeader(from, to, cSeq, callId);
                response.Header.CSeqMethod = SIPMethodsEnum.NONE;
                response.Header.Vias.PushViaHeader(new SIPViaHeader(new SIPEndPoint(localSIPEndPoint.Protocol, remoteSIPEndPoint.GetIPEndPoint()), CallProperties.CreateBranchId()));
                response.Header.MaxForwards = Int32.MinValue;
                response.Header.Allow       = m_allowedSIPMethods;

                return(response);
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPResponse.GetResponse. " + excp.Message);
                throw;
            }
        }
コード例 #41
0
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     throw new NotImplementedException();
 }
コード例 #42
0
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     UASStateChanged.Invoke(this, SIPResponseStatusCodesEnum.ExtensionRequired, "ExtensionRequired");
     throw new NotImplementedException();
 }
コード例 #43
0
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     throw new NotImplementedException("SIPTransferServerUserAgent Redirect");
 }
コード例 #44
0
        public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders,
                             string progressContentType, string progressBody)
        {
            try
            {
                if (!IsUASAnswered)
                {
                    if ((int)progressStatus >= 200)
                    {
                    }
                    else
                    {
                        if (UASStateChanged != null)
                        {
                            UASStateChanged(this, progressStatus, reasonPhrase);
                        }

                        // Allow all Trying responses through as some may contain additional useful information on the call state for the caller.
                        // Also if the response is a 183 Session Progress with audio forward it.
                        if (m_uasTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding &&
                            progressStatus != SIPResponseStatusCodesEnum.Trying &&
                            !(progressStatus == SIPResponseStatusCodesEnum.SessionProgress && progressBody != null))
                        {
                        }
                        else
                        {
                            SIPResponse progressResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest,
                                                                                    progressStatus, reasonPhrase);

                            if (progressResponse.Status != SIPResponseStatusCodesEnum.Trying)
                            {
                                progressResponse.Header.To.ToTag = m_uasTransaction.LocalTag;
                            }

                            if (!progressBody.IsNullOrBlank())
                            {
                                progressResponse.Body = progressBody;
                                progressResponse.Header.ContentType   = progressContentType;
                                progressResponse.Header.ContentLength = progressBody.Length;
                            }

                            if (customHeaders != null && customHeaders.Length > 0)
                            {
                                foreach (string header in customHeaders)
                                {
                                    progressResponse.Header.UnknownHeaders.Add(header);
                                }
                            }

                            m_uasTransaction.SendInformationalResponse(progressResponse);
                        }
                    }
                }
                else
                {
                    Logger.Logger.Warn("SIPServerUserAgent Progress fired on already answered call.");
                }
            }
            catch (Exception excp)
            {
                Logger.Logger.Error("Exception SIPServerUserAgent Progress. ->" + excp.Message);
            }
        }
コード例 #45
0
 public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase)
 {
     Reject(failureStatus, reasonPhrase, null);
 }
コード例 #46
0
 public void Respond(SIPRequest sipRequest, SIPResponseStatusCodesEnum statusCode, string reason) {
     SIPResponse errorResponse = SIPTransport.GetResponse(sipRequest, statusCode, reason);
     m_sipTransport.SendResponse(m_outboundProxy, errorResponse);
 }
コード例 #47
0
 private void CallProgress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody, ISIPClientUserAgent uac)
 {
     SIPResponse progressResponse = new SIPResponse(progressStatus, reasonPhrase, null);
     CallRinging(this, progressResponse);
 }
コード例 #48
0
 /// <summary>
 /// Helper method for dynamic proxy runtime script.
 /// </summary>
 /// <param name="responseCode"></param>
 /// <param name="localEndPoint"></param>
 /// <param name="remoteEndPoint"></param>
 /// <param name="sipRequest"></param>
 public void Respond(SIPRequest sipRequest, SIPResponseStatusCodesEnum responseCode, string reasonPhrase)
 {
     SIPResponse response = SIPTransport.GetResponse(sipRequest, responseCode, reasonPhrase);
     m_sipTransport.SendResponse(response);
 }
コード例 #49
0
ファイル: SIPCDR.cs プロジェクト: sipsorcery/sipsorcery
        public void Progress(SIPResponseStatusCodesEnum progressStatus, string progressReason, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint)
        {
            InProgress = true;
            ProgressTime = DateTimeOffset.UtcNow;
            ProgressStatus = (int)progressStatus;
            ProgressReasonPhrase = progressReason;

            if (localEndPoint != null)
            {
                LocalSIPEndPoint = localEndPoint;
            }

            if (remoteEndPoint != null)
            {
                RemoteEndPoint = remoteEndPoint;
            }
        }
コード例 #50
0
        public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders,
                             string progressContentType, string progressBody)
        {
            try
            {
                if (!IsUASAnswered)
                {
                    if ((int)progressStatus >= 200)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer,
                                                                SIPMonitorEventTypesEnum.DialPlan,
                                                                "UAS call was passed an invalid response status of " + (int)progressStatus + ", ignoring.",
                                                                m_owner));
                    }
                    else
                    {
                        UASStateChanged?.Invoke(this, progressStatus, reasonPhrase);

                        // Allow all Trying responses through as some may contain additional useful information on the call state for the caller.
                        // Also if the response is a 183 Session Progress with audio forward it.
                        if (m_uasTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding &&
                            progressStatus != SIPResponseStatusCodesEnum.Trying &&
                            !(progressStatus == SIPResponseStatusCodesEnum.SessionProgress && progressBody != null))
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer,
                                                                    SIPMonitorEventTypesEnum.DialPlan,
                                                                    "UAS call ignoring progress response with status of " + (int)progressStatus +
                                                                    " as already in " + m_uasTransaction.TransactionState + ".", m_owner));
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer,
                                                                    SIPMonitorEventTypesEnum.DialPlan, "UAS call progressing with " + progressStatus + ".",
                                                                    m_owner));
                            SIPResponse progressResponse = SIPResponse.GetResponse(m_uasTransaction.TransactionRequest,
                                                                                   progressStatus, reasonPhrase);

                            if (progressResponse.Status != SIPResponseStatusCodesEnum.Trying)
                            {
                                progressResponse.Header.To.ToTag = m_uasTransaction.LocalTag;
                            }

                            if (!progressBody.IsNullOrBlank())
                            {
                                progressResponse.Body = progressBody;
                                progressResponse.Header.ContentType   = progressContentType;
                                progressResponse.Header.ContentLength = progressBody.Length;
                            }

                            if (customHeaders != null && customHeaders.Length > 0)
                            {
                                foreach (string header in customHeaders)
                                {
                                    progressResponse.Header.UnknownHeaders.Add(header);
                                }
                            }

                            m_uasTransaction.SendProvisionalResponse(progressResponse);
                        }
                    }
                }
                else
                {
                    logger.LogWarning("SIPServerUserAgent Progress fired on already answered call.");
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPServerUserAgent Progress. " + excp.Message);
            }
        }
コード例 #51
0
ファイル: SIPTransport.cs プロジェクト: sipsorcery/sipsorcery
        public static SIPResponse GetResponse(SIPRequest sipRequest, SIPResponseStatusCodesEnum responseCode, string reasonPhrase)
        {
            try
            {
                SIPResponse response = new SIPResponse(responseCode, reasonPhrase, sipRequest.LocalSIPEndPoint);

                if (reasonPhrase != null)
                {
                    response.ReasonPhrase = reasonPhrase;
                }

                SIPHeader requestHeader = sipRequest.Header;
                SIPFromHeader from = (requestHeader == null || requestHeader.From != null) ? requestHeader.From : new SIPFromHeader(null, new SIPURI(sipRequest.URI.Scheme, sipRequest.LocalSIPEndPoint), null);
                SIPToHeader to = (requestHeader == null || requestHeader.To != null) ? requestHeader.To : new SIPToHeader(null, new SIPURI(sipRequest.URI.Scheme, sipRequest.LocalSIPEndPoint), null);
                int cSeq = (requestHeader == null || requestHeader.CSeq != -1) ? requestHeader.CSeq : 1;
                string callId = (requestHeader == null || requestHeader.CallId != null) ? requestHeader.CallId : CallProperties.CreateNewCallId();

                response.Header = new SIPHeader(from, to, cSeq, callId);
                response.Header.CSeqMethod = (requestHeader != null) ? requestHeader.CSeqMethod : SIPMethodsEnum.NONE;

                if (requestHeader == null || requestHeader.Vias == null || requestHeader.Vias.Length == 0)
                {
                    response.Header.Vias.PushViaHeader(new SIPViaHeader(sipRequest.RemoteSIPEndPoint, CallProperties.CreateBranchId()));
                }
                else
                {
                    response.Header.Vias = requestHeader.Vias;
                }

                response.Header.MaxForwards = Int32.MinValue;
                response.Header.Allow = ALLOWED_SIP_METHODS;

                return response;
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTransport GetResponse. " + excp.Message);
                throw excp;
            }
        }
コード例 #52
0
 public SIPValidationException(SIPValidationFieldsEnum sipErrorField, string message)
     : base(message)
 {
     SIPErrorField = sipErrorField;
     SIPResponseErrorCode = SIPResponseStatusCodesEnum.BadRequest;
 }
コード例 #53
0
 public void AnswerNonInvite(SIPResponseStatusCodesEnum answerStatus, string reasonPhrase, string[] customHeaders, string contentType, string body)
 {
     throw new NotImplementedException();
 }
コード例 #54
0
 public SIPValidationException(SIPValidationFieldsEnum sipErrorField, SIPResponseStatusCodesEnum responseErrorCode, string message)
     : base(message)
 {
     SIPErrorField = sipErrorField;
     SIPResponseErrorCode = responseErrorCode;
 }
コード例 #55
0
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     try
     {
         if (m_uasTransaction.TransactionFinalResponse == null)
         {
             SIPResponse redirectResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, redirectCode, null);
             redirectResponse.Header.Contact = SIPContactHeader.CreateSIPContactList(redirectURI);
             m_uasTransaction.SendFinalResponse(redirectResponse);
         }
     }
     catch (Exception excp)
     {
         logger.Error("Exception SIPServerUserAgent Redirect. " + excp.Message);
     }
 }
コード例 #56
0
        private SIPResponse GetResponse(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponseStatusCodesEnum responseCode, string reasonPhrase, SIPRequest request)
        {
            try
            {
                SIPResponse    response  = new SIPResponse(responseCode, reasonPhrase, localSIPEndPoint);
                SIPSchemesEnum sipScheme = (localSIPEndPoint.Protocol == SIPProtocolsEnum.tls) ? SIPSchemesEnum.sips : SIPSchemesEnum.sip;
                SIPFromHeader  from      = request.Header.From;
                from.FromTag = request.Header.From.FromTag;
                SIPToHeader to = request.Header.To;
                response.Header = new SIPHeader(from, to, request.Header.CSeq, request.Header.CallId)
                {
                    CSeqMethod = request.Header.CSeqMethod,
                    Vias       = request.Header.Vias,
                    UserAgent  = SIPConstants.SIP_USERAGENT_STRING,
                    CSeq       = request.Header.CSeq
                };

                if (response.Header.To.ToTag == null || request.Header.To.ToTag.Trim().Length == 0)
                {
                    response.Header.To.ToTag = CallProperties.CreateNewTag();
                }

                return(response);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTransport GetResponse. " + excp.Message);
                throw;
            }
        }
コード例 #57
0
ファイル: ForkCall.cs プロジェクト: sipsorcery/sipsorcery
 /// <summary>
 /// Starts a call based on multiple forking call legs. As each call leg fails the next leg is popped off the queue and attempted.
 /// </summary>
 /// <param name="callsQueue"></param>
 public void Start(Queue<List<SIPCallDescriptor>> callsQueue)
 {
     if (callsQueue == null || callsQueue.Count == 0)
     {
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "No callable destinations were provided in Dial command, returning.", m_username));
         m_lastFailureStatus = SIPResponseStatusCodesEnum.InternalServerError;
         m_lastFailureReason = "Call list was empty";
         CallLegCompleted();
     }
     else
     {
         m_priorityCallsQueue = callsQueue;
         List<SIPCallDescriptor> calls = m_priorityCallsQueue.Dequeue();
         Start(calls);
     }
 }
コード例 #58
0
ファイル: SIPB2BUserAgent.cs プロジェクト: salihy/sipsorcery
 public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
 {
     logger.LogDebug("SIPB2BUserAgent Redirect.");
     //m_uas.Redirect(redirectCode, redirectURI);
 }
コード例 #59
0
ファイル: ForkCall.cs プロジェクト: sipsorcery/sipsorcery
        /*private void UACCallTrying(ISIPClientUserAgent uac, SIPResponse sipResponse)
        {
            try
            {
                // Test for the custom multiple redirect response.
                if (sipResponse.Status == SIPResponseStatusCodesEnum.MultipleRedirect)
                {
                    ProcessRedirect(uac, sipResponse);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception ForkCall UACCallTrying. " + excp.Message);
            }
        }*/
        /// <summary>
        /// This event occurs if it was not possible to initiate a call to the destination specified in the forwarded call. An example
        /// would be an unresolvable hostname in the destination URI.
        /// </summary>
        /// <param name="sipSwitchCall"></param>
        /// <param name="errorMessage"></param>
        private void UACCallFailed(ISIPClientUserAgent uac, string errorMessage)
        {
            lock (m_switchCalls)
            {
                m_switchCalls.Remove(uac);
            }

            m_lastFailureStatus = SIPResponseStatusCodesEnum.TemporarilyUnavailable;
            m_lastFailureReason = errorMessage;

            if (m_switchCallTransactions != null && uac.ServerTransaction != null)
            {
                m_switchCallTransactions.Add(uac.ServerTransaction);
            }

            uac.CallAnswered -= UACCallAnswered;
            uac.CallFailed -= UACCallFailed;
            uac.CallRinging -= UACCallProgress;

            CallLegCompleted();
        }
コード例 #60
0
ファイル: ForkCall.cs プロジェクト: vishalishere/sipsorcery
        private void UACCallAnswered(ISIPClientUserAgent answeredUAC, SIPResponse answeredResponse)
        {
            try
            {
                // Remove the current call from the pending list.
                lock (m_switchCalls)
                {
                    m_switchCalls.Remove(answeredUAC);
                }

                if (m_switchCallTransactions != null && answeredUAC.ServerTransaction != null)
                {
                    m_switchCallTransactions.Add(answeredUAC.ServerTransaction);
                }

                if (answeredResponse != null && answeredResponse.StatusCode >= 200 && answeredResponse.StatusCode <= 299)
                {
                    #region 2xx final response.

                    if (!m_callAnswered && !m_commandCancelled)
                    {
                        // This is the first call we've got an answer on.
                        m_callAnswered      = true;
                        m_answeredUAC       = answeredUAC;
                        AnsweredSIPResponse = answeredResponse;

                        SIPDialogueTransferModesEnum uasTransferMode = SIPDialogueTransferModesEnum.Default;
                        if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.NotAllowed)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                            uasTransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                        }
                        else if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.BlindPlaceCall)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.BlindPlaceCall;
                            uasTransferMode = SIPDialogueTransferModesEnum.BlindPlaceCall;
                        }
                        else if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.PassThru)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.PassThru;
                            uasTransferMode = SIPDialogueTransferModesEnum.PassThru;
                        }

                        /*else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Caller)
                         * {
                         *  answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                         *  uasTransferMode = SIPDialogueTransferModesEnum.Allowed;
                         * }
                         * else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Callee)
                         * {
                         *  answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.Allowed;
                         *  uasTransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                         * }
                         * else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Both)
                         * {
                         *  answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.Allowed;
                         *  uasTransferMode = SIPDialogueTransferModesEnum.Allowed;
                         * }*/

                        if (CallAnswered != null)
                        {
                            logger.Debug("Transfer mode=" + m_answeredUAC.CallDescriptor.TransferMode + ".");
                            CallAnswered(answeredResponse.Status, answeredResponse.ReasonPhrase, null, null, answeredResponse.Header.ContentType, answeredResponse.Body, answeredUAC.SIPDialogue, uasTransferMode);
                        }

                        // Cancel/hangup and other calls on this leg that are still around.
                        CancelNotRequiredCallLegs(CallCancelCause.NormalClearing);
                    }
                    else
                    {
                        // Call already answered or cancelled, hangup (send BYE).
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg " + answeredUAC.CallDescriptor.Uri + " answered but call was already answered or cancelled, hanging up.", m_username));
                        SIPDialogue sipDialogue = new SIPDialogue(answeredUAC.ServerTransaction, m_username, m_adminMemberId);
                        sipDialogue.Hangup(m_sipTransport, m_outboundProxySocket);
                    }

                    #endregion

                    CallLegCompleted();
                }
                else if (answeredUAC.SIPDialogue != null)
                {
                    // Google Voice calls create the dialogue without using a SIP response.
                    if (!m_callAnswered && !m_commandCancelled)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg for Google Voice call to " + answeredUAC.CallDescriptor.Uri + " answered.", m_username));

                        // This is the first call we've got an answer on.
                        m_callAnswered = true;
                        m_answeredUAC  = answeredUAC;

                        if (CallAnswered != null)
                        {
                            CallAnswered(SIPResponseStatusCodesEnum.Ok, null, null, null, answeredUAC.SIPDialogue.ContentType, answeredUAC.SIPDialogue.RemoteSDP, answeredUAC.SIPDialogue, SIPDialogueTransferModesEnum.NotAllowed);
                        }

                        // Cancel/hangup and other calls on this leg that are still around.
                        CancelNotRequiredCallLegs(CallCancelCause.NormalClearing);
                    }
                    else
                    {
                        // Call already answered or cancelled, hangup (send BYE).
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg for Google Voice call to " + answeredUAC.CallDescriptor.Uri + " answered but call was already answered or cancelled, hanging up.", m_username));
                        answeredUAC.SIPDialogue.Hangup(m_sipTransport, m_outboundProxySocket);
                    }
                }
                else if (answeredResponse != null && answeredResponse.StatusCode >= 300 && answeredResponse.StatusCode <= 399)
                {
                    ProcessRedirect(answeredUAC, answeredResponse);
                }
                else if (answeredResponse != null)
                {
                    // This call leg failed, record the failure status and reason.
                    m_lastFailureStatus = answeredResponse.Status;
                    m_lastFailureReason = answeredResponse.ReasonPhrase;

                    if (m_switchCallTransactions != null && answeredUAC.ServerTransaction != null)
                    {
                        m_switchCallTransactions.Add(answeredUAC.ServerTransaction);
                    }

                    CallLegCompleted();
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception ForkCall UACCallAnswered. " + excp);
            }
        }