Example #1
0
    // Since the test setup / preconditions for the index, find, 
    // contains and containsReference are all the same, these
    // tests have been combined into one utility function. Based
    // on the type argument, the method to be tested is varied. 
    void utlTestIndex_Find_And_Contains(IndexOrContains type)
    {
        const int testCount = 7 ; 
        const char* prefixIndex = "Test the index() method when the match " ; 
        const char* prefixFind = "Test the find() method when the match " ; 
        const char* prefixContains = "Test the contains() method when the match " ; 
        const char* prefixContainsRef = "Test the containsReference() method when the match " ; 
        const char* Msgs[] = { \
               "is the first element ", \
               "is the last element ", \
               "is a mid element (unique match) ", \
               "has two value matches but a single ref match ", \
               "has two ref matches", \
               "has a value match but no ref match", \
               "has no match at all" \
        } ; 
        // insert a clone of the 4th element to the 1st position
        commonList.insertAt(1, commonContainables_Clone[4]) ; 
       // The new index for a value match of commonContainables[4] must be 1. 

       // insert another copy of the 3rd element to the 2nd position. 
       commonList.insertAt(2, commonContainables[3]) ; 
       // The new index for commonContainables[3] must be 2) ; 
       // what used to be the second element has now moved to 4. 

       UtlString noExist("This cannot and should not exist!!!") ; 

       UtlContainable* searchValues[] = { \
                 commonContainables[0], commonContainables[5], commonContainables[2], \
                 commonContainables[4], commonContainables[3], \
                 commonContainables_Clone[2], &noExist \
       } ; 

       int expectedValues_Index[] = { 0, 7, 4, 1, 2, 4, INDEX_NOT_EXIST } ; 
 
       bool expectedValues_Contains[]    = {true, true, true, true, true, true, false } ;
       bool expectedValues_ContainsRef[] = {true, true, true, true, true, false, false} ; 

       UtlContainable* searchValuesForFind[] = { \
                 commonContainables[0], commonContainables[5], commonContainables[2], \
                 commonContainables[4], commonContainables[3], \
                 commonContainables_Clone[1], &noExist \
       } ;
       UtlContainable* expectedValuesForFind[] = { \
                 commonContainables[0], commonContainables[5], commonContainables[2], \
                 commonContainables_Clone[4], commonContainables[3], \
                 commonContainables[1], NULL \
       } ;

       for (int i = 0 ; i < testCount ; i++)
       {
           string msg ; 
           if (type == TEST_INDEX) 
           {
               int actual = commonList.index(searchValues[i]) ; 
               TestUtilities::createMessage(2, &msg, prefixIndex, Msgs[i]) ; 
               CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), expectedValues_Index[i], actual) ; 
           } 
           else if (type == TEST_FIND) 
           {
               UtlContainable* actual = commonList.find(searchValuesForFind[i]) ; 
               TestUtilities::createMessage(2, &msg, prefixFind, Msgs[i]) ; 
               CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), expectedValuesForFind[i], actual) ;
           }
           else if (type == TEST_CONTAINS) 
           {
               UtlBoolean actual = commonList.contains(searchValues[i]) ; 
               TestUtilities::createMessage(2, &msg, prefixContains, Msgs[i]) ; 
               CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), expectedValues_Contains[i], \
                  (TRUE == actual)) ; 
           }
           else if (type == TEST_CONTAINS_REF)
           {
               UtlBoolean actual = commonList.containsReference(searchValues[i]) ;
               TestUtilities::createMessage(2, &msg, prefixContainsRef, Msgs[i]) ;
               CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), expectedValues_ContainsRef[i], \
                   (TRUE == actual)) ;
           }
       }
    }//utlTestIndex
int supervisorMain(bool bOriginalSupervisor)
{
    // Create forked process which will do nothing unless parent dies.  Parent continues with initialization.
    forkSupervisorInWaiting();

    // Drop privileges down to the specified user & group
    const char * sipxpbxuser = SipXecsService::User();
    const char * sipxpbxgroup = SipXecsService::Group();

    if (NULL == sipxpbxuser || 0 == strlen(sipxpbxuser))
    {
       osPrintf("sipXsupervisor: Failed to setuid(%s), username not defined.\n",
          sipxpbxuser);
       return 2;
    }
    if (NULL == sipxpbxgroup || 0 == strlen(sipxpbxgroup))
    {
       osPrintf("sipXsupervisor: Failed to setgid(%s), groupname not defined.\n",
          sipxpbxgroup);
       return 2;
    }

    struct group * grp = getgrnam(sipxpbxgroup);
    if (NULL == grp)
    {
       if (0 != errno)
       {
          osPrintf("getgrnam(%s) failed, errno = %d.",
             sipxpbxgroup, errno);
       }
       else
       {
          osPrintf(
             "sipXsupervisor: getgrnam(%s) failed, user does not exist.",
                sipxpbxgroup);
       }
       return 3;
    }

    struct passwd * pwd = getpwnam(sipxpbxuser);
    if (NULL == pwd)
    {
       if (0 != errno)
       {
          osPrintf("getpwnam(%s) failed, errno = %d.",
             sipxpbxuser, errno);
       }
       else
       {
          osPrintf(
             "sipXsupervisor: getpwnam(%s) failed, user does not exist.",
                sipxpbxuser);
       }
       return 3;
    }

    // Change group first, cause once user is changed this cannot be done.
    if (0 != setgid(grp->gr_gid))
    {
       osPrintf("sipXsupervisor: setgid(%d) failed, errno = %d.",
          (int)grp->gr_gid, errno);
       return 4;
    }

    if (0 != setuid(pwd->pw_uid))
    {
       osPrintf("sipXsupervisor: setuid(%d) failed, errno = %d.",
          (int)pwd->pw_uid, errno);
       return 4;
    }


# if 0
// Only output problems.  This keeps the startup output clean.
    osPrintf("sipXsupervisor: Dropped privileges with setuid(%s)/setgid(%s).",
       sipxpbxuser, sipxpbxgroup);
#endif

    OsMsgQShared::setQueuePreference(OsMsgQShared::QUEUE_UNLIMITED);

    // Block all signals in this the main thread
    // Any threads created after this 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() ;

    // All osPrintf output should go to the console until the log file is initialized.
    enableConsoleOutput(true);

    // Initialize the log file.
    Os::LoggerHelper::instance().processName = "Supervisor";
    UtlString logFile = SipXecsService::Path(SipXecsService::LogDirType, "sipxsupervisor.log");
    Os::LoggerHelper::instance().initialize(PRI_DEBUG, logFile.data());

    if (!bOriginalSupervisor)
    {
       Os::Logger::instance().log(FAC_SUPERVISOR, PRI_CRIT,
                     "Restarting sipxsupervisor after unexpected shutdown");
    }
    Os::Logger::instance().log(FAC_SUPERVISOR, PRI_NOTICE,
                  ">>>>> Starting sipxsupervisor version %s",
                  VERSION);

    // Now that the log file is initialized, stop sending osPrintf to the console.
    // All relevant log messages from this point on must use Os::Logger::instance().log().
    enableConsoleOutput(false);
    fflush(NULL); // Flush all output so children don't get a buffer of output

    // Open the supervisor configuration file
    OsConfigDb supervisorConfiguration;
    OsPath supervisorConfigPath = SipXecsService::Path(SipXecsService::ConfigurationDirType,
                                                       CONFIG_SETTINGS_FILE);
    if (OS_SUCCESS != supervisorConfiguration.loadFromFile(supervisorConfigPath.data()))
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_WARNING,
                     "Failed to open supervisor configuration file at '%s'",
                     supervisorConfigPath.data()
                     );
    }

    // Set logging based on the supervisor configuration - TODO change default to "NOTICE" ?
    OsSysLogPriority logPri = SipXecsService::setLogPriority(supervisorConfiguration, SUPERVISOR_PREFIX, PRI_INFO );
    Os::Logger::instance().setLoggingPriorityForFacility(FAC_ALARM, logPri);

    // Open the domain configuration file
    OsConfigDb domainConfiguration;
    OsPath domainConfigPath = SipXecsService::domainConfigPath();
    if (OS_SUCCESS != domainConfiguration.loadFromFile(domainConfigPath.data()))
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_ERR,
                     "Failed to open domain configuration '%s'",
                     domainConfigPath.data()
                     );
    }
    // @TODO const char* managementIpBindAddress;
    int managementPortNumber;
    managementPortNumber = domainConfiguration.getPort(SipXecsService::DomainDbKey::SUPERVISOR_PORT);
    if (PORT_NONE == managementPortNumber)
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_WARNING,
                     "%s not configured in '%s', using default: %d",
                     SipXecsService::DomainDbKey::SUPERVISOR_PORT,
                     domainConfigPath.data(), DEFAULT_SUPERVISOR_PORT
                     );
       managementPortNumber=DEFAULT_SUPERVISOR_PORT;
    }
    else if (PORT_DEFAULT == managementPortNumber)
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_NOTICE,"%s set to default: %d",
                     SipXecsService::DomainDbKey::SUPERVISOR_PORT, DEFAULT_SUPERVISOR_PORT
                     );
       managementPortNumber=DEFAULT_SUPERVISOR_PORT;
    }

    UtlSList allowedPeers;
    UtlString configHosts;
    domainConfiguration.get(SipXecsService::DomainDbKey::CONFIG_HOSTS, configHosts);
    if (!configHosts.isNull())
    {
       UtlString hostName;
       for (int hostIndex = 0;
            NameValueTokenizer::getSubField(configHosts.data(), hostIndex, ", \t", &hostName);
            hostIndex++)
       {
          // Found at least one config hostname.
          if (!allowedPeers.contains(&hostName))
          {
             Os::Logger::instance().log(FAC_SUPERVISOR,PRI_DEBUG,
                           "%s value '%s'",
                           SipXecsService::DomainDbKey::CONFIG_HOSTS,
                           hostName.data()
                           );
             allowedPeers.insert(new UtlString(hostName));
          }
       }
    }
    else
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_ERR,
                     "%s not configured in '%s'",
                     SipXecsService::DomainDbKey::CONFIG_HOSTS, domainConfigPath.data()
                     );
    }

    UtlString superHost;
    supervisorConfiguration.get(SUPERVISOR_HOST, superHost);
    if (!superHost.isNull())
    {
       if (!allowedPeers.contains(&superHost))
       {
          allowedPeers.insert(new UtlString(superHost));
       }
    }
    else
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_ERR,
                     "%s not configured in '%s'",
                     SUPERVISOR_HOST, supervisorConfigPath.data()
                     );
    }

    if (allowedPeers.isEmpty())
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_ERR,
                     "No configuration peers configured.");
    }

    if (!cAlarmServer::getInstance()->init())
    {
       Os::Logger::instance().log(FAC_SUPERVISOR, PRI_ERR,
             "sipXsupervisor failed to init AlarmServer");
    }

    // Initialize management interfaces on the TLS socket
    OsSSLServerSocket serverSocket(50, managementPortNumber /*@TODO managementIpBindAddress */);
    HttpServer        httpServer(&serverSocket); // set up but don't start https server
    XmlRpcDispatch    xmlRpcDispatcher(&httpServer); // attach xml-rpc service to https
    pSipxRpcImpl = new SipxRpc(&xmlRpcDispatcher, allowedPeers); // register xml-rpc methods
    HttpFileAccess    fileAccessService(&httpServer, pSipxRpcImpl); // attach file xfer to https

    if (serverSocket.isOk())
    {
       Os::Logger::instance().log(FAC_SUPERVISOR, PRI_DEBUG, "Starting Management HTTP Server");
       httpServer.start();
    }
    else
    {
       Os::Logger::instance().log(FAC_SUPERVISOR, PRI_ERR, "Management listening socket failure");
    }

    // Read the process definitions.
    UtlString processDefinitionDirectory =
       SipXecsService::Path(SipXecsService::DataDirType, "process.d");
    SipxProcessManager* processManager = SipxProcessManager::getInstance();
    processManager->instantiateProcesses(processDefinitionDirectory);

    // 3.0 had different process def files.  The only important thing in them is the
    // state of the services.  Transfer this state to the new process def files.
    upgradeFrom3_0();

    doWaitLoop();

    // Successful run.
    return 0;
}