//
//
// 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 <stdio.h>
#include <signal.h>
#if defined(_WIN32)
#include <windows.h>
#elif defined(__pingtel_on_posix__)
#include <unistd.h>
#endif
#include <iostream>
// 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; i<iEntries; i++)
{
if (logLevel == lkupTable[i].pIdentity)
{
priority = lkupTable[i].ePriority;
osPrintf("%s : %s\n", CONFIG_SETTING_LOG_LEVEL, lkupTable[i].pIdentity) ;
OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s",
CONFIG_SETTING_LOG_LEVEL, lkupTable[i].pIdentity) ;
break;
}
}
OsSysLog::setLoggingPriority(priority);
//
// 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(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/<data-file-name>
//
//2) Else the path is assumed to be:
// ./<data-file-name>
//
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;
}
syntax highlighted by Code2HTML, v. 0.9.1