version 1.93.4.4, 2008/01/02 21:05:03
|
version 1.108, 2007/11/27 20:03:02
|
|
|
#include "Tracer.h" | #include "Tracer.h" |
#include <Pegasus/Common/MessageLoader.h> | #include <Pegasus/Common/MessageLoader.h> |
| |
#ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM |
#ifdef PEGASUS_OS_PASE |
#include "EBCDIC_OS400.h" |
# include <as400_protos.h> |
|
# include <Pegasus/Common/PaseCcsid.h> |
#endif | #endif |
| |
|
|
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
| |
static int MAX_CONNECTION_QUEUE_LENGTH = -1; |
static int _maxConnectionQueueLength = -1; |
| |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
// | // |
|
|
Socket::initializeInterface(); | Socket::initializeInterface(); |
| |
/* | /* |
Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH |
Platforms interpret the value of _maxConnectionQueueLength |
differently. Some platforms interpret the value literally, while | differently. Some platforms interpret the value literally, while |
others multiply a fudge factor. When the server is under stress from | others multiply a fudge factor. When the server is under stress from |
multiple clients with multiple requests, toggling this number may | multiple clients with multiple requests, toggling this number may |
|
|
value, we allow an environment variable to be set which specifies a | value, we allow an environment variable to be set which specifies a |
number greater than the maximum concurrent client connections | number greater than the maximum concurrent client connections |
possible. If this environment var is not specified, then | possible. If this environment var is not specified, then |
MAX_CONNECTION_QUEUE_LENGTH = 15. |
_maxConnectionQueueLength = 15. |
*/ | */ |
| |
//To engage runtime backlog queue length: uncomment the following block AND | //To engage runtime backlog queue length: uncomment the following block AND |
//comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15 |
//comment out the line _maxConnectionQueueLength = 15 |
| |
/* | /* |
if (MAX_CONNECTION_QUEUE_LENGTH == -1) |
if (_maxConnectionQueueLength == -1) |
{ | { |
#ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM |
|
#pragma convert(37) |
|
const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE"); |
|
EtoA(env); |
|
#pragma convert(0) |
|
#else |
|
const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE"); | const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE"); |
#endif |
|
if (!env) | if (!env) |
{ | { |
MAX_CONNECTION_QUEUE_LENGTH = 15; |
_maxConnectionQueueLength = 15; |
} | } |
else | else |
{ | { |
char* end = NULL; | char* end = NULL; |
MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10); |
_maxConnectionQueueLength = strtol(env, &end, 10); |
if (*end) | if (*end) |
MAX_CONNECTION_QUEUE_LENGTH = 15; |
_maxConnectionQueueLength = 15; |
cout << " MAX_CONNECTION_QUEUE_LENGTH = " << |
cout << " _maxConnectionQueueLength = " << |
MAX_CONNECTION_QUEUE_LENGTH << endl; |
_maxConnectionQueueLength << endl; |
} | } |
} | } |
*/ | */ |
MAX_CONNECTION_QUEUE_LENGTH = 15; |
#ifdef PEGASUS_WMIMAPPER |
|
//The WMI Mapper can be used as a proxy to multiple WMI Servers. |
|
//If a client application simultaneously initiates connections |
|
//to many Windows systems, many of these connections may be routed |
|
//to a single WMI Mapper. A larger _maxConnectionQueueLength |
|
//value is required to allow these connections to be initiated |
|
//successfully. |
|
_maxConnectionQueueLength = 40; |
|
#else |
|
_maxConnectionQueueLength = 15; |
|
#endif |
} | } |
| |
HTTPAcceptor::~HTTPAcceptor() | HTTPAcceptor::~HTTPAcceptor() |
|
|
*/ | */ |
void HTTPAcceptor::_bind() | void HTTPAcceptor::_bind() |
{ | { |
|
#ifdef PEGASUS_OS_PASE |
|
// bind need ccsid is 819 |
|
int orig_ccsid; |
|
orig_ccsid = _SETCCSID(-1); |
|
if (orig_ccsid == -1) |
|
{ |
|
PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
|
String("HTTPAcceptor::_bind: Can not get current PASE CCSID.")); |
|
orig_ccsid = 1208; |
|
} |
|
PaseCcsid ccsid(819, orig_ccsid); |
|
#endif |
|
|
PEGASUS_ASSERT(_rep != 0); | PEGASUS_ASSERT(_rep != 0); |
// Create address: | // Create address: |
memset(_rep->address, 0, _rep->address_size); | memset(_rep->address, 0, _rep->address_size); |
|
|
if (_connectionType == LOCAL_CONNECTION) | if (_connectionType == LOCAL_CONNECTION) |
{ | { |
#ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET | #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. |
|
// |
|
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 = | reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family = |
AF_UNIX; | AF_UNIX; |
strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path, | strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path, |
PEGASUS_LOCAL_DOMAIN_SOCKET_PATH); | PEGASUS_LOCAL_DOMAIN_SOCKET_PATH); |
#ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM |
|
AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path); |
|
#endif |
|
::unlink( |
|
reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path); |
|
#else | #else |
PEGASUS_ASSERT(false); | PEGASUS_ASSERT(false); |
#endif | #endif |
|
|
throw BindFailedException(parms); | throw BindFailedException(parms); |
} | } |
| |
Socket::disableBlocking(_rep->socket); |
|
| |
// set the close-on-exec bit for this file handle. | // set the close-on-exec bit for this file handle. |
// any unix that forks needs this bit set. | // any unix that forks needs this bit set. |
|
|
| |
// Set up listening on the given socket: | // Set up listening on the given socket: |
| |
//int const MAX_CONNECTION_QUEUE_LENGTH = 15; |
//int const _maxConnectionQueueLength = 15; |
| |
if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0) |
if (listen(_rep->socket, _maxConnectionQueueLength) < 0) |
{ | { |
Socket::close(_rep->socket); | Socket::close(_rep->socket); |
delete _rep; | delete _rep; |
|
|
_rep->socket, | _rep->socket, |
SocketMessage::READ | SocketMessage::EXCEPTION, | SocketMessage::READ | SocketMessage::EXCEPTION, |
getQueueId(), | getQueueId(), |
Monitor::ACCEPTOR))) |
MonitorEntry::TYPE_ACCEPTOR))) |
{ | { |
Socket::close(_rep->socket); | Socket::close(_rep->socket); |
delete _rep; | delete _rep; |
|
|
#endif | #endif |
} | } |
| |
// It is not necessary to handle EINTR errors from this accept() call. |
SocketHandle socket; |
// An EINTR error should not occur on a non-blocking socket. If the |
#ifdef PEGASUS_OS_TYPE_WINDOWS |
// listen socket is blocking and EINTR occurs, the new socket connection |
socket = accept(_rep->socket, accept_address, &address_size); |
// is not accepted here. |
#else |
|
while ( |
// EAGAIN errors are also not handled here. An EAGAIN error should not |
((socket = accept(_rep->socket, accept_address, &address_size)) == -1) |
// occur after select() indicates that the listen socket is available for |
&& (errno == EINTR)) |
// reading. If the accept() fails with an EAGAIN error code, a new |
; |
// connection is not accepted here. |
#endif |
|
|
SocketHandle socket = accept(_rep->socket, accept_address, &address_size); |
|
| |
if (socket == PEGASUS_SOCKET_ERROR) | if (socket == PEGASUS_SOCKET_ERROR) |
{ | { |
|
|
#ifdef PEGASUS_ENABLE_IPV6 | #ifdef PEGASUS_ENABLE_IPV6 |
char ipBuffer[PEGASUS_INET6_ADDRSTR_LEN]; | char ipBuffer[PEGASUS_INET6_ADDRSTR_LEN]; |
int rc; | int rc; |
while ((rc = getnameinfo(accept_address, address_size, ipBuffer, |
if ((rc = System::getNameInfo(accept_address, |
PEGASUS_INET6_ADDRSTR_LEN, 0, 0, NI_NUMERICHOST)) == EAI_AGAIN) |
address_size, |
; |
ipBuffer, |
if (rc) |
PEGASUS_INET6_ADDRSTR_LEN, |
|
0, |
|
0, |
|
NI_NUMERICHOST))) |
{ | { |
Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE, | Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE, |
"HTTPAcceptor - getnameinfo() failure. rc: $0", rc); | "HTTPAcceptor - getnameinfo() failure. rc: $0", rc); |
|
|
PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0, | PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0, |
"HTTPAcceptor - accept() success. Socket: $1" ,socket)); | "HTTPAcceptor - accept() success. Socket: $1" ,socket)); |
| |
AutoPtr<MP_Socket> mp_socket(new MP_Socket( |
SharedPtr<MP_Socket> mp_socket(new MP_Socket( |
socket, _sslcontext, _sslContextObjectLock)); |
socket, _sslcontext, _sslContextObjectLock, ipAddress)); |
| |
mp_socket->disableBlocking(); |
|
mp_socket->setSocketWriteTimeout(_socketWriteTimeout); | mp_socket->setSocketWriteTimeout(_socketWriteTimeout); |
| |
// Perform the SSL handshake, if applicable. |
// Perform the SSL handshake, if applicable. Make the socket non-blocking |
|
// for this operation so we can send it back to the Monitor's select() loop |
|
// if it takes a while. |
| |
|
mp_socket->disableBlocking(); |
Sint32 socketAcceptStatus = mp_socket->accept(); | Sint32 socketAcceptStatus = mp_socket->accept(); |
|
mp_socket->enableBlocking(); |
| |
if (socketAcceptStatus < 0) | if (socketAcceptStatus < 0) |
{ | { |
|
|
if (-1 == (index = _monitor->solicitSocketMessages( | if (-1 == (index = _monitor->solicitSocketMessages( |
connection->getSocket(), | connection->getSocket(), |
SocketMessage::READ | SocketMessage::EXCEPTION, | SocketMessage::READ | SocketMessage::EXCEPTION, |
connection->getQueueId(), Monitor::CONNECTION)) ) |
connection->getQueueId(), MonitorEntry::TYPE_CONNECTION)) ) |
{ | { |
// ATTN-DE-P2-2003100503::TODO::Need to enhance code to return | // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return |
// an error message to Client application. | // an error message to Client application. |