void testConstructor() { /* * This test exists to initialize the singleton plugin. * Doing it as a static ran into ordering problems. */ CPPUNIT_ASSERT((xferctl=dynamic_cast<MSFT_ExchangeTransferHack*>(getAuthPlugin("msft")))); OsConfigDb xferConfigDb; xferConfigDb.set(MSFT_ExchangeTransferHack::RecognizerConfigKey, "^RTCC/"); xferctl->readConfig(xferConfigDb); testUserAgent.setIsUserAgent(FALSE); testUserAgent.setUserAgentHeaderProperty("sipXecs/testproxy"); testUserAgent.setForking(FALSE); // Disable forking OsConfigDb configDb; configDb.set("SIPX_PROXY_AUTHENTICATE_ALGORITHM", "MD5"); configDb.set("SIPX_PROXY_HOSTPORT", "sipx.example.edu"); testSipRouter = new SipRouter(testUserAgent, mForwardingRules, configDb); xferctl->announceAssociatedSipRouter( testSipRouter ); }
void setUp() { hostIp = "127.0.0.1"; eventName = SIP_EVENT_MESSAGE_SUMMARY; mwiMimeType = CONTENT_TYPE_SIMPLE_MESSAGE_SUMMARY;; // Construct a user agent that will function both as the subscriber // and the notfier. // Construct the URI of the notifier, which is also the URI of // the subscriber. // Also construct the name-addr version of the URI, which may be // different if it has a "transport" parameter. // And the resource-id to use, which is the AOR with any // parameters stripped off. createTestSipUserAgent(hostIp, "111", userAgentp, aor, aor_name_addr, aor_contact_name_addr, resource_id); subServerp = SipSubscribeServer::buildBasicServer(*userAgentp, eventName); subServerp->start(); // Get pointers to the Subscription Manager and Dialog Manager. subMgrp = subServerp->getSubscriptionMgr(eventName); CPPUNIT_ASSERT(subMgrp); dialogMgrp = subMgrp->getDialogMgr(); CPPUNIT_ASSERT(dialogMgrp); // Create a simple Subscription client // Register an interest in SUBSCRIBE responses and NOTIFY requests // for this event type userAgentp->addMessageObserver(incomingClientMsgQueue, SIP_SUBSCRIBE_METHOD, FALSE, // no requests TRUE, // reponses TRUE, // incoming FALSE, // no outgoing eventName, NULL, NULL); userAgentp->addMessageObserver(incomingClientMsgQueue, SIP_NOTIFY_METHOD, TRUE, // requests FALSE, // not reponses TRUE, // incoming FALSE, // no outgoing eventName, NULL, NULL); }
SipConfigServerAgent* SipConfigServerAgent::startAgents(const char* configFileName) { int sipTcpPort; int sipUdpPort; int sipTlsPort; OsConfigDb configDb; if(configDb.loadFromFile(configFileName) == OS_SUCCESS) { osPrintf("Found config file: %s\n", configFileName); } else { configDb.set("SIP_SDS_UDP_PORT", "5090"); configDb.set("SIP_SDS_TCP_PORT", "5090"); configDb.set("SIP_SDS_TLS_PORT", "5091"); configDb.set(CONFIG_SETTING_LOG_DIR, ""); configDb.set(CONFIG_SETTING_LOG_LEVEL, ""); configDb.set(CONFIG_SETTING_LOG_CONSOLE, ""); if (configDb.storeToFile(configFileName) != OS_SUCCESS) osPrintf("Could not store config file: %s\n", configFileName); } sipTcpPort = configDb.getPort("SIP_SDS_UDP_PORT") ; sipUdpPort = configDb.getPort("SIP_SDS_TCP_PORT") ; sipTlsPort = configDb.getPort("SIP_SDS_TLS_PORT") ; // Start the sip stack SipUserAgent* pAgent = new SipUserAgent(sipTcpPort, sipUdpPort, sipTlsPort, 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, // 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 ); pAgent->start(); // Start the SipConfigServerAgent SipConfigServerAgent* pConfigAgent = new SipConfigServerAgent(pAgent) ; pConfigAgent->start() ; return(pConfigAgent); }
void tearDown() { // Clean up to prevent use of the queue after it goes out of scope. userAgentp->removeMessageObserver(incomingClientMsgQueue); userAgentp->removeMessageObserver(incomingClientMsgQueue); OsTask::delay(1000); userAgentp->shutdown(TRUE); delete userAgentp; delete subServerp; }
void setUp() { // Construct a SipUserAgent to provide the isMyHostAlias recognizer UserAgent = new SipUserAgent(0, 0, -1); UtlString internalDomainAlias("example.com:5060"); UserAgent->setHostAliases(internalDomainAlias); UtlString internalHostAlias("internal.example.com:5060"); UserAgent->setHostAliases(internalHostAlias); UtlString externalAlias("external.example.net:5060"); UserAgent->setHostAliases(externalAlias); }
void testOnOffHook() { PsMsg *keyMsg; SipUserAgent *ua = CpTestSupport::newSipUserAgent(); ua->start(); CallManager *callmgr = CpTestSupport::newCallManager(ua); callmgr->start(); keyMsg = new PsMsg(PsMsg::HOOKSW_STATE, NULL, PsHookswTask::OFF_HOOK, 0); callmgr->postMessage(*keyMsg); delete keyMsg; keyMsg = new PsMsg(PsMsg::BUTTON_DOWN, NULL, 0, '1'); callmgr->postMessage(*keyMsg); delete keyMsg; keyMsg = new PsMsg(PsMsg::BUTTON_UP, NULL, 0, '1'); callmgr->postMessage(*keyMsg); delete keyMsg; keyMsg = new PsMsg(PsMsg::BUTTON_DOWN, NULL, 0, '0'); callmgr->postMessage(*keyMsg); delete keyMsg; keyMsg = new PsMsg(PsMsg::BUTTON_UP, NULL, 0, '0'); callmgr->postMessage(*keyMsg); delete keyMsg; keyMsg = new PsMsg(PsMsg::BUTTON_DOWN, NULL, 0, '0'); callmgr->postMessage(*keyMsg); delete keyMsg; keyMsg = new PsMsg(PsMsg::BUTTON_UP, NULL, 0, '0'); callmgr->postMessage(*keyMsg); delete keyMsg; keyMsg = new PsMsg(PsMsg::BUTTON_DOWN, NULL, 0, '4'); callmgr->postMessage(*keyMsg); delete keyMsg; keyMsg = new PsMsg(PsMsg::BUTTON_UP, NULL, 0, '4'); callmgr->postMessage(*keyMsg); delete keyMsg; delete callmgr; delete ua; }
void testPickupCall() { PsMsg *keyMsg; SipUserAgent *ua = CpTestSupport::newSipUserAgent(); ua->start(); CallManager *callmgr = CpTestSupport::newCallManager(ua); callmgr->start(); // Wait a little and pick up the hook assuming it is ringing OsTask::delay(30000); printf("Picking up ringing phone\n"); keyMsg = new PsMsg(PsMsg::HOOKSW_STATE, NULL, PsHookswTask::OFF_HOOK, 0); callmgr->postMessage(*keyMsg); delete keyMsg; delete callmgr; delete ua; }
RequestLinterTest() : identity(""), requestUri("sip:[email protected]") { testUserAgent.setIsUserAgent(FALSE); testUserAgent.setUserAgentHeaderProperty("sipXecs/testproxy"); testUserAgent.setForking(FALSE); // Disable forking UtlString hostAliases("mydomainalias.com mydomainotheralias.com"); testUserAgent.setHostAliases(hostAliases); OsConfigDb configDb; configDb.set("SIPX_PROXY_AUTHENTICATE_ALGORITHM", "MD5"); configDb.set("SIPX_PROXY_DOMAIN_NAME", "mydomain.com"); configDb.set("SIPX_PROXY_AUTHENTICATE_REALM", "mydomain.com"); configDb.set("SIPX_PROXY_HOSTPORT", "mydomain.com"); testSipRouter = new SipRouter(testUserAgent, mForwardingRules, configDb); spLinter->announceAssociatedSipRouter( testSipRouter ); }
// Constructor SipPimClient::SipPimClient(SipUserAgent& userAgent, Url& presentityAor) { presentityAor.toString(mFromField); mPresentityAor = presentityAor; mpUserAgent = &userAgent; // Register to get incoming MESSAGE requests OsMsgQ* myQueue = getMessageQueue(); userAgent.addMessageObserver(*myQueue, SIP_MESSAGE_METHOD, TRUE, // requests FALSE, // responces TRUE, // incoming FALSE); // outgoing }
// // The main entry point to the sipXpark // int main(int argc, char* argv[]) { // Configuration Database (used for OsSysLog) OsConfigDb configDb; // Register Signal handlers so we can perform graceful shutdown 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 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", SIPXCHANGE_VERSION, SIPXCHANGE_VERSION_COMMENT); 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 = DEFAULT_UDP_PORT; } int TcpPort; if (configDb.get(CONFIG_SETTING_TCP_PORT, TcpPort) != OS_SUCCESS) { TcpPort = DEFAULT_TCP_PORT; } int HttpPort; if (configDb.get(CONFIG_SETTING_HTTP_PORT, HttpPort) != OS_SUCCESS) { HttpPort = DEFAULT_HTTP_PORT; } // Bind the SIP user agent to a port and start it up SipUserAgent* userAgent = new SipUserAgent(TcpPort, UdpPort); userAgent->start(); UtlString domainName; configDb.get(CONFIG_SETTING_DOMAIN_NAME, domainName); int refreshTimeout; if (configDb.get(CONFIG_SETTING_REFRESH_INTERVAL, refreshTimeout) != OS_SUCCESS) { refreshTimeout = DEFAULT_REFRESH_INTERVAL; } // Create the Sip Dialog Monitor SipDialogMonitor dialogMonitor(userAgent, domainName, TcpPort, refreshTimeout, true); // Create a XmlRpcDispatch XmlRpcDispatch XmlRpcServer(HttpPort, false, "/RPC2"); // Register all the XML-RPC methods DialogMonitorConfig xmlRpcMethods(&XmlRpcServer, &dialogMonitor); // Loop forever until signaled to shut down while (!gShutdownFlag) { OsTask::delay(2000); } // Shut down the sipUserAgent userAgent->shutdown(FALSE); while(!userAgent->isShutdownDone()) { ; } delete userAgent; // Flush the log file OsSysLog::flush(); // Say goodnight Gracie... return 0; }
// // The main entry point to the sipXpark // int main(int argc, char* argv[]) { // Configuration Database (used for OsSysLog) OsConfigDb configDb; // Register Signal handlers so we can perform graceful shutdown 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 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", SIPXCHANGE_VERSION, SIPXCHANGE_VERSION_COMMENT); 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 = PRESENCE_DEFAULT_UDP_PORT; } int TcpPort; if (configDb.get(CONFIG_SETTING_TCP_PORT, TcpPort) != OS_SUCCESS) { TcpPort = PRESENCE_DEFAULT_TCP_PORT; } UtlString bindIp; if (configDb.get(CONFIG_SETTING_BIND_IP, bindIp) != OS_SUCCESS || !OsSocket::isIp4Address(bindIp)) { bindIp = PRESENCE_DEFAULT_BIND_IP; } // Bind the SIP user agent to a port and start it up SipUserAgent* userAgent = new SipUserAgent(TcpPort, UdpPort, PORT_NONE, NULL, NULL, bindIp ); userAgent->start(); if (!userAgent->isOk()) { OsSysLog::add(LOG_FACILITY, PRI_EMERG, "SipUserAgent failed to initialize; requesting shutdown"); gShutdownFlag = TRUE; } UtlString domainName; configDb.get(CONFIG_SETTING_DOMAIN_NAME, domainName); // Normalize SIP domain name to all lower case. domainName.toLower(); // Create the SipPersistentSubscriptionMgr. SipPersistentSubscriptionMgr subscriptionMgr(SUBSCRIPTION_COMPONENT_PRESENCE, domainName); // Determine the name of the persistent file. UtlString pathName = SipXecsService::Path(SipXecsService::VarDirType, sPersistentFileName.data()); // Create the Sip Presence Monitor, which handles all of the processing. SipPresenceMonitor presenceMonitor(userAgent, &subscriptionMgr, domainName, TcpPort, &configDb, true, pathName.data()); // Loop forever until signaled to shut down while (!gShutdownFlag) { OsTask::delay(2000); } // Shut down the sipUserAgent userAgent->shutdown(FALSE); while(!userAgent->isShutdownDone()) { ; } delete userAgent; // Flush the log file OsSysLog::flush(); // Say goodnight Gracie... return 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; } } }
int main(int argc, char* argv[]) { const char* configFileName = "siptest-config"; int proxyTcpPort; int proxyUdpPort; int proxyTlsPort; OsConfigDb configDb; // siptest uses osPrintf for output, so we have to un-suppress it. enableConsoleOutput(TRUE); if(configDb.loadFromFile(configFileName) == OS_SUCCESS) { osPrintf("Found config file: %s\n", configFileName); } else { configDb.set("SIP_TEST_UDP_PORT", "3000"); configDb.set("SIP_TEST_TCP_PORT", "3000"); configDb.set("SIP_TEST_TLS_PORT", "3001"); if(configDb.storeToFile(configFileName) == OS_SUCCESS) { osPrintf("Could not write config file: %s\n", configFileName); } } proxyUdpPort = configDb.getPort("SIP_TEST_UDP_PORT") ; proxyTcpPort = configDb.getPort("SIP_TEST_TCP_PORT") ; proxyTlsPort = configDb.getPort("SIP_TEST_TLS_PORT") ; UtlBoolean commandStatus = CommandProcessor::COMMAND_SUCCESS; char buffer[1024]; char* commandLine; CommandProcessor processor; SipLineMgr* lineMgr = new SipLineMgr(); SipRefreshMgr* refreshMgr = new SipRefreshMgr(); lineMgr->StartLineMgr(); lineMgr->initializeRefreshMgr( refreshMgr ); SipUserAgent* sipUA = new SipUserAgent( proxyTcpPort ,proxyUdpPort ,proxyTlsPort ,NULL // default publicAddress ,NULL // default defaultUser ,NULL // default defaultSipAddress ,NULL // default sipProxyServers ,NULL // default sipDirectoryServers ,NULL // default sipRegistryServers ,NULL // default authenicateRealm ,NULL // default authenticateDb ,NULL // default authorizeUserIds ,NULL // default authorizePasswords ,lineMgr ); sipUA->allowMethod(SIP_REGISTER_METHOD); sipUA->allowMethod(SIP_SUBSCRIBE_METHOD); sipUA->allowMethod(SIP_NOTIFY_METHOD); sipUA->start(); sipUA->startMessageLog(); osPrintf( "SIP logging Started\n" ); refreshMgr->init( sipUA ); CommandMsgProcessor* msgProc = new CommandMsgProcessor(sipUA); msgProc->start(); processor.registerCommand("help", new HelpCommand(&processor)); processor.registerCommand("?", new HelpCommand(&processor)); processor.registerCommand("history", new HistoryCommand(&processor)); processor.registerCommand("send", new SipSendCommand(sipUA)); processor.registerCommand("lsend", new SipLSendCommand()); processor.registerCommand("get", new HttpGetCommand()); processor.registerCommand("respond", new RespondCommand(msgProc)); processor.registerCommand("rt", new RespondTemplate(msgProc)); processor.registerCommand("rrespond", new ResendResponse(msgProc)); processor.registerCommand("log", new SipLogCommand(*sipUA)); processor.registerCommand("auth", new AuthCommand(lineMgr)); processor.registerCommand("sleep", new SleepCommand()); processor.registerCommand("quit", new ExitCommand()); processor.registerCommand("exit", new ExitCommand()); //Initialization UtlBoolean doPrompt = isatty(STDIN_FILENO); if ( doPrompt ) { printf("Enter command or help/? for help\n"); printf("SIPdriver: "); } for ( commandStatus = CommandProcessor::COMMAND_SUCCESS; ( commandStatus < CommandProcessor::COMMAND_FAILED_EXIT && commandStatus != CommandProcessor::COMMAND_SUCCESS_EXIT && (commandLine = fgets(buffer,1024,stdin)) ); ) { //printf("GOT command line:\"%s\"\n", commandLine); commandStatus = processor.executeCommand(commandLine); //printf("command status: %d exit status: %d\n", commandStatus, //CommandProcessor::COMMAND_SUCCESS_EXIT); if ( doPrompt ) { printf("SIPdriver: "); } } delete msgProc; delete sipUA; return CommandProcessor::COMMAND_SUCCESS_EXIT != commandStatus; }
StatusServer* StatusServer::startStatusServer ( const UtlString workingDir, const char* configFileName ) { int httpPort = PORT_NONE; int httpsPort = PORT_NONE; int tcpPort = PORT_NONE; int udpPort = PORT_NONE; int tlsPort = PORT_NONE; UtlString bindIp; UtlString defaultMaxExpiresTime; UtlString defaultMinExpiresTime; UtlString authAlgorithm; UtlString authQop; UtlString authRealm; UtlString authScheme; UtlString domainName; UtlBoolean isCredentialDB = TRUE; // if the configuration file exists, load the name value pairs if ( sConfigDb.loadFromFile(configFileName) == OS_SUCCESS ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "Found config file: %s", configFileName); } else { Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "Could not read config file: %s", configFileName); fprintf(stderr, "Could not read config file: %s", configFileName); exit(1); } Os::Logger::instance().log(LOG_FACILITY, PRI_INFO, "Starting - version: %s %s\n", VERSION, PACKAGE_REVISION); sConfigDb.get("SIP_STATUS_AUTHENTICATE_ALGORITHM", authAlgorithm); sConfigDb.get("SIP_STATUS_AUTHENTICATE_QOP", authQop); sConfigDb.get("SIP_STATUS_AUTHENTICATE_REALM", authRealm); sConfigDb.get("SIP_STATUS_AUTHENTICATE_SCHEME", authScheme); sConfigDb.get("SIP_STATUS_DOMAIN_NAME", domainName); sConfigDb.get("SIP_STATUS_HTTP_PORT", httpPort); sConfigDb.get("SIP_STATUS_HTTPS_PORT", httpsPort); sConfigDb.get("SIP_STATUS_MAX_EXPIRES", defaultMaxExpiresTime); sConfigDb.get("SIP_STATUS_MIN_EXPIRES", defaultMinExpiresTime); // SIP_STATUS_UDP_PORT udpPort = sConfigDb.getPort("SIP_STATUS_UDP_PORT") ; if ( udpPort == PORT_NONE ) { udpPort = 5110; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_UDP_PORT : %d", udpPort); // SIP_STATUS_TCP_PORT tcpPort = sConfigDb.getPort("SIP_STATUS_TCP_PORT") ; if ( tcpPort == PORT_NONE ) { tcpPort = 5110; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_TCP_PORT : %d", tcpPort); // SIP_STATUS_TLS_PORT tlsPort = sConfigDb.getPort("SIP_STATUS_TLS_PORT") ; if ( tlsPort == PORT_NONE ) { tlsPort = 5111; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_TLS_PORT : %d", tlsPort); // SIP_STATUS_BIND_IP sConfigDb.get("SIP_STATUS_BIND_IP", bindIp) ; if ((bindIp.isNull()) || !OsSocket::isIp4Address(bindIp)) { bindIp = "0.0.0.0"; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_BIND_IP : %s", bindIp.data()); UtlString separatedList; // Get the HTTP server Valid IP address database OsConfigDb* pValidIpAddressDB = new OsConfigDb(); sConfigDb.get("SIP_STATUS_HTTP_VALID_IPS", separatedList); parseList ("SIP_STATUS_HTTP_VALID_IPS", separatedList, *pValidIpAddressDB); if( pValidIpAddressDB->isEmpty() ) { delete pValidIpAddressDB; pValidIpAddressDB = NULL; } // Check for default values and, if not specified, set to defaults // SIP_STATUS_AUTHENTICATE_ALGORITHM if ( authAlgorithm.isNull() ) /* MD5/MD5SESS */ { authAlgorithm.append("MD5"); } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_AUTHENTICATE_ALGORITHM : %s", authAlgorithm.data()); // SIP_STATUS_AUTHENTICATE_QOP if ( authQop.isNull() ) /* AUTH/AUTH-INT/NONE */ { authQop.append("NONE"); } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_AUTHENTICATE_QOP : %s", authQop.data()); // SIP_STATUS_DOMAIN_NAME - need this before the SIP_STATUS_AUTHENTICATE_REALM // below since we get the domain name from the socket if ( domainName.isNull() ) { OsSocket::getHostIp(&domainName); } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_DOMAIN_NAME : %s", domainName.data()); // SIP_STATUS_AUTHENTICATE_REALM if(authRealm.isNull()) { authRealm.append(domainName); } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_AUTHENTICATE_REALM : %s", authRealm.data()); // SIP_STATUS_AUTHENTICATE_SCHEME (Hidden) NONE/DIGEST if ( authScheme.compareTo("NONE" , UtlString::ignoreCase) == 0 ) { isCredentialDB = FALSE; } // SIP_STATUS_HTTPS_PORT - See if the SECURE one is set first OsStatus result; UtlString portStr; result = sConfigDb.get("SIP_STATUS_HTTPS_PORT", portStr); Os::Logger::instance().log(FAC_SIP, PRI_INFO, "startStatusServer : HTTPS port %s result %d", portStr.data(), result); // If the key is missing or not set, set it to the default HTTPS port if ( result == OS_NOT_FOUND || portStr.isNull() ) { httpsPort = HTTPS_SERVER_PORT; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_HTTPS_PORT : %d", httpsPort ); // Only search for the non secure SIP_STATUS_HTTP_PORT // if the secure one is disabled if ( httpsPort == PORT_NONE ) { // SIP_STATUS_HTTP_PORT result = sConfigDb.get("SIP_STATUS_HTTP_PORT", portStr); Os::Logger::instance().log(FAC_SIP, PRI_INFO, "startStatusServer : HTTP port %s result %d", portStr.data(), result); // If the key is missing or not set, set it to the default HTTP port if ( result == OS_NOT_FOUND || portStr.isNull() ) { httpPort = HTTP_SERVER_PORT; } Os::Logger::instance().log( FAC_SIP, PRI_INFO, "SIP_STATUS_HTTP_PORT : %d", httpPort ); } int maxNumSrvRecords = -1; sConfigDb.get("SIP_STATUS_DNSSRV_MAX_DESTS", maxNumSrvRecords); Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_DNSSRV_MAX_DESTS : %d", maxNumSrvRecords); // If explicitly set to a valid number if(maxNumSrvRecords > 0) { osPrintf("SIP_STATUS_DNSSRV_MAX_DESTS : %d\n", maxNumSrvRecords); } else { maxNumSrvRecords = 4; } int dnsSrvTimeout = -1; //seconds sConfigDb.get("SIP_STATUS_DNSSRV_TIMEOUT", dnsSrvTimeout); Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_DNSSRV_TIMEOUT : %d", dnsSrvTimeout); // If explicitly set to a valid number if(dnsSrvTimeout > 0) { osPrintf("SIP_STATUS_DNSSRV_TIMEOUT : %d\n", dnsSrvTimeout); } else { dnsSrvTimeout = 4; } // SIP_STATUS_MAX_EXPIRES if ( defaultMaxExpiresTime.isNull() ) { defaultMaxExpiresTime.append("604800"); // default to 1 week } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_MAX_EXPIRES : %s", defaultMaxExpiresTime.data()); int maxExpiresTime = atoi(defaultMaxExpiresTime.data()); // SIP_STATUS_MIN_EXPIRES if ( defaultMinExpiresTime.isNull() ) { defaultMinExpiresTime.append("300"); // default to 300 seconds } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIP_STATUS_MIN_EXPIRES : %s", defaultMinExpiresTime.data()); int webServerPort = httpPort; UtlBoolean isSecureServer = false; // Determine whether we should start the web server or not. Use the port // value as the decision point. A valid port means enable. // If isSecureServer then start the port as a secure web server. OsServerSocket* serverSocket = NULL; HttpServer* httpServer = NULL; if( portIsValid(webServerPort) ) { if ( isSecureServer ) { # ifdef HAVE_SSL serverSocket = new OsSSLServerSocket(50, webServerPort, bindIp); httpServer = new HttpServer(serverSocket, pValidIpAddressDB, false /* no persistent tcp connection */); # else /* ! HAVE_SSL */ // SSL is not configured in, so we cannot open the requested // socket. Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "StatusServer::startStatusServer SSL not configured; " "cannot open secure socket %d", webServerPort); httpServer = NULL; # endif /* HAVE_SSL */ } else { serverSocket = new OsServerSocket(50, webServerPort, bindIp); httpServer = new HttpServer(serverSocket, pValidIpAddressDB ); } } // Start the SIP stack SipUserAgent* sipUserAgent = new SipUserAgent( tcpPort, udpPort, tlsPort, NULL, // public IP address (nopt used in proxy) NULL, // default user (not used in proxy) bindIp, NULL, // outbound proxy NULL, // directory server NULL, // registry server NULL, // auth realm NULL, // auth DB NULL, // auth user IDs NULL, // auth passwords 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 ); // No need to log the message as it goes in the syslog //sipUserAgent->startMessageLog(100000); sipUserAgent->setDnsSrvTimeout(dnsSrvTimeout); sipUserAgent->setMaxSrvRecords(maxNumSrvRecords); sipUserAgent->setUserAgentHeaderProperty("sipXecs/publisher"); sipUserAgent->start(); Notifier* notifier = new Notifier(sipUserAgent); // Start the status server StatusServer* status = new StatusServer( notifier, maxExpiresTime, domainName, defaultMinExpiresTime, isCredentialDB, authAlgorithm, authQop, authRealm, workingDir, serverSocket, httpServer); status->start(); return(status); }
// Primitive to send a SIP message to the AppearanceAgent server under test bool sendToAppearanceAgentUnderTest( SipMessage& msg ) { return pSipUserAgent->send( msg ); }
void testRefreshMgrUATeardown() { for (int i=0; i<NUM_OF_RUNS; ++i) { SipLineMgr* lineMgr = new SipLineMgr(); SipRefreshMgr* refreshMgr = new SipRefreshMgr(); lineMgr->startLineMgr(); lineMgr->initializeRefreshMgr( refreshMgr ); SipUserAgent* sipUA = new SipUserAgent( 5090 ,5090 ,5091 ,NULL // default publicAddress ,NULL // default defaultUser ,"127.0.0.1" // default defaultSipAddress ,NULL // default sipProxyServers ,NULL // default sipDirectoryServers ,NULL // default sipRegistryServers ,NULL // default authenicateRealm ,NULL // default authenticateDb ,NULL // default authorizeUserIds ,NULL // default authorizePasswords ,lineMgr ); sipUA->start(); refreshMgr->init(sipUA); CallManager *pCallManager = new CallManager(FALSE, NULL, //LineMgr TRUE, // early media in 180 ringing NULL, // CodecFactory 9000, // rtp start 9002, // rtp end "sip:[email protected]", "sip:[email protected]", sipUA, //SipUserAgent 0, // sipSessionReinviteTimer NULL, // mgcpStackTask NULL, // 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, //inviteExpireSeconds QOS_LAYER3_LOW_DELAY_IP_TOS, // expeditedIpTos 10, //maxCalls sipXmediaFactoryFactory(NULL)); //pMediaFactory #if 0 printf("Starting CallManager\n"); #endif pCallManager->start(); lineMgr->requestShutdown(); refreshMgr->requestShutdown(); sipUA->shutdown(TRUE); pCallManager->requestShutdown(); #if 0 printf("Deleting CallManager\n"); #endif delete pCallManager; delete refreshMgr; delete lineMgr; } for (int i=0; i<NUM_OF_RUNS; ++i) { sipxDestroyMediaFactoryFactory() ; } }
// Basic server functionality test. // Checks that server answers SUBSCRIBES, sends NOTIFY, sends NOTIFY // when content changes. void basicSubscriptionTest() { // Verify that authentication and authorization are // disabled by default. { SipSubscribeServerEventHandler* eventHandler = subServerp->getEventHandler(eventName); CPPUNIT_ASSERT(eventHandler); SipMessage bogusSubscribeRequest; SipMessage bogusSubscribeResponse; CPPUNIT_ASSERT(eventHandler->isAuthenticated(bogusSubscribeRequest, bogusSubscribeResponse)); CPPUNIT_ASSERT(eventHandler->isAuthorized(bogusSubscribeRequest, bogusSubscribeResponse)); } // Send a SUBSCRIBE to the notifier. SipMessage mwiSubscribeRequest; { UtlString c; CallId::getNewCallId(c); mwiSubscribeRequest.setSubscribeData(notifier_aor, // request URI subscriber_name_addr, // From notifier_name_addr, // To c, // Call-Id 0, // CSeq eventName, // Event mwiMimeType, // Accept NULL, // Event id subscriber_name_addr, // Contact NULL, // Route 3600 // Expires ); } CPPUNIT_ASSERT(subscriberUserAgentp->send(mwiSubscribeRequest)); // We should get a 202 response and a NOTIFY request in the queue OsTime messageTimeout(1, 0); // 1 second { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *subscriberUserAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); // We should have received a SUBSCRIBE response and a NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); CPPUNIT_ASSERT(notifyRequest); // Check that the response code and CSeq method in the // subscribe response are OK. { CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); UtlString subscribeMethod; subscribeResponse->getCSeqField(NULL, &subscribeMethod); ASSERT_STR_EQUAL(SIP_SUBSCRIBE_METHOD, subscribeMethod.data()); } // Check that the method in the notify request is OK. { UtlString notifyMethod; notifyRequest->getRequestMethod(¬ifyMethod); ASSERT_STR_EQUAL(SIP_NOTIFY_METHOD, notifyMethod.data()); } // Check that the Event header in the NOTIFY is the same as the // one in the SUBSCRIBE. { UtlString notifyEventHeader; UtlString subscribeEventHeader; notifyRequest->getEventField(notifyEventHeader); mwiSubscribeRequest.getEventField(subscribeEventHeader); ASSERT_STR_EQUAL(subscribeEventHeader, notifyEventHeader); } // The NOTIFY should have no body because none has been published yet. { const HttpBody* bodyPtr = notifyRequest->getBody(); CPPUNIT_ASSERT(bodyPtr == NULL); } // The Contact in the subscribe response should be the notifier. ASSERT_STR_EQUAL(notifier_contact_name_addr, subscribeResponse-> getHeaderValue(0, SIP_CONTACT_FIELD)); // The Contact in the NOTIFY should be the notifier. CPPUNIT_ASSERT(notifyRequest-> getHeaderValue(0, SIP_CONTACT_FIELD)); ASSERT_STR_EQUAL(notifier_contact_name_addr, notifyRequest-> getHeaderValue(0, SIP_CONTACT_FIELD)); } // Publish some content (mwiStateString) for this resourceID { HttpBody* newMwiBodyPtr = new HttpBody(mwiStateString, strlen(mwiStateString), mwiMimeType); SipPublishContentMgr* publishMgr = subServerp->getPublishMgr(eventName); CPPUNIT_ASSERT(publishMgr); publishMgr->publish(notifier_resource_id, eventName, eventName, 1, &newMwiBodyPtr); } // Should get a NOTIFY queued up { const SipMessage* subscribeResponse; const SipMessage* secondNotify; runListener(incomingClientMsgQueue, *subscriberUserAgentp, messageTimeout, messageTimeout, secondNotify, subscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); CPPUNIT_ASSERT(secondNotify); CPPUNIT_ASSERT(subscribeResponse == NULL); // Check that the body of the NOTIFY is what we expect (mwiStateString). { const HttpBody* secondNotifyBody = secondNotify->getBody(); CPPUNIT_ASSERT(secondNotifyBody); ssize_t notifyBodySize; const char* notifyBodyBytes; secondNotifyBody->getBytes(¬ifyBodyBytes, ¬ifyBodySize); CPPUNIT_ASSERT(notifyBodyBytes); ASSERT_STR_EQUAL(mwiStateString, notifyBodyBytes); } // Check that the Dialog Manager reports that the dialog handle is OK. { UtlString secondNotifyDialogHandle; secondNotify->getDialogHandle(secondNotifyDialogHandle); CPPUNIT_ASSERT(!secondNotifyDialogHandle.isNull()); CPPUNIT_ASSERT(dialogMgrp->dialogExists(secondNotifyDialogHandle)); CPPUNIT_ASSERT(dialogMgrp->countDialogs() == 1); } } // Create a new one-time SUBSCRIBE SipMessage oneTimeMwiSubscribeRequest; { UtlString c; CallId::getNewCallId(c); oneTimeMwiSubscribeRequest. setSubscribeData(notifier_aor, // request URI subscriber_name_addr, // From notifier_name_addr, // To c, // Call-Id 0, // CSeq eventName, // Event mwiMimeType, // Accept NULL, // Event id subscriber_name_addr, // Contact NULL, // Route 0 // Expires ); } CPPUNIT_ASSERT(subscriberUserAgentp->send(oneTimeMwiSubscribeRequest)); { const SipMessage* oneTimeNotifyRequest; const SipMessage* oneTimeSubscribeResponse; runListener(incomingClientMsgQueue, *subscriberUserAgentp, messageTimeout, messageTimeout, oneTimeNotifyRequest, oneTimeSubscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); // Validate the one time subscribe response and notify request CPPUNIT_ASSERT(oneTimeSubscribeResponse); CPPUNIT_ASSERT(oneTimeNotifyRequest); { CPPUNIT_ASSERT(oneTimeSubscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); UtlString oneTimeSubscribeMethod; oneTimeSubscribeResponse->getCSeqField(NULL, &oneTimeSubscribeMethod); ASSERT_STR_EQUAL(SIP_SUBSCRIBE_METHOD, oneTimeSubscribeMethod.data()); UtlString oneTimeSubscribeEventHeader; oneTimeSubscribeResponse->getEventField(oneTimeSubscribeEventHeader); // The Event: header never appears in responses -- see RFC 3265 section 7.2. // The "R" in the "where" column means that "Event" appears only in // requests -- see RFC 3261 table 2 and page 160. ASSERT_STR_EQUAL("", oneTimeSubscribeEventHeader); } { UtlString oneTimeNotifyMethod; oneTimeNotifyRequest->getRequestMethod(&oneTimeNotifyMethod); ASSERT_STR_EQUAL(SIP_NOTIFY_METHOD, oneTimeNotifyMethod.data()); UtlString oneTimeNotifyEventHeader; oneTimeNotifyRequest->getEventField(oneTimeNotifyEventHeader); // The Event: header should appear in the NOTIFY. ASSERT_STR_EQUAL(SIP_EVENT_MESSAGE_SUMMARY, oneTimeNotifyEventHeader); } { const HttpBody* oneTimeBodyPtr = oneTimeNotifyRequest->getBody(); CPPUNIT_ASSERT(oneTimeBodyPtr != NULL); const char* oneTimeBodyString; ssize_t oneTimeNotifyBodySize; oneTimeBodyPtr->getBytes(&oneTimeBodyString, &oneTimeNotifyBodySize); ASSERT_STR_EQUAL(mwiStateString, oneTimeBodyString); } { UtlString oneTimeNotifyDialogHandle; oneTimeNotifyRequest->getDialogHandle(oneTimeNotifyDialogHandle); CPPUNIT_ASSERT(!oneTimeNotifyDialogHandle.isNull()); CPPUNIT_ASSERT(dialogMgrp->dialogExists(oneTimeNotifyDialogHandle)); CPPUNIT_ASSERT(dialogMgrp->countDialogs() == 2); long now = OsDateTime::getSecsSinceEpoch(); subMgrp->removeOldSubscriptions(now + 1); // The one time subscription should get garbage collected // leaving only the persistant 3600 second subscription CPPUNIT_ASSERT(dialogMgrp->countDialogs() == 1); } } }
int main(int argc, char* argv[]) { int port; int expiration; char* targetURI; char* eventType; char* contentType; char* realm; char* user; char* password; // Initialize logging. OsSysLog::initialize(0, "test"); OsSysLog::setOutputFile(0, "log"); OsSysLog::setLoggingPriority(PRI_DEBUG); OsSysLog::setLoggingPriorityForFacility(FAC_SIP_INCOMING_PARSED, PRI_ERR); if (!parseArgs(argc, argv, &port, &expiration, &targetURI, &eventType, &contentType, &realm, &user, &password)) { usage(argv[0]); exit(1); } // The domain name to call myself, obtained from the gethostname() // system call. char buffer[100]; memset(buffer, 0, sizeof (buffer)); // Do not allow gethostname to write over the last NUL in buffer[]. gethostname(buffer, (sizeof (buffer)) - 1); UtlString myDomainName(buffer, strlen(buffer)); // Use "example.com" if gethostname() failed. if (myDomainName.isNull()) { myDomainName = "example.com"; } UtlString fromString = "sip:dialogwatch@" + myDomainName; Url fromUri(fromString, TRUE); // Create the SIP Subscribe Client SipLineMgr lineMgr; // Add credentials if they were specified. if (realm) { UtlString id; id += "sip:"; id += user; id += "@"; id += realm; Url identity(id, TRUE); SipLine line( fromUri // user entered url ,identity // identity url ,user // user ,TRUE // visible ,SipLine::LINE_STATE_PROVISIONED ,TRUE // auto enable ,FALSE // use call handling ); lineMgr.addLine(line); UtlString cred_input; UtlString cred_digest; cred_input.append(user); cred_input.append(":"); cred_input.append(realm); cred_input.append(":"); cred_input.append(password); NetMd5Codec::encode(cred_input.data(), cred_digest); fprintf(stderr, "Adding identity '%s': user='******' realm='%s' password='******' H(A1)='%s'\n", identity.toString().data(), user, realm, password, cred_digest.data() ); assert(lineMgr.addCredentialForLine(identity, realm, user, cred_digest, HTTP_DIGEST_AUTHENTICATION)); } SipUserAgent* pSipUserAgent = new SipUserAgent(port, port, PORT_NONE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &lineMgr); // Add the 'eventlist' extension, so dialogwatch can subscribe to // event lists. pSipUserAgent->allowExtension("eventlist"); if (!pSipUserAgent->isOk()) { fprintf(stderr, "Unable to bind to port %d\n", port); exit(1); } SipDialogMgr dialogManager; SipRefreshManager refreshMgr(*pSipUserAgent, dialogManager); refreshMgr.start(); SipSubscribeClient sipSubscribeClient(*pSipUserAgent, dialogManager, refreshMgr); sipSubscribeClient.start(); // Construct a name-addr from targetURI, in case it contains parameters. UtlString toUri; toUri = "<"; toUri += targetURI; toUri += ">"; UtlString earlyDialogHandle; fprintf(stderr, "resourceId '%s' fromString '%s' toUri '%s' event '%s' content-type '%s' port=%d expiration=%d\n", targetURI, fromString.data(), toUri.data(), eventType, contentType, port, expiration); UtlBoolean status = sipSubscribeClient.addSubscription(targetURI, eventType, contentType, fromString.data(), toUri.data(), NULL, expiration, (void *) NULL, subscriptionStateCallback, notifyEventCallback, earlyDialogHandle); if (!status) { fprintf(stderr, "Subscription attempt failed.\n"); exit(1); } else { fprintf(stderr, "Subscription attempt succeeded. Handle: '%s'\n", earlyDialogHandle.data()); } while (1) { sleep(1000); } }
int proxy() { int proxyTcpPort; int proxyUdpPort; int proxyTlsPort; UtlString bindIp; int maxForwards; UtlString domainName; UtlString proxyRecordRoute; UtlString routeName; UtlString authScheme; UtlString ipAddress; OsMsgQShared::setQueuePreference(OsMsgQShared::QUEUE_UNLIMITED); OsSocket::getHostIp(&ipAddress); OsPath ConfigfileName = SipXecsService::Path(SipXecsService::ConfigurationDirType, CONFIG_SETTINGS_FILE); OsConfigDb configDb; if(OS_SUCCESS != configDb.loadFromFile(ConfigfileName)) { exit(1); } // Initialize the OsSysLog... initSysLog(&configDb); std::set_terminate(catch_global); configDb.get(CONFIG_SETTING_BIND_IP, bindIp); if ((bindIp.isNull()) || !OsSocket::isIp4Address(bindIp)) { bindIp = "0.0.0.0"; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "%s: %s", CONFIG_SETTING_BIND_IP, bindIp.data()); osPrintf("%s: %s", CONFIG_SETTING_BIND_IP, bindIp.data()); UtlString hostname; configDb.get("SIPX_PROXY_HOST_NAME", hostname); if (!hostname.isNull()) { // bias the selection of SRV records so that if the name of this host is an alternative, // it wins in any selection based on random weighting. SipSrvLookup::setOwnHostname(hostname); } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_HOST_NAME : %s", hostname.data()); proxyUdpPort = configDb.getPort("SIPX_PROXY_UDP_PORT"); if (!portIsValid(proxyUdpPort)) { proxyUdpPort = 5060; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_UDP_PORT : %d", proxyUdpPort); proxyTcpPort = configDb.getPort("SIPX_PROXY_TCP_PORT") ; if (!portIsValid(proxyTcpPort)) { proxyTcpPort = 5060; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_TCP_PORT : %d", proxyTcpPort); proxyTlsPort = configDb.getPort("SIPX_PROXY_TLS_PORT") ; if (!portIsValid(proxyTlsPort)) { proxyTlsPort = 5061; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_TLS_PORT : %d", proxyTlsPort); configDb.get("SIPX_PROXY_MAX_FORWARDS", maxForwards); if(maxForwards <= 0) maxForwards = SIP_DEFAULT_MAX_FORWARDS; Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_MAX_FORWARDS : %d", maxForwards); osPrintf("SIPX_PROXY_MAX_FORWARDS : %d\n", maxForwards); int branchTimeout = -1; configDb.get("SIPX_PROXY_BRANCH_TIMEOUT", branchTimeout); if(branchTimeout < 4) { branchTimeout = 24; } int defaultExpires; int defaultSerialExpires; configDb.get("SIPX_PROXY_DEFAULT_EXPIRES", defaultExpires); configDb.get("SIPX_PROXY_DEFAULT_SERIAL_EXPIRES", defaultSerialExpires); if(defaultExpires <= 0 ) { defaultExpires = DEFAULT_SIP_TRANSACTION_EXPIRES; } else if(defaultExpires > DEFAULT_SIP_TRANSACTION_EXPIRES) { Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXproxymain::proxy " "large default expires value: %d NOT RECOMMENDED", defaultExpires); } if(defaultSerialExpires <= 0 || defaultSerialExpires >= defaultExpires) { defaultSerialExpires = DEFAULT_SIP_SERIAL_EXPIRES; } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_DEFAULT_EXPIRES : %d", defaultExpires); osPrintf("SIPX_PROXY_DEFAULT_EXPIRES : %d\n", defaultExpires); Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_DEFAULT_SERIAL_EXPIRES : %d", defaultSerialExpires); osPrintf("SIPX_PROXY_DEFAULT_SERIAL_EXPIRES : %d\n", defaultSerialExpires); UtlString hostAliases; configDb.get("SIPX_PROXY_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); } Os::Logger::instance().log(FAC_SIP, PRI_NOTICE, "SIPX_PROXY_HOST_ALIASES not configured" " using implied value: %s", hostAliases.data()); } Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_HOST_ALIASES : %s", 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; Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipXproxymain:: invalid configuration value for " CONFIG_SETTING_CALL_STATE " '%s' - should be 'enable' or 'disable'", enableCallStateObserverSetting.data() ); } Os::Logger::instance().log(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; } Os::Logger::instance().log(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; Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipAuthProxyMain:: invalid configuration value for %s " " '%s' - should be 'enable' or 'disable'", CONFIG_SETTING_CALL_STATE_DB, enableCallStateDbObserverSetting.data() ); } Os::Logger::instance().log(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; } Os::Logger::instance().log(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; } Os::Logger::instance().log(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; } Os::Logger::instance().log(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; } Os::Logger::instance().log(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; Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXproxymain:: 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("SIPX_PROXY_STALE_TCP_TIMEOUT", staleTcpTimeoutStr); if (staleTcpTimeoutStr.isNull()) { staleTcpTimeout = 3600; } else { // get the parameter value as an integer configDb.get("SIPX_PROXY_STALE_TCP_TIMEOUT", staleTcpTimeout); } if(staleTcpTimeout <= 0) staleTcpTimeout = -1; else if(staleTcpTimeout < 180) staleTcpTimeout = 180; Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_STALE_TCP_TIMEOUT : %d", staleTcpTimeout); osPrintf("SIPX_PROXY_STALE_TCP_TIMEOUT : %d\n", staleTcpTimeout); int maxNumSrvRecords = -1; configDb.get("SIPX_PROXY_DNSSRV_MAX_DESTS", maxNumSrvRecords); Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_DNSSRV_MAX_DESTS : %d", maxNumSrvRecords); // If explicitly set to a valid number if(maxNumSrvRecords > 0) { osPrintf("SIPX_PROXY_DNSSRV_MAX_DESTS : %d\n", maxNumSrvRecords); } else { maxNumSrvRecords = 4; } int dnsSrvTimeout = -1; //seconds configDb.get("SIPX_PROXY_DNSSRV_TIMEOUT", dnsSrvTimeout); Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_DNSSRV_TIMEOUT : %d", dnsSrvTimeout); // If explicitly set to a valid number if(dnsSrvTimeout > 0) { osPrintf("SIPX_PROXY_DNSSRV_TIMEOUT : %d\n", dnsSrvTimeout); } else { dnsSrvTimeout = 4; } // This is an obnoxious special option to work around a // problem with Sonus gateways. The Sonus proxy or redirect // server gives a list of possible gateways to recurse in a // 300 response. It does not assign any Q values so the proxy // gets the impression that it should fork them all in parallel. // When this option is enabled we recurse only the one with the // highest Q value. UtlString recurseOnlyOne300String; configDb.get("SIPX_PROXY_SPECIAL_300", recurseOnlyOne300String); recurseOnlyOne300String.toLower(); UtlBoolean recurseOnlyOne300 = FALSE; if(recurseOnlyOne300String.compareTo("enable") == 0) { recurseOnlyOne300 = TRUE; Os::Logger::instance().log(FAC_SIP, PRI_INFO, "SIPX_PROXY_SPECIAL_300 : ENABLE"); osPrintf("SIPX_PROXY_SPECIAL_300 : ENABLE\n"); } OsPath fileName = SipXecsService::Path(SipXecsService::ConfigurationDirType, FORWARDING_RULES_FILENAME); ForwardRules forwardingRules; OsFile ruleFile(fileName); if(ruleFile.exists()) { if(OS_SUCCESS != forwardingRules.loadMappings(fileName)) { Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "WARNING: Failed to load: %s", fileName.data()); osPrintf("WARNING: Failed to load: %s\n", fileName.data()); } } else { // forwardingrules.xml is not readable; no processing is possible. Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "forwarding rules '%s' not found -- exiting", fileName.data()); exit(1); } #ifdef TEST_PRINT { // scope the test stuff SipMessage foo; const char* uri = "sip:10.1.20.3:5100"; const char* method = SIP_ACK_METHOD; const char* eventType = SIP_EVENT_CONFIG; foo.setRequestData(method, uri, //uri, "sip:[email protected]", // fromField, "\"lajdflsdk ff\"<sip:[email protected]>", // toField, "lkadsj902387", // callId, 123, // CSeq, "sip:10.1.1.123");// contactUrl // Set the event type foo.setHeaderValue(SIP_EVENT_FIELD, eventType, // event type 0); Url msgUrl(uri); UtlString routeTo; UtlString routeType; bool authRequired; OsStatus routeStatus = forwardingRules.getRoute(msgUrl, foo, routeTo, routeType, authRequired); Url msgRouteToUri(routeTo); osPrintf("Message:\n\tmethod: %s\n\turi: %s\n\tevent: %s\nRouted:\n\tstring: %s\n\turi: %s\n\ttype: %s\n", method, uri, eventType, routeTo.data(), msgRouteToUri.toString().data(), routeType.data()); if(routeStatus != OS_SUCCESS) osPrintf("forwardingRules.getRoute returned: %d\n", routeStatus); } #endif // TEST_PRINT // Start the sip stack SipUserAgent* pSipUserAgent = new SipUserAgent( proxyTcpPort, proxyUdpPort, proxyTlsPort, NULL, // public IP address (not used in proxy) NULL, // default user (not used in proxy) bindIp, NULL, // outbound proxy NULL, // directory server NULL, // registry server NULL, // auth realm NULL, // auth DB NULL, // auth user IDs NULL, // auth passwords NULL, // line mgr SIP_DEFAULT_RTT, // first resend timeout FALSE, // default to proxy transaction SIPUA_DEFAULT_SERVER_UDP_BUFFER_SIZE, // socket layer read buffer size SIPUA_DEFAULT_SERVER_OSMSG_QUEUE_SIZE, // OsServerTask message queue size FALSE, // Use Next Available Port TRUE, // Perform message checks TRUE, // Use symmetric signaling SipUserAgent::HANDLE_OPTIONS_AUTOMATICALLY); if (!pSipUserAgent->isOk()) { Os::Logger::instance().log(FAC_SIP, PRI_EMERG, "SipUserAgent reported a problem, setting shutdown flag..."); gShutdownFlag = TRUE; } pSipUserAgent->setDnsSrvTimeout(dnsSrvTimeout); pSipUserAgent->setMaxSrvRecords(maxNumSrvRecords); pSipUserAgent->setUserAgentHeaderProperty("sipXecs/sipXproxy"); pSipUserAgent->setMaxForwards(maxForwards); pSipUserAgent->setDefaultExpiresSeconds(defaultExpires); pSipUserAgent->setDefaultSerialExpiresSeconds(defaultSerialExpires); pSipUserAgent->setMaxTcpSocketIdleTime(staleTcpTimeout); pSipUserAgent->setHostAliases(hostAliases); pSipUserAgent->setRecurseOnlyOne300Contact(recurseOnlyOne300); // Do not start the SipUserAgent until its message listeners are // set up by the creation of the SipRouter below. UtlString buffer; // Create the CSE observer, either writing to file or database SipXProxyCseObserver* 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; pSipUserAgent->getViaInfo(protocol, domainName, port); char portString[12]; sprintf(portString,":%d", port); domainName.append(portString); // and start the observer cseObserver = new SipXProxyCseObserver(*pSipUserAgent, domainName, pEventWriter); cseObserver->start(); } else { // Only log error if any event logging was enabled if (enableCallStateLogObserver || enableCallStateDbObserver) { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipAuthProxyMain:: EventWriter could not be allocated" ); enableCallStateLogObserver = false; enableCallStateDbObserver = false; } } // Create a router to route stuff either // to a local server or on out to the real world SipRouter* pRouter = new SipRouter(*pSipUserAgent, forwardingRules, configDb); // Start the router running pRouter->start(); // Do not exit, let the proxy do its stuff while( !gShutdownFlag ) { OsTask::delay(1000); } // This is a server task so gracefully shutdown the // router task by deleting it. delete pRouter ; // Stop the SipUserAgent. pSipUserAgent->shutdown(); // And delete it, too. delete pSipUserAgent ; // flush and close the call state event log if (enableCallStateLogObserver || enableCallStateDbObserver) { if (cseObserver) { delete cseObserver; } if (pEventWriter) { delete pEventWriter; } } // End the singleton threads. OsTimer::terminateTimerService(); OsStunAgentTask::releaseInstance(); return 0 ; }
// Primitive to send a SIP message to the RLS server under test bool sendToRlsServerUnderTest( SipMessage& msg ) { return pSipUserAgent->send( msg ); }
void subscribeMwiClientTest() { smClientExpiration = -1; smNumClientNotifiesReceived = 0; smLastClientNotifyReceived = NULL; smNumClientSubResponsesReceived = 0; smLastClientSubResponseReceived = NULL; UtlString resourceId("[email protected]:"); UtlString eventTypeKey("message-summary"); UtlString eventType(eventTypeKey); UtlString from("Frida<sip:111@localhost:"); UtlString to("Tia<sip:222@localhost:"); UtlString contact("sip:[email protected]:"); char portString[20]; sprintf(portString, "%d", UNIT_TEST_SIP_PORT); resourceId.append(portString); from.append(portString); from.append('>'); to.append(portString); to.append('>'); contact.append(portString); SipUserAgent* userAgent = new SipUserAgent(UNIT_TEST_SIP_PORT, UNIT_TEST_SIP_PORT); userAgent->start(); // Set up the subscribe client SipDialogMgr* clientDialogMgr = new SipDialogMgr(); SipRefreshManager* refreshMgr = new SipRefreshManager(*userAgent, *clientDialogMgr); refreshMgr->start(); SipSubscribeClient* subClient = new SipSubscribeClient(*userAgent, *clientDialogMgr, *refreshMgr); subClient->start(); // Set up the subscribe server SipSubscribeServer* subServer = SipSubscribeServer::buildBasicServer(*userAgent, eventType); SipSubscriptionMgr* subMgr = subServer->getSubscriptionMgr(eventType); SipDialogMgr* serverDialogMgr = subMgr->getDialogMgr(); SipPublishContentMgr* contentMgr = subServer->getPublishMgr(eventType); HttpBody* preexistingBodyPtr = NULL; UtlBoolean isDefaultContent; subServer->start(); // Enable the handler for the MWI server subServer->enableEventType(eventType, userAgent); //CPPUNIT_ASSERT(TRUE); //ASSERT_STR_EQUAL("a", "a"); // Create a crude Subscription server/observer OsMsgQ incomingServerMsgQueue; // Register an interest in SUBSCRIBE requests // for this event type userAgent->addMessageObserver(incomingServerMsgQueue, SIP_SUBSCRIBE_METHOD, TRUE, // requests FALSE, // no reponses TRUE, // incoming FALSE, // no outgoing eventType, NULL, NULL); OsMsgQ incomingClientMsgQueue; userAgent->addMessageObserver(incomingClientMsgQueue, SIP_SUBSCRIBE_METHOD, FALSE, // no requests TRUE, // reponses TRUE, // incoming FALSE, // no outgoing eventType, NULL, NULL); // Should not be any pre-existing content CPPUNIT_ASSERT(!contentMgr->getContent(resourceId, eventTypeKey, NULL, preexistingBodyPtr, isDefaultContent)); int numDefaultContent = -1; int numResourceSpecificContent = -1; int numCallbacksRegistered = -1; contentMgr->getStats(numDefaultContent, numResourceSpecificContent, numCallbacksRegistered); CPPUNIT_ASSERT(numDefaultContent == 0); CPPUNIT_ASSERT(numResourceSpecificContent == 0); CPPUNIT_ASSERT(numCallbacksRegistered == 1); // Create a subscribe request, send it and keep it refreshed UtlString earlyDialogHandle; CPPUNIT_ASSERT(subClient->addSubscription(resourceId, eventType, from, to, contact, 60, // seconds expiration this, subStateCallback, notifyCallback, earlyDialogHandle)); contentMgr->getStats(numDefaultContent, numResourceSpecificContent, numCallbacksRegistered); CPPUNIT_ASSERT(numDefaultContent == 0); CPPUNIT_ASSERT(numResourceSpecificContent == 0); CPPUNIT_ASSERT(numCallbacksRegistered == 1); // See if a subscribe was sent and received /*OsTime messageTimeout(5, 0); // 5 seconds OsMsg* osMessage = NULL; const SipMessage* subscribeResponse = NULL; const SipMessage* notifyRequest = NULL; incomingServerMsgQueue.receive(osMessage, messageTimeout); CPPUNIT_ASSERT(osMessage); int msgType = osMessage->getMsgType(); int msgSubType = osMessage->getMsgSubType(); CPPUNIT_ASSERT(msgType == OsMsg::PHONE_APP); CPPUNIT_ASSERT(msgSubType == SipMessage::NET_SIP_MESSAGE); const SipMessage* sipMessage = ((SipMessageEvent*)osMessage)->getMessage(); int messageType = ((SipMessageEvent*)osMessage)->getMessageStatus(); CPPUNIT_ASSERT(sipMessage); CPPUNIT_ASSERT(messageType == SipMessageEvent::APPLICATION);*/ const SipMessage* serverSideSubRequest = NULL; CPPUNIT_ASSERT(removeMessage(incomingServerMsgQueue, 5000, // milliseconds serverSideSubRequest)); CPPUNIT_ASSERT(serverSideSubRequest); // Sub request got to server const SipMessage* clientSideSubResponse = NULL; CPPUNIT_ASSERT(removeMessage(incomingClientMsgQueue, 5000, // milliseconds clientSideSubResponse)); CPPUNIT_ASSERT(clientSideSubResponse); //UtlString clientStateString; //subClient->dumpStates(clientStateString); //printf("client states:\n%s\n", clientStateString.data()); int waitIterations = 0; while(smLastClientNotifyReceived == NULL || smLastClientSubResponseReceived == NULL) { OsTask::delay(100); waitIterations++; if(waitIterations >= 100) { break; } } CPPUNIT_ASSERT(smLastClientSubResponseReceived); CPPUNIT_ASSERT(smLastClientNotifyReceived); SipMessage* firstSubResponse = smLastClientSubResponseReceived; smLastClientSubResponseReceived = NULL; int firstSubCseq; firstSubResponse->getCSeqField(&firstSubCseq, NULL); SipMessage* firstNotifyRequest = smLastClientNotifyReceived; smLastClientNotifyReceived = NULL; int firstNotifyCseq; firstNotifyRequest->getCSeqField(&firstNotifyCseq, NULL); CPPUNIT_ASSERT(firstSubCseq == 1); CPPUNIT_ASSERT(firstNotifyCseq == 0); //subClient->dumpStates(clientStateString); //printf("client states:\n%s\n", clientStateString.data()); //UtlString dialogMgrDumpString; //clientDialogMgr.toString(dialogMgrDumpString); //printf("Client Dialog manager dump 1:\n%s\n", // dialogMgrDumpString.data()); // The refresh manager should re-SUBSCRIBE // Wait for the next notify request and subscribe response int secondMessageWait = 60; int resendTimeout = 0.55 * secondMessageWait; if(resendTimeout < 40) { resendTimeout = 40; } for(int i = 0; i < secondMessageWait - 1; i++) { if(i == resendTimeout - 1) { printf("v"); } else { printf("="); } } printf("v\n"); SipMessage* secondSubResponse = NULL; SipMessage* secondNotifyRequest = NULL; while(secondNotifyRequest == NULL || secondSubResponse == NULL) { OsTask::delay(1000); if(smLastClientSubResponseReceived) { secondSubResponse = smLastClientSubResponseReceived; smLastClientSubResponseReceived = NULL; } if(smLastClientNotifyReceived) { secondNotifyRequest = smLastClientNotifyReceived; smLastClientNotifyReceived = NULL; } printf("."); waitIterations++; if(waitIterations >= secondMessageWait) { printf("\n"); break; } } //subClient->dumpStates(clientStateString); //printf("client states:\n%s\n", clientStateString.data()); //clientDialogMgr.toString(dialogMgrDumpString); //printf("Client Dialog manager dump 2:\n%s\n", // dialogMgrDumpString.data()); CPPUNIT_ASSERT(removeMessage(incomingServerMsgQueue, 5000, // milliseconds serverSideSubRequest)); CPPUNIT_ASSERT(serverSideSubRequest); // Sub request got to server //UtlString subRequestDump; //int len; //serverSideSubRequest->getBytes(&subRequestDump, &len); //printf("server side sub request:\n%s\n", // subRequestDump.data()); CPPUNIT_ASSERT(removeMessage(incomingClientMsgQueue, 5000, // milliseconds clientSideSubResponse)); CPPUNIT_ASSERT(clientSideSubResponse); // Sub respon got to client //UtlString subResponseDump; //clientSideSubResponse->getBytes(&subResponseDump, &len); //printf("client side sub response:\n%s\n", // subResponseDump.data()); CPPUNIT_ASSERT(secondNotifyRequest); CPPUNIT_ASSERT(secondSubResponse); int secondSubCseq = -1; int secondNotifyCseq = -1; smLastClientSubResponseReceived = NULL; secondSubResponse->getCSeqField(&secondSubCseq, NULL); smLastClientNotifyReceived = NULL; secondNotifyRequest->getCSeqField(&secondNotifyCseq, NULL); CPPUNIT_ASSERT(firstSubCseq < secondSubCseq); CPPUNIT_ASSERT(firstNotifyCseq < secondNotifyCseq); // Unregister the queues so we stop receiving messages on them userAgent->removeMessageObserver(incomingServerMsgQueue); userAgent->removeMessageObserver(incomingClientMsgQueue); refreshMgr->requestShutdown(); subClient->requestShutdown(); }
// Constructor SipXProxyCseObserver::SipXProxyCseObserver(SipUserAgent& sipUserAgent, const UtlString& dnsName, CallStateEventWriter* pWriter ) : OsServerTask("SipXProxyCseObserver-%d", NULL, 2000), mpSipUserAgent(&sipUserAgent), mpBuilder(NULL), mpWriter(pWriter), mSequenceNumber(0), mFlushTimer(getMessageQueue(), 0) { OsTime timeNow; OsDateTime::getCurTime(timeNow); UtlString event; if (mpWriter) { switch (pWriter->getLogType()) { case CallStateEventWriter::CseLogFile: mpBuilder = new CallStateEventBuilder_XML(dnsName); break; case CallStateEventWriter::CseLogDatabase: mpBuilder = new CallStateEventBuilder_DB(dnsName); break; } if (mpBuilder) { if (pWriter->openLog()) { mpBuilder->observerEvent(mSequenceNumber, timeNow, CallStateEventBuilder::ObserverReset, "SipXProxyCseObserver"); mpBuilder->finishElement(event); if (!mpWriter->writeLog(event.data())) { OsSysLog::add(FAC_SIP, PRI_ERR, "SipXProxyCseObserver initial event log write failed - disabling writer"); mpWriter = NULL; } else { mpWriter->flush(); // try to ensure that at least the sequence restart gets to the file } } else { OsSysLog::add(FAC_SIP, PRI_ERR, "SipXProxyCseObserver initial event log write failed - disabling writer"); mpWriter = NULL; // Set correct state even if nothing is written mpBuilder->observerEvent(mSequenceNumber, timeNow, CallStateEventBuilder::ObserverReset, ""); mpBuilder->finishElement(event); } } } // set up periodic timer to flush log file mFlushTimer.periodicEvery(OsTime(), OsTime(SipXProxyCallStateFlushInterval, 0)) ; // Register to get incoming requests sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_BYE_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_INVITE_METHOD, TRUE, // Requests, TRUE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_REFER_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); }
void instantiateAllTestFixtures( UtlString AppearanceGroupFile, //< Name of the appearance group file to use for the test. The filename //< specified must exist in .../sipXrls/src/test/saadata/ UtlString subscriptionDbName, //< Specifies the subscription DB to use for the test. The name //< is used to select which of the files in .../sipXrls/src/test/saadata/ //< will get used to preload the subscription IMDB. The name provided here is the //< xml file in .../sipXrls/src/test/saadata/ without the ".xml" extension. UtlString credentialDbName, //< Specifies the credential DB to use for the test. The name //< is used to select which of the files in .../sipXrls/src/test/saadata/ //< will get used to preload the credential IMDB. The name provided here is the //< xml file in .../sipXrls/src/test/saadata/ without the ".xml" extension. UtlString domainName //< Specify the domain name to use for the test ) { mCredentialDbName = credentialDbName; // force copy of input files into the 'work' directory sipDbContext.inputFile( subscriptionDbName + ".xml" ); sipDbContext.inputFile( credentialDbName + ".xml" ); UtlString tempAppearanceGroupFile = UtlString(TEST_DATA_DIR) + "/" + AppearanceGroupFile; pSipUserAgent = new SipUserAgent( 45141, 45141, 45142 ,"127.0.0.1" // default publicAddress ,NULL // default defaultUser ,"127.0.0.1" ); // default defaultSipAddress // Stop SipUserAgent from rejecting all SUBSCRIBEs pSipUserAgent->allowMethod(SIP_SUBSCRIBE_METHOD, true); SipXecsService* saaTestService = new SipXecsService("sipxsaaTest", "SIPX_SAA", "TestCase"); pAppearanceAgentUnderTest = new AppearanceAgent(saaTestService, domainName, // domain "rlstest.test", // realm NULL, // line manager 45140, // TCP port 45140, // UDP port 45140, // TLS port "127.0.0.1", // Bind IP address &tempAppearanceGroupFile, (24 * 60 * 60), // Default subscription refresh interval (60 * 60), // Default subscription resubscribe interval. (40 * 60), // Default minimum subscription resubscribe interval. (20 * 60), // Default seized subscription resubscribe interval. 250, // publishing delay? 20, // The maximum number of reg subscriptions per group. 32, 3600, 86400, // Subscribe server expiration parameters subscriptionDbName, credentialDbName ); pUasOutputProcessor = new OutputProcessorFixture(); pAppearanceAgentUnderTest->mServerUserAgent.addSipOutputProcessor( pUasOutputProcessor ); UtlString proxyAddress; proxyAddress = "127.0.0.1:45140"; pSipUserAgent->setProxyServers(proxyAddress.data()); pAppearanceAgentUnderTest->start(); }
// Test for XECS-243, Subscribe Server does not send NOTIFY when it // processes a re-SUBSCRIBE. //*** Error scenario not yet reproduced. void resubscribeContentTest() { // Test MWI messages const char* mwiSubscribe = "SUBSCRIBE sip:111@localhost SIP/2.0\r\n" "From: <sip:[email protected]>;tag=1612c1612\r\n" "To: <sip:[email protected]>\r\n" "Cseq: 1 SUBSCRIBE\r\n" "Event: message-summary\r\n" "Accept: application/simple-message-summary\r\n" "Expires: 3600\r\n" "Date: Tue, 26 Apr 2005 14:59:30 GMT\r\n" "Max-Forwards: 20\r\n" "User-Agent: Pingtel/2.2.0 (VxWorks)\r\n" "Accept-Language: en\r\n" "Supported: sip-cc, sip-cc-01, timer, replaces\r\n" "Content-Length: 0\r\n" "\r\n"; // Send a SUBSCRIBE to ourselves SipMessage mwiSubscribeRequest(mwiSubscribe); { UtlString c; CallId::getNewCallId(c); mwiSubscribeRequest.setCallIdField(c); } mwiSubscribeRequest.setSipRequestFirstHeaderLine(SIP_SUBSCRIBE_METHOD, aor, SIP_PROTOCOL_VERSION); mwiSubscribeRequest.setContactField(aor_name_addr); CPPUNIT_ASSERT(userAgentp->send(mwiSubscribeRequest)); // We should get a 202 response and a NOTIFY request in the queue // Send a 500 response to the NOTIFY. OsTime messageTimeout(1, 0); // 1 second { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *userAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, SIP_SERVER_INTERNAL_ERROR_CODE, FALSE, 0, NULL); // We should have received a SUBSCRIBE response and a NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); CPPUNIT_ASSERT(notifyRequest); CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); // The NOTIFY should have no body because none has been published yet. { const HttpBody* bodyPtr = notifyRequest->getBody(); CPPUNIT_ASSERT(bodyPtr == NULL); } } // Send a re-SUBSCRIBE mwiSubscribeRequest.incrementCSeqNumber(); // Leave the Expires header with the default value. CPPUNIT_ASSERT(userAgentp->send(mwiSubscribeRequest)); // We should get a 202 response and a NOTIFY request in the queue { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *userAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); // We should have received a SUBSCRIBE response and a NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); CPPUNIT_ASSERT(notifyRequest); CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); // The NOTIFY should have no body because none has been published yet. { const HttpBody* bodyPtr = notifyRequest->getBody(); CPPUNIT_ASSERT(bodyPtr == NULL); } } }
// Test for XECS-247, When subscribe server receives 481 for a // NOTIFY, it does not terminate the subscription. // Test for XECS-282, When subscribe server receives 500 for a // NOTIFY, it does not terminate the subscription. // Verify that subscription is terminated when NOTIFY returns a variety // of error responses. (Retry-After suppresses termination. That case // is tested in terminateSubscriptionOnErrorRetryAfter.) void terminateSubscriptionOnError() { // Test MWI messages const char* mwiSubscribe = "SUBSCRIBE sip:111@localhost SIP/2.0\r\n" "From: <sip:[email protected]>;tag=1612c1612\r\n" "To: <sip:[email protected]>\r\n" "Cseq: 1 SUBSCRIBE\r\n" "Event: message-summary\r\n" "Accept: application/simple-message-summary\r\n" "Expires: 3600\r\n" "Date: Tue, 26 Apr 2005 14:59:30 GMT\r\n" "Max-Forwards: 20\r\n" "User-Agent: Pingtel/2.2.0 (VxWorks)\r\n" "Accept-Language: en\r\n" "Supported: sip-cc, sip-cc-01, timer, replaces\r\n" "Content-Length: 0\r\n" "\r\n"; // Loop through this scenario for a series of response codes. int test_codes[] = { SIP_BAD_REQUEST_CODE, SIP_NOT_FOUND_CODE, SIP_BAD_TRANSACTION_CODE, 499, SIP_SERVER_INTERNAL_ERROR_CODE, SIP_SERVICE_UNAVAILABLE_CODE, 599, SIP_GLOBAL_BUSY_CODE, 699 }; for (unsigned int i = 0; i < sizeof (test_codes) / sizeof (test_codes[0]); i++) { // Send a SUBSCRIBE to ourselves SipMessage mwiSubscribeRequest(mwiSubscribe); { UtlString c; CallId::getNewCallId(c); mwiSubscribeRequest.setCallIdField(c); } mwiSubscribeRequest.setSipRequestFirstHeaderLine(SIP_SUBSCRIBE_METHOD, aor, SIP_PROTOCOL_VERSION); mwiSubscribeRequest.setContactField(aor_name_addr); mwiSubscribeRequest.incrementCSeqNumber(); CPPUNIT_ASSERT(userAgentp->send(mwiSubscribeRequest)); // We should get a 202 response and a NOTIFY request in the queue // Send the specified response to the NOTIFY. OsTime messageTimeout(1, 0); // 1 second { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *userAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, test_codes[i], FALSE, 0, NULL); // We should have received a SUBSCRIBE response and a NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); // Extract the to-tag in the response, apply it to // mwiSubscribeRequest. Url toUrl; subscribeResponse->getToUrl(toUrl); UtlString toTag; toUrl.getFieldParameter("tag", toTag); mwiSubscribeRequest.setToFieldTag(toTag); CPPUNIT_ASSERT(notifyRequest); CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); } // Wait for the subscription to be ended. OsTask::delay(100); // Send a re-SUBSCRIBE in the existing dialog, to find out if the // subscription was terminated or not. mwiSubscribeRequest.incrementCSeqNumber(); // Leave the Expires header with the default value. CPPUNIT_ASSERT(userAgentp->send(mwiSubscribeRequest)); // We should get a 481 response and no NOTIFY, because the // subscription has been terminated. { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *userAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); // We should have received a SUBSCRIBE response and no NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_BAD_TRANSACTION_CODE); CPPUNIT_ASSERT(!notifyRequest); } } }
// XECS-1810: Verify that subscription is *not* terminated when NOTIFY // returns a Timeout error. void terminateSubscriptionOnErrorTimeout() { // Test MWI messages const char* mwiSubscribe = "SUBSCRIBE sip:111@localhost SIP/2.0\r\n" "From: <sip:[email protected]>;tag=1612c1612\r\n" "To: <sip:[email protected]>\r\n" "Cseq: 1 SUBSCRIBE\r\n" "Event: message-summary\r\n" "Accept: application/simple-message-summary\r\n" "Expires: 3600\r\n" "Date: Tue, 4 Nov 2008 15:59:30 GMT\r\n" "Max-Forwards: 20\r\n" "User-Agent: Pingtel/2.2.0 (VxWorks)\r\n" "Accept-Language: en\r\n" "Supported: sip-cc, sip-cc-01, timer, replaces\r\n" "Content-Length: 0\r\n" "\r\n"; // Send a SUBSCRIBE to ourselves SipMessage mwiSubscribeRequest(mwiSubscribe); { UtlString c; CallId::getNewCallId(c); mwiSubscribeRequest.setCallIdField(c); } mwiSubscribeRequest.setSipRequestFirstHeaderLine(SIP_SUBSCRIBE_METHOD, aor, SIP_PROTOCOL_VERSION); mwiSubscribeRequest.setContactField(aor_name_addr); mwiSubscribeRequest.incrementCSeqNumber(); CPPUNIT_ASSERT(userAgentp->send(mwiSubscribeRequest)); // We should get a 202 response and a NOTIFY request in the queue // Send a Timeout error response to the NOTIFY. OsTime messageTimeout(1, 0); // 1 second { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *userAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, SIP_REQUEST_TIMEOUT_CODE, FALSE, 0, NULL); // We should have received a SUBSCRIBE response and a NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); CPPUNIT_ASSERT(notifyRequest); // Extract the to-tag in the response, apply it to mwiSubscribeRequest. // This allows the re-SUBSCRIBE below to be applied to the existing dialog. Url toUrl; subscribeResponse->getToUrl(toUrl); UtlString toTag; toUrl.getFieldParameter("tag", toTag); mwiSubscribeRequest.setToFieldTag(toTag); } // Send a re-SUBSCRIBE in the existing dialog, to find out if the // subscription was terminated or not. mwiSubscribeRequest.incrementCSeqNumber(); // Leave the Expires header with the default value. CPPUNIT_ASSERT(userAgentp->send(mwiSubscribeRequest)); // We should get a 202 response and a NOTIFY, because the Timeout // error suppresses the termination of the subscription. { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *userAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); // We should have received a SUBSCRIBE response and no NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); CPPUNIT_ASSERT(notifyRequest); CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); } }
void instantiateAllTestFixtures( UtlString resourceListFile, //< Name of the resource list to use for the test. The filename //< specified mus texist in .../sipXrls/src/test/rlsdata/ UtlString subscriptionDbName, //< Specifies the subscription DB to use for the test. The name //< is used to select which of the files in .../sipXrls/src/test/rlsdata/ //< will get used to preload the subscription IMDB. The name provided here is the //< xml file in .../sipXrls/src/test/rlsdata/ without the ".xml" extension. UtlString credentialDbName, //< Specifies the credential DB to use for the test. The name //< is used to select which of the files in .../sipXrls/src/test/rlsdata/ //< will get used to preload the credential IMDB. The name provided here is the //< xml file in .../sipXrls/src/test/rlsdata/ without the ".xml" extension. UtlString domianName, //< Specify the domain name to use for the test UtlBoolean routeAllRequestsToRlsServer //< Send all requests to either the RLS Server UA or the RLS Client UA //< The Client UA typically deals with the outgoing subscriptions and //< the Server UA deals witht the incoming subscriptions ) { mCredentialDbName = credentialDbName; // force copy of input files into the 'work' directory sipDbContext.inputFile( subscriptionDbName + ".xml" ); sipDbContext.inputFile( credentialDbName + ".xml" ); UtlString tempResourceListFile = UtlString(TEST_DATA_DIR) + "/" + resourceListFile; pSipUserAgent = new SipUserAgent( 45141, 45141, 45142 ,"127.0.0.1" // default publicAddress ,NULL // default defaultUser ,"127.0.0.1" ); // default defaultSipAddress // Stop SipUserAgent from rejecting all SUBSCRIBEs pSipUserAgent->allowMethod(SIP_SUBSCRIBE_METHOD, true); SipXecsService* rlsTestService = new SipXecsService("sipxrlsTest", "SIPX_RLS", "TestCase"); pResourceServerUnderTest = new ResourceListServer(rlsTestService, domianName, // domain "rlstest.test", // realm NULL, DIALOG_EVENT_TYPE, DIALOG_EVENT_CONTENT_TYPE, 45140, // TCP port 45140, // UDP port 45140, // TLS port "127.0.0.1", // Bind IP address &tempResourceListFile, (60 * 60), // Default subscription resubscribe interval. (40 * 60), // Default minimum subscription resubscribe interval. 250, // publishing delay? 20, // The maximum number of reg subscriptions per resource. 20, // The maximum number of contacts per reg subscription. 20, // The maximum number of resource instances per contact 20, // The maximum number of dialogs per resource instance 32, 3600, 86400, // Subscribe server expiration parameters subscriptionDbName, credentialDbName ); pUacOutputProcessor = new OutputProcessorFixture(); pUasOutputProcessor = new OutputProcessorFixture(); pResourceServerUnderTest->mClientUserAgent.addSipOutputProcessor( pUacOutputProcessor ); pResourceServerUnderTest->mServerUserAgent.addSipOutputProcessor( pUasOutputProcessor ); UtlString proxyAddress; if(routeAllRequestsToRlsServer) { proxyAddress = "127.0.0.1:45140"; } else { int pPort; pResourceServerUnderTest->mClientUserAgent.getLocalAddress(&proxyAddress, &pPort); proxyAddress.append(':'); proxyAddress.appendNumber(pPort); } pSipUserAgent->setProxyServers(proxyAddress.data()); pResourceServerUnderTest->start(); }
// Check the Contact header of responses to SUBSCRIBE. // Check the Contact header of NOTIFY. // XECS-297 and XECS-298. void responseContact() { // Test MWI messages const char* mwiSubscribe = "SUBSCRIBE sip:111@localhost SIP/2.0\r\n" "From: <sip:[email protected]>;tag=1612c1612\r\n" "To: <sip:[email protected]>\r\n" "Cseq: 1 SUBSCRIBE\r\n" "Event: message-summary\r\n" "Accept: application/simple-message-summary\r\n" "Expires: 3600\r\n" "Date: Tue, 26 Apr 2005 14:59:30 GMT\r\n" "Max-Forwards: 20\r\n" "User-Agent: Pingtel/2.2.0 (VxWorks)\r\n" "Accept-Language: en\r\n" "Supported: sip-cc, sip-cc-01, timer, replaces\r\n" "Content-Length: 0\r\n" "\r\n"; // Send a SUBSCRIBE to ourselves SipMessage mwiSubscribeRequest(mwiSubscribe); { UtlString c; CallId::getNewCallId(c); mwiSubscribeRequest.setCallIdField(c); } mwiSubscribeRequest.setSipRequestFirstHeaderLine(SIP_SUBSCRIBE_METHOD, aor, SIP_PROTOCOL_VERSION); mwiSubscribeRequest.setContactField(aor_name_addr); CPPUNIT_ASSERT(userAgentp->send(mwiSubscribeRequest)); // We should get a 202 response and a NOTIFY request in the queue // Send the specified response to the NOTIFY. OsTime messageTimeout(1, 0); // 1 second { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *userAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); // We should have received a SUBSCRIBE response and a NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); CPPUNIT_ASSERT(notifyRequest); CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); // Check the Contact headers. UtlString c; subscribeResponse->getContactField(0, c); ASSERT_STR_EQUAL(aor_contact_name_addr, c.data()); notifyRequest->getContactField(0, c); ASSERT_STR_EQUAL(aor_contact_name_addr, c.data()); } }
// // 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; }
// Constructor SipXProxyCseObserver::SipXProxyCseObserver(SipUserAgent& sipUserAgent, const UtlString& dnsName, CallStateEventWriter* pWriter ) : OsServerTask("SipXProxyCseObserver-%d", NULL, 2000), SipOutputProcessor( CSE_AGENT_OUTPUT_PROC_PRIO ), mpSipUserAgent(&sipUserAgent), mpBuilder(NULL), mpWriter(pWriter), mSequenceNumber(0), mFlushTimer(getMessageQueue(), 0), mCallTransMutex(OsMutex::Q_FIFO) { OsTime timeNow; OsDateTime::getCurTime(timeNow); UtlString event; if (mpWriter) { switch (pWriter->getLogType()) { case CallStateEventWriter::CseLogFile: mpBuilder = new CallStateEventBuilder_XML(dnsName); break; case CallStateEventWriter::CseLogDatabase: mpBuilder = new CallStateEventBuilder_DB(dnsName); break; } if (mpBuilder) { if (pWriter->openLog()) { mpBuilder->observerEvent(mSequenceNumber, timeNow, CallStateEventBuilder::ObserverReset, "SipXProxyCseObserver"); mpBuilder->finishElement(event); if (!mpWriter->writeLog(event.data())) { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipXProxyCseObserver initial event log write failed - disabling writer"); mpWriter = NULL; } else { mpWriter->flush(); // try to ensure that at least the sequence restart gets to the file } } else { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipXProxyCseObserver initial event log write failed - disabling writer"); mpWriter = NULL; // Set correct state even if nothing is written mpBuilder->observerEvent(mSequenceNumber, timeNow, CallStateEventBuilder::ObserverReset, ""); mpBuilder->finishElement(event); } } } // set up periodic timer to flush log file mFlushTimer.periodicEvery(OsTime(), OsTime(SipXProxyCallStateFlushInterval, 0)) ; // Register to get incoming requests sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_BYE_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_INVITE_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_REFER_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addSipOutputProcessor( this ); // set up periodic timer to cleanup dead calls in the CallTransMap mpCleanupTimeoutCallback = new OsCallback((void*)this, CleanupTransMap); mpCleanupMapTimer = new OsTimer(*mpCleanupTimeoutCallback); mpCleanupMapTimer->periodicEvery(OsTime(), OsTime(SipXProxyCallStateCleanupInterval, 0)) ; }