OsStatus EmailNotifier::initStrings(TiXmlElement* emailElement) { TiXmlElement* element = emailElement->FirstChildElement("email-intro"); textContentShallow(mEmailStrIntro, element); assembleMsg(mEmailStrIntro, SipXecsService::Name(), mEmailStrIntro); element = emailElement->FirstChildElement("email-subject"); textContentShallow(mEmailStrSubject, element); element = emailElement->FirstChildElement("email-alarm"); textContentShallow(mEmailStrAlarm, element); element = emailElement->FirstChildElement("email-time"); textContentShallow(mEmailStrTime, element); element = emailElement->FirstChildElement("email-host"); textContentShallow(mEmailStrHost, element); element = emailElement->FirstChildElement("email-severity"); textContentShallow(mEmailStrSeverity, element); element = emailElement->FirstChildElement("email-description"); textContentShallow(mEmailStrDescription, element); element = emailElement->FirstChildElement("email-resolution"); textContentShallow(mEmailStrResolution, element); element = emailElement->FirstChildElement("email-from"); textContentShallow(mEmailStrFrom, element); assembleMsg(mEmailStrFrom, SipXecsService::Name(), mEmailStrFrom); return OS_SUCCESS; }
OsStatus LogNotifier::init(TiXmlElement* element, TiXmlElement* dummy) { UtlString alarmFile; textContentShallow(alarmFile, element->FirstChildElement("file")); initLogfile(alarmFile); return OS_SUCCESS; }
// Remove any dialogs in the terminated state. // This operates only on the parsed dialogs in mXmlDialogs, used to generate // the consolidated state. The RFC 4662 events are not affected, but // presumably the resource is not allowing terminated dialogs to accumulate // in the events it sends. void ResourceInstance::purgeTerminatedDialogs() { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceInstance::purgeTerminatedDialogs mInstanceName = '%s'", mInstanceName.data()); // Iterate through all the <dialog> elements. UtlHashMapIterator itor(mXmlDialogs); UtlContainable* id; while ((id = itor())) { // Get the <state> element content. UtlVoidPtr* p = dynamic_cast <UtlVoidPtr*> (itor.value()); TiXmlElement* dialog_element = static_cast <TiXmlElement*> (p->getValue()); TiXmlNode* state_node = dialog_element->FirstChild("state"); UtlString state; textContentShallow(state, state_node); if (state.compareTo("terminated") == 0) { // This dialog was terminated. Remove it. delete dialog_element; mXmlDialogs.destroy(id); } } // Note that we do not have to publish this change, as the deletion // of these dialogs does not have to be sent to the subscribers // quickly. }
OsStatus SmsNotifier::initStrings(TiXmlElement* smsElement) { Os::Logger::instance().log(FAC_ALARM, PRI_DEBUG, "SmsNotifier initStrings"); TiXmlElement* element = smsElement->FirstChildElement("email-intro"); element = smsElement->FirstChildElement("email-subject"); textContentShallow(mSmsStrSubject, element); element = smsElement->FirstChildElement("email-host"); textContentShallow(mSmsStrHost, element); element = smsElement->FirstChildElement("email-from"); textContentShallow(mSmsStrFrom, element); assembleMsg(mSmsStrFrom, SipXecsService::Name(), mSmsStrFrom); return OS_SUCCESS; }
OsStatus EmailNotifier::init(TiXmlElement* emailElement) { OsSysLog::add(FAC_ALARM, PRI_DEBUG, "Created EmailNotifier"); TiXmlElement* element = emailElement->FirstChildElement("email-notification-addr"); textContentShallow(mReplyTo, element); element = emailElement->FirstChildElement("contact"); for (; element; element=element->NextSiblingElement("contact") ) { UtlString contactStr; textContentShallow(contactStr, element); if (contactStr) { mContacts.append(new UtlString(contactStr)); } } return OS_SUCCESS; }
OsStatus EmailNotifier::init(TiXmlElement* emailElement, TiXmlElement* groupElement) { OsSysLog::add(FAC_ALARM, PRI_DEBUG, "Created EmailNotifier"); TiXmlElement* element; // Extract the "From" contact from the alarm configuration file element = emailElement->FirstChildElement("email-notification-addr"); textContentShallow(mReplyTo, element); // Extract the "To" contacts from the alarm groups configuration file element = groupElement->FirstChildElement("group"); for (; element; element=element->NextSiblingElement("group") ) { UtlString groupName = element->Attribute("id"); UtlString contactList; if (!groupName.isNull()) { OsSysLog::add(FAC_ALARM, PRI_DEBUG, "Processing alarm group name: %s", groupName.data()); TiXmlElement* emailElement = element->FirstChildElement("email"); TiXmlElement* toElement = emailElement->FirstChildElement("contact"); for (; toElement; toElement=toElement->NextSiblingElement("contact") ) { UtlString contactStr; textContentShallow(contactStr, toElement); if (contactStr) { contactList.append(contactStr); contactList.append(","); } } // Store the contact list as a comma separated string that UtlHashMap can handle. mContacts.insertKeyAndValue(new UtlString(groupName), new UtlString(contactList)); } } return OS_SUCCESS; }
//! Terminate the non-Terminated contents of mXmlDialogs. void ResourceInstance::terminateXmlDialogs() { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceInstance::terminateXmlDialogs mInstanceName = '%s'", mInstanceName.data()); // Iterate through the contents. UtlHashMapIterator itor(mXmlDialogs); UtlContainable* id; while ((id = itor())) { // The XML document for a single dialog. UtlVoidPtr* value = dynamic_cast <UtlVoidPtr*> (itor.value()); TiXmlElement* dialog_element = static_cast <TiXmlElement*> (value->getValue()); if (NULL != dialog_element) { // Get the "state" XML node. TiXmlNode* state = dialog_element->FirstChild("state"); // Destroy the dialog only if the state is not "terminated". UtlString stateText; textContentShallow(stateText, state); // textContentShallow allows state == NULL. // Check if the state is not terminated. if (0 != stateText.compareTo("terminated")) { TiXmlElement newstate = "state"; TiXmlText newtext = "terminated"; // Replace the old state element with a new state element indicating terminated. // The calling routine will then normally overwrite this with the actual (full) state. // Note that tinyxml will delete the old state element for us. newstate.InsertEndChild(newtext); dialog_element->ReplaceChild(state, newstate); } } } }
bool cAlarmServer::loadAlarmConfig(const UtlString& alarmFile, const UtlString& groupFile) { // load global alarm config from alarm-config.xml OsSysLog::add(FAC_ALARM, PRI_DEBUG, "Loading alarm config files '%s' '%s'", alarmFile.data(), groupFile.data()); // Load the alarm configuration file TiXmlDocument alarmDoc(alarmFile); TiXmlHandle alarmDocHandle( &alarmDoc ); if (!alarmDoc.LoadFile()) { UtlString errorMsg; XmlErrorMsg( alarmDoc, errorMsg ); OsSysLog::add(FAC_ALARM, PRI_ERR, "Failed to load alarm config file: %s", errorMsg.data()); return false; } TiXmlHandle alarmDocH( &alarmDoc ); TiXmlHandle alarmServerHandle = alarmDocH.FirstChildElement("alarm_server"); // Load the alarm group configuration file TiXmlDocument groupDoc(groupFile); TiXmlHandle groupDocHandle( &groupDoc ); if (!groupDoc.LoadFile()) { UtlString errorMsg; XmlErrorMsg( groupDoc, errorMsg ); OsSysLog::add(FAC_ALARM, PRI_ERR, "Failed to load alarm group config file: %s", errorMsg.data()); return false; } TiXmlHandle groupDocH( &groupDoc ); TiXmlHandle groupServerHandle = groupDocH.FirstChildElement("alarm_groups"); // Continue to process the alarm configuration file TiXmlElement* settingsElement = alarmServerHandle.FirstChildElement("settings").Element(); if (!settingsElement) { OsSysLog::add(FAC_ALARM, PRI_ERR, "No <settings> element in alarm config file '%s'", alarmFile.data()); return false; } TiXmlElement* langElement = settingsElement->FirstChildElement("language"); if (langElement) { textContentShallow(mLanguage, langElement); OsSysLog::add(FAC_ALARM, PRI_INFO, "Language for alarm notifications: %s", mLanguage.data()); } //load alarm action settings TiXmlElement* alarmActionsElement = settingsElement->FirstChildElement("actions"); if (alarmActionsElement) { TiXmlElement* element = alarmActionsElement->FirstChildElement("log"); if (getBoolAttribute(element, "enabled")) { LogNotifier* pLogNotifier = new LogNotifier(); if (mpNotifiers[cAlarmData::eActionLog]) { delete mpNotifiers[cAlarmData::eActionLog]; } mpNotifiers[cAlarmData::eActionLog] = pLogNotifier; if (pLogNotifier) { pLogNotifier->init(element, NULL); gbActions[cAlarmData::eActionLog] = true; } } // Alarm email notifications element = alarmActionsElement->FirstChildElement("email"); if (getBoolAttribute(element, "enabled")) { EmailNotifier* pEmailNotifier = new EmailNotifier(); if (mpNotifiers[cAlarmData::eActionEmail]) { delete mpNotifiers[cAlarmData::eActionEmail]; } mpNotifiers[cAlarmData::eActionEmail] = pEmailNotifier; if (pEmailNotifier) { TiXmlElement* groupElement = groupServerHandle.FirstChildElement("definitions").Element(); pEmailNotifier->init(element, groupElement); gbActions[cAlarmData::eActionEmail] = true; } } element = alarmActionsElement->FirstChildElement("sms"); if (getBoolAttribute(element, "enabled")) { SmsNotifier* pSmsNotifier = new SmsNotifier(); if (mpNotifiers[cAlarmData::eActionSms]) { delete mpNotifiers[cAlarmData::eActionSms]; } mpNotifiers[cAlarmData::eActionSms] = pSmsNotifier; if (pSmsNotifier) { TiXmlElement* groupElement = groupServerHandle.FirstChildElement("definitions").Element(); pSmsNotifier->init(element, groupElement); gbActions[cAlarmData::eActionSms] = true; } } // Alarm SNMPv2 trap notifications element = alarmActionsElement->FirstChildElement("trap"); if (getBoolAttribute(element, "enabled")) { TrapNotifier* pTrapNotifier = new TrapNotifier(); if (mpNotifiers[cAlarmData::eActionTrap]) { delete mpNotifiers[cAlarmData::eActionTrap]; } mpNotifiers[cAlarmData::eActionTrap] = pTrapNotifier; if (pTrapNotifier) { TiXmlElement* groupElement = groupServerHandle.FirstChildElement("definitions").Element(); pTrapNotifier->init(element, groupElement); gbActions[cAlarmData::eActionTrap] = true; } } else { // The trap notification of alarms is disabled. // So, delete the notifier if (mpNotifiers[cAlarmData::eActionTrap]) { delete mpNotifiers[cAlarmData::eActionTrap]; mpNotifiers[cAlarmData::eActionTrap] = 0; } gbActions[cAlarmData::eActionTrap] = false; } } return true; }
bool cAlarmServer::loadAlarmStringsFile(const UtlString& stringsFile) { OsSysLog::add(FAC_ALARM, PRI_DEBUG, " load alarm strings file %s", stringsFile.data()); TiXmlDocument doc(stringsFile); TiXmlHandle docHandle( &doc ); if (!doc.LoadFile()) { UtlString errorMsg; XmlErrorMsg( doc, errorMsg ); OsSysLog::add(FAC_ALARM, PRI_ERR, "failed to load alarm strings file: %s", errorMsg.data()); return false; } TiXmlHandle docH( &doc ); TiXmlHandle alarmServerHandle = docH.FirstChildElement("alarm_server"); TiXmlElement* settingsElement = alarmServerHandle.FirstChildElement("settings").Element(); if (settingsElement) { //load alarm action strings TiXmlElement* alarmActionsElement = settingsElement->FirstChildElement("actions"); if (alarmActionsElement) { TiXmlElement* element = alarmActionsElement->FirstChildElement("log"); if (mpNotifiers[cAlarmData::eActionLog]) { mpNotifiers[cAlarmData::eActionLog]->initStrings(element); } element = alarmActionsElement->FirstChildElement("email"); if (mpNotifiers[cAlarmData::eActionEmail]) { mpNotifiers[cAlarmData::eActionEmail]->initStrings(element); } element = alarmActionsElement->FirstChildElement("sms"); if (mpNotifiers[cAlarmData::eActionSms]) { mpNotifiers[cAlarmData::eActionSms]->initStrings(element); } /* Not implemented as Strings are not needed for TrapNotifier. element = alarmActionsElement->FirstChildElement("trap"); if (mpNotifiers[cAlarmData::eActionTrap]) { mpNotifiers[cAlarmData::eActionTrap]->initStrings(element); } */ } } else { OsSysLog::add(FAC_ALARM, PRI_DEBUG, "no <settings> element in alarm config file '%s'", stringsFile.data()); } //load alarm description strings TiXmlElement* alarmDefElement = alarmServerHandle. FirstChildElement("definitions").Element(); if (alarmDefElement) { TiXmlElement* element = alarmDefElement->FirstChildElement(); UtlString idStr; UtlString descStr; UtlString resStr; for (; element; element=element->NextSiblingElement() ) { idStr = element->Attribute("id"); if (idStr.isNull()) { OsSysLog::add(FAC_ALARM, PRI_ERR,"Parsing alarm strings file %s: alarm ID is required", stringsFile.data()); continue; } cAlarmData* alarmData = lookupAlarm(idStr); if (!alarmData) { OsSysLog::add(FAC_ALARM, PRI_ERR,"unknown alarm ID %s", idStr.data()); continue; } TiXmlElement* codeElement = element->FirstChildElement("shorttitle"); if (codeElement) { textContentShallow(descStr, codeElement); if (!descStr.isNull()) { UtlString tempStr; XmlUnEscape(tempStr, descStr); alarmData->setShortTitle(tempStr); } } codeElement = element->FirstChildElement("description"); if (codeElement) { textContentShallow(descStr, codeElement); if (!descStr.isNull()) { UtlString tempStr; XmlUnEscape(tempStr, descStr); alarmData->setDescription(tempStr); } } codeElement = element->FirstChildElement("resolution"); if (codeElement) { textContentShallow(resStr, codeElement); if (!resStr.isNull()) { UtlString tempStr; XmlUnEscape(tempStr, resStr); alarmData->setResolution(tempStr); } } } } return true; }
bool cAlarmServer::loadAlarmData(TiXmlElement* element, cAlarmData* data) { UtlString codeStr; UtlString idStr; UtlString compStr(""); UtlString sevStr("minor"); UtlString resStr(""); UtlString groupName("disabled"); bool actEmail = true; bool actSms = true; bool actLog = true; bool actTrap = true; int filtMax = INT_MAX; int filtMin = 0; if (element && data) { idStr = element->Attribute("id"); if (idStr.isNull()) { OsSysLog::add(FAC_ALARM, PRI_ERR,"code=%s: alarm ID is required", codeStr.data()); return false; } TiXmlElement* codeElement = element->FirstChildElement("code"); if ( !codeElement ) { OsSysLog::add(FAC_ALARM, PRI_ERR, "id=%s: alarm code is required", element->Attribute("id")); return false; } textContentShallow(codeStr, codeElement); codeElement = element->FirstChildElement("severity"); if ( codeElement ) { textContentShallow(sevStr, codeElement); } else { OsSysLog::add(FAC_ALARM, PRI_WARNING, "id=%s: no severity; assuming %s", idStr.data(), sevStr.data()); } codeElement = element->FirstChildElement("component"); if ( codeElement ) { textContentShallow(compStr, codeElement); } else { OsSysLog::add(FAC_ALARM, PRI_WARNING,"id=%s: no component; set to null", idStr.data()); } codeElement = element->FirstChildElement("action"); actLog = getBoolAttribute(codeElement, "log", true); if ( codeElement ) { // Get the alarm group name used for both regular emails and SMS emails. groupName = codeElement->Attribute("email"); if (strcmp(groupName.data(), "disabled") == 0) { // All regular/SMS notifications for this alarm type must be disabled. actEmail = false; actSms = false; actTrap = false; } } codeElement = element->FirstChildElement("filter"); filtMax = getIntAttribute(codeElement, "max_reports", INT_MAX); filtMin = getIntAttribute(codeElement, "min_threshold"); } else { return false; } data->setAlarmId(idStr); data->setCode(codeStr); data->setSeverity(sevToSyslogPri(sevStr)); data->setComponent(compStr); data->setShortTitle(idStr); // default fallback title is internal id data->setDescription(idStr); // default fallback description is internal id data->setResolution(resStr); data->actions[cAlarmData::eActionLog] = actLog; data->actions[cAlarmData::eActionEmail] = actEmail; data->actions[cAlarmData::eActionSms] = actSms; data->actions[cAlarmData::eActionTrap] = actTrap; data->group_name = groupName; data->max_report = filtMax; data->min_threshold = filtMin; data->resetCount(); return true; }
// Read and parse the resource list file and install the resource lists // into the ResourceListSet. OsStatus ResourceListFileReader::initialize() { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceListFileReader::initialize entered"); int changeDelay = mResourceListSet->getResourceListServer()->getChangeDelay(); // The status to return. OsStatus ret = OS_SUCCESS; // Suspend publishing to prevent generating incomplete NOTIFYs. mResourceListSet->suspendPublishing(); // Remove all existing resource lists. mResourceListSet->deleteAllResourceLists(); // No work to be done if file name is not set. if (!mFileName.isNull()) { // Initialize Tiny XML document object. TiXmlDocument document; TiXmlNode* lists_node; if ( // Load the XML into it. document.LoadFile(mFileName.data()) && // Find the top element, which should be a <lists>. (lists_node = document.FirstChild("lists")) != NULL && lists_node->Type() == TiXmlNode::ELEMENT) { // Find all the <list> elements. // Since this loop contains a delay and can run for a long time, // we have to check gShutdownFlag to abort processing when // a shutdown has been requested. for (TiXmlNode* list_node = 0; (list_node = lists_node->IterateChildren("list", list_node)) && !mService->getShutdownFlag(); ) { if (list_node->Type() == TiXmlNode::ELEMENT) { TiXmlElement* list_element = list_node->ToElement(); // Process each <list> element. bool list_valid = true; // Process the 'user' attribute. const char* user_attribute = list_element->Attribute("user"); if (!user_attribute || *user_attribute == '\0') { // User missing or null. OsSysLog::add(FAC_RLS, PRI_ERR, "user attribute of <list> was missing or null"); list_valid = false; ret = OS_FAILED; } // Process the 'user-cons' attribute. const char* user_cons_attribute = list_element->Attribute("user-cons"); if (!user_cons_attribute || *user_cons_attribute == '\0') { // user-cons missing or null. OsSysLog::add(FAC_RLS, PRI_ERR, "user-cons attribute of <list> was missing or null"); list_valid = false; ret = OS_FAILED; } // If the <list> element was OK, create the ResourceList from it. if (list_valid) { // Add this resource list to the set of all resource lists. // (No NAME XML for the resource list.) bool r = mResourceListSet->addResourceList(user_attribute, user_cons_attribute, ""); if (!r) { OsSysLog::add(FAC_RLS, PRI_WARNING, "ResourceListFileReader::initialize " "ResourceList '%s' already exists -- " "continuing adding resources to the list", user_attribute); } OsTask::delay(changeDelay); // Find all the <resource> children and add them to the // ResourceList. // Since this loop contains a delay and can run for a long time, // we have to check gShutdownFlag to abort processing when // a shutdown has been requested. for (TiXmlNode* resource_node = 0; (resource_node = list_element->IterateChildren("resource", resource_node)) && !mService->getShutdownFlag(); ) { if (resource_node->Type() == TiXmlNode::ELEMENT) { TiXmlElement* resource_element = resource_node->ToElement(); // Process each <resource> element. bool resource_valid = true; // Process the 'uri' attribute. const char* uri_attribute = resource_element->Attribute("uri"); if (!uri_attribute || *uri_attribute == '\0') { // URI missing or null. OsSysLog::add(FAC_RLS, PRI_ERR, "main " "uri attribute of <resource> was missing or null"); resource_valid = false; ret = OS_FAILED; } // If the <resource> element was OK, create the // ResourceListResource from it. if (resource_valid) { // Find all the <name> children and add them to the // name string. UtlString names; TiXmlUtlStringWriter writer(&names); // Extract the content of the first // non-empty <name> child, and use it as // the display name. UtlString display_name; for (TiXmlNode* name_node = 0; (name_node = resource_element->IterateChildren("name", name_node)); ) { if (name_node->Type() == TiXmlNode::ELEMENT) { writer << *name_node; if (display_name.isNull()) { textContentShallow(display_name, name_node); } } } bool r = mResourceListSet->addResource(user_attribute, uri_attribute, names.data(), display_name.data()); if (!r) { OsSysLog::add(FAC_RLS, PRI_WARNING, "ResourceListFileReader::initialize " "Resource '%s' already exists in ResourceList '%s' -- " "not adding a second time", uri_attribute, user_attribute); } OsTask::delay(changeDelay); } } } } } } OsSysLog::add(FAC_PARK, PRI_DEBUG, "ResourceListFileReader::initialize Done loading file '%s'", mFileName.data()); } else { // Report error parsing file. OsSysLog::add(FAC_PARK, PRI_CRIT, "main " "Resource list file '%s' could not be parsed.", mFileName.data()); ret = OS_FAILED; } } else { // Report that there is no file. OsSysLog::add(FAC_PARK, PRI_CRIT, "main No resource list file set."); } // Resume publishing. mResourceListSet->resumePublishing(); return ret; }
OsStatus MappingRulesUrlMapping::parsePermMatchContainer(const Url& requestUri, const UtlString& vdigits, ResultSet& rContactResultSet, ResultSet& rPermissions, UtlString& callTag, const TiXmlNode* pUserMatchNode //parent node ) const { OsStatus doTransformStatus = OS_FAILED; UtlBoolean bPermissionFound = false; UtlString requestUriStr; callTag = "UNK"; requestUri.toString(requestUriStr); const TiXmlNode* pPermMatchNode = NULL; while ( (pPermMatchNode = pUserMatchNode->IterateChildren( pPermMatchNode ) ) && (doTransformStatus != OS_SUCCESS) ) { if(pPermMatchNode && pPermMatchNode->Type() == TiXmlNode::ELEMENT) { UtlString tagValue = pPermMatchNode->Value(); if( tagValue.compareTo(XML_TAG_CALLTAG) == 0 ) { // Found call tag element. Read the text value for it. textContentShallow(callTag, pPermMatchNode); } if( tagValue.compareTo(XML_TAG_PERMISSIONMATCH) == 0 ) { //practically there should always be only one permission match tag const TiXmlElement* pPermissionMatchElement = pPermMatchNode->ToElement(); UtlBoolean bPermNodePresent = false; //get the user text value from it for( const TiXmlNode* pPermissionNode = pPermissionMatchElement->FirstChild( XML_TAG_PERMISSION ); pPermissionNode; pPermissionNode = pPermissionNode->NextSibling( XML_TAG_PERMISSION ) ) { bPermNodePresent = true; const TiXmlElement* pPermissionElement = pPermissionNode->ToElement(); //get permission Name const TiXmlNode* pPermissionText = pPermissionElement->FirstChild(); if(pPermissionText) { UtlString permission = pPermissionText->Value(); UtlHashMap record; UtlString* pIdentityKey = new UtlString ( "identity" ); UtlString* pPermissionKey = new UtlString ( "permission" ); UtlString* pIdentityValue = new UtlString ( requestUriStr ); UtlString* pPermissionValue = new UtlString ( permission ); record.insertKeyAndValue ( pIdentityKey, pIdentityValue ); record.insertKeyAndValue ( pPermissionKey, pPermissionValue ); rPermissions.addValue(record); bPermissionFound = true; } } //if no permission node - then it means no permission required - allow all if((!bPermNodePresent || bPermissionFound ) ) { //if the premission matches in the permissions database //go ahead and get the transform tag doTransformStatus = doTransform(requestUri, vdigits, rContactResultSet, pPermMatchNode); } } } } return doTransformStatus; }
// 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"); }
// Process a notify event callback. // This involves parsing the content of the callback and revising our record // of the state for that subscription. Then, we must regenerate the list // of contacts and update the set of subscriptions to match the current // contacts. void ContactSet::notifyEventCallback(const UtlString* dialogHandle, const UtlString* content) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback mUri = '%s', dialogHandle = '%s', content = '%s'", mUri.data(), dialogHandle->data(), content->data()); // Parse the XML and update the contact status. // Find the UtlHashMap for this subscription. UtlHashMap* state_from_this_subscr = dynamic_cast <UtlHashMap*> (mSubscriptions.findValue(dialogHandle)); if (!state_from_this_subscr) { // No state for this dialogHandle, so we need to add one. OsSysLog::add(FAC_RLS, PRI_WARNING, "ContactSet::notifyEventCallback mSubscriptions element does not exist for this dialog handle mUri = '%s', dialogHandle = '%s'", mUri.data(), dialogHandle->data()); // Check that we don't have too many subscriptions. if (mSubscriptions.entries() < getResourceListServer()->getMaxRegSubscInResource()) { state_from_this_subscr = new UtlHashMap; mSubscriptions.insertKeyAndValue(new UtlString(*dialogHandle), state_from_this_subscr); } else { OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback cannot add reg subscription with dialog handle '%s', already %zu in ContactSet '%s'", dialogHandle->data(), mSubscriptions.entries(), mUri.data()); } } // Perform the remainder of the processing if we obtained a hash map // from the above processing. if (state_from_this_subscr) { // Initialize Tiny XML document object. TiXmlDocument document; TiXmlNode* reginfo_node; if ( // Load the XML into it. document.Parse(content->data()) && // Find the top element, which should be a <reginfo>. (reginfo_node = document.FirstChild("reginfo")) != NULL && reginfo_node->Type() == TiXmlNode::ELEMENT) { // Check the state attribute. const char* p = reginfo_node->ToElement()->Attribute("state"); if (p && strcmp(p, "full") == 0) { // If the state is "full", delete the current state. state_from_this_subscr->destroyAll(); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback clearing state"); } // Find all the <registration> elements for this URI. for (TiXmlNode* registration_node = 0; (registration_node = reginfo_node->IterateChildren("registration", registration_node)); ) { // Do not test the aor attribute of <registration> elements // because the reg event server may be operating with the real // AOR for this URI, whereas we may have been told of an alias. // Find all the <contact> elements. for (TiXmlNode* contact_node = 0; (contact_node = registration_node->IterateChildren("contact", contact_node)); ) { TiXmlElement* contact_element = contact_node->ToElement(); // Get the state attribute. const char* state = contact_element->Attribute("state"); // Get the id attribute const char* id = contact_element->Attribute("id"); // Get the Contact URI for the phone. If a GRUU address is present we should // use that as the Contact URI. Otherwise, use the contact URI present in the // "uri" element, and append any path headers that are present to the ROUTE // header parameter in the URI. This will ensure proper routing in HA systems. // Please refer to XECS-1694 for more details. UtlString* uri_allocated = new UtlString; UtlBoolean check_uri = TRUE; TiXmlNode* pub_gruu_node = contact_element->FirstChild("gr:pub-gruu"); if (pub_gruu_node) { TiXmlElement* pub_gruu_element = pub_gruu_node->ToElement(); UtlString pub_gruu_uri(pub_gruu_element->Attribute("uri")); if (!pub_gruu_uri.isNull()) { // Check the URI Scheme. Only accept the GRUU address if it is of either // a sip or sips scheme Url tmp(pub_gruu_uri, TRUE); Url::Scheme uriScheme = tmp.getScheme(); if(Url::SipUrlScheme == uriScheme || Url::SipsUrlScheme == uriScheme) { tmp.removeAngleBrackets(); tmp.getUri(*uri_allocated); check_uri = FALSE; } } } // If we did not find a GRUU address, then use the address in the "uri" element as the // contact URI, and check for path headers. if (check_uri) { TiXmlNode* u = contact_element->FirstChild("uri"); if (u) { textContentShallow(*uri_allocated, u); // Iterate through all the path header elements. Path headers are stored in the // "unknown-param" elements that have a "name" attribute value of "path". for (TiXmlNode* unknown_param_node = 0; (unknown_param_node = contact_node->IterateChildren("unknown-param", unknown_param_node)); ) { TiXmlElement* unknown_param_element = unknown_param_node->ToElement(); UtlString path(unknown_param_element->Attribute("name")); if(0 == path.compareTo("path")) { UtlString pathVector; textContentShallow(pathVector, unknown_param_node); if(!pathVector.isNull()) { Url contact_uri(*uri_allocated, TRUE); // there is already a Route header parameter in the contact; append it to the // Route derived from the Path vector. UtlString existingRouteValue; if ( contact_uri.getHeaderParameter(SIP_ROUTE_FIELD, existingRouteValue)) { pathVector.append(SIP_MULTIFIELD_SEPARATOR); pathVector.append(existingRouteValue); } contact_uri.setHeaderParameter(SIP_ROUTE_FIELD, pathVector); contact_uri.removeAngleBrackets(); contact_uri.getUri(*uri_allocated); } } } } } // Only process <contact> elements that have the needed values. if (state && state[0] != '\0' && id && id[0] != '\0' && !uri_allocated->isNull()) { UtlString* id_allocated = new UtlString(id); if (strcmp(state, "active") == 0) { // Add the contact if it is not already present. if (!state_from_this_subscr->find(id_allocated)) { // Prepend the registration Call-Id and ';' to *uri_allocated.. uri_allocated->insert(0, ';'); const char* call_id = contact_element->Attribute("callid"); if (call_id) { uri_allocated->insert(0, call_id); } // Check that we don't have too many contacts. if (state_from_this_subscr->entries() < getResourceListServer()->getMaxContInRegSubsc()) { // Insert the registration record. if (state_from_this_subscr->insertKeyAndValue(id_allocated, uri_allocated)) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback adding id = '%s' Call-Id;URI = '%s'", id, uri_allocated->data()); id_allocated = NULL; uri_allocated = NULL; } else { OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback adding id = '%s' Call-Id;URI = '%s' failed", id_allocated->data(), uri_allocated->data()); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback *state_from_this_subscr is:"); UtlHashMapIterator itor(*state_from_this_subscr); UtlContainable* k; while ((k = itor())) { UtlContainable* v = itor.value(); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback (*state_from_this_subscr)['%s'] = '%s'", (dynamic_cast <UtlString*> (k))->data(), (dynamic_cast <UtlString*> (v))->data()); } } } else { OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback cannot add Call-Id;RUI '%s', already %zu in ContactSet '%s' subscription '%s'", uri_allocated->data(), state_from_this_subscr->entries(), mUri.data(), dialogHandle->data()); } } } else if (strcmp(state, "terminated") == 0) { // Delete it from the contact state. state_from_this_subscr->destroy(id_allocated); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback deleting id = '%s'", id); } // Free id_allocated, if it is not pointed to by a data // structure, which is indicated by setting it to NULL. if (id_allocated) { delete id_allocated; } } else { OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback <contact> element with id = '%s' is missing id, state, and/or URI", id ? id : "(missing)"); } // Free uri_allocated, if it is not pointed to by a data // structure, which is indicated by setting it to NULL. if (uri_allocated) { delete uri_allocated; } } } } else { // Error parsing the contents. OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback malformed reg event content for mUri = '%s'", mUri.data()); } // Update the subscriptions we maintain to agree with the new state. updateSubscriptions(); } }