version 1.17, 2002/05/22 05:25:30
|
version 1.24.2.3, 2003/02/10 22:07:56
|
|
|
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM, |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM, |
// The Open Group, Tivoli Systems | // The Open Group, Tivoli Systems |
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a copy | // Permission is hereby granted, free of charge, to any person obtaining a copy |
|
|
#include "TLS.h" | #include "TLS.h" |
#include "HTTPAcceptor.h" | #include "HTTPAcceptor.h" |
#include "HTTPConnection.h" | #include "HTTPConnection.h" |
|
#include "Tracer.h" |
| |
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
| |
|
|
#else | #else |
struct sockaddr_in address; | struct sockaddr_in address; |
#endif | #endif |
|
Mutex _connection_mut; |
|
|
Sint32 socket; | Sint32 socket; |
Array<HTTPConnection*> connections; | Array<HTTPConnection*> connections; |
}; | }; |
|
|
// | // |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
| |
HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueueService* outputMessageQueue) |
HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue) |
: Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), | : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), |
_monitor(monitor), _outputMessageQueue(outputMessageQueue), | _monitor(monitor), _outputMessageQueue(outputMessageQueue), |
_rep(0), _sslcontext(NULL) |
_rep(0), _sslcontext(NULL), _entry_index(-1) |
{ | { |
| |
|
_inet_address[0] = 0x00; |
Socket::initializeInterface(); | Socket::initializeInterface(); |
} | } |
| |
HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueueService* outputMessageQueue, |
HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue, |
SSLContext * sslcontext) | SSLContext * sslcontext) |
: Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), | : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), |
_monitor(monitor), _outputMessageQueue(outputMessageQueue), | _monitor(monitor), _outputMessageQueue(outputMessageQueue), |
_rep(0), | _rep(0), |
_sslcontext(sslcontext) |
_sslcontext(sslcontext), |
|
_entry_index(-1) |
|
{ |
|
_inet_address[0] = 0x00; |
|
Socket::initializeInterface(); |
|
} |
|
|
|
HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue, |
|
SSLContext * sslcontext, |
|
char *inet_address) |
|
: Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), |
|
_monitor(monitor), _outputMessageQueue(outputMessageQueue), |
|
_rep(0), |
|
_sslcontext(sslcontext), |
|
_entry_index(-1) |
{ | { |
|
strncpy(_inet_address, inet_address, 16); |
|
_inet_address[16] = 0x00; |
Socket::initializeInterface(); | Socket::initializeInterface(); |
} | } |
| |
|
|
CloseConnectionMessage* closeConnectionMessage | CloseConnectionMessage* closeConnectionMessage |
= (CloseConnectionMessage*)message; | = (CloseConnectionMessage*)message; |
| |
|
_rep->_connection_mut.lock(pegasus_thread_self()); |
|
|
for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) | for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) |
{ | { |
HTTPConnection* connection = _rep->connections[i]; | HTTPConnection* connection = _rep->connections[i]; |
|
|
{ | { |
_monitor->unsolicitSocketMessages(socket); | _monitor->unsolicitSocketMessages(socket); |
_rep->connections.remove(i); | _rep->connections.remove(i); |
while (connection->refcount.value()) { } |
|
delete connection; | delete connection; |
|
PEGASUS_STD(cout) << "Closing HTTP Connection; Current Connection Table Size: " << |
|
_rep->connections.size() << PEGASUS_STD(endl); |
break; | break; |
} | } |
} | } |
|
_rep->_connection_mut.unlock(); |
} | } |
| |
default: | default: |
|
|
void HTTPAcceptor::bind(Uint32 portNumber) | void HTTPAcceptor::bind(Uint32 portNumber) |
{ | { |
if (_rep) | if (_rep) |
throw BindFailed("HTTPAcceptor already bound"); |
throw BindFailedException("HTTPAcceptor already bound"); |
| |
_rep = new HTTPAcceptorRep; | _rep = new HTTPAcceptorRep; |
| |
|
|
strcpy(_rep->address.sun_path, "/var/opt/wbem/cimxml.socket"); | strcpy(_rep->address.sun_path, "/var/opt/wbem/cimxml.socket"); |
::unlink(_rep->address.sun_path); | ::unlink(_rep->address.sun_path); |
#else | #else |
|
if(_inet_address[0] != 0x00) |
|
{ |
|
_rep->address.sin_addr.s_addr = inet_addr(_inet_address); |
|
cout << "binding to " << _inet_address << endl; |
|
} |
|
else |
|
{ |
_rep->address.sin_addr.s_addr = INADDR_ANY; | _rep->address.sin_addr.s_addr = INADDR_ANY; |
|
} |
|
|
_rep->address.sin_family = AF_INET; | _rep->address.sin_family = AF_INET; |
_rep->address.sin_port = htons(_portNumber); | _rep->address.sin_port = htons(_portNumber); |
#endif | #endif |
|
|
{ | { |
delete _rep; | delete _rep; |
_rep = 0; | _rep = 0; |
throw BindFailed("Failed to create socket"); |
throw BindFailedException("Failed to create socket"); |
} | } |
| |
|
#ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC |
|
int sock_flags; |
|
if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0) |
|
{ |
|
PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2, |
|
"HTTPAcceptor: fcntl(F_GETFD) failed"); |
|
} |
|
else |
|
{ |
|
sock_flags |= FD_CLOEXEC; |
|
if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0) |
|
{ |
|
PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2, |
|
"HTTPAcceptor: fcntl(F_SETFD) failed"); |
|
} |
|
} |
|
#endif |
// | // |
// Set the socket option SO_REUSEADDR to reuse the socket address so | // 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 | // that we can rebind to a new socket using the same address when we |
|
|
{ | { |
delete _rep; | delete _rep; |
_rep = 0; | _rep = 0; |
throw BindFailed("Failed to set socket option"); |
throw BindFailedException("Failed to set socket option"); |
} | } |
| |
// Bind socket to port: | // Bind socket to port: |
|
|
Socket::close(_rep->socket); | Socket::close(_rep->socket); |
delete _rep; | delete _rep; |
_rep = 0; | _rep = 0; |
throw BindFailed("Failed to bind socket"); |
throw BindFailedException("Failed to bind socket"); |
} | } |
| |
// Set up listening on the given socket: | // Set up listening on the given socket: |
|
|
Socket::close(_rep->socket); | Socket::close(_rep->socket); |
delete _rep; | delete _rep; |
_rep = 0; | _rep = 0; |
throw BindFailed("Failed to bind socket"); |
throw BindFailedException("Failed to bind socket"); |
} | } |
| |
// Register to receive SocketMessages on this socket: | // Register to receive SocketMessages on this socket: |
| |
if (!_monitor->solicitSocketMessages( |
if ( -1 == ( _entry_index = _monitor->solicitSocketMessages( |
_rep->socket, | _rep->socket, |
SocketMessage::READ | SocketMessage::EXCEPTION, | SocketMessage::READ | SocketMessage::EXCEPTION, |
getQueueId(), | getQueueId(), |
Monitor::ACCEPTOR)) |
Monitor::ACCEPTOR))) |
{ | { |
Socket::close(_rep->socket); | Socket::close(_rep->socket); |
delete _rep; | delete _rep; |
_rep = 0; | _rep = 0; |
throw BindFailed("Failed to solicit socket messaeges"); |
throw BindFailedException("Failed to solicit socket messaeges"); |
} | } |
} | } |
| |
|
|
*/ | */ |
Uint32 HTTPAcceptor::getOutstandingRequestCount() | Uint32 HTTPAcceptor::getOutstandingRequestCount() |
{ | { |
|
Uint32 count = 0; |
|
|
|
_rep->_connection_mut.lock(pegasus_thread_self()); |
if (_rep->connections.size() > 0) | if (_rep->connections.size() > 0) |
{ | { |
HTTPConnection* connection = _rep->connections[0]; | HTTPConnection* connection = _rep->connections[0]; |
return(connection->getRequestCount()); |
count = connection->getRequestCount(); |
} |
|
else |
|
{ |
|
return(0); |
|
} | } |
|
_rep->_connection_mut.unlock(); |
|
return count; |
|
|
} | } |
| |
void HTTPAcceptor::unbind() | void HTTPAcceptor::unbind() |
|
|
{ | { |
// For each connection created by this object: | // For each connection created by this object: |
| |
|
_rep->_connection_mut.lock(pegasus_thread_self()); |
for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) | for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) |
{ | { |
HTTPConnection* connection = _rep->connections[i]; | HTTPConnection* connection = _rep->connections[i]; |
|
|
} | } |
| |
_rep->connections.clear(); | _rep->connections.clear(); |
|
_rep->_connection_mut.unlock(); |
} | } |
| |
void HTTPAcceptor::_acceptConnection() | void HTTPAcceptor::_acceptConnection() |
|
|
| |
sockaddr_in address; | sockaddr_in address; |
| |
|
|
#if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) | #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) |
size_t n = sizeof(address); | size_t n = sizeof(address); |
#else | #else |
int n = sizeof(address); | int n = sizeof(address); |
#endif | #endif |
| |
|
|
#if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) | #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) |
Sint32 socket = accept( | Sint32 socket = accept( |
_rep->socket, (struct sockaddr*)&address, (socklen_t *)&n); | _rep->socket, (struct sockaddr*)&address, (socklen_t *)&n); |
|
|
Sint32 socket = accept(_rep->socket, reinterpret_cast<struct sockaddr*>(&address), &n); | Sint32 socket = accept(_rep->socket, reinterpret_cast<struct sockaddr*>(&address), &n); |
#endif | #endif |
| |
|
|
|
|
if (socket < 0) | if (socket < 0) |
{ | { |
if (getenv("PEGASUS_TRACE")) |
PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2, |
cerr <<"HTTPAcceptor: accept() failed" << endl; |
"HTTPAcceptor: accept() failed"); |
|
|
return; | return; |
} | } |
|
#if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) |
|
if( _inet_address[0] != 0x00) |
|
{ |
|
if( 1023 < htons(address.sin_port) ) |
|
{ |
|
shutdown(socket, 2); |
|
Socket::close(socket); |
|
return; |
|
} |
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
#ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC |
|
int sock_flags; |
|
if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0) |
|
{ |
|
PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2, |
|
"HTTPAcceptor: fcntl(F_GETFD) failed"); |
|
} |
|
else |
|
{ |
|
sock_flags |= FD_CLOEXEC; |
|
if (fcntl(socket, F_SETFD, sock_flags) < 0) |
|
{ |
|
PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2, |
|
"HTTPAcceptor: fcntl(F_SETFD) failed"); |
|
} |
|
} |
|
#endif |
|
|
| |
// Create a new conection and add it to the connection list: | // Create a new conection and add it to the connection list: |
| |
MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext); | MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext); |
if (mp_socket->accept() < 0) { |
if (mp_socket->accept() < 0) |
if (getenv("PEGASUS_TRACE")) |
{ |
cerr <<"HTTPAcceptor: SSL_accept() failed" << endl; |
PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2, |
|
"HTTPAcceptor: SSL_accept() failed"); |
return; | return; |
} | } |
| |
|
|
_monitor, mp_socket, this, static_cast<MessageQueue *>(_outputMessageQueue)); | _monitor, mp_socket, this, static_cast<MessageQueue *>(_outputMessageQueue)); |
| |
// Solicit events on this new connection's socket: | // Solicit events on this new connection's socket: |
|
int index; |
| |
if (!_monitor->solicitSocketMessages( |
if (! (index = _monitor->solicitSocketMessages( |
socket, | socket, |
SocketMessage::READ | SocketMessage::EXCEPTION, | SocketMessage::READ | SocketMessage::EXCEPTION, |
connection->getQueueId(), Monitor::CONNECTION)) |
connection->getQueueId(), Monitor::CONNECTION)) ) |
{ | { |
delete connection; | delete connection; |
Socket::close(socket); | Socket::close(socket); |
} | } |
| |
// Save the socket for cleanup later: | // Save the socket for cleanup later: |
|
connection->_entry_index = index; |
|
_rep->_connection_mut.lock(pegasus_thread_self()); |
_rep->connections.append(connection); | _rep->connections.append(connection); |
|
_rep->_connection_mut.unlock(); |
|
PEGASUS_STD(cout) << "Creating new HTTP Connection; Current Connection Table Size: " << |
|
_rep->connections.size() << " entries" << endl; |
|
|
} | } |
| |
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |