void WinReadWriteLock::unlock() { if (m_lock.Ptr == (PVOID)1) unlockForWrite(); else unlockForRead(); }
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); }
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); }
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); }
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); }
// 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(); }
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(¬ifyRequest); 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); }
// 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; }
/// 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(); }
// 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(¬ifyRequest); 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); }