void SipPresenceMonitor::getState(const Url& aor, UtlString& status) { UtlString contact; aor.getUserId(contact); contact += mHostAndPort; // Make the contact be a proper URI by prepending "sip:". contact.prepend("sip:"); UtlContainable* foundValue; mLock.acquire(); foundValue = mPresenceEventList.findValue(&contact); if (foundValue) { SipPresenceEvent* presenceEvent = dynamic_cast <SipPresenceEvent *> (foundValue); UtlString id; makeId(id, contact); presenceEvent->getTuple(id)->getStatus(status); OsSysLog::add(FAC_SIP, PRI_ERR, "SipPresenceMonitor::getState contact %s state = %s", contact.data(), status.data()); } else { OsSysLog::add(FAC_SIP, PRI_ERR, "SipPresenceMonitor::getState contact %s does not exist", contact.data()); status = STATUS_CLOSED; } mLock.release(); }
void SipImpliedSubscriptions::buildSubscribeRequest( const SipMessage& registerMessage ,int duration ,SipMessage& subscribeRequest ,UtlString& callId ,UtlString& fromTag ,UtlString& fromUri ) { UtlString registrationValue; UtlString tagNameValuePair; UtlString contactUri; int sequenceNumber = 0; // Get the From URL, and change the tag Url fromUrl; registerMessage.getFromUrl( fromUrl ); fromUrl.removeFieldParameter("tag"); // discard from tag from REGISTER registerMessage.getFromUri( &fromUri ); (void) registerMessage.getContactUri(0, &contactUri); (void) registerMessage.getCSeqField(&sequenceNumber, ®istrationValue); Url toUrl; registerMessage.getToUrl( toUrl ); toUrl.removeFieldParameter("tag"); UtlString toUri; registerMessage.getToUri( &toUri ); registerMessage.getCallIdField( &callId ); callId.prepend("implied-mwi-"); // Build a from tag for the SUBSCRIBE // - hash the call id so that it will be the same on each refresh UtlString callIdHash; NetMd5Codec::encode( callId.data(), callIdHash ); fromUrl.setFieldParameter("tag", callIdHash.data() ); fromTag = callIdHash; // for constructing the nonce subscribeRequest.setVoicemailData( fromUrl.toString() // From: ,toUrl.toString() // To: ,toUri.data() // request URI ,contactUri.data() // taken from registration ,callId.data() ,++sequenceNumber ,duration ); /* * Rewrite the event field to add our extension parameter to * ensure that the registration and subscription are synchronized. */ const char* standardEventHeader = subscribeRequest.getHeaderValue(0, SIP_EVENT_FIELD); UtlString extendedEventHeader(standardEventHeader); extendedEventHeader.append(";" SIPX_IMPLIED_SUB "="); char durationString[12]; sprintf(durationString, "%d", duration); extendedEventHeader.append(durationString); subscribeRequest.setHeaderValue(SIP_EVENT_FIELD, extendedEventHeader.data(), 0); }
/// Add identity info to a message. bool SipXauthIdentity::insert(SipMessage & message, HeaderName headerName, const OsDateTime * timestamp) { // Don't proceed if the encapsulated identity is invalid if (!mIsValidIdentity) { Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "SipXauthIdentity::insert: " "encapsulated SipXauthIdentity is invalid"); } else { // make sure no existing identity in the message remove(message, headerName); // set Call-Id and from-tag for the signature calculation UtlString callId; UtlString fromTag; Url fromUrl; message.getCallIdField(&callId); message.getFromUrl(fromUrl); fromUrl.getFieldParameter("tag", fromTag); OsDateTime now; OsDateTime::getCurTime(now); if (NULL==timestamp) { timestamp = &now; } UtlString value; encode(value, callId, fromTag, *timestamp); // Insert displayName if it is an P-Asserted-Identity header. if (headerName == SipXauthIdentity::PAssertedIdentityHeaderName) { UtlString displayName; fromUrl.getDisplayName(displayName); value.prepend(displayName.data()); } message.addHeaderField(headerName, value.data()); } return mIsValidIdentity; }
// Returns TRUE if the requested state is different from the current state. bool SipPresenceMonitor::setStatus(const Url& aor, const Status value) { if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG)) { UtlString aorString; aor.toString(aorString); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::setStatus aor = '%s', value = %d %s", aorString.data(), value, (value == StateChangeNotifier::PRESENT ? "PRESENT" : value == StateChangeNotifier::AWAY ? "AWAY" : "UNKNOWN")); } bool result = false; UtlString contact; aor.getUserId(contact); contact += mHostAndPort; // Make the contact be a proper URI by prepending "sip:". contact.prepend("sip:"); // Create a presence event package and store it in the publisher SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(contact); UtlString id; makeId(id, contact); Tuple* tuple = new Tuple(id.data()); tuple->setStatus(value == StateChangeNotifier::PRESENT ? STATUS_OPEN : STATUS_CLOSED); tuple->setContact(contact, 1.0); sipPresenceEvent->insertTuple(tuple); // Add the SipPresenceEvent object to the presence event list. result = addPresenceEvent(contact, sipPresenceEvent); return result; }
UtlBoolean AppAgentSubscribePolicy::getKeys(const SipMessage& subscribeRequest, UtlString& resourceId, UtlString& eventTypeKey, UtlString& eventType) { // default resourceId is the identity, but we want it from the From URI UtlString uriString; subscribeRequest.getFromUri(&uriString); Url uri(uriString); uri.getIdentity(resourceId); // Make the resourceId be a proper URI by prepending "sip:". resourceId.prepend("sip:"); // Default event key is the event type with no parameters, but we want the full thing (dialog;sla) subscribeRequest.getEventField(eventTypeKey); // Event type is the event type with no parameters. subscribeRequest.getEventFieldParts(&eventType); return(TRUE); }
UtlBoolean SipSubscribeServerEventHandler::getKeys(const SipMessage& subscribeRequest, UtlString& resourceId, UtlString& eventTypeKey, UtlString& eventType) { // default resourceId is the identity UtlString uriString; subscribeRequest.getRequestUri(&uriString); Url uri(uriString); uri.getIdentity(resourceId); // Make the resourceId be a proper URI by prepending "sip:". resourceId.prepend("sip:"); // Default event key is the event type with no parameters subscribeRequest.getEventField(&eventTypeKey, NULL); // Event type is the same. eventType = eventTypeKey; return(TRUE); }
// Add to the HttpBody the current state of the resource. void ResourceCached::generateBody(UtlString& rlmi, HttpBody& body, UtlBoolean consolidated, const UtlString& nameXml, const UtlString& displayName) const { // Generate the preamble for the resource. rlmi += " <resource uri=\""; XmlEscape(rlmi, *(static_cast <const UtlString*> (this))); rlmi += "\">\r\n"; if (!nameXml.isNull()) { rlmi += " "; rlmi += nameXml; } if (consolidated) { // If consolidating resource instances, generate the XML for the // unified resource instance. rlmi += " <instance id=\"consolidated\" state=\"active\""; UtlString contentBodyPartCid; // Use the count of parts in 'body' to generate a unique identifier for // each part. contentBodyPartCid.appendNumber(body.getMultipartCount()); contentBodyPartCid += "@"; contentBodyPartCid += getResourceListServer()->getDomainName(); rlmi += " cid=\""; rlmi += contentBodyPartCid; rlmi += "\""; // Now add the <...> and use it in the header. contentBodyPartCid.prepend("<"); contentBodyPartCid.append(">"); // Create a single HttpBody to contain the unified dialog event. UtlString dialog_event; // XML declaration is optional, but Broadworks uses it. dialog_event += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; dialog_event += BEGIN_DIALOG_INFO; dialog_event += VERSION_EQUAL; dialog_event += "\""; // The consolidated dialog events need to have persistent // version numbers, as they all have the same instance id. // So we use a global version number in the ResourceListSet. dialog_event.appendNumber(getResourceListSet()->getVersion()); dialog_event += "\""; dialog_event += STATE_EQUAL; dialog_event += "\"full\""; dialog_event += ENTITY_EQUAL; dialog_event += "\""; dialog_event += *(static_cast <const UtlString*> (this)); dialog_event += "\">\r\n"; // Save the length of dialog_event, so we can tell later if // any <dialog>s have been added to it. unsigned int preamble_length = dialog_event.length(); // Call the ContactSet to generate the consolidated dialog event body. if (mContactSetP) { mContactSetP->generateBody(dialog_event, body, consolidated, displayName); } // If no <dialog>s have been added, we have to add a dummy // <dialog> to carry the display name. if (dialog_event.length() == preamble_length) { dialog_event += "<dialog id=\";\"><state>terminated</state><local><identity display=\""; XmlEscape(dialog_event, displayName); dialog_event += "\">"; XmlEscape(dialog_event, *(static_cast <const UtlString*> (this))); dialog_event += "</identity></local></dialog>\r\n"; } dialog_event += END_DIALOG_INFO; // Insert the consolidated dialog event body into the multiplart body. HttpBody content_body(dialog_event.data(), dialog_event.length(), DIALOG_EVENT_CONTENT_TYPE); UtlDList content_body_parameters; content_body_parameters.append( new NameValuePair(HTTP_CONTENT_ID_FIELD, contentBodyPartCid)); body.appendBodyPart(content_body, content_body_parameters); content_body_parameters.destroyAll(); // Finish the <instance> element. rlmi += "/>\r\n"; } else { // Call the ContactSet to do the work. if (mContactSetP) { mContactSetP->generateBody(rlmi, body, consolidated, displayName); } } // Generate the postamble for the resource. rlmi += " </resource>\r\n"; }
// Add to the HttpBody the current state of the resource. void ResourceInstance::generateBody(UtlString& rlmi, HttpBody& body, UtlBoolean consolidated, const UtlString& displayName) const { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceInstance::generateBody mInstanceName = '%s', consolidated = %d, displayName = '%s', mContentPresent = %d", mInstanceName.data(), consolidated, displayName.data(), mContentPresent); if (consolidated) { if (mContentPresent) { // If this is a consolidated dialog event list, edit the // stored XML into the right form and append each dialog // to the resource list event notice. TiXmlUtlStringWriter writer(&rlmi); // Iterate through all the <dialog> elements. UtlHashMapIterator itor(mXmlDialogs); UtlContainable* id; while ((id = itor())) { UtlVoidPtr* p = dynamic_cast <UtlVoidPtr*> (itor.value()); TiXmlElement* dialog_element = static_cast <TiXmlElement*> (p->getValue()); // Now that we've got a <dialog> element, edit it to fit // into a consolidated event notice. // Get the display name right. // Find the <local> element, which we know exists due to // earlier processing. TiXmlNode* local = dialog_element->FirstChild("local"); // Find the <local><identity> element, which we know // exists due to earlier processing. TiXmlNode* identity = local->FirstChild("identity"); // Update the display attribute, as that is what will show // on the phone. identity->ToElement()-> SetAttribute("display", displayName); // Un-parse the dialog into the string for storage. writer << *dialog_element; writer << "\r\n"; } } } else { // Generate the XML for the instance. rlmi += " <instance id=\""; XmlEscape(rlmi, mInstanceName); rlmi += "\" state=\""; // Subscription states don't require escaping. rlmi += mSubscriptionState; rlmi += "\""; // Generate the body part for the instance, if necessary. if (mContentPresent) { UtlString contentBodyPartCid; // Use the count of parts in 'body' to generate a unique identifier for // each part. contentBodyPartCid.appendNumber(body.getMultipartCount()); contentBodyPartCid += "@"; contentBodyPartCid += getResourceListServer()->getDomainName(); rlmi += " cid=\""; rlmi += contentBodyPartCid; rlmi += "\""; // Now add the <...> and use it in the header. contentBodyPartCid.prepend("<"); contentBodyPartCid.append(">"); HttpBody content_body(mContent.data(), mContent.length(), getResourceListServer()->getContentType()); UtlDList content_body_parameters; content_body_parameters.append( new NameValuePair(HTTP_CONTENT_ID_FIELD, contentBodyPartCid)); body.appendBodyPart(content_body, content_body_parameters); content_body_parameters.destroyAll(); } rlmi += "/>\r\n"; } }