//: Find a transaction for the given message SipTransaction* SipTransactionList::findTransactionFor(const SipMessage& message, UtlBoolean isOutgoing, enum SipTransaction::messageRelationship& relationship) { SipTransaction* transactionFound = NULL; UtlString callId; SipTransaction::buildHash(message, isOutgoing, callId); lock(); // See if the message knows its transaction // DO NOT TOUCH THE CONTENTS of this transaction as it may no // longer exist. It can only be used as an ID for the transaction. SipTransaction* messageTransaction = message.getSipTransaction(); UtlString matchTransaction(callId); UtlHashBagIterator iterator(mTransactions, &matchTransaction); relationship = SipTransaction::MESSAGE_UNKNOWN; while ((transactionFound = (SipTransaction*) iterator())) { // If the message knows its SIP transaction // and the found transaction pointer does not match, skip the // expensive relationship calculation // The messageTransaction MUST BE TREATED AS OPAQUE // as it may have been deleted. if( messageTransaction && transactionFound != messageTransaction ) { continue; } // If the transaction has never sent the original rquest // it should never get a match for any messages. if( messageTransaction == NULL // this message does not point to this TX && ((transactionFound->getState()) == SipTransaction::TRANSACTION_LOCALLY_INIITATED) ) { continue; } relationship = transactionFound->whatRelation(message, isOutgoing); if(relationship == SipTransaction::MESSAGE_REQUEST || relationship == SipTransaction::MESSAGE_PROVISIONAL || relationship == SipTransaction::MESSAGE_FINAL || relationship == SipTransaction::MESSAGE_NEW_FINAL || relationship == SipTransaction::MESSAGE_CANCEL || relationship == SipTransaction::MESSAGE_CANCEL_RESPONSE || relationship == SipTransaction::MESSAGE_ACK || relationship == SipTransaction::MESSAGE_2XX_ACK || relationship == SipTransaction::MESSAGE_DUPLICATE) { break; } } UtlBoolean isBusy = FALSE; if(transactionFound == NULL) { relationship = SipTransaction::MESSAGE_UNKNOWN; } else { isBusy = transactionFound->isBusy(); if(!isBusy) { transactionFound->markBusy(); } } unlock(); if(transactionFound && isBusy) { // If we cannot lock it, it does not exist if(!waitUntilAvailable(transactionFound, callId)) { if (OsSysLog::willLog(FAC_SIP, PRI_WARNING)) { UtlString relationString; SipTransaction::getRelationshipString(relationship, relationString); OsSysLog::add(FAC_SIP, PRI_WARNING, "SipTransactionList::findTransactionFor %p not available relation: %s", transactionFound, relationString.data()); } transactionFound = NULL; } } #if 0 // enable only for transaction match debugging - log is confusing otherwise UtlString relationString; SipTransaction::getRelationshipString(relationship, relationString); UtlString bytes; int len; message.getBytes(&bytes, &len); OsSysLog::add(FAC_SIP, PRI_DEBUG ,"SipTransactionList::findTransactionFor %p %s %s %s" # ifdef TIME_LOG "\n\tTime Log %s" # endif ,&message ,isOutgoing ? "OUTGOING" : "INCOMING" ,transactionFound ? "FOUND" : "NOT FOUND" ,relationString.data() # ifdef TIME_LOG ,findTimeLog.data() # endif ); #endif return(transactionFound); }
UtlBoolean CommandMsgProcessor::handleMessage(OsMsg& eventMessage) { int msgType = eventMessage.getMsgType(); // int msgSubType = eventMessage.getMsgSubType(); if(msgType == OsMsg::PHONE_APP) // && msgSubType == CP_SIP_MESSAGE) { osPrintf("CommandMsgProcessor::handleMessage Got a message\n"); int messageType = ((SipMessageEvent&)eventMessage).getMessageStatus(); const SipMessage* sipMsg = ((SipMessageEvent&)eventMessage).getMessage(); UtlString callId; if(sipMsg) { osPrintf("numRespondToMessages: %d isResponse: %d messageType: %d TransErro: %d\n", numRespondToMessages, sipMsg->isResponse(), messageType, SipMessageEvent::TRANSPORT_ERROR); if((numRespondToMessages == -1 || numRespondToMessages > 0) && !sipMsg->isResponse() && messageType != SipMessageEvent::TRANSPORT_ERROR) { osPrintf("valid message\n"); if(numRespondToMessages > 0) { numRespondToMessages--; } SipMessage response; if(mpResponseMessage) { response = *mpResponseMessage; } response.setResponseData(sipMsg, responseStatusCode, responseStatusText.data()); UtlString address; int port; UtlString protocol; UtlString tag; sipMsg->getToAddress(&address, &port, &protocol, NULL, NULL, &tag) ; if( tag.isNull()) { int tagNum = rand(); char tag[100]; sprintf(tag, "%d", tagNum); UtlString tagWithDot(tag); tagWithDot.append(".34756498567498567"); response.setToFieldTag(tagWithDot); } UtlString msgBytes; int msgLen; response.getBytes(&msgBytes, &msgLen); osPrintf("%s",msgBytes.data()); if(mpLastResponseMessage) { delete mpLastResponseMessage; mpLastResponseMessage = NULL; } // Keep a copy of the last response sent mpLastResponseMessage = new SipMessage(response); if(userAgent->send(response)) { osPrintf("Sent response\n"); } else { osPrintf("Send failed\n"); } } } } return(TRUE); }
bool SipDialogMonitor::removeExtension(UtlString& groupName, Url& contactUrl) { bool result = false; mLock.acquire(); // Check whether the group exists or not. If not, return false. SipResourceList* list = dynamic_cast <SipResourceList *> (mMonitoredLists.findValue(&groupName)); if (list == NULL) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::removeExtension group %s does not exist", groupName.data()); } else { // Check whether the contact exists in the group or not. UtlString resourceId; contactUrl.getIdentity(resourceId); Resource* resource = list->getResource(resourceId); if (resource) { // If it exists, get the early dialog handle for the SUBSCRIBE, // which specifies all of its subscriptions. UtlString* earlyDialogHandle = dynamic_cast <UtlString *> (mDialogHandleList.findValue(&resourceId)); if (earlyDialogHandle) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::removeExtension Calling endSubscription(%s)", earlyDialogHandle->data()); // Terminate the subscription. UtlBoolean status = mpSipSubscribeClient->endSubscriptionGroup(earlyDialogHandle->data()); if (!status) { OsSysLog::add(FAC_SIP, PRI_ERR, "SipDialogMonitor::removeExtension Unsubscription failed for %s.", resourceId.data()); } // Remove the remembered state for dialog event notices. destroyDialogState(earlyDialogHandle); } else { OsSysLog::add(FAC_SIP, PRI_ERR, "SipDialogMonitor::removeExtension no dialogHandle for %s.", resourceId.data()); } // Now delete all the references to this URI. mDialogHandleList.destroy(&resourceId); resource = list->removeResource(resource); delete resource; result = true; } else { OsSysLog::add(FAC_LOG, PRI_WARNING, "SipDialogMonitor::removeExtension subscription for contact %s does not exists.", resourceId.data()); } } mLock.release(); return result; }
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; }
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; }
// Constructor ResourceListServer::ResourceListServer(const UtlString& domainName, const UtlString& realm, SipLineMgr* lineMgr, const char* eventType, const char* contentType, int tcpPort, int udpPort, int tlsPort, const UtlString& bindIp, UtlString* resourceListFile, int refreshInterval, int resubscribeInterval, int minResubscribeInterval, int publishingDelay, int maxRegSubscInResource, int maxContInRegSubsc, int maxResInstInCont, int maxDialogsInResInst, int serverMinExpiration, int serverDefaultExpiration, int serverMaxExpiration, const UtlString& subscriptionDbName, const UtlString& credentialDbName) : mDomainName(domainName), mEventType(eventType), mContentType(contentType), mResourceListFile(*resourceListFile), mRefreshInterval(refreshInterval), mResubscribeInterval(resubscribeInterval), mMinResubscribeInterval(minResubscribeInterval), mPublishingDelay(publishingDelay), mMaxRegSubscInResource(maxRegSubscInResource), mMaxContInRegSubsc(maxContInRegSubsc), mMaxResInstInCont(maxResInstInCont), mMaxDialogsInResInst(maxDialogsInResInst), mServerUserAgent( tcpPort, // sipTcpPort udpPort, // sipUdpPort tcpPort, // sipTlsPort NULL, // publicAddress NULL, // defaultUser bindIp, // defaultSipAddress NULL, // sipProxyServers NULL, // sipDirectoryServers NULL, // sipRegistryServers NULL, // authenticationScheme NULL, // authenicateRealm NULL, // authenticateDb NULL, // authorizeUserIds NULL, // authorizePasswords NULL, // lineMgr SIP_DEFAULT_RTT, // sipFirstResendTimeout TRUE, // defaultToUaTransactions -1, // readBufferSize OsServerTask::DEF_MAX_MSGS, // queueSize FALSE // bUseNextAvailablePort ), mClientUserAgent( PORT_DEFAULT, // sipTcpPort PORT_DEFAULT, // sipUdpPort PORT_DEFAULT, // sipTlsPort NULL, // publicAddress NULL, // defaultUser bindIp, // defaultSipAddress domainName.data(), // sipProxyServers NULL, // sipDirectoryServers NULL, // sipRegistryServers NULL, // authenticationScheme NULL, // authenicateRealm NULL, // authenticateDb NULL, // authorizeUserIds NULL, // authorizePasswords lineMgr, // lineMgr SIP_DEFAULT_RTT, // sipFirstResendTimeout TRUE, // defaultToUaTransactions -1, // readBufferSize OsServerTask::DEF_MAX_MSGS, // queueSize FALSE // bUseNextAvailablePort ), mSubscriptionMgr(SUBSCRIPTION_COMPONENT_RLS, mDomainName, subscriptionDbName), mPolicyHolder(domainName, realm, credentialDbName), mSubscribeServer(mServerUserAgent, mEventPublisher, mSubscriptionMgr, mPolicyHolder), mRefreshMgr(mClientUserAgent, mDialogManager), mSubscribeClient(mClientUserAgent, mDialogManager, mRefreshMgr), mResourceListTask(this), mResourceListSet(this), // Do not set the resource list file name yet, so the ResourceListFileReader // doesn't add elements to the ResourceListSet before we have the // SIP tasks set up. mResourceListFileReader(UtlString(""), &mResourceListSet) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceListServer::_ this = %p, mDomainName = '%s', mEventType = '%s', mContentType = '%s', " "mRefreshInterval = %d, mResubscribeInterval = %d", this, mDomainName.data(), mEventType.data(), mContentType.data(), mRefreshInterval, mResubscribeInterval); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceListServer::_ this = %p, mPublishingDelay = %d, mMaxRegSubscInResource = %d, " "mMaxContInRegSubsc = %d, mMaxResInstInCont = %d, mMaxDialogsInResInst = %d", this, publishingDelay, mMaxRegSubscInResource, mMaxContInRegSubsc, mMaxResInstInCont, mMaxDialogsInResInst); // Initialize the call processing objects. // Construct addresses: // our local host-part // contact address to be used in client outgoing requests (primarily SUBSCRIBEs) { // Get our address and the client port. UtlString localAddress; int localPort; mClientUserAgent.getLocalAddress(&localAddress, &localPort); char buffer[100]; // Construct the server's host-part. sprintf(buffer, "%s:%d", localAddress.data(), portIsValid(udpPort) ? udpPort : tcpPort); mServerLocalHostPart = buffer; // Construct the client's From URI. sprintf(buffer, "sip:sipXrls@%s:%d", localAddress.data(), localPort); mClientFromURI = buffer; // Obtain the client's Contact URI. mClientUserAgent.getContactURI(mClientContactURI); } // Initialize the SipUserAgent's. // Set the user-agent strings. mServerUserAgent.setUserAgentHeaderProperty("sipXecs/rls"); mClientUserAgent.setUserAgentHeaderProperty("sipXecs/rls"); // Require the "eventlist" extension in the Resource List clients. mServerUserAgent.requireExtension(SIP_EVENTLIST_EXTENSION); // Set the subscribe server grant times. if (!mSubscriptionMgr.setSubscriptionTimes(serverMinExpiration, serverDefaultExpiration, serverMaxExpiration)) { OsSysLog::add(FAC_RLS, PRI_ERR, "ResourceListServer given unacceptable server subscription times: min = %d, default = %d, max = %d. Using the default subscription times.", serverMinExpiration, serverDefaultExpiration, serverMaxExpiration); } }
void testTwoHookTypes() { OsConfigDb configuration; configuration.set("TWO_TYPE_NOTPASSED_HOOK_LIBRARY.Error", PLUGIN_LIB_DIR "libfoo" PLUGIN_EXT); configuration.set("TWO_TYPE_OTHERPARAM", "DummyValue"); // Configure two different hook types - each in its own library // (we cheat - it's the same source, modified by configuration // switches; see comments in ../testplugin/TestPlugin.cpp) configuration.set("TWO_TYPE1_HOOK_LIBRARY.First", PLUGIN_LIB_DIR "libtestpluginA" PLUGIN_EXT); configuration.set("TWO_TYPE1.First.VALUE", "FirstValue"); configuration.set("TWO_TYPE2_HOOK_LIBRARY.Second", PLUGIN_LIB_DIR "libtestpluginB" PLUGIN_EXT); configuration.set("TWO_TYPE2.Second.VALUE", "SecondValue"); // load the first hook type PluginHooks test1Plugins("getTestPlugin", "TWO_TYPE1"); test1Plugins.readConfig(configuration); // load the second hook type PluginHooks test2Plugins("getTestPlugin", "TWO_TYPE2"); test2Plugins.readConfig(configuration); // create iterators for both hook types PluginIterator plugin1(test1Plugins); PluginIterator plugin2(test2Plugins); UtlString name; TestPlugin* thePlugin; UtlString fullName; // get the first instance of the first hook type and confirm the names thePlugin = static_cast<TestPlugin*>(plugin1.next(&name)); CPPUNIT_ASSERT(thePlugin != NULL); thePlugin->pluginName(fullName); ASSERT_STR_EQUAL("TestPluginA::First",fullName.data()); // confirm the first hook type is using the correct configuration value const UtlString ValueKey("VALUE"); UtlString pluginValue; CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue)); ASSERT_STR_EQUAL("FirstValue",pluginValue.data()); // get the first instance of the second hook type and confim its names thePlugin = static_cast<TestPlugin*>(plugin2.next(&name)); CPPUNIT_ASSERT(thePlugin != NULL); thePlugin->pluginName(fullName); ASSERT_STR_EQUAL("TestPluginB::Second",fullName.data()); // confirm the configuration of the second hook type CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue)); ASSERT_STR_EQUAL("SecondValue",pluginValue.data()); // make sure each type only has the one instance CPPUNIT_ASSERT(plugin1.next(&name) == NULL); CPPUNIT_ASSERT(name.isNull()); CPPUNIT_ASSERT(plugin2.next(&name) == NULL); CPPUNIT_ASSERT(name.isNull()); }
void handleRemoteNATedToRemoteNATedCall() { const char* message = "INVITE sip:[email protected]:5060;x-sipX-pubcontact=47.135.162.145%3A29544 SIP/2.0\r\n" "Record-Route: <sip:192.168.0.2:5060;lr>\r\n" "From: caller <sip:[email protected]>;tag=94bc25b8-c0a80165-13c4-3e635-37aa1989-3e635\r\n" "To: <sip:[email protected]>\r\n" "Call-Id: 94bb2520-c0a80165-13c4-3e635-3ccd2971-3e635@rjolyscs2.ca.nortel.com\r\n" "Cseq: 1 INVITE\r\n" "Max-Forwards: 19\r\n" "Supported: replaces\r\n" "User-Agent: LG-Nortel LIP 6804 v1.2.38sp SN/00405A187376\r\n" "Contact: <sip:[email protected]:5060;x-sipX-pubcontact=47.135.162.145%3A14956>\r\n" "Content-Type: application/sdp\r\n" "Content-Length: 297\r\n" "Date: Thu, 12 Jun 2008 19:14:29 GMT\r\n" "Via: SIP/2.0/UDP 192.168.0.2;branch=z9hG4bK-sipXecs-01a17f9662b96b1d454a71775bbda1ec6bf6~9d6590763d78764b93a42e94dbd6b75a\r\n" "Via: SIP/2.0/UDP 192.168.1.101:5060;branch=z9hG4bK-3e635-f3b41fc-310ddca7;received=47.135.162.145;rport=14956\r\n" "\r\n" "\r\n" "v=0\r\n" "o=LGEIPP 874 874 IN IP4 192.168.1.101\r\n" "s=SIP Call\r\n" "c=IN IP4 192.168.1.101\r\n" "t=0 0\r\n" "m=audio 23000 RTP/AVP 18 0 8 4 101\r\n" "a=rtpmap:18 G729/8000\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=rtpmap:8 PCMA/8000\r\n" "a=rtpmap:4 G723/8000\r\n" "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:18 annexb=no\r\n" "a=fmtp:101 0-11\r\n" "a=sendrecv\r\n"; SipMessage testMsg(message, strlen(message)); UtlString rejectReason; UtlSList emptyList; RouteState routeState( message, emptyList, "192.168.0.2:5060" ); AuthPlugin::AuthResult result; result = pNatTraversalAgent->authorizeAndModify( "id", //dummy Url("sip:[email protected]:5060"), //dummy routeState, "INVITE", AuthPlugin::CONTINUE, testMsg, false, rejectReason ); // check auth result CPPUNIT_ASSERT( result == AuthPlugin::CONTINUE ); // check that call tracker got created UtlString callId; CallTracker* pTracker; testMsg.getCallIdField( &callId ); pTracker = pNatTraversalAgent->getCallTrackerFromCallId( callId ); CPPUNIT_ASSERT( pTracker != 0 ); // check that public transport of caller got encoded in route state UtlString transportInfo; routeState.getParameter( pNatTraversalAgent->mInstanceName.data(), CALLER_PUBLIC_TRANSPORT_PARAM, transportInfo ); ASSERT_STR_EQUAL( "47.135.162.145:14956;transport=udp", transportInfo.data() ); // check that public transport of callee got encoded in route state routeState.getParameter( pNatTraversalAgent->mInstanceName.data(), CALLEE_PUBLIC_TRANSPORT_PARAM, transportInfo ); ASSERT_STR_EQUAL( "47.135.162.145:29544;transport=udp", transportInfo.data() ); // Check that sipX NAT route is set to reach the callee's public IP address UtlString natRoute; CPPUNIT_ASSERT( testMsg.getSipXNatRoute( &natRoute ) == true ); ASSERT_STR_EQUAL( "47.135.162.145:29544;transport=udp", natRoute.data() ); // Now present the message to the Output Processor and verify that it got processed correctly. routeState.update( &testMsg ); // uodate route state as it would normally be done by SipRouter. pNatTraversalAgent->handleOutputMessage( testMsg, "47.135.162.145", 29544 ); // verify that top via got adjusted to reflect our public IP address UtlString topmostVia; CPPUNIT_ASSERT( testMsg.getViaFieldSubField( &topmostVia, 0 ) ); ASSERT_STR_EQUAL( "SIP/2.0/UDP 47.135.162.140:5060;branch=z9hG4bK-sipXecs-01a17f9662b96b1d454a71775bbda1ec6bf6~9d6590763d78764b93a42e94dbd6b75a", topmostVia.data() ); // verify that top route got modfified to reflect our public address UtlString tmpRecordRoute; CPPUNIT_ASSERT( testMsg.getRecordRouteUri( 0, &tmpRecordRoute ) ); Url tmpRecordRouteUrl( tmpRecordRoute ); UtlString tmpRecordRouteHost; tmpRecordRouteUrl.getHostWithPort( tmpRecordRouteHost ); ASSERT_STR_EQUAL( "47.135.162.140:5060", tmpRecordRouteHost.data() ); // recall the call tracker based on message and compare with previous CallTracker* pTracker2; pTracker2 = pNatTraversalAgent->getCallTrackerForMessage( testMsg ); CPPUNIT_ASSERT( pTracker2 == pTracker ); // check that the SDP got changed properly to relay media const SdpBody* pSdpBody = testMsg.getSdpBody(); CPPUNIT_ASSERT( pSdpBody ); UtlString mediaType, mediaTransportType; int mediaPort, mediaPortPairs, numPayloadTypes, payloadTypes[10]; SdpDirectionality dir; CPPUNIT_ASSERT( pSdpBody->getMediaData( 0, &mediaType, &mediaPort, &mediaPortPairs, &mediaTransportType, 10, &numPayloadTypes, payloadTypes, &dir ) == TRUE ); CPPUNIT_ASSERT( mediaType == "audio" ); CPPUNIT_ASSERT( mediaPort == 10000 ); CPPUNIT_ASSERT( mediaPortPairs == 1 ); CPPUNIT_ASSERT( mediaTransportType == "RTP/AVP" ); CPPUNIT_ASSERT( numPayloadTypes == 5 ); CPPUNIT_ASSERT( payloadTypes[0] == 18 ); CPPUNIT_ASSERT( payloadTypes[1] == 0 ); CPPUNIT_ASSERT( payloadTypes[2] == 8 ); CPPUNIT_ASSERT( payloadTypes[3] == 4 ); CPPUNIT_ASSERT( payloadTypes[4] == 101 ); CPPUNIT_ASSERT( dir == sdpDirectionalitySendRecv ); // check that we are using the public IP address of the media relay UtlString mediaAddress; CPPUNIT_ASSERT( pSdpBody->getMediaAddress(0, &mediaAddress ) ); ASSERT_STR_EQUAL( pNatTraversalAgent->mNatTraversalRules.getMediaRelayPublicAddress(), mediaAddress ); // Mow simulalate the reception of the response const char* response = "SIP/2.0 200 OK\r\n" "From: \"R1_2 - 602\"<sip:[email protected]>;tag=94bc25b8-c0a80165-13c4-3e635-37aa1989-3e635\r\n" "To: <sip:[email protected]>;tag=94bf84d0-c0a8010b-13c4-3e8d1-496994c2-3e8d1\r\n" "Call-ID: 94bb2520-c0a80165-13c4-3e635-3ccd2971-3e635@rjolyscs2.ca.nortel.com\r\n" "CSeq: 1 INVITE\r\n" "Via: SIP/2.0/UDP 192.168.1.101:5060;received=47.135.162.145;rport=14956;branch=z9hG4bK-3e635-f3b41fc-310ddca7;id=1234-0\r\n" "Supported: replaces\r\n" "Contact: <sip:[email protected]:5060>\r\n" "Record-Route: <sip:47.135.162.140:5060;lr;sipXecs-rs=%2Afrom%7EOTRiYzI1YjgtYzBhODAxNjUtMTNjNC0zZTYzNS0zN2FhMTk4OS0zZTYzNQ%60%60.400_authrules%2Aauth%7E.900_ntap%2ACeT%7ENDcuMTM1LjE2Mi4xNDU6Mjk1NDQ7dHJhbnNwb3J0PXVkcA%60%60.900_ntap%2ACrT%7ENDcuMTM1LjE2Mi4xNDU6MTQ5NTY7dHJhbnNwb3J0PXVkcA%60%60.900_ntap%2Aid%7EMC0w%215d4c53f8d9c9ecd8d089e57ba7a59513>\r\n" "Content-Type: application/sdp\r\n" "Content-Length: 202\r\n" "\r\n" "\r\n" "v=0\r\n" "o=LGEIPP 5466 5466 IN IP4 192.168.1.11\r\n" "s=SIP Call\r\n" "c=IN IP4 192.168.1.11\r\n" "t=0 0\r\n" "m=audio 23020 RTP/AVP 0 101\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:101 0-11\r\n" "a=sendrecv\r\n" "a=x-sipx-ntap:192.168.0.2;1\r\n"; SipMessage okResp( response, strlen(response) ); pNatTraversalAgent->handleOutputMessage( okResp, "47.135.162.145", 14956 ); // check that the record route still has our public IP address CPPUNIT_ASSERT( okResp.getRecordRouteUri( 0, &tmpRecordRoute ) ); Url tmpRecordRouteUrl2( tmpRecordRoute ); tmpRecordRouteUrl2.getHostWithPort( tmpRecordRouteHost ); ASSERT_STR_EQUAL( "47.135.162.140:5060", tmpRecordRouteHost.data() ); // check that the SDP got changed properly to relay media pSdpBody = okResp.getSdpBody(); CPPUNIT_ASSERT( pSdpBody ); CPPUNIT_ASSERT( pSdpBody->getMediaData( 0, &mediaType, &mediaPort, &mediaPortPairs, &mediaTransportType, 10, &numPayloadTypes, payloadTypes, &dir ) == TRUE ); CPPUNIT_ASSERT( mediaType == "audio" ); CPPUNIT_ASSERT( mediaPort == 11000 ); CPPUNIT_ASSERT( mediaPortPairs == 1 ); CPPUNIT_ASSERT( mediaTransportType == "RTP/AVP" ); CPPUNIT_ASSERT( numPayloadTypes == 2 ); CPPUNIT_ASSERT( payloadTypes[0] == 0); CPPUNIT_ASSERT( payloadTypes[1] == 101 ); CPPUNIT_ASSERT( dir == sdpDirectionalitySendRecv ); // check that we are using the public IP address of the media relay CPPUNIT_ASSERT( pSdpBody->getMediaAddress(0, &mediaAddress ) ); ASSERT_STR_EQUAL( pNatTraversalAgent->mNatTraversalRules.getMediaRelayPublicAddress(), mediaAddress ); }
void SipRedirectorMPT::processForm(const HttpRequestContext& requestContext, const HttpMessage& request, HttpMessage*& response) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm entered", mLogName.data()); UtlString* user; // Process the request. // Get the body of the request. const HttpBody* request_body = request.getBody(); // Get the value from the form. // This is quite a chore, because getMultipartBytes gets the entire // multipart section, including the trailing delimiter, rather than just // the body, which is what we need. const char* value; int length; request_body->getMultipartBytes(0, &value, &length); #if 0 OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm A *** seeing '%.*s'", mLogName.data(), length, value); #endif // Advance 'value' over the first \r\n\r\n, which ends the headers. const char* s = strstr(value, "\r\n\r\n"); if (s) { s += 4; // Allow for length of \r\n\r\n. length -= s - value; value = s; } OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm B *** seeing '%.*s'", mLogName.data(), length, value); #if 0 // Search backward for the last \r, excepting the one in the second-to-last // position, which marks the end of the contents. if (length >= 3) { for (s = value + length - 3; !(s == value || *s == '\r'); s--) { /* empty */ } length = s - value; } OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm seeing '%.*s'", mLogName.data(), length, value); #endif // Add the mappings. const char* error_msg; int error_location; UtlBoolean success = MPTredirector->addMappings(value, length, user, error_msg, error_location); // Construct the response. response = new HttpMessage(); // Send 200 OK reply. response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION, HTTP_OK_CODE, HTTP_OK_TEXT); // Construct the HTML. char buffer1[100]; #if 0 OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm *** domain '%s'", mLogName.data(), MPTredirector->mDomainName.data()); #endif if (success) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm success user '%s'", mLogName.data(), user->data()); sprintf(buffer1, "<code>sip:<font size=\"+1\">%s</font>@%s:65070</code> redirects to:<br />", user->data(), MPTredirector->mDomainName.data()); } else { OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::processForm failure error_msg '%s', error_location %d", mLogName.data(), error_msg, error_location); strcpy(buffer1, "<i>Error:</i>"); } // Transcribe the input value into buffer2. char buffer2[FORM_SIZE]; char* p; int i; if (success) { // An impossible location. error_location = -1; } for (p = buffer2, i = 0; ; i++) { // If this is the error location, insert the error message. if (i == error_location) { *p++ = '!'; *p++ = '-'; *p++ = '-'; strcpy(p, error_msg); p += strlen(error_msg); *p++ = '-'; *p++ = '-'; *p++ = '!'; } // Test for ending the loop after testing to insert the error message, // because the error message may be after the last character. if (i >= length) { break; } switch (value[i]) { case '<': *p++ = '&'; *p++ = 'l'; *p++ = 't'; *p++ = ';'; break; case '>': *p++ = '&'; *p++ = 'g'; *p++ = 't'; *p++ = ';'; break; case '&': *p++ = '&'; *p++ = 'a'; *p++ = 'm'; *p++ = 'p'; *p++ = ';'; break; default: *p++ = value[i]; break; } } *p++ = '\0'; char buffer[FORM_SIZE]; sprintf(buffer, form, buffer1, buffer2); // Insert the HTML into the response. HttpBody* response_body = new HttpBody(buffer, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); }
int HttpGetCommand::execute(int argc, char* argv[]) { int commandStatus = CommandProcessor::COMMAND_FAILED; if(argc == 2) { commandStatus = CommandProcessor::COMMAND_SUCCESS; const char* url = argv[1]; const char* serverBegin = strstr(url, "http://"); if(serverBegin != url) { printf("unsupported protocol in Url: %s\n", url); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; } else { serverBegin += 7; UtlString uri(serverBegin); int serverEndIndex = uri.index("/"); if(serverEndIndex < 0) serverEndIndex = uri.length(); if(serverEndIndex > 0) { UtlString server = uri; server.remove(serverEndIndex); int portIndex = server.index(":"); int port = PORT_NONE; if(portIndex > 0) { UtlString portString = server; server.remove(portIndex); portString.remove(0, portIndex + 1); printf("port string: %s\n", portString.data()); port = atoi(portString.data()); } uri.remove(0, serverEndIndex); if(uri.isNull()) uri = "/"; printf("HTTP get of %s from server %s port: %d\n", uri.data(), server.data(), port); if (!portIsValid(port)) { port = 80; printf("defaulting to http port 80\n"); } OsConnectionSocket getSocket(port, server.data()); HttpMessage getRequest; getRequest.setFirstHeaderLine("GET", uri.data(), HTTP_PROTOCOL_VERSION); int wroteBytes = getRequest.write(&getSocket); printf("wrote %d\n", wroteBytes); HttpMessage getResponse; getResponse.read(&getSocket); UtlString responseBytes; int responseLength; getResponse.getBytes(&responseBytes, &responseLength); printf("Got %d bytes\n", responseLength); printf("Response: ++++++++++++++++++++++++++++++++++\n%s\n", responseBytes.data()); } else { printf("invalid server in Url: %s\n", url); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; } } } else { UtlString usage; getUsage(argv[0], &usage); printf("%s", usage.data()); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; //commandStatus = CommandProcessor::COMMAND_FAILED; } return(commandStatus); }
void handleLocalNATedToRemoteNATedCall() { const char* message = "INVITE sip:[email protected]:5060;x-sipX-pubcontact=47.135.162.145%3A29544 SIP/2.0\r\n" "Record-Route: <sip:192.168.0.2:5060;lr>\r\n" "From: \"L3\"<sip:[email protected]>;tag=94bb9480-c0a80065-13c4-50045-20c55bd3-50045\r\n" "To: <sip:[email protected]>\r\n" "Call-Id: 94bb55a0-c0a80065-13c4-50045-61a3ad3-50045@rjolyscs2.ca.nortel.com\r\n" "Cseq: 1 INVITE\r\n" "Via: SIP/2.0/UDP 192.168.0.2;branch=z9hG4bK-sipXecs-8130adee90e0277761fec4ee1c194a56838f~9d6590763d78764b93a42e94dbd6b75a\r\n" "Via: SIP/2.0/UDP 192.168.0.101:5060;branch=z9hG4bK-50045-13890e4e-4f17a229\r\n" "Max-Forwards: 19\r\n" "Supported: replaces\r\n" "User-Agent: LG-Nortel LIP 6812 v1.2.38sp SN/00405A183385\r\n" "Contact: <sip:[email protected]:5060;x-sipX-nonat>\r\n" "Content-Type: application/sdp\r\n" "Content-Length: 301\r\n" "Date: Fri, 13 Jun 2008 14:48:44 GMT\r\n" "\r\n" "\r\n" "v=0\r\n" "o=LGEIPP 14595 14595 IN IP4 192.168.0.101\r\n" "s=SIP Call\r\n" "c=IN IP4 192.168.0.101\r\n" "t=0 0\r\n" "m=audio 23016 RTP/AVP 18 4 0 8 101\r\n" "a=rtpmap:18 G729/8000\r\n" "a=rtpmap:4 G723/8000\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=rtpmap:8 PCMA/8000\r\n" "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:18 annexb=no\r\n" "a=fmtp:101 0-11\r\n" "a=sendrecv\r\n"; SipMessage testMsg(message, strlen(message)); UtlString rejectReason; UtlSList emptyList; RouteState routeState( message, emptyList, "192.168.0.2:5060" ); AuthPlugin::AuthResult result; result = pNatTraversalAgent->authorizeAndModify( "id", //dummy Url("sip:[email protected]:5060"), //dummy routeState, "INVITE", AuthPlugin::CONTINUE, testMsg, false, rejectReason ); // check auth result CPPUNIT_ASSERT( result == AuthPlugin::CONTINUE ); // check that call tracker got created UtlString callId; CallTracker* pTracker; testMsg.getCallIdField( &callId ); pTracker = pNatTraversalAgent->getCallTrackerFromCallId( callId ); CPPUNIT_ASSERT( pTracker != 0 ); // check that no public transport of caller got encoded in route state UtlString transportInfo; CPPUNIT_ASSERT( !routeState.getParameter( pNatTraversalAgent->mInstanceName.data(), CALLER_PUBLIC_TRANSPORT_PARAM, transportInfo ) ); // check that public transport of callee got encoded in route state routeState.getParameter( pNatTraversalAgent->mInstanceName.data(), CALLEE_PUBLIC_TRANSPORT_PARAM, transportInfo ); ASSERT_STR_EQUAL( "47.135.162.145:29544;transport=udp", transportInfo.data() ); // Check that sipX NAT route is set to reach the callee's public IP address UtlString natRoute; CPPUNIT_ASSERT( testMsg.getSipXNatRoute( &natRoute ) == true ); ASSERT_STR_EQUAL( "47.135.162.145:29544;transport=udp", natRoute.data() ); // Now present the message to the Output Processor and verify that it got processed correctly. routeState.update( &testMsg ); // uodate route state as it would normally be done by SipRouter. pNatTraversalAgent->handleOutputMessage( testMsg, "47.135.162.145", 29544 ); // verify that top via got adjusted to reflect our public IP address UtlString topmostVia; CPPUNIT_ASSERT( testMsg.getViaFieldSubField( &topmostVia, 0 ) ); ASSERT_STR_EQUAL( "SIP/2.0/UDP 47.135.162.140:5060;branch=z9hG4bK-sipXecs-8130adee90e0277761fec4ee1c194a56838f~9d6590763d78764b93a42e94dbd6b75a", topmostVia.data() ); // verify that top route got modfified to reflect our public address UtlString tmpRecordRoute; CPPUNIT_ASSERT( testMsg.getRecordRouteUri( 0, &tmpRecordRoute ) ); Url tmpRecordRouteUrl( tmpRecordRoute ); UtlString tmpRecordRouteHost; tmpRecordRouteUrl.getHostWithPort( tmpRecordRouteHost ); ASSERT_STR_EQUAL( "47.135.162.140:5060", tmpRecordRouteHost.data() ); // recall the call tracker based on message and compare with previous CallTracker* pTracker2; pTracker2 = pNatTraversalAgent->getCallTrackerForMessage( testMsg ); CPPUNIT_ASSERT( pTracker2 == pTracker ); // check that the SDP got changed properly to relay media const SdpBody* pSdpBody = testMsg.getSdpBody(); CPPUNIT_ASSERT( pSdpBody ); UtlString mediaType, mediaTransportType; int mediaPort, mediaPortPairs, numPayloadTypes, payloadTypes[10]; SdpDirectionality dir; CPPUNIT_ASSERT( pSdpBody->getMediaData( 0, &mediaType, &mediaPort, &mediaPortPairs, &mediaTransportType, 10, &numPayloadTypes, payloadTypes, &dir ) == TRUE ); CPPUNIT_ASSERT( mediaType == "audio" ); CPPUNIT_ASSERT( mediaPort == 10000 ); CPPUNIT_ASSERT( mediaPortPairs == 1 ); CPPUNIT_ASSERT( mediaTransportType == "RTP/AVP" ); CPPUNIT_ASSERT( numPayloadTypes == 5 ); CPPUNIT_ASSERT( payloadTypes[0] == 18 ); CPPUNIT_ASSERT( payloadTypes[1] == 4 ); CPPUNIT_ASSERT( payloadTypes[2] == 0 ); CPPUNIT_ASSERT( payloadTypes[3] == 8 ); CPPUNIT_ASSERT( payloadTypes[4] == 101 ); CPPUNIT_ASSERT( dir == sdpDirectionalitySendRecv ); // check that we are using the public IP address of the media relay UtlString mediaAddress; CPPUNIT_ASSERT( pSdpBody->getMediaAddress(0, &mediaAddress ) ); ASSERT_STR_EQUAL( pNatTraversalAgent->mNatTraversalRules.getMediaRelayPublicAddress(), mediaAddress ); // Mow simulalate the reception of the response const char* response = "SIP/2.0 200 OK\r\n" "From: \"L3\"<sip:[email protected]>;tag=94bb9480-c0a80065-13c4-50045-20c55bd3-50045\r\n" "To: <sip:[email protected]>;tag=94bf81c0-c0a8010b-13c4-4fc07-650a9211-4fc07\r\n" "Call-Id: 94bb55a0-c0a80065-13c4-50045-61a3ad3-50045@rjolyscs2.ca.nortel.com\r\n" "Cseq: 1 INVITE\r\n" "Via: SIP/2.0/UDP 192.168.0.101:5060;branch=z9hG4bK-50045-13890e4e-4f17a229;id=1234-1\r\n" "Supported: replaces\r\n" "Contact: <sip:[email protected]:5060>\r\n" "Record-Route: <sip:47.135.162.140:5060;lr;sipXecs-rs=%2Afrom%7EOTRiYjk0ODAtYzBhODAwNjUtMTNjNC01MDA0NS0yMGM1NWJkMy01MDA0NQ%60%60.400_authrules%2Aauth%7E.900_ntap%2ACeT%7ENDcuMTM1LjE2Mi4xNDU6Mjk1NDQ7dHJhbnNwb3J0PXVkcA%60%60.900_ntap%2Aid%7EMy0z%21641c6aa1807d3544000f310a64a5360a>\r\n" "Content-Type: application/sdp\r\n" "Content-Length: 250\r\n" "Date: Fri, 13 Jun 2008 14:48:46 GMT\r\n" "\r\n" "\r\n" "v=0\r\n" "o=LGEIPP 12617 12617 IN IP4 192.168.1.11\r\n" "s=SIP Call\r\n" "c=IN IP4 192.168.1.11\r\n" "t=0 0\r\n" "m=audio 25038 RTP/AVP 4 101\r\n" "c=IN IP4 192.168.0.2\r\n" "a=rtpmap:4 G723/8000\r\n" "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:101 0-11\r\n" "a=sendrecv\r\n" "a=x-sipx-ntap:192.168.0.2;3\r\n"; SipMessage okResp( response, strlen(response) ); pNatTraversalAgent->handleOutputMessage( okResp, "192.168.0.101", 5060 ); // check that the record route has our private IP address CPPUNIT_ASSERT( okResp.getRecordRouteUri( 0, &tmpRecordRoute ) ); Url tmpRecordRouteUrl2( tmpRecordRoute ); tmpRecordRouteUrl2.getHostWithPort( tmpRecordRouteHost ); ASSERT_STR_EQUAL( "192.168.0.2:5060", tmpRecordRouteHost.data() ); // check that the SDP got changed properly to relay media pSdpBody = okResp.getSdpBody(); CPPUNIT_ASSERT( pSdpBody ); CPPUNIT_ASSERT( pSdpBody->getMediaData( 0, &mediaType, &mediaPort, &mediaPortPairs, &mediaTransportType, 10, &numPayloadTypes, payloadTypes, &dir ) == TRUE ); CPPUNIT_ASSERT( mediaType == "audio" ); CPPUNIT_ASSERT( mediaPort == 11000 ); CPPUNIT_ASSERT( mediaPortPairs == 1 ); CPPUNIT_ASSERT( mediaTransportType == "RTP/AVP" ); CPPUNIT_ASSERT( numPayloadTypes == 2 ); CPPUNIT_ASSERT( payloadTypes[0] == 4); CPPUNIT_ASSERT( payloadTypes[1] == 101 ); CPPUNIT_ASSERT( dir == sdpDirectionalitySendRecv ); // check that we are using the native IP address of the media relay CPPUNIT_ASSERT( pSdpBody->getMediaAddress(0, &mediaAddress ) ); ASSERT_STR_EQUAL( pNatTraversalAgent->mNatTraversalRules.getMediaRelayNativeAddress(), mediaAddress ); }
/* //////////////////////////// PROTECTED ///////////////////////////////// */ void Connection::postTaoListenerMessage(int state, int newCause, int isLocal) { int eventId = PtEvent::EVENT_INVALID; int termEventId = PtEvent::EVENT_INVALID; UtlString causeStr; causeStr.remove(0); #ifdef TEST_PRINT Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::postTaoListenerMessage: " "Enter- %s state %d cause %d " "eventid- %d termeventid %d", (isLocal?"LOCAL":"REMOTE"), state, newCause, eventId, termEventId); #endif switch(state) { case CONNECTION_IDLE: eventId = PtEvent::CONNECTION_CREATED; termEventId = PtEvent::TERMINAL_CONNECTION_IDLE; break; case CONNECTION_INITIATED: eventId = PtEvent::CONNECTION_INITIATED; termEventId = PtEvent::TERMINAL_CONNECTION_CREATED; break; case CONNECTION_QUEUED: eventId = PtEvent::CONNECTION_QUEUED; termEventId = PtEvent::CONNECTION_CREATED; break; case CONNECTION_OFFERING: eventId = PtEvent::CONNECTION_OFFERED; break; case CONNECTION_DIALING: eventId = PtEvent::CONNECTION_DIALING ; break; case CONNECTION_ALERTING: eventId = PtEvent::CONNECTION_ALERTING; termEventId = PtEvent::TERMINAL_CONNECTION_RINGING; break; case CONNECTION_ESTABLISHED: eventId = PtEvent::CONNECTION_ESTABLISHED; termEventId = PtEvent::TERMINAL_CONNECTION_TALKING; break; case CONNECTION_FAILED: eventId = PtEvent::CONNECTION_FAILED; termEventId = PtEvent::TERMINAL_CONNECTION_DROPPED; break; case CONNECTION_DISCONNECTED: eventId = PtEvent::CONNECTION_DISCONNECTED; termEventId = PtEvent::TERMINAL_CONNECTION_DROPPED; break; case PtEvent::TERMINAL_CONNECTION_HELD: termEventId = PtEvent::TERMINAL_CONNECTION_HELD; break; default: eventId = PtEvent::CONNECTION_UNKNOWN; termEventId = PtEvent::TERMINAL_CONNECTION_UNKNOWN; break; } int cause; switch(newCause) { case CONNECTION_CAUSE_UNKNOWN: cause = PtEvent::CAUSE_UNKNOWN; causeStr.append("CAUSE_UNKNOWN"); break; case CONNECTION_CAUSE_REDIRECTED: cause = PtEvent::CAUSE_REDIRECTED; causeStr.append("CAUSE_REDIRECTED"); break ; case CONNECTION_CAUSE_NETWORK_CONGESTION: cause = PtEvent::CAUSE_NETWORK_CONGESTION; causeStr.append("CAUSE_NETWORK_CONGESTION"); break; case CONNECTION_CAUSE_NETWORK_NOT_OBTAINABLE: cause = PtEvent::CAUSE_NETWORK_NOT_OBTAINABLE; causeStr.append("CAUSE_NETWORK_NOT_OBTAINABLE"); break; case CONNECTION_CAUSE_DEST_NOT_OBTAINABLE: cause = PtEvent::CAUSE_DESTINATION_NOT_OBTAINABLE; causeStr.append("CAUSE_DESTINATION_NOT_OBTAINABLE"); break; case CONNECTION_CAUSE_INCOMPATIBLE_DESTINATION: cause = PtEvent::CAUSE_INCOMPATIBLE_DESTINATION; causeStr.append("CAUSE_INCOMPATIBLE_DESTINATION"); break; case CONNECTION_CAUSE_NOT_ALLOWED: cause = PtEvent::CAUSE_NOT_ALLOWED; causeStr.append("CAUSE_NOT_ALLOWED"); break; case CONNECTION_CAUSE_NETWORK_NOT_ALLOWED: cause = PtEvent::CAUSE_NETWORK_NOT_ALLOWED; causeStr.append("CAUSE_NETWORK_NOT_ALLOWED"); break; case CONNECTION_CAUSE_BUSY: case CONNECTION_CAUSE_SERVICE_UNAVAILABLE: cause = PtEvent::CAUSE_BUSY; causeStr.append("CAUSE_BUSY"); break ; case CONNECTION_CAUSE_CANCELLED: cause = PtEvent::CAUSE_CALL_CANCELLED; causeStr.append("CAUSE_CALL_CANCELLED"); break ; case CONNECTION_CAUSE_TRANSFER: cause = PtEvent::CAUSE_TRANSFER; causeStr.append("CAUSE_TRANSFER"); break; default: case CONNECTION_CAUSE_NORMAL: cause = PtEvent::CAUSE_NORMAL; causeStr.append("CAUSE_NORMAL"); break; } int cnt = 0; if (mpListenerCnt) cnt = mpListenerCnt->getRef(); if (cnt > 0) { TaoObjHandle* pListeners; pListeners = new TaoObjHandle[cnt]; mpListeners->getActiveObjects(pListeners, cnt); UtlString callId; // Use the connection call id first -- followed by call if // unavailable getCallId(&callId); // arg[0], callId if (callId.isNull()) { mpCall->getCallId(callId); #ifdef TEST_PRINT Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::postTaoListenerMessage: " "Connection call id not found, " "Using CpCall Id = %s ", callId.data()); #endif } callId += TAOMESSAGE_DELIMITER + mLocalAddress; // arg[1], localAddress UtlString remoteAddress; getRemoteAddress(&remoteAddress, TRUE); if (remoteAddress.isNull()) // arg[2], remote address { callId += TAOMESSAGE_DELIMITER + (UtlString)"UNKNOWN"; // not available yet } else { callId += TAOMESSAGE_DELIMITER + remoteAddress; } char buff[128]; sprintf(buff, "%d", (int)mRemoteIsCallee); callId += TAOMESSAGE_DELIMITER + UtlString(buff); // arg[3], remoteIsCallee sprintf(buff, "%d", cause); callId += TAOMESSAGE_DELIMITER + UtlString(buff); // arg[4], cause if (mRemoteIsCallee) { remoteAddress.insert(0, "foreign-terminal-"); callId += TAOMESSAGE_DELIMITER + remoteAddress; // arg[5], remote terminal name } else { mpCall->getLocalTerminalId(buff, 127); callId += TAOMESSAGE_DELIMITER + UtlString(buff); // arg[5], local terminal name } if (isLocal) // TAO_OFFER_PARAM_LOCAL_CONNECTION { callId += TAOMESSAGE_DELIMITER + "1"; // arg[6], isLocal } else { callId += TAOMESSAGE_DELIMITER + "0"; // isLocal } sprintf(buff, "%d", mResponseCode); callId += TAOMESSAGE_DELIMITER + UtlString(buff); // arg[7], SIP response code callId += TAOMESSAGE_DELIMITER + mResponseText; // arg[8], SIP response text int argCnt = 9; if(mpCall) { int metaEventId = 0; int metaEventType = PtEvent::META_EVENT_NONE; int numCalls = 0; const UtlString* metaEventCallIds = NULL; mpCall->getMetaEvent(metaEventId, metaEventType, numCalls, &metaEventCallIds); if (metaEventId != PtEvent::META_EVENT_NONE) { sprintf(buff, "%d", metaEventId); callId += TAOMESSAGE_DELIMITER + UtlString(buff); // arg[9], meta event id sprintf(buff, "%d", metaEventType); callId += TAOMESSAGE_DELIMITER + UtlString(buff); // arg[10], meta code argCnt += 2; for (int i = 0; i < numCalls; i++) { if (metaEventCallIds && metaEventCallIds[i]) { callId += TAOMESSAGE_DELIMITER + metaEventCallIds[i]; // meta call ids argCnt++; } } } } TaoMessage msg(TaoMessage::EVENT, 0, 0, eventId, 0, argCnt, callId); UtlString eventIdStr; if (eventId != PtEvent::EVENT_INVALID) { for (int i = 0; i < cnt; i++) // post connection events { ((OsServerTask*) pListeners[i])->postMessage((OsMsg&)msg); } mpCall->getStateString(eventId, &eventIdStr); mpCallManager->logCallState(callId.data(), eventIdStr.data(), causeStr); } if (termEventId != PtEvent::EVENT_INVALID) // post terminal connection events { msg.setObjHandle(termEventId); for (int i = 0; i < cnt; i++) { ((OsServerTask*) pListeners[i])->postMessage((OsMsg&)msg); } mpCall->getStateString(termEventId, &eventIdStr); mpCallManager->logCallState(callId.data(), eventIdStr.data(), causeStr); } delete[] pListeners; callId.remove(0); eventIdStr.remove(0); remoteAddress.remove(0); } #ifdef TEST_PRINT Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::postTaoListenerMessage: " "Leave- %s state %d cause %d " "eventid- %d termeventid %d", (isLocal?"LOCAL":"REMOTE"), state, newCause, eventId, termEventId); #endif causeStr.remove(0); }
// Constructor Connection::Connection(CpCallManager* callMgr, CpCall* call, CpMediaInterface* mediaInterface, //UiContext* callUiContext, int offeringDelayMilliSeconds, int availableBehavior, const char* forwardUnconditionalUrl, int busyBehavior, const char* forwardOnBusyUrl, int forwardOnNoAnswerSeconds) : mConnectionId(-1) , callIdMutex(OsMutex::Q_FIFO) , mDeleteAfter(OsTime::OS_INFINITY) { #ifdef TEST_PRINT UtlString callId; if (call) { call->getCallId(callId); Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::Connection- %s\n", callId.data()); } else Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::Connection- call is Null\n"); #endif mOfferingDelay = offeringDelayMilliSeconds; mLineAvailableBehavior = availableBehavior; if(mLineAvailableBehavior == FORWARD_UNCONDITIONAL && forwardUnconditionalUrl != NULL) { mForwardUnconditional.append(forwardUnconditionalUrl); } mLineBusyBehavior = busyBehavior; if(mLineBusyBehavior == FORWARD_ON_BUSY && forwardOnBusyUrl != NULL) { mForwardOnBusy.append(forwardOnBusyUrl); } mForwardOnNoAnswerSeconds = forwardOnNoAnswerSeconds; mRemoteIsCallee = FALSE; mRemoteRequestedHold = FALSE; remoteRtpPort = PORT_NONE; sendCodec = -1; receiveCodec = -1; mLocalConnectionState = CONNECTION_IDLE; mRemoteConnectionState = CONNECTION_IDLE; mConnectionStateCause = CONNECTION_CAUSE_NORMAL; mTerminalConnState = PtTerminalConnection::IDLE; mFarEndHoldState = TERMCONNECTION_NONE; mResponseCode = 0; mResponseText.remove(0); mpCallManager = callMgr; mpCall = call; mpMediaInterface = mediaInterface; mConnectionId = -10; //mpCallUiContext = callUiContext; mpListenerCnt = new TaoReference(); mpListeners = new TaoObjectMap(); m_eLastMajor = (SIPX_CALLSTATE_EVENT) -1 ; m_eLastMinor = (SIPX_CALLSTATE_CAUSE) -1 ; m_eLastAudioMajor = (SIPX_CALLSTATE_EVENT) -1 ; m_eLastAudioMinor = (SIPX_CALLSTATE_CAUSE) -1 ; CallId::getNewCallId(*this) ; #ifdef TEST_PRINT if (!callId.isNull()) Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::Connection -leaving: %s\n", callId.data()); else Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::Connection -leaving: call is Null\n"); #endif }
void Connection::setState(int newState, int isLocal, int newCause, int termState) { UtlString oldStateString; UtlString newStateString; int currentState = isLocal ? mLocalConnectionState : mRemoteConnectionState; getStateString(currentState, &oldStateString); getStateString(newState, &newStateString); int metaEventId = 0; int metaEventType = PtEvent::META_EVENT_NONE; int numCalls = 0; const UtlString* metaEventCallIds = NULL; if (mpCall) { mpCall->getMetaEvent(metaEventId, metaEventType, numCalls, &metaEventCallIds); } UtlString callId; if (mpCall) { mpCall->getCallId(callId); } if (callId.isNull()) callId="null"; UtlString strCallName; if (mpCall) { strCallName = mpCall->getName(); } if (strCallName.isNull()) { strCallName="null"; } if (!isStateTransitionAllowed(newState, currentState)) { // Under some conditions, "invalid" state changes are allowed. if (!(!isLocal && metaEventId > 0 && (metaEventType == PtEvent::META_CALL_TRANSFERRING || metaEventType == PtEvent::META_CALL_REPLACING))) { if (newState == currentState) { Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::setState: " "Questionable connection state change - isLocal %d, for call " "'%s' with callid '%s' from %s to %s, cause %d", isLocal, strCallName.data(), callId.data(), oldStateString.data(), newStateString.data(), newCause); } else { Os::Logger::instance().log(FAC_CP, PRI_ERR, "Connection::setState: " "Invalid connection state change - isLocal %d, for call " "'%s' with callid '%s' from %s to %s, cause %d", isLocal, strCallName.data(), callId.data(), oldStateString.data(), newStateString.data(), newCause); } return; } } UtlBoolean bPostStateChange = FALSE; if (newState != currentState || newCause != CONNECTION_CAUSE_NORMAL || (newState == currentState && newState == CONNECTION_ALERTING && (0 == isLocal))) { if (isLocal && newState == CONNECTION_DISCONNECTED) { if (( mpCall->canDisconnectConnection(this) || newCause == CONNECTION_CAUSE_CANCELLED) && metaEventType != PtEvent::META_CALL_TRANSFERRING && metaEventType != PtEvent::META_CALL_REPLACING) { bPostStateChange = TRUE; } } else { bPostStateChange = TRUE; } } Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::setState " "Call %s %s state isLocal %d\n" "change\n" "from %s to\n" "\t %s\n" "cause=%d\n" "post change to upper layer %d", strCallName.data(), callId.data(), isLocal, oldStateString.data(), newStateString.data(), newCause, bPostStateChange); if (bPostStateChange) { mConnectionStateCause = newCause; mTerminalConnState = termState == -1 ? terminalConnectionState(newState) : termState; if (isLocal) { mLocalConnectionState = newState; } else { mRemoteConnectionState = newState; } postTaoListenerMessage(newState, newCause, isLocal); } }
// Returns an escaped version of the specified source string UtlString OsSysLog::escape(const UtlString& source) { UtlString results ; const char* pStart = source.data() ; const char* pTraverse = pStart ; const char* pLast = pStart ; while (*pTraverse) { switch (*pTraverse) { case '\\': // Copy old data if (pLast < pTraverse) { results.append(pLast, pTraverse-pLast); } pLast = pTraverse + 1 ; // Add escaped Text results.append("\\\\") ; break ; case '\r': // Copy old data if (pLast < pTraverse) { results.append(pLast, pTraverse-pLast); } pLast = pTraverse + 1 ; // Add escaped Text results.append("\\r") ; break ; case '\n': // Copy old data if (pLast < pTraverse) { results.append(pLast, pTraverse-pLast); } pLast = pTraverse + 1 ; // Add escaped Text results.append("\\n") ; break ; case '\"': // Copy old data if (pLast < pTraverse) { results.append(pLast, pTraverse-pLast); } pLast = pTraverse + 1 ; // Add escaped Text results.append("\\\"") ; break ; default: break ; } pTraverse++ ; } // if nothing to escape, short-circuit if (pLast == pStart) { return source ; } else if (pLast < pTraverse) { results.append(pLast, pTraverse-pLast); } return results ; }
// Construct mappings from an input string. UtlBoolean SipRedirectorMPT::addMappings(const char* value, int length, UtlString*& user, const char*& error_msg, int& location) { // Process the input string one character at a time. // Buffer into which to edit the input string. char buffer[FORM_SIZE]; // Pointer for filling the edit buffer. char* p = buffer; char c; int count = length; while (count-- > 0) { c = *value++; switch (c) { case '\n': // Trim trailing whitespace on the line. while (p > buffer && p[-1] != '\n' && isspace(p[-1])) { p--; } // Fall through to insert if not at the beginning of a line. case ' ': case '\t': // If at the beginning of a line, ignore it. if (p > buffer && p[-1] != '\n' && p[-1] != '{') { *p++ = c; } break; case '}': { // Process component redirection. // Trim trailing whitespace. while (p > buffer && isspace(p[-1])) { p--; } // Find the matching '{'. *p = '\0'; // End scope of strrchr. char* open = strrchr(buffer, '{'); if (open == NULL) { error_msg = "Unmatched '}'"; location = length - count; return FALSE; } if (open+1 == p) { error_msg = "No contacts given"; location = length - count; return FALSE; } // Insert the addresses into the map and get the assigned user name. UtlString* user = MPTredirector->addMapping(open+1, p - (open+1)); // Truncate off the sub-redirection. p = open; // Append the resulting user name. strcpy(p, user->data()); p += strlen(user->data()); } break; case '{': // '{' is copied into the buffer like other characters. default: // Ordinary characters are just copied. *p++ = c; break; } } // Trim trailing whitespace. while (p > buffer && isspace(p[-1])) { p--; } // Check that there are no unclosed '{'. *p = '\0'; // To limit strchr's search. if (strchr(buffer, '{') != NULL) { error_msg = "Unmatched '{'"; // Report at end of string because we have no better choice. location = length; return FALSE; } // Check that the contacts are not empty. if (p == buffer) { error_msg = "No contacts given"; location = 0; return FALSE; } // Insert the addresses into the map and return the assigned user name. user = MPTredirector->addMapping(buffer, p - buffer); return TRUE; }
// Unescapes previously escaped Quotes and CrLfs UtlString OsSysLog::unescape(const UtlString& source) { UtlString results ; const char* pStart = source.data() ; const char* pTraverse = pStart ; const char* pLast = pStart ; UtlBoolean bLastWasEscapeChar = false; while (*pTraverse) { if (bLastWasEscapeChar) { switch (*pTraverse) { case '\\': case '"': if (pLast < pTraverse) { results.append(pLast, pTraverse-pLast-1); } pLast = pTraverse + 1 ; results.append(*pTraverse) ; break ; case 'r': if (pLast < pTraverse) { results.append(pLast, pTraverse-pLast-1); } pLast = pTraverse + 1 ; results.append("\r") ; break ; case 'n': if (pLast < pTraverse) { results.append(pLast, pTraverse-pLast-1); } pLast = pTraverse + 1 ; results.append("\n") ; break; default: // Invalid/Illegal Escape Character break ; } bLastWasEscapeChar = false ; } else { if (*pTraverse == '\\') { bLastWasEscapeChar = true ; } } pTraverse++ ; } // if nothing to escape, short-circuit if (pLast == pStart) { return source ; } else if (pLast < pTraverse) { results.append(pLast, (pTraverse-1)-pLast); } return results ; }
void SipSubscribeServer::handleNotifyResponse(const SipMessage& notifyResponse) { int responseCode = notifyResponse.getResponseStatusCode(); // If it is a non-Timeout error response and has no Retry-After header, // terminate the subscription. if (responseCode >= SIP_3XX_CLASS_CODE) { UtlString dialogHandle; notifyResponse.getDialogHandleReverse(dialogHandle); if ( SIP_REQUEST_TIMEOUT_CODE == responseCode || SIP_LOOP_DETECTED_CODE == responseCode || SIP_SERVER_INTERNAL_ERROR_CODE == responseCode) { // Log the response. OsSysLog::add(FAC_SIP, PRI_WARNING, "SipSubscribeServer::handleNotifyResponse " "Not terminating subscription due to %d response. Handle: %s", responseCode, dialogHandle.data()); // RFC 3265 section 3.2.2 says that when a "NOTIFY request // fails ... due to a timeout condition ... the notifier // SHOULD remove the subscription." However, we feel this // is a problem with the spec. Endpoints that become // temporarily unavailable and do not respond to the NOTIFY // (or do not respond in time) should not cause the // subscription to be silently terminated. Our deviation // from the spec will cause subscriptions to now-defunct // subscribers to continue, but only until the subscription // expires. This is far preferable to the alternative. // Similarly, RFC 3265 prescribes that when the notifier // receives a 482 response, it should remove the // subscription. But that seems to be counterproductive in // practice, as a 482 response shows that the subscriber did // receive the NOTIFY. Unfortunately, under congested // circumstances, a notifier can receive a 482 response // rather than the more informative 2xx response. // Similar problems arise with the 500 response, which usually // indicates that a request was retried with a second transport. // But note that SipTransaction translates 503 into 500, // so 503 is also exempt. } else if (notifyResponse.getHeaderValue(0, SIP_RETRY_AFTER_FIELD) == NULL) { OsSysLog::add(FAC_SIP, PRI_WARNING, "SipSubscribeServer::handleNotifyResponse " "Terminating subscription due to %d response. Handle: %s", responseCode, dialogHandle.data()); // End this subscription because we got an error response from // the NOTIFY request. generateTerminatingNotify(dialogHandle); } else { // This was an error response, but because there was a Retry-After // header, we should not terminate the subscription. OsSysLog::add(FAC_SIP, PRI_WARNING, "SipSubscribeServer::handleNotifyResponse " "Not terminating subscription due to Retry-After header. Handle: %s", dialogHandle.data()); } } }
void testHandleAlarm() { OsSysLog::add(FAC_ALARM, PRI_DEBUG, "AlarmServerTest::testHandleAlarm"); UtlString localhost("localhost"); UtlString alarmId("NO_LOG"); UtlString alarmParam("testing"); UtlSList alarmParams; alarmParams.append(&alarmParam); UtlString oldLastString; tail(mAlarmFile, oldLastString); OsSysLog::add(FAC_ALARM, PRI_DEBUG, "oldLastString %s", oldLastString.data()); bool rc=cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams); OsTask::delay(500); CPPUNIT_ASSERT_MESSAGE("handleAlarm('NO_LOG') failed", rc==true); UtlString newLastString; tail(mAlarmFile, newLastString); OsSysLog::add(FAC_ALARM, PRI_DEBUG, "newLastString %s", newLastString.data()); CPPUNIT_ASSERT_MESSAGE("alarm with 'NO_LOG' was logged", !oldLastString.compareTo(newLastString)); alarmId = "TEST_LOG"; alarmParam = "single parameter"; alarmParams.removeAll(); alarmParams.append(&alarmParam); OsSysLog::add(FAC_ALARM, PRI_DEBUG, "Test TEST_LOG"); cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams); OsTask::delay(DELAY); UtlString actualString; UtlString expectedString = "This is a test of the log function. Single parameter should be here: single parameter, and that's all that is required"; tail(mAlarmFile, actualString); char msg[1000]; sprintf(msg, "incorrect message was logged: actualString '%s' expected '%s'", actualString.data(), expectedString.data()); CPPUNIT_ASSERT_MESSAGE(msg, actualString.contains(expectedString)); // test that non-existant alarm returns false alarmId = "NONEXISTANT_ID"; rc=cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams); CPPUNIT_ASSERT_MESSAGE("handleAlarm('NONEXISTANT_ID') did not fail, and should have", rc!=true); // test that alarm with min_threshold is only logged after n attempts alarmId = "MIN_THRESHOLD"; alarmParam = "one"; alarmParams.removeAll(); alarmParams.append(&alarmParam); tail(mAlarmFile, oldLastString); OsSysLog::add(FAC_ALARM, PRI_DEBUG, "oldLastString %s", oldLastString.data()); cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams); OsTask::delay(DELAY); tail(mAlarmFile, newLastString); OsSysLog::add(FAC_ALARM, PRI_DEBUG, "newLastString %s", newLastString.data()); CPPUNIT_ASSERT_MESSAGE("first instance of alarm with 'min_threshold' was logged", !oldLastString.compareTo(newLastString)); alarmParam = "two"; alarmParams.append(&alarmParam); cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams); OsTask::delay(DELAY); tail(mAlarmFile, actualString); expectedString = "This should only be logged the second time"; sprintf(msg, "incorrect message was logged: actualString '%s' expected '%s'", actualString.data(), expectedString.data()); CPPUNIT_ASSERT_MESSAGE(msg, actualString.contains(expectedString)); }
/// Terminate all subscriptions and accept no new ones. void SipSubscribeServer::shutdown(const char* reason) { // If reason is NULL, use the default reason established by the constructor. if (!reason) { reason = mDefaultTermination; } OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSubscribeServer::shutdown reason '%s'", reason ? reason : "[null]"); lockForRead(); // Select the subscriptionChange value to describe what we're doing // with the subscriptions. enum SipSubscriptionMgr::subscriptionChange change; // Select the correct format for generating the Subscription-State value. UtlString* formatp = NULL; // We may need a temp UtlString. const char* format; if (reason == NULL) { format = "active;expires=%ld"; change = SipSubscriptionMgr::subscriptionContinues; } else if (strcmp(reason, terminationReasonSilent) == 0) { // Do not admit that the subscription is ending. format = "active;expires=%ld"; change = SipSubscriptionMgr::subscriptionTerminatedSilently; } else if (strcmp(reason, terminationReasonNone) == 0) { format = "terminated"; change = SipSubscriptionMgr::subscriptionTerminated; } else { // Allocate a UtlString and assemble the Subscription-State format in it. formatp = new UtlString(); formatp->append("terminated;reason="); formatp->append(reason); format = formatp->data(); change = SipSubscriptionMgr::subscriptionTerminated; } // For each event type that is registered, delete all the subscriptions. UtlHashBagIterator event_itor(mEventDefinitions); SubscribeServerEventData* eventData; while ((eventData = dynamic_cast <SubscribeServerEventData*> (event_itor()))) { // Unregister interest in SUBSCRIBE requests and NOTIFY // responses for this event type, so we do not service new subscriptions. eventData->mpEventSpecificUserAgent->removeMessageObserver(*(getMessageQueue())); int numSubscriptions = 0; SipMessage** notifyArray = NULL; UtlString** acceptHeaderValuesArray = NULL; UtlString** resourceIdArray = NULL; UtlString** eventTypeKeyArray = NULL; // :TODO: The four situations where NOTIFYs are generated should // be factored into a series of methods in // mpEventSpecificSubscriptionMgr that generate NOTIFYs // sequentially, and for each NOTIFY, call a common service // method that does the remaining operations and sends the // NOTIFY. // Construct a NOTIFY (without body) for every subscription, containing // the dialog-related information about each subscription. eventData->mpEventSpecificSubscriptionMgr-> createNotifiesDialogInfoEvent(static_cast <const UtlString&> (*eventData), format, numSubscriptions, acceptHeaderValuesArray, notifyArray, resourceIdArray, eventTypeKeyArray); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSubscribeServer::shutdown eventType = '%s', numSubscriptions = %d", eventData->data(), numSubscriptions); // For each NOTIFY, add the subscription-related information and then // send it. for (int notifyIndex = 0; notifyIndex < numSubscriptions; notifyIndex++) { SipMessage* notify = notifyArray[notifyIndex]; // Check to see if the dialog information could be added. // (The subscription might have been destroyed between when // it was decided to respond to it, and when the dialog information // was retrieved.) UtlString callId; notify->getCallIdField(&callId); if (!callId.isNull()) { if (change != SipSubscriptionMgr::subscriptionTerminatedSilently) { // Fill in the NOTIFY request body/content eventData->mpEventSpecificHandler-> getNotifyContent(*(resourceIdArray[notifyIndex]), *(eventTypeKeyArray[notifyIndex]), *eventData, *(eventData->mpEventSpecificContentMgr), *(acceptHeaderValuesArray[notifyIndex]), *notify, eventData->mEventSpecificFullState, NULL); // Call the application callback to edit the NOTIFY // content if that is required for this event type. // Also gets 'version' (if relevant) and 'savedEventTypeKey'. int version; UtlString savedEventTypeKey; eventData->mpEventSpecificSubscriptionMgr-> updateNotifyVersion(eventData->mpEventSpecificContentVersionCallback, *notify, version, savedEventTypeKey); // Set the Contact header. setContact(notify); // Send the NOTIFY request. eventData->mpEventSpecificUserAgent->send(*notify); } // Remove the record of the subscription. UtlString dialogHandle; notify->getDialogHandle(dialogHandle); eventData->mpEventSpecificSubscriptionMgr-> endSubscription(dialogHandle, change); } } // Free the NOTIFY requests and accept header field values. SipSubscriptionMgr::freeNotifies(numSubscriptions, acceptHeaderValuesArray, notifyArray); // Free the resource and event type arrays. for (int index = 0; index < numSubscriptions; index++) { delete resourceIdArray[index]; delete eventTypeKeyArray[index]; } delete[] resourceIdArray; delete[] eventTypeKeyArray; // Remove eventData from mEventDefinitions. mEventDefinitions.removeReference(eventData); delete eventData; } unlockForRead(); // Free the temporary UtlString, if necessary. if (formatp) { delete formatp; } lockForWrite(); mEventDefinitions.destroyAll(); unlockForWrite(); }
void testReconfigure() { PluginHooks testPlugins("getTestPlugin", "RECONFIG_TEST"); const UtlString ValueKey("VALUE"); UtlString name; TestPlugin* thePlugin; UtlString pluginValue; UtlString fullName; { // Do the initial configuration of two instances of a hook OsConfigDb configuration; configuration.set("RECONFIG_TEST_HOOK_LIBRARY.First", PLUGIN_LIB_DIR "libtestpluginA" PLUGIN_EXT); configuration.set("RECONFIG_TEST.First.VALUE", "FirstValue"); configuration.set("RECONFIG_TEST_HOOK_LIBRARY.Second", PLUGIN_LIB_DIR "libtestpluginA" PLUGIN_EXT); configuration.set("RECONFIG_TEST.Second.VALUE", "SecondValue"); // load them up testPlugins.readConfig(configuration); PluginIterator plugin(testPlugins); // check the first instance thePlugin = static_cast<TestPlugin*>(plugin.next(&name)); CPPUNIT_ASSERT(thePlugin != NULL); CPPUNIT_ASSERT(!name.isNull()); ASSERT_STR_EQUAL("First",name.data()); thePlugin->pluginName(fullName); ASSERT_STR_EQUAL("TestPluginA::First",fullName.data()); CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue)); ASSERT_STR_EQUAL("FirstValue",pluginValue.data()); // check the second instance thePlugin = static_cast<TestPlugin*>(plugin.next(&name)); CPPUNIT_ASSERT(thePlugin != NULL); CPPUNIT_ASSERT(!name.isNull()); ASSERT_STR_EQUAL("Second",name.data()); thePlugin->pluginName(fullName); ASSERT_STR_EQUAL("TestPluginA::Second",fullName.data()); CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue)); ASSERT_STR_EQUAL("SecondValue",pluginValue.data()); // and confirm that is the end CPPUNIT_ASSERT(plugin.next(&name) == NULL); CPPUNIT_ASSERT(name.isNull()); } { // Now create a new configuration that eliminates the First instance // and changes the configuration value for the Second instance OsConfigDb configuration; configuration.set("RECONFIG_TEST_HOOK_LIBRARY.Second", PLUGIN_LIB_DIR "libtestpluginA" PLUGIN_EXT); configuration.set("RECONFIG_TEST.Second.VALUE", "NewValue"); // reconfigure the plugins testPlugins.readConfig(configuration); PluginIterator plugin(testPlugins); // confirm that we still get the Second instance (but we get it first :-) thePlugin = static_cast<TestPlugin*>(plugin.next(&name)); CPPUNIT_ASSERT(thePlugin != NULL); CPPUNIT_ASSERT(!name.isNull()); ASSERT_STR_EQUAL("Second",name.data()); thePlugin->pluginName(fullName); ASSERT_STR_EQUAL("TestPluginA::Second",fullName.data()); // and check that it has the new configuration value CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue)); ASSERT_STR_EQUAL("NewValue",pluginValue.data()); // and that it's the only hook configured now CPPUNIT_ASSERT(plugin.next(&name) == NULL); CPPUNIT_ASSERT(name.isNull()); } { // Now create a third configuration that changes the library for the Second instance OsConfigDb configuration; configuration.set("RECONFIG_TEST_HOOK_LIBRARY.Second", PLUGIN_LIB_DIR "libtestpluginB" PLUGIN_EXT); configuration.set("RECONFIG_TEST.Second.VALUE", "ChangedValue"); // reconfigure the plugins testPlugins.readConfig(configuration); PluginIterator plugin(testPlugins); // confirm that we still get the Second instance (but we get it first :-) thePlugin = static_cast<TestPlugin*>(plugin.next(&name)); CPPUNIT_ASSERT(thePlugin != NULL); CPPUNIT_ASSERT(!name.isNull()); ASSERT_STR_EQUAL("Second",name.data()); thePlugin->pluginName(fullName); ASSERT_STR_EQUAL("TestPluginB::Second",fullName.data()); // and check that it has the new configuration value CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue)); ASSERT_STR_EQUAL("ChangedValue",pluginValue.data()); // and that it's the only hook configured now CPPUNIT_ASSERT(plugin.next(&name) == NULL); CPPUNIT_ASSERT(name.isNull()); } }
// Send a NOTIFY to all subscribers to the given resourceId and eventTypeKey. UtlBoolean SipSubscribeServer::notifySubscribers(const char* resourceId, const char* eventTypeKey, const char* eventType, const char* reason) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSubscribeServer::notifySubscribers resourceId '%s', eventTypeKey '%s', eventType '%s', reason '%s'", resourceId, eventTypeKey, eventType, reason ? reason : "[null]"); UtlBoolean notifiedSubscribers = FALSE; UtlString eventName(eventType); lockForRead(); SubscribeServerEventData* eventData = dynamic_cast <SubscribeServerEventData*> (mEventDefinitions.find(&eventName)); // Get the event-specific info to find subscriptions interested in // this content. if (eventData) { int numSubscriptions = 0; SipMessage** notifyArray = NULL; UtlString** acceptHeaderValuesArray = NULL; // Select the subscriptionChange value to describe what we're doing // with the subscriptions. enum SipSubscriptionMgr::subscriptionChange change; { // Select the correct format for generating the Subscription-State value. UtlString* formatp = NULL; // We may need a temp UtlString. const char* format; if (reason == NULL) { format = "active;expires=%ld"; change = SipSubscriptionMgr::subscriptionContinues; } else if (strcmp(reason, terminationReasonSilent) == 0) { // Do not admit that the subscription is ending. format = "active;expires=%ld"; change = SipSubscriptionMgr::subscriptionTerminatedSilently; } else if (strcmp(reason, terminationReasonNone) == 0) { format = "terminated"; change = SipSubscriptionMgr::subscriptionTerminated; } else { // Allocate a UtlString and assemble the Subscription-State format in it. formatp = new UtlString(); formatp->append("terminated;reason="); formatp->append(reason); format = formatp->data(); change = SipSubscriptionMgr::subscriptionTerminated; } // Construct a NOTIFY (without body) for each subscription, containing // the dialog-related information about each subscription. eventData->mpEventSpecificSubscriptionMgr-> createNotifiesDialogInfo(resourceId, eventTypeKey, format, numSubscriptions, acceptHeaderValuesArray, notifyArray); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSubscribeServer::notifySubscribers numSubscriptions for '%s' = %d", resourceId, numSubscriptions); // Free the temporary UtlString, if necessary. if (formatp) { delete formatp; } } // For each NOTIFY, add the subscription-related information and then // send it. for (int notifyIndex = 0; notifyIndex < numSubscriptions; notifyIndex++) { SipMessage* notify = notifyArray[notifyIndex]; // Check to see if the dialog information could be added. // (The subscription might have been destroyed between when // it was decided to respond to it, and when the dialog information // was retrieved.) UtlString callId; notify->getCallIdField(&callId); if (!callId.isNull()) { if (change != SipSubscriptionMgr::subscriptionTerminatedSilently) { // Fill in the NOTIFY request body/content eventData->mpEventSpecificHandler-> getNotifyContent(resourceId, eventTypeKey, eventType, *(eventData->mpEventSpecificContentMgr), *(acceptHeaderValuesArray[notifyIndex]), *notify, eventData->mEventSpecificFullState, NULL); // Call the application callback to edit the NOTIFY // content if that is required for this event type. // Also gets 'version' (if relevant) and 'savedEventTypeKey'. int version; UtlString savedEventTypeKey; eventData->mpEventSpecificSubscriptionMgr-> updateNotifyVersion(eventData->mpEventSpecificContentVersionCallback, *notify, version, savedEventTypeKey); // Update the saved record of the NOTIFY CSeq and the // XML version number for the specified savedEventTypeKey, // 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. eventData->mpEventSpecificSubscriptionMgr-> updateVersion(*notify, version, savedEventTypeKey); // Set the Contact header. setContact(notify); // Send the NOTIFY request. eventData->mpEventSpecificUserAgent->send(*notify); } if (change != SipSubscriptionMgr::subscriptionContinues) { // Remove the record of the subscription. UtlString dialogHandle; notify->getDialogHandle(dialogHandle); eventData->mpEventSpecificSubscriptionMgr-> endSubscription(dialogHandle, change); } } } // Free the NOTIFY requests and accept header field values. eventData->mpEventSpecificSubscriptionMgr-> freeNotifies(numSubscriptions, acceptHeaderValuesArray, notifyArray); } // event type not enabled else { OsSysLog::add(FAC_SIP, PRI_ERR, "SipSubscribeServer::notifySubscribers " "event type: %s not enabled - " "Why are we seeing a callback for this?", eventName.data()); } unlockForRead(); return notifiedSubscribers; }
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; }
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); }
bool cAlarmServer::loadAlarms() { // load global alarm config from alarm-config.xml UtlString strAlarmFilename = SipXecsService::Path(SipXecsService::ConfigurationDirType, "alarm-config.xml"); UtlString strGroupFilename = SipXecsService::Path(SipXecsService::ConfigurationDirType, "alarm-groups.xml"); loadAlarmConfig(strAlarmFilename, strGroupFilename); // load specific alarm definitions from ${confdir}/alarms/*.xml UtlString alarmDefDir = SipXecsService::Path(SipXecsService::ConfigurationDirType); alarmDefDir.append("/alarms/"); OsSysLog::add(FAC_ALARM, PRI_INFO, "Looking for alarm def files in '%s'", alarmDefDir.data()); OsFileIterator files(alarmDefDir); OsPath entry; // for each file in the ${confdir}/alarms, load alarm definitions OsStatus status; int numFound; for (status=files.findFirst(entry, ".*\\.xml$", OsFileIterator::FILES), numFound=0; status == OS_SUCCESS; status = files.findNext(entry) ) { loadAlarmDefinitions(alarmDefDir + entry); } // load alarm strings and local language version from ${datadir}/alarms/*.xml UtlString alarmStringsDir = SipXecsService::Path(SipXecsService::DataDirType); alarmStringsDir.append("/alarms/"); OsSysLog::add(FAC_ALARM, PRI_INFO, "Looking for alarm string files in '%s'", alarmStringsDir.data()); OsFileIterator stringFiles(alarmStringsDir); // for each "base" file (*-strings.xml) in the ${datadir}/alarms, load alarm strings for (status=stringFiles.findFirst(entry, ".*-strings\\.xml$", OsFileIterator::FILES), numFound=0; status == OS_SUCCESS; status = stringFiles.findNext(entry) ) { loadAlarmStrings(alarmStringsDir + entry); } #ifdef DEBUG UtlHashMapIterator alarmIter(mAlarmMap); UtlString* alarmKey; int count=0; while ((alarmKey = dynamic_cast<UtlString*>(alarmIter()))) { cAlarmData* alarm = dynamic_cast<cAlarmData*>(alarmIter.value()); OsSysLog::add(FAC_ALARM, PRI_DEBUG, "alarm[%d]: %s %s: %s, Log:%d, Email:%d", count, alarmKey->data(), alarm->getCode().data(), OsSysLog::priorityName(alarm->getSeverity()), alarm->actions[cAlarmData::eActionLog], alarm->actions[cAlarmData::eActionEmail]); OsSysLog::add(FAC_ALARM, PRI_DEBUG, " Title:%s", alarm->getShortTitle().data()); OsSysLog::add(FAC_ALARM, PRI_DEBUG, " Description:%s", alarm->getDescription().data()); OsSysLog::add(FAC_ALARM, PRI_DEBUG, " Resolution:%s", alarm->getResolution().data()); count++; } #endif return true; }
int SipLSendCommand::execute(int argc, char* argv[]) { int commandStatus = CommandProcessor::COMMAND_FAILED; UtlString messageBuffer; char buffer[1025]; int bufferSize = 1024; int charsRead; printf("send command with %d arguments\n", argc); if(argc != 5) { UtlString usage; getUsage(argv[0], &usage); printf("%s", usage.data()); } else { UtlString protocol(argv[2]); protocol.toUpper(); UtlString hostAddress(argv[3]); int hostPort = atoi(argv[4]); FILE* sipMessageFile = fopen(argv[1], "r"); if(sipMessageFile && hostPort > 0 && !hostAddress.isNull() && (protocol.compareTo("TCP") == 0 || protocol.compareTo("UDP") == 0)) { //printf("opened file: \"%s\"\n", argv[1]); do { charsRead = fread(buffer, 1, bufferSize, sipMessageFile); if(charsRead > 0) { messageBuffer.append(buffer, charsRead); } } while(charsRead); fclose(sipMessageFile); OsSocket* writeSocket = NULL; if(protocol.compareTo("TCP") == 0) writeSocket = new OsConnectionSocket(hostPort ,hostAddress); else if(protocol.compareTo("UDP") == 0) writeSocket = new OsDatagramSocket(hostPort ,hostAddress); //printf("Read file contents:\n%s\n====END====\n", messageBuffer.data()); //SipMessage message(messageBuffer.data()); int bytesSent; if((bytesSent = writeSocket->write(messageBuffer.data(), messageBuffer.length())) > 0) { commandStatus = CommandProcessor::COMMAND_SUCCESS; } else { printf("Failed to send SIP message"); } printf("Send message with %d bytes\n", bytesSent); } else if(!sipMessageFile) { printf("send file: \"%s\" does not exist\n", argv[1]); commandStatus = CommandProcessor::COMMAND_FAILED; } else if(hostPort <= 0) { printf("Invalid destination port: %s\n", argv[4]); commandStatus = CommandProcessor::COMMAND_FAILED; } else if(hostAddress.isNull()) { printf("Invalid destination address: %s\n", argv[3]); commandStatus = CommandProcessor::COMMAND_FAILED; } else if(protocol.compareTo("TCP") && protocol.compareTo("UDP")) { printf("Invalid protocol: %s\n", argv[2]); commandStatus = CommandProcessor::COMMAND_FAILED; } } return(commandStatus); }
bool SipDialogMonitor::addExtension(UtlString& groupName, Url& contactUrl) { bool result = false; mLock.acquire(); // Check whether the group already exists. If not, create one. SipResourceList* list = dynamic_cast <SipResourceList *> (mMonitoredLists.findValue(&groupName)); if (list == NULL) { UtlString* listName = new UtlString(groupName); list = new SipResourceList((UtlBoolean)TRUE, listName->data(), DIALOG_EVENT_TYPE); mMonitoredLists.insertKeyAndValue(listName, list); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::addExtension insert listName %s and object %p to the resource list", groupName.data(), list); } // Check whether the contact has already been added to the group. UtlString resourceId; contactUrl.getIdentity(resourceId); Resource* resource = list->getResource(resourceId); if (resource == NULL) { // If not, add it. resource = new Resource(resourceId); UtlString userName; contactUrl.getDisplayName(userName); resource->setName(userName); UtlString id; NetMd5Codec::encode(resourceId, id); resource->setInstance(id, STATE_PENDING); list->insertResource(resource); // Set up the subscription to the URI. OsSysLog::add(FAC_LOG, PRI_DEBUG, "SipDialogMonitor::addExtension Sending out the SUBSCRIBE to contact %s", resourceId.data()); UtlString toUrl; contactUrl.toString(toUrl); UtlString fromUri = "dialogMonitor@" + mDomainName; UtlString earlyDialogHandle; UtlBoolean status = mpSipSubscribeClient->addSubscription(resourceId.data(), DIALOG_EVENT_TYPE, DIALOG_EVENT_CONTENT_TYPE, fromUri.data(), toUrl.data(), mContact.data(), mRefreshTimeout, (void *) this, SipDialogMonitor::subscriptionStateCallback, SipDialogMonitor::notifyEventCallback, earlyDialogHandle); if (!status) { result = false; OsSysLog::add(FAC_LOG, PRI_ERR, "SipDialogMonitor::addExtension Subscription failed to contact %s.", resourceId.data()); } else { mDialogHandleList.insertKeyAndValue(new UtlString(resourceId), new UtlString(earlyDialogHandle)); createDialogState(&earlyDialogHandle); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::addExtension Added earlyDialogHandle: %s", earlyDialogHandle.data()); result = true; } } else { OsSysLog::add(FAC_LOG, PRI_WARNING, "SipDialogMonitor::addExtension contact %s already exists.", resourceId.data()); } list->buildBody(); mLock.release(); return result; }
// Add a log entry given a variable argument list OsStatus OsSysLog::vadd(const char* taskName, const OsTaskId_t taskId, const OsSysLogFacility facility, const OsSysLogPriority priority, const char* format, va_list ap) { // If the log has not been initialized, print everything to the console if (!isTaskPtrNull()) { if (willLog(facility, priority)) { UtlString logData; UtlString logEntry; myvsprintf(logData, format, ap) ; logData = escape(logData) ; #ifdef ANDROID __android_log_print(androidPri(priority), "sipXsyslog", "[%s] %s", OsSysLog::sFacilityNames[facility], logData.data()); #endif OsTime timeNow; OsDateTime::getCurTime(timeNow); OsDateTime logTime(timeNow); UtlString strTime ; logTime.getIsoTimeStringZus(strTime) ; UtlString taskHex; // TODO: Should get abstracted into a OsTaskBase method #ifdef __pingtel_on_posix__ OsTaskLinux::getIdString_X(taskHex, taskId); #endif mysprintf(logEntry, "\"%s\":%d:%s:%s:%s:%s:%s:%s:\"%s\"", strTime.data(), ++sEventCount, OsSysLog::sFacilityNames[facility], OsSysLog::sPriorityNames[priority], sHostname.data(), (taskName == NULL) ? "" : taskName, taskHex.data(), sProcessId.data(), logData.data()) ; // If the logger for some reason trys to log a message // there is a recursive problem. Drop the message on the // floor for now. This can occur if one of the os utilities // logs a message. if(strcmp("syslog", taskName) == 0) { // Just discard the log entry // // (rschaaf): // NOTE: Don't try to use osPrintf() to emit the log entry since this // can cause consternation for applications (e.g. CGIs) that expect to // use stdout for further processing. } else { char* szPtr = strdup(logEntry.data()) ; OsSysLogMsg msg(OsSysLogMsg::LOG, szPtr) ; OsTime timeout(1000) ; OsSysLogTask *pOsSysLogTask = spOsSysLogTask; if ( pOsSysLogTask != NULL && pOsSysLogTask->postMessage(msg, timeout) != OS_SUCCESS) { printf("OsSysLog jammed: %s\n", szPtr) ; free(szPtr) ; OsTask::yield() ; } } } } return OS_SUCCESS ; }
StateChangeNotifier::Status SipDialogMonitor::mergeEventInformation(SipDialogEvent* dialogEvent, const char* earlyDialogHandle, const char* dialogHandle) { // Status to be returned to caller. StateChangeNotifier::Status rc; OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::mergeEventInformation " "earlyDialogHandle = '%s', dialogHandle = '%s'", earlyDialogHandle, dialogHandle); // Get the list of active dialogs for the group of subscriptions generated // by this SUBSCRIBE. UtlString earlyDialogHandleString(earlyDialogHandle); UtlHashBag* active_dialog_list = dynamic_cast <UtlHashBag*> (mDialogState.findValue(&earlyDialogHandleString)); // Ignore the event if there is no entry in mDialogState -- this is a // NOTIFY that arrived after and un-SUBSCRIBE terminated its subscription. if (active_dialog_list) { // If this is a full update, remove from the active list any dialog // for this dialog handle. UtlString notify_state; dialogEvent->getState(notify_state); if (notify_state.compareTo("full") == 0) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::mergeEventInformation " "active_dialog_list elements for handle '%s'", dialogHandle); // Iterate through the active dialog list, removing elements // for this dialog handle. UtlHashBagIterator dialog_id_itor(*active_dialog_list); UtlString* dialog_id; while ((dialog_id = dynamic_cast <UtlString*> (dialog_id_itor()))) { // Extract the dialog handle part of the dialog identifier string // and compare it to the dialog handle of this event notice. if (strcmp(dialogHandle, dialog_id->data() + dialog_id->index("\001") + 1) == 0) { // This is a dialog for this subscription, so remove it. active_dialog_list->remove(dialog_id); } } } // Iterate through the dialog event, updating active_dialog_list for // each dialog mentioned. UtlSListIterator* dialog_itor = dialogEvent->getDialogIterator(); Dialog* dialog; UtlString state, event, code, dialogId; while ((dialog = dynamic_cast <Dialog*> ((*dialog_itor)()))) { // Construct the dialog identifier string, // <dialog id><ctrl-A><dialog handle> dialog->getDialogId(dialogId); dialogId.append("\001"); dialogId.append(dialogHandle); dialog->getState(state, event, code); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::mergeEventInformation " "dialogId '%s' state '%s' event '%s' code '%s'", dialogId.data(), state.data(), event.data(), code.data()); if (state.compareTo("terminated") != 0) { // Active dialog. // If it is not in active_dialog_list, add it. if (!active_dialog_list->contains(&dialogId)) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::mergeEventInformation " "adding dialog '%s'", dialogId.data()); active_dialog_list->insert(new UtlString(dialogId)); } } else { // Terminated dialog // If it is in active_dialog_list, remove it. OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::mergeEventInformation " "removing dialog '%s'", dialogId.data()); active_dialog_list->destroy(&dialogId); } } delete dialog_itor; // If debugging, list the active dialog list. if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG)) { UtlHashBagIterator dialog_list_itor(*active_dialog_list); UtlString* dialog; while ((dialog = dynamic_cast <UtlString*> (dialog_list_itor()))) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::mergeEventInformation " "active dialog '%s'", dialog->data()); } OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::mergeEventInformation " "End of list"); } // Set the return code based on whether there are any active dialogs. rc = active_dialog_list->isEmpty() ? StateChangeNotifier::ON_HOOK : StateChangeNotifier::OFF_HOOK; } else { // This is a late NOTIFY and there are (should be) no notifiers for it, // so the return code is arbitrary. OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::mergeEventInformation " "No active dialog list found"); rc = StateChangeNotifier::ON_HOOK; } return rc; }
UtlBoolean SipTransactionList::waitUntilAvailable(SipTransaction* transaction, const UtlString& hash) { UtlBoolean exists; UtlBoolean busy = FALSE; int numTries = 0; do { numTries++; lock(); exists = transactionExists(transaction, hash); if(exists) { busy = transaction->isBusy(); if(!busy) { transaction->markBusy(); unlock(); //#ifdef TEST_PRINT OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::waitUntilAvailable %p locked after %d tries\n", transaction, numTries); //#endif } else { // We set an event to be signaled when a // transaction is released. OsEvent* waitEvent = new OsEvent; transaction->notifyWhenAvailable(waitEvent); // Must unlock while we wait or there is a dead lock unlock(); //#ifdef TEST_PRINT OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::waitUntilAvailable %p waiting on: %p after %d tries\n", transaction, waitEvent, numTries); //#endif OsStatus waitStatus; OsTime transBusyTimeout(1, 0); int waitTime = 0; do { if(waitTime > 0) OsSysLog::add(FAC_SIP, PRI_WARNING, "SipTransactionList::waitUntilAvailable %p still waiting: %d", transaction, waitTime); waitStatus = waitEvent->wait(transBusyTimeout); waitTime+=1; } while(waitStatus != OS_SUCCESS && waitTime < 30); // If we were never signaled, then we signal the // event so the other side knows that it has to // free up the event if(waitEvent->signal(-1) == OS_ALREADY_SIGNALED) { delete waitEvent; waitEvent = NULL; } // If we bailed out before the event was signaled // pretend the transaction does not exist. if(waitStatus != OS_SUCCESS) { exists = FALSE; } if(waitTime > 1) { if (OsSysLog::willLog(FAC_SIP, PRI_WARNING)) { UtlString transTree; UtlString waitingTaskName; OsTask* waitingTask = OsTask::getCurrentTask(); if(waitingTask) waitingTaskName = waitingTask->getName(); transaction->dumpTransactionTree(transTree, FALSE); OsSysLog::add(FAC_SIP, PRI_WARNING, "SipTransactionList::waitUntilAvailable status: %d wait time: %d transaction: %p task: %s transaction tree: %s", waitStatus, waitTime, transaction, waitingTaskName.data(), transTree.data()); } } //#ifdef TEST_PRINT OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::waitUntilAvailable %p done waiting after %d tries\n", transaction, numTries); //#endif } } else { unlock(); //#ifdef TEST_PRINT OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::waitUntilAvailable %p gone after %d tries\n", transaction, numTries); //#endif } } while(exists && busy); return(exists && !busy); }