/** Test the setValue() method. * * The test data for this method is * a) For a NULL pointer set a different type * a) Set the value from one Non-NULL to another Non-NULL * d) set the value from Non-NULL to NULL */ void testSetValue() { const char* prefix ; const char* suffix1 = " : test return value" ; const char* suffix2 = " : test that value has been set" ; string Message ; UtlVoidPtr testVoidObj ; void* returnValue ; void* newValue ; void* oldValue = 0 ; newValue = (void*)"Hello world" ; returnValue = testVoidObj.setValue(newValue) ; prefix = "For a VoidPtr object which is not NULL, test setValue(void* value) " \ "where val is non NULL " ; TestUtilities::createMessage(2, &Message, prefix, suffix1) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(Message.data(), (void*)oldValue, (void*)returnValue) ; TestUtilities::createMessage(2, &Message, prefix, suffix2) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(Message.data(), (void*)newValue, \ (void*)testVoidObj.getValue()) ; oldValue = testVoidObj.getValue() ; prefix = "Test setValue(void* value) where value is not NULL and the " \ "existing object is not NULL" ; newValue = (void*)"Hello again world" ; returnValue = (void*)testVoidObj.setValue(newValue) ; TestUtilities::createMessage(2, &Message, prefix, suffix1) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(Message.data(), (void*)oldValue, (void*)returnValue) ; TestUtilities::createMessage(2, &Message, prefix, suffix2) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(Message.data(), (void*)newValue, \ (void*)testVoidObj.getValue()) ; oldValue = testVoidObj.getValue() ; prefix = "Test setValue(void* value) where value = NULL and existing object is not" ; newValue = 0 ; returnValue = (void*)testVoidObj.setValue(newValue) ; TestUtilities::createMessage(2, &Message, prefix, suffix1) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(Message.data(), (void*)oldValue, (void*)returnValue); TestUtilities::createMessage(2, &Message, prefix, suffix1) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(Message.data(), (void*)newValue, \ (void*)testVoidObj.getValue()) ; } //testSetValue
// Process a notify event callback. void ResourceInstance::notifyEventCallback(const UtlString* dialogHandle, const UtlString* content) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceInstance::notifyEventCallback mInstanceName = '%s', content = '%s'", mInstanceName.data(), content->data()); // Set to true if we find publishable data. bool publish = false; // Set the subscription state to "active". mSubscriptionState = "active"; // Save the content as text for the RFC 4662 resource list events. mContent.remove(0); mContent.append(*content); mContentPresent = TRUE; // Dissect the XML for each dialog event and store it in a map // so we can construct BroadWorks-style resource list events // (which have to have full state). // Initialize Tiny XML document object. TiXmlDocument xmlDialogEvent; TiXmlNode* dialog_info_node; if ( // Load the XML into it. xmlDialogEvent.Parse(mContent.data()) && // Find the top element, which should be a <dialog-info>. (dialog_info_node = xmlDialogEvent.FirstChild("dialog-info")) != NULL && dialog_info_node->Type() == TiXmlNode::ELEMENT) { // Check the state attribute. const char* p = dialog_info_node->ToElement()->Attribute("state"); if (p && strcmp(p, "full") == 0) { // If the state is "full", terminate all non-terminated dialogs. (XECS-1668) terminateXmlDialogs(); publish = true; OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceInstance::notifyEventCallback all non-terminated dialogs"); } // Find all the <dialog> elements. for (TiXmlNode* dialog_node = 0; (dialog_node = dialog_info_node->IterateChildren("dialog", dialog_node)); ) { if (dialog_node->Type() == TiXmlNode::ELEMENT) { TiXmlElement* dialog_element = dialog_node->ToElement(); // Determine if the <dialog> is a bogus report of a NAT Keepalive // OPTIONS message, as reported by Polycom SPIP firmware 3.1.2. // (XTRN-425) If so, ignore it. #ifdef NAT_KEEPALIVE_DETECT const char* call_id_attr = dialog_element->Attribute("call-id"); // Reject <dialog>s on the narrowest grounds, that is, only if the // call-id attribute is present and contains NAT_KEEPALIVE_SIGNATURE. const bool ok = !(call_id_attr && strstr(call_id_attr, NAT_KEEPALIVE_SIGNATURE) != NULL); #else const bool ok = true; #endif if (ok) { // Now that we've got a <dialog> element, edit it to fit // into a consolidated event notice. publish = true; // Prepend the resource instance name to the 'id' // attribute, so it is unique within the <resource>. UtlString id(mInstanceName); // mInstanceName is guaranteed to not contain ';', because // it is a dialog handle that we generate by concatenating // the Call-Id and tags using ',' as a separator. And ';' // may not appear in Call-Ids or tags. id.append(";"); id.append(dialog_element->Attribute("id")); dialog_element->SetAttribute("id", id.data()); // Prepare the display name, so we can insert it easily // when we generate consolidated events. // Find or add the <local> element. TiXmlNode* local = dialog_element->FirstChild("local"); if (!local) { local = dialog_element->LinkEndChild(new TiXmlElement("local")); } // Find or add the <local><identity> element. TiXmlNode* identity = local->FirstChild("identity"); if (!identity) { identity = local->LinkEndChild(new TiXmlElement("identity")); } // Clear the display attribute. identity->ToElement()->SetAttribute("display", ""); // Put the resource URI as the content of the // <local><identity> element. // First, remove all text children. TiXmlNode* child; for (TiXmlNode* prev_child = 0; (child = identity->IterateChildren(prev_child)); ) { if (child->Type() == TiXmlNode::TEXT) { identity->RemoveChild(child); // Leave prev_child unchanged. } else { prev_child = child; } } // Insert a text child containing the URI. identity->LinkEndChild(new TiXmlText(getResourceCached()-> getUri()->data())); // Now that we have the XML all nice and pretty, store a copy of // it in mXmlDialogs. // Clone the XML and create a UtlVoidPtr to wrap it. TiXmlElement* alloc_xml = dialog_element->Clone()->ToElement(); // Look for an earlier version of this dialog in the hash map. UtlVoidPtr* p = dynamic_cast <UtlVoidPtr*> (mXmlDialogs.findValue(&id)); if (p) { // Replace the old XML with new XML. delete static_cast <TiXmlElement*> (p->getValue()); p->setValue(alloc_xml); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceInstance::notifyEventCallback replaced dialog with id '%s'", id.data()); } else { // Check that we don't have too many dialogs. if (mXmlDialogs.entries() < getResourceListServer()->getMaxDialogsInResInst()) { mXmlDialogs.insertKeyAndValue(new UtlString(id), new UtlVoidPtr(alloc_xml)); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceInstance::notifyEventCallback added dialog with id '%s'", id.data()); } else { // Free alloc_xml, because we aren't saving a pointer to it. delete alloc_xml; OsSysLog::add(FAC_RLS, PRI_ERR, "ResourceInstance::notifyEventCallback cannot add dialog with id '%s', already %zu in ResourceInstance '%s'", id.data(), mXmlDialogs.entries(), mInstanceName.data()); } } } else { // The <dialog> was rejected because it appears to report // a NAT Maintainer OPTIONS message. // We log this at DEBUG level because if these appear, // there is likely to be one every 20 seconds. OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceInstance::notifyEventCallback " "ignored <dialog> reporting a NAT Keepalive message " "in subscription dialog handle '%s' - " "see XTRN-426", mInstanceName.data()); } } } } else { // Report error parsing XML. OsSysLog::add(FAC_RLS, PRI_ERR, "ResourceInstance::notifyEventCallback " "Dialog event from '%s' not parsable.", getResourceCached()->getUri()->data()); OsSysLog::add(FAC_RLS, PRI_INFO, "ResourceInstance::notifyEventCallback " "Dialog event content is '%s'", content->data()); // Throw away the content, since we cannot generate matching // consolidated content. mContentPresent = FALSE; mContent.remove(0); destroyXmlDialogs(); } // Get the change published, if we found <dialog> that was not incorrect. if (publish) { getResourceCached()->setToBePublished(FALSE, getResourceCached()->getUri()); } }