// // // Copyright (C) 2005-2006 SIPez LLC. // Licensed to SIPfoundry under a Contributor Agreement. // // Copyright (C) 2004 SIPfoundry Inc. // Licensed by SIPfoundry under the LGPL license. // // Copyright (C) 2004 Pingtel Corp. // Licensed to SIPfoundry under a Contributor Agreement. // // $$ ////////////////////////////////////////////////////////////////////////////// // Author: Dan Petrie (dpetrie AT SIPez DOT com) // SYSTEM INCLUDES #include #include #if defined(_WIN32) #include #elif defined(__pingtel_on_posix__) #include #endif #include // APPLICATION INCLUDES #include "os/OsFS.h" #include "os/OsConfigDb.h" #include "os/OsTask.h" #include "net/SipUserAgent.h" #include "net/NameValueTokenizer.h" #include "sipdb/SIPDBManager.h" #include "SipAaa.h" #include "AuthProxyCseObserver.h" #ifndef SIPX_VERSION # include "sipxproxy-buildstamp.h" # define SIPX_VERSION SipXproxyVersion # define SIPX_BUILD SipXproxyBuildStamp #else # define SIPX_BUILD "" #endif // DEFINES #define CONFIG_SETTING_CALL_STATE "SIP_AUTHPROXY_CALL_STATE" #define CONFIG_SETTING_CALL_STATE_LOG "SIP_AUTHPROXY_CALL_STATE_LOG" #define CALL_STATE_LOG_FILE_DEFAULT SIPX_LOGDIR "/sipauthproxy_callstate.log" // MACROS // EXTERNAL FUNCTIONS // EXTERNAL VARIABLES // CONSTANTS static const char* CONFIG_SETTING_CALL_STATE_DB = "SIP_AUTHPROXY_CALL_STATE_DB"; static const char* CONFIG_SETTING_CALL_STATE_DB_HOST = "SIP_AUTHPROXY_CALL_STATE_DB_HOST"; static const char* CONFIG_SETTING_CALL_STATE_DB_NAME = "SIP_AUTHPROXY_CALL_STATE_DB_NAME"; static const char* CONFIG_SETTING_CALL_STATE_DB_USER = "SIP_AUTHPROXY_CALL_STATE_DB_USER"; static const char* CONFIG_SETTING_CALL_STATE_DB_DRIVER = "SIP_AUTHPROXY_CALL_STATE_DB_DRIVER"; static const char* CALL_STATE_DATABASE_HOST = "localhost"; static const char* CALL_STATE_DATABASE_NAME = "SIPXCDR"; static const char* CALL_STATE_DATABASE_USER = "postgres"; static const char* CALL_STATE_DATABASE_DRIVER = "{PostgreSQL}"; // STRUCTS // TYPEDEFS typedef void (*sighandler_t)(int); #ifndef _WIN32 using namespace std ; #endif // FUNCTIONS extern "C" { void sigHandler( int sig_num ); sighandler_t pt_signal( int sig_num, sighandler_t handler ); } // FORWARD DECLARATIONS // EXTERNAL VARIABLES // CONSTANTS // STATIC VARIABLE INITIALIZATIONS // GLOBAL VARIABLE INITIALIZATIONS OsServerTask* pServerTask = NULL; UtlBoolean gShutdownFlag = FALSE; UtlBoolean gClosingIMDB = FALSE; OsMutex* gpLockMutex = new OsMutex(OsMutex::Q_FIFO); /* ============================ FUNCTIONS ================================= */ /** * Description: * closes any open connections to the IMDB safely using a mutex lock */ void closeIMDBConnections () { // Critical Section here OsLock lock( *gpLockMutex ); // now deregister this process's database references from the IMDB // and also ensure that we do not cause this code recursively // specifically SIGABRT or SIGSEGV could cause problems here if ( !gClosingIMDB ) { gClosingIMDB = TRUE; // if deleting this causes another problem in this process // the gClosingIMDB flag above will protect us delete SIPDBManager::getInstance(); } } /** * Description: * This is a replacement for signal() which registers a signal handler but sets * a flag causing system calls ( namely read() or getchar() ) not to bail out * upon recepit of that signal. We need this behavior, so we must call * sigaction() manually. */ sighandler_t pt_signal( int sig_num, sighandler_t handler) { #if defined(__pingtel_on_posix__) struct sigaction action[2]; action[0].sa_handler = handler; sigemptyset(&action[0].sa_mask); action[0].sa_flags = 0; sigaction ( sig_num, &action[0], &action[1] ); return action[1].sa_handler; #else return signal( sig_num, handler ); #endif } /** * Description: * This is the signal handler, When called this sets the * global gShutdownFlag allowing the main processing * loop to exit cleanly. */ void sigHandler( int sig_num ) { // set a global shutdown flag gShutdownFlag = TRUE; // Unregister interest in the signal to prevent recursive callbacks pt_signal( sig_num, SIG_DFL ); // Minimize the chance that we loose log data OsSysLog::flush(); if (SIGTERM == sig_num) { OsSysLog::add( LOG_FACILITY, PRI_INFO, "sigHandler: terminate signal received."); } else { OsSysLog::add( LOG_FACILITY, PRI_CRIT, "sigHandler: caught signal: %d", sig_num ); } OsSysLog::add( LOG_FACILITY, PRI_CRIT, "sigHandler: closing IMDB connections" ); OsSysLog::flush(); // Finally close the IMDB connections closeIMDBConnections(); } // 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 struct tagPriorityLookupTable { const char* pIdentity; OsSysLogPriority ePriority; }; struct tagPriorityLookupTable lkupTable[] = { { "DEBUG", PRI_DEBUG}, { "INFO", PRI_INFO}, { "NOTICE", PRI_NOTICE}, { "WARNING", PRI_WARNING}, { "ERR", PRI_ERR}, { "CRIT", PRI_CRIT}, { "ALERT", PRI_ALERT}, { "EMERG", PRI_EMERG}, }; OsSysLog::initialize(0, "SipAuthProxy"); // // 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(FAC_SIP, 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(FAC_SIP, 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(FAC_SIP, 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 // if ((pConfig->get(CONFIG_SETTING_LOG_LEVEL, logLevel) != OS_SUCCESS) || logLevel.isNull()) { logLevel = "ERR"; } logLevel.toUpper(); OsSysLogPriority priority = PRI_ERR; int iEntries = sizeof(lkupTable)/sizeof(struct tagPriorityLookupTable); for (int i=0; iget(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(FAC_SIP, 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); } } int main( int argc, char* argv[] ) { // Register Signal handlers to close IMDB pt_signal(SIGINT, sigHandler); // Trap Ctrl-C on NT pt_signal(SIGILL, sigHandler); pt_signal(SIGABRT, sigHandler); // Abort signal 6 pt_signal(SIGFPE, sigHandler); // Floading Point Exception pt_signal(SIGSEGV, sigHandler); // Address access violations signal 11 pt_signal(SIGTERM, sigHandler); // Trap kill -15 on UNIX # if defined(__pingtel_on_posix__) pt_signal(SIGHUP, sigHandler); // Hangup pt_signal(SIGQUIT, sigHandler); pt_signal(SIGPIPE, SIG_IGN); // Handle TCP Failure pt_signal(SIGBUS, sigHandler); pt_signal(SIGSYS, sigHandler); pt_signal(SIGXCPU, sigHandler); pt_signal(SIGXFSZ, sigHandler); pt_signal(SIGUSR1, sigHandler); pt_signal(SIGUSR2, sigHandler); # endif UtlBoolean interactiveSet = 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) { osPrintf("Version: %s %s\n", SIPX_VERSION, SIPX_BUILD); return(1); } else if( argString.compareTo("-i") == 0) { interactiveSet = true; osPrintf("Entering Interactive Mode\n"); } else { osPrintf("usage: %s [-v] [-i]\nwhere:\n -v provides the software version\n" " -i starts the server in an interactive mode\n", argv[0]); return(1); } } //Config files which are specific to a component //(e.g. mappingrules.xml is to sipregistrar) Use the //following logic: //1) If directory ../etc exists: // The path to the data file is as follows // ../etc/ // //2) Else the path is assumed to be: // ./ // 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 ConfigfileName = workingDirectory + OsPathBase::separator + "authproxy-config" ; int proxyTcpPort; int proxyUdpPort; int proxyTlsPort; UtlString routeName; OsConfigDb configDb; UtlString ipAddress; OsSocket::getHostIp(&ipAddress); if(configDb.loadFromFile(ConfigfileName) == OS_SUCCESS) { osPrintf("Found config file: %s\n", ConfigfileName.data()); } else { configDb.set("SIP_AUTHPROXY_AUTHENTICATE_ALGORITHM", ""); configDb.set("SIP_AUTHPROXY_AUTHENTICATE_QOP", ""); configDb.set("SIP_AUTHPROXY_AUTHENTICATE_REALM", ""); configDb.set("SIP_AUTHPROXY_UDP_PORT", "5080"); configDb.set("SIP_AUTHPROXY_TCP_PORT", "5080"); configDb.set("SIP_AUTHPROXY_TLS_PORT", "5081"); configDb.set("SIP_AUTHPROXY_ROUTE_NAME", ""); configDb.set("SIP_AUTHPROXY_HOST_ALIASES", ""); configDb.set("SIP_AUTHPROXY_STALE_TCP_TIMEOUT", ""); configDb.set(CONFIG_SETTING_LOG_DIR, ""); configDb.set(CONFIG_SETTING_LOG_LEVEL, ""); configDb.set(CONFIG_SETTING_LOG_CONSOLE, ""); configDb.set(CONFIG_SETTING_CALL_STATE, "DISABLE"); configDb.set(CONFIG_SETTING_CALL_STATE_LOG, ""); configDb.set(CONFIG_SETTING_CALL_STATE_DB, "DISABLE"); configDb.set(CONFIG_SETTING_CALL_STATE_DB_HOST, CALL_STATE_DATABASE_HOST); configDb.set(CONFIG_SETTING_CALL_STATE_DB_NAME, CALL_STATE_DATABASE_NAME); configDb.set(CONFIG_SETTING_CALL_STATE_DB_USER, CALL_STATE_DATABASE_USER); configDb.set(CONFIG_SETTING_CALL_STATE_DB_DRIVER, CALL_STATE_DATABASE_DRIVER); if (configDb.storeToFile(ConfigfileName) != OS_SUCCESS) { osPrintf("Could not write config file: %s\n", ConfigfileName.data()); } } initSysLog(&configDb) ; UtlString algorithm; configDb.get("SIP_AUTHPROXY_AUTHENTICATE_ALGORITHM", algorithm); algorithm.toUpper(); if( TRUE ) { algorithm = "MD5"; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_AUTHENTICATE_ALGORITHM : %s", algorithm.data()); osPrintf("SIP_AUTHPROXY_AUTHENTICATE_ALGORITHM : %s\n", algorithm.data()); UtlString qop; configDb.get("SIP_AUTHPROXY_AUTHENTICATE_QOP", qop); qop.toUpper(); if( TRUE ) { qop = "none"; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_AUTHENTICATE_QOP : %s", qop.data()); osPrintf("SIP_AUTHPROXY_AUTHENTICATE_QOP : %s\n", qop.data()); UtlString realm; configDb.get("SIP_AUTHPROXY_AUTHENTICATE_REALM", realm); if(realm.isNull()) { realm = ipAddress; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_AUTHENTICATE_REALM : %s", realm.data()); osPrintf("SIP_AUTHPROXY_AUTHENTICATE_REALM : %s\n", realm.data()); UtlBoolean authEnabled; UtlString authScheme; configDb.get("SIP_AUTHPROXY_AUTHENTICATE_SCHEME", authScheme); authScheme.toLower(); if(authScheme.compareTo("none") == 0) { authEnabled = FALSE; OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_AUTHENTICATE_SCHEME : NONE"); osPrintf("SIP_AUTHPROXY_AUTHENTICATE_SCHEME : NONE\n"); } configDb.get("SIP_AUTHPROXY_ROUTE_NAME", routeName); if(routeName.isNull()) { routeName = ipAddress; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_ROUTE_NAME : %s", routeName.data()); osPrintf("SIP_AUTHPROXY_ROUTE_NAME : %s\n", routeName.data()); proxyUdpPort = configDb.getPort("SIP_AUTHPROXY_UDP_PORT"); if (!portIsValid(proxyUdpPort)) { proxyUdpPort = 5080; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_UDP_PORT : %d", proxyUdpPort); proxyTcpPort = configDb.getPort("SIP_AUTHPROXY_TCP_PORT") ; if (!portIsValid(proxyTcpPort)) { proxyTcpPort = 5080; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_TCP_PORT : %d", proxyTcpPort); proxyTlsPort = configDb.getPort("SIP_AUTHPROXY_TLS_PORT") ; if (!portIsValid(proxyTlsPort)) { proxyTlsPort = 5081; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_TLS_PORT : %d", proxyTlsPort); UtlString hostAliases; configDb.get("SIP_AUTHPROXY_HOST_ALIASES", hostAliases); if(hostAliases.isNull()) { hostAliases = ipAddress; char portBuf[20]; sprintf(portBuf, ":%d", proxyUdpPort); hostAliases.append(portBuf); if(!routeName.isNull()) { hostAliases.append(" "); hostAliases.append(routeName); char portBuf[20]; sprintf(portBuf, ":%d", proxyUdpPort); hostAliases.append(portBuf); } } OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_PROXY_AUTHHOST_ALIASES : %s", hostAliases.data()); osPrintf("SIP_AUTHPROXY_HOST_ALIASES : %s\n", hostAliases.data()); UtlString enableCallStateObserverSetting; configDb.get(CONFIG_SETTING_CALL_STATE, enableCallStateObserverSetting); bool enableCallStateLogObserver; if ( (enableCallStateObserverSetting.isNull()) || ((0 == enableCallStateObserverSetting.compareTo("disable", UtlString::ignoreCase))) ) { enableCallStateLogObserver = false; } else if (0 == enableCallStateObserverSetting.compareTo("enable", UtlString::ignoreCase)) { enableCallStateLogObserver = true; } else { enableCallStateLogObserver = false; OsSysLog::add(FAC_SIP, PRI_ERR, "SipAuthProxyMain:: invalid configuration value for " CONFIG_SETTING_CALL_STATE " '%s' - should be 'enable' or 'disable'", enableCallStateObserverSetting.data() ); } OsSysLog::add(FAC_SIP, PRI_INFO, CONFIG_SETTING_CALL_STATE " : %s", enableCallStateLogObserver ? "ENABLE" : "DISABLE" ); UtlString callStateLogFileName; if (enableCallStateLogObserver) { configDb.get(CONFIG_SETTING_CALL_STATE_LOG, callStateLogFileName); if (callStateLogFileName.isNull()) { callStateLogFileName = CALL_STATE_LOG_FILE_DEFAULT; } OsSysLog::add(FAC_SIP, PRI_INFO, CONFIG_SETTING_CALL_STATE_LOG " : %s", callStateLogFileName.data()); } // Check if CSE logging should go into a database UtlString enableCallStateDbObserverSetting; configDb.get(CONFIG_SETTING_CALL_STATE_DB, enableCallStateDbObserverSetting); bool enableCallStateDbObserver; if ( (enableCallStateDbObserverSetting.isNull()) || ((0 == enableCallStateDbObserverSetting.compareTo("disable", UtlString::ignoreCase))) ) { enableCallStateDbObserver = false; } else if (0 == enableCallStateDbObserverSetting.compareTo("enable", UtlString::ignoreCase)) { enableCallStateDbObserver = true; } else { enableCallStateDbObserver = false; OsSysLog::add(FAC_SIP, PRI_ERR, "SipAuthProxyMain:: invalid configuration value for %s " " '%s' - should be 'enable' or 'disable'", CONFIG_SETTING_CALL_STATE_DB, enableCallStateDbObserverSetting.data() ); } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB, enableCallStateDbObserver ? "ENABLE" : "DISABLE" ); UtlString callStateDbHostName; UtlString callStateDbName; UtlString callStateDbUserName; UtlString callStateDbDriver; if (enableCallStateDbObserver) { configDb.get(CONFIG_SETTING_CALL_STATE_DB_HOST, callStateDbHostName); if (callStateDbHostName.isNull()) { callStateDbHostName = CALL_STATE_DATABASE_HOST; } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB_HOST, callStateDbHostName.data()); configDb.get(CONFIG_SETTING_CALL_STATE_DB_NAME, callStateDbName); if (callStateDbName.isNull()) { callStateDbName = CALL_STATE_DATABASE_NAME; } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB_NAME, callStateDbName.data()); configDb.get(CONFIG_SETTING_CALL_STATE_DB_USER, callStateDbUserName); if (callStateDbUserName.isNull()) { callStateDbUserName = CALL_STATE_DATABASE_USER; } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB_USER, callStateDbUserName.data()); configDb.get(CONFIG_SETTING_CALL_STATE_DB_DRIVER, callStateDbDriver); if (callStateDbDriver.isNull()) { callStateDbDriver = CALL_STATE_DATABASE_DRIVER; } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB_DRIVER, callStateDbDriver.data()); } // Select logging method - database takes priority over XML file if (enableCallStateLogObserver && enableCallStateDbObserver) { enableCallStateLogObserver = false; OsSysLog::add(FAC_SIP, PRI_WARNING, "SipAuthProxyMain:: both XML and database call state " "logging was enabled - turning off XML log, only use database logging"); } // Set the maximum amount of time that TCP connections can // stay around when they are not used. int staleTcpTimeout = 3600; UtlString staleTcpTimeoutStr; // Check for missing parameter or empty value configDb.get("SIP_AUTHPROXY_STALE_TCP_TIMEOUT", staleTcpTimeoutStr); if (staleTcpTimeoutStr.isNull()) { staleTcpTimeout = 3600; } else { // get the parameter value as an integer configDb.get("SIP_AUTHPROXY_STALE_TCP_TIMEOUT", staleTcpTimeout); } if(staleTcpTimeout <= 0) staleTcpTimeout = -1; else if(staleTcpTimeout < 180) staleTcpTimeout = 180; OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_STALE_TCP_TIMEOUT : %d", staleTcpTimeout); osPrintf("SIP_AUTHPROXY_STALE_TCP_TIMEOUT : %d\n", staleTcpTimeout); int maxNumSrvRecords = -1; configDb.get("SIP_AUTHPROXY_DNSSRV_MAX_DESTS", maxNumSrvRecords); OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_DNSSRV_MAX_DESTS : %d", maxNumSrvRecords); // If explicitly set to a valid number if(maxNumSrvRecords > 0) { osPrintf("SIP_AUTHPROXY_DNSSRV_MAX_DESTS : %d\n", maxNumSrvRecords); } else { maxNumSrvRecords = 4; } int dnsSrvTimeout = -1; //seconds configDb.get("SIP_AUTHPROXY_DNSSRV_TIMEOUT", dnsSrvTimeout); OsSysLog::add(FAC_SIP, PRI_INFO, "SIP_AUTHPROXY_DNSSRV_TIMEOUT : %d", dnsSrvTimeout); // If explicitly set to a valid number if(dnsSrvTimeout > 0) { osPrintf("SIP_AUTHPROXY_DNSSRV_TIMEOUT : %d\n", dnsSrvTimeout); } else { dnsSrvTimeout = 4; } // Start the sip stack SipUserAgent sipUserAgent( proxyTcpPort, proxyUdpPort, proxyTlsPort, NULL, // public IP address (nopt used in proxy) NULL, // default user (not used in proxy) NULL, // default SIP address (not used in proxy) NULL, // outbound proxy NULL, // directory server NULL, // registry server NULL, // auth scheme NULL, //auth realm NULL, // auth DB NULL, // auth user IDs NULL, // auth passwords NULL, // nat ping URL 0, // nat ping frequency "PING", // nat ping method NULL, // line mgr SIP_DEFAULT_RTT, // first resend timeout TRUE, // default to UA transaction SIPUA_DEFAULT_SERVER_UDP_BUFFER_SIZE, // socket layer read buffer size SIPUA_DEFAULT_SERVER_OSMSG_QUEUE_SIZE // OsServerTask message queue size ); sipUserAgent.setIsUserAgent(FALSE); sipUserAgent.setDnsSrvTimeout(dnsSrvTimeout); sipUserAgent.setMaxSrvRecords(maxNumSrvRecords); sipUserAgent.setUserAgentHeaderProperty("sipX/authproxy"); sipUserAgent.setForking(FALSE); // Disable forking sipUserAgent.setHostAliases(hostAliases); sipUserAgent.start(); UtlString buffer; // Create a router to route stuff either // to a local server or on out to the real world pServerTask = new SipAaa(sipUserAgent, realm, routeName); // Start the router running pServerTask->start(); // Create the CSE observer, either writing to file or database AuthProxyCseObserver* cseObserver = NULL; CallStateEventWriter* pEventWriter = NULL; if (enableCallStateLogObserver) { // Set up the call state event log file pEventWriter = new CallStateEventWriter_XML(callStateLogFileName.data()); } else if (enableCallStateDbObserver) { pEventWriter = new CallStateEventWriter_DB(callStateDbName.data(), callStateDbHostName.data(), callStateDbUserName, callStateDbDriver); } if (pEventWriter) { // get the identifier for this observer int protocol = OsSocket::UDP; UtlString domainName; int port; sipUserAgent.getViaInfo(protocol, domainName, port); char portString[12]; sprintf(portString,":%d", port); domainName.append(portString); // and start the observer cseObserver = new AuthProxyCseObserver(sipUserAgent, domainName, pEventWriter); cseObserver->start(); } else { // Only log error if any event logging was enabled if (enableCallStateLogObserver || enableCallStateDbObserver) { OsSysLog::add(FAC_SIP, PRI_ERR, "SipAuthProxyMain:: EventWriter could not be allocated" ); enableCallStateLogObserver = false; enableCallStateDbObserver = false; } } // Do not exit, let the proxy do its stuff while( !gShutdownFlag ) { if( interactiveSet) { int charCode = getchar(); if(charCode != '\n' && charCode != '\r') { if( charCode == 'e') { OsSysLog::enableConsoleOutput(TRUE); } else if( charCode == 'd') { OsSysLog::enableConsoleOutput(FALSE); } else { sipUserAgent.printStatus(); sipUserAgent.getMessageLog(buffer); printf("=================>\n%s\n", buffer.data()); } } } else { OsTask::delay(2000); } } // Remove the current process's row from the IMDB // Persisting the database if necessary osPrintf("Cleaning Up..Start.\n"); // This is a server task so gracefully shutdown the // server task using the waitForShutdown method, this // will implicitly request a shutdown for us if one is // not already in progress if ( pServerTask != NULL ) { // Deleting a server task is the only way of // waiting for shutdown to complete cleanly pServerTask->requestShutdown(); delete pServerTask; pServerTask = NULL; } // now deregister this process's database references from the IMDB closeIMDBConnections(); // flush and close the call state event log if (enableCallStateLogObserver || enableCallStateDbObserver) { if (cseObserver) { delete cseObserver; } if (pEventWriter) { delete pEventWriter; } } // Flush the log file OsSysLog::flush(); osPrintf("Cleanup...Finished/n"); return 0; }