(file) Return to HTTPAcceptor.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

Diff for /pegasus/src/Pegasus/Common/HTTPAcceptor.cpp between version 1.45.2.1 and 1.92

version 1.45.2.1, 2004/01/16 16:57:31 version 1.92, 2006/11/08 22:24:00
Line 1 
Line 1 
 //%2003////////////////////////////////////////////////////////////////////////  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development  // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.  // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.; // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
 // IBM Corp.; EMC Corporation, The Open Group. // IBM Corp.; EMC Corporation, The Open Group.
   // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; Symantec Corporation; The Open Group.
 // //
 // 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
 // of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
Line 23 
Line 29 
 // //
 //============================================================================== //==============================================================================
 // //
 // Author: Mike Brasher (mbrasher@bmc.com)  
 //  
 // Modified By:  
 //         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)  
 //         Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)  
 //         Dave Rosckes (rosckes@us.ibm.com)  
 //         Denise Eckstein (denise.eckstein@hp.com)  
 //  
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include "Config.h" #include "Config.h"
 #include "Constants.h" #include "Constants.h"
 #include <iostream> #include <iostream>
 #include "Socket.h"  
   
 #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC  
 #include <windows.h>  
 #else  
 # include <cctype>  
 # include <cstdlib>  
 # include <errno.h>  
 # include <fcntl.h>  
 # include <netdb.h>  
 # include <netinet/in.h>  
 # include <arpa/inet.h>  
 # include <sys/socket.h>  
 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  
 # include <unistd.h>  
 #  include <sys/un.h>  
 # endif  
 #endif  
  
   #include "Network.h"
 #include "Socket.h" #include "Socket.h"
 #include "TLS.h" #include "TLS.h"
 #include "HTTPAcceptor.h" #include "HTTPAcceptor.h"
Line 63 
Line 44 
 #include <Pegasus/Common/MessageLoader.h> //l10n #include <Pegasus/Common/MessageLoader.h> //l10n
  
 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
 #include "OS400ConvertChar.h"  #include "EBCDIC_OS400.h"
 #endif #endif
  
   
 PEGASUS_USING_STD; PEGASUS_USING_STD;
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
   
   static int MAX_CONNECTION_QUEUE_LENGTH = -1;
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // HTTPAcceptorRep // HTTPAcceptorRep
Line 83 
Line 68 
     {     {
         if (local)         if (local)
         {         {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
             address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);              address =
                   reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
             address_size = sizeof(struct sockaddr_un);             address_size = sizeof(struct sockaddr_un);
 #else #else
             PEGASUS_ASSERT(false);             PEGASUS_ASSERT(false);
Line 92 
Line 78 
         }         }
         else         else
         {         {
             address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);              address =
                   reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
             address_size = sizeof(struct sockaddr_in);             address_size = sizeof(struct sockaddr_in);
         }         }
     }     }
       ~HTTPAcceptorRep()
       {
           delete address;
       }
     struct sockaddr* address;     struct sockaddr* address;
  
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)      SocketLength address_size;
    size_t address_size;  
 #elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || (defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC) && !defined(SUNOS_5_6))  
    socklen_t address_size;  
 #else  
    int address_size;  
 #endif  
       Mutex _connection_mut;       Mutex _connection_mut;
  
       Sint32 socket;      SocketHandle socket;
       Array<HTTPConnection*> connections;       Array<HTTPConnection*> connections;
 }; };
  
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // HTTPAcceptor // HTTPAcceptor
Line 122 
Line 107 
                            MessageQueue* outputMessageQueue,                            MessageQueue* outputMessageQueue,
                            Boolean localConnection,                            Boolean localConnection,
                            Uint32 portNumber,                            Uint32 portNumber,
                            SSLContext * sslcontext)                             SSLContext * sslcontext,
                              ReadWriteSem* sslContextObjectLock)
    : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?    : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
      _monitor(monitor),      _monitor(monitor),
      _outputMessageQueue(outputMessageQueue),      _outputMessageQueue(outputMessageQueue),
Line 130 
Line 116 
      _entry_index(-1),      _entry_index(-1),
      _localConnection(localConnection),      _localConnection(localConnection),
      _portNumber(portNumber),      _portNumber(portNumber),
      _sslcontext(sslcontext)       _sslcontext(sslcontext),
        _sslContextObjectLock(sslContextObjectLock)
 { {
    Socket::initializeInterface();    Socket::initializeInterface();
   
      /*
           Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH
           differently.  Some platforms interpret the value literally, while
           others multiply a fudge factor. When the server is under stress from
           multiple clients with multiple requests, toggling this number may
           prevent clients from being dropped.  Instead of hard coding the
           value, we allow an environment variable to be set which specifies a
           number greater than the maximum concurrent client connections
           possible.  If this environment var is not specified, then
           MAX_CONNECTION_QUEUE_LENGTH = 15.
      */
   
   //To engage runtime backlog queue length: uncomment the following block AND
   //comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
   
   /*
       if (MAX_CONNECTION_QUEUE_LENGTH == -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");
   #endif
           if (!env)
           {
               MAX_CONNECTION_QUEUE_LENGTH = 15;
           }
           else
           {
               char* end = NULL;
               MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
               if (*end)
                   MAX_CONNECTION_QUEUE_LENGTH = 15;
               cout << " MAX_CONNECTION_QUEUE_LENGTH = " <<
                   MAX_CONNECTION_QUEUE_LENGTH << endl;
           }
       }
   */
       MAX_CONNECTION_QUEUE_LENGTH = 15;
 } }
  
 HTTPAcceptor::~HTTPAcceptor() HTTPAcceptor::~HTTPAcceptor()
 { {
       destroyConnections();
    unbind();    unbind();
    // ATTN: Is this correct in a multi-HTTPAcceptor server?    // ATTN: Is this correct in a multi-HTTPAcceptor server?
    Socket::uninitializeInterface();    Socket::uninitializeInterface();
Line 147 
Line 178 
    if (! message)    if (! message)
       return;       return;
  
       PEGASUS_ASSERT(_rep != 0);
    switch (message->getType())    switch (message->getType())
    {    {
       case SOCKET_MESSAGE:       case SOCKET_MESSAGE:
Line 156 
Line 188 
          // If this is a connection request:          // If this is a connection request:
  
          if (socketMessage->socket == _rep->socket &&          if (socketMessage->socket == _rep->socket &&
              socketMessage->events | SocketMessage::READ)                  socketMessage->events & SocketMessage::READ)
          {          {
             _acceptConnection();             _acceptConnection();
          }          }
Line 164 
Line 196 
          {          {
             // ATTN! this can't happen!             // ATTN! this can't happen!
             Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,             Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");                      "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE "
                           "received.");
          }          }
  
          break;          break;
Line 172 
Line 205 
  
       case CLOSE_CONNECTION_MESSAGE:       case CLOSE_CONNECTION_MESSAGE:
       {       {
          CloseConnectionMessage* closeConnectionMessage             CloseConnectionMessage* closeConnectionMessage =
             = (CloseConnectionMessage*)message;                 (CloseConnectionMessage*)message;
  
          _rep->_connection_mut.lock(pegasus_thread_self());             AutoMutex autoMut(_rep->_connection_mut);
  
          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];
             Sint32 socket = connection->getSocket();                 SocketHandle socket = connection->getSocket();
  
             if (socket == closeConnectionMessage->socket)             if (socket == closeConnectionMessage->socket)
             {             {
Line 190 
Line 223 
                break;                break;
             }             }
          }          }
          _rep->_connection_mut.unlock();  
          break;          break;
       }       }
  
Line 199 
Line 232 
       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
            "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");            "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
       break;       break;
    };      }
  
    delete message;    delete message;
 } }
Line 217 
Line 250 
    }    }
  
    handleEnqueue(message);    handleEnqueue(message);
   
 } }
  
 void HTTPAcceptor::bind() void HTTPAcceptor::bind()
 { {
    if (_rep){      if (_rep)
         //l10n      {
       //throw BindFailedException("HTTPAcceptor already bound");  
   
       MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",       MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
                                "HTTPAcceptor already bound");                                "HTTPAcceptor already bound");
  
Line 238 
Line 268 
  
    // bind address    // bind address
    _bind();    _bind();
   
    return;  
 } }
  
 /** /**
    _bind - creates a new server socket and bind socket to the port address.    _bind - creates a new server socket and bind socket to the port address.
    If PEGASUS_LOCAL_DOMAIN_SOCKET is defined, the port number is ignored and      If PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET is not defined, the port number is
    a domain socket is bound.      ignored and a domain socket is bound.
 */ */
 void HTTPAcceptor::_bind() void HTTPAcceptor::_bind()
 { {
       PEGASUS_ASSERT(_rep != 0);
    // Create address:    // Create address:
  
    memset(_rep->address, 0, sizeof(*_rep->address));    memset(_rep->address, 0, sizeof(*_rep->address));
  
    if (_localConnection)    if (_localConnection)
    {    {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
        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,
Line 264 
Line 292 
 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
        AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);        AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
 #endif #endif
        ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);          ::unlink(
               reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
 #else #else
        PEGASUS_ASSERT(false);        PEGASUS_ASSERT(false);
 #endif #endif
Line 283 
Line 312 
  
    if (_localConnection)    if (_localConnection)
    {    {
        _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);          _rep->socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
    }    }
    else    else
    {    {
        _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);          _rep->socket = Socket::createSocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    }    }
  
    if (_rep->socket < 0)    if (_rep->socket < 0)
    {    {
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
       //l10n  
       //throw BindFailedException("Failed to create socket");  
       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
                                "Failed to create socket");                                "Failed to create socket");
       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
Line 306 
Line 333 
  
 // 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.
 #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC  #if !defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_OS_VMS)
    int sock_flags;    int sock_flags;
  if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)  if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
    {    {
Line 338 
Line 365 
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
       //l10n  
       //throw BindFailedException("Failed to set socket option");  
       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
                                "Failed to set socket option");                                "Failed to set socket option");
       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
Line 347 
Line 372 
       throw BindFailedException(parms);       throw BindFailedException(parms);
    }    }
  
    // Bind socket to port:  
  
       //
       // Bind socket to port:
       //
    if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)    if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
    {    {
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
       //l10n  
       //throw BindFailedException("Failed to bind socket");  
       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
                                "Failed to bind socket");                                "Failed to bind socket");
       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
Line 363 
Line 388 
       throw BindFailedException(parms);       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_PLATFORM_ZOS_ZSERIES_IBM))
       if (_localConnection)
       {
           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 )
           {
               Socket::close(_rep->socket);
               delete _rep;
               _rep = 0;
               MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
                   "Failed to bind socket");
               PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                   "HTTPAcceptor::_bind: Failed to set domain socket "
                       "permissions.");
               throw BindFailedException(parms);
           }
       }
   #endif
   
    // Set up listening on the given socket:    // Set up listening on the given socket:
  
    int const MAX_CONNECTION_QUEUE_LENGTH = 15;      //int const MAX_CONNECTION_QUEUE_LENGTH = 15;
  
    if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)    if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
    {    {
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
       //l10n  
       //throw BindFailedException("Failed to bind socket");  
       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
                                "Failed to bind socket");                                "Failed to bind socket");
       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
Line 392 
Line 458 
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
       //l10n          MessageLoaderParms parms(
       //throw BindFailedException("Failed to solicit socket messaeges");              "Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
       MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",  
                                "Failed to solicit socket messaeges");                                "Failed to solicit socket messaeges");
       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                   "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");                   "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
Line 417 
Line 482 
  
       // close the socket       // close the socket
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
           // Unlink Local Domain Socket Bug# 3312
           if (_localConnection)
           {
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
               PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
                   "HTTPAcceptor::closeConnectionSocket Unlinking local "
                       "connection.");
               ::unlink(
                   reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
   #else
               PEGASUS_ASSERT(false);
   #endif
           }
    }    }
    else    else
    {    {
Line 441 
Line 519 
    }    }
 } }
  
   
   /**
      reconnectConnectionSocket - creates a new server socket.
   */
   void HTTPAcceptor::reconnectConnectionSocket()
   {
       if (_rep)
       {
           // unregister the socket
           _monitor->unsolicitSocketMessages(_rep->socket);
           // close the socket
           Socket::close(_rep->socket);
           // Unlink Local Domain Socket Bug# 3312
           if (_localConnection)
           {
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
               PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
                   "HTTPAcceptor::reconnectConnectionSocket Unlinking local "
                       "connection." );
               ::unlink(
                   reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
   #else
               PEGASUS_ASSERT(false);
   #endif
           }
           // open the socket
           _bind();
       }
       else
       {
           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::reconnectConnectionSocket failure _rep is null.");
       }
   }
   
 /** /**
    getOutstandingRequestCount - returns the number of outstanding requests.    getOutstandingRequestCount - returns the number of outstanding requests.
 */ */
 Uint32 HTTPAcceptor::getOutstandingRequestCount()  Uint32 HTTPAcceptor::getOutstandingRequestCount() const
 { {
    Uint32 count = 0;    Uint32 count = 0;
       if (_rep)
    _rep->_connection_mut.lock(pegasus_thread_self());      {
           AutoMutex autoMut(_rep->_connection_mut);
    if (_rep->connections.size() > 0)    if (_rep->connections.size() > 0)
    {    {
       HTTPConnection* connection = _rep->connections[0];       HTTPConnection* connection = _rep->connections[0];
       count = connection->getRequestCount();       count = connection->getRequestCount();
    }    }
    _rep->_connection_mut.unlock();      }
    return count;    return count;
 } }
  
   
   /**
       getPortNumber - returns the port number used for the connection
   */
   Uint32 HTTPAcceptor::getPortNumber() const
   {
       return _portNumber;
   }
   
   void HTTPAcceptor::setSocketWriteTimeout(Uint32 socketWriteTimeout)
   {
       _socketWriteTimeout = socketWriteTimeout;
   }
   
 void HTTPAcceptor::unbind() void HTTPAcceptor::unbind()
 { {
    if (_rep)    if (_rep)
    {    {
           _portNumber = 0;
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
  
       if (_localConnection)       if (_localConnection)
       {       {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
          ::unlink(          ::unlink(
              reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);              reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
 #else #else
Line 486 
Line 615 
  
 void HTTPAcceptor::destroyConnections() void HTTPAcceptor::destroyConnections()
 { {
       if (_rep)
       {
    // For each connection created by this object:    // For each connection created by this object:
  
    _rep->_connection_mut.lock(pegasus_thread_self());          AutoMutex autoMut(_rep->_connection_mut);
    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];
       Sint32 socket = connection->getSocket();              SocketHandle socket = connection->getSocket();
  
       // Unsolicit SocketMessages:       // Unsolicit SocketMessages:
  
Line 502 
Line 631 
  
       // Destroy the connection (causing it to close):       // Destroy the connection (causing it to close):
  
       while (connection->refcount.value()) { }              while (connection->refcount.get()) { }
       delete connection;       delete connection;
    }    }
  
    _rep->connections.clear();    _rep->connections.clear();
    _rep->_connection_mut.unlock();      }
 } }
  
 void HTTPAcceptor::_acceptConnection() void HTTPAcceptor::_acceptConnection()
Line 516 
Line 645 
  
    PEGASUS_ASSERT(_rep != 0);    PEGASUS_ASSERT(_rep != 0);
  
    if (!_rep)  
       return;  
   
    // Accept the connection (populate the address):    // Accept the connection (populate the address):
  
    struct sockaddr* accept_address;    struct sockaddr* accept_address;
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)      SocketLength address_size;
    size_t address_size;  
 #elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || (defined(PEGASUS_OS_SOLARIS) && !defined(SUNOS_5_6))  
    socklen_t address_size;  
 #else  
    int address_size;  
 #endif  
  
    if (_localConnection)    if (_localConnection)
    {    {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
        accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);          accept_address =
               reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
        address_size = sizeof(struct sockaddr_un);        address_size = sizeof(struct sockaddr_un);
 #else #else
        PEGASUS_ASSERT(false);        PEGASUS_ASSERT(false);
Line 541 
Line 662 
    }    }
    else    else
    {    {
        accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);          accept_address =
               reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
        address_size = sizeof(struct sockaddr_in);        address_size = sizeof(struct sockaddr_in);
    }    }
  
    Sint32 socket = accept(_rep->socket, accept_address, &address_size);      SocketHandle socket = accept(_rep->socket, accept_address, &address_size);
  
       if (socket == PEGASUS_SOCKET_ERROR)
       {
           // the remote connection is invalid, destroy client address.
    delete accept_address;    delete accept_address;
  
    if (socket < 0)          // TCPIP is down reconnect this acceptor
           if (getSocketError() == PEGASUS_NETWORK_TCPIP_STOPPED)
    {    {
               PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                   "Socket has an IO error. TCP/IP down. Try to reconnect.");
   
               reconnectConnectionSocket();
   
               return;
           }
  
        Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,        Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
                    "HTTPAcceptor - accept() failure.  errno: $0"              "HTTPAcceptor - accept() failure.  errno: $0", errno);
                    ,errno);  
  
        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                         "HTTPAcceptor: accept() failed");                         "HTTPAcceptor: accept() failed");
       return;       return;
    }    }
  
       String ipAddress;
   
       if (_localConnection)
       {
           ipAddress = "localhost";
       }
       else
       {
           unsigned char* sa = reinterpret_cast<unsigned char*>(
               &reinterpret_cast<struct sockaddr_in*>(
                   accept_address)->sin_addr.s_addr);
           char ipBuffer[32];
           sprintf(ipBuffer, "%u.%u.%u.%u", sa[0], sa[1], sa[2], sa[3]);
           ipAddress = ipBuffer;
       }
   
       delete accept_address;
   
 // set the close on exec flag // set the close on exec flag
 #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC  #if !defined(PEGASUS_OS_TYPE_WINDOWS) && !defined(PEGASUS_OS_VMS)
    int sock_flags;    int sock_flags;
  if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)  if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
    {    {
Line 581 
Line 731 
 #endif #endif
  
  
    Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,      PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0,
                "HTTPAcceptor - accept() success.  Socket: $1"          "HTTPAcceptor - accept() success.  Socket: $1" ,socket));
                ,socket);  
       AutoPtr<MP_Socket> mp_socket(new MP_Socket(
           socket, _sslcontext, _sslContextObjectLock));
   
       mp_socket->setSocketWriteTimeout(_socketWriteTimeout);
   
       // 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.
  
    // Create a new conection and add it to the connection list:      mp_socket->disableBlocking();
       Sint32 socketAcceptStatus = mp_socket->accept();
       mp_socket->enableBlocking();
  
    MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);      if (socketAcceptStatus < 0)
    if (mp_socket->accept() < 0)  
    {    {
        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                         "HTTPAcceptor: SSL_accept() failed");                         "HTTPAcceptor: SSL_accept() failed");
           mp_socket->close();
       return;       return;
    }    }
  
    HTTPConnection* connection = new HTTPConnection(      // Create a new connection and add it to the connection list:
       _monitor, mp_socket, this, static_cast<MessageQueue *>(_outputMessageQueue));  
       HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
           ipAddress, this, static_cast<MessageQueue *>(_outputMessageQueue));
   
       if (socketAcceptStatus == 0)
       {
           PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
               "HTTPAcceptor: SSL_accept() pending");
           connection->_acceptPending = true;
       }
  
    // Solicit events on this new connection's socket:    // Solicit events on this new connection's socket:
    int index;    int index;
  
    if (-1 ==  (index = _monitor->solicitSocketMessages(    if (-1 ==  (index = _monitor->solicitSocketMessages(
           socket,              connection->getSocket(),
           SocketMessage::READ | SocketMessage::EXCEPTION,           SocketMessage::READ | SocketMessage::EXCEPTION,
           connection->getQueueId(), Monitor::CONNECTION)) )           connection->getQueueId(), Monitor::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.
       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
           "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");              "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in "
                   "_entries table failed.");
       delete connection;       delete connection;
       Socket::close(socket);       Socket::close(socket);
       return;       return;
Line 617 
Line 787 
  
    // Save the socket for cleanup later:    // Save the socket for cleanup later:
    connection->_entry_index = index;    connection->_entry_index = index;
    _rep->_connection_mut.lock(pegasus_thread_self());      AutoMutex autoMut(_rep->_connection_mut);
    _rep->connections.append(connection);    _rep->connections.append(connection);
    _rep->_connection_mut.unlock();  
 }  
   
 AsyncDQueue<pegasus_acceptor> pegasus_acceptor::acceptors(true, 0);  
   
 void pegasus_acceptor::close_all_acceptors(void)  
 {  
    try  
    {  
       pegasus_acceptor* temp = acceptors.remove_first();  
       while(temp)  
       {  
          delete temp;  
          temp = acceptors.remove_first();  
       }  
    }  
    catch(...)  
    {  
    }  
   
 }  
   
   
   
 pegasus_acceptor::pegasus_acceptor(monitor_2* monitor,  
                                    MessageQueue* outputMessageQueue,  
                                    Boolean localConnection,  
                                    Uint32 portNumber,  
                                    SSLContext* sslcontext)  
   : _monitor(monitor), _outputMessageQueue(outputMessageQueue),  
     _localConnection(localConnection), _portNumber(portNumber),  
     _sslcontext(sslcontext), connections(true, 0)  
 {  
   
      Socket::initializeInterface();  
      try {  
        acceptors.insert_first(this);  
      }  
      catch(...){  
      }  
   
 }  
   
 pegasus_acceptor::~pegasus_acceptor(void)  
 {  
    unbind();  
    Socket::uninitializeInterface();  
    try {  
      acceptors.remove(this);  
    }  
    catch(...){  
    }  
   
 }  
   
   
 void pegasus_acceptor::bind()  
 {  
   
   PEGASUS_SOCKLEN_SIZE addr_size;  
   struct sockaddr *addr;  
   struct sockaddr_in addr_in;  
 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  
   struct sockaddr_un addr_un;  
 #endif  
   
   memset(&addr_in, 0, sizeof(addr_in));  
   addr_in.sin_addr.s_addr = INADDR_ANY;  
   addr_in.sin_family = AF_INET;  
   addr_in.sin_port = htons(_portNumber);  
   addr = (struct sockaddr*) &addr_in;  
   addr_size = sizeof(addr_in);  
   
   // first step: determine which kind of socket factory to initialize,  
   // then create the socket and bind it to an address  
   if(_localConnection == true){  
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  
     unix_socket_factory sf;  
     pegasus_socket temp(&sf);  
     _listener = temp;  
   
     memset(&addr_un, 0, sizeof(addr_un));  
     addr_un.sun_family = AF_UNIX;  
     strcpy(addr_un.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);  
 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM  
     AtoE(addr_un.sun_path);  
 #endif  
     addr = (struct sockaddr*) &addr_un;  
     addr_size = sizeof(addr_un);  
     _listener.socket(AF_UNIX, SOCK_STREAM, 0);  
 #else  
     bsd_socket_factory sf;  
     pegasus_socket temp(&sf);  
     _listener = temp;  
     _listener.socket(AF_UNIX, SOCK_STREAM, 0);  
 #endif  
   }  
   else if( _sslcontext != 0 ) {  
 #ifdef PEGASUS_HAS_SSL  
     ssl_socket_factory sf;  
 #else  
     bsd_socket_factory sf;  
 #endif  
     pegasus_socket temp(&sf, _sslcontext);  
     _listener = temp;  
     _listener.socket(PF_INET, SOCK_STREAM, 0);  
   }  
   else {  
     bsd_socket_factory sf;  
     pegasus_socket temp(&sf);  
     _listener = temp;  
     _listener.socket(PF_INET, SOCK_STREAM, 0);  
   }  
   
   _listener.bind((struct sockaddr*)addr, addr_size);  
   
   // second step: listen on the socket  
   
   _listener.listen(5);  
   
   // third step: add this listening socket to the monitor  
   
    _monitor->tickle();  
    _monitor->add_entry(_listener, LISTEN, this, this);  
 }  
   
   
 /** Unbind from the given port.  
  */  
 void pegasus_acceptor::unbind()  
 {  
   // remove the socket from the monitor  
   _monitor->remove_entry((Sint32)_listener);  
   
   // close the socket  
   _listener.close();  
 }  
   
   
       /** Close the connection socket.  
        */  
 void pegasus_acceptor::closeConnectionSocket()  
 {  
   unbind();  
 }  
   
   
       /** Reopen the connection socket.  
        */  
 void pegasus_acceptor::reopenConnectionSocket()  
 {  
   bind();  
 }  
   
   
   /** Returns the number of outstanding requests  
    */  
 Uint32 pegasus_acceptor::getOutstandingRequestCount()  
 {  
   return _monitor->getOutstandingRequestCount();  
 }  
   
 Boolean pegasus_acceptor::operator ==(const pegasus_acceptor& pa)  
 {  
   if(this == &pa)  
     return true;  
   return false;  
 }  
   
 Boolean pegasus_acceptor::operator ==(void* pa)  
 {  
   if((void*)this == pa)  
     return true;  
   return false;  
 }  
   
   
 pegasus_acceptor* pegasus_acceptor::find_acceptor(Boolean local, Uint32 port)  
 {  
   pegasus_acceptor* temp = 0;  
   
   try {  
     acceptors.try_lock(pegasus_thread_self());  
     temp = acceptors.next(temp);  
     while(temp){  
       if( local == true ){  
         if(temp->_localConnection){  
           acceptors.unlock();  
           return temp;  
         }  
       }  
       if(temp->_localConnection == local && temp->_portNumber ==port){  
         acceptors.unlock();  
         return temp;  
       }  
       temp = acceptors.next(temp);  
     }  
     acceptors.unlock();  
   }  
   catch(...){  
   }  
   return temp;  
 }  
   
 class m2e_rep;  
   
 void pegasus_acceptor::accept_dispatch(monitor_2_entry *entry)  
 {  
   pegasus_acceptor* myself = (pegasus_acceptor*)entry->get_accept();  
   
   HTTPConnection2* connection = new HTTPConnection2(entry->_rep->psock, myself->_outputMessageQueue);  
   
   // set the entry's dispatch parameter to point to the connection object  
   entry->set_dispatch ((void*)connection);  
   
   monitor_2::insert_connection(connection);  
   
 } }
  
   
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.45.2.1  
changed lines
  Added in v.1.92

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2