version 1.105, 2007/09/07 20:08:37
|
version 1.106.2.6, 2008/01/25 21:46:34
|
|
|
_connectionType(connectionType), | _connectionType(connectionType), |
_portNumber(portNumber), | _portNumber(portNumber), |
_sslcontext(sslcontext), | _sslcontext(sslcontext), |
_sslContextObjectLock(sslContextObjectLock) |
_sslContextObjectLock(sslContextObjectLock), |
|
_idleConnectionTimeoutSeconds(0) |
{ | { |
Socket::initializeInterface(); | Socket::initializeInterface(); |
| |
|
|
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. |
|
|
if (_rep) | if (_rep) |
{ | { |
AutoMutex autoMut(_rep->_connection_mut); | AutoMutex autoMut(_rep->_connection_mut); |
if (_rep->connections.size() > 0) |
for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) |
|
{ |
|
HTTPConnection* connection = _rep->connections[i]; |
|
if (connection->isResponsePending()) |
{ | { |
HTTPConnection* connection = _rep->connections[0]; |
count++; |
count = connection->getRequestCount(); |
} |
} | } |
} | } |
return count; | return count; |
|
|
_socketWriteTimeout = socketWriteTimeout; | _socketWriteTimeout = socketWriteTimeout; |
} | } |
| |
|
void HTTPAcceptor::setIdleConnectionTimeout(Uint32 idleConnectionTimeoutSeconds) |
|
{ |
|
_idleConnectionTimeoutSeconds = idleConnectionTimeoutSeconds; |
|
} |
|
|
void HTTPAcceptor::unbind() | void HTTPAcceptor::unbind() |
{ | { |
if (_rep) | if (_rep) |
|
|
#endif | #endif |
} | } |
| |
SocketHandle socket; |
// It is not necessary to handle EINTR errors from this accept() call. |
#ifdef PEGASUS_OS_TYPE_WINDOWS |
// An EINTR error should not occur on a non-blocking socket. If the |
socket = accept(_rep->socket, accept_address, &address_size); |
// listen socket is blocking and EINTR occurs, the new socket connection |
#else |
// is not accepted here. |
while ( |
|
((socket = accept(_rep->socket, accept_address, &address_size)) == -1) |
// EAGAIN errors are also not handled here. An EAGAIN error should not |
&& (errno == EINTR)) |
// occur after select() indicates that the listen socket is available for |
; |
// reading. If the accept() fails with an EAGAIN error code, a new |
#endif |
// connection is not accepted here. |
|
|
|
SocketHandle socket = accept(_rep->socket, accept_address, &address_size); |
| |
if (socket == PEGASUS_SOCKET_ERROR) | if (socket == PEGASUS_SOCKET_ERROR) |
{ | { |
|
|
"HTTPAcceptor: accept() failed"); | "HTTPAcceptor: accept() failed"); |
return; | return; |
} | } |
|
// 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) |
|
{ |
|
// the remote connection is invalid, destroy client address. |
|
delete accept_address; |
|
|
|
Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE, |
|
"HTTPAcceptor out of available sockets. " |
|
"Closing connection to the new client."); |
|
|
|
PEG_TRACE( |
|
(TRC_DISCARDED_DATA, |
|
Tracer::LEVEL2, |
|
"accept() returned too large socket number %d.", |
|
socket)); |
|
|
|
// close the connection |
|
Socket::close(socket); |
|
return; |
|
} |
|
|
| |
String ipAddress; | String ipAddress; |
| |
|
|
#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); |
|
|
SharedPtr<MP_Socket> mp_socket(new MP_Socket( | SharedPtr<MP_Socket> mp_socket(new MP_Socket( |
socket, _sslcontext, _sslContextObjectLock, ipAddress)); | socket, _sslcontext, _sslContextObjectLock, ipAddress)); |
| |
|
mp_socket->disableBlocking(); |
mp_socket->setSocketWriteTimeout(_socketWriteTimeout); | mp_socket->setSocketWriteTimeout(_socketWriteTimeout); |
| |
// Perform the SSL handshake, if applicable. Make the socket non-blocking |
// Perform the SSL handshake, if applicable. |
// 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) |
{ | { |
|
|
HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket, | HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket, |
ipAddress, this, static_cast<MessageQueue *>(_outputMessageQueue)); | ipAddress, this, static_cast<MessageQueue *>(_outputMessageQueue)); |
| |
|
if (_idleConnectionTimeoutSeconds) |
|
{ |
|
connection->_idleConnectionTimeoutSeconds = |
|
_idleConnectionTimeoutSeconds; |
|
Time::gettimeofday(&connection->_idleStartTime); |
|
} |
|
|
if (socketAcceptStatus == 0) | if (socketAcceptStatus == 0) |
{ | { |
PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL2, | PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL2, |
"HTTPAcceptor: SSL_accept() pending"); | "HTTPAcceptor: SSL_accept() pending"); |
connection->_acceptPending = true; | connection->_acceptPending = true; |
|
Time::gettimeofday(&connection->_acceptPendingStartTime); |
} | } |
| |
// Solicit events on this new connection's socket: | // Solicit events on this new connection's socket: |