int OsDatagramSocket::read(char* buffer, int bufferLength) { int bytesRead; // If the remote end is not "connected" we cannot use recv if(mSimulatedConnect || !portIsValid(remoteHostPort) || remoteHostName.isNull()) { #ifdef GETFROMINFO /* [ */ if (GETFROMINFO) { int fromPort; UtlString fromAddress; bytesRead = OsSocket::read(buffer, bufferLength, &fromAddress, &fromPort); fromAddress.remove(0); } else #endif /* GETFROMINFO ] */ { bytesRead = OsSocket::read(buffer, bufferLength, (struct in_addr*) NULL, NULL); } } else { bytesRead = OsSocket::read(buffer, bufferLength); } return(bytesRead); }
// Queue a message to be sent to the specified address and port. UtlBoolean SipClient::sendTo(SipMessage& message, const char* address, int port) { UtlBoolean sendOk; if (mClientSocket) { // If port == PORT_NONE, get the correct default port for this // transport method. int portToSendTo = ( port == PORT_NONE ? defaultPort() : port ); // We are about to post a message that will cause the // SIP message to be sent. Notify the user agent so // that it can offer the message to all its registered // output processors. ssize_t msgLength = 0; UtlString msgText; message.getBytes(&msgText, &msgLength, true); if (msgLength) { system_tap_sip_tx( mLocalHostAddress.data(), portIsValid(mLocalHostPort) ? mLocalHostPort : defaultPort(), address, portToSendTo, msgText.data(), msgLength); mpSipUserAgent->executeAllSipOutputProcessors( message, address, portToSendTo ); } // Create message to queue. SipClientSendMsg sendMsg(OsMsg::OS_EVENT, SipClientSendMsg::SIP_CLIENT_SEND, message, address, portToSendTo ); // Post the message to the task's queue. OsStatus status = postMessage(sendMsg, OsTime::NO_WAIT); sendOk = status == OS_SUCCESS; if (!sendOk) { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipClient[%s]::sendTo attempt to post message failed", mName.data()); } } else { Os::Logger::instance().log(FAC_SIP, PRI_CRIT, "SipClient[%s]::sendTo called for client without socket", mName.data() ); sendOk = FALSE; } return sendOk; }
/// Implementation of OsServerTask's pure virtual method UtlBoolean SipSrvLookupThread::handleMessage(OsMsg& rMsg) { if (OsMsg::OS_SHUTDOWN == rMsg.getMsgType()) { OsTask::requestShutdown(); } else if (SRV_LOOKUP_MSG == rMsg.getMsgType()) { SrvThreadArgs * mySrvArgs = dynamic_cast <SrvThreadArgs*> (&rMsg); switch (mLookupType) { case SRV_UDP: lookup_SRV(mySrvArgs->list, *(mySrvArgs->list_length_allocated), *(mySrvArgs->list_length_used), mySrvArgs->domain.data(), mySrvArgs->service.data(), "udp", OsSocket::UDP); break; case SRV_TCP: lookup_SRV(mySrvArgs->list, *(mySrvArgs->list_length_allocated), *(mySrvArgs->list_length_used), mySrvArgs->domain.data(), mySrvArgs->service.data(), "tcp", OsSocket::TCP); break; case SRV_TLS: lookup_SRV(mySrvArgs->list, *(mySrvArgs->list_length_allocated), *(mySrvArgs->list_length_used), mySrvArgs->domain.data(), mySrvArgs->service.data(), "tls", OsSocket::SSL_SOCKET); break; case A_RECORD: lookup_A(mySrvArgs->list, *(mySrvArgs->list_length_allocated), *(mySrvArgs->list_length_used), mySrvArgs->domain.data(), // If sips service, make sure transport is set correctly. (mySrvArgs->socketType == OsSocket::UNKNOWN && strcmp(mySrvArgs->service.data(), "sips") == 0) ? OsSocket::SSL_SOCKET : mySrvArgs->socketType, NULL, // must do a query. (portIsValid(mySrvArgs->port) ? mySrvArgs->port : // use port if specified ((strcmp(mySrvArgs->service.data(), "sips") == 0) || // else use 5061 for sips; (mySrvArgs->socketType == OsSocket::SSL_SOCKET)) ? 5061 : 5060), // else use 5060. 0, 0); // Set priority and weight to 0. break; } } mQueryCompleted->signal(0); return TRUE; }
void Url::getIdentity(UtlString &identity) const { identity.remove(0); identity.append(mUserId); identity.append("@", 1); UtlString lowerHostAddress(mHostAddress); lowerHostAddress.toLower(); identity.append(lowerHostAddress); // If the port designates an actual port, it must be specified. if(portIsValid(mHostPort)) { char portBuffer[20]; sprintf(portBuffer, ":%d", mHostPort); identity.append(portBuffer); } }
UtlBoolean SipUserAgentStateless::send(SipMessage& message, OsMsgQ* responseListener, void* responseListenerData) { UtlString sendAddress; UtlString sendProtocol; int sendPort; if(message.isResponse()) { int receivedPort; UtlBoolean receivedSet; UtlBoolean maddrSet; UtlBoolean receivedPortSet; message.getLastVia(&sendAddress, &sendPort, &sendProtocol, &receivedPort, &receivedSet, &maddrSet, &receivedPortSet); if(receivedPortSet && portIsValid(receivedPort)) { sendPort = receivedPort; } } else { UtlString uriString; message.getRequestUri(&uriString); Url uri(uriString); uri.getHostAddress(sendAddress); // Check for maddr UtlString maddr; uri.getUrlParameter("maddr", maddr); if(!maddr.isNull()) { // Use maddr if present sendAddress = maddr; } uri.getUrlParameter("transport", sendProtocol); sendPort = uri.getHostPort(); } UtlBoolean sendOk = sendTo(message, sendAddress.data(), sendProtocol.data(), sendPort); return(sendOk); }
// Constructor SipTlsServer::SipTlsServer(int port, SipUserAgent* userAgent, UtlBoolean bUseNextAvailablePort) : SipTcpServer(PORT_NONE, userAgent, SIP_TRANSPORT_TLS, "SipTlsServer-%d") { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTlsServer[%s]::_ port = %d, bUseNextAvailablePort = %d", getName().data(), port, bUseNextAvailablePort); mServerPort = PORT_NONE; OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTlsServer[%s]::_ port %d", getName().data(), port); if (portIsValid(port)) { OsServerSocket* pServerSocket = new OsSSLServerSocket(64, port); // If the socket is busy or unbindable and the user requested using the // next available port, try the next SIP_MAX_PORT_RANGE ports. if (bUseNextAvailablePort && !pServerSocket->isOk()) { for (int i=1; i<=SIP_MAX_PORT_RANGE; i++) { delete pServerSocket ; pServerSocket = new OsSSLServerSocket(64, port+i); if (pServerSocket->isOk()) { break ; } } } if (pServerSocket->isOk()) { mServerPort = pServerSocket->getLocalHostPort() ; } } mDefaultPort = SIP_TLS_PORT; }
UtlBoolean SipUserAgentStateless::sendTo(SipMessage& message, const char* sendAddress, const char* sendProtocol, int sendPort) { UtlBoolean sendOk = FALSE; if(sendAddress && *sendAddress && mpUdpServer) { if (!portIsValid(sendPort)) { sendPort = SIP_PORT; } sendOk = mpUdpServer->sendTo(message, sendAddress, sendPort); } // Log the message if (isMessageLoggingEnabled()) { UtlString messageStatus; char messageChars[200]; if(sendOk) sprintf(messageChars, "Sent message %s port:%d:\n", sendAddress, sendPort); else sprintf(messageChars, "Failed to send message %s port:%d:\n", sendAddress, sendPort); messageStatus = messageChars; UtlString msgBytes; int msgLen; message.getBytes(&msgBytes, &msgLen); msgBytes.insert(0, messageStatus); msgBytes.append("--------------------END--------------------\n"); logMessage(msgBytes.data(), msgBytes.length()); } return(sendOk); }
// Get a port number from the configuration database int OsConfigDb::getPort(const char* szKey) const { assert(szKey) ; UtlString value ; int port = PORT_NONE ; if (get(szKey, value) == OS_SUCCESS) { // If the value is null, leave port == PORT_NONE. if (value.length()) { if (value.compareTo("DEFAULT", UtlString::ignoreCase) == 0) { port = PORT_DEFAULT; } else if (value.compareTo("NONE", UtlString::ignoreCase) == 0) { port = PORT_NONE; } else { port = atoi(value.data()); if (!portIsValid(port)) { port = PORT_NONE; OsSysLog::add(FAC_KERNEL, PRI_CRIT, "Invalid port number value '%s' for config variable '%s' in file '%s'.", value.data(), szKey, mIdentityLabel.data()); } } } } return port ; }
UtlBoolean SipClient::isAcceptableForDestination( const UtlString& hostName, int hostPort, const UtlString& localIp ) { UtlBoolean isAcceptable = FALSE; // Only accept it if the local IP is correct. if (0 == strcmp(getLocalIp(), localIp)) { if( isSharedSocket() ) { // A shared socket implies that it is not connected to any specific far-end host and // therefore can be used to send to any destination. isAcceptable = TRUE; } else { int tempHostPort = portIsValid(hostPort) ? hostPort : defaultPort(); #ifdef TEST_SOCKET Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::isAcceptableForDestination hostName = '%s', tempHostPort = %d, mRemoteHostName = '%s', mRemoteHostPort = %d, mRemoteSocketAddress = '%s', mReceivedAddress = '%s', mRemoteViaAddress = '%s'", mName.data(), hostName.data(), tempHostPort, mRemoteHostName.data(), mRemoteHostPort, mRemoteSocketAddress.data(), mReceivedAddress.data(), mRemoteViaAddress.data()); #endif // If the ports match and the host is the same as either the // original name that the socket was constructed with or the // name it was resolved to (usually an IP address). if ( mRemoteHostPort == tempHostPort && ( hostName.compareTo(mRemoteHostName, UtlString::ignoreCase) == 0 || hostName.compareTo(mRemoteSocketAddress, UtlString::ignoreCase) == 0)) { isAcceptable = TRUE; } else if ( mRemoteReceivedPort == tempHostPort && hostName.compareTo(mReceivedAddress, UtlString::ignoreCase) == 0) { isAcceptable = TRUE; } else if ( mSocketType == OsSocket::SSL_SOCKET && ( hostName.compareTo(mRemoteHostName, UtlString::ignoreCase) == 0 || hostName.compareTo(mRemoteSocketAddress, UtlString::ignoreCase) == 0 || hostName.compareTo(mReceivedAddress, UtlString::ignoreCase) == 0 || hostName.compareTo(mRemoteViaAddress, UtlString::ignoreCase) == 0 ) ) { isAcceptable = TRUE; } else if ( mRemoteViaPort == tempHostPort && hostName.compareTo(mRemoteViaAddress, UtlString::ignoreCase) == 0) { // Cannot trust what the other side said was their IP address // as this is a bad spoofing/denial of service hole Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::isAcceptableForDestination matches %s:%d but is not trusted", mName.data(), mRemoteViaAddress.data(), mRemoteViaPort); } } } // Make sure client is okay before declaring it acceptable if( isAcceptable && !isOk() ) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::isAcceptableForDestination('%s', %d, '%s')" " Client matches host/port but is not OK", mName.data(), hostName.data(), hostPort, localIp.data()); isAcceptable = FALSE; } return(isAcceptable); }
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); }
void OsDatagramSocket::doConnect(int remoteHostPortNum, const char* remoteHost, UtlBoolean simulateConnect) { struct hostent* server = NULL; mToSockaddrValid = FALSE; memset(mpToSockaddr, 0, sizeof(struct sockaddr_in)); remoteHostPort = remoteHostPortNum; // Store host name if(remoteHost) { remoteHostName = remoteHost ; getHostIpByName(remoteHostName, &mRemoteIpAddress); } else { remoteHostName.remove(0) ; } // Connect to a remote host if given if(portIsValid(remoteHostPort) && remoteHost && !simulateConnect) { #if defined(_WIN32) || defined(__pingtel_on_posix__) unsigned long ipAddr; ipAddr = inet_addr(remoteHost); if (ipAddr != INADDR_NONE) { server = gethostbyaddr((char * )&ipAddr,sizeof(ipAddr),AF_INET); } if ( server == NULL ) { server = gethostbyname(remoteHost); } #elif defined(_VXWORKS) char hostentBuf[512]; server = resolvGetHostByName((char*) remoteHost, hostentBuf, sizeof(hostentBuf)); #else # error Unsupported target platform. #endif //_VXWORKS if (server) { struct in_addr* serverAddr = (in_addr*) (server->h_addr); struct sockaddr_in serverSockAddr; serverSockAddr.sin_family = server->h_addrtype; serverSockAddr.sin_port = htons(remoteHostPort); serverSockAddr.sin_addr.s_addr = (serverAddr->s_addr); // Set the default destination address for the socket #if defined(_WIN32) || defined(__pingtel_on_posix__) if(connect(socketDescriptor, (const struct sockaddr*) &serverSockAddr, sizeof(serverSockAddr))) #elif defined(_VXWORKS) if(connect(socketDescriptor, (struct sockaddr*) &serverSockAddr, sizeof(serverSockAddr))) #else # error Unsupported target platform. #endif { int error = OsSocketGetERRNO(); close(); OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "OsDatagramSocket::doConnect( %s:%d ) failed w/ errno %d)", remoteHost, remoteHostPortNum, error); } else { mIsConnected = TRUE; } } else { close(); OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "OsDatagramSocket::doConnect( %s:%d ) failed host lookup)", remoteHost, remoteHostPortNum); goto EXIT; } } else if(portIsValid(remoteHostPort) && remoteHost && simulateConnect) { mIsConnected = TRUE; mSimulatedConnect = TRUE; } EXIT: ; }
void OsDatagramSocket::doConnect(int remoteHostPortNum, const char* remoteHost, UtlBoolean simulateConnect) { struct hostent* server; mToSockaddrValid = FALSE; memset(mpToSockaddr, 0, sizeof(struct sockaddr_in)); remoteHostPort = remoteHostPortNum; // Store host name if(remoteHost) { remoteHostName = remoteHost ; getHostIpByName(remoteHostName, &mRemoteIpAddress); } else { remoteHostName.remove(0) ; } // Connect to a remote host if given if(portIsValid(remoteHostPort) && remoteHost && !simulateConnect) { server = gethostbyname(remoteHost); if (server) { struct in_addr* serverAddr = (in_addr*) (server->h_addr); struct sockaddr_in serverSockAddr; serverSockAddr.sin_family = server->h_addrtype; serverSockAddr.sin_port = htons(remoteHostPort); serverSockAddr.sin_addr.s_addr = (serverAddr->s_addr); // Set the default destination address for the socket if(connect(socketDescriptor, (const struct sockaddr*) &serverSockAddr, sizeof(serverSockAddr))) { int error = OsSocketGetERRNO(); close(); OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "OsDatagramSocket::doConnect( %s:%d ) failed w/ errno %d)", remoteHost, remoteHostPortNum, error); } else { mIsConnected = TRUE; } } else { close(); OsSysLog::add(FAC_KERNEL, PRI_DEBUG, "OsDatagramSocket::doConnect( %s:%d ) failed host lookup)", remoteHost, remoteHostPortNum); goto EXIT; } } else if(portIsValid(remoteHostPort) && remoteHost && simulateConnect) { mIsConnected = TRUE; mSimulatedConnect = TRUE; } EXIT: ; }
// // 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 SipUdpServer::run(void* runArg) { int cseq = 1; if(mSipUserAgent) { UtlString contact; mSipUserAgent->getContactUri(&contact); // Add a tag to the contact and build the from field UtlString from(contact); int tagRand1 = rand(); int tagRand2 = rand(); char fromTag[80]; sprintf(fromTag, ";tag=%d%d", tagRand1, tagRand2); from.append(fromTag); UtlString rawAddress; int port; Url pingUrl(mNatPingUrl); // Create a cannonized version of the ping URL in case // it does not specify "sip:", etc. UtlString cannonizedPingUrl = pingUrl.toString(); // Get the address and port in the png URL so that // we can look up the DNS stuff if needed port = pingUrl.getHostPort(); pingUrl.getHostAddress(rawAddress); // Resolve the raw address from a DNS SRV, A record // to an IP address server_t* dnsSrvRecords = SipSrvLookup::servers(rawAddress.data(), "sip", OsSocket::UDP, port); // Do a DNS SRV or A record lookup // If we started with an IP address, we will still get an IP // address in the result UtlString address; if(dnsSrvRecords[0].isValidServerT()) { // Get the highest priority address and port from the // list with randomization of those according to the // weights. // Note: we are not doing any failover here as that is // a little tricky with the NAT stuff. We cannot change // addresses with every transaction as we may get different // ports and addresses every time we send a ping. For now // we do one DNS SRV lookup at the begining of time and // stick to that result. dnsSrvRecords[0].getIpAddressFromServerT(address); port = dnsSrvRecords[0].getPortFromServerT(); // If the ping URL or DNS SRV did not specify a port // bind it to the default port. if (!portIsValid(port)) { port = SIP_PORT; } } // Did not get a valid response from the DNS lookup else { // Configured with a bad DNS name that did not resolve. // Or the DNS server did not respond. if(!rawAddress.isNull()) { OsSysLog::add(FAC_SIP, PRI_INFO, "SipUdpServer::run DNS lookup failed for ping host: %s in URI: %s", rawAddress.data(), mNatPingUrl.data()); } // Else no ping address, this means we are not supposed to // do a ping } // Free the list of server addresses. delete[] dnsSrvRecords; // Get the address to be used in the callId scoping int dummyPort; UtlString callId; if (mSipUserAgent) { mSipUserAgent->getViaInfo(OsSocket::UDP, callId, dummyPort); } // Make up a call Id long epochTime = OsDateTime::getSecsSinceEpoch(); int randNum = rand(); char callIdPrefix[80]; sprintf(callIdPrefix, "%ld%d-ping@", epochTime, randNum); callId.insert(0,callIdPrefix); while(mNatPingFrequencySeconds > 0 && !mNatPingUrl.isNull() && !mNatPingMethod.isNull() && !address.isNull()) { // Send a no-op SIP message to the // server to keep a port open through a NAT // based firewall SipMessage pingMessage; pingMessage.setRequestData(mNatPingMethod, cannonizedPingUrl.data(), from.data(), mNatPingUrl.data(), callId, cseq, contact.data()); // Get the UDP via info from the SipUserAgent UtlString viaAddress; int viaPort; if (mSipUserAgent) { mSipUserAgent->getViaInfo(OsSocket::UDP, viaAddress, viaPort); } pingMessage.addVia(viaAddress.data(), viaPort, SIP_TRANSPORT_UDP); // Mark the via so the receiver knows we support and want the // received port to be set pingMessage.setLastViaTag("", "rport"); # ifdef TEST_PRINT osPrintf("Sending ping to %s %d, From: %s\n", address.data(), port, contact.data()); # endif // Send from the same UDP port that we receive from if (mSipUserAgent) { mSipUserAgent->sendSymmetricUdp(pingMessage, address.data(), port); } cseq++; // Wait until it is time to send another ping delay(mNatPingFrequencySeconds * 1000); } } return(mNatPingFrequencySeconds); }
int main(int argc, char* argv[]) { bool bError = true ; int iSipPort, iRtpPort ; bool bLoopback ; char* szIdentity ; char* szUsername ; char* szPassword ; char* szRealm ; char* szStunServer ; char* szProxy ; bool bDialogEvents ; // The default run time is 2^31-1 seconds, which is over 68 years. long int runTime = LONG_MAX; SIPX_INST hInst ; SIPX_LINE hLine ; // Support for the dialog event notifier. // Component for holding the subscription data SipSubscriptionMgr* pSubscriptionMgr; // Component for granting the subscription rights SipSubscribeServerEventHandler* pPolicyHolder; // Component for publishing the event contents SipPublishContentMgr* pPublisher; SipSubscribeServer* pSubscribeServer; // The dialog event publisher DialogEventPublisher* pDialogEvents; // Parse Arguments if (parseArgs(argc, argv, &iDuration, &iSipPort, &iRtpPort, &g_szPlayTones, &g_szFile, &bLoopback, &szIdentity, &szUsername, &szPassword, &szRealm, &szStunServer, &szProxy, &bDialogEvents, &g_callAnswerDelay, &g_timestamp, &runTime) && (iDuration > 0) && (portIsValid(iSipPort)) && (portIsValid(iRtpPort))) { if (bLoopback) { initLoopback() ; } // initialize sipx TAPI-like API sipxConfigSetLogLevel(LOG_LEVEL_DEBUG) ; sipxConfigSetLogFile("ReceiveCall.log"); if (sipxInitialize(&hInst, iSipPort, iSipPort, 5061, iRtpPort, 16, szIdentity) == SIPX_RESULT_SUCCESS) { // Start dialog event notifier if requested. if (bDialogEvents) { // Get pointer to the call manager. CallManager* pCallManager = ((SIPX_INSTANCE_DATA*) hInst)->pCallManager; SipUserAgent* pUserAgent = ((SIPX_INSTANCE_DATA*) hInst)->pSipUserAgent; // Start the SIP Subscribe Server pSubscriptionMgr = new SipSubscriptionMgr(); pPolicyHolder = new SipSubscribeServerEventHandler; pPublisher = new SipPublishContentMgr; pSubscribeServer = new SipSubscribeServer(*pUserAgent, *pPublisher, *pSubscriptionMgr, *pPolicyHolder); pSubscribeServer->enableEventType(DIALOG_EVENT_TYPE, NULL, NULL, NULL, NULL, SipSubscribeServer::standardVersionCallback); pSubscribeServer->start(); // Create the dialog event publisher pDialogEvents = new DialogEventPublisher(pCallManager, pPublisher); pCallManager->addTaoListener(pDialogEvents); pDialogEvents->start(); } if (szProxy) { sipxConfigSetOutboundProxy(hInst, szProxy); } sipxConfigEnableRport(hInst, true) ; if (szStunServer) { sipxConfigEnableStun(hInst, szStunServer, 28) ; } sipxEventListenerAdd(hInst, EventCallBack, NULL) ; hLine = lineInit(hInst, szIdentity, szUsername, szPassword, szRealm) ; dumpLocalContacts(hInst) ; // Run as long as requested. for (long int i = 0; i < runTime; i++) { SLEEP(1000) ; } lineShutdown(hInst, hLine); // Wait a bit, so that we can re-send the REGISTER if it needs // authorization. SLEEP(5000); } else { printf("unable to initialize sipXtapi layer\n") ; } } else { usage(argv[0]) ; } return (int) bError ; }
SipClient* SipProtocolServerBase::createClient(const char* hostAddress, int hostPort, const char* localIp) { UtlString remoteHostAddr; UtlBoolean clientStarted = FALSE; mClientLock.acquireWrite(); SipClient* client = getClient(hostAddress, hostPort, localIp); if(! client) { # if TEST_CLIENT_CREATION OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipProtocolServerBase::createClient( %s, %d )", hostAddress, hostPort); # endif if(!portIsValid(hostPort)) { hostPort = mDefaultPort; # if TEST_CLIENT_CREATION OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipProtocolServerBase::createClient port defaulting to %d", hostPort); # endif } OsTime time; OsDateTime::getCurTimeSinceBoot(time); long beforeSecs = time.seconds(); OsSocket* clientSocket = buildClientSocket(hostPort, hostAddress, localIp); OsDateTime::getCurTimeSinceBoot(time); long afterSecs = time.seconds(); if(afterSecs - beforeSecs > 1) { OsSysLog::add(FAC_SIP, PRI_WARNING, "SIP %s socket create for %s:%d took %d seconds", mProtocolString.data(), hostAddress, hostPort, (int)(afterSecs - beforeSecs)); } UtlBoolean isOk = clientSocket->isOk(); int writeWait = 3000; // mSec UtlBoolean isReadyToWrite = clientSocket->isReadyToWrite(writeWait); if(!isReadyToWrite) { OsSysLog::add(FAC_SIP, PRI_WARNING, "SIP %s socket %s:%d not ready for writing after %d seconds", mProtocolString.data(), hostAddress, hostPort, (int) (writeWait/1000)); } if(isOk && isReadyToWrite) { #ifdef TEST osPrintf("Socket OK, creating client\n"); #endif client = new SipClient(clientSocket) ; if (client && mSipUserAgent->getUseRport() && clientSocket->getIpProtocol() == OsSocket::UDP) { client->setSharedSocket(TRUE) ; } #ifdef TEST osPrintf("Created client\n"); #endif if(mSipUserAgent) { client->setUserAgent(mSipUserAgent); } if (clientSocket->getIpProtocol() != OsSocket::UDP) { //osPrintf("starting client\n"); clientStarted = client->start(); if(!clientStarted) { osPrintf("SIP %s client failed to start\n", mProtocolString.data()); } } OsSysLog::add(FAC_SIP, PRI_DEBUG, "Sip%sServer::createClient client: %p %s -> %s:%d", mProtocolString.data(), client, localIp, hostAddress, hostPort); mClientList.push(client); } // The socket failed to be connected else { if(clientSocket) { if (!mSipUserAgent->getUseRport() || (clientSocket->getIpProtocol() == OsSocket::TCP)) { delete clientSocket; } clientSocket = NULL; } OsSysLog::add(FAC_SIP, PRI_WARNING, "Sip%sServer::createClient client %p Failed to create socket %s -> %s:%d", mProtocolString.data(), this, localIp, hostAddress, hostPort); } } int isBusy = FALSE; if(client) { isBusy = client->isInUseForWrite(); if(!isBusy) client->markInUseForWrite(); } mClientLock.releaseWrite(); if(client && isBusy) { if(!waitForClientToWrite(client)) client = NULL; } return(client); }
// // Pull out important parameters from the config DB. // These parameters are set at runtime and cannot be changed without a restart. // UtlBoolean ProxyService::loadInitialConfig( int& proxyTcpPort, int& proxyUdpPort, int& proxyTlsPort, UtlString& bindIp, int& maxForwards, UtlString& domainName, UtlString& proxyRecordRoute, UtlString& routeName, UtlString& authScheme, UtlString& ipAddress, bool& enableCallStateLogObserver, bool& enableCallStateDbObserver, int& dnsSrvTimeout, int& maxNumSrvRecords, UtlString& callStateLogFileName, UtlBoolean& recurseOnlyOne300, UtlString& hostAliases, int& staleTcpTimeout, UtlString& callStateDbHostName, UtlString& callStateDbName, UtlString& callStateDbUserName, UtlString& callStateDbDriver, ForwardRules& forwardingRules ) { UtlBoolean ret = true; // SipXecsService owns the main configDb OsConfigDb& configDb = getConfigDb(); OsSocket::getHostIp(&ipAddress); configDb.get(CONFIG_SETTING_BIND_IP, bindIp); if ((bindIp.isNull()) || !OsSocket::isIp4Address(bindIp)) { bindIp = "0.0.0.0"; } OsSysLog::add(FAC_SIP, PRI_INFO, "%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); } OsSysLog::add(FAC_SIP, PRI_INFO, "SIPX_PROXY_HOST_NAME : %s", hostname.data()); proxyUdpPort = configDb.getPort("SIPX_PROXY_UDP_PORT"); if (!portIsValid(proxyUdpPort)) { proxyUdpPort = 5060; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIPX_PROXY_UDP_PORT : %d", proxyUdpPort); proxyTcpPort = configDb.getPort("SIPX_PROXY_TCP_PORT") ; if (!portIsValid(proxyTcpPort)) { proxyTcpPort = 5060; } OsSysLog::add(FAC_SIP, PRI_INFO, "SIPX_PROXY_TCP_PORT : %d", proxyTcpPort); proxyTlsPort = configDb.getPort("SIPX_PROXY_TLS_PORT") ; if (!portIsValid(proxyTlsPort)) { proxyTlsPort = 5061; } OsSysLog::add(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; OsSysLog::add(FAC_SIP, PRI_INFO, "SIPX_PROXY_MAX_FORWARDS : %d", maxForwards); int branchTimeout = -1; configDb.get("SIPX_PROXY_BRANCH_TIMEOUT", branchTimeout); if(branchTimeout < 4) { branchTimeout = 24; } 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); } OsSysLog::add(FAC_SIP, PRI_NOTICE, "SIPX_PROXY_HOST_ALIASES not configured" " using implied value: %s", hostAliases.data()); } OsSysLog::add(FAC_SIP, PRI_INFO, "SIPX_PROXY_HOST_ALIASES : %s", hostAliases.data()); UtlString enableCallStateObserverSetting; configDb.get(CONFIG_SETTING_CALL_STATE, enableCallStateObserverSetting); if ( (enableCallStateObserverSetting.isNull()) || ((0 == enableCallStateObserverSetting.compareTo("disable", UtlString::ignoreCase))) ) { enableCallStateLogObserver = false; } else if (0 == enableCallStateObserverSetting.compareTo("enable", UtlString::ignoreCase)) { enableCallStateLogObserver = true; } else { enableCallStateLogObserver = false; OsSysLog::add(FAC_SIP, PRI_ERR, "SipXproxymain:: invalid configuration value for " CONFIG_SETTING_CALL_STATE " '%s' - should be 'enable' or 'disable'", enableCallStateObserverSetting.data() ); } OsSysLog::add(FAC_SIP, PRI_INFO, CONFIG_SETTING_CALL_STATE " : %s", enableCallStateLogObserver ? "ENABLE" : "DISABLE" ); if (enableCallStateLogObserver) { configDb.get(CONFIG_SETTING_CALL_STATE_LOG, callStateLogFileName); if (callStateLogFileName.isNull()) { callStateLogFileName = CALL_STATE_LOG_FILE_DEFAULT; } OsSysLog::add(FAC_SIP, PRI_INFO, CONFIG_SETTING_CALL_STATE_LOG " : %s", callStateLogFileName.data()); } // Check if CSE logging should go into a database UtlString enableCallStateDbObserverSetting; configDb.get(CONFIG_SETTING_CALL_STATE_DB, enableCallStateDbObserverSetting); if ( (enableCallStateDbObserverSetting.isNull()) || ((0 == enableCallStateDbObserverSetting.compareTo("disable", UtlString::ignoreCase))) ) { enableCallStateDbObserver = false; } else if (0 == enableCallStateDbObserverSetting.compareTo("enable", UtlString::ignoreCase)) { enableCallStateDbObserver = true; } else { enableCallStateDbObserver = false; OsSysLog::add(FAC_SIP, PRI_ERR, "SipAuthProxyMain:: invalid configuration value for %s " " '%s' - should be 'enable' or 'disable'", CONFIG_SETTING_CALL_STATE_DB, enableCallStateDbObserverSetting.data() ); } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB, enableCallStateDbObserver ? "ENABLE" : "DISABLE" ); if (enableCallStateDbObserver) { configDb.get(CONFIG_SETTING_CALL_STATE_DB_HOST, callStateDbHostName); if (callStateDbHostName.isNull()) { callStateDbHostName = CALL_STATE_DATABASE_HOST; } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB_HOST, callStateDbHostName.data()); configDb.get(CONFIG_SETTING_CALL_STATE_DB_NAME, callStateDbName); if (callStateDbName.isNull()) { callStateDbName = CALL_STATE_DATABASE_NAME; } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB_NAME, callStateDbName.data()); configDb.get(CONFIG_SETTING_CALL_STATE_DB_USER, callStateDbUserName); if (callStateDbUserName.isNull()) { callStateDbUserName = CALL_STATE_DATABASE_USER; } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB_USER, callStateDbUserName.data()); configDb.get(CONFIG_SETTING_CALL_STATE_DB_DRIVER, callStateDbDriver); if (callStateDbDriver.isNull()) { callStateDbDriver = CALL_STATE_DATABASE_DRIVER; } OsSysLog::add(FAC_SIP, PRI_INFO, "%s : %s", CONFIG_SETTING_CALL_STATE_DB_DRIVER, callStateDbDriver.data()); } // Select logging method - database takes priority over XML file if (enableCallStateLogObserver && enableCallStateDbObserver) { enableCallStateLogObserver = false; OsSysLog::add(FAC_SIP, PRI_WARNING, "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. 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; OsSysLog::add(FAC_SIP, PRI_INFO, "SIPX_PROXY_STALE_TCP_TIMEOUT : %d", staleTcpTimeout); configDb.get("SIPX_PROXY_DNSSRV_MAX_DESTS", maxNumSrvRecords); OsSysLog::add(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; } configDb.get("SIPX_PROXY_DNSSRV_TIMEOUT", dnsSrvTimeout); OsSysLog::add(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(); if(recurseOnlyOne300String.compareTo("enable") == 0) { recurseOnlyOne300 = TRUE; OsSysLog::add(FAC_SIP, PRI_INFO, "SIPX_PROXY_SPECIAL_300 : ENABLE"); } OsPath fileName = SipXecsService::Path(SipXecsService::ConfigurationDirType, FORWARDING_RULES_FILENAME); OsFile ruleFile(fileName); UtlBoolean useDefaultRules = FALSE; if(ruleFile.exists()) { if(OS_SUCCESS != forwardingRules.loadMappings(fileName)) { OsSysLog::add(FAC_SIP, PRI_WARNING, "WARNING: Failed to load: %s", fileName.data()); useDefaultRules = TRUE; } } else { // forwardingrules.xml is not readable; no processing is possible. OsSysLog::add(FAC_SIP, PRI_CRIT, "forwarding rules '%s' not found -- exiting", fileName.data()); ret = false; } return ret; }
int SipLSendCommand::execute(int argc, char* argv[]) { int commandStatus = CommandProcessor::COMMAND_FAILED; UtlString messageBuffer; char buffer[1025]; int bufferSize = 1024; int charsRead; printf("send command with %d arguments\n", argc); if(argc != 5) { UtlString usage; getUsage(argv[0], &usage); printf("%s", usage.data()); } else { UtlString protocol(argv[2]); protocol.toUpper(); UtlString hostAddress(argv[3]); int hostPort = atoi(argv[4]); FILE* sipMessageFile = fopen(argv[1], "r"); if(sipMessageFile && portIsValid(hostPort) && !hostAddress.isNull() && (protocol.compareTo("TCP") == 0 || protocol.compareTo("UDP") == 0)) { //printf("opened file: \"%s\"\n", argv[1]); do { charsRead = fread(buffer, 1, bufferSize, sipMessageFile); if(charsRead > 0) { messageBuffer.append(buffer, charsRead); } } while(charsRead); fclose(sipMessageFile); OsSocket* writeSocket = NULL; if(protocol.compareTo("TCP") == 0) writeSocket = new OsConnectionSocket(hostPort ,hostAddress); else if(protocol.compareTo("UDP") == 0) writeSocket = new OsDatagramSocket(hostPort ,hostAddress); //printf("Read file contents:\n%s\n====END====\n", messageBuffer.data()); //SipMessage message(messageBuffer.data()); int bytesSent; if((bytesSent = writeSocket->write(messageBuffer.data(), messageBuffer.length())) > 0) { commandStatus = CommandProcessor::COMMAND_SUCCESS; } else { printf("Failed to send SIP message"); } printf("Send message with %d bytes\n", bytesSent); } else if(!sipMessageFile) { printf("send file: \"%s\" does not exist\n", argv[1]); commandStatus = CommandProcessor::COMMAND_FAILED; } else if (!portIsValid(hostPort)) { printf("Invalid destination port: %s\n", argv[4]); commandStatus = CommandProcessor::COMMAND_FAILED; } else if(hostAddress.isNull()) { printf("Invalid destination address: %s\n", argv[3]); commandStatus = CommandProcessor::COMMAND_FAILED; } else if(protocol.compareTo("TCP") && protocol.compareTo("UDP")) { printf("Invalid protocol: %s\n", argv[2]); commandStatus = CommandProcessor::COMMAND_FAILED; } } return(commandStatus); }
void ForwardRules::buildDefaultRules(const char* domain, const char* hostname, const char* ipAddress, const char* fqhn, int localPort, TiXmlDocument& xmlDoc) { // Note: fqhn == fully qualified host name UtlString hostnamePort(hostname ? hostname : "localhost"); UtlString domainPort(domain ? domain : ""); UtlString ipAddressPort(ipAddress ? ipAddress : "127.0.0.1"); UtlString fqhnPort(fqhn ? fqhn : "localhost"); if(localPort == 5060) localPort = PORT_NONE; if(portIsValid(localPort)) { char portString[40]; sprintf(portString,":%d", localPort); hostnamePort.append(portString); domainPort.append(portString); ipAddressPort.append(portString); fqhnPort.append(portString); } UtlString sdsAddress(fqhn); sdsAddress.append(":5090"); UtlString statusAddress(fqhn); statusAddress.append(":5110"); UtlString regAddress(fqhn); regAddress.append(":5070"); UtlString configAddress("sipuaconfig"); UtlString configFqhnAddress(configAddress); configFqhnAddress.append("."); configFqhnAddress.append(domain); TiXmlElement routes("routes"); TiXmlElement route("route"); route.SetAttribute("mappingType", "local"); TiXmlElement routeFromDomain("routeFrom"); TiXmlText domainText(domainPort.data()); TiXmlElement routeFromFqhn("routeFrom"); TiXmlText fqhnText(fqhnPort.data()); TiXmlElement routeFromHost("routeFrom"); TiXmlText hostText(hostnamePort.data()); TiXmlElement routeFromIp("routeFrom"); TiXmlText ipText(ipAddressPort.data()); TiXmlElement methodMatch("methodMatch"); TiXmlElement methodPattern("methodPattern"); TiXmlText subscribe("SUBSCRIBE"); TiXmlElement fieldMatchConfig("fieldMatch"); fieldMatchConfig.SetAttribute("fieldName", "Event"); TiXmlElement fieldPatternConfig("fieldPattern"); TiXmlText configEvent("sip-config"); TiXmlElement routeToSds("routeTo"); TiXmlText sdsText(sdsAddress.data()); TiXmlElement fieldMatchStatus("fieldMatch"); fieldMatchStatus.SetAttribute("fieldName", "Event"); TiXmlElement fieldPatternStatus("fieldPattern"); TiXmlText mwiEvent("message-summary*"); TiXmlElement routeToStatus("routeTo"); TiXmlText statusText(statusAddress.data()); TiXmlElement routeToReg("routeTo"); TiXmlText regText(regAddress.data()); TiXmlElement routeConfig("route"); TiXmlElement routeFromFqhnConfig("routeFrom"); TiXmlText fqhnConfigText(configFqhnAddress.data()); TiXmlElement routeFromConfig("routeFrom"); TiXmlText configText(configAddress.data()); // Link everything up in reverse order as it TinyXml // makes copies routeFromDomain.InsertEndChild(domainText); route.InsertEndChild(routeFromDomain); routeFromHost.InsertEndChild(hostText); route.InsertEndChild(routeFromHost); routeFromFqhn.InsertEndChild(fqhnText); route.InsertEndChild(routeFromFqhn); routeFromIp.InsertEndChild(ipText); route.InsertEndChild(routeFromIp); methodPattern.InsertEndChild(subscribe); methodMatch.InsertEndChild(methodPattern); fieldPatternStatus.InsertEndChild(mwiEvent); fieldMatchStatus.InsertEndChild(fieldPatternStatus); routeToStatus.InsertEndChild(statusText); fieldMatchStatus.InsertEndChild(routeToStatus); methodMatch.InsertEndChild(fieldMatchStatus); fieldPatternConfig.InsertEndChild(configEvent); fieldMatchConfig.InsertEndChild(fieldPatternConfig); routeToSds.InsertEndChild(sdsText); fieldMatchConfig.InsertEndChild(routeToSds); methodMatch.InsertEndChild(fieldMatchConfig); routeToReg.InsertEndChild(regText); methodMatch.InsertEndChild(routeToReg); route.InsertEndChild(methodMatch); route.InsertEndChild(routeToReg); routeFromFqhnConfig.InsertEndChild(fqhnConfigText); routeConfig.InsertEndChild(routeFromFqhnConfig); routeFromConfig.InsertEndChild(configText); routeConfig.InsertEndChild(routeFromConfig); routeConfig.InsertEndChild(routeToReg); routes.InsertEndChild(route); routes.InsertEndChild(routeConfig); xmlDoc.InsertEndChild(routes); }
/// Get the list of server entries for SIP domain name 'domain'. server_t* SipSrvLookup::servers(const char* domain, ///< SIP domain name or host name const char* service, ///< "sip" or "sips" OsSocket::IpProtocolSocketType socketType, ///< types of transport int port, ///< port number from URI, or PORT_NONE OsSocket::IpProtocolSocketType preferredTransport ///< preferred transport protocol ) { server_t* serverList; int list_length_allocated; int list_length_used = 0; struct sockaddr_in in; OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSrvLookup::servers domain = '%s', service = '%s', " "socketType = %s, port = %d", domain, service, OsSocket::ipProtocolString(socketType), port); // Initialize the list of servers. server_list_initialize(serverList, list_length_allocated, list_length_used); // Seize the lock. OsLock lock(sMutex); // Case 0: Eliminate contradictory combinations of service and type. // While a sip: URI can be used with a socketType of SSL_SOCKET // (e.g., <sip:[email protected];transport=tls>), a sips: URI must // be used with TLS. if ((strcmp(service, "sips") == 0 && (socketType == OsSocket::TCP || socketType == OsSocket::UDP))) { OsSysLog::add(FAC_SIP, PRI_INFO, "SipSrvLookup::servers Incompatible service '%s' and " "socketType %d", service, socketType); /* Add no elements to the list. */ } // Case 1: Domain name is a numeric IP address. else if (inet_aton(domain, &in.sin_addr)) { in.sin_family = AF_INET; // Set up the port number. // If port was specified in the URI, that is the port to use. // if not specified, use 5061 for sips service; use 5060 for anything else. in.sin_port = htons(portIsValid(port) ? port : ((strcmp(service, "sips") == 0) || (socketType == OsSocket::SSL_SOCKET)) ? 5061 : 5060); // If sips service, make sure transport is set correctly. if (socketType == OsSocket::UNKNOWN && strcmp(service, "sips") == 0) { socketType = OsSocket::SSL_SOCKET; } server_insert_addr(serverList, list_length_allocated, list_length_used, domain, socketType, in, 0, 0); } // Case 1A: Domain name is a literal IPv6 address. else if (domain[0] == '[') { OsSysLog::add(FAC_SIP, PRI_INFO, "SipSrvLookup::servers IPv6 address '%s'", domain); /* Add no elements to the list. */ } else { // Free unused server_t instances, pointer must always be reloaded in this path delete[] serverList; SipSrvLookupThread** myQueryThreads = SipSrvLookupThread::getLookupThreads(); // Initialize the SRV lookup thread args, and the A Record lookup thread args. // They are initialized separately as the A Records are only needed if SRV // records don't exist for the domain. (Or if a port name is included in the // domain). server_t * srv_record_list; server_list_initialize(srv_record_list, list_length_allocated, list_length_used); SrvThreadArgs srvLookupArgs(domain, service, srv_record_list, list_length_allocated, list_length_used, port, socketType); server_t * a_record_list; server_list_initialize(a_record_list, list_length_allocated, list_length_used); SrvThreadArgs aRecordLookupArgs(domain, service, a_record_list, list_length_allocated, list_length_used, port, socketType); myQueryThreads[SipSrvLookupThread::A_RECORD]->postMessage(aRecordLookupArgs); // Case 2: SRV records exist for this domain. // (Only used if no port is specified in the URI.) if (port <= 0 && !options[OptionCodeIgnoreSRV]) { // If UDP transport is acceptable. if ((socketType == OsSocket::UNKNOWN || socketType == OsSocket::UDP) && strcmp(service, "sips") != 0) { myQueryThreads[SipSrvLookupThread::SRV_UDP]->postMessage(srvLookupArgs); } // If TCP transport is acceptable. if ((socketType == OsSocket::UNKNOWN || socketType == OsSocket::TCP) && strcmp(service, "sips") != 0) { myQueryThreads[SipSrvLookupThread::SRV_TCP]->postMessage(srvLookupArgs); } // If TLS transport is acceptable. if (socketType == OsSocket::UNKNOWN || socketType == OsSocket::SSL_SOCKET) { myQueryThreads[SipSrvLookupThread::SRV_TLS]->postMessage(srvLookupArgs); } // Wait for each of the executed queries to finish // If UDP SRV query was carried out if ((socketType == OsSocket::UNKNOWN || socketType == OsSocket::UDP) && strcmp(service, "sips") != 0) { myQueryThreads[SipSrvLookupThread::SRV_UDP]->isDone(); } // If TCP SRV query was carried out if ((socketType == OsSocket::UNKNOWN || socketType == OsSocket::TCP) && strcmp(service, "sips") != 0) { myQueryThreads[SipSrvLookupThread::SRV_TCP]->isDone(); } // If TLS SRV query was carried out if (socketType == OsSocket::UNKNOWN || socketType == OsSocket::SSL_SOCKET) { myQueryThreads[SipSrvLookupThread::SRV_TLS]->isDone(); } } // Finally wait for the A Record Query to finish as well myQueryThreads[SipSrvLookupThread::A_RECORD]->isDone(); // Check if there is a need for A records. // (Only used for non-numeric addresses for which SRV lookup did not // produce any addresses. This includes if an explicit port was given.) if (*(srvLookupArgs.list_length_used) < 1) { // No SRV query results. Discard the SRV Lookup lists, continue with // and return the A Record list back to the caller. delete[] srvLookupArgs.list; serverList = aRecordLookupArgs.list; list_length_used = *(aRecordLookupArgs.list_length_used); list_length_allocated = *(aRecordLookupArgs.list_length_allocated); } else { // We got SRV query results. Discard the A Record Lookup lists, // continue with and return the SRV list back to the caller. delete[] aRecordLookupArgs.list; serverList = srvLookupArgs.list; list_length_used = *(srvLookupArgs.list_length_used); list_length_allocated = *(srvLookupArgs.list_length_allocated); } } // If testing the code, sort the list of servers into a canonical order, // so the pseudo-random scores we calculate for them are deterministic. if (options[OptionCodeSortServers]) { qsort(serverList, list_length_used, sizeof (server_t), server_compare_presort); } // Apply the scores to the list of servers. // Why we construct it this way is described in // sipXtackLib/doc/developer/scores/README. for (int j = 0; j < list_length_used; j++) { if (serverList[j].weight == 0) { // If weight is 0, set score to infinity. serverList[j].score = 1000; } else { int i = rand(); // If random number is 0, change it to 1, so log() doesn't have a problem. if (i == 0) { i = 1; } serverList[j].score = - log(((float) i) / RAND_MAX) / serverList[j].weight; } } // Sort the list of servers found by priority and score. if (preferredTransport == OsSocket::UDP) // list order is UDP before TCP { qsort(serverList, list_length_used, sizeof (server_t), server_compare_prefer_udp); } else // list order puts TCP before UDP (large requests need this) { qsort(serverList, list_length_used, sizeof (server_t), server_compare_prefer_tcp); } // Add ending empty element to list (after sorting the real entries). memset(&in, 0, sizeof(in)) ; server_insert(serverList, list_length_allocated, list_length_used, NULL, OsSocket::UNKNOWN, in, 0, 0); // Return the list of servers. if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG)) { // Debugging print of list of servers. for (int j = 0; j < list_length_used; j++) { if (serverList[j].isValidServerT()) { UtlString host; serverList[j].getHostNameFromServerT(host); UtlString ip_addr; serverList[j].getIpAddressFromServerT(ip_addr); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipSrvLookup::servers host = '%s', IP addr = '%s', " "port = %d, weight = %u, score = %f, " "priority = %u, proto = %s", host.data(), ip_addr.data(), serverList[j].getPortFromServerT(), serverList[j].getWeightFromServerT(), serverList[j].getScoreFromServerT(), serverList[j].getPriorityFromServerT(), OsSocket::ipProtocolString(serverList[j].getProtocolFromServerT()) ); } } } return serverList; }
OsStatus SipTlsServer::createServerSocket(const char* szBindAddr, int& port, const UtlBoolean& bUseNextAvailablePort) { OsStatus rc = OS_FAILED; if(portIsValid(port)) { #ifdef SIP_TLS # ifdef SIP_TLS_NSS // TODO - create a new OpenTLSServerSocket OsServerSocket* pServerSocket = new OsTLSServerSocket(64, port, mCertNickname, mCertPassword, mDbLocation, szBindAddr); if (pServerSocket) { } # else OsServerSocket* pServerSocket = new OsSSLServerSocket(64, port); # endif #else OsServerSocket* pServerSocket = new OsServerSocket(64, port); #endif // If the socket is busy or unbindable and the user requested using the // next available port, try the next SIP_MAX_PORT_RANGE ports. if (bUseNextAvailablePort && !pServerSocket->isOk()) { for (int i=1; i<=SIP_MAX_PORT_RANGE; i++) { delete pServerSocket ; #ifdef SIP_TLS # ifdef SIP_TLS_NSS pServerSocket = new OsTLSServerSocket(64, port+i, mCertNickname, mCertPassword, mDbLocation); # else pServerSocket = new OsSSLServerSocket(64, port+i); # endif #else pServerSocket = new OsServerSocket(64, port+i); #endif if (pServerSocket->isOk()) { break ; } } } if (pServerSocket && pServerSocket->isOk()) { mServerPort = pServerSocket->getLocalHostPort() ; port = pServerSocket->getLocalHostPort(); SIPX_CONTACT_ADDRESS contact; strcpy(contact.cIpAddress, szBindAddr); contact.iPort = port; contact.eContactType = CONTACT_LOCAL; char szAdapterName[16]; memset((void*)szAdapterName, 0, sizeof(szAdapterName)); // null out the string getContactAdapterName(szAdapterName, contact.cIpAddress, false); strcpy(contact.cInterface, szAdapterName); contact.eTransportType = TRANSPORT_TLS; mSipUserAgent->addContactAddress(contact); // add address and port to the maps mServerSocketMap.insertKeyAndValue(new UtlString(szBindAddr), new UtlVoidPtr((void*)pServerSocket)); mServerPortMap.insertKeyAndValue(new UtlString(szBindAddr), new UtlInt(pServerSocket->getLocalHostPort())); mServerBrokers.insertKeyAndValue(new UtlString(szBindAddr), new UtlVoidPtr(new SipServerBroker((OsServerTask*)mpServerBrokerListener, pServerSocket))); rc = OS_SUCCESS; # ifdef SIP_TLS_NSS TlsInitCodes tlsInitCode = ((OsTLSServerSocket*)pServerSocket)->getTlsInitCode(); if (tlsInitCode != TLS_INIT_SUCCESS) { switch (tlsInitCode) { case TLS_INIT_DATABASE_FAILURE: mTlsInitCode = OS_TLS_INIT_DATABASE_FAILURE; break; case TLS_INIT_BAD_PASSWORD: mTlsInitCode = OS_TLS_INIT_BAD_PASSWORD; break; case TLS_INIT_TCP_IMPORT_FAILURE: mTlsInitCode = OS_TLS_INIT_TCP_IMPORT_FAILURE; break; case TLS_INIT_NSS_FAILURE: mTlsInitCode = OS_TLS_INIT_NSS_FAILURE; break; default: mTlsInitCode = OS_TLS_INIT_NSS_FAILURE; break; } OsSysLog::add(FAC_SIP, PRI_ERR, "SipTlsServer - init failure = %d", mTlsInitCode); } # endif } } return rc; }
int HttpGetCommand::execute(int argc, char* argv[]) { int commandStatus = CommandProcessor::COMMAND_FAILED; if(argc == 2) { commandStatus = CommandProcessor::COMMAND_SUCCESS; const char* url = argv[1]; const char* serverBegin = strstr(url, "http://"); if(serverBegin != url) { printf("unsupported protocol in Url: %s\n", url); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; } else { serverBegin += 7; UtlString uri(serverBegin); int serverEndIndex = uri.index("/"); if(serverEndIndex < 0) serverEndIndex = uri.length(); if(serverEndIndex > 0) { UtlString server = uri; server.remove(serverEndIndex); int portIndex = server.index(":"); int port = PORT_NONE; if(portIndex > 0) { UtlString portString = server; server.remove(portIndex); portString.remove(0, portIndex + 1); printf("port string: %s\n", portString.data()); port = atoi(portString.data()); } uri.remove(0, serverEndIndex); if(uri.isNull()) uri = "/"; printf("HTTP get of %s from server %s port: %d\n", uri.data(), server.data(), port); if (!portIsValid(port)) { port = 80; printf("defaulting to http port 80\n"); } OsConnectionSocket getSocket(port, server.data()); HttpMessage getRequest; getRequest.setFirstHeaderLine("GET", uri.data(), HTTP_PROTOCOL_VERSION); int wroteBytes = getRequest.write(&getSocket); printf("wrote %d\n", wroteBytes); HttpMessage getResponse; getResponse.read(&getSocket); UtlString responseBytes; int responseLength; getResponse.getBytes(&responseBytes, &responseLength); printf("Got %d bytes\n", responseLength); printf("Response: ++++++++++++++++++++++++++++++++++\n%s\n", responseBytes.data()); } else { printf("invalid server in Url: %s\n", url); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; } } } else { UtlString usage; getUsage(argv[0], &usage); printf("%s", usage.data()); commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX; //commandStatus = CommandProcessor::COMMAND_FAILED; } return(commandStatus); }
OsStatus SipUdpServer::createServerSocket(const char* szBoundIp, int& port, const UtlBoolean& bUseNextAvailablePort, int udpReadBufferSize) { OsStatus rc = OS_FAILED; OsStunDatagramSocket* pSocket = new OsStunDatagramSocket(0, NULL, port, szBoundIp, FALSE); if (pSocket) { // If the socket is busy or unbindable and the user requested using the // next available port, try the next SIP_MAX_PORT_RANGE ports. if (bUseNextAvailablePort & portIsValid(port) && pSocket && !pSocket->isOk()) { for (int i=1; i<=SIP_MAX_PORT_RANGE; i++) { delete pSocket ; pSocket = new OsStunDatagramSocket(0, NULL, port+i, szBoundIp, FALSE); if (pSocket->isOk()) { break ; } } } } if (pSocket) { port = pSocket->getLocalHostPort(); CONTACT_ADDRESS contact; strcpy(contact.cIpAddress, szBoundIp); contact.iPort = port; contact.eContactType = LOCAL; char szAdapterName[16]; memset((void*)szAdapterName, 0, sizeof(szAdapterName)); // null out the string getContactAdapterName(szAdapterName, contact.cIpAddress); strcpy(contact.cInterface, szAdapterName); mSipUserAgent->addContactAddress(contact); // add address and port to the maps mServerSocketMap.insertKeyAndValue(new UtlString(szBoundIp), new UtlVoidPtr((void*)pSocket)); port = pSocket->getLocalHostPort() ; mServerPortMap.insertKeyAndValue(new UtlString(szBoundIp), new UtlInt(port)); int sockbufsize = 0; int size = sizeof(int); getsockopt(pSocket->getSocketDescriptor(), SOL_SOCKET, SO_RCVBUF, (char*)&sockbufsize, #if defined(__pingtel_on_posix__) (socklen_t*) // caste #endif &size); #ifdef LOG_SIZE OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipUdpServer::SipUdpServer UDP buffer size: %d size: %d\n", sockbufsize, size); #endif /* LOG_SIZE */ if(udpReadBufferSize > 0) { setsockopt(pSocket->getSocketDescriptor(), SOL_SOCKET, SO_RCVBUF, (char*)&udpReadBufferSize, sizeof(int)); getsockopt(pSocket->getSocketDescriptor(), SOL_SOCKET, SO_RCVBUF, (char*)&sockbufsize, #if defined(__pingtel_on_posix__) (socklen_t*) // caste #endif &size); #ifdef LOG_SIZE OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipUdpServer::SipUdpServer reset UDP buffer size: %d size: %d\n", sockbufsize, size); #endif /* LOG_SIZE */ } } return rc; }
// Thread execution code. int SipClient::run(void* runArg) { OsMsg* pMsg = NULL; OsStatus res; // Buffer to hold data read from the socket but not yet parsed // into incoming SIP messages. UtlString readBuffer; bool waitingToReportErr = FALSE; // controls whether to read-select on socket bool tcpOnErrWaitForSend = TRUE; int repeatedEOFs = 0; Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run start " "tcpOnErrWaitForSend-%d waitingToReportErr-%d mbTcpOnErrWaitForSend-%d repeatedEOFs-%d", mName.data(), tcpOnErrWaitForSend, waitingToReportErr, mbTcpOnErrWaitForSend, repeatedEOFs); // Wait structure: struct pollfd fds[2]; // Incoming message on the message queue (to be sent on the socket). fds[0].fd = mPipeReadingFd; // Socket ready to write (to continue sending message). // Socket ready to read (message to be received). do { assert(repeatedEOFs < 20); // The file descriptor for the socket may changemsg->getSendAddress(&fromIpAddress, &fromPort);, as OsSocket's // can be re-opened. fds[1].fd = mClientSocket->getSocketDescriptor(); // Initialize the revents members. // This may not be necessary (the man page is not clear), but // Valgrind flags 'fds[*].revents' as undefined if they aren't // initialized. fds[0].revents = 0; fds[1].revents = 0; fds[0].events = POLLIN; // only read-select on pipe // For non-blocking connect failures, don't read-select on socket if // the initial read showed an error but we have to wait to report it. if (!waitingToReportErr) { // This is the normal path. // Read the socket only if the socket is not shared. // If it is shared, the ancestral SipClient will read it. // If multiple threads attempt to read the socket, poll() may // succeed but another may read the data, leaving us to block on // read. fds[1].events = mbSharedSocket ? 0 : POLLIN; // Set wait for writing the socket if there is queued messages to // send. if (mWriteQueued) { // Wait for output on the socket to not block. fds[1].events |= POLLOUT; } } else { // just waiting to report error, ignore the socket fds[1].fd =-1; fds[1].events = 0; } // If there is residual data in the read buffer, // pretend the socket is ready to read. if (!readBuffer.isNull()) { fds[1].revents = POLLIN; } else { // Otherwise, call poll() to wait. int resPoll = poll(&fds[0], sizeof (fds) / sizeof (fds[0]), POLL_TIMEOUT); assert(resPoll >= 0 || (resPoll == -1 && errno == EINTR)); if (resPoll != 0) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run " "resPoll= %d revents: fd[0]= %x fd[1]= %x", mName.data(), resPoll, fds[0].revents, fds[1].revents ); } } if ((fds[1].revents & (POLLERR | POLLHUP)) != 0) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run " "SipMessage::poll error(%d) ", mName.data(), errno); if (OsSocket::isFramed(mClientSocket->getIpProtocol())) { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipClient[%s]::run " "SipMessage::poll error(%d) got POLLERR | POLLHUP on UDP socket", mName.data(), errno); } else // eg. tcp socket // This client's socket is a connection-oriented protocol and the // connection has been terminated (probably by the remote end). // We must terminate the SipClient. // We drop the queued messages, but we do not report them to // SipUserAgent as failed sends. This will cause SipUserAgent to // retry the send using the same transport (rather than continuing // to the next transport), which should cause a new connection to // be made to the remote end. { // On non-blocking connect failures, we need to get the first send message // in order to successfully trigger the protocol fallback mechanism if (!tcpOnErrWaitForSend) { // Return all buffered messages with a transport error indication. emptyBuffer(TRUE); clientStopSelf(); } else { fds[1].revents &= ~(POLLERR | POLLHUP); // clear error bit if waiting waitingToReportErr = TRUE; } } } // Check for message queue messages (fds[0]) before checking the socket(fds[1]), // to make sure that we process shutdown messages promptly, even // if we would be spinning trying to service the socket. else if ((fds[0].revents & POLLIN) != 0) { // Poll finished because the pipe is ready to read. // (One byte in pipe means message available in queue.) // Only a SipClient with a derived SipClientWriteBuffer // uses the pipe in the Sip message send process // Check to see how many messages are in the queue. int numberMsgs = (getMessageQueue())->numMsgs(); Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run got pipe-select " "Number of Messages waiting: %d", mName.data(), numberMsgs); int i; char buffer[1]; for (i = 0; i < numberMsgs; i++) { // Receive the messages. res = receiveMessage((OsMsg*&) pMsg, OsTime::NO_WAIT); assert(res == OS_SUCCESS); // Normally, this is a SIP message for the write buffer. Once we have gotten // here, we are able to report any initial non-blocking connect error. mbTcpOnErrWaitForSend = FALSE; tcpOnErrWaitForSend = FALSE; Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run got pipe-select " "mbTcpOnErrWaitForSend-%d waitingToReportErr-%d mbTcpOnErrWaitForSend-%d repeatedEOFs-%d", mName.data(), mbTcpOnErrWaitForSend, waitingToReportErr, mbTcpOnErrWaitForSend, repeatedEOFs); // Read 1 byte from the pipe to clear it for this message. One byte is // inserted into the pipe for each message. assert(read(mPipeReadingFd, &buffer, 1) == 1); if (!handleMessage(*pMsg)) // process the message (from queue) { OsServerTask::handleMessage(*pMsg); } if (!pMsg->getSentFromISR()) { pMsg->releaseMsg(); // free the message } // In order to report an unframed(eg TCP) socket error to SipUserAgent dispatcher, // the error must be carried in a sip message from the client's message queue. // The message holds all the identifying information. if (waitingToReportErr) { // Return all buffered messages with a transport error indication. emptyBuffer(TRUE); clientStopSelf(); } } } // end reading msg-available-for-output-queue pipe else if ((fds[1].revents & POLLOUT) != 0) { // Poll finished because socket is ready to write. // Call method to continue writing data. writeMore(); } else if ((fds[1].revents & POLLIN) != 0) { // Poll finished because socket is ready to read. // Read message. // Must allocate a new message because SipUserAgent::dispatch will // take ownership of it. SipMessage* msg = new SipMessage; int res = msg->read(mClientSocket, HTTP_DEFAULT_SOCKET_BUFFER_SIZE, &readBuffer); if (res >= 65536) { // // This is more than the allowable size of a SIP message. Discard! // UtlString remoteHostAddress; int remoteHostPort; msg->getSendAddress(&remoteHostAddress, &remoteHostPort); OS_LOG_WARNING(FAC_SIP, "Received a SIP Message (" << res << " bytes) beyond the maximum allowable size from host " << remoteHostAddress.data() << ":" << remoteHostPort); delete msg; readBuffer.remove(0); continue; } // Use readBuffer to hold any unparsed data after the message // we read. // Note that if a message was successfully parsed, readBuffer // still contains as its prefix the characters of that message. // We save them for logging purposes below and will delete them later. UtlString remoteHostAddress; int remoteHostPort; msg->getSendAddress(&remoteHostAddress, &remoteHostPort); if (!mClientSocket->isSameHost(remoteHostAddress.data(), mLocalHostAddress.data())) { try { if (!remoteHostAddress.isNull()) { boost::asio::ip::address remoteIp = boost::asio::ip::address::from_string(remoteHostAddress.data()); if (rateLimit().isBannedAddress(remoteIp)) { delete msg; readBuffer.remove(0); continue; } rateLimit().logPacket(remoteIp, 0); } } catch(const std::exception& e) { Os::Logger::instance().log(FAC_SIP_INCOMING, PRI_CRIT, "SipClient[%s]::run rate limit exception: %s", mName.data(), e.what()); } } // Note that input was processed at this time. touch(); // // Count the CR/LF to see if this is a keep-alive // int crlfCount = 0; for (int i = 0; i < res; i++) { if (readBuffer(i) == '\r' || readBuffer(i) == '\n') { crlfCount++; } else { break; } } if (res == crlfCount) { repeatedEOFs = 0; // The 'message' was a keepalive (CR-LF or CR-LF-CR-LF). UtlString fromIpAddress; int fromPort; UtlString buffer; int bufferLen; // send one CRLF set in the reply buffer.append("\r\n"); bufferLen = buffer.length(); // Get the send address for response. msg->getSendAddress(&fromIpAddress, &fromPort); if ( !portIsValid(fromPort)) { fromPort = defaultPort(); } // Log the message at DEBUG level. // Only bother processing if the logs are enabled if ( mpSipUserAgent->isMessageLoggingEnabled() || Os::Logger::instance().willLog(FAC_SIP_INCOMING, PRI_DEBUG) ) { UtlString logMessage; logMessage.append("Read keepalive message:\n"); logMessage.append("----Local Host:"); logMessage.append(mLocalHostAddress); logMessage.append("---- Port: "); logMessage.appendNumber( portIsValid(mLocalHostPort) ? mLocalHostPort : defaultPort()); logMessage.append("----\n"); logMessage.append("----Remote Host:"); logMessage.append(fromIpAddress); logMessage.append("---- Port: "); logMessage.appendNumber( portIsValid(fromPort) ? fromPort : defaultPort()); logMessage.append("----\n"); logMessage.append(readBuffer.data(), res); UtlString messageString; logMessage.append(messageString); logMessage.append("====================END====================\n"); // Don't bother to send the message to the SipUserAgent for its internal log. // Write the message to the syslog. Os::Logger::instance().log(FAC_SIP_INCOMING, PRI_DEBUG, "%s", logMessage.data()); } // send the CR-LF response message switch (mSocketType) { case OsSocket::TCP: { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run send TCP keep-alive CR-LF response, ", mName.data()); SipClientSendMsg sendMsg(OsMsg::OS_EVENT, SipClientSendMsg::SIP_CLIENT_SEND_KEEP_ALIVE, fromIpAddress, fromPort); handleMessage(sendMsg); // add newly created keep-alive to write buffer } break; case OsSocket::UDP: { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run send UDP keep-alive CR-LF response, ", mName.data()); (dynamic_cast <OsDatagramSocket*> (mClientSocket))->write(buffer.data(), bufferLen, fromIpAddress, fromPort); } break; default: break; } // Delete the SipMessage allocated above, which is no longer needed. delete msg; // Now that logging is done, remove the parsed bytes and // remember any unparsed input for later use. readBuffer.remove(0, res); } // end keep-alive msg else if (res > 0) // got message, but not keep-alive { // Message successfully read. repeatedEOFs = 0; // Do preliminary processing of message to log it, // clean up its data, and extract any needed source address. preprocessMessage(*msg, readBuffer, res); // Dispatch the message. // dispatch() takes ownership of *msg. mpSipUserAgent->dispatch(msg); // Now that logging is done, remove the parsed bytes and // remember any unparsed input for later use. readBuffer.remove(0, res); } // end process read of >0 bytes else { // Something went wrong while reading the message. // (Possibly EOF on a connection-oriented socket.) repeatedEOFs++; // Delete the SipMessage allocated above, which is no longer needed. delete msg; Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run SipMessage::read returns %d (error(%d) or EOF), " "readBuffer = '%.1000s'", mName.data(), res, errno, readBuffer.data()); Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipClient[%s]::run error wait status " "tcpOnErrWaitForSend-%d waitingToReportErr-%d " "mbTcpOnErrWaitForSend-%d repeatedEOFs-%d " "protocol %d framed %d", mName.data(), tcpOnErrWaitForSend, waitingToReportErr, mbTcpOnErrWaitForSend, repeatedEOFs, mClientSocket->getIpProtocol(), OsSocket::isFramed(mClientSocket->getIpProtocol())); // If the socket is not framed (is connection-oriented), // we need to abort the connection and post a message // :TODO: This doesn't work right for framed connection-oriented // protocols (like SCTP), but OsSocket doesn't have an EOF-query // method -- we need to close all connection-oriented // sockets as well in case it was an EOF. // Define a virtual function that returns the correct bit. if (!OsSocket::isFramed(mClientSocket->getIpProtocol())) { // On non-blocking connect failures, we need to get the first send message // in order to successfully trigger the protocol fallback mechanism if (!tcpOnErrWaitForSend) { // Return all buffered messages with a transport error indication. emptyBuffer(TRUE); clientStopSelf(); } else { fds[1].revents &= ~(POLLERR | POLLHUP); // clear error bit if waiting waitingToReportErr = TRUE; } } // Delete the data read so far, which will not have been // deleted by HttpMessage::read. readBuffer.remove(0); } } // end POLLIN reading socket } while (isStarted()); return 0; // and then exit }
int local_main(int argc, char* argv[]) { bool bError = true ; int iDuration, iSipPort, iRtpPort ; char* szIdentity ; char* szUsername ; char* szPassword ; char* szRealm ; char* szStunServer ; char* szProxy ; SIPX_INST hInst ; SIPX_LINE hLine ; // Parse Arguments if (parseArgs(argc, argv, &iDuration, &iSipPort, &iRtpPort, &g_szPlayTones, &g_szFile, &szIdentity, &szUsername, &szPassword, &szRealm, &szStunServer, &szProxy) && (iDuration > 0) && (portIsValid(iSipPort)) && (portIsValid(iRtpPort))) { // Initialize sipX TAPI-like API sipxConfigSetLogLevel(LOG_LEVEL_DEBUG) ; sipxConfigSetLogFile("ReceiveCall.log"); if (sipxInitialize(&hInst, iSipPort, iSipPort, 5061, iRtpPort, 16, szIdentity) == SIPX_RESULT_SUCCESS) { g_hInst1 = hInst; if (szProxy) { sipxConfigSetOutboundProxy(hInst, szProxy); } sipxConfigEnableRport(hInst, true) ; if (szStunServer) { sipxConfigEnableStun(hInst, szStunServer, DEFAULT_STUN_PORT, 28) ; } sipxEventListenerAdd(hInst, EventCallBack, NULL) ; if (sipxConfigSelectAudioCodecByName(g_hInst1, "PCMU PCMA") == SIPX_RESULT_FAILURE) { printf("!! Setting audio codecs to PCMU PCMA failed !!\n"); }; #if defined(_WIN32) && defined(VIDEO) if (bVideo) { gPreviewDisplay.type = SIPX_WINDOW_HANDLE_TYPE; gPreviewDisplay.handle = ghPreview; sipxConfigSetVideoPreviewDisplay(hInst, &gPreviewDisplay); } #endif // get first contact size_t numAddresses = 0; SIPX_CONTACT_ADDRESS address; sipxConfigGetLocalContacts(hInst, &address, 1, &numAddresses); hLine = lineInit(hInst, szIdentity, szUsername, szPassword, szRealm) ; dumpLocalContacts(hInst) ; while (true) { SLEEP(1000) ; } } else { printf("unable to initialize sipXtapi layer\n") ; } } else { usage(argv[0]) ; } #if defined(_WIN32) && defined(VIDEO) PostMessage(hMain, WM_CLOSE, 0, 0L); #endif return (int) bError ; }
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 ; }
// // 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; }
int local_main(int argc, char* argv[]) { bool bError = false ; int iDuration, iSipPort, iRtpPort, iRepeatCount ; char* szPlayTones; char* szSipUrl; char* szFile; char* szFileBuffer; char* szUsername; char* szPassword; char* szRealm; char* szFromIdentity; char* szStunServer; char* szProxy; char* szBindAddr; char* szOutDevice; char* szInDevice; char* szCodec; bool bUseRport; bool bCList; bool bAEC; bool bAGC; bool bDenoise; if ( signal( SIGINT, ctrlCHandler ) == SIG_ERR ) { printf("Couldn't install signal handler for SIGINT\n"); exit(1); } if ( signal( SIGTERM, ctrlCHandler ) == SIG_ERR ) { printf("Couldn't install signal handler for SIGTERM\n"); exit(1); } // Parse Arguments if (parseArgs(argc, argv, &iDuration, &iSipPort, &iRtpPort, &szPlayTones, &szFile, &szFileBuffer, &szSipUrl, &bUseRport, &szUsername, &szPassword, &szRealm, &szFromIdentity, &szStunServer, &szProxy, &szBindAddr, &iRepeatCount, &szInDevice, &szOutDevice, &szCodec, &bCList, &bAEC, &bAGC, &bDenoise, &bUseCustomTransportReliable, &bUseCustomTransportUnreliable) && (iDuration > 0) && (portIsValid(iSipPort)) && (portIsValid(iRtpPort))) { // initialize sipx TAPI-like API sipxConfigSetLogLevel(LOG_LEVEL_DEBUG) ; sipxConfigSetLogFile("PlaceCall.log"); int mediaEngineSampleRate = 16000; sipxInitialize(&g_hInst, iSipPort, iSipPort, -1, iRtpPort, DEFAULT_CONNECTIONS, DEFAULT_IDENTITY, szBindAddr, false, // use sequential RTP/RTCP ports NULL, // cert. nickname NULL, // cert. password NULL, // DB location true, // Enable local audio mediaEngineSampleRate, 48000); // Audio device sample rate sipxConfigEnableRport(g_hInst, bUseRport) ; dumpInputOutputDevices() ; sipxEventListenerAdd(g_hInst, EventCallBack, NULL) ; // Enable/disable AEC. if (bAEC) sipxAudioSetAECMode(g_hInst, SIPX_AEC_CANCEL_AUTO) ; else sipxAudioSetAECMode(g_hInst, SIPX_AEC_DISABLED) ; // Enable/disable AGC sipxAudioSetAGCMode(g_hInst, bAGC); if (bDenoise) sipxAudioSetNoiseReductionMode(g_hInst, SIPX_NOISE_REDUCTION_HIGH); else sipxAudioSetNoiseReductionMode(g_hInst, SIPX_NOISE_REDUCTION_DISABLED); if (bCList) { int numAudioCodecs; int numVideoCodecs; int index; SIPX_AUDIO_CODEC audioCodec; SIPX_VIDEO_CODEC videoCodec; printf("Audio codecs:\n"); if (sipxConfigGetNumAudioCodecs(g_hInst, &numAudioCodecs) == SIPX_RESULT_SUCCESS) { for (index=0; index<numAudioCodecs; ++index) { if (sipxConfigGetAudioCodec(g_hInst, index, &audioCodec) == SIPX_RESULT_SUCCESS) { printf(" audio %02d : %s\n", index, audioCodec.cName); } else { printf("Error in retrieving audio codec #%d\n", index); } } } else { printf("Error in retrieving number of audio codecs\n"); } #ifdef VIDEO printf("Video codecs:\n"); if (sipxConfigGetNumVideoCodecs(g_hInst, &numVideoCodecs) == SIPX_RESULT_SUCCESS) { for (index=0; index<numVideoCodecs; ++index) { if (sipxConfigGetVideoCodec(g_hInst, index, &videoCodec) == SIPX_RESULT_SUCCESS) { printf(" video %02d : %s\n", index, videoCodec.cName); } else { printf("Error in retrieving video codec #%d\n"); } } } else { printf("Error in retrieving number of video codecs\n"); } #endif // VIDEO sipxUnInitialize(g_hInst, true); exit(0); } if (szProxy) { sipxConfigSetOutboundProxy(g_hInst, szProxy); } if (szStunServer) { sipxConfigEnableStun(g_hInst, szStunServer, DEFAULT_STUN_PORT, 28) ; } if (szOutDevice) { if (sipxAudioSetCallOutputDevice(g_hInst, szOutDevice) != SIPX_RESULT_SUCCESS) { printf("!! Setting output device %s failed !!\n", szOutDevice); } } if (szInDevice) { if (sipxAudioSetCallInputDevice(g_hInst, szInDevice) != SIPX_RESULT_SUCCESS) { printf("!! Setting input device %s failed !!\n", szOutDevice); } } if (szCodec) { if (sipxConfigSetAudioCodecByName(g_hInst, szCodec) == SIPX_RESULT_FAILURE) { printf("!! Setting audio codec to %s failed !!\n", szCodec); }; } // Wait for a STUN response (should actually look for the STUN event status // (config event) ; SLEEP(1500) ; for (int i=0; i<iRepeatCount; i++) { ClearSipXEvents() ; printf("<-> Attempt %d of %d\n", i+1, iRepeatCount) ; // Place a call to designed URL if (placeCall(szSipUrl, szFromIdentity, szUsername, szPassword, szRealm)) { bError = false ; // Play tones if provided if (szPlayTones) { if (!playTones(szPlayTones)) { printf("%s: Failed to play tones: %s\n", argv[0], szPlayTones) ; } else { bError = true ; } } // Play file if provided if (szFile) { if (!playFile(szFile)) { printf("%s: Failed to play file: %s\n", argv[0], szFile) ; } else { bError = true ; } } // Play file from buffer if provided if (szFileBuffer) { if (!playFileBuffer(szFileBuffer)) { printf("%s: Failed to play file from buffer: %s\n", argv[0], szFileBuffer) ; } else { bError = true ; } } // Leave the call up for specified time period (or wait for hangup) WaitForSipXEvent(CALLSTATE_DISCONNECTED, iDuration) ; // Shutdown / cleanup if (!shutdownCall()) { printf("%s: Failed to shutdown call\n", argv[0]) ; bError = true ; } } else { printf("%s: Unable to complete call\n", argv[0]) ; shutdownCall() ; bError = true ; } if (bError) { break ; } } sipxEventListenerRemove(g_hInst, EventCallBack, NULL) ; sipxUnInitialize(g_hInst, true); } else { usage(argv[0]) ; } #if defined(_WIN32) && defined(VIDEO) PostMessage(hMain, WM_CLOSE, 0, 0L); #endif return (int) bError ; }
// Constructor ResourceListServer::ResourceListServer(const UtlString& domainName, const UtlString& realm, SipLineMgr* lineMgr, const char* eventType, const char* contentType, int tcpPort, int udpPort, int tlsPort, const UtlString& bindIp, UtlString* resourceListFile, int refreshInterval, int resubscribeInterval, int minResubscribeInterval, int publishingDelay, int maxRegSubscInResource, int maxContInRegSubsc, int maxResInstInCont, int maxDialogsInResInst, int serverMinExpiration, int serverDefaultExpiration, int serverMaxExpiration, const UtlString& subscriptionDbName, const UtlString& credentialDbName) : mDomainName(domainName), mEventType(eventType), mContentType(contentType), mResourceListFile(*resourceListFile), mRefreshInterval(refreshInterval), mResubscribeInterval(resubscribeInterval), mMinResubscribeInterval(minResubscribeInterval), mPublishingDelay(publishingDelay), mMaxRegSubscInResource(maxRegSubscInResource), mMaxContInRegSubsc(maxContInRegSubsc), mMaxResInstInCont(maxResInstInCont), mMaxDialogsInResInst(maxDialogsInResInst), mServerUserAgent( tcpPort, // sipTcpPort udpPort, // sipUdpPort tcpPort, // sipTlsPort NULL, // publicAddress NULL, // defaultUser bindIp, // defaultSipAddress NULL, // sipProxyServers NULL, // sipDirectoryServers NULL, // sipRegistryServers NULL, // authenticationScheme NULL, // authenicateRealm NULL, // authenticateDb NULL, // authorizeUserIds NULL, // authorizePasswords NULL, // lineMgr SIP_DEFAULT_RTT, // sipFirstResendTimeout TRUE, // defaultToUaTransactions -1, // readBufferSize OsServerTask::DEF_MAX_MSGS, // queueSize FALSE // bUseNextAvailablePort ), mClientUserAgent( PORT_DEFAULT, // sipTcpPort PORT_DEFAULT, // sipUdpPort PORT_DEFAULT, // sipTlsPort NULL, // publicAddress NULL, // defaultUser bindIp, // defaultSipAddress domainName.data(), // sipProxyServers NULL, // sipDirectoryServers NULL, // sipRegistryServers NULL, // authenticationScheme NULL, // authenicateRealm NULL, // authenticateDb NULL, // authorizeUserIds NULL, // authorizePasswords lineMgr, // lineMgr SIP_DEFAULT_RTT, // sipFirstResendTimeout TRUE, // defaultToUaTransactions -1, // readBufferSize OsServerTask::DEF_MAX_MSGS, // queueSize FALSE // bUseNextAvailablePort ), mSubscriptionMgr(SUBSCRIPTION_COMPONENT_RLS, mDomainName, subscriptionDbName), mPolicyHolder(domainName, realm, credentialDbName), mSubscribeServer(mServerUserAgent, mEventPublisher, mSubscriptionMgr, mPolicyHolder), mRefreshMgr(mClientUserAgent, mDialogManager), mSubscribeClient(mClientUserAgent, mDialogManager, mRefreshMgr), mResourceListTask(this), mResourceListSet(this), // Do not set the resource list file name yet, so the ResourceListFileReader // doesn't add elements to the ResourceListSet before we have the // SIP tasks set up. mResourceListFileReader(UtlString(""), &mResourceListSet) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceListServer::_ this = %p, mDomainName = '%s', mEventType = '%s', mContentType = '%s', " "mRefreshInterval = %d, mResubscribeInterval = %d", this, mDomainName.data(), mEventType.data(), mContentType.data(), mRefreshInterval, mResubscribeInterval); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ResourceListServer::_ this = %p, mPublishingDelay = %d, mMaxRegSubscInResource = %d, " "mMaxContInRegSubsc = %d, mMaxResInstInCont = %d, mMaxDialogsInResInst = %d", this, publishingDelay, mMaxRegSubscInResource, mMaxContInRegSubsc, mMaxResInstInCont, mMaxDialogsInResInst); // Initialize the call processing objects. // Construct addresses: // our local host-part // contact address to be used in client outgoing requests (primarily SUBSCRIBEs) { // Get our address and the client port. UtlString localAddress; int localPort; mClientUserAgent.getLocalAddress(&localAddress, &localPort); char buffer[100]; // Construct the server's host-part. sprintf(buffer, "%s:%d", localAddress.data(), portIsValid(udpPort) ? udpPort : tcpPort); mServerLocalHostPart = buffer; // Construct the client's From URI. sprintf(buffer, "sip:sipXrls@%s:%d", localAddress.data(), localPort); mClientFromURI = buffer; // Obtain the client's Contact URI. mClientUserAgent.getContactURI(mClientContactURI); } // Initialize the SipUserAgent's. // Set the user-agent strings. mServerUserAgent.setUserAgentHeaderProperty("sipXecs/rls"); mClientUserAgent.setUserAgentHeaderProperty("sipXecs/rls"); // Require the "eventlist" extension in the Resource List clients. mServerUserAgent.requireExtension(SIP_EVENTLIST_EXTENSION); // Set the subscribe server grant times. if (!mSubscriptionMgr.setSubscriptionTimes(serverMinExpiration, serverDefaultExpiration, serverMaxExpiration)) { OsSysLog::add(FAC_RLS, PRI_ERR, "ResourceListServer given unacceptable server subscription times: min = %d, default = %d, max = %d. Using the default subscription times.", serverMinExpiration, serverDefaultExpiration, serverMaxExpiration); } }
// Do preliminary processing of message to log it, // clean up its data, and extract any needed source address. void SipClient::preprocessMessage(SipMessage& msg, const UtlString& msgText, int msgLength) { // Canonicalize short field names. msg.replaceShortFieldNames(); // Get the send address. UtlString fromIpAddress; int fromPort; msg.getSendAddress(&fromIpAddress, &fromPort); // Log the message. // Only bother processing if the logs are enabled if ( mpSipUserAgent->isMessageLoggingEnabled() || Os::Logger::instance().willLog(FAC_SIP_INCOMING, PRI_INFO) ) { UtlString logMessage; logMessage.append("Read SIP message:\n"); logMessage.append("----Local Host:"); logMessage.append(mLocalHostAddress); logMessage.append("---- Port: "); logMessage.appendNumber( portIsValid(mLocalHostPort) ? mLocalHostPort : defaultPort()); logMessage.append("----\n"); logMessage.append("----Remote Host:"); logMessage.append(fromIpAddress); logMessage.append("---- Port: "); logMessage.appendNumber( portIsValid(fromPort) ? fromPort : defaultPort()); logMessage.append("----\n"); logMessage.append(msgText.data(), msgLength); UtlString messageString; logMessage.append(messageString); logMessage.append("====================END====================\n"); // Send the message to the SipUserAgent for its internal log. mpSipUserAgent->logMessage(logMessage.data(), logMessage.length()); // Write the message to the syslog. Os::Logger::instance().log(FAC_SIP_INCOMING, PRI_INFO, "%s", logMessage.data()); } // Set the date field if not present long epochDate; if (!msg.getDateField(&epochDate)) { msg.setDateField(); } // Set the protocol and time. msg.setSendProtocol(mSocketType); msg.setTransportTime(touchedTime); // Keep track of where this message came from msg.setSendAddress(fromIpAddress.data(), fromPort); // Keep track of the interface on which this message was // received. msg.setInterfaceIpPort(mClientSocket->getLocalIp(), mClientSocket->getLocalHostPort()); if (mReceivedAddress.isNull()) { mReceivedAddress = fromIpAddress; mRemoteReceivedPort = fromPort; } // If this is a request... if (!msg.isResponse()) { UtlString lastAddress; int lastPort; UtlString lastProtocol; int receivedPort; UtlBoolean receivedSet; UtlBoolean maddrSet; UtlBoolean receivedPortSet; // Fill in 'received' and 'rport' in top Via if needed. msg.setReceivedViaParams(fromIpAddress, fromPort); // Derive information about the other end of the connection // from the Via that the other end provided. // Get the addresses from the topmost Via. msg.getTopVia(&lastAddress, &lastPort, &lastProtocol, &receivedPort, &receivedSet, &maddrSet, &receivedPortSet); // :QUERY: Should this test be mClientSocket->isConnected()? if ( ( mSocketType == OsSocket::TCP || mSocketType == OsSocket::SSL_SOCKET ) && !receivedPortSet ) { // we can use this socket as if it were // connected to the port specified in the // via field mRemoteReceivedPort = lastPort; } // Keep track of the address the other // side said they sent from. Note, this cannot // be trusted unless this transaction is // authenticated if (mRemoteViaAddress.isNull()) { mRemoteViaAddress = lastAddress; mRemoteViaPort = portIsValid(lastPort) ? lastPort : defaultPort(); } } // // Call all sip input processors // system_tap_sip_rx(fromIpAddress.data(), portIsValid(fromPort) ? fromPort : defaultPort(), mLocalHostAddress.data(), portIsValid(mLocalHostPort) ? mLocalHostPort : defaultPort(), msgText.data(), msgLength); mpSipUserAgent->executeAllSipInputProcessors(msg, fromIpAddress.data(), portIsValid(fromPort) ? fromPort : defaultPort()); }