void testSendInput() { OsStatus stat; OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "testSendInput"); // this command will produce a mix of stdout and stderr UtlString appName = "sh"; UtlString params[10]; params[0] = "-c"; params[1] = "cat"; params[2] = NULL; OsProcess process; OsPath startupDir = "."; // std::cout << "Launching process: " << appName.data() << std::endl; OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "launching process %s %s", appName.data(), params[0].data()); stat = process.launch(appName, params, startupDir, OsProcessBase::NormalPriorityClass, false, false/* don't ignore child signals*/); CPPUNIT_ASSERT(stat == OS_SUCCESS); CPPUNIT_ASSERT(process.isRunning()); UtlString stdoutMsg, stderrMsg; int rc; // send "well", then "hello", and expect "goodbye" back bool bGotGoodbye = false; OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "starting sendInput task"); SimpleTask * pTask = new SimpleTask(&process); pTask->start(); OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "calling getOutput"); while ( !bGotGoodbye && pTask->isStarted() && (rc = process.getOutput(&stdoutMsg, &stderrMsg)) > 0 ) { if ( stdoutMsg.length() > 0 ) { // The output is sure to contain newlines, and may contain several lines. // Clean it up before dispatching. UtlTokenizer tokenizer(stdoutMsg); UtlString msg; while ( tokenizer.next(msg, "\r\n") ) { OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "got stdout: %s", msg.data()); if ( msg == "goodbye" ) { OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "got goodbye command"); bGotGoodbye = true; } } } if ( stderrMsg.length() > 0 ) { OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "got stderr: %s", stderrMsg.data()); } } CPPUNIT_ASSERT(bGotGoodbye==true); pTask->requestShutdown(); delete pTask; }
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); ssize_t serverEndIndex = uri.index("/"); if(serverEndIndex < 0) serverEndIndex = uri.length(); if(serverEndIndex > 0) { UtlString server = uri; server.remove(serverEndIndex); ssize_t 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; ssize_t responseLength; getResponse.getBytes(&responseBytes, &responseLength); printf("Got %zu 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); }
bool SwAdminRpcMethod::buildOutputFiles(const UtlString& command, UtlString& stdoutfn, UtlString& stderrfn ) { bool result = true; stdoutfn.remove(0); stderrfn.remove(0); if ( command.compareTo(SwAdminVersion_cmd, UtlString::ignoreCase) == 0) { stdoutfn.append(SwAdminVersion_cmd); stderrfn.append(SwAdminVersion_cmd); } else if ( command.compareTo(SwAdminCheckUpdate_cmd, UtlString::ignoreCase) == 0) { stdoutfn.append(SwAdminCheckUpdate_cmd); stderrfn.append(SwAdminCheckUpdate_cmd); } else if ( command.compareTo(SwAdminUpdate_cmd, UtlString::ignoreCase) == 0) { stdoutfn.append(SwAdminUpdate_cmd); stderrfn.append(SwAdminUpdate_cmd); } else if ( command.compareTo(SwAdminRestart_cmd, UtlString::ignoreCase) == 0) { stdoutfn.append(SwAdminRestart_cmd); stderrfn.append(SwAdminRestart_cmd); } else if ( command.compareTo(SwAdminReboot_cmd, UtlString::ignoreCase) == 0) { stdoutfn.append(SwAdminReboot_cmd); stderrfn.append(SwAdminReboot_cmd); } else { return false; } stderrfn.append(SwAdminStdErr_filetype); stdoutfn.append(SwAdminStdOut_filetype); return result; }
// Construct mappings from an input string. UtlBoolean SipRedirectorGateway::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 = 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 = addMapping(buffer, p - buffer); return TRUE; }
virtual bool execute(const HttpRequestContext& requestContext, ///< request context UtlSList& params, ///< request param list void* userData, ///< user data XmlRpcResponse& response, ///< request response ExecutionStatus& status ) { UtlString* dbName = dynamic_cast<UtlString*>(params.at(0)); if (dbName && !dbName->isNull()) { OsReadLock lock(*ConfigRPC::spDatabaseLock); ConfigRPC* db = ConfigRPC::find(*dbName); if (db) { status = db->mCallback->accessAllowed(requestContext, ConfigRPC_Callback::Set); if ( XmlRpcMethod::OK == status ) { // read in the dataset OsConfigDb dataset; OsStatus datasetStatus = db->load(dataset); if ( OS_SUCCESS == datasetStatus ) { // get the list of names that the request is asking for UtlContainable* secondParam = params.at(1); if ( secondParam ) { UtlHashMap* paramList = dynamic_cast<UtlHashMap*>(secondParam); if (paramList) { /* * Iterate over the requested name/value pairs */ UtlHashMapIterator params(*paramList); UtlContainable* nextParam = NULL; size_t paramsSet = 0; while ( XmlRpcMethod::OK == status && (nextParam = params()) ) { UtlString* name = dynamic_cast<UtlString*>(params.key()); if ( name ) { UtlString* value = dynamic_cast<UtlString*>(params.value()); if (value) { dataset.set(*name, *value); paramsSet++; } else { UtlString faultMsg; faultMsg.append("parameter name '"); faultMsg.append(*name); faultMsg.append("' value is not a string"); response.setFault(ConfigRPC::invalidType, faultMsg.data()); status = XmlRpcMethod::FAILED; } } else { UtlString faultMsg; faultMsg.append("parameter number "); char paramIndex[10]; sprintf(paramIndex,"%zu", paramsSet + 1); faultMsg.append(paramIndex); faultMsg.append(" name is not a string"); response.setFault(ConfigRPC::invalidType, faultMsg.data()); status = XmlRpcMethod::FAILED; } } if ( XmlRpcMethod::OK == status ) { if (OS_SUCCESS == db->store(dataset)) { UtlInt numberSet(paramList->entries()); response.setResponse(&numberSet); } else { response.setFault( ConfigRPC::storeFailed ,"error storing dataset" ); status = XmlRpcMethod::FAILED; } } } else { // The second parameter was not a list response.setFault( ConfigRPC::invalidType ,"second parameter is not a struct" ); status = XmlRpcMethod::FAILED; } } else // no parameter names specified { // No second parameter response.setFault( ConfigRPC::invalidType ,"no second parameter of name/value pairs" ); status = XmlRpcMethod::FAILED; } } else { UtlString faultMsg("dataset load failed"); response.setFault(ConfigRPC::loadFailed, faultMsg); status = XmlRpcMethod::FAILED; } } else { UtlString faultMsg("Access Denied"); response.setFault(XmlRpcMethod::FAILED, faultMsg.data()); } } else { UtlString faultMsg; faultMsg.append("db lookup failed for '"); faultMsg.append(*dbName); faultMsg.append("'"); response.setFault( XmlRpcResponse::UnregisteredMethod, faultMsg.data()); status = XmlRpcMethod::FAILED; } } else { response.setFault( XmlRpcResponse::EmptyParameterValue ,"'dbname' parameter is missing or invalid type" ); status = XmlRpcMethod::FAILED; } return true; }
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 deadlock 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); }
void SipRedirectorGateway::processForm(const HttpRequestContext& requestContext, const HttpMessage& request, HttpMessage*& response) { UtlString string_get("get"); UtlString string_set("set"); UtlString string_prefix("prefix"); UtlString string_destination("destination"); Os::Logger::instance().log(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(); Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm A *** request body is '%s'", mLogName.data(), request_body->getBytes()); // Get the values from the form. if (request_body->isMultipart()) { // Extract the values from the form data. UtlHashMap values; int c = request_body->getMultipartCount(); for (int i = 0; i < c; i++) { UtlString* name = new UtlString; if (request_body->getMultipart(i)->getPartHeaderValue("name", *name)) { const char* v; int l; request_body->getMultipartBytes(i, &v, &l); // Strip leading and trailing whitespace from values. UtlString* value = new UtlString(v, l); value->strip(UtlString::both); Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "%s::processForm " "form value '%s' = '%s'", mLogName.data(), name->data(), value->data()); // 'name' and 'value' are now owned by 'values'. values.insertKeyAndValue(name, value); } else { // 'name' is not owned by 'values' and we have to delete it. delete name; } } if (values.findValue(&string_get)) { // This is a "get gateway" request. // Insert the HTML into the response. HttpBody* response_body = new HttpBody(form, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); } else if (values.findValue(&string_set)) { // This is a "set gateway" request. // Validate the routing prefix. UtlString* prefix = dynamic_cast <UtlString*> (values.findValue(&string_prefix)); if (prefixIsValid(*prefix)) { // Validate the destination. UtlString* destination = dynamic_cast <UtlString*> (values.findValue(&string_destination)); if (destination_is_valid(destination)) { Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "%s::processForm " "add mapping '%s' -> '%s'", mLogName.data(), prefix->data(), destination->data()); mMapLock.acquire(); // Insert the mapping. mMapUserToContacts.insertKeyAndValue(prefix, destination); mMapContactsToUser.insertKeyAndValue(destination, prefix); mMapLock.release(); writeMappings(); } } // Insert the HTML into the response. HttpBody* response_body = new HttpBody(form, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); } else { // Incomprehensible request. // Insert the HTML into the response. HttpBody* response_body = new HttpBody(form, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); } } else { // Incomprehensible request. // Insert the default HTML into the response. HttpBody* response_body = new HttpBody(form, -1, CONTENT_TYPE_TEXT_HTML); response->setBody(response_body); } #if 0 #if 0 // 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 Os::Logger::instance().log(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; } Os::Logger::instance().log(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; } Os::Logger::instance().log(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 = 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 Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::processForm *** domain '%s'", mLogName.data(), Gatewayredirector->mDomainName.data()); #endif if (success) { Os::Logger::instance().log(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(), Gatewayredirector->mDomainName.data()); } else { Os::Logger::instance().log(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'; #endif #endif }
void testAllLongDistancePermutations() { FallbackRulesUrlMapping* urlmap; ResultSet registrations; UtlString actual; UtlString callTag = "UNK"; CPPUNIT_ASSERT( urlmap = new FallbackRulesUrlMapping() ); UtlString simpleXml; mFileTestContext->inputFilePath("fallbackrules.xml", simpleXml); CPPUNIT_ASSERT( urlmap->loadMappings(simpleXml.data() ) == OS_SUCCESS ); // permutations for the 'boston' location CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 2 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.9",actual); getResult( registrations, 1, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.8",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 2 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.9",actual); getResult( registrations, 1, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.8",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 2 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.9",actual); getResult( registrations, 1, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.8",actual); registrations.destroyAll(); // permutations for the 'seattle' location CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 2 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.9",actual); getResult( registrations, 1, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.7",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 2 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.9",actual); getResult( registrations, 1, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.7",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 2 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.9",actual); getResult( registrations, 1, "contact", actual); ASSERT_STR_EQUAL("<sip:[email protected]>;q=0.7",actual); registrations.destroyAll(); // permutations for the other locations CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("walla-walla"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString(""), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("ogden"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); delete urlmap; }
void testAllEmergencyPermutations() { FallbackRulesUrlMapping* urlmap; ResultSet registrations; UtlString actual; UtlString callTag = "UNK"; CPPUNIT_ASSERT( urlmap = new FallbackRulesUrlMapping() ); UtlString simpleXml; mFileTestContext->inputFilePath("fallbackrules.xml", simpleXml); CPPUNIT_ASSERT( urlmap->loadMappings(simpleXml.data() ) == OS_SUCCESS ); // permutations for the 'boston' location CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); // permutation for the 'seattle' location CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("seattle"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); // permutation for the default location CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Kookamonga"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString(""), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); delete urlmap; }
int main(int argc, char* argv[]) { int provisioningAgentPort = 8110; int watchdogRpcServerPort = 8092; ACDServer* pAcdServer; // Disable osPrintf's enableConsoleOutput(false); UtlString argString; for (int argIndex = 1; argIndex < argc; argIndex++) { osPrintf("arg[%d]: %s\n", argIndex, argv[argIndex]); argString = argv[argIndex]; NameValueTokenizer::frontBackTrim(&argString, "\t "); if (argString.compareTo("-v") == 0) { enableConsoleOutput(true); osPrintf("Version: %s (%s)\n", VERSION, PACKAGE_REVISION); return(1); } else if (argString.compareTo("-c") == 0) { // Enable osPrintf's enableConsoleOutput(true); } else if (argString.compareTo("-d") == 0) { // Switch ACDServer PRI_DEBUG to PRI_NOTICE gACD_DEBUG = PRI_NOTICE; } else if (argString.compareTo("-P") == 0) { argString = argv[++argIndex]; provisioningAgentPort = atoi(argString.data()); } else if (argString.compareTo("-W") == 0) { argString = argv[++argIndex]; watchdogRpcServerPort = atoi(argString.data()); } else { enableConsoleOutput(true); osPrintf("usage: %s [-v] [-c] [-d] [-P port] [-W wport]\nwhere:\n -v Provides the software version\n" " -c Enables console output of log and debug messages\n" " -d Changes ACDServer DEBUG logging to run at NOTICE level\n" " -P port Specifies the provisioning interface port number\n" " -W wport Specifies the Watchdog interface port number\n", argv[0]); return(1); } } // Create the ACDServer and get to work. pAcdServer = new ACDServer(provisioningAgentPort, watchdogRpcServerPort); // Loop forever until signaled to shut down while (!Os::UnixSignals::instance().isTerminateSignalReceived() && !gShutdownFlag) { OsTask::delay(2000); } // Shut down the ACDServer. delete pAcdServer; // Flush the log file Os::Logger::instance().flush(); // Say goodnight Gracie... // Use _exit to avoid the atexit() processing which will cause the // destruction of static objects...yet there are still threads out // there using those static objects. This prevents core dumps // due to those threads accessing the static objects post destruction. // // --Woof! _exit(0); /*NOTREACHED*/ return 0 ; // To appease the compiler gods }
void testAll800Permutations() { FallbackRulesUrlMapping* urlmap; ResultSet registrations; UtlString actual; UtlString callTag = "UNK"; CPPUNIT_ASSERT( urlmap = new FallbackRulesUrlMapping() ); UtlString simpleXml; mFileTestContext->inputFilePath("fallbackrules.xml", simpleXml); CPPUNIT_ASSERT( urlmap->loadMappings(simpleXml.data() ) == OS_SUCCESS ); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("boston"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("regina"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString(""), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("new-york"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("DC"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("Philly"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString(""), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("miami"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); CPPUNIT_ASSERT( urlmap->getContactList( Url("sip:[email protected]") ,UtlString("orlando"), registrations, callTag ) == OS_SUCCESS ); CPPUNIT_ASSERT_EQUAL( 1 , registrations.getSize() ); getResult( registrations, 0, "contact", actual); ASSERT_STR_EQUAL("sip:[email protected]",actual); registrations.destroyAll(); delete urlmap; }
void SessionContext::reportDialogTrackerReadyForDeletion( const UtlString& handleOfRequestingDialogContext ) { OsSysLog::add(FAC_NAT, PRI_DEBUG, "SessionContext[%s]::reportDialogTrackerReadyForDeletion for dialog tracker %s", mHandle.data(), handleOfRequestingDialogContext.data() ); mListOfDialogTrackersReadyForDeletion.push_back( handleOfRequestingDialogContext ); }
bool SessionContext::linkFarEndMediaRelayPortToRequester( const UtlString& handleOfRequestingDialogContext, const tMediaRelayHandle& relayHandle, const MediaDescriptor* pMediaDescriptor, EndpointRole endpointRoleOfRequester ) { EndpointRole farEndRole; EndpointDescriptor *pRequestingEndpointDescriptor; if( endpointRoleOfRequester == CALLER ) { farEndRole = CALLEE; pRequestingEndpointDescriptor = mpCaller; } else { farEndRole = CALLER; pRequestingEndpointDescriptor = mpCallee; } bool bLinkPerformed = false; LocationCode requestingEndpointLocation; UtlString requestingEndpointIpAddress; int requestingEndpointRtpPort; int requestingEndpointRtcpPort; requestingEndpointLocation = pRequestingEndpointDescriptor->getLocationCode(); if( requestingEndpointLocation != UNKNOWN && pMediaDescriptor->getEndpoint( endpointRoleOfRequester ).getAddress() == pRequestingEndpointDescriptor->getNativeTransportAddress().getAddress() ) { // SDP originates from the actual endpoint, the call is not 3PCC. If the endpoint falls into one // of these two categories then link the media relay to the endpoint's media IP and port // #1 - the location of the endpoint is PUBLIC // #2 - the location of the endpoint is LOCAL_NATED and the media server is location in the same subnet as sipXecs if( ( requestingEndpointLocation == PUBLIC ) || ( requestingEndpointLocation == LOCAL_NATED && mpMediaRelay->isPartOfsipXLocalPrivateNetwork() ) ) { // the endpoint is at a predictable IP address and port, no need to autolearn anything requestingEndpointIpAddress = pMediaDescriptor->getEndpoint( endpointRoleOfRequester ).getAddress(); requestingEndpointRtpPort = pMediaDescriptor->getEndpoint( endpointRoleOfRequester ).getRtpPort(); requestingEndpointRtcpPort = pMediaDescriptor->getEndpoint( endpointRoleOfRequester ).getRtcpPort(); } else { // the endpoint is behind a NAT relative to the media relay server. This means that its // media IP address is going to be its public IP address but the port is non-deterministic requestingEndpointIpAddress = pRequestingEndpointDescriptor->getPublicTransportAddress().getAddress(); requestingEndpointRtpPort = 0; requestingEndpointRtcpPort = 0; } } else { // The location of the endpoint is UNKNOWN or the IP address in the SDP does not // belong to the sender of the SDP in which case we may be in the presence or a 3PCC. // In either case, since we cannot establish the position of the endpoint relative // to the media relay, let's assume the worst case and autolearn both the IP address // and port number. requestingEndpointIpAddress = ""; requestingEndpointRtpPort = 0; requestingEndpointRtcpPort = 0; } OsSysLog::add(FAC_NAT, PRI_DEBUG, "SessionContext[%s]::linkMediaRelayPortToFarEnd for dialog tracker %s: relay handle %d - linking far-end relay port to '%s':%d,%d", mHandle.data(), handleOfRequestingDialogContext.data(), (int)(relayHandle.getValue()), requestingEndpointIpAddress.data(), requestingEndpointRtpPort, requestingEndpointRtcpPort ); bLinkPerformed = mpMediaRelay->linkSymToEndpoint( relayHandle, requestingEndpointIpAddress, requestingEndpointRtpPort, requestingEndpointRtcpPort, farEndRole ); return bLinkPerformed; }
bool SessionContext::handleRequest( SipMessage& message, const char* address, int port, bool bFromCallerToCallee ) { // This routine steers incoming requests to the DialogTracker instance that is // responsible for handling them based on the request's to- or from-tags depending // on the directionality of the request. ssize_t numberOfDialogTrackersEnteringRoutine = getNumberOfTrackedDialogs(); bool bTrackRequestResponse = false; UtlString discriminatingTag = getDiscriminatingTagValue( message, bFromCallerToCallee ); // if a discriminating tag was found, try to find a DialogTracker for it. if( !discriminatingTag.isNull() ) { DialogTracker* pDialogTracker = 0; if( ( pDialogTracker = getDialogTrackerForTag( discriminatingTag ) ) != 0 ) { bTrackRequestResponse = pDialogTracker->handleRequest( message, address, port, bFromCallerToCallee ); } else { OsSysLog::add(FAC_NAT, PRI_CRIT, "SessionContext[%s]::handleRequest: received in-dialog request with unknown discriminating tag: %s", mHandle.data(), discriminatingTag.data() ); } } else { // The request does not yet have a discriminating tag. This is likely indicating a // dialog-forming INVITE but to be sure, check that the request is indeed an // INVITE in the caller->callee direction. UtlString method; message.getRequestMethod(&method); if( bFromCallerToCallee && method.compareTo( SIP_INVITE_METHOD ) == 0 ) { // The INVITE is dialog-forming. Check whether or not already have // the reference dialog tracker for it. if( !mpReferenceDialogTracker ) { // This is the first time we see that dialog-forming request - create // a reference dialog tracker that will serve as a template to create // new DialogTracker objects for the dialogs that responses to the // request will establish. Url tempUrl; char tempBuffer[50]; sprintf( tempBuffer, "%s-%s", mHandle.data(), "ref" ); if( ( mpReferenceDialogTracker = new DialogTracker( tempBuffer, mSystemIdentificationString, this ) ) ) { mpReferenceDialogTracker->handleRequest( message, address, port, bFromCallerToCallee ); // save the From tag of the dialog-forming request. This will be used to identify // the discriminating tag when the directionality of a message is unknown. message.getFromUrl( tempUrl ); tempUrl.getFieldParameter( "tag", mDialogOriginalFromTag ); mDialogFormingInviteCseq.setValue( message ); bTrackRequestResponse = true; } } else { // This dialog-forming request has already been seen - this is likely a // retransmission. Present it to the reference dialog tracker so that // it can handle the retransmission properly. bTrackRequestResponse = mpReferenceDialogTracker->handleRequest( message, address, port, bFromCallerToCallee ); } } } // Check if the processing of the request caused the last DialogTracker to be deleted. // If so, the SessionContext is not required anymore therefore tell the CallTracker that // we are ready for deletion if( numberOfDialogTrackersEnteringRoutine && deleteDialogTrackersReadyForDeletion() == numberOfDialogTrackersEnteringRoutine ) { mpOwningCallTracker->reportSessionContextReadyForDeletion( mHandle ); } return bTrackRequestResponse; }
/** * Test header, message, body, message contructor */ void testMessage() { // TODO break this up into several tests. Too intertwined const char* name = "Content-Type"; const char* value = "text/plain"; const char* httpTopLine = "GET /index.html HTTP/1.0"; const char* valueRef = NULL; const char* n2 = "yyy"; const char* v2 = "yyy-value"; const char* v2a = "yyy-value2"; UtlString messageBytes; UtlString messageBytes2; ssize_t messageLen = 0; ssize_t messageLen2 = 0; const char* body = "<HTML>\n<H3>Hello\n<BR>\n</HTML>\n"; const HttpBody *bodyRef; ssize_t bodyLength = 0; UtlString headerLinePart; HttpMessage *msg; HttpMessage *msg2; msg = new HttpMessage(); // H E A D E R int fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be zero", 0, fieldCount); msg->addHeaderField(name, value); fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be zero", 1, fieldCount); valueRef = msg->getHeaderValue(0); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value, valueRef); msg->setFirstHeaderLine(httpTopLine); valueRef = msg->getFirstHeaderLine(); ASSERT_STR_EQUAL_MESSAGE("incorrect top header line value", valueRef, httpTopLine); valueRef = msg->getHeaderValue(0, name); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", value, valueRef); msg->addHeaderField(n2, v2); fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 2", 2, fieldCount); valueRef = msg->getHeaderValue(0, n2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", v2, valueRef); msg->addHeaderField(n2, v2a); fieldCount = msg->getCountHeaderFields(); CPPUNIT_ASSERT_EQUAL_MESSAGE("field count should be 3", 3, fieldCount); valueRef = msg->getHeaderValue(1, n2); CPPUNIT_ASSERT_MESSAGE("NULL field value", valueRef != NULL); ASSERT_STR_EQUAL_MESSAGE("incorrect field value", v2a, valueRef); // B O D Y HttpBody *httpBody = new HttpBody(body, strlen(body)); msg->setBody(httpBody); bodyRef = msg->getBody(); CPPUNIT_ASSERT_MESSAGE("bad body pointer", httpBody == bodyRef); bodyRef->getBytes(&valueRef, &bodyLength); CPPUNIT_ASSERT_MESSAGE("bad body pointer", valueRef != NULL); CPPUNIT_ASSERT_EQUAL_MESSAGE("incorrect body len", (ssize_t)strlen(body), bodyLength); ASSERT_STR_EQUAL_MESSAGE("incorrect body value", body, valueRef); const char* expectedLinePart[] = { "GET", "/index.html", "HTTP/1.0" }; size_t n = sizeof(expectedLinePart) / sizeof(expectedLinePart[0]); for (size_t i = 0; i < n; i++) { msg->getFirstHeaderLinePart(i, &headerLinePart); CPPUNIT_ASSERT_MESSAGE("NULL header line part pointer", !headerLinePart.isNull()); ASSERT_STR_EQUAL_MESSAGE("incorrect hdr line", expectedLinePart[i], headerLinePart.data()); headerLinePart.remove(0); } msg->getBytes(&messageBytes, &messageLen); CPPUNIT_ASSERT_MESSAGE("NULL body pointer", !messageBytes.isNull()); // message constructor msg2 = new HttpMessage(messageBytes.data(), messageLen); msg2->getBytes(&messageBytes2, &messageLen2); valueRef = msg2->getHeaderValue(0, name); ASSERT_STR_EQUAL_MESSAGE("incorrect message bytes", value, valueRef); CPPUNIT_ASSERT_EQUAL_MESSAGE("incorrect message byte length", messageLen, messageLen2); delete msg2; delete msg; // AS DESIGNED: body delete is handled by delete msg // delete httpBody; }
// Process a notify event callback. // This involves parsing the content of the callback and revising our record // of the state for that subscription. Then, we must regenerate the list // of contacts and update the set of subscriptions to match the current // contacts. void ContactSet::notifyEventCallback(const UtlString* dialogHandle, const UtlString* content) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback mUri = '%s', dialogHandle = '%s', content = '%s'", mUri.data(), dialogHandle->data(), content->data()); // Parse the XML and update the contact status. // Find the UtlHashMap for this subscription. UtlHashMap* state_from_this_subscr = dynamic_cast <UtlHashMap*> (mSubscriptions.findValue(dialogHandle)); if (!state_from_this_subscr) { // No state for this dialogHandle, so we need to add one. OsSysLog::add(FAC_RLS, PRI_WARNING, "ContactSet::notifyEventCallback mSubscriptions element does not exist for this dialog handle mUri = '%s', dialogHandle = '%s'", mUri.data(), dialogHandle->data()); // Check that we don't have too many subscriptions. if (mSubscriptions.entries() < getResourceListServer()->getMaxRegSubscInResource()) { state_from_this_subscr = new UtlHashMap; mSubscriptions.insertKeyAndValue(new UtlString(*dialogHandle), state_from_this_subscr); } else { OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback cannot add reg subscription with dialog handle '%s', already %zu in ContactSet '%s'", dialogHandle->data(), mSubscriptions.entries(), mUri.data()); } } // Perform the remainder of the processing if we obtained a hash map // from the above processing. if (state_from_this_subscr) { // Initialize Tiny XML document object. TiXmlDocument document; TiXmlNode* reginfo_node; if ( // Load the XML into it. document.Parse(content->data()) && // Find the top element, which should be a <reginfo>. (reginfo_node = document.FirstChild("reginfo")) != NULL && reginfo_node->Type() == TiXmlNode::ELEMENT) { // Check the state attribute. const char* p = reginfo_node->ToElement()->Attribute("state"); if (p && strcmp(p, "full") == 0) { // If the state is "full", delete the current state. state_from_this_subscr->destroyAll(); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback clearing state"); } // Find all the <registration> elements for this URI. for (TiXmlNode* registration_node = 0; (registration_node = reginfo_node->IterateChildren("registration", registration_node)); ) { // Do not test the aor attribute of <registration> elements // because the reg event server may be operating with the real // AOR for this URI, whereas we may have been told of an alias. // Find all the <contact> elements. for (TiXmlNode* contact_node = 0; (contact_node = registration_node->IterateChildren("contact", contact_node)); ) { TiXmlElement* contact_element = contact_node->ToElement(); // Get the state attribute. const char* state = contact_element->Attribute("state"); // Get the id attribute const char* id = contact_element->Attribute("id"); // Get the Contact URI for the phone. If a GRUU address is present we should // use that as the Contact URI. Otherwise, use the contact URI present in the // "uri" element, and append any path headers that are present to the ROUTE // header parameter in the URI. This will ensure proper routing in HA systems. // Please refer to XECS-1694 for more details. UtlString* uri_allocated = new UtlString; UtlBoolean check_uri = TRUE; TiXmlNode* pub_gruu_node = contact_element->FirstChild("gr:pub-gruu"); if (pub_gruu_node) { TiXmlElement* pub_gruu_element = pub_gruu_node->ToElement(); UtlString pub_gruu_uri(pub_gruu_element->Attribute("uri")); if (!pub_gruu_uri.isNull()) { // Check the URI Scheme. Only accept the GRUU address if it is of either // a sip or sips scheme Url tmp(pub_gruu_uri, TRUE); Url::Scheme uriScheme = tmp.getScheme(); if(Url::SipUrlScheme == uriScheme || Url::SipsUrlScheme == uriScheme) { tmp.removeAngleBrackets(); tmp.getUri(*uri_allocated); check_uri = FALSE; } } } // If we did not find a GRUU address, then use the address in the "uri" element as the // contact URI, and check for path headers. if (check_uri) { TiXmlNode* u = contact_element->FirstChild("uri"); if (u) { textContentShallow(*uri_allocated, u); // Iterate through all the path header elements. Path headers are stored in the // "unknown-param" elements that have a "name" attribute value of "path". for (TiXmlNode* unknown_param_node = 0; (unknown_param_node = contact_node->IterateChildren("unknown-param", unknown_param_node)); ) { TiXmlElement* unknown_param_element = unknown_param_node->ToElement(); UtlString path(unknown_param_element->Attribute("name")); if(0 == path.compareTo("path")) { UtlString pathVector; textContentShallow(pathVector, unknown_param_node); if(!pathVector.isNull()) { Url contact_uri(*uri_allocated, TRUE); // there is already a Route header parameter in the contact; append it to the // Route derived from the Path vector. UtlString existingRouteValue; if ( contact_uri.getHeaderParameter(SIP_ROUTE_FIELD, existingRouteValue)) { pathVector.append(SIP_MULTIFIELD_SEPARATOR); pathVector.append(existingRouteValue); } contact_uri.setHeaderParameter(SIP_ROUTE_FIELD, pathVector); contact_uri.removeAngleBrackets(); contact_uri.getUri(*uri_allocated); } } } } } // Only process <contact> elements that have the needed values. if (state && state[0] != '\0' && id && id[0] != '\0' && !uri_allocated->isNull()) { UtlString* id_allocated = new UtlString(id); if (strcmp(state, "active") == 0) { // Add the contact if it is not already present. if (!state_from_this_subscr->find(id_allocated)) { // Prepend the registration Call-Id and ';' to *uri_allocated.. uri_allocated->insert(0, ';'); const char* call_id = contact_element->Attribute("callid"); if (call_id) { uri_allocated->insert(0, call_id); } // Check that we don't have too many contacts. if (state_from_this_subscr->entries() < getResourceListServer()->getMaxContInRegSubsc()) { // Insert the registration record. if (state_from_this_subscr->insertKeyAndValue(id_allocated, uri_allocated)) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback adding id = '%s' Call-Id;URI = '%s'", id, uri_allocated->data()); id_allocated = NULL; uri_allocated = NULL; } else { OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback adding id = '%s' Call-Id;URI = '%s' failed", id_allocated->data(), uri_allocated->data()); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback *state_from_this_subscr is:"); UtlHashMapIterator itor(*state_from_this_subscr); UtlContainable* k; while ((k = itor())) { UtlContainable* v = itor.value(); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback (*state_from_this_subscr)['%s'] = '%s'", (dynamic_cast <UtlString*> (k))->data(), (dynamic_cast <UtlString*> (v))->data()); } } } else { OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback cannot add Call-Id;RUI '%s', already %zu in ContactSet '%s' subscription '%s'", uri_allocated->data(), state_from_this_subscr->entries(), mUri.data(), dialogHandle->data()); } } } else if (strcmp(state, "terminated") == 0) { // Delete it from the contact state. state_from_this_subscr->destroy(id_allocated); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::notifyEventCallback deleting id = '%s'", id); } // Free id_allocated, if it is not pointed to by a data // structure, which is indicated by setting it to NULL. if (id_allocated) { delete id_allocated; } } else { OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback <contact> element with id = '%s' is missing id, state, and/or URI", id ? id : "(missing)"); } // Free uri_allocated, if it is not pointed to by a data // structure, which is indicated by setting it to NULL. if (uri_allocated) { delete uri_allocated; } } } } else { // Error parsing the contents. OsSysLog::add(FAC_RLS, PRI_ERR, "ContactSet::notifyEventCallback malformed reg event content for mUri = '%s'", mUri.data()); } // Update the subscriptions we maintain to agree with the new state. updateSubscriptions(); } }
void SipTransactionList::removeOldTransactions(long oldTransaction, long oldInviteTransaction) { SipTransaction** transactionsToBeDeleted = NULL; int deleteCount = 0; int busyCount = 0; # ifdef TIME_LOG OsTimeLog gcTimes; gcTimes.addEvent("start"); # endif lock(); int numTransactions = mTransactions.entries(); if(numTransactions > 0) { UtlHashBagIterator iterator(mTransactions); SipTransaction* transactionFound = NULL; long transTime; // Pull all of the transactions to be deleted out of the list while ((transactionFound = (SipTransaction*) iterator())) { if(transactionFound->isBusy()) busyCount++; transTime = transactionFound->getTimeStamp(); // Invites need to be kept longer than other transactions if(((!transactionFound->isMethod(SIP_INVITE_METHOD) && transTime < oldTransaction) || transTime < oldInviteTransaction) && ! transactionFound->isBusy()) { // Remove it from the list mTransactions.removeReference(transactionFound); OsSysLog::add(FAC_SIP, PRI_DEBUG, "removing transaction %p\n",transactionFound); // Make sure we have a pointer array to hold it if(transactionsToBeDeleted == NULL) { transactionsToBeDeleted = new SipTransaction*[numTransactions]; } // Put it in the pointer array transactionsToBeDeleted[deleteCount] = transactionFound; deleteCount++; // Make sure the events waiting for the transaction // to be available are signaled before we delete // any of the transactions or we end up with // incomplete transaction trees (i.e. deleted branches) transactionFound->signalAllAvailable(); transactionFound = NULL; } } } unlock(); // We do not need the lock if the transactions have been // removed from the list if ( deleteCount || busyCount ) // do not log 'doing nothing when nothing to do', even at debug level { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::removeOldTransactions deleting %d of %d transactions (%d busy)\n", deleteCount , numTransactions, busyCount); } // Delete the transactions in the array if (transactionsToBeDeleted) { # ifdef TIME_LOG gcTimes.addEvent("start delete"); # endif for(int txIndex = 0; txIndex < deleteCount; txIndex++) { delete transactionsToBeDeleted[txIndex]; # ifdef TIME_LOG gcTimes.addEvent("transaction deleted"); # endif } # ifdef TIME_LOG gcTimes.addEvent("finish delete"); # endif delete[] transactionsToBeDeleted; } # ifdef TIME_LOG UtlString timeString; gcTimes.getLogString(timeString); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::removeOldTransactions " "%s", timeString.data() ); # endif }
// Update the subscriptions we maintain to agree with the current contact state void ContactSet::updateSubscriptions() { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions mUri = '%s'", mUri.data()); // First, scan mSubscriptions to construct a list of all the // call-id/contact combinations. // (If a phone reboots and starts registering with a different Call-Id, // the call-id/contact combination will be different even if the contact // URI is unchanged. So the new registration will appear to be different // to this machinery, and it will establish a new SubscriptionSet to // the contact URI. This compensates for the fact that the previous // SubscriptionSet to the contact URI appears to the RLS to be // working but the phone no longer knows of the subscription. The // reg events will eventually terminate the old combination and we // will delete its SubscriptionSet.) UtlHashBag callid_contacts; UtlHashMapIterator subs_itor(mSubscriptions); while (subs_itor()) { if (OsSysLog::willLog(FAC_RLS, PRI_DEBUG)) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions subscription '%s'", (dynamic_cast <UtlString*> (subs_itor.key()))->data()); } UtlHashMap* contact_state = dynamic_cast <UtlHashMap*> (subs_itor.value()); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions contact_state = %p", contact_state); UtlHashMapIterator contact_itor(*contact_state); while (contact_itor()) { UtlString* contact = dynamic_cast <UtlString*> (contact_itor.value()); if (OsSysLog::willLog(FAC_RLS, PRI_DEBUG)) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions contact id '%s', Call-Id/URI '%s'", (dynamic_cast <UtlString*> (contact_itor.key()))->data(), contact->data()); } // Check if the contact is already in callid_contacts. if (!callid_contacts.find(contact)) { // If not, add it. UtlString* c = new UtlString(*contact); callid_contacts.insert(c); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions contact added"); } } } // If the list of callid_contacts is empty, add mUri as the default contact // (with an empty registration Call-Id). if (callid_contacts.isEmpty()) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions adding default contact mUri = '%s'", mUri.data()); UtlString* c = new UtlString(";"); c->append(mUri); callid_contacts.insert(c); } // Now that we have a clean list of callid_contacts, update // SubscriptionSets to match it. // If we both terminate subscriptions and create subscriptions, // wait a short while to allow the terminations to complete. This // should not be necessary, but it makes life easier on Polycom // phones which (at this time) cannot support two subscriptions at // a time, and if the termination of the old subscription arrives // after the initiation of the new subscription, the new // subscription will be lost. // This variable tracks whether such a wait is needed before a // subscription is started. bool subscription_ended_but_no_wait_done_yet = false; // Iterate through the list of SubscriptionSets and remove any that aren't // in callid_contacts. { UtlHashMapIterator itor(mSubscriptionSets); UtlString* ss; while ((ss = dynamic_cast <UtlString*> (itor()))) { if (!callid_contacts.find(ss)) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions deleting subscription for '%s' in mUri = '%s'", ss->data(), mUri.data()); mSubscriptionSets.destroy(ss); subscription_ended_but_no_wait_done_yet = true; } } } // Iterate through callid_contacts and add a SubscriptionSet for // any that aren't in mSubscriptionSets. // We don't limit the number of additions here, as the size of // callid_contacts is guarded by the tests in notifyEventCallback. { UtlHashBagIterator itor(callid_contacts); UtlString* callid_contact; while ((callid_contact = dynamic_cast <UtlString*> (itor()))) { if (!mSubscriptionSets.find(callid_contact)) { // If we both terminate subscriptions and create subscriptions, // wait a short while to allow the terminations to complete. // Note that this wait must be no more than the bulk add/delete // change delay, as that is how fast ResourceListFileReader // generates requests to the ResourceListServer task. int wait = getResourceListServer()->getChangeDelay(); if (wait > 0) { if (subscription_ended_but_no_wait_done_yet) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions waiting for %d msec", wait); OsTask::delay(wait); subscription_ended_but_no_wait_done_yet = false; } } OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions adding subscription for '%s' in mUri = '%s'", callid_contact->data(), mUri.data()); // Get the contact URI into a UtlString. UtlString uri(callid_contact->data() + callid_contact->index(';') + 1); mSubscriptionSets.insertKeyAndValue(new UtlString(*callid_contact), new SubscriptionSet(mResource, uri)); } } } // Free callid_contacts. callid_contacts.destroyAll(); }
//: 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); }
// Returns TRUE if the requested state is different from the current state. bool SipPresenceMonitor::addPresenceEvent(UtlString& contact, SipPresenceEvent* presenceEvent) { mLock.acquire(); bool requiredPublish = false; if (mPresenceEventList.find(&contact) == NULL) { requiredPublish = true; OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent adding presenceEvent %p for contact %s", presenceEvent, contact.data()); } else { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent presenceEvent %p for contact %s already exists, updating its contents.", presenceEvent, contact.data()); // Get the object from the presence event list UtlContainable* oldKey; UtlContainable* foundValue; foundValue = mPresenceEventList.findValue(&contact); SipPresenceEvent* oldPresenceEvent = dynamic_cast <SipPresenceEvent *> (foundValue); UtlString oldStatus, status; UtlString id; makeId(id, contact); oldPresenceEvent->getTuple(id)->getStatus(oldStatus); presenceEvent->getTuple(id)->getStatus(status); if (status.compareTo(oldStatus) != 0) { requiredPublish = true; // Since we will be saving a new value, remove the old one. oldKey = mPresenceEventList.removeKeyAndValue(&contact, foundValue); delete oldKey; if (oldPresenceEvent) { delete oldPresenceEvent; } } } if (requiredPublish) { // Insert it into the presence event list. presenceEvent->buildBody(); mPresenceEventList.insertKeyAndValue(new UtlString(contact), presenceEvent); if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG)) { UtlString b; ssize_t l; presenceEvent->getBytes(&b, &l); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::addPresenceEvent presenceEvent %p for contact '%s' body '%s' is different from previous presenceEvent", presenceEvent, contact.data(), b.data()); } if (mToBePublished) { // Publish the content to the resource list. publishContent(contact, presenceEvent); } // Notify the state change. notifyStateChange(contact, presenceEvent); if (!mPersistentFile.isNull()) { // Start the save timer. mPersistenceTimer.oneshotAfter(sPersistInterval); } } else { // Since this presenceEvent will not be published (it does not // change the state we've sent out), delete it now. delete presenceEvent; } mLock.release(); return requiredPublish; }
// Read config information. void SipRedirectorGateway::readConfig(OsConfigDb& configDb) { UtlString string; char *endptr; mReturn = OS_SUCCESS; if (configDb.get("MAPPING_FILE", mMappingFileName) != OS_SUCCESS || mMappingFileName.isNull()) { Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "%s::readConfig " "MAPPING_FILE parameter '%s' missing or empty", mLogName.data(), mMappingFileName.data()); mReturn = OS_FAILED; } else { Os::Logger::instance().log(FAC_SIP, PRI_INFO, "%s::readConfig " "MAPPING_FILE is '%s'", mLogName.data(), mMappingFileName.data()); } if (configDb.get("PREFIX", mPrefix) != OS_SUCCESS || mPrefix.isNull()) { Os::Logger::instance().log(FAC_SIP, PRI_INFO, "%s::readConfig " "dialing prefix is empty", mLogName.data()); } else { Os::Logger::instance().log(FAC_SIP, PRI_INFO, "%s::readConfig " "dialing prefix is '%s'", mLogName.data(), mPrefix.data()); } if (configDb.get("DIGITS", string) == OS_SUCCESS && !string.isNull() && (mDigits = strtol(string.data(), &endptr, 10), endptr - string.data() == string.length() && mDigits >= 1 && mDigits <= 10)) { Os::Logger::instance().log(FAC_SIP, PRI_INFO, "%s::readConfig " "variable digit count is %d", mLogName.data(), mDigits); } else { Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "%s::readConfig " "variable digit count is missing, empty, " "or out of range (1 to 10)", mLogName.data()); mReturn = OS_FAILED; } if (configDb.get("PORT", string) == OS_SUCCESS && !string.isNull() && (mPort = strtol(string.data(), &endptr, 10), endptr - string.data() == string.length() && mPort >= 1 && mPort <= 65535)) { Os::Logger::instance().log(FAC_SIP, PRI_INFO, "%s::readConfig " "listening port is %d", mLogName.data(), mPort); } else { Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "%s::readConfig " "listening port '%s' is missing, empty, " "or out of range (1 to 65535)", mLogName.data(), string.data()); mReturn = OS_FAILED; } }
// Read the presence events from the persistent file. void SipPresenceMonitor::readPersistentFile() { mLock.acquire(); // Initialize Tiny XML document object. TiXmlDocument document; TiXmlNode* items_node; if ( // Load the XML into it. document.LoadFile(mPersistentFile.data()) && // Find the top element, which should be an <items>. (items_node = document.FirstChild("items")) != NULL && items_node->Type() == TiXmlNode::ELEMENT) { // Find all the <item> elements. int item_seq_no = 0; for (TiXmlNode* item_node = 0; (item_node = items_node->IterateChildren("item", item_node)); ) { if (item_node->Type() == TiXmlNode::ELEMENT) { item_seq_no++; TiXmlElement* item_element = item_node->ToElement(); // Process the <item> element. bool item_valid = true; // Process the 'id' child. UtlString id; TiXmlNode* id_node = item_element->FirstChild("id"); if (id_node && id_node->Type() == TiXmlNode::ELEMENT) { textContentShallow(id, id_node); if (id.isNull()) { // Id null. OsSysLog::add(FAC_ACD, PRI_ERR, "id child of <item> was null"); item_valid = false; } } else { // Id missing. OsSysLog::add(FAC_ACD, PRI_ERR, "id child of <item> was missing"); item_valid = false; } // Process the 'contact' child. UtlString contact; TiXmlNode* contact_node = item_element->FirstChild("contact"); if (contact_node && contact_node->Type() == TiXmlNode::ELEMENT) { textContentShallow(contact, contact_node); if (contact.isNull()) { // Contact null. OsSysLog::add(FAC_ACD, PRI_ERR, "contact child of <item> was null"); item_valid = false; } } else { // Contact missing. OsSysLog::add(FAC_ACD, PRI_ERR, "contact child of <item> was missing"); item_valid = false; } // Process the 'status' child. UtlString status; TiXmlNode* status_node = item_element->FirstChild("status"); if (status_node && status_node->Type() == TiXmlNode::ELEMENT) { textContentShallow(status, status_node); if (status.isNull()) { // Status null. OsSysLog::add(FAC_ACD, PRI_ERR, "status child of <item> was null"); item_valid = false; } } else { // Status missing. OsSysLog::add(FAC_ACD, PRI_ERR, "status child of <item> was missing"); item_valid = false; } OsSysLog::add(FAC_ACD, PRI_DEBUG, "SipPresenceMonitor::readPersistentFile row: id = '%s', contact = '%s', status = '%s'", id.data(), contact.data(), status.data()); if (item_valid) { // Create a presence event package and store it in // mPresenceEventList. SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(contact); Tuple* tuple = new Tuple(id.data()); tuple->setStatus(status); tuple->setContact(contact, 1.0); sipPresenceEvent->insertTuple(tuple); sipPresenceEvent->buildBody(); mPresenceEventList.insertKeyAndValue(new UtlString(contact), sipPresenceEvent); } else { OsSysLog::add(FAC_ACD, PRI_ERR, "In presence status file '%s', <item> number %d had invalid or incomplete information. The readable information was: id = '%s', contact = '%s', status = '%s'", mPersistentFile.data(), item_seq_no, id.data(), contact.data(), status.data()); } } } } else { // Report error parsing file. OsSysLog::add(FAC_ACD, PRI_CRIT, "Presence status file '%s' could not be parsed.", mPersistentFile.data()); } mLock.release(); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitorPersistenceTask::readPersistentFile done"); }
virtual bool execute(const HttpRequestContext& requestContext, ///< request context UtlSList& params, ///< request param list void* userData, ///< user data XmlRpcResponse& response, ///< request response ExecutionStatus& status ) { UtlString* dbName = dynamic_cast<UtlString*>(params.at(0)); if (dbName && !dbName->isNull()) { OsReadLock lock(*ConfigRPC::spDatabaseLock); // find the dataset registered with this name ConfigRPC* db = ConfigRPC::find(*dbName); if (db) { // check with the application to see if this request is authorized on this dataset status = db->mCallback->accessAllowed(requestContext, ConfigRPC_Callback::Get); if ( XmlRpcMethod::OK == status ) { // read in the dataset OsConfigDb dataset; OsStatus datasetStatus = db->load(dataset); if ( OS_SUCCESS == datasetStatus ) { // get the list of names that the request is asking for UtlContainable* secondParam = params.at(1); if ( secondParam ) { UtlSList* nameList = dynamic_cast<UtlSList*>(secondParam); if (nameList) { /* * Iterate over the requested names * - All must be present or the request is an error * - For each name found, add the name and value to the * selectedParams hash to be returned in a success response. */ UtlHashMap selectedParams; UtlSListIterator requestedNames(*nameList); UtlString* requestedName = NULL; bool allNamesFound = true; while ( allNamesFound && (requestedName = dynamic_cast<UtlString*>(requestedNames())) ) { UtlString* paramValue = new UtlString(); if ( OS_SUCCESS == dataset.get(*requestedName, *paramValue) ) { UtlString* paramName = new UtlString(*requestedName); // put it into the results selectedParams.insertKeyAndValue(paramName, paramValue); } else { allNamesFound = false; delete paramValue; } } if (allNamesFound) { // all were found - return the name/value pairs response.setResponse(&selectedParams); } else { // at least one name was not found - return an error. UtlString faultMsg; faultMsg.append("parameter name '"); faultMsg.append(*requestedName); faultMsg.append("' not found"); response.setFault(ConfigRPC::nameNotFound, faultMsg.data()); status = XmlRpcMethod::FAILED; } selectedParams.destroyAll(); } else { // The second parameter was not a list response.setFault( ConfigRPC::invalidType ,"namelist parameter is not an array" ); status = XmlRpcMethod::FAILED; } } else // no parameter names specified { // return all names UtlHashMap allParams; UtlString lastKey; OsStatus iterateStatus; UtlString* paramName; UtlString* paramValue; bool notEmpty = false; for ( ( paramName = new UtlString() ,paramValue = new UtlString() ,iterateStatus = dataset.getNext(lastKey, *paramName, *paramValue) ); OS_SUCCESS == iterateStatus; ( lastKey = *paramName ,paramName = new UtlString() ,paramValue = new UtlString() ,iterateStatus = dataset.getNext(lastKey, *paramName, *paramValue) ) ) { notEmpty = true; // got at least one parameter // put it into the result array allParams.insertKeyAndValue(paramName, paramValue); } // on the final iteration these were not used delete paramName; delete paramValue; if (notEmpty) { response.setResponse(&allParams); allParams.destroyAll(); } else { // there is no way to send a well-formed but empty response, // so a 'get all' on an empty dataset returns a fault. UtlString faultMsg; faultMsg.append("dataset '"); faultMsg.append(*dbName); faultMsg.append("' has no parameters"); response.setFault(ConfigRPC::emptyDataset, faultMsg); status = XmlRpcMethod::FAILED; } } } else { UtlString faultMsg("dataset load failed"); response.setFault(ConfigRPC::loadFailed, faultMsg); status = XmlRpcMethod::FAILED; } } else { UtlString faultMsg("Access Denied"); response.setFault(XmlRpcMethod::FAILED, faultMsg.data()); } } else { UtlString faultMsg; faultMsg.append("db lookup failed for '"); faultMsg.append(*dbName); faultMsg.append("'"); response.setFault( XmlRpcResponse::UnregisteredMethod, faultMsg.data()); status = XmlRpcMethod::FAILED; } } else { response.setFault( XmlRpcResponse::EmptyParameterValue ,"'dbname' parameter is missing or invalid type" ); status = XmlRpcMethod::FAILED; } return true; }
// Write the presence events to the persistent file. void SipPresenceMonitor::writePersistentFile() { mLock.acquire(); // Create an empty document TiXmlDocument document; // Create a hard coded standalone declaration section document.Parse("<?xml version=\"1.0\" standalone=\"yes\"?>"); // Create the root node container TiXmlElement itemsElement ("items"); itemsElement.SetAttribute("type", sType.data()); itemsElement.SetAttribute("xmlns", sXmlNamespace.data()); int timeNow = (int)OsDateTime::getSecsSinceEpoch(); itemsElement.SetAttribute("timestamp", timeNow); // mPresenceEventList is a hash map that maps contacts to SipPresenceEvents. // SipPresenceEvents are hash maps of contacts to Tuples. In practice, // a SipPresenceEvent has only one Tuple. (And if it had more, there // would be no way to discover what they are, as there is no iterator.) // Tuples are triples: id, contact, status. // Loop through all the events in mPresenceEventList. UtlHashMapIterator iterator(mPresenceEventList); UtlString* contact; while ((contact = dynamic_cast <UtlString*> (iterator()))) { // Create an item container TiXmlElement itemElement ("item"); // Get the SipPresenceEvent. SipPresenceEvent* event = dynamic_cast <SipPresenceEvent*> (iterator.value()); // Calculate the id of the Tuple. UtlString id; makeId(id, *contact); // Get the Tuple. Tuple* tuple = event->getTuple(id); // Get the status. UtlString status; tuple->getStatus(status); // Construct the <item>. TiXmlElement id_element("id"); TiXmlText id_content(id); id_element.InsertEndChild(id_content); itemElement.InsertEndChild(id_element); TiXmlElement contact_element("contact"); TiXmlText contact_content(contact->data()); contact_element.InsertEndChild(contact_content); itemElement.InsertEndChild(contact_element); TiXmlElement status_element("status"); TiXmlText status_content(status); status_element.InsertEndChild(status_content); itemElement.InsertEndChild(status_element); // Add the <item> element to the <items> element. itemsElement.InsertEndChild ( itemElement ); } // Attach <items> to the root node to the document document.InsertEndChild(itemsElement); document.SaveFile(mPersistentFile); mLock.release(); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitorPersistenceTask::writePersistentFile file written"); }
virtual bool execute(const HttpRequestContext& requestContext, ///< request context UtlSList& params, ///< request param list void* userData, ///< user data XmlRpcResponse& response, ///< request response ExecutionStatus& status ) { UtlString* dbName = dynamic_cast<UtlString*>(params.at(0)); if (dbName && !dbName->isNull()) { OsReadLock lock(*ConfigRPC::spDatabaseLock); ConfigRPC* db = ConfigRPC::find(*dbName); if (db) { status = db->mCallback->accessAllowed(requestContext, ConfigRPC_Callback::Set); if ( XmlRpcMethod::OK == status ) { // read in the dataset OsConfigDb dataset; OsStatus datasetStatus = db->load(dataset); if ( OS_SUCCESS == datasetStatus ) { // get the list of names that the request is trying to delete UtlContainable* secondParam = params.at(1); if ( secondParam ) { UtlSList* nameList = dynamic_cast<UtlSList*>(secondParam); if (nameList) { /* * Iterate over the names * - For each name found, delete it from the dataset and count it */ UtlSListIterator deleteNames(*nameList); UtlString* deleteName = NULL; size_t deleted = 0; while ((deleteName = dynamic_cast<UtlString*>(deleteNames()))) { if (OS_SUCCESS == dataset.remove(*deleteName)) { deleted++; } } if (OS_SUCCESS == db->store(dataset)) { status = XmlRpcMethod::OK; UtlInt deletedCount(deleted); response.setResponse(&deletedCount); } else { response.setFault( ConfigRPC::storeFailed ,"error storing dataset" ); status = XmlRpcMethod::FAILED; } } else { // The second parameter was not a list response.setFault( ConfigRPC::invalidType ,"namelist parameter is not an array" ); status = XmlRpcMethod::FAILED; } } else // No second parameter { response.setFault( ConfigRPC::invalidType ,"no second parameter list of names to delete" ); status = XmlRpcMethod::FAILED; } } else { UtlString faultMsg("dataset load failed"); response.setFault(ConfigRPC::loadFailed, faultMsg); status = XmlRpcMethod::FAILED; } } else { UtlString faultMsg("Access Denied"); response.setFault(XmlRpcMethod::FAILED, faultMsg.data()); } } else { UtlString faultMsg; faultMsg.append("db lookup failed for '"); faultMsg.append(*dbName); faultMsg.append("'"); response.setFault( XmlRpcResponse::UnregisteredMethod, faultMsg.data()); status = XmlRpcMethod::FAILED; } } else { response.setFault( XmlRpcResponse::EmptyParameterValue ,"'dbname' parameter is missing or invalid type" ); status = XmlRpcMethod::FAILED; } return true; }
void SipPresenceMonitor::publishContent(UtlString& contact, SipPresenceEvent* presenceEvent) { #ifdef SUPPORT_RESOURCE_LIST // Loop through all the resource lists UtlHashMapIterator iterator(mMonitoredLists); UtlString* listUri; SipResourceList* list; Resource* resource; UtlString id, state; while (listUri = dynamic_cast <UtlString *> (iterator())) { bool contentChanged = false; list = dynamic_cast <SipResourceList *> (mMonitoredLists.findValue(listUri)); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPresenceMonitor::publishContent listUri %s list %p", listUri->data(), list); // Search for the contact in this list resource = list->getResource(contact); if (resource) { resource->getInstance(id, state); if (presenceEvent->isEmpty()) { resource->setInstance(id, STATE_TERMINATED); } else { UtlString id; makeId(id, contact); Tuple* tuple = presenceEvent->getTuple(id); UtlString status; tuple->getStatus(status); if (status.compareTo(STATUS_CLOSED) == 0) { resource->setInstance(id, STATE_TERMINATED); } else { resource->setInstance(id, STATE_ACTIVE); } } list->buildBody(); contentChanged = true; } if (contentChanged) { // Publish the content to the subscribe server // Make a copy, because mpSipPublishContentMgr will own it. HttpBody* pHttpBody = new HttpBody(*(HttpBody*)list); mSipPublishContentMgr.publish(listUri->data(), PRESENCE_EVENT_TYPE, PRESENCE_EVENT_TYPE, 1, &pHttpBody); } } #endif // Publish the content to the subscribe server // Make a copy, because mpSipPublishContentMgr will own it. HttpBody* pHttpBody = new HttpBody(*(HttpBody*)presenceEvent); mSipPublishContentMgr.publish(contact.data(), PRESENCE_EVENT_TYPE, PRESENCE_EVENT_TYPE, 1, &pHttpBody); }
OsStatus MpAudioDriverManager::setCurrentInputDevice(const UtlString& device, const UtlString& driverName) { OsLock lock(ms_mutex); if (m_pAudioDriver) { if (device.compareTo("None", UtlString::ignoreCase) == 0) { // we want to disable current input device return closeInputStream(); } else if (device.compareTo("Default", UtlString::ignoreCase) == 0) { MpAudioDeviceIndex defaultInputDeviceIndex; // we want to set default input device OsStatus res = m_pAudioDriver->getDefaultInputDevice(defaultInputDeviceIndex); if (res != OS_SUCCESS) { return OS_FAILED; } if (defaultInputDeviceIndex != m_inputDeviceIndex) { // we want to change active input device // first close current stream closeInputStream(); MpAudioStreamParameters inputParameters; inputParameters.setChannelCount(1); inputParameters.setSampleFormat(MP_AUDIO_FORMAT_INT16); inputParameters.setSuggestedLatency(m_initialInputStreamLatency); inputParameters.setDeviceIndex(defaultInputDeviceIndex); // open asynchronous input stream res = m_pAudioDriver->openStream(&m_inputAudioStream, &inputParameters, NULL, MpMisc.m_audioSamplesPerSec, MpMisc.m_audioSamplesPerFrame, MP_AUDIO_STREAM_DITHEROFF, TRUE); if (res != OS_SUCCESS) { return OS_FAILED; } res = m_pAudioDriver->startStream(m_inputAudioStream); if (res != OS_SUCCESS) { return OS_FAILED; } m_inputDeviceIndex = defaultInputDeviceIndex; m_inputAudioMixer = m_pAudioDriver->getMixerForStream(m_inputAudioStream, INPUT_MIXER_INDEX); return OS_SUCCESS; } else { // new and old device are the same, no need to change return OS_SUCCESS; } } else { // user wants to select a particular device OsStatus res = OS_FAILED; UtlBoolean bDeviceFound = FALSE; UtlBoolean bDriverReq = !driverName.isNull(); MpAudioDeviceIndex deviceCount = 0; MpAudioDeviceIndex i = 0; UtlString hostApiName; m_pAudioDriver->getDeviceCount(deviceCount); // loop through all devices, and find matching one for (i = 0; i < deviceCount; i++) { MpAudioDeviceInfo deviceInfo; m_pAudioDriver->getDeviceInfo(i, deviceInfo); if (!bDriverReq) { // driver match is not required, match by name only if (deviceInfo.getName().compareTo(device.data(), UtlString::matchCase) == 0 && deviceInfo.getMaxInputChannels() > 0) { // we found match, we will select this device bDeviceFound = TRUE; hostApiName = deviceInfo.getHostApiName(); break; } } else { // now try to match by driver name, device name if (deviceInfo.getName().compareTo(device.data(), UtlString::matchCase) == 0 && deviceInfo.getHostApiName().compareTo(driverName.data(), UtlString::matchCase) == 0 && deviceInfo.getMaxInputChannels() > 0) { // we found match, we will select this device bDeviceFound = TRUE; hostApiName = deviceInfo.getHostApiName(); break; } } } if (bDeviceFound && i != m_inputDeviceIndex) { // we found a matching device // first close current stream closeInputStream(); MpAudioStreamParameters inputParameters; inputParameters.setChannelCount(1); inputParameters.setSampleFormat(MP_AUDIO_FORMAT_INT16); inputParameters.setSuggestedLatency(m_initialInputStreamLatency); inputParameters.setDeviceIndex(i); // open asynchronous input stream res = m_pAudioDriver->openStream(&m_inputAudioStream, &inputParameters, NULL, MpMisc.m_audioSamplesPerSec, MpMisc.m_audioSamplesPerFrame, MP_AUDIO_STREAM_DITHEROFF, MpAudioDriverManager::useSynchronousStream(hostApiName)); if (res != OS_SUCCESS) { return OS_FAILED; } res = m_pAudioDriver->startStream(m_inputAudioStream); if (res != OS_SUCCESS) { return OS_FAILED; } m_inputDeviceIndex = i; m_inputAudioMixer = m_pAudioDriver->getMixerForStream(m_inputAudioStream, INPUT_MIXER_INDEX); return OS_SUCCESS; } // Selecting a device that is already selected is not a failure if(bDeviceFound && i == m_inputDeviceIndex) { return OS_SUCCESS; } } } return OS_FAILED; }
void testGetAuthenticateField() { UtlString value; HttpMessage proxyRspOne( "SIP/2.0 407 Proxy Authentication Required\r\n" "From: <sip:[email protected]>;tag=1c1198308561\r\n" "To: <sip:[email protected];user=phone>\r\n" "Call-Id: [email protected]\r\n" "Cseq: 1 INVITE\r\n" "Via: SIP/2.0/UDP 10.139.4.84;branch=z9hG4bK-de2c934952294f774ee0acbc133e9b1d\r\n" "Via: SIP/2.0/UDP 10.139.33.244;branch=z9hG4bKac1198312375\r\n" "Proxy-Authenticate: Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"\r\n" "Server: sipX/3.6.6 sipX/authproxy (Linux)\r\n" "Date: Wed, 18 Jul 2007 19:34:26 GMT\r\n" "Content-Length: 0\r\n" "\r\n" ); CPPUNIT_ASSERT(!proxyRspOne.getAuthenticateField(0,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(!proxyRspOne.getAuthenticateField(1,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(proxyRspOne.getAuthenticateField(0,HttpMessage::PROXY,value)); ASSERT_STR_EQUAL("Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"", value.data()); CPPUNIT_ASSERT(!proxyRspOne.getAuthenticateField(1,HttpMessage::PROXY,value)); CPPUNIT_ASSERT(value.isNull()); HttpMessage proxyRspTwo( "SIP/2.0 407 Proxy Authentication Required\r\n" "From: <sip:[email protected]>;tag=1c1198308561\r\n" "To: <sip:[email protected];user=phone>\r\n" "Call-Id: [email protected]\r\n" "Cseq: 1 INVITE\r\n" "Via: SIP/2.0/UDP 10.139.4.84;branch=z9hG4bK-de2c934952294f774ee0acbc133e9b1d\r\n" "Via: SIP/2.0/UDP 10.139.33.244;branch=z9hG4bKac1198312375\r\n" "Proxy-Authenticate: Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"\r\n" "Proxy-Authenticate: Digest realm=\"example.net\", nonce=\"nothernonce\"\r\n" "Server: sipX/3.6.6 sipX/authproxy (Linux)\r\n" "Date: Wed, 18 Jul 2007 19:34:26 GMT\r\n" "Content-Length: 0\r\n" "\r\n" ); CPPUNIT_ASSERT(!proxyRspTwo.getAuthenticateField(0,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(!proxyRspTwo.getAuthenticateField(1,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(!proxyRspTwo.getAuthenticateField(2,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(proxyRspTwo.getAuthenticateField(0,HttpMessage::PROXY,value)); ASSERT_STR_EQUAL("Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"", value.data()); CPPUNIT_ASSERT(proxyRspTwo.getAuthenticateField(1,HttpMessage::PROXY,value)); ASSERT_STR_EQUAL("Digest realm=\"example.net\", nonce=\"nothernonce\"", value.data()); CPPUNIT_ASSERT(!proxyRspTwo.getAuthenticateField(2,HttpMessage::PROXY,value)); CPPUNIT_ASSERT(value.isNull()); HttpMessage serverRspOne( "SIP/2.0 401 Authentication Required\r\n" "From: <sip:[email protected]>;tag=1c1198308561\r\n" "To: <sip:[email protected];user=phone>\r\n" "Call-Id: [email protected]\r\n" "Cseq: 1 INVITE\r\n" "Via: SIP/2.0/UDP 10.139.4.84;branch=z9hG4bK-de2c934952294f774ee0acbc133e9b1d\r\n" "Via: SIP/2.0/UDP 10.139.33.244;branch=z9hG4bKac1198312375\r\n" "WWW-Authenticate: Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"\r\n" "Server: sipX/3.6.6 sipX/authproxy (Linux)\r\n" "Date: Wed, 18 Jul 2007 19:34:26 GMT\r\n" "Content-Length: 0\r\n" "\r\n" ); CPPUNIT_ASSERT(!serverRspOne.getAuthenticateField(0,HttpMessage::PROXY,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(!serverRspOne.getAuthenticateField(1,HttpMessage::PROXY,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(serverRspOne.getAuthenticateField(0,HttpMessage::SERVER,value)); ASSERT_STR_EQUAL("Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"", value.data()); CPPUNIT_ASSERT(!serverRspOne.getAuthenticateField(1,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); HttpMessage serverRspTwo( "SIP/2.0 401 Authentication Required\r\n" "From: <sip:[email protected]>;tag=1c1198308561\r\n" "To: <sip:[email protected];user=phone>\r\n" "Call-Id: [email protected]\r\n" "Cseq: 1 INVITE\r\n" "Via: SIP/2.0/UDP 10.139.4.84;branch=z9hG4bK-de2c934952294f774ee0acbc133e9b1d\r\n" "Via: SIP/2.0/UDP 10.139.33.244;branch=z9hG4bKac1198312375\r\n" "WWW-Authenticate: Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"\r\n" "WWW-Authenticate: Digest realm=\"example.net\", nonce=\"nothernonce\"\r\n" "Server: sipX/3.6.6 sipX/authproxy (Linux)\r\n" "Date: Wed, 18 Jul 2007 19:34:26 GMT\r\n" "Content-Length: 0\r\n" "\r\n" ); CPPUNIT_ASSERT(!serverRspTwo.getAuthenticateField(0,HttpMessage::PROXY,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(!serverRspTwo.getAuthenticateField(1,HttpMessage::PROXY,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(!serverRspTwo.getAuthenticateField(2,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(serverRspTwo.getAuthenticateField(0,HttpMessage::SERVER,value)); ASSERT_STR_EQUAL("Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"", value.data()); CPPUNIT_ASSERT(serverRspTwo.getAuthenticateField(1,HttpMessage::SERVER,value)); ASSERT_STR_EQUAL("Digest realm=\"example.net\", nonce=\"nothernonce\"", value.data()); CPPUNIT_ASSERT(!serverRspTwo.getAuthenticateField(2,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); HttpMessage proxyRspMixed( "SIP/2.0 407 Proxy Authentication Required\r\n" "From: <sip:[email protected]>;tag=1c1198308561\r\n" "To: <sip:[email protected];user=phone>\r\n" "Call-Id: [email protected]\r\n" "Cseq: 1 INVITE\r\n" "Via: SIP/2.0/UDP 10.139.4.84;branch=z9hG4bK-de2c934952294f774ee0acbc133e9b1d\r\n" "Via: SIP/2.0/UDP 10.139.33.244;branch=z9hG4bKac1198312375\r\n" "Proxy-Authenticate: Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"\r\n" "WWW-Authenticate: Digest realm=\"example.net\", nonce=\"nothernonce\"\r\n" "Server: sipX/3.6.6 sipX/authproxy (Linux)\r\n" "Date: Wed, 18 Jul 2007 19:34:26 GMT\r\n" "Content-Length: 0\r\n" "\r\n" ); CPPUNIT_ASSERT(proxyRspMixed.getAuthenticateField(0,HttpMessage::SERVER,value)); ASSERT_STR_EQUAL("Digest realm=\"example.net\", nonce=\"nothernonce\"", value.data()); CPPUNIT_ASSERT(!proxyRspMixed.getAuthenticateField(1,HttpMessage::SERVER,value)); CPPUNIT_ASSERT(value.isNull()); CPPUNIT_ASSERT(proxyRspMixed.getAuthenticateField(0,HttpMessage::PROXY,value)); ASSERT_STR_EQUAL("Digest realm=\"example.com\", nonce=\"c6c882469d27a9e9c4f75ab3fca4f7921184787266\"", value.data()); CPPUNIT_ASSERT(!proxyRspMixed.getAuthenticateField(1,HttpMessage::PROXY,value)); CPPUNIT_ASSERT(value.isNull()); }
bool SwAdminRpcExec::execute(const HttpRequestContext& requestContext, UtlSList& params, void* userData, XmlRpcResponse& response, ExecutionStatus& status) { bool result = false; status = XmlRpcMethod::FAILED; if (2 != params.entries()) { handleExtraExecuteParam(name(), response, status); } else { if (!params.at(0) || !params.at(0)->isInstanceOf(UtlString::TYPE)) { handleMissingExecuteParam(name(), PARAM_NAME_CALLING_HOST, response, status); } else { UtlString* pCallingHostname = dynamic_cast<UtlString*>(params.at(0)); SipxRpc* pSipxRpcImpl = ((SipxRpc *)userData); if (!params.at(1) || !params.at(1)->isInstanceOf(UtlString::TYPE)) { handleMissingExecuteParam(name(), PARAM_NAME_COMMAND, response, status); } else { if(validCaller(requestContext, *pCallingHostname, response, *pSipxRpcImpl, name())) { UtlBool method_result(true); UtlString arguments[3]; OsPath mWorkingDirectory = "."; OsPath mExec = SipXecsService::Path(SipXecsService::LibExecDirType,"sipxswadmin"); UtlString mStdOutFile; UtlString mStdErrFile; UtlString* pSubCommand = dynamic_cast<UtlString*>(params.at(1)); if ( !buildOutputFiles(*pSubCommand, mStdOutFile, mStdErrFile)) { // Invalid request. Set a Fault. response.setFault(SwAdminRpcMethod::FailureToLaunch, "Invalid command"); status = XmlRpcMethod::FAILED; return result; } OsPath mStdOutPath = SipXecsService::Path(SipXecsService::LogDirType, mStdOutFile.data()); OsPath mStdErrPath = SipXecsService::Path(SipXecsService::LogDirType, mStdErrFile.data()); // arguments[0] = mExec.data(); arguments[0] = pSubCommand->data(); arguments[1] = NULL; // Make sure that there is no other instance running. if (! duplicateProcess(SwAdminExec, response, status)) { // execute the command and return whether or not the launch was successful. OsProcess* swCheck = new OsProcess(); // Setup the Standard Output and Standard Error files. OsPath mStdInFile; // Blank int rc; rc = swCheck->setIORedirect(mStdInFile, mStdOutPath, mStdErrPath); // Launch the process but tell the parent to ignore the child's signals (especially on shutdown). // It will let the system handle it to avoid a defunct process. if ( (rc=swCheck->launch(mExec, &arguments[0], mWorkingDirectory, swCheck->NormalPriorityClass, FALSE, TRUE)) // Parent to ignore child signals. == OS_SUCCESS ) { // Construct and set the response. UtlSList outputPaths; outputPaths.insert(&mStdOutPath); outputPaths.insert(&mStdErrPath); // Add the file resources to Supervisor Process so they can be retrieved FileResource::logFileResource( mStdOutPath, SipxProcessManager::getInstance()->findProcess(SUPERVISOR_PROCESS_NAME)); FileResource::logFileResource( mStdErrPath, SipxProcessManager::getInstance()->findProcess(SUPERVISOR_PROCESS_NAME)); response.setResponse(&outputPaths); status = XmlRpcMethod::OK; result = true; } // launch else { // Failed to launch the command, send a fault. response.setFault(SwAdminRpcMethod::FailureToLaunch, "Failure to launch command"); status = XmlRpcMethod::FAILED; } delete swCheck; } // duplicateProcess } // validcaller else { status = XmlRpcMethod::FAILED; } } // param 1 okay } // param 0 okay } //number of parms check return result; }
bool SipXMessageObserver::handleIncomingInfoStatus(SipMessage* pSipMessage, int messageType) { OsStackTraceLogger stackLogger(FAC_SIPXTAPI, PRI_DEBUG, "SipXMessageObserver::handleIncomingInfoStatus"); if (NULL == pSipMessage) { // something went wrong return false; } SIPX_INFO hInfo = (SIPX_INFO)pSipMessage->getResponseListenerData(); if (hInfo) { SIPX_INFOSTATUS_INFO infoStatus; memset((void*) &infoStatus, 0, sizeof(SIPX_INFOSTATUS_INFO)); infoStatus.nSize = sizeof(SIPX_INFOSTATUS_INFO); infoStatus.responseCode = pSipMessage->getResponseStatusCode(); infoStatus.event = INFOSTATUS_RESPONSE; infoStatus.hInfo = hInfo; SIPX_INFO_DATA* pInfoData = sipxInfoLookup(hInfo, SIPX_LOCK_READ, stackLogger); if(pInfoData) { int statusCode = pSipMessage->getResponseStatusCode(); if (statusCode < 400) { infoStatus.status = SIPX_MESSAGE_OK; } // May want to add special case for authentication //else if(statusCode == HTTP_PROXY_UNAUTHORIZED_CODE || statusCode == HTTP_UNAUTHORIZED_CODE) //{ // infoStatus.status = //} else if (statusCode < 500) { infoStatus.status = SIPX_MESSAGE_FAILURE; } else if (statusCode < 600) { infoStatus.status = SIPX_MESSAGE_SERVER_FAILURE; } else { infoStatus.status = SIPX_MESSAGE_GLOBAL_FAILURE; } UtlString sResponseText; pSipMessage->getResponseStatusText(&sResponseText); infoStatus.szResponseText = sResponseText.data(); UtlVoidPtr* ptr = NULL; OsLock eventLock(*g_pEventListenerLock) ; UtlSListIterator eventListenerItor(*g_pEventListeners); while ((ptr = (UtlVoidPtr*) eventListenerItor()) != NULL) { EVENT_LISTENER_DATA *pData = (EVENT_LISTENER_DATA*) ptr->getValue(); if (pData) { if(pInfoData->pInst == pData->pInst) { pData->pCallbackProc(EVENT_CATEGORY_INFO_STATUS, &infoStatus, pData->pUserData); } } else { OsSysLog::add(FAC_SIPXTAPI, PRI_ERR, "SipXMessageObserver::handleIncomingInfoStatus NULL pData in listener"); } } // I think the following is incorrect. I think this is not added as a global mssage observer, only // as an obsever to individual transactions when the INFO is sent. So this is not needed. pInfoData->pInst->pSipUserAgent->removeMessageObserver(*(this->getMessageQueue()), (void*)hInfo); // release lock sipxInfoReleaseLock(pInfoData, SIPX_LOCK_READ, stackLogger); } // If an INFO was resent with auth credentials, don't remove the INFO object. Wait // for the response to the resend. if(messageType != SipMessageEvent::AUTHENTICATION_RETRY) { // info message has been handled, so go ahead and delete the object sipxInfoObjectFree(hInfo); } } return true; }