void testNoHooks() { OsConfigDb configuration; configuration.set("NOHOOKS_NOTPASSED_HOOK_LIBRARY.Error", PLUGIN_LIB_DIR "libfoo" PLUGIN_EXT); configuration.set("NOHOOKS_OTHERPARAM", "DummyValue"); // there are no hooks configured for this prefix PluginHooks testPlugins("getTestPlugin", "NOHOOKS_PASSED"); testPlugins.readConfig(configuration); PluginIterator shouldBeEmpty(testPlugins); UtlString name; // confirm that there are no hooks configured. CPPUNIT_ASSERT(shouldBeEmpty.next(&name) == NULL); CPPUNIT_ASSERT(name.isNull()); CPPUNIT_ASSERT(shouldBeEmpty.next() == NULL); }
UtlBoolean SipDialog::isTransactionRemotelyInitiated(const UtlString& callId, const UtlString& fromTag, const UtlString& toTag) const { UtlBoolean isRemoteDialog = FALSE; if(callId.compareTo(*this, UtlString::ignoreCase) == 0) { if((toTag.compareTo(mLocalTag, UtlString::ignoreCase) == 0 || toTag.isNull() || mLocalTag.isNull()) && fromTag.compareTo(mRemoteTag, UtlString::ignoreCase) == 0 || mRemoteTag.isNull()) // If this is remotely initiated fromTag // cannot be a null string. mRemoteTag can be a null string // as occurs when a remotely initiated NOTIFY is received // before the SUBSCRIBE response is received. { isRemoteDialog = TRUE; } } return(isRemoteDialog); }
// Activate the escape mechanisms, if the right conditions are present. // One is the time-out timer, which if it expires, will transfer // the call back to the user that parked it. // The other is the escape keycode, which lets the user transfer the call back. // Neither mechanism is activated if there is no parker URI to transfer back // to. Both need appropriate configuration items in the orbits.xml file // to be activated. void ParkedCallObject::startEscapeTimer(UtlString& parker, int timeout, int keycode) { OsSysLog::add(FAC_PARK, PRI_DEBUG, "ParkedCallObject::startEscapeTimer callId = '%s', " "parker = '%s', timeout = %d, keycode = %d", mOriginalCallId.data(), parker.data(), timeout, keycode); // First, check that there is a parker URI. If not, none of these // mechanisms can function. if (parker.isNull()) { return; } // Here, we can insert further validation, such as that the parker URI // is local. // Save the parker URI. mParker = parker; if (timeout != OrbitData::NO_TIMEOUT) { // Set the timeout timer. OsTime timeoutOsTime(timeout, 0); // Use a periodic timer, so if the transfer generated by one timeout // fails, we will try again later. mTimeoutTimer.periodicEvery(timeoutOsTime, timeoutOsTime); } // Remember the keycode for escaping, if any. mKeycode = keycode; if (mKeycode != OrbitData::NO_KEYCODE) { // Register the DTMF listener. // The "interdigit timeout" time of 1 is just a guess. // Enable keyup events, as those are the ones we will act on. mpCallManager->enableDtmfEvent(mOriginalCallId.data(), 1, &mDtmfEvent, false); } }
/// Retrieve the User PIN check values for a given identity and realm UtlBoolean CredentialDB::getUserPin ( const Url& uri, const UtlString& realm, UtlString& userid, UtlString& pintoken, UtlString& authType ) const { UtlBoolean found = FALSE; UtlString identity; uri.getIdentity(identity); // Match the row and return the passtoken and authtype if ( !identity.isNull() && (m_pFastDB != NULL) ) { // Thread Local Storage m_pFastDB->attach(); dbCursor< CredentialRow > cursor; dbQuery query; query="np_identity=",identity, \ "and realm=",realm, \ "order by np_identity asc, realm asc"; if ( cursor.select( query ) > 0 ) { do { userid = cursor->userid; pintoken = cursor->pintoken; authType = cursor->authtype; found = TRUE; } while ( cursor.next() ); } // Commit rows to memory - multiprocess workaround m_pFastDB->detach(0); } return found; }
/// Get the caller alias for this combination of caller identity and target domain. bool CallerAliasDB::getCallerAlias ( const UtlString& identity, ///< identity of caller in 'user@domain' form (no scheme) const UtlString& domain, /**< domain and optional port for target * ( 'example.com' or 'example.com:5099' ) */ UtlString& callerAlias /// returned alias ) const { /* * This first looks in the database for an exact match of identity and domain; * if this match is found, the resulting alias is returned in callerAlias. * If no exact match is found, the database is then checked for a row containing * a null (empty string) identity and the domain; this is a domain wildcard entry * and it is returned in callerAlias. * If neither match is found, callerAlias is set to the null string. */ callerAlias.remove(0); if (mpFastDB) { // Thread Local Storage mpFastDB->attach(); // Search to see if we have a row with this exact combination dbQuery exactQuery; exactQuery="identity=",identity.data()," and domain=",domain.data(); dbCursor< CallerAliasRow > exactCursor; if (exactCursor.select(exactQuery)) { // found a match callerAlias.append(exactCursor->alias); } // Commit the rows to memory - multiprocess workaround mpFastDB->detach(0); } // Returns true if an alias was found for this caller, false if not return ! callerAlias.isNull(); }
void XCpCall::destroySipConnection(const SipDialog& sSipDialog) { UtlString sSipCallId; { // check that we really have connection with given sip dialog OsLock lock(m_memberMutex); if (m_pSipConnection && m_pSipConnection->compareSipDialog(sSipDialog) != SipDialog::DIALOG_MISMATCH) { // dialog matches sSipDialog.getCallId(sSipCallId); m_pSipConnection->acquireExclusive(); delete m_pSipConnection; m_pSipConnection = NULL; } } if (!sSipCallId.isNull()) { // we destroyed some connection, notify call stack onConnectionRemoved(sSipCallId); } }
void SipLine::setIdentityAndUrl(Url identity, Url userEnteredUrl) { UtlString identityHost; UtlString address; int identityPort; mIdentity = identity; mLineId.remove(0); generateLineID(mLineId); mUserEnteredUrl = userEnteredUrl; //construct a complete url from identity and userEntered Url. mCanonicalUrl = mUserEnteredUrl; mUserEnteredUrl.getHostAddress(address); if (address.isNull()) { mIdentity.getHostAddress(identityHost); identityPort = mIdentity.getHostPort(); mCanonicalUrl.setHostAddress(identityHost); mCanonicalUrl.setHostPort(identityPort); } }
UtlBoolean ExtensionDB::getUri ( const UtlString& extension, Url& rUri ) const { UtlBoolean found = FALSE; if ( !extension.isNull() && (m_pFastDB != NULL) ) { // Thread Local Storage m_pFastDB->attach(); dbQuery query; // Primary Key is the uriExtension's identity query="extension=",extension; // Search to see if we have a Credential Row dbCursor< ExtensionRow > cursor; // new style extensions have a domain specifier // we can only return true here if we have one unique // row, if there are > 1 rows then we have the same extension // used in multiple domains if ( cursor.select(query) == 1 ) { // should only be row do { // The serialized vrsion of the uri // is compatible with the Uri constructor rUri = cursor->uri; } while ( cursor.next() ); found = TRUE; } // Commit the rows to memory - multiprocess workaround m_pFastDB->detach(0); } return found; }
TaoStatus TaoListenerManager::addEventListener(TaoMessage& rMsg) { UtlString terminalName; TaoString str(rMsg.getArgList(), TAOMESSAGE_DELIMITER); terminalName = str[0]; if (terminalName.isNull() || 0 == terminalName.compareTo("0.0.0.0")) { if (mListenerCnt <= 0) { terminalName = "127.0.0.1"; osPrintf("WARNING - TaoListenerManager::addEventListener: using invalid host, replaced with %s\n", terminalName.data()); } else { osPrintf("WARNING - TaoListenerManager::addEventListener: using invalid host %s, listener not added.\n", terminalName.data()); return TAO_FAILURE; } } return addEventListener(terminalName.data(), FALSE); }
void testManipulators() { NetAttributeTokenizer a("Basic realm = \"/root/subdir\", ddd=\"no end quote"); UtlString name; UtlString value; a.getNextAttribute(name, value); CPPUNIT_ASSERT_MESSAGE("no value given", value.isNull()); CPPUNIT_ASSERT_MESSAGE("first key", name.compareTo("Basic") == 0); a.getNextAttribute(name, value); CPPUNIT_ASSERT_MESSAGE("escaped value test 1", value.compareTo("/root/subdir") == 0); CPPUNIT_ASSERT_MESSAGE("2nd key", name.compareTo("realm") == 0); a.getNextAttribute(name, value); CPPUNIT_ASSERT_MESSAGE("graceful handle of no end quote", value.compareTo("no end quote") == 0); CPPUNIT_ASSERT_MESSAGE("3rd key", name.compareTo("ddd") == 0); NetAttributeTokenizer b("ab =\"bunch\\\' \\\" of escaped \\\\\\\' quotes\\\\\""); b.getNextAttribute(name, value); CPPUNIT_ASSERT_MESSAGE("parade of toothpicks", value.compareTo("bunch\\\' \\\" of escaped \\\\\\\' quotes\\\\") == 0); CPPUNIT_ASSERT_MESSAGE("toothpicks's key value", name.compareTo("ab") == 0); }
/// expireAllBindings for this URI as of 1 second before timeNow void RegistrationDB::expireAllBindings( const Url& uri ,const UtlString& callid ,const int& cseq ,const int& timeNow ,const UtlString& primary ,const Int64& update_number ) { UtlString identity; uri.getIdentity(identity); int expirationTime = timeNow-1; if ( !identity.isNull() && ( m_pFastDB != NULL ) ) { SMART_DB_ACCESS; dbCursor< RegistrationRow > cursor(dbCursorForUpdate); dbQuery query; query="np_identity=",identity," and expires>=",expirationTime; if (cursor.select(query) > 0) { do { cursor->expires = expirationTime; cursor->callid = callid; cursor->cseq = cseq; cursor->primary = primary; cursor->update_number = update_number; cursor.update(); } while ( cursor.next() ); } } else { OsSysLog::add(FAC_DB, PRI_CRIT, "RegistrationDB::expireAllBindings failed - no DB"); } }
void SipXecsService::setLogPriority(const OsConfigDb& configSettings, // configuration data const char* servicePrefix, /* the string "_LOG_LEVEL" is * appended to this prefix to * find the config directive that * sets the level */ OsSysLogPriority defaultLevel // default default is "NOTICE" ) { UtlString logLevel; UtlString logLevelTag(servicePrefix); logLevelTag.append(LogLevelSuffix); configSettings.get(logLevelTag, logLevel); OsSysLogPriority priority; if ( logLevel.isNull() ) { OsSysLog::add(FAC_KERNEL,PRI_WARNING, "SipXecsService::setLogPriority: %s not found, using '%s'", logLevelTag.data(), OsSysLog::priorityName(defaultLevel) ); priority = defaultLevel; } else if ( ! OsSysLog::priority(logLevel.data(), priority)) { OsSysLog::add(FAC_KERNEL,PRI_ERR, "SipXecsService::setLogPriority: %s value '%s' is invalid, using '%s'", logLevelTag.data(), logLevel.data(), OsSysLog::priorityName(defaultLevel) ); priority = defaultLevel; } OsSysLog::setLoggingPriority(priority); }
UtlBoolean SipRefreshManager::getInitialExpiration(const SipMessage& sipRequest, int& expirationPeriod) { UtlString method; UtlBoolean foundExpiration = FALSE; sipRequest.getRequestMethod(&method); if(method.compareTo(SIP_REGISTER_METHOD) == 0) { // Register could have it in the Contact header UtlString requestContactValue; if(sipRequest.getContactEntry(0 , &requestContactValue)) { // Get the expires parameter for the contact if it exists Url contactUri(requestContactValue); UtlString contactExpiresParameter; if(contactUri.getFieldParameter(SIP_EXPIRES_FIELD, contactExpiresParameter) && !contactExpiresParameter.isNull()) { foundExpiration = TRUE; // Convert to int expirationPeriod = atoi(contactExpiresParameter); } } } if(!foundExpiration) { // Not sure if we care if this is a request or response foundExpiration = sipRequest.getExpiresField(&expirationPeriod); } return(foundExpiration); }
void UserLocationDB::removeRows ( const Url& identityUri ) { UtlString identityStr; identityUri.getIdentity(identityStr); if ( !identityStr.isNull() && ( m_pFastDB != NULL ) ) { // Thread Local Storage m_pFastDB->attach(); dbCursor< UserLocationRow > cursor(dbCursorForUpdate); dbQuery query; query="identity=",identityStr; if ( cursor.select( query ) > 0 ) { cursor.removeAllSelected(); } // Commit rows to memory - multiprocess workaround m_pFastDB->detach(0); } return; }
UtlBoolean ExtensionDB::getExtension ( const Url& uri, UtlString& rExtesnion ) const { UtlBoolean found = FALSE; UtlString identity; uri.getIdentity(identity); if ( !identity.isNull() && (m_pFastDB != NULL) ) { // Thread Local Storage m_pFastDB->attach(); dbQuery query; // Primary Key is the uriExtension's identity query="np_identity=",identity; // Search to see if we have a Credential Row dbCursor< ExtensionRow > cursor; if ( cursor.select(query) > 0 ) { // should only be row do { rExtesnion = cursor->extension; } while ( cursor.next() ); found = TRUE; } // Commit the rows to memory - multiprocess workaround m_pFastDB->detach(0); } return found; }
// // The main entry point to the sipXpark // int main(int argc, char* argv[]) { // Block all signals in this the main thread. // Any threads created from now on will have all signals masked. OsTask::blockSignals(); // Create a new task to wait for signals. Only that task // will ever see a signal from the outside. SignalTask* signalTask = new SignalTask(); signalTask->start(); // Configuration Database (used for OsSysLog) OsConfigDb configDb; 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) { osPrintf("Version: %s (%s)\n", SIPX_VERSION, SIPX_BUILD); return(1); } else { osPrintf("usage: %s [-v]\nwhere:\n -v provides the software version\n", argv[0]); return(1); } } // Load configuration file file OsPath workingDirectory; if (OsFileSystem::exists(CONFIG_ETC_DIR)) { workingDirectory = CONFIG_ETC_DIR; OsPath path(workingDirectory); path.getNativePath(workingDirectory); } else { OsPath path; OsFileSystem::getWorkingDirectory(path); path.getNativePath(workingDirectory); } UtlString fileName = workingDirectory + OsPathBase::separator + CONFIG_SETTINGS_FILE; if (configDb.loadFromFile(fileName) != OS_SUCCESS) { exit(1); } // Initialize log file initSysLog(&configDb); // Read the user agent parameters from the config file. int UdpPort; if (configDb.get(CONFIG_SETTING_UDP_PORT, UdpPort) != OS_SUCCESS) UdpPort = PARK_DEFAULT_UDP_PORT; int TcpPort; if (configDb.get(CONFIG_SETTING_TCP_PORT, TcpPort) != OS_SUCCESS) TcpPort = PARK_DEFAULT_TCP_PORT; int RtpBase; if (configDb.get(CONFIG_SETTING_RTP_PORT, RtpBase) != OS_SUCCESS) RtpBase = DEFAULT_RTP_PORT; UtlString bindIp; if (configDb.get(CONFIG_SETTING_BIND_IP, bindIp) != OS_SUCCESS || !OsSocket::isIp4Address(bindIp)) bindIp = PARK_DEFAULT_BIND_IP; int MaxSessions; if (configDb.get(CONFIG_SETTING_MAX_SESSIONS, MaxSessions) != OS_SUCCESS) { MaxSessions = DEFAULT_MAX_SESSIONS; } UtlBoolean OneButtonBLF = configDb.getBoolean(CONFIG_SETTING_ONE_BUTTON_BLF, DEFAULT_ONE_BUTTON_BLF); UtlString domain; UtlString realm; UtlString user; SipLine* line = NULL; SipLineMgr* lineMgr = NULL; OsConfigDb domainConfiguration; OsPath domainConfigPath = SipXecsService::domainConfigPath(); if (OS_SUCCESS == domainConfiguration.loadFromFile(domainConfigPath.data())) { domainConfiguration.get(SipXecsService::DomainDbKey::SIP_DOMAIN_NAME, domain); domainConfiguration.get(SipXecsService::DomainDbKey::SIP_REALM, realm); if (!domain.isNull() && !realm.isNull()) { CredentialDB* credentialDb; if ((credentialDb = CredentialDB::getInstance())) { Url identity; identity.setUserId(PARK_SERVER_ID_TOKEN); identity.setHostAddress(domain); UtlString ha1_authenticator; UtlString authtype; if (credentialDb->getCredential(identity, realm, user, ha1_authenticator, authtype)) { if ((line = new SipLine( identity // user entered url ,identity // identity url ,user // user ,TRUE // visible ,SipLine::LINE_STATE_PROVISIONED ,TRUE // auto enable ,FALSE // use call handling ))) { if ((lineMgr = new SipLineMgr())) { if (lineMgr->addLine(*line)) { if (lineMgr->addCredentialForLine( identity, realm, user, ha1_authenticator ,HTTP_DIGEST_AUTHENTICATION ) ) { OsSysLog::add(LOG_FACILITY, PRI_INFO, "Added identity '%s': user='******' realm='%s'" ,identity.toString().data(), user.data(), realm.data() ); } else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Error adding identity '%s': user='******' realm='%s'\n" " escape and timeout from park may not work.", identity.toString().data(), user.data(), realm.data() ); } lineMgr->setDefaultOutboundLine(identity); } // end addLine else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "addLine failed: " " escape and timeout from park may not work." ); } } else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Constructing SipLineMgr failed: " " escape and timeout from park may not work." ); } } // end new SipLine else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Constructing SipLine failed: " " escape and timeout from park may not work." ); } } // end getCredential else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "No credential found for '%s@%s' in realm '%s'" "; transfer functions will not work", PARK_SERVER_ID_TOKEN, domain.data(), realm.data() ); } credentialDb->releaseInstance(); } // end credentialDB else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Failed to open credentials database" "; transfer functions will not work" ); } } // end have domain and realm else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Domain or Realm not configured:" "\n '%s' : '%s'\n '%s' : '%s'" " transfer functions will not work.", SipXecsService::DomainDbKey::SIP_DOMAIN_NAME, domain.data(), SipXecsService::DomainDbKey::SIP_REALM, realm.data() ); } } // end found domain config else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "main: failed to load domain configuration from '%s'", domainConfigPath.data() ); } // Read Park Server parameters from the config file. int Lifetime, BlindXferWait, KeepAliveTime, ConsXferWait; if (configDb.get(CONFIG_SETTING_LIFETIME, Lifetime) != OS_SUCCESS) { Lifetime = DEFAULT_LIFETIME; } if (configDb.get(CONFIG_SETTING_BLIND_WAIT, BlindXferWait) != OS_SUCCESS) { BlindXferWait = DEFAULT_BLIND_WAIT; } if (configDb.get(CONFIG_SETTING_KEEPALIVE_TIME, KeepAliveTime) != OS_SUCCESS) { KeepAliveTime = DEFAULT_KEEPALIVE_TIME; } // This is not configurable, as consultative transfers should // succeed or fail immediately. ConsXferWait = CONS_XFER_WAIT; // Bind the SIP user agent to a port and start it up SipUserAgent* userAgent = new SipUserAgent(TcpPort, UdpPort, TcpPort+1, NULL, // publicAddress user.isNull() ? NULL : user.data(), // default user bindIp, domain.isNull() ? NULL : domain.data(), // outbound proxy NULL, // sipDirectoryServers (deprecated) NULL, // sipRegistryServers (deprecated) NULL, // authenticationScheme NULL, // authenicateRealm NULL, // authenticateDb NULL, // authorizeUserIds (deprecated) NULL, // authorizePasswords (deprecated) lineMgr ); userAgent->setUserAgentHeaderProperty("sipXecs/park"); userAgent->start(); if (!userAgent->isOk()) { OsSysLog::add(LOG_FACILITY, PRI_EMERG, "SipUserAgent failed to initialize, requesting shutdown"); gShutdownFlag = TRUE; } // Read the list of codecs from the configuration file. SdpCodecFactory codecFactory; initCodecs(&codecFactory, &configDb); // Initialize and start up the media subsystem mpStartUp(MP_SAMPLE_RATE, MP_SAMPLES_PER_FRAME, 6 * MaxSessions, &configDb); MpMediaTask::getMediaTask(MaxSessions); #ifdef INCLUDE_RTCP CRTCManager::getRTCPControl(); #endif //INCLUDE_RTCP mpStartTasks(); // Instantiate the call processing subsystem UtlString localAddress; int localPort ; userAgent->getLocalAddress(&localAddress, &localPort) ; if (localAddress.isNull()) OsSocket::getHostIp(&localAddress); // Construct an address to be used in outgoing requests (primarily // INVITEs stimulated by REFERs). UtlString outgoingAddress; { char buffer[100]; sprintf(buffer, "sip:sipXpark@%s:%d", localAddress.data(), portIsValid(UdpPort) ? UdpPort : TcpPort); outgoingAddress = buffer; } CallManager callManager(FALSE, NULL, TRUE, // early media in 180 ringing &codecFactory, RtpBase, // rtp start RtpBase + (2 * MaxSessions), // rtp end localAddress, localAddress, userAgent, 0, // sipSessionReinviteTimer NULL, // mgcpStackTask outgoingAddress, // defaultCallExtension Connection::RING, // availableBehavior NULL, // unconditionalForwardUrl -1, // forwardOnNoAnswerSeconds NULL, // forwardOnNoAnswerUrl Connection::BUSY, // busyBehavior NULL, // sipForwardOnBusyUrl NULL, // speedNums CallManager::SIP_CALL, // phonesetOutgoingCallProtocol 4, // numDialPlanDigits CallManager::NEAR_END_HOLD, // holdType 5000, // offeringDelay "", // pLocal CP_MAXIMUM_RINGING_EXPIRE_SECONDS, // inviteExpiresSeconds QOS_LAYER3_LOW_DELAY_IP_TOS, // expeditedIpTos MaxSessions, // maxCalls sipXmediaFactoryFactory(NULL)); // CpMediaInterfaceFactory // Create a listener (application) to deal with call // processing events (e.g. incoming call and hang ups) OrbitListener listener(&callManager, Lifetime, BlindXferWait, KeepAliveTime, ConsXferWait); callManager.addTaoListener(&listener); listener.start(); // Create the SIP Subscribe Server SipPersistentSubscriptionMgr subscriptionMgr(SUBSCRIPTION_COMPONENT_PARK, domain, "subscription"); // Component for holding the subscription data SipSubscribeServerEventHandler policyHolder; // Component for granting the subscription rights SipPublishContentMgr publisher; // Component for publishing the event contents SipSubscribeServer subscribeServer(*userAgent, publisher, subscriptionMgr, policyHolder); subscribeServer.enableEventType(DIALOG_EVENT_TYPE); subscribeServer.start(); // Create the DialogEventPublisher. // Use the sipX domain as the hostport of resource-IDs of the // published events, as that will be the request-URIs of SUBSCRIBEs. DialogEventPublisher dialogEvents(&callManager, &publisher, domain, PORT_NONE, OneButtonBLF); callManager.addTaoListener(&dialogEvents); dialogEvents.start(); // Start up the call processing system callManager.start(); // Loop forever until signaled to shut down int numTwoSecIntervals = 0; int CleanLoopWaitTimeSecs = 10; while (!gShutdownFlag) { OsTask::delay(2000); if (2*numTwoSecIntervals >= CleanLoopWaitTimeSecs) { numTwoSecIntervals = 0; if (OsSysLog::willLog(FAC_PARK, PRI_DEBUG)) { OsSysLog::add(LOG_FACILITY, PRI_DEBUG, "park main " "logging call status" ); callManager.printCalls(0) ; listener.dumpCallsAndTransfers(); } } else { numTwoSecIntervals += 1; } } // Flush the log file OsSysLog::flush(); // Say goodnight Gracie... return 0; }
// Initialize the OsSysLog void initSysLog(OsConfigDb* pConfig) { UtlString logLevel; // Controls Log Verbosity UtlString consoleLogging; // Enable console logging by default? UtlString fileTarget; // Path to store log file. UtlBoolean bSpecifiedDirError ; // Set if the specified log dir does not // exist OsSysLog::initialize(0, "sipxpark"); OsSysLog::add(FAC_SIP, PRI_INFO, ">>>>>>>>>>>>>>>> Starting - version %s build %s", SIPX_VERSION, SIPX_BUILD ); // // Get/Apply Log Filename // fileTarget.remove(0); if ((pConfig->get(CONFIG_SETTING_LOG_DIR, fileTarget) != OS_SUCCESS) || fileTarget.isNull() || !OsFileSystem::exists(fileTarget)) { bSpecifiedDirError = !fileTarget.isNull(); // If the log file directory exists use that, otherwise place the log // in the current directory OsPath workingDirectory; if (OsFileSystem::exists(CONFIG_LOG_DIR)) { fileTarget = CONFIG_LOG_DIR; OsPath path(fileTarget); path.getNativePath(workingDirectory); osPrintf("%s : %s\n", CONFIG_SETTING_LOG_DIR, workingDirectory.data()); OsSysLog::add(LOG_FACILITY, PRI_INFO, "%s : %s", CONFIG_SETTING_LOG_DIR, workingDirectory.data()); } else { OsPath path; OsFileSystem::getWorkingDirectory(path); path.getNativePath(workingDirectory); osPrintf("%s : %s\n", CONFIG_SETTING_LOG_DIR, workingDirectory.data()); OsSysLog::add(LOG_FACILITY, PRI_INFO, "%s : %s", CONFIG_SETTING_LOG_DIR, workingDirectory.data()); } fileTarget = workingDirectory + OsPathBase::separator + CONFIG_LOG_FILE; } else { bSpecifiedDirError = false; osPrintf("%s : %s\n", CONFIG_SETTING_LOG_DIR, fileTarget.data()); OsSysLog::add(LOG_FACILITY, PRI_INFO, "%s : %s", CONFIG_SETTING_LOG_DIR, fileTarget.data()); fileTarget = fileTarget + OsPathBase::separator + CONFIG_LOG_FILE; } OsSysLog::setOutputFile(0, fileTarget); // // Get/Apply Log Level // SipXecsService::setLogPriority(*pConfig, CONFIG_SETTING_PREFIX, PRI_ERR); OsSysLog::setLoggingPriorityForFacility(FAC_SIP_INCOMING_PARSED, PRI_ERR); // // Get/Apply console logging // UtlBoolean bConsoleLoggingEnabled = false; if ((pConfig->get(CONFIG_SETTING_LOG_CONSOLE, consoleLogging) == OS_SUCCESS)) { consoleLogging.toUpper(); if (consoleLogging == "ENABLE") { OsSysLog::enableConsoleOutput(true); bConsoleLoggingEnabled = true; } } osPrintf("%s : %s\n", CONFIG_SETTING_LOG_CONSOLE, bConsoleLoggingEnabled ? "ENABLE" : "DISABLE") ; OsSysLog::add(LOG_FACILITY, PRI_INFO, "%s : %s", CONFIG_SETTING_LOG_CONSOLE, bConsoleLoggingEnabled ? "ENABLE" : "DISABLE") ; if (bSpecifiedDirError) { OsSysLog::add(FAC_LOG, PRI_CRIT, "Cannot access %s directory; please check configuration.", CONFIG_SETTING_LOG_DIR); } }
//! Generate the HttpBody for the current state of the resource list. HttpBody* ResourceList::generateRlmiBody(UtlBoolean consolidated, UtlBoolean fullRlmi, UtlSList& listToSend) { if (Os::Logger::instance().willLog(FAC_RLS, PRI_DEBUG)) { UtlString l; UtlSListIterator resourcesItor(listToSend); ResourceReference* resource; while ((resource = dynamic_cast <ResourceReference*> (resourcesItor()))) { l.append(*resource->getUri()); l.append(","); } if (!l.isNull()) { l.remove(l.length() - 1); } Os::Logger::instance().log(FAC_RLS, PRI_DEBUG, "ResourceList::generateRlmiBody cons=%d URI='%s' full=%d listToSend='%s'", consolidated, (consolidated ? mResourceListNameCons.data() : mResourceListName.data()), fullRlmi, l.data()); } // Construct the multipart body. // We add the <...> here, as they are used in all the contexts where // rlmiBodyPartCid appears. UtlString rlmiBodyPartCid; rlmiBodyPartCid += "<rlmi@"; rlmiBodyPartCid += getResourceListServer()->getDomainName(); rlmiBodyPartCid += ">"; UtlString content_type(CONTENT_TYPE_MULTIPART_RELATED ";type=\"" RLMI_CONTENT_TYPE "\"" ";start=\""); content_type += rlmiBodyPartCid; content_type += "\""; HttpBody* body = new HttpBodyMultipart(content_type); // This is the Resource List Meta-Information, XML describing the resources // and their instances. It is the main part of the NOTIFY body. UtlString rlmi; // Generate the initial part of the RLMI. rlmi += "<?xml version=\"1.0\"?>\r\n"; rlmi += "<list xmlns=\"" RLMI_XMLNS "\" uri=\""; XmlEscape(rlmi, consolidated ? mResourceListNameCons : mResourceListName); // Placeholder for version from SIP stack. rlmi += "\" version=\"" VERSION_PLACEHOLDER "\" "; // Generate either the full or the partial RLMI. if (fullRlmi) { rlmi += "fullState=\"true\">\r\n"; } else { rlmi += "fullState=\"false\">\r\n"; } // If we implemented names for resource lists, <name> elements would be added here. // Iterate through the resources. UtlSListIterator resourcesItor(listToSend); ResourceReference* resource; while ((resource = dynamic_cast <ResourceReference*> (resourcesItor()))) { // Add the content for the resource. resource->generateBody(rlmi, *body, consolidated); } // Generate the postamble for the resource list. rlmi += "</list>\r\n"; // Construct the RLMI body part. HttpBody rlmi_body(rlmi.data(), rlmi.length(), RLMI_CONTENT_TYPE); UtlDList rlmi_body_parameters; rlmi_body_parameters.append(new NameValuePair(HTTP_CONTENT_ID_FIELD, rlmiBodyPartCid)); // Attach the RLMI. body->appendBodyPart(rlmi_body, rlmi_body_parameters); // Clean up the parameter list. rlmi_body_parameters.destroyAll(); return body; }
OsStatus DialByNameDB::load() const { // Critical Section here OsLock lock( sLockMutex ); OsStatus result = OS_SUCCESS; if ( m_pFastDB != NULL ) { // Clean out the existing DB rows before loading // a new set from persistent storage removeAllRows (); // Query all Identities with 'AutoAttendant' permission set PermissionDB * pPermissionDB = PermissionDB::getInstance(); ResultSet permissionsResultSet; pPermissionDB->getIdentities ( "AutoAttendant", permissionsResultSet ); CredentialDB * pCredentialDB = CredentialDB::getInstance(); ResultSet credentialsResultSet; UtlString identity, permission; int numAutoAttendees = permissionsResultSet.getSize(); for (int index = 0; index < numAutoAttendees; index++) { // get the next identity UtlString identityKey("identity"); UtlHashMap record; permissionsResultSet.getIndex( index, record ); UtlString identity = *((UtlString*)record.findValue(&identityKey)); Url identityUrl (identity); pCredentialDB-> getAllCredentials ( identityUrl, credentialsResultSet ); // we should only have one credential! we're // only interested in the uri column's display name if ( credentialsResultSet.getSize() == 1) { UtlString uriKey("uri"); UtlHashMap record; credentialsResultSet.getIndex( 0, record ); UtlString uri = *((UtlString*)record.findValue(&uriKey)); // must have a display name present before inserting a row // @TODO convert to url and get display name UtlHashMap nvPairs; if (!uri.isNull()) { // Null Element value create a special // char string we have key and value so insert UtlString* contactValue = new UtlString( uri ); // Memory Leak fixes, make shallow copies of static keys UtlString* contactKey = new UtlString( gNp_contactKey ); nvPairs.insertKeyAndValue ( contactKey, contactValue ); } // Insert the item row into the IMDB insertRow ( nvPairs ); } } // Reset the changed flags after a successful load SIPDBManager::getInstance()-> setDatabaseChangedFlag("credential", FALSE); SIPDBManager::getInstance()-> setDatabaseChangedFlag("permission", FALSE); } else { result = OS_FAILED; } return result; }
UtlBoolean SipRegistrar::handleMessage( OsMsg& eventMessage ) { UtlBoolean handled = FALSE; int msgType = eventMessage.getMsgType(); int msgSubType = eventMessage.getMsgSubType(); if ( (msgType == OsMsg::PHONE_APP) && (msgSubType == SipMessage::NET_SIP_MESSAGE) ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage()" " Start processing SIP message") ; const SipMessage* message = ((SipMessageEvent&)eventMessage).getMessage(); UtlString callId; if ( message ) { message->getCallIdField(&callId); UtlString method; message->getRequestMethod(&method); if ( !message->isResponse() ) // is a request ? { if ( method.compareTo(SIP_REGISTER_METHOD) == 0 ) { //send to Register Thread sendToRegistrarServer(eventMessage); } else if ( method.compareTo(SIP_OPTIONS_METHOD) == 0 ) { UtlString requestUri; message->getRequestUri(&requestUri); // Check if the OPTIONS request URI is addressed to a user or // to the domain. if (!requestUri.contains("@")) { UtlString contentEncoding; message->getContentEncodingField(&contentEncoding); UtlString disallowedExtensions; int extensionIndex = 0; UtlString extension; disallowedExtensions.remove(0); while(message->getRequireExtension(extensionIndex, &extension)) { if(!(mSipUserAgent->isExtensionAllowed(extension.data())) ) { if(!disallowedExtensions.isNull()) { disallowedExtensions.append(SIP_MULTIFIELD_SEPARATOR); disallowedExtensions.append(SIP_SINGLE_SPACE); } disallowedExtensions.append(extension.data()); } extensionIndex++; } //delete leading and trailing white spaces disallowedExtensions = disallowedExtensions.strip(UtlString::both); SipMessage response; // Check if the extensions are supported if(!disallowedExtensions.isNull() ) { // error response - bad extension response.setRequestBadExtension(message, disallowedExtensions); } // Check if the encoding is supported // i.e. no encoding else if(!contentEncoding.isNull()) { // error response - content encoding response.setRequestBadContentEncoding(message,""); } else { // Send an OK, the allowed field will get added to all final responses. // Options 200 response response.setResponseData(message, SIP_OK_CODE, SIP_OK_TEXT); } mSipUserAgent->send(response); } else { //OPTIONS is addressed to a user, send to redirect thread sendToRedirectServer(eventMessage); } } else { //send to redirect thread sendToRedirectServer(eventMessage); } } else { // responses are ignored. } } else { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage no message." ) ; } handled = TRUE; } else if ( OsMsg::OS_SHUTDOWN == msgType ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage shutting down all tasks"); // Do an orderly shutdown of all the various threads. if ( mSipUserAgent ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage shutting down SipUserAgent"); mSipUserAgent->shutdown(); delete mSipUserAgent ; mSipUserAgent = NULL ; } if ( mRegistrarPersist ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage shutting down RegistrarPersist"); mRegistrarPersist->requestShutdown(); delete mRegistrarPersist; mRegistrarPersist = NULL; } if ( mRedirectServer ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage shutting down RedirectServer"); mRedirectServer->requestShutdown(); delete mRedirectServer; mRedirectServer = NULL; mRedirectMsgQ = NULL; } if ( mRegistrarServer ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage shutting down RegistrarServer"); mRegistrarServer->requestShutdown(); delete mRegistrarServer; mRegistrarServer = NULL; mRegistrarMsgQ = NULL; } if ( mRegisterEventServer ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage shutting down RegisterEventServer"); delete mRegisterEventServer; mRegisterEventServer = NULL; } OsTask::requestShutdown(); // tell OsServerTask::run to exit handled = TRUE; } else { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::handleMessage unhandled type %d/%d", msgType, msgSubType ) ; } return handled; }
///////////////////////////PUBLIC/////////////////////////////////// UtlBoolean SubscribeServerThread::initialize ( SipUserAgent* sipUserAgent, int defaultSubscribePeriod, const UtlString& minExpiresTime, const UtlString& defaultDomain, const UtlBoolean& useCredentialDB, const UtlString& realm, PluginXmlParser* pluginTable) { if ( !mIsStarted ) { //start the thread start(); } if ( !minExpiresTime.isNull() ) { mMinExpiresTimeStr.append(minExpiresTime); mMinExpiresTimeint = atoi(minExpiresTime.data()); } mDefaultSubscribePeriod = defaultSubscribePeriod; if ( mMinExpiresTimeint > mDefaultSubscribePeriod ) { OsSysLog::add(FAC_SIP, PRI_ERR, "SubscribeServerThread::initialize - minimum expiration time (%d)" " > default/maximum expiration time (%d); reset to equal", mMinExpiresTimeint, mDefaultSubscribePeriod ); mMinExpiresTimeint = mDefaultSubscribePeriod; } if ( !defaultDomain.isNull() ) { mDefaultDomain.remove(0); mDefaultDomain.append( defaultDomain ); Url defaultDomainUrl( mDefaultDomain ); mDefaultDomainPort = defaultDomainUrl.getHostPort(); // the isValidDomain compares the server's domain to // that in the incoming URI, sometimes the incoming // URI is a dotted IP address. UtlString ipOrFQDNHost; defaultDomainUrl.getHostAddress(ipOrFQDNHost); // sometimes the request URI will contain // an IP Address and at others it contains a FQDN if ( OsSocket::isIp4Address( ipOrFQDNHost.data() ) ) { mDefaultDomainHostIP = ipOrFQDNHost; OsSocket::getDomainName( mDefaultDomainHostFQDN ); } else { mDefaultDomainHostFQDN = ipOrFQDNHost; OsSocket::getHostIp( &mDefaultDomainHostIP ); } } if ( !realm.isNull() ) { mRealm.remove(0); mRealm.append(realm); } mIsCredentialDB = useCredentialDB; //get sip user agent if ( sipUserAgent ) { mpSipUserAgent = sipUserAgent; } else { mpSipUserAgent = NULL; return FALSE; } //get Plugin table if ( pluginTable ) { mPluginTable = pluginTable; } else { return FALSE; } return TRUE; }
int SipUdpServer::run(void* runArg) { int cseq = 1; if(mSipUserAgent) { UtlString contact; mSipUserAgent->getContactUri(&contact); // Add a tag to the contact and build the from field UtlString from(contact); int tagRand1 = rand(); int tagRand2 = rand(); char fromTag[80]; sprintf(fromTag, ";tag=%d%d", tagRand1, tagRand2); from.append(fromTag); UtlString rawAddress; int port; Url pingUrl(mNatPingUrl); // Create a cannonized version of the ping URL in case // it does not specify "sip:", etc. UtlString cannonizedPingUrl = pingUrl.toString(); // Get the address and port in the png URL so that // we can look up the DNS stuff if needed port = pingUrl.getHostPort(); pingUrl.getHostAddress(rawAddress); // Resolve the raw address from a DNS SRV, A record // to an IP address server_t* dnsSrvRecords = SipSrvLookup::servers(rawAddress.data(), "sip", OsSocket::UDP, port); // Do a DNS SRV or A record lookup // If we started with an IP address, we will still get an IP // address in the result UtlString address; if(dnsSrvRecords[0].isValidServerT()) { // Get the highest priority address and port from the // list with randomization of those according to the // weights. // Note: we are not doing any failover here as that is // a little tricky with the NAT stuff. We cannot change // addresses with every transaction as we may get different // ports and addresses every time we send a ping. For now // we do one DNS SRV lookup at the begining of time and // stick to that result. dnsSrvRecords[0].getIpAddressFromServerT(address); port = dnsSrvRecords[0].getPortFromServerT(); // If the ping URL or DNS SRV did not specify a port // bind it to the default port. if (!portIsValid(port)) { port = SIP_PORT; } } // Did not get a valid response from the DNS lookup else { // Configured with a bad DNS name that did not resolve. // Or the DNS server did not respond. if(!rawAddress.isNull()) { OsSysLog::add(FAC_SIP, PRI_INFO, "SipUdpServer::run DNS lookup failed for ping host: %s in URI: %s", rawAddress.data(), mNatPingUrl.data()); } // Else no ping address, this means we are not supposed to // do a ping } // Free the list of server addresses. delete[] dnsSrvRecords; // Get the address to be used in the callId scoping int dummyPort; UtlString callId; if (mSipUserAgent) { mSipUserAgent->getViaInfo(OsSocket::UDP, callId, dummyPort); } // Make up a call Id long epochTime = OsDateTime::getSecsSinceEpoch(); int randNum = rand(); char callIdPrefix[80]; sprintf(callIdPrefix, "%ld%d-ping@", epochTime, randNum); callId.insert(0,callIdPrefix); while(mNatPingFrequencySeconds > 0 && !mNatPingUrl.isNull() && !mNatPingMethod.isNull() && !address.isNull()) { // Send a no-op SIP message to the // server to keep a port open through a NAT // based firewall SipMessage pingMessage; pingMessage.setRequestData(mNatPingMethod, cannonizedPingUrl.data(), from.data(), mNatPingUrl.data(), callId, cseq, contact.data()); // Get the UDP via info from the SipUserAgent UtlString viaAddress; int viaPort; if (mSipUserAgent) { mSipUserAgent->getViaInfo(OsSocket::UDP, viaAddress, viaPort); } pingMessage.addVia(viaAddress.data(), viaPort, SIP_TRANSPORT_UDP); // Mark the via so the receiver knows we support and want the // received port to be set pingMessage.setLastViaTag("", "rport"); # ifdef TEST_PRINT osPrintf("Sending ping to %s %d, From: %s\n", address.data(), port, contact.data()); # endif // Send from the same UDP port that we receive from if (mSipUserAgent) { mSipUserAgent->sendSymmetricUdp(pingMessage, address.data(), port); } cseq++; // Wait until it is time to send another ping delay(mNatPingFrequencySeconds * 1000); } } return(mNatPingFrequencySeconds); }
// Add to the HttpBody the current state of the resource. void ResourceCached::generateBody(UtlString& rlmi, HttpBody& body, UtlBoolean consolidated, const UtlString& nameXml, const UtlString& displayName) const { // Generate the preamble for the resource. rlmi += " <resource uri=\""; XmlEscape(rlmi, *(static_cast <const UtlString*> (this))); rlmi += "\">\r\n"; if (!nameXml.isNull()) { rlmi += " "; rlmi += nameXml; } if (consolidated) { // If consolidating resource instances, generate the XML for the // unified resource instance. rlmi += " <instance id=\"consolidated\" state=\"active\""; UtlString contentBodyPartCid; // Use the count of parts in 'body' to generate a unique identifier for // each part. contentBodyPartCid.appendNumber(body.getMultipartCount()); contentBodyPartCid += "@"; contentBodyPartCid += getResourceListServer()->getDomainName(); rlmi += " cid=\""; rlmi += contentBodyPartCid; rlmi += "\""; // Now add the <...> and use it in the header. contentBodyPartCid.prepend("<"); contentBodyPartCid.append(">"); // Create a single HttpBody to contain the unified dialog event. UtlString dialog_event; // XML declaration is optional, but Broadworks uses it. dialog_event += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; dialog_event += BEGIN_DIALOG_INFO; dialog_event += VERSION_EQUAL; dialog_event += "\""; // The consolidated dialog events need to have persistent // version numbers, as they all have the same instance id. // So we use a global version number in the ResourceListSet. dialog_event.appendNumber(getResourceListSet()->getVersion()); dialog_event += "\""; dialog_event += STATE_EQUAL; dialog_event += "\"full\""; dialog_event += ENTITY_EQUAL; dialog_event += "\""; dialog_event += *(static_cast <const UtlString*> (this)); dialog_event += "\">\r\n"; // Save the length of dialog_event, so we can tell later if // any <dialog>s have been added to it. unsigned int preamble_length = dialog_event.length(); // Call the ContactSet to generate the consolidated dialog event body. if (mContactSetP) { mContactSetP->generateBody(dialog_event, body, consolidated, displayName); } // If no <dialog>s have been added, we have to add a dummy // <dialog> to carry the display name. if (dialog_event.length() == preamble_length) { dialog_event += "<dialog id=\";\"><state>terminated</state><local><identity display=\""; XmlEscape(dialog_event, displayName); dialog_event += "\">"; XmlEscape(dialog_event, *(static_cast <const UtlString*> (this))); dialog_event += "</identity></local></dialog>\r\n"; } dialog_event += END_DIALOG_INFO; // Insert the consolidated dialog event body into the multiplart body. HttpBody content_body(dialog_event.data(), dialog_event.length(), DIALOG_EVENT_CONTENT_TYPE); UtlDList content_body_parameters; content_body_parameters.append( new NameValuePair(HTTP_CONTENT_ID_FIELD, contentBodyPartCid)); body.appendBodyPart(content_body, content_body_parameters); content_body_parameters.destroyAll(); // Finish the <instance> element. rlmi += "/>\r\n"; } else { // Call the ContactSet to do the work. if (mContactSetP) { mContactSetP->generateBody(rlmi, body, consolidated, displayName); } } // Generate the postamble for the resource. rlmi += " </resource>\r\n"; }
UtlBoolean CommandMsgProcessor::handleMessage(OsMsg& eventMessage) { int msgType = eventMessage.getMsgType(); // int msgSubType = eventMessage.getMsgSubType(); if(msgType == OsMsg::PHONE_APP) // && msgSubType == CP_SIP_MESSAGE) { osPrintf("CommandMsgProcessor::handleMessage Got a message\n"); int messageType = ((SipMessageEvent&)eventMessage).getMessageStatus(); const SipMessage* sipMsg = ((SipMessageEvent&)eventMessage).getMessage(); UtlString callId; if(sipMsg) { osPrintf("numRespondToMessages: %d isResponse: %d messageType: %d TransErro: %d\n", numRespondToMessages, sipMsg->isResponse(), messageType, SipMessageEvent::TRANSPORT_ERROR); if((numRespondToMessages == -1 || numRespondToMessages > 0) && !sipMsg->isResponse() && messageType != SipMessageEvent::TRANSPORT_ERROR) { osPrintf("valid message\n"); if(numRespondToMessages > 0) { numRespondToMessages--; } SipMessage response; if(mpResponseMessage) { response = *mpResponseMessage; } response.setResponseData(sipMsg, responseStatusCode, responseStatusText.data()); UtlString address; int port; UtlString protocol; UtlString tag; sipMsg->getToAddress(&address, &port, &protocol, NULL, NULL, &tag) ; if( tag.isNull()) { int tagNum = rand(); char tag[100]; sprintf(tag, "%d", tagNum); UtlString tagWithDot(tag); tagWithDot.append(".34756498567498567"); response.setToFieldTag(tagWithDot); } UtlString msgBytes; int msgLen; response.getBytes(&msgBytes, &msgLen); osPrintf("%s",msgBytes.data()); if(mpLastResponseMessage) { delete mpLastResponseMessage; mpLastResponseMessage = NULL; } // Keep a copy of the last response sent mpLastResponseMessage = new SipMessage(response); if(userAgent->send(response)) { osPrintf("Sent response\n"); } else { osPrintf("Send failed\n"); } } } } return(TRUE); }
//functions UtlBoolean SubscribeServerThread::handleMessage(OsMsg& eventMessage) { // Only handle SIP messages if (eventMessage.getMsgType() != OsMsg::PHONE_APP || eventMessage.getMsgSubType() != SipMessage::NET_SIP_MESSAGE) { return FALSE ; } const SipMessage* message = ((SipMessageEvent&)eventMessage).getMessage(); UtlString userKey; UtlString uri; SipMessage finalResponse; // Test for request/response processing code path if (!message->isResponse()) { // this is a request, so authenticate and authorize the request if ( isValidDomain( message, &finalResponse ) ) { UtlString eventPackage; UtlString id; UtlHashMap otherParams; message->getEventField(&eventPackage, &id, &otherParams); StatusPluginReference* pluginContainer = mPluginTable->getPlugin( eventPackage ); if( pluginContainer ) { //check in credential database if authentication needed UtlString authenticatedUser, authenticatedRealm; if( isAuthenticated ( message, &finalResponse, authenticatedUser, authenticatedRealm ) ) { if ( isAuthorized ( message, &finalResponse, pluginContainer ) ) { // fetch the plugin SubscribeServerPluginBase* plugin = pluginContainer->getPlugin(); if (plugin) { int timeNow = (int)OsDateTime::getSecsSinceEpoch(); int grantedExpiration; UtlString newToTag; // add the subscription to the IMDB SubscribeStatus isSubscriptionAdded = addSubscription(timeNow, message, mDefaultDomain, eventPackage, id, otherParams, newToTag, grantedExpiration); otherParams.destroyAll(); switch ( isSubscriptionAdded ) { case STATUS_SUCCESS: // create response - 202 Accepted Response finalResponse.setResponseData( message, SIP_ACCEPTED_CODE, SIP_ACCEPTED_TEXT); // Set the granted subscription time. finalResponse.setExpiresField(grantedExpiration); plugin->handleSubscribeRequest( *message, finalResponse, authenticatedUser.data(), authenticatedRealm.data(), mDefaultDomain.data()); // ensure that the contact returned will route back to here // (the default supplied by SipUserAgent will not). { UtlString requestUri; message->getRequestUri(&requestUri); finalResponse.setContactField(requestUri); } break; case STATUS_TO_BE_REMOVED: // create response - 202 Accepted Response finalResponse.setResponseData( message, SIP_ACCEPTED_CODE, SIP_ACCEPTED_TEXT); // Set the granted subscription time. finalResponse.setExpiresField(grantedExpiration); plugin->handleSubscribeRequest( *message, finalResponse, authenticatedUser.data(), authenticatedRealm.data(), mDefaultDomain.data()); // ensure that the contact returned will route back to here // (the default supplied by SipUserAgent will not). { UtlString requestUri; message->getRequestUri(&requestUri); finalResponse.setContactField(requestUri); } // Now that final NOTIFY has been sent, remove row removeSubscription(message); break; case STATUS_LESS_THAN_MINEXPIRES: // (already logged in addSubscription) // send 423 Subscription Too Brief response finalResponse.setResponseData( message, SIP_TOO_BRIEF_CODE, SIP_TOO_BRIEF_TEXT ); finalResponse.setHeaderValue( SIP_MIN_EXPIRES_FIELD, mMinExpiresTimeStr, 0 ); break; case STATUS_INVALID_REQUEST: OsSysLog::add(FAC_SIP, PRI_ERR, "SubscribeServerThread::handleMessage()" "Subscription Could Not Be Added " SIP_BAD_REQUEST_TEXT ); finalResponse.setResponseData( message, SIP_BAD_REQUEST_CODE, SIP_BAD_REQUEST_TEXT ); break; case STATUS_FORBIDDEN: OsSysLog::add(FAC_SIP, PRI_ERR, "SubscribeServerThread::handleMessage()" "Subscription Could Not Be Added " SIP_FORBIDDEN_TEXT ); finalResponse.setResponseData( message, SIP_FORBIDDEN_CODE, SIP_FORBIDDEN_TEXT); break; case STATUS_NOT_FOUND: OsSysLog::add(FAC_SIP, PRI_ERR, "SubscribeServerThread::handleMessage()" "Subscription Could Not Be Added " SIP_NOT_FOUND_TEXT ); finalResponse.setResponseData( message, SIP_NOT_FOUND_CODE, SIP_NOT_FOUND_TEXT ); break; case STATUS_BAD_SUBSCRIPTION: // send 481 Subscription Does Not Exist response OsSysLog::add(FAC_SIP, PRI_DEBUG, "SubscribeServerThread::handleMessage()" "Subscription to be renewed does not exist " SIP_BAD_SUBSCRIPTION_TEXT ); finalResponse.setResponseData( message, SIP_BAD_SUBSCRIPTION_CODE, SIP_BAD_SUBSCRIPTION_TEXT ); break; case STATUS_INTERNAL_ERROR: default: OsSysLog::add(FAC_SIP, PRI_ERR, "SubscribeServerThread::handleMessage()" "Subscription Could Not Be Added " "Status %d from addSubscription", isSubscriptionAdded ); finalResponse.setResponseData( message, SIP_SERVER_INTERNAL_ERROR_CODE, "Subscription database error" ); } // Apply the new to-tag, if any, to the response. if (!newToTag.isNull()) { finalResponse.setToFieldTag(newToTag); } } else { OsSysLog::add(FAC_SIP, PRI_CRIT, "SubscribeServerThread::handleMessage()" " container->getPlugin failed for '%s'", eventPackage.data() ); finalResponse.setResponseData( message, SIP_SERVER_INTERNAL_ERROR_CODE, SIP_SERVER_INTERNAL_ERROR_TEXT ); } } else { // not authorized - the response was created in isAuthorized } } else { // not authenticated - the response was created in isAuthenticated } } else // no plugin found for this event type { OsSysLog::add(FAC_SIP, PRI_WARNING, "SubscribeServerThread::handleMessage()" " Request denied - " SIP_BAD_EVENT_TEXT ); finalResponse.setResponseData( message, SIP_BAD_EVENT_CODE, "Event type not supported" ); } // send final response UtlString finalMessageStr; ssize_t finalMessageLen; finalResponse.getBytes(&finalMessageStr, &finalMessageLen); OsSysLog::add(FAC_SIP, PRI_DEBUG, "\n----------------------------------\n" "Sending final response\n%s",finalMessageStr.data()); mpSipUserAgent->setUserAgentHeader( finalResponse ); mpSipUserAgent->send( finalResponse ); } else // Invalid domain { const char* notFoundMsg = SIP_NOT_FOUND_TEXT " Invalid Domain"; finalResponse.setResponseData(message, SIP_NOT_FOUND_CODE, notFoundMsg ); mpSipUserAgent->setUserAgentHeader( finalResponse ); mpSipUserAgent->send( finalResponse ); } } else // response { // The server may send us back a "481" response, if it does we need // to remove the subscription from the SubscriptionDB as the callid // that it corresponds to is stale (probably the phone was rebooted) // In the above case, RFC 3265 says we MUST remove the subscription. // It also says (essentially) that any error that does not imply a retry // SHOULD remove the subscription. We will interpret this to be any // 4xx code _except_ 408 timeout (because that may be a transient error). int responseCode = message->getResponseStatusCode(); if ( responseCode >= SIP_4XX_CLASS_CODE && responseCode != SIP_REQUEST_TIMEOUT_CODE ) { // remove the subscription removeErrorSubscription ( *message ); } } return TRUE; }
OsStatus EmailNotifier::handleAlarm(const OsTime alarmTime, const UtlString& callingHost, const cAlarmData* alarmData, const UtlString& alarmMsg) { OsStatus retval = OS_FAILED; //execute the mail command for each user UtlString groupKey(alarmData->getGroupName()); if (!groupKey.isNull()) { UtlContainable* pContact = mContacts.findValue(&groupKey); if (pContact) { // Process the comma separated list of contacts UtlString* contactList = dynamic_cast<UtlString*> (pContact); if (!contactList->isNull()) { MailMessage message(mEmailStrFrom, mReplyTo, mSmtpServer); UtlTokenizer tokenList(*contactList); UtlString entry; while (tokenList.next(entry, ",")) { message.To(entry, entry); } UtlString body; UtlString tempStr; body = mEmailStrIntro; body.append("\n"); assembleMsg(mEmailStrAlarm, alarmData->getCode(), tempStr); body.append(tempStr); body.append("\n"); assembleMsg(mEmailStrHost, callingHost, tempStr); body.append(tempStr); body.append("\n"); OsDateTime logTime(alarmTime); UtlString strTime; logTime.getIsoTimeStringZus(strTime); assembleMsg(mEmailStrTime, strTime, tempStr); body.append(tempStr); body.append("\n"); UtlString sevStr = OsSysLog::priorityName(alarmData->getSeverity()); assembleMsg(mEmailStrSeverity, sevStr, tempStr); body.append(tempStr); body.append("\n"); assembleMsg(mEmailStrDescription, alarmMsg, tempStr); body.append(tempStr); body.append("\n"); assembleMsg(mEmailStrResolution, alarmData->getResolution(), tempStr); body.append(tempStr); OsSysLog::add(FAC_ALARM, PRI_DEBUG, "AlarmServer: email body is %s", body.data()); message.Body(body); UtlSList subjectParams; UtlString codeStr(alarmData->getCode()); UtlString titleStr(alarmData->getShortTitle()); subjectParams.append(&codeStr); subjectParams.append(&titleStr); assembleMsg(mEmailStrSubject, subjectParams, tempStr); message.Subject(tempStr); // delegate send to separate task so as not to block EmailSendTask::getInstance()->sendMessage(message); } } } return retval; }
void OsSSL::logConnectParams(const OsSysLogFacility facility, ///< callers facility const OsSysLogPriority priority, ///< log priority const char* callerMsg, ///< Identifies circumstances of connection SSL* connection ///< SSL connection to be described ) { if (connection) { char* subjectStr = NULL; char* issuerStr = NULL; UtlString altNames; // Extract the subject and issuer information about the peer // and the certificate validation result. Neither of these // are meaningful without the other. // (note various dynamically allocated items - freed below) int validity = SSL_get_verify_result(connection); X509* peer_cert = SSL_get_peer_certificate(connection); if (peer_cert) { subjectStr = X509_NAME_oneline(X509_get_subject_name(peer_cert),0,0); issuerStr = X509_NAME_oneline(X509_get_issuer_name(peer_cert),0,0); // Look for the subjectAltName URI or DNS attributes GENERAL_NAMES* names; names = (GENERAL_NAMES*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL); for(int i = 0; i < sk_GENERAL_NAME_num(names); i++) { GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i); switch (name->type) { case GEN_DNS: { ASN1_IA5STRING* uri = name->d.uniformResourceIdentifier; if (!altNames.isNull()) { altNames.append(","); } altNames.append((const char*)(uri->data),uri->length); } break; case GEN_URI: { ASN1_IA5STRING* uri = name->d.uniformResourceIdentifier; if (!altNames.isNull()) { altNames.append(","); } altNames.append((const char*)(uri->data),uri->length); } break; default: // don't care about any other values break; } } sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); } // Get the name of the encryption applied to the connection const char* cipher = SSL_get_cipher(connection); OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "%s SSL Connection:\n" " status: %s\n" " peer: '%s'\n" " alt names: %s\n" " cipher: '%s'\n" " issuer: '%s'", callerMsg, validity == X509_V_OK ? "Verified" : "NOT VERIFIED", subjectStr ? subjectStr : "", altNames.isNull() ? "" : altNames.data(), cipher ? cipher : "", issuerStr ? issuerStr : "" ); // Release the various dynamic things if (subjectStr) { OPENSSL_free(subjectStr); } if (issuerStr) { OPENSSL_free(issuerStr); } if (peer_cert) { X509_free(peer_cert); } } else { OsSysLog::add(FAC_KERNEL, PRI_ERR, "OsSSL::logConnectParams called by %s with NULL connection", callerMsg ); } }
// // Pull out important parameters from the config DB. // These parameters are set at runtime and cannot be changed without a restart. // UtlBoolean ParkService::loadConfig( int& UdpPort, int& TcpPort, int& RtpBase, UtlString& bindIp, int& MaxSessions, UtlBoolean& OneButtonBLF, UtlString& domain, UtlString& realm, UtlString& user, SipLineMgr* lineMgr, int& Lifetime, int& BlindXferWait, int& KeepAliveTime ) { UtlBoolean ret = true; // SipXecsService owns the main configDb OsConfigDb& configDb = getConfigDb(); // Read the user agent parameters from the config file. if (configDb.get(CONFIG_SETTING_UDP_PORT, UdpPort) != OS_SUCCESS) UdpPort = PARK_DEFAULT_UDP_PORT; if (configDb.get(CONFIG_SETTING_TCP_PORT, TcpPort) != OS_SUCCESS) TcpPort = PARK_DEFAULT_TCP_PORT; if (configDb.get(CONFIG_SETTING_RTP_PORT, RtpBase) != OS_SUCCESS) RtpBase = DEFAULT_RTP_PORT; if (configDb.get(CONFIG_SETTING_BIND_IP, bindIp) != OS_SUCCESS || !OsSocket::isIp4Address(bindIp)) bindIp = PARK_DEFAULT_BIND_IP; if (configDb.get(CONFIG_SETTING_MAX_SESSIONS, MaxSessions) != OS_SUCCESS) { MaxSessions = DEFAULT_MAX_SESSIONS; } OneButtonBLF = configDb.getBoolean(CONFIG_SETTING_ONE_BUTTON_BLF, DEFAULT_ONE_BUTTON_BLF); OsConfigDb domainConfiguration; OsPath domainConfigPath = SipXecsService::domainConfigPath(); if (OS_SUCCESS == domainConfiguration.loadFromFile(domainConfigPath.data())) { domainConfiguration.get(SipXecsService::DomainDbKey::SIP_DOMAIN_NAME, domain); domainConfiguration.get(SipXecsService::DomainDbKey::SIP_REALM, realm); if (!domain.isNull() && !realm.isNull()) { CredentialDB* credentialDb; if ((credentialDb = CredentialDB::getInstance())) { Url identity; identity.setUserId(PARK_SERVER_ID_TOKEN); identity.setHostAddress(domain); UtlString ha1_authenticator; UtlString authtype; if (credentialDb->getCredential(identity, realm, user, ha1_authenticator, authtype)) { if ((lineMgr = new SipLineMgr())) { SipLine line(identity // user entered url ,identity // identity url ,user // user ,TRUE // visible ,SipLine::LINE_STATE_PROVISIONED ,TRUE // auto enable ,FALSE // use call handling ); if (lineMgr->addLine(line)) { lineMgr->startLineMgr(); if (lineMgr->addCredentialForLine( identity, realm, user, ha1_authenticator ,HTTP_DIGEST_AUTHENTICATION ) ) { OsSysLog::add(LOG_FACILITY, PRI_INFO, "Added identity '%s': user='******' realm='%s'" ,identity.toString().data(), user.data(), realm.data() ); } else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Error adding identity '%s': user='******' realm='%s'\n" " escape and timeout from park may not work.", identity.toString().data(), user.data(), realm.data() ); } lineMgr->setDefaultOutboundLine(identity); } // end addLine else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "addLine failed: " " escape and timeout from park may not work." ); } } else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Constructing SipLineMgr failed: " " escape and timeout from park may not work." ); } } // end getCredential else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "No credential found for '%s@%s' in realm '%s'" "; transfer functions will not work", PARK_SERVER_ID_TOKEN, domain.data(), realm.data() ); } credentialDb->releaseInstance(); } // end credentialDB else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Failed to open credentials database" "; transfer functions will not work" ); } } // end have domain and realm else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "Domain or Realm not configured:" "\n '%s' : '%s'\n '%s' : '%s'" " transfer functions will not work.", SipXecsService::DomainDbKey::SIP_DOMAIN_NAME, domain.data(), SipXecsService::DomainDbKey::SIP_REALM, realm.data() ); } } // end found domain config else { OsSysLog::add(LOG_FACILITY, PRI_ERR, "main: failed to load domain configuration from '%s'", domainConfigPath.data() ); } // Read Park Server parameters from the config file. if (configDb.get(CONFIG_SETTING_LIFETIME, Lifetime) != OS_SUCCESS) { Lifetime = DEFAULT_LIFETIME; } if (configDb.get(CONFIG_SETTING_BLIND_WAIT, BlindXferWait) != OS_SUCCESS) { BlindXferWait = DEFAULT_BLIND_WAIT; } if (configDb.get(CONFIG_SETTING_KEEPALIVE_TIME, KeepAliveTime) != OS_SUCCESS) { KeepAliveTime = DEFAULT_KEEPALIVE_TIME; } return ret; }
// Constructor SipRegistrar::SipRegistrar(OsConfigDb* configDb) : OsServerTask("SipRegistrar", NULL, SIPUA_DEFAULT_SERVER_OSMSG_QUEUE_SIZE), mConfigDb(configDb), mSipUserAgent(NULL), mRedirectServer(NULL), mRedirectMsgQ(NULL), // Create the SipRegistrarServer object so it will be available immediately, // but don't start the associated thread until the registrar is operational. mRegistrarServer(new SipRegistrarServer(*this)), mRegistrarMsgQ(NULL), mRegisterEventServer(NULL), mRegistrarPersist(NULL), mpRegDb(NULL), mpSubscribeDb(NULL), mpEntityDb(NULL) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::SipRegistrar constructed."); // Some phones insist (incorrectly) on putting the proxy port number on urls; // we get it from the configuration so that we can ignore it. mProxyNormalPort = mConfigDb->getPort("SIP_REGISTRAR_PROXY_PORT"); if (mProxyNormalPort == PORT_DEFAULT) { mProxyNormalPort = SIP_PORT; } // Domain Name mConfigDb->get("SIP_REGISTRAR_DOMAIN_NAME", mDefaultDomain); if ( mDefaultDomain.isNull() ) { OsSocket::getHostIp(&mDefaultDomain); Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "SIP_REGISTRAR_DOMAIN_NAME not configured using IP '%s'", mDefaultDomain.data() ); } // get the url parts for the domain Url defaultDomainUrl(mDefaultDomain); mDefaultDomainPort = defaultDomainUrl.getHostPort(); defaultDomainUrl.getHostAddress(mDefaultDomainHost); // make sure that the unspecified domain name is also valid addValidDomain(mDefaultDomainHost, mDefaultDomainPort); // read the domain configuration OsConfigDb domainConfig; domainConfig.loadFromFile(SipXecsService::domainConfigPath()); // Domain Aliases // (other domain names that this registrar accepts as valid in the request URI) UtlString domainAliases; domainConfig.get(SipXecsService::DomainDbKey::SIP_DOMAIN_ALIASES, domainAliases); if (!domainAliases.isNull()) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRegistrar::SipRegistrar " "SIP_DOMAIN_ALIASES : %s", domainAliases.data()); } else { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipRegistrar::SipRegistrar " "SIP_DOMAIN_ALIASES not found."); } UtlString aliasString; int aliasIndex = 0; while(NameValueTokenizer::getSubField(domainAliases.data(), aliasIndex, ", \t", &aliasString)) { Url aliasUrl(aliasString); UtlString hostAlias; aliasUrl.getHostAddress(hostAlias); int port = aliasUrl.getHostPort(); addValidDomain(hostAlias,port); aliasIndex++; } mongo::ConnectionString mongoConn = MongoDB::ConnectionInfo::connectionStringFromFile(); mpRegDb = new RegDB(MongoDB::ConnectionInfo(mongoConn, RegDB::NS)); mpSubscribeDb = new SubscribeDB(MongoDB::ConnectionInfo(mongoConn, SubscribeDB::NS)); mpEntityDb = new EntityDB(MongoDB::ConnectionInfo(mongoConn, EntityDB::NS)); mConfigDb->get("SIP_REGISTRAR_BIND_IP", mBindIp); if ((mBindIp.isNull()) || !OsSocket::isIp4Address(mBindIp)) { mBindIp = "0.0.0.0"; } }
// // Create the real Server, passing in the configured parameters // void ParkService::run() { int UdpPort; int TcpPort; int RtpBase; UtlString bindIp; int MaxSessions; UtlBoolean OneButtonBLF; UtlString domain; UtlString realm; UtlString user; SipLineMgr* lineMgr = NULL; int Lifetime; int BlindXferWait; int KeepAliveTime; loadConfig( UdpPort, TcpPort, RtpBase, bindIp, MaxSessions, OneButtonBLF, domain, realm, user, lineMgr, Lifetime, BlindXferWait, KeepAliveTime ); // initialize other pieces // This is not configurable, as consultative transfers should // succeed or fail immediately. int ConsXferWait; ConsXferWait = CONS_XFER_WAIT; // Bind the SIP user agent to a port and start it up SipUserAgent* userAgent = new SipUserAgent(TcpPort, UdpPort, TcpPort+1, NULL, // publicAddress user.isNull() ? NULL : user.data(), // default user bindIp, domain.isNull() ? NULL : domain.data(), // outbound proxy NULL, // sipDirectoryServers (deprecated) NULL, // sipRegistryServers (deprecated) NULL, // authenicateRealm NULL, // authenticateDb NULL, // authorizeUserIds (deprecated) NULL, // authorizePasswords (deprecated) lineMgr ); userAgent->setUserAgentHeaderProperty("sipXecs/park"); userAgent->start(); if (!userAgent->isOk()) { OsSysLog::add(LOG_FACILITY, PRI_EMERG, "SipUserAgent failed to initialize, requesting shutdown"); setShutdownFlag(true); } // Read the list of codecs from the configuration file. SdpCodecFactory codecFactory; initCodecs(&codecFactory, &getConfigDb()); // Initialize and start up the media subsystem mpStartUp(MP_SAMPLE_RATE, MP_SAMPLES_PER_FRAME, 6 * MaxSessions, &getConfigDb()); MpMediaTask::getMediaTask(MaxSessions); #ifdef INCLUDE_RTCP CRTCManager::getRTCPControl(); #endif //INCLUDE_RTCP mpStartTasks(); // Instantiate the call processing subsystem UtlString localAddress; int localPort ; userAgent->getLocalAddress(&localAddress, &localPort) ; if (localAddress.isNull()) OsSocket::getHostIp(&localAddress); // Construct an address to be used in outgoing requests (primarily // INVITEs stimulated by REFERs). UtlString outgoingAddress; { char buffer[100]; sprintf(buffer, "sip:sipXpark@%s:%d", localAddress.data(), portIsValid(UdpPort) ? UdpPort : TcpPort); outgoingAddress = buffer; } CallManager callManager(FALSE, NULL, TRUE, // early media in 180 ringing &codecFactory, RtpBase, // rtp start RtpBase + (2 * MaxSessions), // rtp end localAddress, localAddress, userAgent, 0, // sipSessionReinviteTimer NULL, // mgcpStackTask outgoingAddress, // defaultCallExtension Connection::RING, // availableBehavior NULL, // unconditionalForwardUrl -1, // forwardOnNoAnswerSeconds NULL, // forwardOnNoAnswerUrl Connection::BUSY, // busyBehavior NULL, // sipForwardOnBusyUrl NULL, // speedNums CallManager::SIP_CALL, // phonesetOutgoingCallProtocol 4, // numDialPlanDigits CallManager::NEAR_END_HOLD, // holdType 5000, // offeringDelay "", // pLocal CP_MAXIMUM_RINGING_EXPIRE_SECONDS, // inviteExpiresSeconds QOS_LAYER3_LOW_DELAY_IP_TOS, // expeditedIpTos MaxSessions, // maxCalls sipXmediaFactoryFactory(NULL)); // CpMediaInterfaceFactory // Create a listener (application) to deal with call // processing events (e.g. incoming call and hang ups) OrbitListener listener(&callManager, Lifetime, BlindXferWait, KeepAliveTime, ConsXferWait); callManager.addTaoListener(&listener); listener.start(); // Create the SIP Subscribe Server SipPersistentSubscriptionMgr subscriptionMgr(SUBSCRIPTION_COMPONENT_PARK, domain, "subscription"); // Component for holding the subscription data SipSubscribeServerEventHandler policyHolder; // Component for granting the subscription rights SipPublishContentMgr publisher; // Component for publishing the event contents SipSubscribeServer subscribeServer(SipSubscribeServer::terminationReasonSilent, *userAgent, publisher, subscriptionMgr, policyHolder); subscribeServer.enableEventType(DIALOG_EVENT_TYPE, NULL, NULL, NULL, SipSubscribeServer::standardVersionCallback, TRUE // dialogEvents only produces full content. ); subscribeServer.start(); // Create the DialogEventPublisher. // Use the sipX domain as the hostport of resource-IDs of the // published events, as that will be the request-URIs of SUBSCRIBEs. DialogEventPublisher dialogEvents(&callManager, &publisher, domain, PORT_NONE, OneButtonBLF); callManager.addTaoListener(&dialogEvents); dialogEvents.start(); // Start up the call processing system callManager.start(); // Loop forever until signaled to shut down int numTwoSecIntervals = 0; int CleanLoopWaitTimeSecs = 10; while (!getShutdownFlag()) { OsTask::delay(2000); if (2*numTwoSecIntervals >= CleanLoopWaitTimeSecs) { numTwoSecIntervals = 0; if (OsSysLog::willLog(FAC_PARK, PRI_DEBUG)) { OsSysLog::add(LOG_FACILITY, PRI_DEBUG, "park main " "logging call status" ); callManager.printCalls(0) ; listener.dumpCallsAndTransfers(); } } else { numTwoSecIntervals += 1; } } }