public void SendFullStateNotify(string sessionID)
        {
            try
            {
                if (m_subscriptions.ContainsKey(sessionID))
                {
                    SIPEventSubscription subscription = m_subscriptions[sessionID];

                    lock (subscription)
                    {
                        subscription.GetFullState();
                        SendNotifyRequestForSubscription(subscription);
                    }
                }
                else
                {
                    logger.Warn("No subscription could be found for " + sessionID + " when attempting to send a full state notification.");
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception NotifierSubscriptionsManager SendFullStateNotify. " + excp.Message);
                throw;
            }
        }
        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;
            }
        }
        private void StopSubscription(SIPEventSubscription subscription)
        {
            try
            {
                m_publisher.CloseSession(m_notificationsAddress, subscription.SessionID);
                lock (m_subscriptions)
                {
                    m_subscriptions.Remove(subscription.SessionID);
                }

                MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Warn, "Stopping subscription for " + subscription.SubscriptionEventPackage.ToString() + " " + subscription.ResourceURI.ToString() + ".", subscription.SubscriptionDialogue.Owner));
            }
            catch (Exception excp)
            {
                logger.Error("Exception StopSubscription. " + excp.Message);
            }
        }
        private bool MonitorEventAvailable(SIPMonitorEvent sipMonitorEvent)
        {
            try
            {
                SIPMonitorMachineEvent machineEvent = sipMonitorEvent as SIPMonitorMachineEvent;

                if (machineEvent != null && !machineEvent.SessionID.IsNullOrBlank() && m_subscriptions.ContainsKey(machineEvent.SessionID))
                {
                    SIPEventSubscription subscription = m_subscriptions[machineEvent.SessionID];

                    lock (subscription)
                    {
                        string resourceURI = (machineEvent.ResourceURI != null) ? machineEvent.ResourceURI.ToString() : null;

                        //logger.Debug("NotifierSubscriptionsManager received new " + machineEvent.MachineEventType + ", resource ID=" + machineEvent.ResourceID + ", resource URI=" + resourceURI + ".");

                        //MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Monitor, "NotifierSubscriptionsManager received new " + machineEvent.MachineEventType + ", resource ID=" + machineEvent.ResourceID + ", resource URI=" + resourceURI + ".", subscription.SubscriptionDialogue.Owner));

                        if (subscription.AddMonitorEvent(machineEvent))
                        {
                            SendNotifyRequestForSubscription(subscription);
                        }

                        //logger.Debug("NotifierSubscriptionsManager completed " + machineEvent.MachineEventType + ", resource ID=" + machineEvent.ResourceID + ", resource URI=" + resourceURI + ".");
                    }

                    return(true);
                }

                return(false);
            }
            catch (Exception excp)
            {
                logger.Error("Exception NotifierSubscriptionsManager MonitorEventAvailable. " + excp.Message);
                return(false);
            }
        }
 private void NotifyTransactionFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse, SIPEventSubscription subscription)
 {
     try
     {
         if (sipResponse.StatusCode >= 300)
         {
             // The NOTIFY request was met with an error response.
             MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Warn, "A notify request received an error response of " + sipResponse.Status + " " + sipResponse.ReasonPhrase + ".", subscription.SubscriptionDialogue.Owner));
             StopSubscription(subscription);
         }
     }
     catch (Exception excp)
     {
         logger.Error("Exception NotifyTransactionFinalResponseReceived. " + excp.Message);
     }
 }
        /// <summary>
        /// Attempts to renew an existing subscription.
        /// </summary>
        /// <returns>The session ID if the renewal was successful or null if it wasn't.</returns>
        public string RenewSubscription(SIPRequest subscribeRequest, out SIPResponseStatusCodesEnum errorResponse, out string errorReason)
        {
            errorResponse = SIPResponseStatusCodesEnum.None;
            errorReason   = null;

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

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

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

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

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

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

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

                        return(existingSubscription.SessionID);
                    }
                    else
                    {
                        throw new ApplicationException("A duplicate SUBSCRIBE request was received by NotifierSubscriptionsManager.");
                    }
                }
                else
                {
                    //throw new ApplicationException("No existing subscription could be found for a subscribe renewal request.");
                    errorResponse = SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist;
                    errorReason   = "Subscription dialog not found";
                    return(null);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception RenewSubscription. " + excp.Message);
                throw;
            }
        }