PaseCcsid::~PaseCcsid() { if (_SETCCSID(_back) == -1) { PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1, "PaseCcsid::~PaseCcsid: Can not change PASE CCSID."); } _paseCcsidMutex.unlock(); }
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."); } }
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; }
/** _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(); }