// Generate the default content for presence status. void PresenceDefaultConstructor::generateDefaultContent(SipPublishContentMgr* contentMgr, const char* resourceId, const char* eventTypeKey, const char* eventType) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "PresenceDefaultConstructor::generateDefaultContent " "generating default content for resourceId '%s', " "eventTypeKey '%s', eventType '%s'", resourceId, eventTypeKey, eventType); // Create a presence event package and store it in the publisher. // This code parallels SipPresenceMonitor::setStatus. SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(resourceId); UtlString id; UtlString resource(resourceId); SipPresenceMonitor::makeId(id, resource); Tuple* tuple = new Tuple(id.data()); tuple->setStatus(DEFAULT_PRESENCE_STATUS); tuple->setContact(resourceId, 1.0); sipPresenceEvent->insertTuple(tuple); // Build its text version. sipPresenceEvent->buildBody(); // Publish the event (storing it for the resource), but set // noNotify to TRUE, because our caller will push the NOTIFYs. contentMgr->publish(resourceId, eventTypeKey, eventType, 1, &(HttpBody*&) sipPresenceEvent, TRUE); }
bool SipPresenceMonitor::addPresenceEvent(UtlString& contact, SipPresenceEvent* presenceEvent) { bool requiredPublish = false; if (mPresenceEventList.find(&contact) == NULL) { requiredPublish = true; OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent adding the presenceEvent %p for contact %s", presenceEvent, contact.data()); } else { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent presenceEvent %p for contact %s already exists, just update the content.", presenceEvent, contact.data()); // Get the object from the presence event list UtlContainable* oldKey; UtlContainable* foundValue; foundValue = mPresenceEventList.findValue(&contact); SipPresenceEvent* oldPresenceEvent = dynamic_cast <SipPresenceEvent *> (foundValue); UtlString oldStatus, status; UtlString id; NetMd5Codec::encode(contact, id); oldPresenceEvent->getTuple(id)->getStatus(oldStatus); presenceEvent->getTuple(id)->getStatus(status); if (status.compareTo(oldStatus) != 0) { requiredPublish = true; oldKey = mPresenceEventList.removeKeyAndValue(&contact, foundValue); delete oldKey; OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent remove the presenceEvent %p for contact %s", oldPresenceEvent, contact.data()); if (oldPresenceEvent) { delete oldPresenceEvent; } } } if (requiredPublish) { // Insert it into the presence event list presenceEvent->buildBody(); mPresenceEventList.insertKeyAndValue(new UtlString(contact), presenceEvent); if (mToBePublished) { // Publish the content to the resource list publishContent(contact, presenceEvent); } // Notify the state change notifyStateChange(contact, presenceEvent); } return requiredPublish; }
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(); }
// 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; }
bool SipPresenceMonitor::setStatus(const Url& aor, const Status value) { bool result = false; UtlString contact; aor.getIdentity(contact); // Create a presence event package and store it in the publisher SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(contact); UtlString id; NetMd5Codec::encode(contact, id); Tuple* tuple = new Tuple(id.data()); if (value == StateChangeNotifier::PRESENT) { tuple->setStatus(STATUS_OPEN); tuple->setContact(contact, 1.0); } else { if (value == StateChangeNotifier::AWAY) { tuple->setStatus(STATUS_CLOSE); tuple->setContact(contact, 1.0); } } sipPresenceEvent->insertTuple(tuple); // Add the SipPresenceEvent object to the subscribe list result = addPresenceEvent(contact, sipPresenceEvent); return result; }
// Write the presence events to the persistent file. void SipPresenceMonitor::writePersistentFile() { mLock.acquire(); // Create an empty document TiXmlDocument document; // Create a hard coded standalone declaration section document.Parse("<?xml version=\"1.0\" standalone=\"yes\"?>"); // Create the root node container TiXmlElement itemsElement ("items"); itemsElement.SetAttribute("type", sType.data()); itemsElement.SetAttribute("xmlns", sXmlNamespace.data()); int timeNow = (int)OsDateTime::getSecsSinceEpoch(); itemsElement.SetAttribute("timestamp", timeNow); // mPresenceEventList is a hash map that maps contacts to SipPresenceEvents. // SipPresenceEvents are hash maps of contacts to Tuples. In practice, // a SipPresenceEvent has only one Tuple. (And if it had more, there // would be no way to discover what they are, as there is no iterator.) // Tuples are triples: id, contact, status. // Loop through all the events in mPresenceEventList. UtlHashMapIterator iterator(mPresenceEventList); UtlString* contact; while ((contact = dynamic_cast <UtlString*> (iterator()))) { // Create an item container TiXmlElement itemElement ("item"); // Get the SipPresenceEvent. SipPresenceEvent* event = dynamic_cast <SipPresenceEvent*> (iterator.value()); // Calculate the id of the Tuple. UtlString id; makeId(id, *contact); // Get the Tuple. Tuple* tuple = event->getTuple(id); // Get the status. UtlString status; tuple->getStatus(status); // Construct the <item>. TiXmlElement id_element("id"); TiXmlText id_content(id); id_element.InsertEndChild(id_content); itemElement.InsertEndChild(id_element); TiXmlElement contact_element("contact"); TiXmlText contact_content(contact->data()); contact_element.InsertEndChild(contact_content); itemElement.InsertEndChild(contact_element); TiXmlElement status_element("status"); TiXmlText status_content(status); status_element.InsertEndChild(status_content); itemElement.InsertEndChild(status_element); // Add the <item> element to the <items> element. itemsElement.InsertEndChild ( itemElement ); } // Attach <items> to the root node to the document document.InsertEndChild(itemsElement); document.SaveFile(mPersistentFile); mLock.release(); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitorPersistenceTask::writePersistentFile file written"); }
// Read the presence events from the persistent file. void SipPresenceMonitor::readPersistentFile() { mLock.acquire(); // Initialize Tiny XML document object. TiXmlDocument document; TiXmlNode* items_node; if ( // Load the XML into it. document.LoadFile(mPersistentFile.data()) && // Find the top element, which should be an <items>. (items_node = document.FirstChild("items")) != NULL && items_node->Type() == TiXmlNode::ELEMENT) { // Find all the <item> elements. int item_seq_no = 0; for (TiXmlNode* item_node = 0; (item_node = items_node->IterateChildren("item", item_node)); ) { if (item_node->Type() == TiXmlNode::ELEMENT) { item_seq_no++; TiXmlElement* item_element = item_node->ToElement(); // Process the <item> element. bool item_valid = true; // Process the 'id' child. UtlString id; TiXmlNode* id_node = item_element->FirstChild("id"); if (id_node && id_node->Type() == TiXmlNode::ELEMENT) { textContentShallow(id, id_node); if (id.isNull()) { // Id null. OsSysLog::add(FAC_ACD, PRI_ERR, "id child of <item> was null"); item_valid = false; } } else { // Id missing. OsSysLog::add(FAC_ACD, PRI_ERR, "id child of <item> was missing"); item_valid = false; } // Process the 'contact' child. UtlString contact; TiXmlNode* contact_node = item_element->FirstChild("contact"); if (contact_node && contact_node->Type() == TiXmlNode::ELEMENT) { textContentShallow(contact, contact_node); if (contact.isNull()) { // Contact null. OsSysLog::add(FAC_ACD, PRI_ERR, "contact child of <item> was null"); item_valid = false; } } else { // Contact missing. OsSysLog::add(FAC_ACD, PRI_ERR, "contact child of <item> was missing"); item_valid = false; } // Process the 'status' child. UtlString status; TiXmlNode* status_node = item_element->FirstChild("status"); if (status_node && status_node->Type() == TiXmlNode::ELEMENT) { textContentShallow(status, status_node); if (status.isNull()) { // Status null. OsSysLog::add(FAC_ACD, PRI_ERR, "status child of <item> was null"); item_valid = false; } } else { // Status missing. OsSysLog::add(FAC_ACD, PRI_ERR, "status child of <item> was missing"); item_valid = false; } OsSysLog::add(FAC_ACD, PRI_DEBUG, "SipPresenceMonitor::readPersistentFile row: id = '%s', contact = '%s', status = '%s'", id.data(), contact.data(), status.data()); if (item_valid) { // Create a presence event package and store it in // mPresenceEventList. SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(contact); Tuple* tuple = new Tuple(id.data()); tuple->setStatus(status); tuple->setContact(contact, 1.0); sipPresenceEvent->insertTuple(tuple); sipPresenceEvent->buildBody(); mPresenceEventList.insertKeyAndValue(new UtlString(contact), sipPresenceEvent); } else { OsSysLog::add(FAC_ACD, PRI_ERR, "In presence status file '%s', <item> number %d had invalid or incomplete information. The readable information was: id = '%s', contact = '%s', status = '%s'", mPersistentFile.data(), item_seq_no, id.data(), contact.data(), status.data()); } } } } else { // Report error parsing file. OsSysLog::add(FAC_ACD, PRI_CRIT, "Presence status file '%s' could not be parsed.", mPersistentFile.data()); } mLock.release(); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitorPersistenceTask::readPersistentFile done"); }
// Returns TRUE if the requested state is different from the current state. bool SipPresenceMonitor::addPresenceEvent(UtlString& contact, SipPresenceEvent* presenceEvent) { mLock.acquire(); bool requiredPublish = false; if (mPresenceEventList.find(&contact) == NULL) { requiredPublish = true; OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent adding presenceEvent %p for contact %s", presenceEvent, contact.data()); } else { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent presenceEvent %p for contact %s already exists, updating its contents.", presenceEvent, contact.data()); // Get the object from the presence event list UtlContainable* oldKey; UtlContainable* foundValue; foundValue = mPresenceEventList.findValue(&contact); SipPresenceEvent* oldPresenceEvent = dynamic_cast <SipPresenceEvent *> (foundValue); UtlString oldStatus, status; UtlString id; makeId(id, contact); oldPresenceEvent->getTuple(id)->getStatus(oldStatus); presenceEvent->getTuple(id)->getStatus(status); if (status.compareTo(oldStatus) != 0) { requiredPublish = true; // Since we will be saving a new value, remove the old one. oldKey = mPresenceEventList.removeKeyAndValue(&contact, foundValue); delete oldKey; if (oldPresenceEvent) { delete oldPresenceEvent; } } } if (requiredPublish) { // Insert it into the presence event list. presenceEvent->buildBody(); mPresenceEventList.insertKeyAndValue(new UtlString(contact), presenceEvent); if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG)) { UtlString b; ssize_t l; presenceEvent->getBytes(&b, &l); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent presenceEvent %p for contact '%s' body '%s' is different from previous presenceEvent", presenceEvent, contact.data(), b.data()); } if (mToBePublished) { // Publish the content to the resource list. publishContent(contact, presenceEvent); } // Notify the state change. notifyStateChange(contact, presenceEvent); if (!mPersistentFile.isNull()) { // Start the save timer. mPersistenceTimer.oneshotAfter(sPersistInterval); } } else { // Since this presenceEvent will not be published (it does not // change the state we've sent out), delete it now. delete presenceEvent; } mLock.release(); return requiredPublish; }