private void UACInviteTransaction_TransactionFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                // BranchId for 2xx responses needs to be a new one, non-2xx final responses use same one as original request.
                if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode < 299)
                {
                    if (_sendOkAckManually == false)
                    {
                        Send2xxAckRequest(null, null);
                    }
                }
                else
                {
                    // ACK for non 2xx response is part of the INVITE transaction and gets routed to the same endpoint as the INVITE.
                    var ackRequest = GetInTransactionACKRequest(sipResponse, m_transactionRequest.URI, LocalSIPEndPoint);
                    base.SendRequest(RemoteEndPoint, ackRequest);
                }

                UACInviteTransactionFinalResponseReceived?.Invoke(localSIPEndPoint, remoteEndPoint, sipTransaction, sipResponse);

                if (CDR != null)
                {
                    SIPEndPoint localEP  = SIPEndPoint.TryParse(sipResponse.Header.ProxyReceivedOn) ?? localSIPEndPoint;
                    SIPEndPoint remoteEP = SIPEndPoint.TryParse(sipResponse.Header.ProxyReceivedFrom) ?? remoteEndPoint;
                    CDR.Answered(sipResponse.StatusCode, sipResponse.Status, sipResponse.ReasonPhrase, localEP, remoteEP);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception UACInviteTransaction_TransactionFinalResponseReceived. " + excp.Message);
            }
        }
        /// <param name="sendOkAckManually">If set an ACK request for the 2xx response will NOT be sent and it will be up to the application to explicitly call the SendACK request.</param>
        internal UACInviteTransaction(SIPTransport sipTransport, SIPRequest sipRequest, SIPEndPoint dstEndPoint, SIPEndPoint localSIPEndPoint, SIPEndPoint outboundProxy, bool sendOkAckManually = false)
            : base(sipTransport, sipRequest, dstEndPoint, localSIPEndPoint, outboundProxy)
        {
            TransactionType = SIPTransactionTypesEnum.Invite;
            m_localTag      = sipRequest.Header.From.FromTag;
            SIPEndPoint localEP = SIPEndPoint.TryParse(sipRequest.Header.ProxySendFrom) ?? localSIPEndPoint;

            CDR = new SIPCDR(SIPCallDirection.Out, sipRequest.URI, sipRequest.Header.From, sipRequest.Header.CallId, localEP, dstEndPoint);
            _sendOkAckManually = sendOkAckManually;

            TransactionFinalResponseReceived       += UACInviteTransaction_TransactionFinalResponseReceived;
            TransactionInformationResponseReceived += UACInviteTransaction_TransactionInformationResponseReceived;
            TransactionTimedOut        += UACInviteTransaction_TransactionTimedOut;
            TransactionRequestReceived += UACInviteTransaction_TransactionRequestReceived;
            TransactionRemoved         += UACInviteTransaction_TransactionRemoved;
        }
        private void UACInviteTransaction_TransactionInformationResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                UACInviteTransactionInformationResponseReceived?.Invoke(localSIPEndPoint, remoteEndPoint, sipTransaction, sipResponse);

                if (CDR != null)
                {
                    SIPEndPoint localEP  = SIPEndPoint.TryParse(sipResponse.Header.ProxyReceivedOn) ?? localSIPEndPoint;
                    SIPEndPoint remoteEP = SIPEndPoint.TryParse(sipResponse.Header.ProxyReceivedFrom) ?? remoteEndPoint;
                    CDR.Progress(sipResponse.Status, sipResponse.ReasonPhrase, localEP, remoteEP);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception UACInviteTransaction_TransactionInformationResponseReceived. " + excp.Message);
            }
        }
        public UASInviteTransaction(
            SIPTransport sipTransport,
            SIPRequest sipRequest,
            SIPEndPoint dstEndPoint,
            SIPEndPoint localSIPEndPoint,
            SIPEndPoint outboundProxy,
            IPAddress contactIPAddress,
            bool noCDR = false)
            : base(sipTransport, sipRequest, dstEndPoint, localSIPEndPoint, outboundProxy)
        {
            TransactionType    = SIPTransactionTypesEnum.Invite;
            m_remoteTag        = sipRequest.Header.From.FromTag;
            m_contactIPAddress = contactIPAddress;

            if (sipRequest.Header.To.ToTag == null)
            {
                // This UAS needs to set the To Tag.
                m_localTag = CallProperties.CreateNewTag();
            }
            else
            {
                // This is a re-INVITE.
                m_localTag = sipRequest.Header.To.ToTag;
            }

            //logger.Debug("New UASTransaction (" + TransactionId + ") for " + TransactionRequest.URI.ToString() + " to " + RemoteEndPoint + ".");
            SIPEndPoint localEP  = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedOn) ?? localSIPEndPoint;
            SIPEndPoint remoteEP = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedFrom) ?? dstEndPoint;

            if (!noCDR)
            {
                CDR = new SIPCDR(SIPCallDirection.In, sipRequest.URI, sipRequest.Header.From, sipRequest.Header.CallId,
                                 localEP, remoteEP);
            }

            //UpdateTransactionState(SIPTransactionStatesEnum.Proceeding);

            TransactionRequestReceived             += UASInviteTransaction_TransactionRequestReceived;
            TransactionInformationResponseReceived += UASInviteTransaction_TransactionResponseReceived;
            TransactionFinalResponseReceived       += UASInviteTransaction_TransactionResponseReceived;
            TransactionTimedOut += UASInviteTransaction_TransactionTimedOut;
            TransactionRemoved  += UASInviteTransaction_TransactionRemoved;
        }
        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 + "->" +
                                         registerTransaction.TransactionRequest.ToString();
                Logger.Logger.Error(regErrorMessage);

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

                return(RegisterResultEnum.Error);
            }
        }
Exemplo n.º 6
0
        private RegisterResultEnum Register(SIPNonInviteTransaction registerTransaction)
        {
            try
            {
                SIPRequest  sipRequest      = registerTransaction.TransactionRequest;
                SIPURI      registerURI     = sipRequest.URI;
                SIPToHeader toHeader        = sipRequest.Header.To;
                string      toUser          = toHeader.ToURI.User;
                string      canonicalDomain = m_sipDomainManager.GetCanonicalDomain(toHeader.ToURI.HostAddress);
                int         requestedExpiry = GetRequestedExpiry(sipRequest);

                if (canonicalDomain == null)
                {
                    Logger.LogWarning($"Register request for {toHeader.ToURI.HostAddress} rejected as no matching domain found.");
                    SIPResponse noDomainResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced");
                    registerTransaction.SendResponse(noDomainResponse);
                    return(RegisterResultEnum.DomainNotServiced);
                }
                else
                {
                    SIPAccount sipAccount = m_sipAccountsDataLayer.GetSIPAccount(toUser, canonicalDomain).Result;

                    if (sipAccount == null)
                    {
                        Logger.LogWarning($"RegistrarCore SIP account {toUser}@{canonicalDomain} does not exist.");
                        SIPResponse forbiddenResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, null);
                        registerTransaction.SendResponse(forbiddenResponse);
                        return(RegisterResultEnum.Forbidden);
                    }
                    else
                    {
                        SIPRequestAuthenticationResult authenticationResult = SIPRequestAuthenticator.AuthenticateSIPRequest(
                            registerTransaction.TransactionRequest.LocalSIPEndPoint,
                            registerTransaction.TransactionRequest.RemoteSIPEndPoint,
                            sipRequest,
                            sipAccount.ToSIPAccountModel());

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

                            if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                            {
                                Logger.LogWarning($"Forbidden {sipAccount.AOR} does not exist, {sipRequest.Header.ProxyReceivedFrom}, {sipRequest.Header.UserAgent}.");
                                return(RegisterResultEnum.Forbidden);
                            }
                            else
                            {
                                return(RegisterResultEnum.AuthenticationRequired);
                            }
                        }
                        else
                        {
                            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(sipAccount.ID);
                                List <SIPRegistrarBinding> bindings = m_sipRegistrarBindingDataLayer.GetForSIPAccount(new Guid(sipAccount.ID)).ToList();
                                //List<SIPContactHeader> contactsList = m_registrarBindingsManager.GetContactHeader(); // registration.GetContactHeader(true, null);
                                if (bindings != null)
                                {
                                    sipRequest.Header.Contact = GetContactHeader(bindings);
                                }

                                SIPResponse okResponse = GetOkResponse(sipRequest);
                                registerTransaction.SendResponse(okResponse);
                                Logger.LogDebug($"Empty registration request successful for {sipAccount.AOR} from {sipRequest.Header.ProxyReceivedFrom}.");
                            }
                            else
                            {
                                SIPEndPoint uacRemoteEndPoint = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedFrom) ?? registerTransaction.TransactionRequest.RemoteSIPEndPoint;
                                SIPEndPoint proxySIPEndPoint  = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedOn);
                                SIPEndPoint registrarEndPoint = registerTransaction.TransactionRequest.LocalSIPEndPoint;

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

                                DateTime startTime = DateTime.Now;

                                List <SIPRegistrarBinding> bindingsList = m_registrarBindingsManager.UpdateBindings(
                                    sipAccount,
                                    proxySIPEndPoint,
                                    uacRemoteEndPoint,
                                    registrarEndPoint,
                                    sipRequest.Header.Contact,
                                    sipRequest.Header.CallId,
                                    sipRequest.Header.CSeq,
                                    sipRequest.Header.Expires,
                                    sipRequest.Header.UserAgent,
                                    out updateResult,
                                    out updateMessage);

                                TimeSpan duration = DateTime.Now.Subtract(startTime);
                                Logger.LogDebug($"Binding update time for {sipAccount.AOR} took {duration.TotalMilliseconds}ms.");

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

                                    Logger.LogDebug($"Bindings for {sipAccount.AOR}:");
                                    for (int i = 0; i < bindingsList.Count(); i++)
                                    {
                                        var binding = bindingsList[i];
                                        Logger.LogDebug($" {i}: {binding.ContactURI}, expiry {binding.Expiry}s.");
                                    }

                                    sipRequest.Header.Contact = GetContactHeader(bindingsList);
                                    SIPResponse okResponse = GetOkResponse(sipRequest);
                                    registerTransaction.SendResponse(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.
                                    Logger.LogError($"Registration request successful but binding update failed for {sipAccount.AOR} from {registerTransaction.TransactionRequest.RemoteSIPEndPoint}.");
                                    sipRequest.Header.Contact[0].Expires = m_minimumBindingExpiry;
                                    SIPResponse okResponse = GetOkResponse(sipRequest);
                                    registerTransaction.SendResponse(okResponse);
                                }
                            }

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

                SIPResponse errorResponse = SIPResponse.GetResponse(registerTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                registerTransaction.SendResponse(errorResponse);

                return(RegisterResultEnum.Error);
            }
        }
        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);
            }
        }
Exemplo n.º 8
0
        /// <summary>
        ///  From RFC3261: Stateless Proxy Request Processing:
        ///
        ///  For each target, the proxy forwards the request following these
        ///   1.  Make a copy of the received request
        ///   2.  Update the Request-URI
        ///   3.  Update the Max-Forwards header field
        ///   4.  Optionally add a Record-route header field value
        ///   5.  Optionally add additional header fields
        ///   6.  Postprocess routing information
        ///   7.  Determine the next-hop address, port, and transport
        ///   8.  Add a Via header field value
        ///   9.  Add a Content-Length header field if necessary
        ///  10.  Forward the new request
        ///
        ///  See sections 12.2.1.1 and 16.12.1.2 in the SIP RFC for the best explanation on the way the Route header works.
        /// </summary>
        /// <param name="sipRequest"></param>
        /// <param name="inEndPoint">End point the request was received on.</param>
        /// <param name="sipChannel"></param>
        private void GotRequest(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest)
        {
            try
            {
                // Calculate the proxy branch parameter for this request. The branch parameter has to be calculated so that INVITE's and CANCEL's generate the same branchid.
                //string toTag = (sipRequest.Header.To != null) ? sipRequest.Header.To.ToTag : null;
                //string fromTag = (sipRequest.Header.From != null) ? sipRequest.Header.From.FromTag : null;
                string route = (sipRequest.Header.Routes != null) ? sipRequest.Header.Routes.ToString() : null;
                //string authHeader = (sipRequest.Header.AuthenticationHeader != null) ? sipRequest.Header.AuthenticationHeader.ToString() : null;
                string proxyBranch = CallProperties.CreateBranchId(SIPConstants.SIP_BRANCH_MAGICCOOKIE, null, null, sipRequest.Header.CallId, sipRequest.URI.ToString(), null, sipRequest.Header.CSeq, route, null, null);

                // Check whether the branch parameter already exists in the Via list. One instance of an already added Via header will be allowed to support a single spiral.
                int loopedViaCount = 0;
                foreach (SIPViaHeader viaHeader in sipRequest.Header.Vias.Via)
                {
                    //if (viaHeader.Branch == proxyBranch)
                    SIPEndPoint sentFromEndPoint = SIPEndPoint.TryParse(viaHeader.Transport + ":" + viaHeader.ContactAddress);
                    if (sentFromEndPoint != null && m_sipTransport.IsLocalSIPEndPoint(sentFromEndPoint))
                    {
                        loopedViaCount++;
                    }

                    if (loopedViaCount >= 2)
                    {
                        SendMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.SIPProxy, SIPMonitorEventTypesEnum.Warn, "Loop detected on request from " + remoteEndPoint + " to " + sipRequest.URI.ToString() + ".", null));
                        m_sipTransport.SendResponse(SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.LoopDetected, null));
                        return;
                    }
                }

                // Used in the proxy monitor messages only, plays no part in request routing.
                string fromUser   = (sipRequest.Header.From != null) ? sipRequest.Header.From.FromURI.User : null;
                string toUser     = (sipRequest.Header.To != null) ? sipRequest.Header.To.ToURI.User : null;
                string summaryStr = "req " + sipRequest.Method + " from=" + fromUser + ", to=" + toUser + ", " + remoteEndPoint.ToString();

                bool isFromAppServer = (m_sipCallDispatcherFile != null) ? m_sipCallDispatcherFile.IsAppServerEndPoint(remoteEndPoint) : false;

                lock (this)
                {
                    m_compiledScript.DefaultScope.RemoveVariable("sys");
                    m_compiledScript.DefaultScope.RemoveVariable("localEndPoint");
                    m_compiledScript.DefaultScope.RemoveVariable("isreq");
                    m_compiledScript.DefaultScope.RemoveVariable("req");
                    m_compiledScript.DefaultScope.RemoveVariable("remoteEndPoint");
                    m_compiledScript.DefaultScope.RemoveVariable("summary");
                    m_compiledScript.DefaultScope.RemoveVariable("proxyBranch");
                    m_compiledScript.DefaultScope.RemoveVariable("sipMethod");
                    m_compiledScript.DefaultScope.RemoveVariable("publicip");
                    m_compiledScript.DefaultScope.RemoveVariable("IsFromAppServer");

                    m_compiledScript.DefaultScope.SetVariable("sys", m_proxyScriptFacade);
                    m_compiledScript.DefaultScope.SetVariable("localEndPoint", localSIPEndPoint);
                    m_compiledScript.DefaultScope.SetVariable("isreq", true);
                    m_compiledScript.DefaultScope.SetVariable("req", sipRequest);
                    m_compiledScript.DefaultScope.SetVariable("remoteEndPoint", remoteEndPoint);
                    m_compiledScript.DefaultScope.SetVariable("summary", summaryStr);
                    m_compiledScript.DefaultScope.SetVariable("proxyBranch", proxyBranch);
                    m_compiledScript.DefaultScope.SetVariable("sipMethod", sipRequest.Method.ToString());
                    m_compiledScript.DefaultScope.SetVariable("publicip", PublicIPAddress);
                    m_compiledScript.DefaultScope.SetVariable("IsFromAppServer", isFromAppServer);

                    m_compiledScript.Execute();
                }

                //if (requestStopwatch.ElapsedMilliseconds > 20)
                //{
                //    logger.Debug("GotRequest processing time=" + requestStopwatch.ElapsedMilliseconds + "ms, script time=" + scriptStopwatch.ElapsedMilliseconds + "ms.");
                //}
            }
            catch (SIPValidationException)
            {
                throw;
            }
            catch (Exception excp)
            {
                string remoteEndPointStr = (remoteEndPoint != null) ? remoteEndPoint.ToString() : null;
                string reqExcpError      = "Exception SIPProxyCore GotRequest (from " + remoteEndPointStr + "). " + excp.Message;
                logger.Error(reqExcpError);
                SIPMonitorEvent reqExcpEvent = new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.SIPProxy, SIPMonitorEventTypesEnum.Error, reqExcpError, localSIPEndPoint, remoteEndPoint, null);
                SendMonitorEvent(reqExcpEvent);

                throw excp;
            }
        }