示例#1
0
        /// <summary>
        /// Sends in initial notification request for a new subscription where it makes sense to do so.
        /// </summary>
        /// <param name="subscribeRequest">The client request that resulted in the subscription creation.</param>
        /// <param name="sipAccount">The authenticated SIP account that created the subscription.</param>
        private void SendInitialNotification(SIPRequest subscribeRequest, ISIPAccount sipAccount)
        {
            if (SIPEventPackageType.IsValid(subscribeRequest.Header.Event))
            {
                var eventPackage = SIPEventPackageType.Parse(subscribeRequest.Header.Event);

                if (eventPackage == SIPEventPackagesEnum.MessageSummary)
                {
                    // Send a dummy message waiting indicator message so that a client can verify a notification request can
                    // be received.
                    var dstUri     = subscribeRequest.Header.Contact[0].ContactURI;
                    var accountURI = new SIPURI(sipAccount.SIPUsername, sipAccount.SIPDomain, null, dstUri.Scheme, dstUri.Protocol);

                    var notifyReq = SIPRequest.GetRequest(SIPMethodsEnum.NOTIFY,
                                                          subscribeRequest.Header.Contact[0].ContactURI,
                                                          new SIPToHeader(null, accountURI.CopyOf(), CallProperties.CreateNewTag()),
                                                          new SIPFromHeader(null, accountURI.CopyOf(), CallProperties.CreateNewTag()));
                    notifyReq.Header.CallId            = subscribeRequest.Header.CallId;
                    notifyReq.Header.CSeq              = subscribeRequest.Header.CSeq++;
                    notifyReq.Header.Server            = m_serverAgent;
                    notifyReq.Header.Event             = SIPEventPackageType.MESSAGE_SUMMARY_EVENT_VALUE;
                    notifyReq.Header.SubscriptionState = "active";
                    notifyReq.Header.SetDateHeader();
                    notifyReq.Header.ContentType = SIPMIMETypes.MWI_CONTENT_TYPE;
                    notifyReq.Body = "Messages-Waiting: no";

                    // A little trick here is using the remote SIP end point as the destination rather than the Contact URI.
                    // Ideally some extra logic to check for IPv4 NAT should be applied. But since this server is known to
                    // be operating in the cloud and only send NOTIFY requests to Internet clients it should be a reasonable
                    // option.
                    SIPNonInviteTransaction notifyTx = new SIPNonInviteTransaction(m_sipTransport, notifyReq, subscribeRequest.RemoteSIPEndPoint);
                    notifyTx.SendRequest();
                }
            }
        }
示例#2
0
 public SIPAccountBinding(ISIPAccount sipAccount, SIPURI contact, SIPEndPoint remote, SIPEndPoint local, int expiry)
 {
     SIPAccount        = sipAccount;
     RegisteredContact = contact;
     RemoteEndPoint    = remote;
     LocalEndPoint     = local;
     Expiry            = expiry;
 }
示例#3
0
        public ManualResetEvent DelayMRE;       // If the call needs to be delayed DelaySeconds this MRE will be used.

        /// <summary>
        /// This constructor is for calls to a SIP account that the application recognises as belonging to it.
        /// </summary>
        /// <param name="toSIPAccount">The destination SP account for teh call.</param>
        /// <param name="uri">The uri can be different to the to SIP account if a dotted notation is used. For
        /// example [email protected].</param>
        /// <param name="fromHeader"></param>
        /// <param name="contentType"></param>
        /// <param name="content"></param>
        public SIPCallDescriptor(ISIPAccount toSIPAccount, string uri, string fromHeader, string contentType, string content)
        {
            ToSIPAccount = toSIPAccount;
            Uri          = uri ?? toSIPAccount.SIPUsername + "@" + toSIPAccount.SIPDomain;
            From         = fromHeader;
            ContentType  = contentType;
            Content      = content;
        }
示例#4
0
 public SIPB2BUserAgent(
     SIPTransport sipTransport,
     SIPEndPoint outboundProxy,
     UASInviteTransaction uasTransaction,
     ISIPAccount sipAccount) :
     base(sipTransport, outboundProxy, uasTransaction, sipAccount)
 {
     IsB2B = true;
     base.CallCancelled += SIPServerUserAgent_CallCancelled;
 }
示例#5
0
        public SIPServerUserAgent(
            SIPTransport sipTransport,
            SIPEndPoint outboundProxy,
            UASInviteTransaction uasTransaction,
            ISIPAccount sipAccount)
        {
            m_sipTransport   = sipTransport;
            m_outboundProxy  = outboundProxy;
            m_uasTransaction = uasTransaction;
            m_sipAccount     = sipAccount;

            m_uasTransaction.UASInviteTransactionFailed    += ClientTransactionFailed;
            m_uasTransaction.UASInviteTransactionCancelled += UASTransactionCancelled;
        }
        public SIPServerUserAgent(
            SIPTransport sipTransport,
            SIPEndPoint outboundProxy,
            UASInviteTransaction uasTransaction,
            ISIPAccount sipAccount)
        {
            m_sipTransport   = sipTransport;
            m_outboundProxy  = outboundProxy;
            m_uasTransaction = uasTransaction;
            m_sipAccount     = sipAccount;

            m_uasTransaction.UASInviteTransactionTimedOut  += ClientTimedOut;
            m_uasTransaction.UASInviteTransactionCancelled += UASTransactionCancelled;
            m_uasTransaction.TransactionRemoved            += new SIPTransactionRemovedDelegate(UASTransaction_TransactionRemoved);
        }
        private async Task Forward(UASInviteTransaction uasTx, ISIPAccount callerSIPAccount)
        {
            var invReq = uasTx.TransactionRequest;

            //uasTx.TransactionStateChanged += (tx) => Logger.LogDebug($"B2B uas tx state changed to {tx.TransactionState}.");
            //uasTx.TransactionTraceMessage += (tx, msg) => Logger.LogDebug($"B2B uas tx trace message. {msg}");

            Logger.LogDebug($"B2B commencing forward for caller {invReq.Header.From.FromURI} to {invReq.URI}.");

            SIPB2BUserAgent b2bua = new SIPB2BUserAgent(_sipTransport, null, uasTx, callerSIPAccount);

            bool isAuthenticated = false;

            if (callerSIPAccount != null)
            {
                isAuthenticated = b2bua.AuthenticateCall();
            }

            if (callerSIPAccount == null || isAuthenticated == true)
            {
                b2bua.CallAnswered += (uac, resp) => ForwardCallAnswered(uac, b2bua);

                var dst = await _sipdialPlan.Lookup(uasTx, null);

                if (dst == null)
                {
                    Logger.LogInformation($"B2BUA lookup did not return a destination. Rejecting UAS call.");

                    var notFoundResp = SIPResponse.GetResponse(uasTx.TransactionRequest, SIPResponseStatusCodesEnum.NotFound, null);
                    uasTx.SendFinalResponse(notFoundResp);

                    OnAcceptCallFailure?.Invoke(uasTx.TransactionRequest.RemoteSIPEndPoint, CallFailureEnum.NotFound, invReq);
                }
                else
                {
                    Logger.LogInformation($"B2BUA forwarding call to {dst.Uri}.");
                    b2bua.Call(dst);
                }
            }
        }
#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() + "."); };
        }
示例#9
0
        /// <summary>
        /// This function type is to allow B2B user agents to lookup the forwarding destination
        /// for an accepted User Agent Server (UAS) call leg. The intent is that functions
        /// can implement a form of a dialplan and pass to the B2BUA core.
        /// </summary>
        /// <param name="uas">A User Agent Server (UAS) transaction that has been accepted
        /// for forwarding.</param>
        /// <returns>A call descriptor for the User Agent Client (UAC) call leg that will
        /// be bridged to the UAS leg.</returns>
        public async Task <SIPCallDescriptor> Lookup(UASInviteTransaction uasTx, ISIPAccount from)
        {
            var dialplan = await LoadDialPlan();

            //_logger.LogDebug($"Our dialplan last update {TrimMilliseconds(_dialplanLastUpdated).ToString("o")}, " +
            //    $"database last update {TrimMilliseconds(dialplan.LastUpdate).ToString("o")}.");

            if (dialplan != null && TrimMilliseconds(DateTime.Parse(dialplan.LastUpdate)) > TrimMilliseconds(_dialplanLastUpdated))
            {
                _logger.LogInformation($"SIP DialPlan Manager loading updated dialplan.");
                CompileDialPlan(dialplan.DialPlanScript, DateTime.Parse(dialplan.LastUpdate));
            }

            if (_dialPlanScriptRunner != null)
            {
                var result = await _dialPlanScriptRunner.Invoke(new SIPDialPlanGlobals { UasTx = uasTx, From = from });

                return(result as SIPCallDescriptor);
            }
            else
            {
                return(null);
            }
        }
示例#10
0
        /// <summary>
        /// Authenticates a SIP request.
        /// </summary>
        public static SIPRequestAuthenticationResult AuthenticateSIPRequest(
            SIPEndPoint localSIPEndPoint,
            SIPEndPoint remoteEndPoint,
            SIPRequest sipRequest,
            ISIPAccount sipAccount)
        {
            try
            {
                if (sipAccount == null)
                {
                    return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Forbidden, null));
                }
                else if (sipAccount.IsDisabled)
                {
                    logger.LogWarning($"SIP account {sipAccount.SIPUsername}@{sipAccount.SIPDomain} is disabled for {sipRequest.Method}.");

                    return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Forbidden, null));
                }
                else
                {
                    SIPAuthenticationHeader reqAuthHeader = sipRequest.Header.AuthenticationHeader;
                    if (reqAuthHeader == null)
                    {
                        // Check for IP address authentication.
                        //if (!sipAccount.IPAddressACL.IsNullOrBlank())
                        //{
                        //    SIPEndPoint uaEndPoint = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : remoteEndPoint;
                        //    if (Regex.Match(uaEndPoint.GetIPEndPoint().ToString(), sipAccount.IPAddressACL).Success)
                        //    {
                        //        // Successfully authenticated
                        //        return new SIPRequestAuthenticationResult(true, true);
                        //    }
                        //}

                        SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce());
                        return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader));
                    }
                    else
                    {
                        // Check for IP address authentication.
                        //if (!sipAccount.IPAddressACL.IsNullOrBlank())
                        //{
                        //    SIPEndPoint uaEndPoint = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : remoteEndPoint;
                        //    if (Regex.Match(uaEndPoint.GetIPEndPoint().ToString(), sipAccount.IPAddressACL).Success)
                        //    {
                        //        // Successfully authenticated
                        //        return new SIPRequestAuthenticationResult(true, true);
                        //    }
                        //}

                        string requestNonce = reqAuthHeader.SIPDigest.Nonce;
                        string uri          = reqAuthHeader.SIPDigest.URI;
                        string response     = reqAuthHeader.SIPDigest.Response;

                        // Check for stale nonces.
                        if (IsNonceStale(requestNonce))
                        {
                            logger.LogWarning($"Authentication failed stale nonce for realm={sipAccount.SIPDomain}, username={sipAccount.SIPUsername}, uri={uri}, nonce={requestNonce}, method={sipRequest.Method}.");

                            SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce());
                            return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader));
                        }
                        else
                        {
                            SIPAuthorisationDigest checkAuthReq = reqAuthHeader.SIPDigest;

                            if (sipAccount.SIPPassword != null)
                            {
                                checkAuthReq.SetCredentials(sipAccount.SIPUsername, sipAccount.SIPPassword, uri, sipRequest.Method.ToString());
                            }
                            else if (sipAccount.HA1Digest != null)
                            {
                                checkAuthReq.SetCredentials(sipAccount.HA1Digest, uri, sipRequest.Method.ToString());
                            }
                            else
                            {
                                throw new ApplicationException("SIP authentication cannot be attempted as neither a password or HA1 digest are available.");
                            }

                            string digest = checkAuthReq.Digest;

                            if (digest == response)
                            {
                                // Successfully authenticated
                                return(new SIPRequestAuthenticationResult(true, false));
                            }
                            else
                            {
                                logger.LogWarning("Authentication token check failed for realm=" + sipAccount.SIPDomain + ", username="******", uri=" + uri + ", nonce=" + requestNonce + ", method=" + sipRequest.Method + ".");

                                SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce());
                                return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader));
                            }
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError(0, excp, "Exception AuthoriseSIPRequest. " + excp.Message);
                return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.InternalServerError, null));
            }
        }