void WinReadWriteLock::unlock()
{
	if (m_lock.Ptr == (PVOID)1)
		unlockForWrite();
	else
		unlockForRead();
}
Exemple #2
0
UtlBoolean SipSubscribeServer::isEventTypeEnabled(const UtlString& eventType)
{
    lockForRead();
    // Only add the event support if it does not already exist;
    SubscribeServerEventData* eventData =
       dynamic_cast <SubscribeServerEventData*> (mEventDefinitions.find(&eventType));
    unlockForRead();

    return(eventData != NULL);
}
UtlBoolean SipSubscribeServer::handleNotifyResponse(const SipMessage& notifyResponse)
{
    UtlBoolean handledNotifyResponse = FALSE;
    int responseCode = notifyResponse.getResponseStatusCode();

    // Ignore provisional responses or success cases
    if(responseCode >= SIP_3XX_CLASS_CODE)
    {
        UtlString dialogHandle;
        notifyResponse.getDialogHandle(dialogHandle);

        // Not modifying the SubscribeServerEventData, just reading it
        lockForRead();

        // Get the event specific handler and information
        SubscribeServerEventData* eventPackageInfo = NULL;
        UtlHashMapIterator iterator(mEventDefinitions);
        
        while((eventPackageInfo = (SubscribeServerEventData*) iterator()))
        {
            // End this subscription as we got an error response from
            // the NOTIFY request.
            // Returns TRUE if the SipSubscriptionMgr has this dialog
            handledNotifyResponse = 
                eventPackageInfo->mpEventSpecificSubscriptionMgr->endSubscription(
                                                                    dialogHandle);
            if(handledNotifyResponse)
            {
                break;
            }
        }

        unlockForRead();

        // Should not happen, first of all we should never get a
        // response which does not correspond to a request sent from 
        // the SipUserAgent.  Secondly, we should not get a response to
        // and event type that we do not support
        if(!handledNotifyResponse)
        {
            OsSysLog::add(FAC_SIP, PRI_ERR,
                "SipSubscribeServer::handleNotifyResponse NOTIFY response with no dialog. Handle: %s",
                 dialogHandle.data());
        }
    }

    // Provisional or 2XX class responses
    else
    {
        handledNotifyResponse = TRUE;
    }

    return(handledNotifyResponse);
}
Exemple #4
0
SipSubscriptionMgr* SipSubscribeServer::getSubscriptionMgr(const UtlString& eventType)
{
    SipSubscriptionMgr* subscribeMgr = NULL;
    lockForRead();
    SubscribeServerEventData* eventData =
       dynamic_cast <SubscribeServerEventData*> (mEventDefinitions.find(&eventType));
    if (eventData)
    {
        subscribeMgr = eventData->mpEventSpecificSubscriptionMgr;
    }

    else
    {
        subscribeMgr = mpDefaultSubscriptionMgr;
    }
    unlockForRead();

    return(subscribeMgr);
}
Exemple #5
0
SipSubscribeServerEventHandler*
SipSubscribeServer::getEventHandler(const UtlString& eventType)
{
    SipSubscribeServerEventHandler* eventHandler = NULL;
    lockForRead();
    SubscribeServerEventData* eventData =
       dynamic_cast <SubscribeServerEventData*> (mEventDefinitions.find(&eventType));
    if (eventData)
    {
        eventHandler = eventData->mpEventSpecificHandler;
    }
    else
    {
        eventHandler = mpDefaultEventHandler;
    }
    unlockForRead();

    return(eventHandler);
}
SipPublishServerEventStateMgr* SipPublishServer::getEventStateMgr(const UtlString& eventType)
{
    SipPublishServerEventStateMgr* eventStateMgr = NULL;
    lockForRead();
    PublishServerEventData* eventData = 
        (PublishServerEventData*) mEventDefinitions.find(&eventType);
    if(eventData)
    {
        eventStateMgr = eventData->mpEventSpecificStateMgr;
    }

    else 
    {
        eventStateMgr = mpDefaultEventStateMgr;
    }
    unlockForRead(); 

    return(eventStateMgr);
}
Exemple #7
0
SipPublishContentMgr*
SipSubscribeServer::getPublishMgr(const UtlString& eventType)
{
    SipPublishContentMgr* contentMgr = NULL;
    lockForRead();
    SubscribeServerEventData* eventData =
       dynamic_cast <SubscribeServerEventData*> (mEventDefinitions.find(&eventType));
    if (eventData)
    {
        contentMgr = eventData->mpEventSpecificContentMgr;
    }

    else
    {
        contentMgr = mpDefaultContentMgr;
    }
    unlockForRead();

    return(contentMgr);
}
Exemple #8
0
// Dump the object's internal state.
void SipSubscribeServer::dumpState()
{
   lockForRead();

   // indented 2

   OsSysLog::add(FAC_RLS, PRI_INFO,
                 "\t  SipSubscribeServer %p",
                 this);

   mpDefaultContentMgr->dumpState();
   mpDefaultSubscriptionMgr->dumpState();
   // mpDefaultEventHandler has no internal state.
   UtlHashBagIterator itor(mEventDefinitions);
   SubscribeServerEventData* ed;
   while ((ed = dynamic_cast <SubscribeServerEventData*> (itor())))
   {
      ed->dumpState();
   }

   unlockForRead();
}
Exemple #9
0
UtlBoolean SipSubscribeServer::handleSubscribe(const SipMessage& subscribeRequest)
{
    UtlBoolean handledSubscribe = FALSE;
    UtlString eventName;
    subscribeRequest.getEventField(&eventName, NULL);

    // Not modifying the SubscribeServerEventData, just reading it
    lockForRead();

    // Get the event specific handler and information
    SubscribeServerEventData* eventPackageInfo =
       dynamic_cast <SubscribeServerEventData*> (mEventDefinitions.find(&eventName));

    // We handle this event type
    if (eventPackageInfo)
    {
        handledSubscribe = TRUE;
        SipSubscribeServerEventHandler* handler =
            eventPackageInfo->mpEventSpecificHandler;

        SipMessage subscribeResponse;

        // Check if authenticated (or if it needs to be authenticated)
        if (handler->isAuthenticated(subscribeRequest,
                                     subscribeResponse))
        {
            // Check if authorized (or if authorization is required)
            if (handler->isAuthorized(subscribeRequest,
                                     subscribeResponse))
            {
                // The subscription is allowed, so update the
                // subscription state.  Set the To field tag if
                // this request initiated the dialog
                UtlString subscribeDialogHandle;
                UtlBoolean isNewDialog;
                UtlBoolean isExpiredSubscription;
                UtlString resourceId, eventTypeKey, eventType;
                eventPackageInfo->mpEventSpecificSubscriptionMgr->
                   updateDialogInfo(
                      subscribeRequest,
                      resourceId,
                      eventTypeKey,
                      eventType,
                      subscribeDialogHandle,
                      isNewDialog,
                      isExpiredSubscription,
                      subscribeResponse,
                      // The event-specific handler provides a getKeys method
                      // which is used to determine the resource ID
                      // and event type if this is a new subscription.
                      *handler);

                 // Build a NOTIFY
                 SipMessage notifyRequest;

                 // Set the dialog information into the NOTIFY.
                 // Note that the dialog can have ended by now, because of
                 // a race condition with the processing of dialog-ending
                 // messages from the outside world.
                 if (eventPackageInfo->mpEventSpecificSubscriptionMgr->
                     getNotifyDialogInfo(subscribeDialogHandle,
                                         notifyRequest,
                                         "active;expires=%ld"))
                 {
                    // We still have record of the dialog, so the
                    // NOTIFY headers were set.

                    // Set the NOTIFY content
                    UtlString acceptHeaderValue;
                    if (!subscribeRequest.getAcceptField(acceptHeaderValue))
                    {
                       // No Accept header seen, set special value allowing any
                       // content type.
                       acceptHeaderValue = SipPublishContentMgr::acceptAllTypes;
                    }
                    // Note that since this NOTIFY is due to a SUBSCRIBE,
                    // it should contain 'full' content.  Hence,
                    // the fullState parameter of getNotifyContent is TRUE,
                    // and is not taken from
                    // eventPackageInfo->mEventSpecificFullState.
                    UtlString availableMediaTypes;
                    if (handler->getNotifyContent(resourceId,
                                                  eventTypeKey,
                                                  eventType,
                                                  *(eventPackageInfo->mpEventSpecificContentMgr),
                                                  acceptHeaderValue,
                                                  notifyRequest,
                                                  TRUE,
                                                  &availableMediaTypes))
                    {
                       // Update the NOTIFY content if required for this event type.
                       // Sets 'version' and 'eventTypeKey'.
                       int version;
                       eventPackageInfo->mpEventSpecificSubscriptionMgr->
                          updateNotifyVersion(eventPackageInfo->mpEventSpecificContentVersionCallback,
                                              notifyRequest,
                                              version,
                                              eventTypeKey);

                       // Update the saved record of the NOTIFY CSeq and the
                       // XML version number for the specified eventTypeKey,
                       // as needed by the subscription manager.
                       // In practice, this is only used by SipPersistentSubscriptionMgr
                       // to write the NOTIFY Cseq and XML version into the IMDB.
                       eventPackageInfo->mpEventSpecificSubscriptionMgr->
                          updateVersion(notifyRequest, version, eventTypeKey);

                       // Send the NOTIFY request
                       setContact(&notifyRequest);
                       eventPackageInfo->mpEventSpecificUserAgent->send(notifyRequest);

                       if (OsSysLog::willLog(FAC_SIP, PRI_INFO))
                       {
                          UtlString requestContact;
                          subscribeRequest.getContactField(0, requestContact);
                          OsSysLog::add(FAC_SIP, PRI_INFO,
                              "SipSubscribeServer::handleSubscribe: %s has setup subscription to %s, eventTypeKey %s",
                              requestContact.data(), resourceId.data(), eventTypeKey.data());
                       }
                    }
                    else
                    {
                       // No content was available, so the subscription fails.

                       // Determine the reason and set the response code.
                       if (availableMediaTypes.isNull())
                       {
                          // No MIME types are available, so the resource does not exist.
                          subscribeResponse.setResponseFirstHeaderLine(SIP_PROTOCOL_VERSION,
                                                                       SIP_NOT_FOUND_CODE,
                                                                       SIP_NOT_FOUND_TEXT);
                       }
                       else
                       {
                          // MIME types are available, so the resource exists.
                          subscribeResponse.setResponseFirstHeaderLine(SIP_PROTOCOL_VERSION,
                                                                       SIP_BAD_MEDIA_CODE,
                                                                       SIP_BAD_MEDIA_TEXT);
                          subscribeResponse.setAcceptField(availableMediaTypes);
                       }

                       // Destroy the subscription.
                       eventPackageInfo->mpEventSpecificSubscriptionMgr->
                          endSubscription(subscribeDialogHandle,
                                          SipSubscriptionMgr::subscriptionTerminated);

                       // Do not send the NOTIFY.
                    }
                 }
                 else
                 {
                    // Oops, the subscription was destroyed while we looked.
                    OsSysLog::add(FAC_SIP, PRI_WARNING,
                                  "SipSubscribeServer::handleSubscribe "
                                  "subscription '%s' vanished while being processed",
                                  subscribeDialogHandle.data());
                 }

                 // Send the response ASAP to minimize resending.
                 setContact(&subscribeResponse);
                 eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
            }
            // Not authorized
            else
            {
                // Send the response that was prepared by ::isAuthorized().
                setContact(&subscribeResponse);
                eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
            }
        }

        // Not authenticated
        else
        {
            // Send the response that was prepared by ::isAuthenticated().
            setContact(&subscribeResponse);
            eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
        }
    }

    // We should not have received SUBSCRIBE requests for this event type.
    // This event type has not been enabled in this SubscribeServer.
    else
    {
        OsSysLog::add(FAC_SIP, PRI_ERR,
            "SipSubscribeServer::handleSubscribe event type: %s not enabled",
            eventName.data());

        SipMessage eventTypeNotHandled;
        eventTypeNotHandled.setResponseData(&subscribeRequest,
                                            SIP_BAD_EVENT_CODE,
                                            SIP_BAD_EVENT_TEXT);

        setContact(&eventTypeNotHandled);
        mpDefaultUserAgent->send(eventTypeNotHandled);
    }
    unlockForRead();

    return(handledSubscribe);
}
Exemple #10
0
// Send a NOTIFY to all subscribers to the given resourceId and eventTypeKey.
UtlBoolean SipSubscribeServer::notifySubscribers(const char* resourceId,
                                                 const char* eventTypeKey,
                                                 const char* eventType,
                                                 const char* reason)
{
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSubscribeServer::notifySubscribers resourceId '%s', eventTypeKey '%s', eventType '%s', reason '%s'",
                 resourceId, eventTypeKey, eventType,
                 reason ? reason : "[null]");
    UtlBoolean notifiedSubscribers = FALSE;
    UtlString eventName(eventType);

    lockForRead();
    SubscribeServerEventData* eventData =
       dynamic_cast <SubscribeServerEventData*>
           (mEventDefinitions.find(&eventName));

    // Get the event-specific info to find subscriptions interested in
    // this content.
    if (eventData)
    {
        int numSubscriptions = 0;
        SipMessage** notifyArray = NULL;
        UtlString** acceptHeaderValuesArray = NULL;

        // Select the subscriptionChange value to describe what we're doing
        // with the subscriptions.
        enum SipSubscriptionMgr::subscriptionChange change;

        {
           // Select the correct format for generating the Subscription-State value.
           UtlString* formatp = NULL; // We may need a temp UtlString.
           const char* format;

           if (reason == NULL)
           {
              format = "active;expires=%ld";
              change = SipSubscriptionMgr::subscriptionContinues;
           }
           else if (strcmp(reason, terminationReasonSilent) == 0)
           {
              // Do not admit that the subscription is ending.
              format = "active;expires=%ld";
              change = SipSubscriptionMgr::subscriptionTerminatedSilently;
           }
           else if (strcmp(reason, terminationReasonNone) == 0)
           {
              format = "terminated";
              change = SipSubscriptionMgr::subscriptionTerminated;
           }
           else
           {
              // Allocate a UtlString and assemble the Subscription-State format in it.
              formatp = new UtlString();
              formatp->append("terminated;reason=");
              formatp->append(reason);
              format = formatp->data();
              change = SipSubscriptionMgr::subscriptionTerminated;
           }

           // Construct a NOTIFY (without body) for each subscription, containing
           // the dialog-related information about each subscription.
           eventData->mpEventSpecificSubscriptionMgr->
              createNotifiesDialogInfo(resourceId,
                                       eventTypeKey,
                                       format,
                                       numSubscriptions,
                                       acceptHeaderValuesArray,
                                       notifyArray);

           OsSysLog::add(FAC_SIP, PRI_DEBUG,
                         "SipSubscribeServer::notifySubscribers numSubscriptions for '%s' = %d",
                         resourceId, numSubscriptions);

           // Free the temporary UtlString, if necessary.
           if (formatp)
           {
              delete formatp;
           }
        }

        // For each NOTIFY, add the subscription-related information and then
        // send it.
        for (int notifyIndex = 0;
             notifyIndex < numSubscriptions;
             notifyIndex++)
        {
            SipMessage* notify = notifyArray[notifyIndex];

            // Check to see if the dialog information could be added.
            // (The subscription might have been destroyed between when
            // it was decided to respond to it, and when the dialog information
            // was retrieved.)
            UtlString callId;
            notify->getCallIdField(&callId);
            if (!callId.isNull())
            {
               if (change != SipSubscriptionMgr::subscriptionTerminatedSilently)
               {
                  // Fill in the NOTIFY request body/content
                  eventData->mpEventSpecificHandler->
                     getNotifyContent(resourceId,
                                      eventTypeKey,
                                      eventType,
                                      *(eventData->mpEventSpecificContentMgr),
                                      *(acceptHeaderValuesArray[notifyIndex]),
                                      *notify,
                                      eventData->mEventSpecificFullState,
                                      NULL);

                  // Call the application callback to edit the NOTIFY
                  // content if that is required for this event type.
                  // Also gets 'version' (if relevant) and 'savedEventTypeKey'.
                  int version;
                  UtlString savedEventTypeKey;
                  eventData->mpEventSpecificSubscriptionMgr->
                     updateNotifyVersion(eventData->mpEventSpecificContentVersionCallback,
                                         *notify,
                                         version,
                                         savedEventTypeKey);

                  // Update the saved record of the NOTIFY CSeq and the
                  // XML version number for the specified savedEventTypeKey,
                  // as needed by the subscription manager.
                  // In practice, this is only used by SipPersistentSubscriptionMgr
                  // to write the NOTIFY Cseq and XML version into the IMDB.
                  eventData->mpEventSpecificSubscriptionMgr->
                     updateVersion(*notify, version, savedEventTypeKey);

                  // Set the Contact header.
                  setContact(notify);

                  // Send the NOTIFY request.
                  eventData->mpEventSpecificUserAgent->send(*notify);
               }

               if (change != SipSubscriptionMgr::subscriptionContinues)
               {
                  // Remove the record of the subscription.
                  UtlString dialogHandle;
                  notify->getDialogHandle(dialogHandle);
                  eventData->mpEventSpecificSubscriptionMgr->
                     endSubscription(dialogHandle, change);
               }
            }
        }

        // Free the NOTIFY requests and accept header field values.
        eventData->mpEventSpecificSubscriptionMgr->
           freeNotifies(numSubscriptions,
                        acceptHeaderValuesArray,
                        notifyArray);
    }
    // event type not enabled
    else
    {
        OsSysLog::add(FAC_SIP, PRI_ERR,
                      "SipSubscribeServer::notifySubscribers "
                      "event type: %s not enabled - "
                      "Why are we seeing a callback for this?",
            eventName.data());
    }

    unlockForRead();

    return notifiedSubscribers;
}
Exemple #11
0
/// Terminate all subscriptions and accept no new ones.
void SipSubscribeServer::shutdown(const char* reason)
{
   // If reason is NULL, use the default reason established by the constructor.
   if (!reason)
   {
      reason = mDefaultTermination;
   }

   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSubscribeServer::shutdown reason '%s'",
                 reason ? reason : "[null]");                 

   lockForRead();

   // Select the subscriptionChange value to describe what we're doing
   // with the subscriptions.
   enum SipSubscriptionMgr::subscriptionChange change;

   // Select the correct format for generating the Subscription-State value.
   UtlString* formatp = NULL; // We may need a temp UtlString.
   const char* format;

   if (reason == NULL)
   {
      format = "active;expires=%ld";
      change = SipSubscriptionMgr::subscriptionContinues;
   }
   else if (strcmp(reason, terminationReasonSilent) == 0)
   {
      // Do not admit that the subscription is ending.
      format = "active;expires=%ld";
      change = SipSubscriptionMgr::subscriptionTerminatedSilently;
   }
   else if (strcmp(reason, terminationReasonNone) == 0)
   {
      format = "terminated";
      change = SipSubscriptionMgr::subscriptionTerminated;
   }
   else
   {
      // Allocate a UtlString and assemble the Subscription-State format in it.
      formatp = new UtlString();
      formatp->append("terminated;reason=");
      formatp->append(reason);
      format = formatp->data();
      change = SipSubscriptionMgr::subscriptionTerminated;
   }

   // For each event type that is registered, delete all the subscriptions.

   UtlHashBagIterator event_itor(mEventDefinitions);
   SubscribeServerEventData* eventData;
   while ((eventData =
              dynamic_cast <SubscribeServerEventData*> (event_itor())))
   {
      // Unregister interest in SUBSCRIBE requests and NOTIFY
      // responses for this event type, so we do not service new subscriptions.

      eventData->mpEventSpecificUserAgent->removeMessageObserver(*(getMessageQueue()));
      
      int numSubscriptions = 0;
      SipMessage** notifyArray = NULL;
      UtlString** acceptHeaderValuesArray = NULL;
      UtlString** resourceIdArray = NULL;
      UtlString** eventTypeKeyArray = NULL;

      // :TODO: The four situations where NOTIFYs are generated should
      // be factored into a series of methods in
      // mpEventSpecificSubscriptionMgr that generate NOTIFYs
      // sequentially, and for each NOTIFY, call a common service
      // method that does the remaining operations and sends the
      // NOTIFY.

      // Construct a NOTIFY (without body) for every subscription, containing
      // the dialog-related information about each subscription.
      eventData->mpEventSpecificSubscriptionMgr->
         createNotifiesDialogInfoEvent(static_cast <const UtlString&> (*eventData),
                                       format,
                                       numSubscriptions,
                                       acceptHeaderValuesArray,
                                       notifyArray,
                                       resourceIdArray,
                                       eventTypeKeyArray);

      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "SipSubscribeServer::shutdown eventType = '%s', numSubscriptions = %d",
                    eventData->data(), numSubscriptions);

      // For each NOTIFY, add the subscription-related information and then
      // send it.
      for (int notifyIndex = 0;
           notifyIndex < numSubscriptions;
           notifyIndex++)
      {
         SipMessage* notify = notifyArray[notifyIndex];

         // Check to see if the dialog information could be added.
         // (The subscription might have been destroyed between when
         // it was decided to respond to it, and when the dialog information
         // was retrieved.)
         UtlString callId;
         notify->getCallIdField(&callId);
         if (!callId.isNull())
         {
            if (change != SipSubscriptionMgr::subscriptionTerminatedSilently)
            {
               // Fill in the NOTIFY request body/content
               eventData->mpEventSpecificHandler->
                  getNotifyContent(*(resourceIdArray[notifyIndex]),
                                   *(eventTypeKeyArray[notifyIndex]),
                                   *eventData,
                                   *(eventData->mpEventSpecificContentMgr),
                                   *(acceptHeaderValuesArray[notifyIndex]),
                                   *notify,
                                   eventData->mEventSpecificFullState,
                                   NULL);

               // Call the application callback to edit the NOTIFY
               // content if that is required for this event type.
               // Also gets 'version' (if relevant) and 'savedEventTypeKey'.
               int version;
               UtlString savedEventTypeKey;
               eventData->mpEventSpecificSubscriptionMgr->
                  updateNotifyVersion(eventData->mpEventSpecificContentVersionCallback,
                                      *notify,
                                      version,
                                      savedEventTypeKey);

               // Set the Contact header.
               setContact(notify);

               // Send the NOTIFY request.
               eventData->mpEventSpecificUserAgent->send(*notify);
            }

            // Remove the record of the subscription.
            UtlString dialogHandle;
            notify->getDialogHandle(dialogHandle);
            eventData->mpEventSpecificSubscriptionMgr->
               endSubscription(dialogHandle, change);
         }
      }

      // Free the NOTIFY requests and accept header field values.
      SipSubscriptionMgr::freeNotifies(numSubscriptions,
                                       acceptHeaderValuesArray,
                                       notifyArray);

      // Free the resource and event type arrays.
      for (int index = 0;
           index < numSubscriptions;
           index++)
      {
         delete resourceIdArray[index];
         delete eventTypeKeyArray[index];
      }
      delete[] resourceIdArray;
      delete[] eventTypeKeyArray;

      // Remove eventData from mEventDefinitions.
      mEventDefinitions.removeReference(eventData);
      delete eventData;
   }

   unlockForRead();

   // Free the temporary UtlString, if necessary.
   if (formatp)
   {
      delete formatp;
   }

   lockForWrite();
   mEventDefinitions.destroyAll();
   unlockForWrite();
}
Exemple #12
0
// End a subscription because we got an error ersponse from a NOTIFY request.
// This requires sending a terminating NOTIFY.
void SipSubscribeServer::generateTerminatingNotify(const UtlString& dialogHandle)
{
   // Sending a terminating NOTIFY presents the risk of an infinite
   // loop, as the terminating NOTIFY may get an error response.  We
   // prevent this loop by removing record of the subscription as soon
   // as we send the terminating NOTIFY, and only initiating sending a
   // terminating NOTIFY if record of the subscription exists.

   // Not modifying the SubscribeServerEventData, just reading it.
   lockForRead();

   // Get the event-specific handler and information.
   SubscribeServerEventData* eventPackageInfo;
   UtlHashBagIterator iterator(mEventDefinitions);

   // The terminating NOTIFY request that we will send.
   SipMessage notifyRequest;

   // We have to search for the right eventPackageInfo.
   while ((eventPackageInfo =
           dynamic_cast <SubscribeServerEventData*> (iterator())))
   {
      UtlString resourceId;
      UtlString eventTypeKey;
      UtlString eventType;
      UtlString acceptHeaderValue;

      // Returns TRUE if eventPackageInfo->mpEventSpecificSubscriptionMgr
      // has this dialog.
      if (eventPackageInfo->mpEventSpecificSubscriptionMgr->
          getNotifyDialogInfo(dialogHandle,
                              notifyRequest,
                              "terminated;reason=deactivated",
                              &resourceId,
                              &eventTypeKey,
                              &eventType,
                              &acceptHeaderValue))
      {
         // There is still record of the subscription (hence a
         // terminating NOTIFY has not yet been sent), and this
         // eventPackageInfo has record of this subscription.
         
         // The NOTIFY headers were set by getNotifyDialogInfo.

         // Get the body for the NOTIFY.
         if (eventPackageInfo->mpEventSpecificHandler->
             getNotifyContent(resourceId,
                              eventTypeKey,
                              eventType,
                              *(eventPackageInfo->mpEventSpecificContentMgr),
                              acceptHeaderValue,
                              notifyRequest,
                              eventPackageInfo->mEventSpecificFullState,
                              NULL))
         {
            // Update the NOTIFY content if required for this event type.
            // Sets 'version' and 'eventTypeKey'.
            int version;
            eventPackageInfo->mpEventSpecificSubscriptionMgr->
               updateNotifyVersion(eventPackageInfo->mpEventSpecificContentVersionCallback,
                                   notifyRequest,
                                   version,
                                   eventTypeKey);
            
            // Update the saved record of the NOTIFY CSeq and the
            // XML version number for the specified eventTypeKey,
            // as needed by the subscription manager.
            // In practice, this is only used by SipPersistentSubscriptionMgr
            // to write the NOTIFY Cseq and XML version into the IMDB.
            eventPackageInfo->mpEventSpecificSubscriptionMgr->
               updateVersion(notifyRequest, version, eventTypeKey);
            
            // Send the NOTIFY request
            setContact(&notifyRequest);
            eventPackageInfo->mpEventSpecificUserAgent->send(notifyRequest);
         }

         // Destroy the subscription.
         // This prevents this method from sending a second terminating
         // NOTIFY for this subscription, even if it is called again.
         eventPackageInfo->mpEventSpecificSubscriptionMgr->
            endSubscription(dialogHandle,
                            SipSubscriptionMgr::subscriptionTerminated);
      }
   }

   unlockForRead();
}
UtlBoolean SipSubscribeServer::handleSubscribe(const SipMessage& subscribeRequest)
{
    UtlBoolean handledSubscribe = FALSE;
    UtlString eventName;
    subscribeRequest.getEventField(&eventName, NULL);

    // Not modifying the SubscribeServerEventData, just reading it
    lockForRead();

    // Get the event specific handler and information
    SubscribeServerEventData* eventPackageInfo = (SubscribeServerEventData*)
        mEventDefinitions.find(&eventName);

    // We handle this event type
    if(eventPackageInfo)
    {
        handledSubscribe = TRUE;
        UtlString resourceId;
        UtlString eventTypeKey, eventType;
        SipSubscribeServerEventHandler* handler =
            eventPackageInfo->mpEventSpecificHandler;

        // Get the keys used to identify the event state content
        handler->getKeys(subscribeRequest,
                         resourceId,
                         eventTypeKey,
                         eventType);

        SipMessage subscribeResponse;

        // Check if authenticated (or if it needs to be authenticated)
        if(handler->isAuthenticated(subscribeRequest,
                                     resourceId,
                                     eventTypeKey,
                                     subscribeResponse))
        {
            // Check if authorized (or if authorization is required)
            if(handler->isAuthorized(subscribeRequest,
                                     resourceId,
                                     eventTypeKey,
                                     subscribeResponse))
            {
                // The subscription is allowed, so update the
                // subscription state.  Set the To field tag if
                // this request initiated the dialog
                UtlString subscribeDialogHandle;
                UtlBoolean isNewDialog;
                UtlBoolean isExpiredSubscription;
                eventPackageInfo->mpEventSpecificSubscriptionMgr->updateDialogInfo(
                                                            subscribeRequest,
                                                            resourceId, 
                                                            eventTypeKey, 
                                                            getMessageQueue(),
                                                            subscribeDialogHandle, 
                                                            isNewDialog, 
                                                            isExpiredSubscription,
                                                            subscribeResponse);

                // Send the response ASAP to minimize resend handling of request
                 eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);

                 // Build a NOTIFY
                 SipMessage notifyRequest;

                 // Set the dialog information
                 eventPackageInfo->mpEventSpecificSubscriptionMgr->getNotifyDialogInfo(subscribeDialogHandle,
                                                                    notifyRequest);

                 // Set the NOTIFY content
                 UtlString acceptHeaderValue;
                 subscribeRequest.getAcceptField(acceptHeaderValue);
                 handler->getNotifyContent(resourceId, 
                                           eventTypeKey, 
                                           eventType, 
                                           *(eventPackageInfo->mpEventSpecificContentMgr),
                                           acceptHeaderValue,
                                           notifyRequest);

                 // Send the notify request
                 eventPackageInfo->mpEventSpecificUserAgent->send(notifyRequest);
            }
            // Not authorized
            else
            {
                // Send the response
                eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
            }
        }

        // Not authenticated
        else
        {
            // Send the response
            eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
        }
    }


    // We should not have received SUBSCRIBE requests for this event type
    // This event type has not been enabled in this SubscribeServer
    else
    {
        OsSysLog::add(FAC_SIP, PRI_ERR, 
            "SipSubscribeServer::handleSubscribe event type: %s not enabled",
            eventName.data());

        SipMessage eventTypeNotHandled;
        eventTypeNotHandled.setResponseData(&subscribeRequest,
            SIP_BAD_EVENT_CODE, SIP_BAD_EVENT_TEXT);

        mpDefaultUserAgent->send(eventTypeNotHandled);
    }
    unlockForRead();

    return(handledSubscribe);
}
UtlBoolean SipSubscribeServer::notifySubscribers(const char* resourceId, 
                                                 const char* eventTypeKey,
                                                 const char* eventType,
                                                 UtlBoolean isDefaultContent)
{
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSubscribeServer::notifySubscribers resourceId '%s', eventTypeKey '%s', eventType '%s', isDefaultContent %d",
                 resourceId, eventTypeKey, eventType, isDefaultContent);
    UtlBoolean notifiedSubscribers = FALSE;
    UtlString eventName(eventType ? eventType : "");

    lockForRead();
    SubscribeServerEventData* eventData = 
        (SubscribeServerEventData*) mEventDefinitions.find(&eventName);

    // Get the event specific info to find subscriptions interested in
    // this content
    if(eventData)
    {
        OsSysLog::add(FAC_SIP, PRI_DEBUG,
             "SipSubscribeServer::notifySubscribers received the request for sending out the notification for resourceId '%s', event type '%s'",
              resourceId, eventType);
              
        int numSubscriptions = 0;
        SipMessage** notifyArray = NULL;
        UtlString** acceptHeaderValuesArray = NULL;

        eventData->mpEventSpecificSubscriptionMgr->
           createNotifiesDialogInfo(resourceId,
                                                                            eventTypeKey,
                                                                            numSubscriptions,
                                                                            acceptHeaderValuesArray,
                                                                            notifyArray);

        OsSysLog::add(FAC_SIP, PRI_DEBUG,
             "SipSubscribeServer::notifySubscribers numSubscriptions for %s = %d",
              resourceId, numSubscriptions);

        // Setup and send a NOTIFY for each subscription interested in
        // this resourcesId and eventTypeKey
        SipMessage* notify = NULL;
        for(int notifyIndex = 0;
            notifyArray != NULL && 
              notifyIndex < numSubscriptions && 
              notifyArray[notifyIndex] != NULL;
            notifyIndex++)
        {
            notify = notifyArray[notifyIndex];

            // Fill in the NOTIFY request body/content
            eventData->mpEventSpecificHandler->
                    getNotifyContent(resourceId,
                    eventTypeKey,
                    eventType,
                    *(eventData->mpEventSpecificContentMgr),
                    *(acceptHeaderValuesArray[notifyIndex]),
                    *notify);

            // Send the NOTIFY request
            eventData->mpEventSpecificUserAgent->send(*notify);
        }

        // Free up the NOTIFY requests and accept header field values
        eventData->mpEventSpecificSubscriptionMgr->
                freeNotifies(numSubscriptions, 
                acceptHeaderValuesArray,
                notifyArray);
    }

    // event type not enabled
    else
    {
        OsSysLog::add(FAC_SIP, PRI_ERR,
            "SipSubscribeServer::notifySubscribers event type: %s not enabled",
            eventName.data());
    }

    unlockForRead();

    return(notifiedSubscribers);
}
UtlBoolean SipPublishServer::handlePublish(const SipMessage& publishRequest)
{
    UtlBoolean handledPublish = FALSE;
    UtlString eventName;
    publishRequest.getEventField(&eventName, NULL);

    // Not modifying the PublishServerEventData, just reading it
    lockForRead();

    // Get the event specific handler and information
    PublishServerEventData* eventPackageInfo = (PublishServerEventData*)
        mEventDefinitions.find(&eventName);

    // We handle this event type
    if(eventPackageInfo)
    {
        handledPublish = TRUE;
        UtlString resourceId;
        UtlString eventTypeKey;
        SipPublishServerEventStateCompositor* compositor =
            eventPackageInfo->mpEventSpecificStateCompositor;

        // Get the keys used to identify the event state content
        compositor->getKeys(publishRequest,
                            resourceId,
                            eventTypeKey);

        SipMessage publishResponse;

        // Check if authenticated (or if it needs to be authenticated)
        if(compositor->isAuthenticated(publishRequest,
                                       resourceId,
                                       eventTypeKey,
                                       publishResponse))
        {
            // Check if authorized (or if authorization is required)
            if(compositor->isAuthorized(publishRequest,
                                        resourceId,
                                        eventTypeKey,
                                        publishResponse))
            {
                // The publication is allowed, so process the PUBLISH request
                
                // Modify the expiration if neccessary
                int expiration;
                if (publishRequest.getExpiresField(&expiration))
                {
                    // Check whether the expiration is too brief
                    if (!eventPackageInfo->mpEventSpecificStateMgr->checkExpiration(&expiration))
                    {
                         OsSysLog::add(FAC_SIP, PRI_ERR, 
                                       "SipPublishServer::handlePublish interval too brief");
               
                         publishResponse.setResponseData(&publishRequest,
                                                         SIP_TOO_BRIEF_CODE, SIP_TOO_BRIEF_TEXT);
                         publishResponse.setMinExpiresField(expiration);
                         
                         mpDefaultUserAgent->send(publishResponse);
                         
                         unlockForRead();
                     
                         return(handledPublish);
                    }
                }
                
                // Generate a new entity tag
                UtlString entity;
                eventPackageInfo->mpEventSpecificStateMgr->generateETag(entity);
                
                 UtlString sipIfMatchField;
                if (publishRequest.getSipIfMatchField(sipIfMatchField))
                {
                    // Check whether the SIP-If-Match header matches with an existing one
                    if (eventPackageInfo->mpEventSpecificStateMgr->publishExists(sipIfMatchField))
                    {
                        if (expiration == 0)
                        {
                            // Remove the publication
                            eventPackageInfo->mpEventSpecificStateMgr->removePublish(sipIfMatchField);
                        }
                        else
                        {
                            // Update the publication
                            eventPackageInfo->mpEventSpecificStateMgr->updatePublish(sipIfMatchField, entity, resourceId, eventTypeKey, expiration);
                        }
                    }
                    else
                    {
                         OsSysLog::add(FAC_SIP, PRI_ERR, 
                                       "SipPublishServer::handlePublish interval too brief");
               
                         publishResponse.setResponseData(&publishRequest,
                                                         SIP_CONDITIONAL_REQUEST_FAILED_CODE,
                                                         SIP_CONDITIONAL_REQUEST_FAILED_TEXT);
                         
                         mpDefaultUserAgent->send(publishResponse);
                         
                         unlockForRead();
                     
                         return(handledPublish);
                    }
                }
                else
                {
                    // Initial publish
                    eventPackageInfo->mpEventSpecificStateMgr->addPublish(entity, resourceId, eventTypeKey, expiration);
                }
                
                publishResponse.setResponseData(&publishRequest, 
                                                SIP_ACCEPTED_CODE,
                                                SIP_ACCEPTED_TEXT);
                publishResponse.setExpiresField(expiration);

                // Send the response ASAP to minimize resend handling of request
                 eventPackageInfo->mpEventSpecificUserAgent->send(publishResponse);
            }
            // Not authorized
            else
            {
                // Send the response
                eventPackageInfo->mpEventSpecificUserAgent->send(publishResponse);
            }
        }

        // Not authenticated
        else
        {
            // Send the response
            eventPackageInfo->mpEventSpecificUserAgent->send(publishResponse);
        }
    }


    // We should not have received SUBSCRIBE requests for this event type
    // This event type has not been enabled in this SubscribeServer
    else
    {
        OsSysLog::add(FAC_SIP, PRI_ERR, 
            "SipPublishServer::handlePublish event type: %s not enabled",
            eventName.data());

        SipMessage eventTypeNotHandled;
        eventTypeNotHandled.setResponseData(&publishRequest,
                                            SIP_BAD_EVENT_CODE, SIP_BAD_EVENT_TEXT);

        mpDefaultUserAgent->send(eventTypeNotHandled);
    }
    unlockForRead();

    return(handledPublish);
}