Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
// 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;
}
Ejemplo n.º 3
0
/// 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;
}
Ejemplo n.º 4
0
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);
   }
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
// 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;
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
// 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 ;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
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:
   ;
}
Ejemplo n.º 12
0
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:
   ;
}
Ejemplo n.º 13
0
//
// Create the real Server, passing in the configured parameters
//
void ParkService::run()
{
    int UdpPort;
    int TcpPort;
    int RtpBase;
    UtlString bindIp;
    int MaxSessions;
    UtlBoolean OneButtonBLF;
    UtlString   domain;
    UtlString   realm;
    UtlString   user;
    SipLineMgr* lineMgr = NULL;
    int Lifetime;
    int BlindXferWait;
    int KeepAliveTime;

   loadConfig(
       UdpPort,
       TcpPort,
       RtpBase,
       bindIp,
       MaxSessions,
       OneButtonBLF,
       domain,
       realm,
       user,
       lineMgr,
       Lifetime,
       BlindXferWait,
       KeepAliveTime
       );

   // initialize other pieces

    // This is not configurable, as consultative transfers should
    // succeed or fail immediately.
    int ConsXferWait;
    ConsXferWait = CONS_XFER_WAIT;

    // Bind the SIP user agent to a port and start it up
    SipUserAgent* userAgent = new SipUserAgent(TcpPort,
                                               UdpPort,
                                               TcpPort+1,
                                               NULL, // publicAddress
                                               user.isNull() ? NULL : user.data(), // default user
                                               bindIp,
                                               domain.isNull() ? NULL : domain.data(), // outbound proxy
                                               NULL, // sipDirectoryServers (deprecated)
                                               NULL, // sipRegistryServers (deprecated)
                                               NULL, // authenicateRealm
                                               NULL, // authenticateDb
                                               NULL, // authorizeUserIds (deprecated)
                                               NULL, // authorizePasswords (deprecated)
                                               lineMgr
                                               );
    userAgent->setUserAgentHeaderProperty("sipXecs/park");
    userAgent->start();

    if (!userAgent->isOk())
    {
       OsSysLog::add(LOG_FACILITY, PRI_EMERG, "SipUserAgent failed to initialize, requesting shutdown");
       setShutdownFlag(true);
    }

    // Read the list of codecs from the configuration file.
    SdpCodecFactory codecFactory;
    initCodecs(&codecFactory, &getConfigDb());

    // Initialize and start up the media subsystem
    mpStartUp(MP_SAMPLE_RATE, MP_SAMPLES_PER_FRAME, 6 * MaxSessions, &getConfigDb());
    MpMediaTask::getMediaTask(MaxSessions);

#ifdef INCLUDE_RTCP
    CRTCManager::getRTCPControl();
#endif //INCLUDE_RTCP

    mpStartTasks();

    // Instantiate the call processing subsystem
    UtlString localAddress;
    int localPort ;
    userAgent->getLocalAddress(&localAddress, &localPort) ;
    if (localAddress.isNull())
        OsSocket::getHostIp(&localAddress);

    // Construct an address to be used in outgoing requests (primarily
    // INVITEs stimulated by REFERs).
    UtlString outgoingAddress;
    {
       char buffer[100];
       sprintf(buffer, "sip:sipXpark@%s:%d", localAddress.data(),
               portIsValid(UdpPort) ? UdpPort : TcpPort);
       outgoingAddress = buffer;
    }
    CallManager callManager(FALSE,
                           NULL,
                           TRUE,                              // early media in 180 ringing
                           &codecFactory,
                           RtpBase,                           // rtp start
                           RtpBase + (2 * MaxSessions),       // rtp end
                           localAddress,
                           localAddress,
                           userAgent,
                           0,                                 // sipSessionReinviteTimer
                           NULL,                              // mgcpStackTask
                           outgoingAddress,                   // defaultCallExtension
                           Connection::RING,                  // availableBehavior
                           NULL,                              // unconditionalForwardUrl
                           -1,                                // forwardOnNoAnswerSeconds
                           NULL,                              // forwardOnNoAnswerUrl
                           Connection::BUSY,                  // busyBehavior
                           NULL,                              // sipForwardOnBusyUrl
                           NULL,                              // speedNums
                           CallManager::SIP_CALL,             // phonesetOutgoingCallProtocol
                           4,                                 // numDialPlanDigits
                           CallManager::NEAR_END_HOLD,        // holdType
                           5000,                              // offeringDelay
                           "",                                // pLocal
                           CP_MAXIMUM_RINGING_EXPIRE_SECONDS, // inviteExpiresSeconds
                           QOS_LAYER3_LOW_DELAY_IP_TOS,       // expeditedIpTos
                           MaxSessions,                       // maxCalls
                           sipXmediaFactoryFactory(NULL));    // CpMediaInterfaceFactory



    // Create a listener (application) to deal with call
    // processing events (e.g. incoming call and hang ups)
    OrbitListener listener(&callManager, Lifetime, BlindXferWait, KeepAliveTime, ConsXferWait);

    callManager.addTaoListener(&listener);
    listener.start();

    // Create the SIP Subscribe Server
    SipPersistentSubscriptionMgr
       subscriptionMgr(SUBSCRIPTION_COMPONENT_PARK,
                       domain,
                       "subscription"); // Component for holding the subscription data
    SipSubscribeServerEventHandler policyHolder; // Component for granting the subscription rights
    SipPublishContentMgr publisher; // Component for publishing the event contents

    SipSubscribeServer subscribeServer(SipSubscribeServer::terminationReasonSilent,
                                       *userAgent, publisher,
                                       subscriptionMgr, policyHolder);
    subscribeServer.enableEventType(DIALOG_EVENT_TYPE, NULL, NULL, NULL,
                                    SipSubscribeServer::standardVersionCallback,
                                    TRUE // dialogEvents only produces full content.
       );
    subscribeServer.start();

    // Create the DialogEventPublisher.
    // Use the sipX domain as the hostport of resource-IDs of the
    // published events, as that will be the request-URIs of SUBSCRIBEs.
    DialogEventPublisher dialogEvents(&callManager, &publisher, domain, PORT_NONE, OneButtonBLF);
    callManager.addTaoListener(&dialogEvents);
    dialogEvents.start();

    // Start up the call processing system
    callManager.start();

    // Loop forever until signaled to shut down

    int numTwoSecIntervals = 0;
    int CleanLoopWaitTimeSecs = 10;

    while (!getShutdownFlag())
    {
       OsTask::delay(2000);

       if (2*numTwoSecIntervals >= CleanLoopWaitTimeSecs)
       {
           numTwoSecIntervals = 0;
           if (OsSysLog::willLog(FAC_PARK, PRI_DEBUG))
           {
               OsSysLog::add(LOG_FACILITY, PRI_DEBUG,
                             "park main "
                             "logging call status"
                             );
               callManager.printCalls(0) ;
               listener.dumpCallsAndTransfers();
           }
       }
       else
       {
           numTwoSecIntervals += 1;
       }

    }

}
Ejemplo n.º 14
0
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);
}
Ejemplo n.º 15
0
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 ;
}
Ejemplo n.º 16
0
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);
}
Ejemplo n.º 17
0
//
// 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;
}
Ejemplo n.º 18
0
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);
}
Ejemplo n.º 19
0
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);

}
Ejemplo n.º 20
0
/// 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;
}
Ejemplo n.º 21
0
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;
}    
Ejemplo n.º 22
0
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);
}
Ejemplo n.º 23
0
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;
}
Ejemplo n.º 24
0
// 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
}
Ejemplo n.º 25
0
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 ;
}
Ejemplo n.º 26
0
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 ;
}
Ejemplo n.º 27
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;
}
Ejemplo n.º 28
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 ;
}
Ejemplo n.º 29
0
// 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);
   }
}
Ejemplo n.º 30
0
// 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());
}