public SIPNonInviteServerUserAgent(
            SIPTransport sipTransport,
            SIPEndPoint outboundProxy,
            string sipUsername,
            string sipDomain,
            SIPCallDirection callDirection,
            SIPAssetGetDelegate<SIPAccount> getSIPAccount,
            SIPAuthenticateRequestDelegate sipAuthenticateRequest,
            SIPMonitorLogDelegate logDelegate,
            SIPNonInviteTransaction transaction)
        {
            m_sipTransport = sipTransport;
            m_outboundProxy = outboundProxy;
            m_sipUsername = sipUsername;
            m_sipDomain = sipDomain;
            m_sipCallDirection = callDirection;
            GetSIPAccount_External = getSIPAccount;
            SIPAuthenticateRequest_External = sipAuthenticateRequest;
            Log_External = logDelegate ?? Log_External;
            m_transaction = transaction;

            m_transaction.TransactionTraceMessage += TransactionTraceMessage;
            //m_uasTransaction.UASInviteTransactionTimedOut += ClientTimedOut;
            //m_uasTransaction.UASInviteTransactionCancelled += UASTransactionCancelled;
            //m_uasTransaction.TransactionRemoved += new SIPTransactionRemovedDelegate(UASTransaction_TransactionRemoved);
            //m_uasTransaction.TransactionStateChanged += (t) => { logger.Debug("Transaction state change to " + t.TransactionState + ", uri=" + t.TransactionRequestURI.ToString() + "."); };
        }
Example #2
0
        private void ByeServerFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentServer, SIPMonitorEventTypesEnum.DialPlan, "Response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " + sipTransaction.TransactionRequest.URI.ToString() + ".", Owner));

                SIPNonInviteTransaction byeTransaction = sipTransaction as SIPNonInviteTransaction;
                byeTransaction.NonInviteTransactionFinalResponseReceived -= ByeServerFinalResponseReceived;

                if ((sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised) && SIPAccount != null)
                {
                    // Resend BYE with credentials.
                    SIPAuthorisationDigest authRequest = sipResponse.Header.AuthenticationHeader.SIPDigest;
                    SIPURI contactUri = sipResponse.Header.Contact.Any() ? sipResponse.Header.Contact[0].ContactURI : sipResponse.Header.From.FromURI;

                    authRequest.SetCredentials(SIPAccount.SIPUsername, SIPAccount.SIPPassword, contactUri.ToString(), SIPMethodsEnum.BYE.ToString());

                    SIPRequest authByeRequest = byeTransaction.TransactionRequest;
                    authByeRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authRequest);
                    authByeRequest.Header.AuthenticationHeader.SIPDigest.Response = authRequest.Digest;
                    authByeRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId();
                    authByeRequest.Header.CSeq = authByeRequest.Header.CSeq + 1;

                    SIPNonInviteTransaction bTransaction = m_sipTransport.CreateNonInviteTransaction(authByeRequest, null);
                    bTransaction.SendReliableRequest();
                }
            }
            catch (Exception excp)
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.Error, "Exception ByServerFinalResponseReceived. " + excp.Message, Owner));
            }
        }
        public SIPReferServerUserAgent(SIPTransport sipTransport, SIPMonitorLogDelegate logDelegate, SIPNonInviteTransaction sipTransaction)
        {
            m_sipTransport = sipTransport;
            Log_External = logDelegate;
            m_sipTransaction = sipTransaction;

            m_sipTransaction.TransactionTraceMessage += TransactionTraceMessage;
            m_sipTransaction.NonInviteTransactionTimedOut += ClientTimedOut;

            // If external logging is not required assign an empty handler to stop null reference exceptions.
            if (Log_External == null)
            {
                Log_External = (e) => { };
            }

            var referTo = SIPURI.ParseSIPURI(m_sipTransaction.TransactionRequest.Header.ReferTo);
            var replacesParameter = SIPReplacesParameter.Parse(referTo.Headers.Get("Replaces"));

            ReplacedCall = new ReplacesCallDescriptor();
            ReplacedCall.CallId = replacesParameter.CallID;
            ReplacedCall.FromTag = replacesParameter.FromTag;
            ReplacedCall.ToTag = replacesParameter.ToTag;

            ReferToUri = referTo.CopyOf();
            ReferToUri.Headers.RemoveAll();
        }
Example #4
0
        /// <summary>
        /// Used to hangup the call or indicate that the client hungup.
        /// </summary>
        /// <param name="clientHungup">True if the BYE request was received from the client. False if the hangup
        /// needs to originate from this agent.</param>
        public void Hangup(bool clientHungup)
        {
            m_isHungup = true;

            if (SIPDialogue == null)
            {
                return;
            }

            // Only need to send a BYE request if the client didn't already do so.
            if (clientHungup == false)
            {
                try
                {
                    // Cases found where the Contact in the INVITE was to a different protocol than the oringinal request.
                    var inviteContact = m_uasTransaction.TransactionRequest.Header.Contact.FirstOrDefault();
                    if (inviteContact == null)
                    {
                        logger.LogWarning("The Contact header on the INVITE request was missing, BYE request cannot be generated.");
                    }
                    else
                    {
                        SIPRequest byeRequest = GetByeRequest();
                        SIPNonInviteTransaction byeTransaction = m_sipTransport.CreateNonInviteTransaction(byeRequest, m_outboundProxy);
                        byeTransaction.NonInviteTransactionFinalResponseReceived += ByeServerFinalResponseReceived;
                        byeTransaction.SendReliableRequest();
                    }
                }
                catch (Exception excp)
                {
                    logger.LogError("Exception SIPServerUserAgent Hangup. " + excp.Message);
                    throw;
                }
            }
        }
Example #5
0
        private void SendInitialRegister()
        {
            try
            {
                if (m_attempts >= MAX_REGISTER_ATTEMPTS)
                {
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.", m_owner));
                    m_isRegistered = false;
                    if (RegistrationTemporaryFailure != null)
                    {
                        RegistrationTemporaryFailure(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts.");
                    }
                    m_waitForRegistrationMRE.Set();
                }
                else
                {
                    m_attempts++;

                    SIPEndPoint registrarSIPEndPoint = m_outboundProxy;
                    if (registrarSIPEndPoint == null)
                    {
                        SIPDNSLookupResult lookupResult = m_sipTransport.GetHostEndPoint(m_registrarHost, false);
                        if (lookupResult.LookupError != null)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Could not resolve " + m_registrarHost + ", " + lookupResult.LookupError, m_owner));
                        }
                        else
                        {
                            registrarSIPEndPoint = lookupResult.GetSIPEndPoint();
                        }
                    }

                    if (registrarSIPEndPoint == null && RegistrationFailed != null)
                    {
                        RegistrationFailed(m_sipAccountAOR, "Could not resolve " + m_registrarHost + ".");
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Initiating registration to " + m_registrarHost + " at " + registrarSIPEndPoint.ToString() + " for " + m_sipAccountAOR.ToString() + ".", m_owner));
                        SIPRequest regRequest = GetRegistrationRequest(m_localEndPoint);

                        SIPNonInviteTransaction regTransaction = m_sipTransport.CreateNonInviteTransaction(regRequest, registrarSIPEndPoint, m_localEndPoint, m_outboundProxy);
                        // These handlers need to be on their own threads to take the processing off the SIP transport layer.
                        regTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { ServerResponseReceived(lep, rep, tn, rsp); }); };
                        regTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); };

                        m_sipTransport.SendSIPReliable(regTransaction);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message);
                if (RegistrationFailed != null)
                {
                    RegistrationFailed(m_sipAccountAOR, "Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message);
                }
            }
        }
        /// <summary>
        /// Cancels an in progress call. This method should be called prior to the remote user agent server answering the call.
        /// </summary>
        public void Cancel()
        {
            try
            {
                m_callCancelled = true;

                // Cancel server call.
                if (m_serverTransaction == null)
                {
                    logger.LogDebug("Cancelling forwarded call leg " + m_sipCallDescriptor.Uri + ", server transaction has not been created yet no CANCEL request required.");
                }
                else if (m_cancelTransaction != null)
                {
                    if (m_cancelTransaction.TransactionState != SIPTransactionStatesEnum.Completed)
                    {
                        logger.LogDebug("Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already been cancelled once, trying again.");
                        m_cancelTransaction.SendRequest();
                    }
                    else
                    {
                        logger.LogDebug("Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already responded to CANCEL, probably overlap in messages not re-sending.");
                    }
                }
                else //if (m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding || m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Trying)
                {
                    logger.LogDebug("Cancelling forwarded call leg, sending CANCEL to " + m_serverTransaction.TransactionRequest.URI.ToString() + ".");

                    // No response has been received from the server so no CANCEL request necessary, stop any retransmits of the INVITE.
                    m_serverTransaction.CancelCall();

                    SIPRequest cancelRequest = GetCancelRequest(m_serverTransaction.TransactionRequest);

                    // If auth header is included inside INVITE request, we re-include them inside CANCEL request
                    if (m_serverTransaction.TransactionRequest.Header.HasAuthenticationHeader)
                    {
                        string username = (m_sipCallDescriptor.AuthUsername == null || m_sipCallDescriptor.AuthUsername.Trim().Length <= 0 ? m_sipCallDescriptor.Username : m_sipCallDescriptor.AuthUsername);
                        SIPAuthorisationDigest authDigest = m_serverTransaction.TransactionRequest.Header.AuthenticationHeaders.First().SIPDigest;
                        authDigest.SetCredentials(username, m_sipCallDescriptor.Password, m_sipCallDescriptor.Uri, SIPMethodsEnum.CANCEL.ToString());

                        var authHeader = new SIPAuthenticationHeader(authDigest);
                        authHeader.SIPDigest.IncrementNonceCount();
                        authHeader.SIPDigest.Response = authDigest.GetDigest();

                        cancelRequest.Header.AuthenticationHeaders.Clear();
                        cancelRequest.Header.AuthenticationHeaders.Add(authHeader);
                    }

                    m_cancelTransaction = new SIPNonInviteTransaction(m_sipTransport, cancelRequest, m_outboundProxy);
                    m_cancelTransaction.SendRequest();
                }

                CallFailed?.Invoke(this, "Call cancelled by user.", null);
            }
            catch (Exception excp)
            {
                logger.LogError("Exception CancelServerCall. " + excp.Message);
            }
        }
Example #7
0
        public void ProcessInDialogueRequest(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest)
        {
            SIPDialogue dialogue = GetDialogue(sipRequest);

            if (dialogue == null)
            {
                SIPNonInviteTransaction nonInvTx = new SIPNonInviteTransaction(m_sipTransport, sipRequest, m_outboundProxy);
                var noLegResp = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist, null);
                nonInvTx.SendResponse(noLegResp);
            }
            else if (sipRequest.Method == SIPMethodsEnum.BYE)
            {
                SIPNonInviteTransaction byeTransaction = new SIPNonInviteTransaction(m_sipTransport, sipRequest, m_outboundProxy);
                //logger.Debug("Matching dialogue found for BYE request to " + sipRequest.URI.ToString() + ".");
                SIPResponse byeResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                byeTransaction.SendResponse(byeResponse);

                // Normal BYE request.
                CallHungup(dialogue, sipRequest.Header.Reason, false);
            }
            //else if (sipRequest.Method == SIPMethodsEnum.INVITE)
            //{
            //    UASInviteTransaction reInviteTransaction = new UASInviteTransaction(m_sipTransport, sipRequest, m_outboundProxy);
            //    SIPResponse tryingResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Trying, null);
            //    reInviteTransaction.SendProvisionalResponse(tryingResponse);
            //    reInviteTransaction.CDR = null;     // Don't want CDR's on re-INVITEs.
            //    ForwardInDialogueRequest(dialogue, reInviteTransaction, localSIPEndPoint, remoteEndPoint);
            //}
            else if (sipRequest.Method == SIPMethodsEnum.OPTIONS)
            {
                // Send back the remote SDP.
                logger.LogDebug("OPTIONS request for established dialogue " + dialogue.DialogueName + ".");
                SIPNonInviteTransaction optionsTransaction = new SIPNonInviteTransaction(m_sipTransport, sipRequest, m_outboundProxy);
                SIPResponse             okResponse         = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                okResponse.Body = dialogue.RemoteSDP;
                okResponse.Header.ContentLength = okResponse.Body.Length;
                okResponse.Header.ContentType   = m_sdpContentType;
                optionsTransaction.SendResponse(okResponse);
            }
            else if (sipRequest.Method == SIPMethodsEnum.MESSAGE)
            {
                logger.LogDebug("MESSAGE for call " + sipRequest.URI.ToString() + ": " + sipRequest.Body + ".");
                SIPNonInviteTransaction messageTransaction = new SIPNonInviteTransaction(m_sipTransport, sipRequest, m_outboundProxy);
                SIPResponse             okResponse         = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                messageTransaction.SendResponse(okResponse);
            }
            else
            {
                //// This is a request on an established call forward through to the opposite dialogue.
                //SIPNonInviteTransaction passThruTransaction = new SIPNonInviteTransaction(m_sipTransport, sipRequest, m_outboundProxy);
                //ForwardInDialogueRequest(dialogue, passThruTransaction, localSIPEndPoint, remoteEndPoint);
                logger.LogDebug($"{sipRequest.Method} received for dialogue {sipRequest.URI}, processing not yet implemented TODO!.");

                SIPNonInviteTransaction nonInvTx = new SIPNonInviteTransaction(m_sipTransport, sipRequest, m_outboundProxy);
                var noLegResp = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist, null);
                nonInvTx.SendResponse(noLegResp);
            }
        }
Example #8
0
        private void SendInitialRegister()
        {
            try
            {
                if (m_attempts >= m_maxRegisterAttempts)
                {
                    logger.LogWarning("Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.");
                    m_isRegistered = false;
                    RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts.");
                    m_waitForRegistrationMRE.Set();
                }
                else
                {
                    m_attempts++;

                    SIPEndPoint registrarSIPEndPoint = m_outboundProxy;
                    if (registrarSIPEndPoint == null)
                    {
                        //SIPDNSLookupResult lookupResult = m_sipTransport.GetHostEndPoint(m_registrarHost, false);
                        SIPURI uri          = SIPURI.ParseSIPURIRelaxed(m_registrarHost);
                        var    lookupResult = m_sipTransport.ResolveSIPUriAsync(uri).ConfigureAwait(false).GetAwaiter().GetResult();
                        if (lookupResult == null)
                        {
                            logger.LogWarning("Could not resolve " + m_registrarHost + ".");
                        }
                        else
                        {
                            registrarSIPEndPoint = lookupResult;
                        }
                    }

                    if (registrarSIPEndPoint == null)
                    {
                        logger.LogWarning("SIPRegistrationAgent could not resolve " + m_registrarHost + ".");

                        RegistrationFailed?.Invoke(m_sipAccountAOR, "Could not resolve " + m_registrarHost + ".");
                    }
                    else
                    {
                        logger.LogDebug("Initiating registration to " + m_registrarHost + " at " + registrarSIPEndPoint.ToString() + " for " + m_sipAccountAOR.ToString() + ".");
                        SIPRequest regRequest = GetRegistrationRequest();

                        SIPNonInviteTransaction regTransaction = new SIPNonInviteTransaction(m_sipTransport, regRequest, registrarSIPEndPoint);
                        // These handlers need to be on their own threads to take the processing off the SIP transport layer.
                        regTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { ServerResponseReceived(lep, rep, tn, rsp); }); return(Task.FromResult(SocketError.Success)); };
                        regTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); };

                        m_sipTransport.SendTransaction(regTransaction);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message);
                RegistrationFailed?.Invoke(m_sipAccountAOR, "Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message);
            }
        }
        private void DoSubscribe(SIPNonInviteTransaction subTx)
        {
            SIPRequest req    = subTx.TransactionRequest;
            string     user   = req.Header.From.FromURI.User;
            string     domain = req.Header.From.FromURI.HostAddress;

            string canonicalDomain = m_sipDomainManager.GetCanonicalDomain(domain);

            if (canonicalDomain == null)
            {
                Logger.LogWarning($"Subscribe Register request for {req.Header.From.FromURI.Host} rejected as no matching domain found.");
                SIPResponse noDomainResponse = SIPResponse.GetResponse(req, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced");
                subTx.SendResponse(noDomainResponse);
            }
            else
            {
                SIPAccount sipAccount = m_sipAccountsDataLayer.GetSIPAccount(user, canonicalDomain).Result;

                if (sipAccount == null)
                {
                    Logger.LogWarning($"SubscriberCore SIP account {user}@{canonicalDomain} does not exist.");
                    SIPResponse forbiddenResponse = SIPResponse.GetResponse(req, SIPResponseStatusCodesEnum.Forbidden, null);
                    subTx.SendResponse(forbiddenResponse);
                }
                else
                {
                    SIPRequestAuthenticationResult authenticationResult = SIPRequestAuthenticator.AuthenticateSIPRequest(req.LocalSIPEndPoint, req.RemoteSIPEndPoint, req, sipAccount);

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

                        if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                        {
                            Logger.LogWarning($"Forbidden {sipAccount.AOR} does not exist, received from {req.RemoteSIPEndPoint}, user agent {req.Header.UserAgent}.");
                        }
                    }
                    else
                    {
                        SIPResponse okResponse = SIPResponse.GetResponse(req, SIPResponseStatusCodesEnum.Ok, null);
                        subTx.SendResponse(okResponse);
                        Logger.LogDebug($"Subscription request for {user}@{domain} was successful.");

                        // Give the subscribe response time to be sent.
                        Thread.Sleep(500);

                        if (req.Header.Expires > 0)
                        {
                            SendInitialNotification(req, sipAccount);
                        }
                    }
                }
            }
        }
        private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint,
                                            SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank())
                    ? sipResponse.Status.ToString()
                    : sipResponse.ReasonPhrase;

                if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired ||
                    sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    if (sipResponse.Header.AuthenticationHeader != null)
                    {
                        if ((m_callDescriptor.Username != null || m_callDescriptor.AuthUsername != null) &&
                            m_callDescriptor.Password != null)
                        {
                            SIPRequest authenticatedRequest =
                                GetAuthenticatedRequest(sipTransaction.TransactionRequest, sipResponse);
                            SIPNonInviteTransaction authTransaction =
                                m_sipTransport.CreateNonInviteTransaction(authenticatedRequest,
                                                                          sipTransaction.RemoteEndPoint, localSIPEndPoint, m_outboundProxy);
                            authTransaction.NonInviteTransactionFinalResponseReceived += AuthResponseReceived;
                            authTransaction.NonInviteTransactionTimedOut += RequestTimedOut;
                            m_sipTransport.SendSIPReliable(authTransaction);
                        }
                        else
                        {
                            if (ResponseReceived != null)
                            {
                                ResponseReceived(sipResponse);
                            }
                        }
                    }
                    else
                    {
                        if (ResponseReceived != null)
                        {
                            ResponseReceived(sipResponse);
                        }
                    }
                }
                else
                {
                    if (ResponseReceived != null)
                    {
                        ResponseReceived(sipResponse);
                    }
                }
            }
            catch (Exception excp)
            {
                Logger.Logger.Error("Exception SIPNonInviteClientUserAgent ServerResponseReceived (" + remoteEndPoint +
                                    "). ->" +
                                    excp.Message);
            }
        }
Example #11
0
        private void SendInitialRegister()
        {
            try
            {
                if (m_attempts >= m_maxRegisterAttempts)
                {
                    logger.LogWarning($"Registration to {m_sipAccountAOR} reached the maximum number of allowed attempts without a failure condition.");
                    m_isRegistered = false;
                    RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts.");
                    m_waitForRegistrationMRE.Set();
                }
                else
                {
                    m_attempts++;

                    SIPEndPoint registrarSIPEndPoint = m_outboundProxy;
                    if (registrarSIPEndPoint == null)
                    {
                        SIPURI uri          = SIPURI.ParseSIPURIRelaxed(m_registrarHost);
                        var    lookupResult = m_sipTransport.ResolveSIPUriAsync(uri).Result;
                        if (lookupResult == null || lookupResult == SIPEndPoint.Empty)
                        {
                            logger.LogWarning("Could not resolve " + m_registrarHost + " when sending initial registration request.");
                        }
                        else
                        {
                            registrarSIPEndPoint = lookupResult;
                        }
                    }

                    if (registrarSIPEndPoint == null)
                    {
                        logger.LogWarning("SIPRegistrationAgent could not resolve " + m_registrarHost + ".");

                        RegistrationFailed?.Invoke(m_sipAccountAOR, "Could not resolve " + m_registrarHost + ".");
                    }
                    else
                    {
                        logger.LogDebug("Initiating registration to " + m_registrarHost + " at " + registrarSIPEndPoint.ToString() + " for " + m_sipAccountAOR.ToString() + ".");
                        SIPRequest regRequest = GetRegistrationRequest();

                        SIPNonInviteTransaction regTransaction = new SIPNonInviteTransaction(m_sipTransport, regRequest, registrarSIPEndPoint);
                        regTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ServerResponseReceived(lep, rep, tn, rsp); return(Task.FromResult(SocketError.Success)); };
                        regTransaction.NonInviteTransactionTimedOut += RegistrationTimedOut;

                        m_sipTransport.SendTransaction(regTransaction);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message);
                RegistrationFailed?.Invoke(m_sipAccountAOR, "Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message);
            }
        }
Example #12
0
        public void ProcessRegisterRequest()
        {
            logger.Debug("SIPRegistrarCore is running at " + _localSipAccount.MsgProtocol + ":" + _localSipAccount.LocalIP + ":" + _localSipAccount.LocalPort);
            try
            {
                while (!Stop)
                {
                    if (m_registerQueue.Count > 0)
                    {
                        try
                        {
                            SIPNonInviteTransaction registrarTransaction = null;
                            lock (m_registerQueue)
                            {
                                registrarTransaction = m_registerQueue.Dequeue();
                            }

                            if (registrarTransaction != null)
                            {
                                DateTime startTime = DateTime.Now;
                                var      result    = Register(registrarTransaction);
                                var      duration  = DateTime.Now.Subtract(startTime);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "register result=" + result.ToString() + ", time=" + duration.TotalMilliseconds + "ms, user="******".", null));
                                RegisterComplete?.Invoke(duration.TotalMilliseconds, registrarTransaction.TransactionRequest.Header.AuthenticationHeader != null);

                                logger.Debug("Camera[" + registrarTransaction.RemoteEndPoint + "] have completed registering GB service.");
                                //CacheDeviceItem(registrarTransaction.TransactionRequest);

                                //device alarm subscribe
                                DeviceAlarmSubscribe?.Invoke(registrarTransaction);
                            }
                        }
                        catch (InvalidOperationException invalidOpExcp)
                        {
                            // This occurs when the queue is empty.
                            logger.Warn("InvalidOperationException ProcessRegisterRequest Register Job. " + invalidOpExcp.Message);
                        }
                        catch (Exception regExcp)
                        {
                            logger.Error("Exception ProcessRegisterRequest Register Job. " + regExcp.Message);
                        }
                    }
                    else
                    {
                        m_registerARE.WaitOne(MAX_PROCESS_REGISTER_SLEEP);
                    }
                }

                logger.Warn("ProcessRegisterRequest thread " + Thread.CurrentThread.Name + " stopping.");
            }
            catch (Exception excp)
            {
                logger.Error("Exception ProcessRegisterRequest (" + Thread.CurrentThread.Name + "). " + excp.Message);
            }
        }
Example #13
0
        private Task <SocketError> ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
                logger.LogDebug("Server response " + sipResponse.StatusCode + " " + reasonPhrase + " received for " + sipTransaction.TransactionRequest.Method + " to " + m_callDescriptor.Uri + ".");

                if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    if (sipResponse.Header.AuthenticationHeader != null)
                    {
                        if ((m_callDescriptor.Username != null || m_callDescriptor.AuthUsername != null) && m_callDescriptor.Password != null)
                        {
                            SIPRequest authenticatedRequest         = GetAuthenticatedRequest(sipTransaction.TransactionRequest, sipResponse);
                            SIPNonInviteTransaction authTransaction = new SIPNonInviteTransaction(m_sipTransport, authenticatedRequest, m_outboundProxy);
                            authTransaction.NonInviteTransactionFinalResponseReceived += AuthResponseReceived;
                            authTransaction.NonInviteTransactionTimedOut += RequestTimedOut;
                            m_sipTransport.SendTransaction(authTransaction);
                        }
                        else
                        {
                            logger.LogDebug("Send request received an authentication required response but no credentials were available.");

                            if (ResponseReceived != null)
                            {
                                ResponseReceived(sipResponse);
                            }
                        }
                    }
                    else
                    {
                        logger.LogDebug("Send request failed with " + sipResponse.StatusCode + " but no authentication header was supplied for " + sipTransaction.TransactionRequest.Method + " to " + m_callDescriptor.Uri + ".");

                        if (ResponseReceived != null)
                        {
                            ResponseReceived(sipResponse);
                        }
                    }
                }
                else
                {
                    if (ResponseReceived != null)
                    {
                        ResponseReceived(sipResponse);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPNonInviteClientUserAgent ServerResponseReceived (" + remoteEndPoint + "). " + excp.Message);
            }

            return(Task.FromResult(SocketError.Success));
        }
        private void ProcessRegisterRequest(string threadName)
        {
            try
            {
                Thread.CurrentThread.Name = threadName;

                while (!Stop)
                {
                    if (m_registerQueue.Count > 0)
                    {
                        try
                        {
                            SIPNonInviteTransaction registrarTransaction = null;
                            lock (m_registerQueue)
                            {
                                registrarTransaction = m_registerQueue.Dequeue();
                            }

                            if (registrarTransaction != null)
                            {
                                DateTime           startTime = DateTime.Now;
                                RegisterResultEnum result    = Register(registrarTransaction);
                                TimeSpan           duration  = DateTime.Now.Subtract(startTime);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "register result=" + result.ToString() + ", time=" + duration.TotalMilliseconds + "ms, user="******".", null));

                                if (RegisterComplete != null)
                                {
                                    RegisterComplete(duration.TotalMilliseconds, registrarTransaction.TransactionRequest.Header.AuthenticationHeader != null);
                                }
                            }
                        }
                        catch (InvalidOperationException invalidOpExcp)
                        {
                            // This occurs when the queue is empty.
                            logger.Warn("InvalidOperationException ProcessRegisterRequest Register Job. " + invalidOpExcp.Message);
                        }
                        catch (Exception regExcp)
                        {
                            logger.Error("Exception ProcessRegisterRequest Register Job. " + regExcp.Message);
                        }
                    }
                    else
                    {
                        m_registerARE.WaitOne(MAX_PROCESS_REGISTER_SLEEP);
                    }
                }

                logger.Warn("ProcessRegisterRequest thread " + Thread.CurrentThread.Name + " stopping.");
            }
            catch (Exception excp)
            {
                logger.Error("Exception ProcessRegisterRequest (" + Thread.CurrentThread.Name + "). " + excp.Message);
            }
        }
        private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Server response " + sipResponse.StatusCode + " " + reasonPhrase + " received for " + sipTransaction.TransactionRequest.Method + " to " + m_callDescriptor.Uri + ".", m_owner));

                if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    if (sipResponse.Header.AuthenticationHeader != null)
                    {
                        if ((m_callDescriptor.Username != null || m_callDescriptor.AuthUsername != null) && m_callDescriptor.Password != null)
                        {
                            SIPRequest authenticatedRequest         = GetAuthenticatedRequest(sipTransaction.TransactionRequest, sipResponse);
                            SIPNonInviteTransaction authTransaction = m_sipTransport.CreateNonInviteTransaction(authenticatedRequest, sipTransaction.RemoteEndPoint, localSIPEndPoint, m_outboundProxy);
                            authTransaction.NonInviteTransactionFinalResponseReceived += AuthResponseReceived;
                            authTransaction.NonInviteTransactionTimedOut += RequestTimedOut;
                            m_sipTransport.SendSIPReliable(authTransaction);
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Send request received an authentication required response but no credentials were available.", m_owner));

                            if (ResponseReceived != null)
                            {
                                ResponseReceived(sipResponse);
                            }
                        }
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Send request failed with " + sipResponse.StatusCode + " but no authentication header was supplied for " + sipTransaction.TransactionRequest.Method + " to " + m_callDescriptor.Uri + ".", m_owner));

                        if (ResponseReceived != null)
                        {
                            ResponseReceived(sipResponse);
                        }
                    }
                }
                else
                {
                    if (ResponseReceived != null)
                    {
                        ResponseReceived(sipResponse);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPNonInviteClientUserAgent ServerResponseReceived (" + remoteEndPoint + "). " + excp.Message);
            }
        }
Example #16
0
        /// <summary>
        /// 处理注册请求消息
        /// </summary>
        /// <param name="localSIPEndPoint">本地终结点</param>
        /// <param name="remoteEndPoint">远程终结点</param>
        /// <param name="registerRequest">注册请求</param>
        private void ProcessRegisterReqMessage(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest registerRequest)
        {
            SIPSorceryPerformanceMonitor.IncrementCounter(SIPSorceryPerformanceMonitor.REGISTRAR_REGISTRATION_REQUESTS_PER_SECOND);

            int requestedExpiry = GetRequestedExpiry(registerRequest);

            if (registerRequest.Header.To == null)
            {
                logger.Debug("Bad register request, no To header from " + remoteEndPoint + ".");
                SIPResponse badReqResponse = SIPTransport.GetResponse(registerRequest, SIPResponseStatusCodesEnum.BadRequest, "Missing To header");
                m_sipTransport.SendResponse(badReqResponse);
            }
            else if (registerRequest.Header.To.ToURI.User.IsNullOrBlank())
            {
                logger.Debug("Bad register request, no To user from " + remoteEndPoint + ".");
                SIPResponse badReqResponse = SIPTransport.GetResponse(registerRequest, SIPResponseStatusCodesEnum.BadRequest, "Missing username on To header");
                m_sipTransport.SendResponse(badReqResponse);
            }
            else if (registerRequest.Header.Contact == null || registerRequest.Header.Contact.Count == 0)
            {
                logger.Debug("Bad register request, no Contact header from " + remoteEndPoint + ".");
                SIPResponse badReqResponse = SIPTransport.GetResponse(registerRequest, SIPResponseStatusCodesEnum.BadRequest, "Missing Contact header");
                m_sipTransport.SendResponse(badReqResponse);
            }
            else if (requestedExpiry > 0 && requestedExpiry < MINIMUM_EXPIRY_SECONDS)
            {
                logger.Debug("Bad register request, no expiry of " + requestedExpiry + " to small from " + remoteEndPoint + ".");
                SIPResponse tooFrequentResponse = GetErrorResponse(registerRequest, SIPResponseStatusCodesEnum.IntervalTooBrief, null);
                tooFrequentResponse.Header.MinExpires = MINIMUM_EXPIRY_SECONDS;
                m_sipTransport.SendResponse(tooFrequentResponse);
            }
            else
            {
                if (m_registerQueue.Count < MAX_REGISTER_QUEUE_SIZE)
                {
                    SIPNonInviteTransaction registrarTransaction = m_sipTransport.CreateNonInviteTransaction(registerRequest, remoteEndPoint, localSIPEndPoint, null);
                    lock (m_registerQueue)
                    {
                        m_registerQueue.Enqueue(registrarTransaction);
                    }
                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "Register queued for " + registerRequest.Header.To.ToURI.ToString() + ".", null));
                }
                else
                {
                    logger.Error("Register queue exceeded max queue size " + MAX_REGISTER_QUEUE_SIZE + ", overloaded response sent.");
                    SIPResponse overloadedResponse = SIPTransport.GetResponse(registerRequest, SIPResponseStatusCodesEnum.TemporarilyUnavailable, "Registrar overloaded, please try again shortly");
                    m_sipTransport.SendResponse(overloadedResponse);
                }

                m_registerARE.Set();
            }
        }
        private void SendNotifyRequestForSubscription(SIPEventSubscription subscription)
        {
            try
            {
                subscription.SubscriptionDialogue.CSeq++;

                //logger.Debug(DateTime.Now.ToString("HH:mm:ss:fff") + " Sending NOTIFY request for " + subscription.SubscriptionDialogue.Owner + " event " + subscription.SubscriptionEventPackage.ToString()
                //    + " and " + subscription.ResourceURI.ToString() + " to " + subscription.SubscriptionDialogue.RemoteTarget.ToString() + ", cseq=" + (subscription.SubscriptionDialogue.CSeq) + ".");

                int secondsRemaining = Convert.ToInt32(subscription.LastSubscribe.AddSeconds(subscription.Expiry).Subtract(DateTime.Now).TotalSeconds % Int32.MaxValue);

                SIPRequest notifyRequest = m_sipTransport.GetRequest(SIPMethodsEnum.NOTIFY, subscription.SubscriptionDialogue.RemoteTarget);
                notifyRequest.Header.From              = SIPFromHeader.ParseFromHeader(subscription.SubscriptionDialogue.LocalUserField.ToString());
                notifyRequest.Header.To                = SIPToHeader.ParseToHeader(subscription.SubscriptionDialogue.RemoteUserField.ToString());
                notifyRequest.Header.Event             = subscription.SubscriptionEventPackage.ToString();
                notifyRequest.Header.CSeq              = subscription.SubscriptionDialogue.CSeq;
                notifyRequest.Header.CallId            = subscription.SubscriptionDialogue.CallId;
                notifyRequest.Body                     = subscription.GetNotifyBody();
                notifyRequest.Header.ContentLength     = notifyRequest.Body.Length;
                notifyRequest.Header.SubscriptionState = "active;expires=" + secondsRemaining.ToString();
                notifyRequest.Header.ContentType       = subscription.NotifyContentType;
                notifyRequest.Header.ProxySendFrom     = subscription.SubscriptionDialogue.ProxySendFrom;

                // If the outbound proxy is a loopback address, as it will normally be for local deployments, then it cannot be overriden.
                SIPEndPoint dstEndPoint = m_outboundProxy;
                if (m_outboundProxy != null && IPAddress.IsLoopback(m_outboundProxy.Address))
                {
                    dstEndPoint = m_outboundProxy;
                }
                else if (subscription.SubscriptionDialogue.ProxySendFrom != null)
                {
                    // The proxy will always be listening on UDP port 5060 for requests from internal servers.
                    dstEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(SIPEndPoint.ParseSIPEndPoint(subscription.SubscriptionDialogue.ProxySendFrom).Address, m_defaultSIPPort));
                }

                SIPNonInviteTransaction notifyTransaction = m_sipTransport.CreateNonInviteTransaction(notifyRequest, dstEndPoint, m_sipTransport.GetDefaultSIPEndPoint(dstEndPoint), m_outboundProxy);
                notifyTransaction.NonInviteTransactionFinalResponseReceived += (local, remote, transaction, response) => { NotifyTransactionFinalResponseReceived(local, remote, transaction, response, subscription); };
                m_sipTransport.SendSIPReliable(notifyTransaction);

                //logger.Debug(notifyRequest.ToString());

                MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.NotifySent, "Notification sent for " + subscription.SubscriptionEventPackage.ToString() + " and " + subscription.ResourceURI.ToString() + " to " + subscription.SubscriptionDialogue.RemoteTarget.ToString() + " (cseq=" + notifyRequest.Header.CSeq + ").", subscription.SubscriptionDialogue.Owner));

                subscription.NotificationSent();
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendNotifyRequestForSubscription. " + excp.Message);
                throw;
            }
        }
Example #18
0
        /// <summary>
        /// Processes a transfer once the REFER request has been determined.
        /// </summary>
        /// <param name="referRequest">The REFER request for the transfer.</param>
        /// <param name="timeout">Timeout for the transfer request to get accepted.</param>
        /// <param name="ct">Cancellation token. Can be set to cancel the transfer prior to it being
        /// accepted or timing out.</param>
        /// <returns>True if the transfer was accepted by the Transferee or false if not.</returns>
        private async Task <bool> Transfer(SIPRequest referRequest, TimeSpan timeout, CancellationToken ct)
        {
            if (Dialogue == null)
            {
                logger.LogWarning("Transfer was called on the SIPUserAgent when no dialogue was available.");
                return(false);
            }
            else
            {
                TaskCompletionSource <bool> transferAccepted = new TaskCompletionSource <bool>();

                SIPNonInviteTransaction referTx = new SIPNonInviteTransaction(m_transport, referRequest, null);

                SIPTransactionResponseReceivedDelegate referTxStatusHandler = (localSIPEndPoint, remoteEndPoint, sipTransaction, sipResponse) =>
                {
                    // This handler has to go on a separate thread or the SIPTransport "ProcessInMessage" thread will be blocked.
                    Task.Run(() =>
                    {
                        if (sipResponse.Header.CSeqMethod == SIPMethodsEnum.REFER && sipResponse.Status == SIPResponseStatusCodesEnum.Accepted)
                        {
                            logger.LogInformation("Call transfer was accepted by remote server.");
                            transferAccepted.SetResult(true);
                        }
                        else
                        {
                            transferAccepted.SetResult(false);
                        }
                    }, ct);

                    return(Task.FromResult(SocketError.Success));
                };

                referTx.NonInviteTransactionFinalResponseReceived += referTxStatusHandler;
                referTx.SendRequest();

                await Task.WhenAny(transferAccepted.Task, Task.Delay((int)timeout.TotalMilliseconds, ct)).ConfigureAwait(false);

                referTx.NonInviteTransactionFinalResponseReceived -= referTxStatusHandler;

                if (transferAccepted.Task.IsCompleted)
                {
                    return(transferAccepted.Task.Result);
                }
                else
                {
                    logger.LogWarning($"Call transfer request timed out after {timeout.TotalMilliseconds}ms.");
                    return(false);
                }
            }
        }
        public void SendRequest(SIPMethodsEnum method)
        {
            try
            {
                SIPRequest req = GetRequest(method);
                SIPNonInviteTransaction tran = new SIPNonInviteTransaction(m_sipTransport, req, m_outboundProxy);

                ManualResetEvent waitForResponse = new ManualResetEvent(false);
                tran.NonInviteTransactionFailed += TransactionFailed;
                tran.NonInviteTransactionFinalResponseReceived += ServerResponseReceived;
                tran.SendRequest();
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPNonInviteClientUserAgent SendRequest to " + m_callDescriptor.Uri + ". " + excp.Message);
                throw;
            }
        }
        public void SendRequest(SIPMethodsEnum method)
        {
            try
            {
                SIPRequest req = GetRequest(method);
                SIPNonInviteTransaction tran = m_sipTransport.CreateNonInviteTransaction(req, null, m_sipTransport.GetDefaultSIPEndPoint(), m_outboundProxy);

                ManualResetEvent waitForResponse = new ManualResetEvent(false);
                tran.NonInviteTransactionTimedOut += RequestTimedOut;
                tran.NonInviteTransactionFinalResponseReceived += ServerResponseReceived;
                tran.SendReliableRequest();
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPNonInviteClientUserAgent SendRequest to " + m_callDescriptor.Uri + ". " + excp.Message);
                throw;
            }
        }
Example #21
0
        private void ProcessSubscribeRequest(string threadName)
        {
            try
            {
                Thread.CurrentThread.Name = threadName;

                while (!m_exit)
                {
                    if (m_notifierQueue.Count > 0)
                    {
                        try
                        {
                            SIPNonInviteTransaction subscribeTransaction = null;
                            lock (m_notifierQueue)
                            {
                                subscribeTransaction = m_notifierQueue.Dequeue();
                            }

                            if (subscribeTransaction != null)
                            {
                                DateTime startTime = DateTime.Now;
                                Subscribe(subscribeTransaction);
                                TimeSpan duration = DateTime.Now.Subtract(startTime);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Timing, "Subscribe time=" + duration.TotalMilliseconds + "ms, user="******".", null));
                            }
                        }
                        catch (Exception regExcp)
                        {
                            logger.Error("Exception ProcessSubscribeRequest Subscribe Job. " + regExcp.Message);
                        }
                    }
                    else
                    {
                        m_notifierARE.WaitOne(MAX_NOTIFIER_SLEEP_TIME);
                    }
                }

                logger.Warn("ProcessSubscribeRequest thread " + Thread.CurrentThread.Name + " stopping.");
            }
            catch (Exception excp)
            {
                logger.Error("Exception ProcessSubscribeRequest (" + Thread.CurrentThread.Name + "). " + excp.Message);
            }
        }
Example #22
0
        public void SendSIPRequest(SIPRequest sipRequest, string dstSocket)
        {
            //ResetSIPResponse();

            if (sipRequest.Method == SIPMethodsEnum.INVITE)
            {
                //m_inviteRequest = sipRequest;
                UACInviteTransaction inviteTransaction = m_sipTransport.CreateUACTransaction(sipRequest, IPSocket.GetIPEndPoint(dstSocket), m_sipTransport.GetTransportContact(null), SIPProtocolsEnum.UDP);
                inviteTransaction.UACInviteTransactionInformationResponseReceived += new SIPTransactionResponseReceivedDelegate(TransactionInformationResponseReceived);
                inviteTransaction.UACInviteTransactionFinalResponseReceived       += new SIPTransactionResponseReceivedDelegate(TransactionFinalResponseReceived);
                m_sipTransport.SendSIPReliable(inviteTransaction);
            }
            else
            {
                SIPNonInviteTransaction sipTransaction = m_sipTransport.CreateNonInviteTransaction(sipRequest, IPSocket.GetIPEndPoint(dstSocket), m_sipTransport.GetTransportContact(null), SIPProtocolsEnum.UDP);
                sipTransaction.NonInviteTransactionFinalResponseReceived += new SIPTransactionResponseReceivedDelegate(TransactionFinalResponseReceived);
                m_sipTransport.SendSIPReliable(sipTransaction);
            }
        }
Example #23
0
        private Task <SocketError> ByeServerFinalResponseReceived(SIPEndPoint localSIPEndPoint,
                                                                  SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                logger.LogDebug("Response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " +
                                sipTransaction.TransactionRequest.URI.ToString() + ".");

                SIPNonInviteTransaction byeTransaction = sipTransaction as SIPNonInviteTransaction;

                if ((sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired ||
                     sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised) && SIPAccount != null)
                {
                    // Resend BYE with credentials.
                    SIPAuthorisationDigest authRequest = sipResponse.Header.AuthenticationHeader.SIPDigest;
                    SIPURI contactUri = sipResponse.Header.Contact.Any()
                        ? sipResponse.Header.Contact[0].ContactURI
                        : sipResponse.Header.From.FromURI;

                    authRequest.SetCredentials(SIPAccount.SIPUsername, SIPAccount.SIPPassword, contactUri.ToString(),
                                               SIPMethodsEnum.BYE.ToString());

                    SIPRequest authByeRequest = byeTransaction.TransactionRequest;
                    authByeRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authRequest);
                    authByeRequest.Header.AuthenticationHeader.SIPDigest.Response = authRequest.Digest;
                    authByeRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId();
                    authByeRequest.Header.CSeq = authByeRequest.Header.CSeq + 1;

                    SIPNonInviteTransaction authByeTransaction =
                        new SIPNonInviteTransaction(m_sipTransport, authByeRequest, null);
                    authByeTransaction.SendRequest();
                }

                return(Task.FromResult(SocketError.Success));
            }
            catch (Exception excp)
            {
                logger.LogError("Exception ByServerFinalResponseReceived. " + excp.Message);
                return(Task.FromResult(SocketError.Fault));
            }
        }
        public void Hangup()
        {
            if (m_sipDialogue == null)
            {
                return;
            }

            try
            {
                //SIPRequest byeRequest = GetByeRequest(m_serverTransaction.TransactionFinalResponse, m_sipDialogue.RemoteTarget);
                SIPRequest byeRequest = m_sipDialogue.GetInDialogRequest(SIPMethodsEnum.BYE);
                byeRequest.SetSendFromHints(m_serverTransaction.TransactionRequest.LocalSIPEndPoint);
                m_byeTransaction = new SIPNonInviteTransaction(m_sipTransport, byeRequest, m_outboundProxy);
                m_byeTransaction.NonInviteTransactionFinalResponseReceived += ByeServerFinalResponseReceived;
                m_byeTransaction.NonInviteTransactionFailed += (tx, reason) => logger.LogWarning($"Bye request for {m_sipCallDescriptor.Uri} failed with {reason}.");
                m_byeTransaction.SendRequest();
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPClientUserAgent Hangup. " + excp.Message);
            }
        }
#pragma warning restore

        public SIPNonInviteServerUserAgent(
            SIPTransport sipTransport,
            SIPEndPoint outboundProxy,
            string sipUsername,
            string sipDomain,
            SIPCallDirection callDirection,
            ISIPAccount sipAccount,
            SIPNonInviteTransaction transaction)
        {
            m_sipTransport     = sipTransport;
            m_outboundProxy    = outboundProxy;
            m_sipUsername      = sipUsername;
            m_sipDomain        = sipDomain;
            m_sipCallDirection = callDirection;
            m_sipAccount       = sipAccount;
            m_transaction      = transaction;

            //m_transaction.TransactionTraceMessage += TransactionTraceMessage;
            //m_uasTransaction.UASInviteTransactionTimedOut += ClientTimedOut;
            //m_uasTransaction.UASInviteTransactionCancelled += UASTransactionCancelled;
            //m_uasTransaction.TransactionRemoved += new SIPTransactionRemovedDelegate(UASTransaction_TransactionRemoved);
            //m_uasTransaction.TransactionStateChanged += (t) => { logger.Debug("Transaction state change to " + t.TransactionState + ", uri=" + t.TransactionRequestURI.ToString() + "."); };
        }
Example #26
0
        public void AddRegisterRequest(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest registerRequest)
        {
            if (registerRequest.Method != SIPMethodsEnum.REGISTER)
            {
                SIPResponse notSupportedResponse = SIPResponse.GetResponse(registerRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, "Registration requests only");
                m_sipTransport.SendResponseAsync(notSupportedResponse).Wait();
            }
            else
            {
                int requestedExpiry = GetRequestedExpiry(registerRequest);

                if (requestedExpiry > 0 && requestedExpiry < m_minimumBindingExpiry)
                {
                    Logger.LogDebug("Bad register request, no expiry of " + requestedExpiry + " to small from " + remoteEndPoint + ".");
                    SIPResponse tooFrequentResponse = SIPResponse.GetResponse(registerRequest, SIPResponseStatusCodesEnum.IntervalTooBrief, null);
                    tooFrequentResponse.Header.MinExpires = m_minimumBindingExpiry;
                    m_sipTransport.SendResponseAsync(tooFrequentResponse).Wait();
                }
                else
                {
                    if (m_registerQueue.Count < MAX_REGISTER_QUEUE_SIZE)
                    {
                        SIPNonInviteTransaction regTx = new SIPNonInviteTransaction(m_sipTransport, registerRequest, null);
                        m_registerQueue.Enqueue(regTx);
                    }
                    else
                    {
                        Logger.LogError("Register queue exceeded maximum queue size " + MAX_REGISTER_QUEUE_SIZE + ", overloaded response sent.");
                        SIPResponse overloadedResponse = SIPResponse.GetResponse(registerRequest, SIPResponseStatusCodesEnum.TemporarilyUnavailable, "Registrar overloaded, please try again shortly");
                        m_sipTransport.SendResponseAsync(overloadedResponse).Wait();
                    }

                    m_registerARE.Set();
                }
            }
        }
Example #27
0
        public void AddSubscribeRequest(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest subscribeRequest)
        {
            if (subscribeRequest.Method != SIPMethodsEnum.SUBSCRIBE)
            {
                SIPResponse notSupportedResponse = SIPResponse.GetResponse(subscribeRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, "Subscribe requests only");
                m_sipTransport.SendResponseAsync(notSupportedResponse).Wait();
            }
            else
            {
                if (m_subscribeQueue.Count < MAX_SUBSCRIBE_QUEUE_SIZE)
                {
                    SIPNonInviteTransaction subTx = new SIPNonInviteTransaction(m_sipTransport, subscribeRequest, null);
                    m_subscribeQueue.Enqueue(subTx);
                }
                else
                {
                    Logger.LogError($"Subscribe queue exceeded maximum queue size {MAX_SUBSCRIBE_QUEUE_SIZE}, overloaded response sent.");
                    SIPResponse overloadedResponse = SIPResponse.GetResponse(subscribeRequest, SIPResponseStatusCodesEnum.TemporarilyUnavailable, "Subscriber core overloaded, please try again shortly");
                    m_sipTransport.SendResponseAsync(overloadedResponse).Wait();
                }

                m_subscribeARE.Set();
            }
        }
        private Task <SocketError> ByeServerFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                logger.LogDebug("Response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " + sipTransaction.TransactionRequest.URI.ToString() + ".");

                SIPNonInviteTransaction byeTransaction = sipTransaction as SIPNonInviteTransaction;

                if ((sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised) && SIPAccount != null)
                {
                    var authRequest = sipTransaction.TransactionRequest.DuplicateAndAuthenticate(sipResponse.Header.AuthenticationHeaders,
                                                                                                 SIPAccount.SIPUsername, SIPAccount.SIPPassword);
                    SIPNonInviteTransaction authByeTransaction = new SIPNonInviteTransaction(m_sipTransport, authRequest, null);
                    authByeTransaction.SendRequest();
                }

                return(Task.FromResult(SocketError.Success));
            }
            catch (Exception excp)
            {
                logger.LogError("Exception ByServerFinalResponseReceived. " + excp.Message);
                return(Task.FromResult(SocketError.Fault));
            }
        }
Example #29
0
        private void SIPTransportRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest)
        {
            try
            {
                switch (sipRequest.Method)
                {
                case SIPMethodsEnum.OPTIONS:
                    SIPNonInviteTransaction optionsTransaction = _sipTransport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null);
                    SIPResponse             optionsResponse    = SipHelper.WG67ResponseNormalize(
                        SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null));
                    optionsTransaction.SendFinalResponse(optionsResponse);
                    OptionsReceived?.Invoke(remoteEndPoint.ToString());
                    break;

                case SIPMethodsEnum.SUBSCRIBE:
                    m_sip_notifier.AddSubscribeRequest(localSIPEndPoint, remoteEndPoint, sipRequest);
                    break;

                case SIPMethodsEnum.PUBLISH:
                default:
                    throw new NotImplementedException();
                }
            }
            catch (NotImplementedException)
            {
                _logger.From().Debug(sipRequest.Method + " request processing not implemented for " + sipRequest.URI.ToParameterlessString() + " from " + remoteEndPoint + ".");

                SIPNonInviteTransaction notImplTransaction = _sipTransport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null);
                SIPResponse             notImplResponse    = SipHelper.WG67ResponseNormalize(SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotImplemented, null));
                notImplTransaction.SendFinalResponse(notImplResponse);
            }
            catch (Exception x)
            {
                _logger.From().Debug($"SIPTransportRequestReceived Exception {x.Message}", x);
            }
        }
        /// <summary>
        /// The event handler for responses to the initial register request.
        /// </summary>
        private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Server response " + sipResponse.Status + " received for " + m_sipAccountAOR.ToString() + ".", m_owner));

                if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    if (sipResponse.Header.AuthenticationHeader != null)
                    {
                        if (m_attempts >= MAX_REGISTER_ATTEMPTS)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.", m_owner));
                            m_isRegistered = false;
                            RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts.");
                            m_waitForRegistrationMRE.Set();
                        }
                        else
                        {
                            m_attempts++;
                            SIPRequest authenticatedRequest            = GetAuthenticatedRegistrationRequest(sipTransaction.TransactionRequest, sipResponse);
                            SIPNonInviteTransaction regAuthTransaction = m_sipTransport.CreateNonInviteTransaction(authenticatedRequest, sipTransaction.RemoteEndPoint, localSIPEndPoint, m_outboundProxy);
                            regAuthTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { AuthResponseReceived(lep, rep, tn, rsp); }); };
                            regAuthTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); };
                            m_sipTransport.SendSIPReliable(regAuthTransaction);
                        }
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied for " + m_sipAccountAOR.ToString() + ".", m_owner));
                        m_isRegistered = false;
                        RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied.");
                        m_waitForRegistrationMRE.Set();
                    }
                }
                else
                {
                    if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
                    {
                        if (m_expiry > 0)
                        {
                            m_isRegistered = true;
                            m_expiry       = GetUpdatedExpiry(sipResponse);
                            RegistrationSuccessful?.Invoke(m_sipAccountAOR);
                        }
                        else
                        {
                            m_isRegistered = false;
                            RegistrationRemoved?.Invoke(m_sipAccountAOR);
                        }

                        m_waitForRegistrationMRE.Set();
                    }
                    else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound)
                    {
                        // SIP account does not appear to exist.
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", m_owner));
                        string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
                        RegistrationFailed?.Invoke(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + ".");
                        m_exit = true;
                        m_waitForRegistrationMRE.Set();
                    }
                    else if (sipResponse.Status == SIPResponseStatusCodesEnum.IntervalTooBrief && m_expiry != 0)
                    {
                        m_expiry = GetUpdatedExpiryForIntervalTooBrief(sipResponse);
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Registration for " + m_sipAccountAOR.ToString() + " had a too short expiry, updated to +" + m_expiry + " and trying again.", m_owner));
                        SendInitialRegister();
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ".", m_owner));
                        m_isRegistered = false;
                        RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + ".");
                        m_waitForRegistrationMRE.Set();
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPRegistrationUserAgent ServerResponseReceived (" + remoteEndPoint + "). " + excp.Message);
            }
        }
Example #31
0
        /// <summary>
        /// Handler for processing incomign 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 void SIPTransportRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest)
        {
            if (sipRequest.Method == SIPMethodsEnum.BYE)
            {
                if (m_uac != null && m_uac.SIPDialogue != null && sipRequest.Header.CallId == m_uac.SIPDialogue.CallId)
                {
                    // Call has been hungup by remote end.
                    StatusMessage("Call hungup by remote end.");
                    SIPNonInviteTransaction byeTransaction = m_sipTransport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null);
                    SIPResponse             byeResponse    = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                    byeTransaction.SendFinalResponse(byeResponse);
                    CallFinished();
                }
                else if (m_uas != null && m_uas.SIPDialogue != null && sipRequest.Header.CallId == m_uas.SIPDialogue.CallId)
                {
                    // Call has been hungup by remote end.
                    StatusMessage("Call hungup.");
                    m_uas.SIPDialogue.Hangup(m_sipTransport, null);
                    CallFinished();
                }
                else
                {
                    logger.Debug("Unmatched BYE request received for " + sipRequest.URI.ToString() + ".");
                    SIPResponse noCallLegResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist, null);
                    m_sipTransport.SendResponse(noCallLegResponse);
                }
            }
            else if (sipRequest.Method == SIPMethodsEnum.INVITE)
            {
                StatusMessage("Incoming call request: " + localSIPEndPoint + "<-" + remoteEndPoint + " " + sipRequest.URI.ToString() + ".");
                UASInviteTransaction uasTransaction = m_sipTransport.CreateUASTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null);
                m_uas = new SIPServerUserAgent(m_sipTransport, null, null, null, SIPCallDirection.In, null, null, null, uasTransaction);
                m_uas.CallCancelled += UASCallCancelled;
                IncomingCall();
            }
            else if (sipRequest.Method == SIPMethodsEnum.CANCEL)
            {
                UASInviteTransaction inviteTransaction = (UASInviteTransaction)m_sipTransport.GetTransaction(SIPTransaction.GetRequestTransactionId(sipRequest.Header.Vias.TopViaHeader.Branch, SIPMethodsEnum.INVITE));

                if (inviteTransaction != null)
                {
                    StatusMessage("Call was cancelled by remote end.");
                    SIPCancelTransaction cancelTransaction = m_sipTransport.CreateCancelTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, inviteTransaction);
                    cancelTransaction.GotRequest(localSIPEndPoint, remoteEndPoint, sipRequest);
                }
                else
                {
                    logger.Debug("No matching transaction was found for CANCEL to " + sipRequest.URI.ToString() + ".");
                    SIPResponse noCallLegResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist, null);
                    m_sipTransport.SendResponse(noCallLegResponse);
                }

                CallFinished();
            }
            else
            {
                logger.Debug("SIP " + sipRequest.Method + " request received but no processing has been set up for it, rejecting.");
                SIPResponse notAllowedResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null);
                m_sipTransport.SendResponse(notAllowedResponse);
            }
        }
Example #32
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);
            }
        }
        public void ReferOutOfDialog(SIPURI fromUri, SIPURI toUri, SIPURI referToUri, ReplacesCallDescriptor sipReplacesCallDescriptor)
        {
            try
            {
                m_sipCallDescriptor = new SIPCallDescriptor(null,toUri.ToString(),fromUri.ToString(),null,null);
                m_sipCallDescriptor.Gruu = toUri.Parameters.Get(SIPCallDescriptor.GRUU_KEY);
                m_sipCallDescriptor.ReplacesCall = sipReplacesCallDescriptor;

                SIPURI callURI = SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri);

                    // If the outbound proxy is a loopback address, as it will normally be for local deployments, then it cannot be overriden.
                    if (m_outboundProxy != null && IPAddress.IsLoopback(m_outboundProxy.Address))
                    {
                        m_serverEndPoint = m_outboundProxy;
                    }
                    else if (!m_sipCallDescriptor.ProxySendFrom.IsNullOrBlank())
                    {
                        // If the binding has a specific proxy end point sent then the request needs to be forwarded to the proxy's default end point for it to take care of.
                        SIPEndPoint outboundProxyEndPoint = SIPEndPoint.ParseSIPEndPoint(m_sipCallDescriptor.ProxySendFrom);
                        m_outboundProxy = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(outboundProxyEndPoint.Address, m_defaultSIPPort));
                        m_serverEndPoint = m_outboundProxy;
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "SIPReferClientUserAgent refer request using alternate outbound proxy of " + m_outboundProxy + ".", Owner));
                    }
                    else if (m_outboundProxy != null)
                    {
                        // Using the system outbound proxy only, no additional user routing requirements.
                        m_serverEndPoint = m_outboundProxy;
                    }

                    // A custom route set may have been specified for the call.
                    if (m_sipCallDescriptor.RouteSet != null && m_sipCallDescriptor.RouteSet.IndexOf(OUTBOUNDPROXY_AS_ROUTESET_CHAR) != -1)
                    {
                        try
                        {
                            RouteSet = new SIPRouteSet();
                            RouteSet.PushRoute(new SIPRoute(m_sipCallDescriptor.RouteSet, true));
                        }
                        catch
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Error an outbound proxy value was not recognised in SIPReferClientUserAgent refer request. " + m_sipCallDescriptor.RouteSet + ".", Owner));
                        }
                    }

                    // No outbound proxy, determine the forward destination based on the SIP request.
                    if (m_serverEndPoint == null)
                    {
                        SIPDNSLookupResult lookupResult = null;

                        if (RouteSet == null || RouteSet.Length == 0)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Attempting to resolve " + callURI.Host + ".", Owner));
                            lookupResult = m_sipTransport.GetURIEndPoint(callURI, false);
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Route set for refer request " + RouteSet.ToString() + ".", Owner));
                            lookupResult = m_sipTransport.GetURIEndPoint(RouteSet.TopRoute.URI, false);
                        }

                        if (lookupResult.LookupError != null)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "DNS error resolving " + callURI.Host + ", " + lookupResult.LookupError + ". Refer request cannot proceed.", Owner));
                        }
                        else
                        {
                            m_serverEndPoint = lookupResult.GetSIPEndPoint();
                        }
                    }

                    if (m_serverEndPoint != null)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Switching to " + SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri).CanonicalAddress + " via " + m_serverEndPoint + ".", Owner));

                        m_localSIPEndPoint = m_sipTransport.GetDefaultSIPEndPoint(m_serverEndPoint);
                        if (m_localSIPEndPoint == null)
                        {
                            throw new ApplicationException("The refer request could not locate an appropriate SIP transport channel for protocol " + callURI.Protocol + ".");
                        }

                        SIPRequest referRequest = GetReferRequest(m_localSIPEndPoint,referToUri, sipReplacesCallDescriptor);

                        // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call.
                        m_serverTransaction = m_sipTransport.CreateNonInviteTransaction(referRequest, m_serverEndPoint, m_localSIPEndPoint, m_outboundProxy);

                        m_serverTransaction.NonInviteTransactionFinalResponseReceived += m_serverTransaction_NonInviteTransactionFinalResponseReceived;
                        m_serverTransaction.NonInviteTransactionTimedOut += m_serverTransaction_NonInviteTransactionTimedOut;
                        m_serverTransaction.TransactionTraceMessage += TransactionTraceMessage;

                        m_serverTransaction.SendReliableRequest();

                    }
                    else
                    {
                        if (RouteSet == null || RouteSet.Length == 0)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Forward leg failed, could not resolve URI host " + callURI.Host, Owner));
                            FireReferFailed(this, "unresolvable destination " + callURI.Host);
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Forward leg failed, could not resolve top Route host " + RouteSet.TopRoute.Host, Owner));
                            FireReferFailed(this, "unresolvable destination " + RouteSet.TopRoute.Host);
                        }
                    }
            }
            catch (ApplicationException appExcp)
            {
                FireReferFailed(this, appExcp.Message);
            }
            catch (Exception excp)
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Exception UserAgentClient Call. " + excp.Message, Owner));
                FireReferFailed(this, excp.Message);
            }
        }
        public void Cancel()
        {
            try
            {
                m_callCancelled = true;

                // Cancel server call.
                if (m_serverTransaction == null)
                {
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Cancelling forwarded call leg " + m_sipCallDescriptor.Uri + ", server transaction has not been created yet no CANCEL request required.", Owner));
                }
                else if (m_cancelTransaction != null)
                {
                    if (m_cancelTransaction.TransactionState != SIPTransactionStatesEnum.Completed)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already been cancelled once, trying again.", Owner));
                        m_cancelTransaction.SendRequest(m_cancelTransaction.TransactionRequest);
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already responded to CANCEL, probably overlap in messages not re-sending.", Owner));
                    }
                }
                else //if (m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding || m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Trying)
                {
                    //logger.Debug("Cancelling forwarded call leg, sending CANCEL to " + ForwardedTransaction.TransactionRequest.URI.ToString() + " (transid: " + ForwardedTransaction.TransactionId + ").");
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Cancelling forwarded call leg, sending CANCEL to " + m_serverTransaction.TransactionRequest.URI.ToString() + ".", Owner));

                    // No reponse has been received from the server so no CANCEL request neccessary, stop any retransmits of the INVITE.
                    m_serverTransaction.CancelCall();

                    SIPRequest cancelRequest = GetCancelRequest(m_serverTransaction.TransactionRequest);
                    m_cancelTransaction = m_sipTransport.CreateNonInviteTransaction(cancelRequest, m_serverEndPoint, m_serverTransaction.LocalSIPEndPoint, m_outboundProxy);
                    m_cancelTransaction.TransactionTraceMessage += TransactionTraceMessage;
                    //m_cancelTransaction.SendRequest(m_serverEndPoint, cancelRequest);
                    m_cancelTransaction.SendReliableRequest();
                }
                //else
                //{
                // No reponse has been received from the server so no CANCEL request neccessary, stop any retransmits of the INVITE.
                //    m_serverTransaction.CancelCall();
                //    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Cancelling forwarded call leg " + m_sipCallDescriptor.Uri.ToString() + ", no response from server has been received so no CANCEL request required.", Owner));
                //}

                FireCallFailed(this, "Call cancelled by user.");
            }
            catch (Exception excp)
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Exception CancelServerCall. " + excp.Message, Owner));
            }
        }