UtlBoolean TestRegistrar::handleRegisterRequest(SipMessage message) { UtlBoolean messageProcessed = false; SipMessage finalResponse; UtlString responseToAddress; UtlString protocol; int responseToPort; int seqNum; UtlString method; UtlString contactField; int expires; static int retrySeqNum = 0; UtlString callId; message.getCallIdField(&callId); message.getContactField(0, contactField); message.getExpiresField(&expires); message.getCSeqField(&seqNum, &method); message.getFromAddress(&responseToAddress, &responseToPort, &protocol); finalResponse.setContactField(contactField); finalResponse.setExpiresField(expires); finalResponse.setFromField("sip:127.0.0.1:5070", 5070); finalResponse.setSendAddress(contactField, responseToPort); finalResponse.setToField(contactField, responseToPort, protocol); finalResponse.setUserAgentField("TestRegistrar"); // finalResponse.setRegisterData(responseToAddress, contactField, "127.0.0.1", contactField, callId, seqNum); if (contactField.contains("anon")) // anonymous user doesnt need authentication, just say ok { finalResponse.setResponseData(&message, 200, "OK"); } else if (contactField.contains("mike")) // mike requires registration, say 401 { UtlString realm; UtlString requestUser; UtlString requestRealm; UtlString requestNonce; UtlString uriParam; // TBD - 25-jan-2010 work might be needed if these tests are re-enabled message.getDigestAuthorizationData( &requestUser, &requestRealm, &requestNonce, NULL, NULL, &uriParam, NULL, // TBD cnonce NULL, // TBD nonceCount NULL, // TBD qop HttpMessage::SERVER, 0); if (seqNum == retrySeqNum) // if this is a retry response { // if they've sent any auth field, just accept it. // TODO: figure out if a username and password has been encrypted and sent. finalResponse.setCSeqField(++seqNum, SIP_REGISTER_METHOD); finalResponse.setResponseData(&message, 200, "OK"); } else { message.getCSeqField(&seqNum, &method); finalResponse.setCSeqField(++seqNum, method); retrySeqNum = seqNum; #ifdef _WIN32 finalResponse.setAuthenticateData("md5", "TestRegistrar", NULL, NULL, NULL, HttpMessage::HttpEndpointEnum::SERVER ); #else finalResponse.setAuthenticateData("md5", "TestRegistrar", NULL, NULL, NULL, HttpMessage::SERVER ); #endif finalResponse.setResponseData(&message, 401, "Not authorized"); } } else if (contactField.contains("xyzzy")) { // this is our special username that will cause a response // to be echoed back with the 3 digit value after xyzzy. // for instance, the contact xyzzy401 will cause a 401 response int pos = contactField.first("xyzzy"); char szCode[4]; szCode[0] = contactField[pos + 5]; szCode[1] = contactField[pos + 6]; szCode[2] = contactField[pos + 7]; szCode[3] = '\0'; finalResponse.setResponseData(&message, atoi(szCode), "OK"); } mpUserAgent->send(finalResponse); return messageProcessed; }
UtlBoolean SipSubscriptionMgr::insertDialogInfo(const SipMessage& subscribeRequest, const UtlString& resourceId, const UtlString& eventTypeKey, UtlString& subscribeDialogHandle, UtlBoolean& isNew, UtlBoolean& isSubscriptionExpired, SipMessage& subscribeResponse) { isNew = FALSE; UtlBoolean subscriptionSucceeded = FALSE; UtlString dialogHandle; subscribeRequest.getDialogHandle(dialogHandle); SubscriptionServerState* state = NULL; int expiration = -1; isSubscriptionExpired = TRUE; // If this is an early dialog we need to make it an established dialog. if(SipDialog::isEarlyDialog(dialogHandle)) { UtlString establishedDialogHandle; if(mDialogMgr.getEstablishedDialogHandleFor(dialogHandle, establishedDialogHandle)) { OsSysLog::add(FAC_SIP, PRI_WARNING, "Incoming early SUBSCRIBE dialog: %s matches established dialog: %s", dialogHandle.data(), establishedDialogHandle.data()); } // make up a To tag and set it UtlString toTag; CallId::getNewTag(dialogHandle.data(), toTag); // Get and validate the expires period // This potentially should be delegated to the event handler specifics if(!subscribeRequest.getExpiresField(&expiration)) { expiration = mDefaultExpiration; } else if(expiration > mMaxExpiration) { expiration = mMaxExpiration; } // Acceptable expiration, create a subscription and dialog if(expiration >= mMinExpiration || expiration == 0 || // :WORKAROUND: Also allow expiration == 1, to support the // 1-second subscriptions the pick-up agent makes because // current Snom phones do not respond to 0-second subscriptions. // See XPB-399 and ENG-319. expiration == 1) { // Create a dialog and subscription state even if // the expiration is zero as we need the dialog info // to route the one-time NOTIFY. The immediately // expired dialog will be garbage collected. SipMessage* subscribeCopy = new SipMessage(subscribeRequest); subscribeCopy->setToFieldTag(toTag); // Re-get the dialog handle now that the To tag is set subscribeCopy->getDialogHandle(dialogHandle); // Create the dialog mDialogMgr.createDialog(*subscribeCopy, FALSE, dialogHandle); isNew = TRUE; // Create a subscription state state = new SubscriptionServerState(); *((UtlString*) state) = dialogHandle; state->mEventTypeKey = eventTypeKey; state->mpLastSubscribeRequest = subscribeCopy; state->mResourceId = resourceId; subscribeCopy->getAcceptField(state->mAcceptHeaderValue); long now = OsDateTime::getSecsSinceEpoch(); state->mExpirationDate = now + expiration; // TODO: currently the SipSubsribeServer does not handle timeout // events to send notifications that the subscription has ended. // So we do not set a timer at the end of the subscription state->mpExpirationTimer = NULL; // Create the index by resourceId and eventTypeKey key SubscriptionServerStateIndex* stateKey = new SubscriptionServerStateIndex; *((UtlString*) stateKey) = resourceId; stateKey->append(eventTypeKey); stateKey->mpState = state; subscribeResponse.setResponseData(subscribeCopy, SIP_ACCEPTED_CODE, SIP_ACCEPTED_TEXT, NULL); subscribeResponse.setExpiresField(expiration); subscribeCopy->getDialogHandle(subscribeDialogHandle); lock(); mSubscriptionStatesByDialogHandle.insert(state); mSubscriptionStateResourceIndex.insert(stateKey); if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG)) { UtlString requestContact; subscribeRequest.getContactField(0, requestContact); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSubscriptionMgr::insertDialogInfo insert early-dialog subscription for dialog handle '%s', key '%s', contact '%s', mExpirationDate %ld", state->data(), stateKey->data(), requestContact.data(), state->mExpirationDate); } // Not safe to touch these after we unlock stateKey = NULL; state = NULL; subscribeCopy = NULL; unlock(); subscriptionSucceeded = TRUE; // One time subscribe? isSubscriptionExpired = expiration == 0; } // Expiration too small else { // Set expiration too small error subscribeResponse.setResponseData(&subscribeRequest, SIP_TOO_BRIEF_CODE, SIP_SUB_TOO_BRIEF_TEXT); subscribeResponse.setMinExpiresField(mMinExpiration); isSubscriptionExpired = TRUE; } } // Not an early dialog handle -- The dialog for this message may already exist else { // Get and validate the expires period // This potentially should be delegated to the event handler specifics if(!subscribeRequest.getExpiresField(&expiration)) { expiration = mDefaultExpiration; } else if(expiration > mMaxExpiration) { expiration = mMaxExpiration; } // Acceptable expiration, create a subscription and dialog if(expiration > mMinExpiration || expiration == 0) { // Update the dialog state mDialogMgr.updateDialog(subscribeRequest, dialogHandle); // Get the subscription state and update that // TODO: This assumes that no one reuses the same dialog // to subscribe to more than one event type. mSubscriptionStatesByDialogHandle // will need to be changed to a HashBag and we will need to // search through to find a matching event type lock(); state = (SubscriptionServerState*) mSubscriptionStatesByDialogHandle.find(&dialogHandle); if(state) { long now = OsDateTime::getSecsSinceEpoch(); state->mExpirationDate = now + expiration; if(state->mpLastSubscribeRequest) { delete state->mpLastSubscribeRequest; } state->mpLastSubscribeRequest = new SipMessage(subscribeRequest); subscribeRequest.getAcceptField(state->mAcceptHeaderValue); // Set the contact to the same request URI that came in UtlString contact; subscribeRequest.getRequestUri(&contact); // Add the angle brackets for contact Url url(contact); url.includeAngleBrackets(); contact = url.toString(); subscribeResponse.setResponseData(&subscribeRequest, SIP_ACCEPTED_CODE, SIP_ACCEPTED_TEXT, contact); subscribeResponse.setExpiresField(expiration); subscriptionSucceeded = TRUE; isSubscriptionExpired = FALSE; subscribeDialogHandle = dialogHandle; } // No state, but SUBSCRIBE had a to-tag. else { SipMessage* subscribeCopy = new SipMessage(subscribeRequest); // Create the dialog mDialogMgr.createDialog(*subscribeCopy, FALSE, dialogHandle); isNew = TRUE; // Create a subscription state state = new SubscriptionServerState(); *((UtlString*)state) = dialogHandle; state->mEventTypeKey = eventTypeKey; state->mpLastSubscribeRequest = subscribeCopy; state->mResourceId = resourceId; subscribeCopy->getAcceptField(state->mAcceptHeaderValue); long now = OsDateTime::getSecsSinceEpoch(); state->mExpirationDate = now + expiration; // TODO: currently the SipSubsribeServer does not handle timeout // events to send notifications that the subscription has ended. // So we do not set a timer at the end of the subscription state->mpExpirationTimer = NULL; // Create the index by resourceId and eventTypeKey key SubscriptionServerStateIndex* stateKey = new SubscriptionServerStateIndex; *((UtlString*)stateKey) = resourceId; stateKey->append(eventTypeKey); stateKey->mpState = state; mSubscriptionStatesByDialogHandle.insert(state); mSubscriptionStateResourceIndex.insert(stateKey); if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG)) { UtlString requestContact; subscribeRequest.getContactField(0, requestContact); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSubscriptionMgr::insertDialogInfo insert subscription for key '%s', contact '%s', mExpirationDate %ld", stateKey->data(), requestContact.data(), state->mExpirationDate); } // Not safe to touch these after we unlock stateKey = NULL; state = NULL; subscribeCopy = NULL; // Set the contact to the same request URI that came in UtlString contact; subscribeRequest.getRequestUri(&contact); // Add the angle brackets for contact Url url(contact); url.includeAngleBrackets(); contact = url.toString(); subscribeResponse.setResponseData(&subscribeRequest, SIP_ACCEPTED_CODE, SIP_ACCEPTED_TEXT, contact); subscribeResponse.setExpiresField(expiration); subscriptionSucceeded = TRUE; // Unsubscribe if(expiration == 0) { isSubscriptionExpired = TRUE; } else { isSubscriptionExpired = FALSE; } subscribeDialogHandle = dialogHandle; } unlock(); } // Expiration too small else { // Set expiration too small error subscribeResponse.setResponseData(&subscribeRequest, SIP_TOO_BRIEF_CODE, SIP_SUB_TOO_BRIEF_TEXT); subscribeResponse.setMinExpiresField(mMinExpiration); isSubscriptionExpired = isExpired(dialogHandle); } } return(subscriptionSucceeded); }
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); }
UtlBoolean SipSubscriptionMgr::updateDialogInfo(const SipMessage& subscribeRequest, UtlString& resourceId, UtlString& eventTypeKey, UtlString& eventType, UtlString& subscribeDialogHandle, UtlBoolean& isNew, UtlBoolean& isSubscriptionExpired, SipMessage& subscribeResponse, SipSubscribeServerEventHandler& handler) { isNew = FALSE; UtlBoolean subscriptionSucceeded = FALSE; UtlString dialogHandle; subscribeRequest.getDialogHandle(dialogHandle); SubscriptionServerState* state = NULL; int expiration = -1; isSubscriptionExpired = TRUE; // Double check the sanity of the class attributes if(mMaxExpiration < mMinExpiration) { // This is an error case. Switch the values so that we do not // run into any negative expiration times. int tmp = mMaxExpiration; mMaxExpiration = mMinExpiration; mMinExpiration = tmp; OsSysLog::add(FAC_SIP, PRI_WARNING, "Swapping values as mMinExpiration => %d is greater than mMaxExpiration => %d", mMinExpiration, mMaxExpiration); } if(mMaxExpiration < mDefaultExpiration) { // This is an error case. Switch the values so that we do not // run into any negative expiration times. int tmp = mMaxExpiration; mMaxExpiration = mDefaultExpiration; mDefaultExpiration = tmp; OsSysLog::add(FAC_SIP, PRI_WARNING, "Swapping values as mDefaultExpiration => %d is greater than mMaxExpiration => %d", mDefaultExpiration, mMaxExpiration); } // Set the expires period randomly int spreadFloor = mMinExpiration*2; if(!subscribeRequest.getExpiresField(&expiration)) { // no expires field // spread it between the default expiration and max allowed expiration expiration = ( (rand() % (mMaxExpiration - mDefaultExpiration)) + mDefaultExpiration); } else if ( expiration >= mMaxExpiration ) { if (mMaxExpiration > spreadFloor) { // - spread it between the spreadFloor and the max allowed expiration expiration = ( (rand() % (mMaxExpiration - spreadFloor)) + spreadFloor); } else { // Max Expiration is smaller than the spreadFloor, hence // spread it between the min and the max allowed expiration expiration = ( (rand() % (mMaxExpiration - mMinExpiration)) + mMinExpiration); } } else if ( expiration > spreadFloor ) { // a normal (long) expiration // - spread it between the spreadFloor and the longest they asked for expiration = ( (rand() % (expiration - spreadFloor)) + spreadFloor); } else if ( expiration > mMinExpiration ) { // a short but greater than minimum expiration // - spread it between the min and the longest they asked for expiration = ( (rand() % (expiration - mMinExpiration)) + mMinExpiration); } // Cases where the expiration is less than the min value is handled below. // If this is an early dialog we need to make it an established dialog. if(SipDialog::isEarlyDialog(dialogHandle)) { UtlString establishedDialogHandle; if(mDialogMgr.getEstablishedDialogHandleFor(dialogHandle, establishedDialogHandle)) { OsSysLog::add(FAC_SIP, PRI_WARNING, "Incoming early SUBSCRIBE dialog: %s matches established dialog: %s", dialogHandle.data(), establishedDialogHandle.data()); } // make up a To tag and set it UtlString toTag; CallId::getNewTag(dialogHandle.data(), toTag); // Acceptable expiration, create a subscription and dialog if(expiration >= mMinExpiration || expiration == 0 || // :WORKAROUND: Also allow expiration == 1, to support the // 1-second subscriptions the pick-up agent makes because // current Snom phones do not respond to 0-second subscriptions. // See XPB-399 and ENG-319. expiration == 1) { // Call the event-specific function to determine the resource ID // and event type for this SUBSCRIBE. handler.getKeys(subscribeRequest, resourceId, eventTypeKey, eventType); // Create a dialog and subscription state even if // the expiration is zero as we need the dialog info // to route the one-time NOTIFY. The immediately // expired dialog will be garbage collected. SipMessage* subscribeCopy = new SipMessage(subscribeRequest); subscribeCopy->setToFieldTag(toTag); // Re-get the dialog handle now that the To tag is set subscribeCopy->getDialogHandle(dialogHandle); // Create the dialog mDialogMgr.createDialog(*subscribeCopy, FALSE, dialogHandle); isNew = TRUE; // Create a subscription state state = new SubscriptionServerState(); *((UtlString*) state) = dialogHandle; state->mEventTypeKey = eventTypeKey; state->mpLastSubscribeRequest = subscribeCopy; state->mResourceId = resourceId; subscribeCopy->getAcceptField(state->mAcceptHeaderValue); long now = OsDateTime::getSecsSinceEpoch(); state->mExpirationDate = now + expiration; // TODO: currently the SipSubsribeServer does not handle timeout // events to send notifications that the subscription has ended. // So we do not set a timer at the end of the subscription state->mpExpirationTimer = NULL; // Create the index by resourceId and eventTypeKey key SubscriptionServerStateIndex* stateKey = new SubscriptionServerStateIndex; *((UtlString*) stateKey) = resourceId; stateKey->append(eventTypeKey); stateKey->mpState = state; subscribeResponse.setResponseData(subscribeCopy, SIP_ACCEPTED_CODE, SIP_ACCEPTED_TEXT, NULL); subscribeResponse.setExpiresField(expiration); subscribeCopy->getDialogHandle(subscribeDialogHandle); lock(); mSubscriptionStatesByDialogHandle.insert(state); mSubscriptionStateResourceIndex.insert(stateKey); if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG)) { UtlString requestContact; subscribeRequest.getContactField(0, requestContact); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSubscriptionMgr::updateDialogInfo insert early-dialog subscription for dialog handle '%s', key '%s', contact '%s', mExpirationDate %ld", state->data(), stateKey->data(), requestContact.data(), state->mExpirationDate); } // Not safe to touch these after we unlock stateKey = NULL; state = NULL; subscribeCopy = NULL; unlock(); subscriptionSucceeded = TRUE; // One time subscribe? isSubscriptionExpired = expiration == 0; } // Expiration too small else { // Set expiration too small error subscribeResponse.setResponseData(&subscribeRequest, SIP_TOO_BRIEF_CODE, SIP_SUB_TOO_BRIEF_TEXT); subscribeResponse.setMinExpiresField(mMinExpiration); isSubscriptionExpired = TRUE; } } // Not an early dialog handle -- The dialog for this message should already exist else { // Acceptable expiration, create a subscription and dialog if(expiration > mMinExpiration || expiration == 0) { // Update the dialog state mDialogMgr.updateDialog(subscribeRequest, dialogHandle); // Get the subscription state and update that // TODO: This assumes that no one reuses the same dialog // to subscribe to more than one event type. mSubscriptionStatesByDialogHandle // will need to be changed to a HashBag and we will need to // search through to find a matching event type lock(); state = (SubscriptionServerState*) mSubscriptionStatesByDialogHandle.find(&dialogHandle); if(state) { // Update the expiration time. long now = OsDateTime::getSecsSinceEpoch(); state->mExpirationDate = now + expiration; // Record this SUBSCRIBE as the latest SUBSCRIBE request. if(state->mpLastSubscribeRequest) { delete state->mpLastSubscribeRequest; } state->mpLastSubscribeRequest = new SipMessage(subscribeRequest); subscribeRequest.getAcceptField(state->mAcceptHeaderValue); // Set our Contact to the same request URI that came in UtlString contact; subscribeRequest.getRequestUri(&contact); // Add the angle brackets to Contact, since it is a name-addr. Url url(contact); url.includeAngleBrackets(); contact = url.toString(); subscribeResponse.setResponseData(&subscribeRequest, SIP_ACCEPTED_CODE, SIP_ACCEPTED_TEXT, contact); subscribeResponse.setExpiresField(expiration); subscriptionSucceeded = TRUE; isSubscriptionExpired = FALSE; subscribeDialogHandle = dialogHandle; // Set the resource information so our caller can generate a NOTIFY. resourceId = state->mResourceId; eventTypeKey = state->mEventTypeKey; // Unfortuantely, we don't record the eventType separately. eventType = state->mEventTypeKey; } // No state, but SUBSCRIBE had a to-tag. else { // Unknown subscription. subscribeResponse.setResponseData(&subscribeRequest, SIP_BAD_SUBSCRIPTION_CODE, SIP_BAD_SUBSCRIPTION_TEXT); } unlock(); } // Expiration too small else { // Set expiration too small error subscribeResponse.setResponseData(&subscribeRequest, SIP_TOO_BRIEF_CODE, SIP_SUB_TOO_BRIEF_TEXT); subscribeResponse.setMinExpiresField(mMinExpiration); isSubscriptionExpired = isExpired(dialogHandle); } } return(subscriptionSucceeded); }