Example #1
0
PaseCcsid::~PaseCcsid()
{
    if (_SETCCSID(_back) == -1)
    {
        PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
                "PaseCcsid::~PaseCcsid: Can not change PASE CCSID.");
    }
    _paseCcsidMutex.unlock();
}
Example #2
0
PaseCcsid::PaseCcsid(int to, int back)
    : _to(to), _back(back)
{
    _paseCcsidMutex.lock();
   if (_SETCCSID(_to) == -1)
   {
       PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
               "PaseCcsid::PaseCcsid: Can not change PASE CCSID.");
   }
}
Example #3
0
int CIMServerProcess::cimserver_run(
    int argc,
    char** argv,
    Boolean shutdownOption,
    Boolean debugOutputOption)
{
    Boolean daemonOption = false;

#if defined (PEGASUS_OS_PASE) && !defined (PEGASUS_DEBUG)
    // PASE have itself regular for checking privileged user
    if (!System::isPrivilegedUser("*CURRENT  "))
    {
        MessageLoaderParms parms(
                "src.Server.cimserver.NO_AUTHORITY.PEGASUS_OS_PASE",
                "The caller should be a privileged user,"
                " or the server will not run.");
        cerr << MessageLoader::getMessage(parms) << endl;
        exit (1);
    }
    char jobName[11];
    // this function only can be found in PASE environment
    umeGetJobName(jobName, false);
    if (strncmp("QUMECIMOM ", jobName, 10) != 0
            && strncmp("QUMEENDCIM", jobName, 10) != 0)
    {
        MessageLoaderParms parms(
                "src.Server.cimserver.NOT_OFFICIAL_START.PEGASUS_OS_PASE",
                "cimserver can not be started by user.\nServer will not run.");
        cerr << MessageLoader::getMessage(parms) << endl;
        exit (1);
    }

    // Direct standard input, output, and error to /dev/null,
    // PASE run this job in background, any output in not allowed
    freopen("/dev/null", "r", stdin);
    freopen("/dev/null", "w", stdout);
    freopen("/dev/null", "w", stderr);
#endif

    //
    // Get an instance of the Config Manager.
    //
    ConfigManager* configManager = ConfigManager::getInstance();
    configManager->useConfigFiles = true;

    try
    {
        //
        // Get options (from command line and from configuration file); this
        // removes corresponding options and their arguments from the command
        // line.  NOTE: If shutdownOption=true, the contents of current config
        // file are not overwritten by the planned config file.
        //
        GetOptions(configManager, argc, argv, shutdownOption);

        //
        // Initialize the message home directory in the MessageLoader.
        // This is the default directory where the resource bundles are found.
        //
        MessageLoader::setPegasusMsgHome(ConfigManager::getHomedPath(
            ConfigManager::getInstance()->getCurrentValue("messageDir")));

#if !defined(PEGASUS_USE_SYSLOGS)
        String logsDirectory = ConfigManager::getHomedPath(
            configManager->getCurrentValue("logdir"));

        // Set up the Logger.  This does not open the logs.
        // Might be more logical to clean before set.
        Logger::setHomeDirectory(logsDirectory);
#endif


#ifdef PEGASUS_OS_PASE
        /* write job log to tell where pegasus log is.*/
        if(logsDirectory.size() > 0)
            // this function only can be found in PASE environment
            logPegasusDir2joblog(logsDirectory.getCString());
        else
            logPegasusDir2joblog(".");

        // set ccsid to unicode for entire job
        // ccsid is globolization mechanism in PASE environment
        if (_SETCCSID(1208) == -1)
        {
            MessageLoaderParms parms(
                    "src.Server.cimserver.SET_CCSID_ERROR.PEGASUS_OS_PASE",
                    "Failed to set CCSID, server will stop.");
            cerr << MessageLoader::getMessage(parms) << endl;
            Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::FATAL,
                    parms);
            exit (1);
        }

        char fullJobName[29];
        umeGetJobName(fullJobName, true);
        Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
                Logger::INFORMATION,
                MessageLoaderParms(
                    "src.Server.cimserver.SERVER_JOB_NAME.PEGASUS_OS_PASE",
                    "CIM Server's Job Name is: $0", fullJobName));
#endif

#ifdef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
        // Make sure at least one connection is enabled

        Boolean enableHttpConnection = ConfigManager::parseBooleanValue(
            configManager->getCurrentValue("enableHttpConnection"));
        Boolean enableHttpsConnection = ConfigManager::parseBooleanValue(
            configManager->getCurrentValue("enableHttpsConnection"));

        if (!enableHttpConnection && !enableHttpsConnection)
        {
            MessageLoaderParms parms(
                "src.Server.cimserver.HTTP_NOT_ENABLED_SERVER_NOT_STARTING",
                "Neither HTTP nor HTTPS connection is enabled."
                    "  CIMServer will not be started.");
            Logger::put_l(
                Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
                parms);
            cerr << MessageLoader::getMessage(parms) << endl;
            return 1;
        }
#endif

        //
        // Check to see if we should start Pegasus as a daemon
        //
        daemonOption = ConfigManager::parseBooleanValue(
            configManager->getCurrentValue("daemon"));

        if ((Executor::detectExecutor() == 0) && (daemonOption == false))
        {
            MessageLoaderParms parms(
                "src.Server.cimserver.PRIVSEP_REQUIRES_DAEMON",
                "Warning: The configuration setting daemon=false is ignored "
                    "with privilege separation enabled.");
            cerr << MessageLoader::getMessage(parms) << endl;
            daemonOption = true;
        }

        //
        // Check to see if we need to shutdown CIMOM
        //
        if (shutdownOption)
        {
#if defined(PEGASUS_OS_ZOS) && defined(PEGASUS_ZOS_SECURITY)
            // This checks whether user is authorized to stop the
            // CIM Server. When unauthorized a message is logged to
            // to the user and program exits.
            shutdownCheckProfileCIMSERVclassWBEM();
            // Depending on the success of the previous check we may not
            // reach this code!!!
#endif
            String configTimeout =
                configManager->getCurrentValue("shutdownTimeout");
            Uint32 timeoutValue =
                strtol(configTimeout.getCString(), (char **)0, 10);

            ServerShutdownClient serverShutdownClient(&_serverRunStatus);
            serverShutdownClient.shutdown(timeoutValue);

            MessageLoaderParms parms(
                "src.Server.cimserver.SERVER_STOPPED",
                "CIM Server stopped.");

            cout << MessageLoader::getMessage(parms) << endl;
            return 0;
        }

#if defined(PEGASUS_DEBUG) && !defined(PEGASUS_USE_SYSLOGS)
        // Leave this in until people get familiar with the logs.
        MessageLoaderParms parms("src.Server.cimserver.LOGS_DIRECTORY",
                                 "Logs Directory = ");
        cout << MessageLoader::getMessage(parms) << logsDirectory << endl;
#endif
    }
    catch (Exception& e)
    {
        MessageLoaderParms parms("src.Server.cimserver.SERVER_NOT_STARTED",
            "cimserver not started: $0", e.getMessage());
        Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
            parms);
        cerr << MessageLoader::getMessage(parms) << endl;

        return 1;
    }

#if defined(PEGASUS_OS_ZOS) 
#  if defined(PEGASUS_ZOS_SECURITY)
    startupCheckBPXServer(true);
    startupCheckProfileCIMSERVclassWBEM();
    startupEnableMSC();
#  endif
    startupWaitForTCPIP();
#endif

#if defined(PEGASUS_DEBUG)
    // Put out startup up message.
    cout << _cimServerProcess->getProductName() << " " <<
        _cimServerProcess->getCompleteVersion() << endl;
#endif

    // Force initialization of hostname and fullyQualifiedHostName through
    // retrieving current value from Configuration Manager
    // - this will run getCurrentValue() in DefaultPropertyOwner.cpp
    configManager->getCurrentValue("hostname");
    configManager->getCurrentValue("fullyQualifiedHostName");

    // reset message loading to NON-process locale
    MessageLoader::_useProcessLocale = false;

    // Get the parent's PID before forking
    _serverRunStatus.setParentPid(System::getPID());

    // Do not fork when using privilege separation (executor will daemonize
    // itself later).
    if (daemonOption)
    {
        if (-1 == _cimServerProcess->cimserver_fork())
            return -1;
    }

    // Now we are after the fork...
    // Create a dummy Thread object that can be used to store the
    // AcceptLanguageList object for CIM requests that are serviced
    // by this thread (initial thread of server).  Need to do this
    // because this thread is not in a ThreadPool, but is used
    // to service CIM requests.
    // The run function for the dummy Thread should never be called,
    dummyInitialThread = new Thread(dummyThreadFunc, NULL, false);
    Thread::setCurrent(dummyInitialThread);
    try
    {
        Thread::setLanguages(LanguageParser::getDefaultAcceptLanguages());
    }
    catch (InvalidAcceptLanguageHeader& e)
    {
        Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
            MessageLoaderParms(
                "src.Server.cimserver.FAILED_TO_SET_PROCESS_LOCALE",
                "Could not convert the system process locale into a valid "
                    "AcceptLanguage format."));
        Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
            e.getMessage());
    }

#ifndef PEGASUS_OS_TYPE_WINDOWS
    umask(S_IRWXG|S_IRWXO);
#endif

    // Start up the CIM Server

    try
    {
#if defined(PEGASUS_OS_TYPE_UNIX)
        //
        // Lock the CIMSERVER_LOCK_FILE during CIM Server start-up to prevent
        // concurrent writes to this file by multiple cimserver processes
        // starting at the same time.
        //
        CString startupLockFileName = ConfigManager::getHomedPath(
            PEGASUS_CIMSERVER_START_LOCK_FILE).getCString();

        // Make sure the start-up lock file exists
        FILE* startupLockFile;
        if ((startupLockFile = fopen(startupLockFileName, "w")) != 0)
        {
            fclose(startupLockFile);
        }

        AutoFileLock fileLock(startupLockFileName);
#endif

#if defined(PEGASUS_OS_TYPE_UNIX) || defined(PEGASUS_OS_VMS)
        //
        // Check if a CIM Server is already running.  If so, print an error
        // message and notify the parent process (if there is one) to terminate
        //
        if (_serverRunStatus.isServerRunning())
        {
            MessageLoaderParms parms(
                "src.Server.cimserver.UNABLE_TO_START_SERVER_ALREADY_RUNNING",
                "Unable to start CIMServer. CIMServer is already running.");
            Logger::put_l(
                Logger::ERROR_LOG, System::CIMSERVER, Logger::INFORMATION,
                parms);
            cerr << MessageLoader::getMessage(parms) << endl;

            if (daemonOption)
            {
                _cimServerProcess->notify_parent(1);
            }

            return 1;
        }

        //
        // Declare ourselves as the running CIM Server process, and write our
        // PID to the PID file.
        //
        _serverRunStatus.setServerRunning();
#endif

        // Create and initialize the CIMServer object

        _cimServer = new CIMServer();

        Boolean enableHttpConnection = ConfigManager::parseBooleanValue(
            configManager->getCurrentValue("enableHttpConnection"));
        Boolean enableHttpsConnection = ConfigManager::parseBooleanValue(
            configManager->getCurrentValue("enableHttpsConnection"));

#ifdef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
        // Make sure at least one connection is enabled
        if (!enableHttpConnection && !enableHttpsConnection)
        {
            MessageLoaderParms parms(
                "src.Server.cimserver.HTTP_NOT_ENABLED_SERVER_NOT_STARTING",
                "Neither HTTP nor HTTPS connection is enabled.");
            throw Exception(parms);
        }
#endif

        Boolean addIP6Acceptor = false;
        Boolean addIP4Acceptor = false;

#ifdef PEGASUS_OS_TYPE_WINDOWS
        addIP4Acceptor = true;
#endif

#ifdef PEGASUS_ENABLE_IPV6
        // If IPv6 stack is disabled swicth to IPv4 stack.
        if (System::isIPv6StackActive())
        {
            addIP6Acceptor = true;
        }
        else
        {
            PEG_TRACE_CSTRING(TRC_SERVER,Tracer::LEVEL4,
                "IPv6 stack is not active, using IPv4 socket.");
        }
#endif
        if (!addIP6Acceptor)
        {
            addIP4Acceptor = true;
        }

        // The server HTTP and HTTPS ports are determined via this algorithm:
        // 1) If the user explicitly specified a port, use it.
        // 2) If the user did not specify a port, get the port from the
        //    services file.
        // 3) If no value is specified in the services file, use the IANA WBEM
        //    default port.
        // Note that 2 and 3 are done within the System::lookupPort method
        // An empty string from the ConfigManager implies that the user did not
        // specify a port.

        if (enableHttpConnection)
        {
            Uint32 portNumberHttp = 0;
            String httpPort = configManager->getCurrentValue("httpPort");
            if (httpPort.size() == 0)
            {
                //
                // Look up the WBEM-HTTP port number
                //
                portNumberHttp = System::lookupPort(
                    WBEM_HTTP_SERVICE_NAME, WBEM_DEFAULT_HTTP_PORT);
                _initConfigProperty("httpPort", portNumberHttp);
            }
            else
            {
                Uint64 longNumber;
                // use the current value which has been checked for validity at
                // load(fct. GetOptions), see DefaultPropertyOwner::isValid()
                StringConversion::decimalStringToUint64(
                    httpPort.getCString(),
                    longNumber);
                portNumberHttp = longNumber & 0xffff;
            }

            String listenOn = configManager->getCurrentValue("listenAddress");
            if(String::equalNoCase(listenOn, "All"))
            {
                if (addIP6Acceptor)
                {
                    _cimServer->addAcceptor(HTTPAcceptor::IPV6_CONNECTION,
                        portNumberHttp, false);
                }
                if (addIP4Acceptor)
                {
                    _cimServer->addAcceptor(HTTPAcceptor::IPV4_CONNECTION,
                        portNumberHttp, false);
                }
            }
            else // Restricted listening
            {
                _restrictListening(
                    configManager, listenOn, portNumberHttp, false);
            }

            // The port number is converted to a string to avoid the
            //  addition of localized characters (e.g., "5,988").
            char scratchBuffer[22];
            Uint32 n;
            const char * portNumberHttpStr = Uint32ToString(
                scratchBuffer, portNumberHttp, n);
            MessageLoaderParms parms(
                "src.Server.cimserver.LISTENING_ON_HTTP_PORT",
                "Listening on HTTP port $0.", portNumberHttpStr);
            Logger::put_l(
                Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
                parms);
#if defined(PEGASUS_DEBUG)
            cout << MessageLoader::getMessage(parms) << endl;
#endif
        }

        if (enableHttpsConnection)
        {
            Uint32 portNumberHttps = 0;
            String httpsPort = configManager->getCurrentValue("httpsPort");
            if (httpsPort.size() == 0)
            {
                //
                // Look up the WBEM-HTTPS port number
                //
                portNumberHttps = System::lookupPort(
                    WBEM_HTTPS_SERVICE_NAME, WBEM_DEFAULT_HTTPS_PORT);
                _initConfigProperty("httpsPort", portNumberHttps);
            }
            else
            {
                Uint64 longNumber;
                // use the current value which has been checked for validity at
                // load(fct. GetOptions), see DefaultPropertyOwner::isValid()
                StringConversion::decimalStringToUint64(
                    httpsPort.getCString(),
                    longNumber);
                portNumberHttps = longNumber & 0xffff;
            }

            String listenOn = configManager->getCurrentValue("listenAddress");
            if(String::equalNoCase(listenOn, "All"))
            {
                if (addIP6Acceptor)
                {
                    _cimServer->addAcceptor(HTTPAcceptor::IPV6_CONNECTION,
                        portNumberHttps, true);
                }
                if (addIP4Acceptor)
                {
                    _cimServer->addAcceptor(HTTPAcceptor::IPV4_CONNECTION,
                        portNumberHttps, true);
                }
            }
            else //Restricted
            {
                _restrictListening(
                    configManager, listenOn, portNumberHttps, true);
            }

            // The port number is converted to a string to avoid the
            //  addition of localized characters (e.g., "5,989").
            char scratchBuffer[22];
            Uint32 n;
            const char * portNumberHttpsStr = Uint32ToString(
                scratchBuffer, portNumberHttps, n);
            MessageLoaderParms parms(
                "src.Server.cimserver.LISTENING_ON_HTTPS_PORT",
                "Listening on HTTPS port $0.", portNumberHttpsStr);
            Logger::put_l(
                Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
                parms);
#if defined(PEGASUS_DEBUG)
            cout << MessageLoader::getMessage(parms) << endl;
#endif
        }

#ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
        {
            _cimServer->addAcceptor(HTTPAcceptor::LOCAL_CONNECTION, 0, false);

            MessageLoaderParms parms(
                "src.Server.cimserver.LISTENING_ON_LOCAL",
                "Listening on local connection socket.");
            Logger::put_l(
                Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
                parms);
# if defined(PEGASUS_DEBUG)
            cout << MessageLoader::getMessage(parms) << endl;
# endif
        }
#endif

        _cimServer->bind();

        // notify parent process (if there is a parent process) to terminate
        // so user knows that there is cimserver ready to serve CIM requests.
        if (daemonOption)
        {
            _cimServerProcess->notify_parent(0);
        }

#if defined(PEGASUS_DEBUG)
        cout << "Started. " << endl;
#endif

        // Put server started message to the logger
        Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
            Logger::INFORMATION,
            MessageLoaderParms(
                "src.Server.cimserver.STARTED_VERSION",
                "Started $0 version $1.",
                _cimServerProcess->getProductName(),
                _cimServerProcess->getCompleteVersion()));

#if defined(PEGASUS_OS_TYPE_UNIX) && !defined(PEGASUS_OS_ZOS)
        if (daemonOption && !debugOutputOption)
        {
            // Direct standard input, output, and error to /dev/null,
            // since we are running as a daemon.
            close(STDIN_FILENO);
            open("/dev/null", O_RDONLY);
            close(STDOUT_FILENO);
            open("/dev/null", O_RDWR);
            close(STDERR_FILENO);
            open("/dev/null", O_RDWR);
        }
#endif
    }
    catch (Exception& e)
    {
        MessageLoaderParms parms("src.Server.cimserver.SERVER_NOT_STARTED",
            "cimserver not started: $0", e.getMessage());
        Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
            parms);
        cerr << MessageLoader::getMessage(parms) << endl;

        deleteCIMServer();

        //
        // notify parent process (if there is a parent process) to terminate
        //
        if (daemonOption)
            _cimServerProcess->notify_parent(1);

        return 1;
    }

    // Run the main CIM Server loop

    try
    {
#if defined(PEGASUS_OS_ZOS)

        // ARM is a z/OS internal restart facility.
        // This is a z/OS specific change.

        // Instatiating the automatic restart manager for zOS
        ARM_zOS automaticRestartManager;

        // register to zOS ARM
        automaticRestartManager.Register();

#endif

#ifdef PEGASUS_ENABLE_SLP
        _cimServer->startSLPProvider();
#endif
        _cimServer->initComplete();

        //
        // Loop to call CIMServer's runForever() method until CIMServer
        // has been shutdown
        //
        while (!_cimServer->terminated())
        {
            _cimServer->runForever();
        }

        //
        // normal termination
        //

#if defined(PEGASUS_OS_ZOS)

        // ARM is a z/OS internal restart facility.
        // This is a z/OS specific change.

        // register to zOS ARM
        automaticRestartManager.DeRegister();

#endif

        // Put server shutdown message to the logger
        Logger::put_l(
            Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
            MessageLoaderParms(
                "src.Server.cimserver.STOPPED",
                "$0 stopped.", _cimServerProcess->getProductName()));
    }
    catch (Exception& e)
    {
        MessageLoaderParms parms(
            "src.Server.cimserver.ERROR",
            "Error: $0",
            e.getMessage());
        Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
            parms);
        cerr << MessageLoader::getMessage(parms) << endl;

        deleteCIMServer();
        return 1;
    }

    deleteCIMServer();
    return 0;
}
Example #4
0
/**
    _bind - creates a new server socket and bind socket to the port address.
    If PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET is not defined, the port number is
    ignored and a domain socket is bound.
*/
void HTTPAcceptor::_bind()
{
#ifdef PEGASUS_OS_PASE
    AutoPtr<PaseCcsid> ccsid;
#endif

    PEGASUS_ASSERT(_rep != 0);
    // Create address:
    memset(_rep->address, 0, _rep->address_size);

    if (_connectionType == LOCAL_CONNECTION)
    {
#ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
        //
        // Make sure the local domain socket can be owned by the cimserver
        // user.  Otherwise, the bind may fail with a vague "bind failed"
        // error.
        //
#ifdef PEGASUS_OS_PASE
        // PASE domain socket needs ccsid 819
        int orig_ccsid;
        orig_ccsid = _SETCCSID(-1);
        if (orig_ccsid == -1)
        {
            PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
                    "HTTPAcceptor::_bind: Can not get current PASE CCSID.");
            orig_ccsid = 1208;
        }
        ccsid.reset(new PaseCcsid(819, orig_ccsid));
#endif
        if (System::exists(PEGASUS_LOCAL_DOMAIN_SOCKET_PATH))
        {
            if (!System::removeFile(PEGASUS_LOCAL_DOMAIN_SOCKET_PATH))
            {
                throw CannotRemoveFile(PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
            }
        }

        reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
            AF_UNIX;
        strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
            PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
#else
        PEGASUS_ASSERT(false);
#endif
    }
#ifdef PEGASUS_ENABLE_IPV6
    else if (_connectionType == IPV6_CONNECTION)
    {
        reinterpret_cast<struct sockaddr_in6*>(_rep->address)->sin6_addr =
            in6addr_any;
        reinterpret_cast<struct sockaddr_in6*>(_rep->address)->sin6_family =
            AF_INET6;
        reinterpret_cast<struct sockaddr_in6*>(_rep->address)->sin6_port =
            htons(_portNumber);
    }
#endif
    else if(_connectionType == IPV4_CONNECTION)
    {
        reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_addr.s_addr =
            INADDR_ANY;
        reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_family =
            AF_INET;
        reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_port =
            htons(_portNumber);
    }
    else
    {
        PEGASUS_ASSERT(false);
    }

    // Create socket:

    if (_connectionType == LOCAL_CONNECTION)
    {
        _rep->socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
    }
#ifdef PEGASUS_ENABLE_IPV6
    else if (_connectionType == IPV6_CONNECTION)
    {
        _rep->socket = Socket::createSocket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
    }
#endif
    else if (_connectionType == IPV4_CONNECTION)
    {
        _rep->socket = Socket::createSocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    }
    else
    {
        PEGASUS_ASSERT(false);
    }

    if (_rep->socket < 0)
    {
        delete _rep;
        _rep = 0;
        MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
            "Failed to create socket");
        throw BindFailedException(parms);
    }

    Socket::disableBlocking(_rep->socket);

// set the close-on-exec bit for this file handle.
// any unix that forks needs this bit set.
#if !defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_OS_VMS)
    int sock_flags;
    if ((sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
    {
        PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
            "HTTPAcceptor::_bind: fcntl(F_GETFD) failed");
    }
    else
    {
        sock_flags |= FD_CLOEXEC;
        if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
        {
            PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
                "HTTPAcceptor::_bind: fcntl(F_SETFD) failed");
        }
    }
#endif


    //
    // Set the socket option SO_REUSEADDR to reuse the socket address so
    // that we can rebind to a new socket using the same address when we
    // need to resume the cimom as a result of a timeout during a Shutdown
    // operation.
    //
    int opt=1;
    if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
            (char *)&opt, sizeof(opt)) < 0)
    {
        delete _rep;
        _rep = 0;
        MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
            "Failed to set socket option");
        throw BindFailedException(parms);
    }


    //
    // Bind socket to port:
    //
    if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
    {
        MessageLoaderParms parms(
            "Common.HTTPAcceptor.FAILED_BIND_SOCKET_DETAIL",
            "Failed to bind socket on port $0: $1.",
            _portNumber, PEGASUS_SYSTEM_NETWORK_ERRORMSG_NLS);

        delete _rep;
        _rep = 0;
        throw BindFailedException(parms);
    }


    //
    // Get the actual port value used if the caller specified a port value of 0.
    //
    if (_portNumber == 0)
    {
        sockaddr_in buf;
        SocketLength bufSize = sizeof(buf);
        if (getsockname(_rep->socket, reinterpret_cast<sockaddr *>(&buf),
                &bufSize) == 0 )
        {
            _portNumber = ntohs(buf.sin_port);
        }
    }


    //
    // Change permissions on Linux local domain socket to allow writes by
    // others.
    //
#if !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET) && \
     (defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
      defined(PEGASUS_OS_ZOS) || \
      defined(PEGASUS_OS_PASE))
    if (_connectionType == LOCAL_CONNECTION)
    {
        if (::chmod(PEGASUS_LOCAL_DOMAIN_SOCKET_PATH,
                S_IRUSR | S_IWUSR | S_IXUSR |
                S_IRGRP | S_IWGRP | S_IXGRP |
                S_IROTH | S_IWOTH | S_IXOTH ) < 0 )
        {
            MessageLoaderParms parms(
                "Common.HTTPAcceptor.FAILED_SET_LDS_FILE_OPTION",
                "Failed to set permission on local domain socket {0}: {1}.",
                PEGASUS_LOCAL_DOMAIN_SOCKET_PATH,
                PEGASUS_SYSTEM_ERRORMSG_NLS );

            delete _rep;
            _rep = 0;
            throw BindFailedException(parms);
        }
    }
#endif

    // Set up listening on the given socket:

    //int const _maxConnectionQueueLength = 15;

    if (::listen(_rep->socket, _maxConnectionQueueLength) < 0)
    {
        MessageLoaderParms parms(
            "Common.HTTPAcceptor.FAILED_LISTEN_SOCKET",
            "Failed to listen on socket {0}: {1}.",
            (int)_rep->socket,PEGASUS_SYSTEM_NETWORK_ERRORMSG_NLS );

        delete _rep;
        _rep = 0;
        throw BindFailedException(parms);
    }

    // Register to receive SocketMessages on this socket:

    if (-1 == ( _entry_index = _monitor->solicitSocketMessages(
            _rep->socket,
            SocketMessage::READ | SocketMessage::EXCEPTION,
            getQueueId(),
            MonitorEntry::TYPE_ACCEPTOR)))
    {
        delete _rep;
        _rep = 0;
        MessageLoaderParms parms(
            "Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
            "Failed to solicit socket messaeges");
        throw BindFailedException(parms);
    }
}
HTTPConnection* HTTPConnector::connect(
    const String& host,
    const Uint32 portNumber,
    SSLContext * sslContext,
    Uint32 timeoutMilliseconds,
    MessageQueue* outputMessageQueue)
{
    PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnector::connect()");

#ifdef PEGASUS_OS_PASE
    AutoPtr<PaseCcsid> ccsid;
#endif

    SocketHandle socket = PEGASUS_INVALID_SOCKET;
    // Use an AutoPtr to ensure the socket handle is closed on exception
    AutoPtr<SocketHandle, CloseSocketHandle> socketPtr(&socket);

#ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
    if (0 == host.size())
    {
        // Set up the domain socket for a local connection

        sockaddr_un address;

#ifdef PEGASUS_OS_PASE
        // PASE needs ccsid 819 to perform domain socket operation
        int orig_ccsid;
        orig_ccsid = _SETCCSID(-1);
        if (orig_ccsid == -1)
        {
            PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                    "HTTPConnector::connect() Can not get current PASE CCSID.");
            orig_ccsid = 1208;
        }
        ccsid.reset(new PaseCcsid(819, orig_ccsid));
#endif

        memset(&address, 0, sizeof(address));
        address.sun_family = AF_UNIX;
        strcpy(address.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);

        socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
        if (socket == PEGASUS_INVALID_SOCKET)
        {
            PEG_METHOD_EXIT();
            throw CannotCreateSocketException();
        }

        Socket::disableBlocking(socket);

        // Connect the socket to the address:

        if (!Socket::timedConnect(
                socket,
                reinterpret_cast<sockaddr*>(&address),
                sizeof(address),
                timeoutMilliseconds))
        {
            MessageLoaderParms parms(
                "Common.HTTPConnector.CONNECTION_FAILED_LOCAL_CIM_SERVER",
                "Cannot connect to local CIM server. Connection failed.");
            PEG_METHOD_EXIT();
            throw CannotConnectException(parms);
        }
    }
    else
#endif
    {
        // Set up the IP socket connection

        // Make the internet address:
#ifdef PEGASUS_ENABLE_IPV6
        struct addrinfo *addrInfo, *addrInfoRoot = NULL;
#else
        sockaddr_in address;
#endif
#ifdef PEGASUS_ENABLE_IPV6
        if (!_MakeAddress(
                 (const char*)host.getCString(),
                 portNumber,
                 (void**)(void*)&addrInfoRoot))
#else
        if (!_MakeAddress((const char*)host.getCString(), portNumber, address))
#endif
        {
            char scratch[22];
            Uint32 n;
            const char * portStr = Uint32ToString(scratch, portNumber, n);
            PEG_METHOD_EXIT();
            throw InvalidLocatorException(host+":"+String(portStr,n));
        }

#ifdef PEGASUS_ENABLE_IPV6
        addrInfo = addrInfoRoot;
        while (addrInfo)
        {
            // Create the socket:
            socket = Socket::createSocket(addrInfo->ai_family,
                addrInfo->ai_socktype, addrInfo->ai_protocol);
#else
            socket = Socket::createSocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
#endif
            if (socket == PEGASUS_INVALID_SOCKET)
            {
#ifdef PEGASUS_ENABLE_IPV6
                freeaddrinfo(addrInfoRoot);
#endif
                PEG_METHOD_EXIT();
                throw CannotCreateSocketException();
            }

#ifndef PEGASUS_OS_TYPE_WINDOWS
            // We need to ensure that the socket number is not higher than
            // what fits into FD_SETSIZE,because we else won't be able to select
            // on it and won't ever communicate correct on that socket.
            if (socket >= FD_SETSIZE)
            {
# ifdef PEGASUS_ENABLE_IPV6
                freeaddrinfo(addrInfoRoot);
# endif
                // the socket is useless to us, close it
                Socket::close(socket);

                PEG_TRACE(
                    (TRC_DISCARDED_DATA,
                     Tracer::LEVEL1,
                     "createSocket() returned too large socket number %d."
                         "Cannot connect to %s:%d. Connection failed.",
                     socket,
                     (const char*) host.getCString(),
                     portNumber));

                PEG_METHOD_EXIT();
                throw CannotCreateSocketException();
    }
#endif

            Socket::disableBlocking(socket);

            // Connect the socket to the address:
            if (!Socket::timedConnect(
                    socket,
#ifdef PEGASUS_ENABLE_IPV6
                    reinterpret_cast<sockaddr*>(addrInfo->ai_addr),
                    addrInfo->ai_addrlen,
#else
                    reinterpret_cast<sockaddr*>(&address),
                    sizeof(address),
#endif
                    timeoutMilliseconds))
            {
#ifdef PEGASUS_ENABLE_IPV6
                addrInfo = addrInfo->ai_next;
                if (addrInfo)
                {
                    Socket::close(socket);
                    continue;
                }
#endif
                char scratch[22];
                Uint32 n;
                const char * portStr = Uint32ToString(scratch, portNumber, n);
                MessageLoaderParms parms(
                    "Common.HTTPConnector.CONNECTION_FAILED_TO",
                    "Cannot connect to $0:$1. Connection failed.",
                    host,
                    portStr);
#ifdef PEGASUS_ENABLE_IPV6
                freeaddrinfo(addrInfoRoot);
#endif
                PEG_METHOD_EXIT();
                throw CannotConnectException(parms);
            }
#ifdef PEGASUS_ENABLE_IPV6
            break;
        }
        freeaddrinfo(addrInfoRoot);
#endif
    }

    // Create HTTPConnection object:

    SharedPtr<MP_Socket> mp_socket(new MP_Socket(socket, sslContext, 0));
    // mp_socket now has responsibility for closing the socket handle
    socketPtr.release();

    if (mp_socket->connect(timeoutMilliseconds) < 0)
    {
        char scratch[22];
        Uint32 n;
        const char * portStr = Uint32ToString(scratch, portNumber, n);
        MessageLoaderParms parms(
            "Common.HTTPConnector.CONNECTION_FAILED_TO",
            "Cannot connect to $0:$1. Connection failed.",
            host,
            portStr);
        PEG_METHOD_EXIT();
        throw CannotConnectException(parms);
    }

    AutoPtr<HTTPConnection> connection(new HTTPConnection(
        _monitor,
        mp_socket,
        String::EMPTY,
        0,
        outputMessageQueue));

    // Solicit events on this new connection's socket:
    int index;

    if (-1 == (index = _monitor->solicitSocketMessages(
            connection->getSocket(),
            connection->getQueueId(), MonitorEntry::TYPE_CONNECTION)))
    {
        PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
            "HTTPConnector::connect: Attempt to allocate entry in "
                "_entries table failed.");
        (connection->getMPSocket()).close();
    }

    connection->_entry_index = index;
    _rep->connections.append(connection.get());
    PEG_METHOD_EXIT();
    return connection.release();
}