(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.17 and 1.49.2.1

version 1.17, 2002/05/22 05:25:30 version 1.49.2.1, 2004/07/26 18:09:08
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%2003////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM,  // Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
 // 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.;
   // IBM Corp.; EMC 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 26 
Line 28 
 // Modified By: // Modified By:
 //         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com) //         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
 //         Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com) //         Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
   //         Dave Rosckes (rosckes@us.ibm.com)
   //         Denise Eckstein (denise.eckstein@hp.com)
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
Line 38 
Line 42 
 #include <windows.h> #include <windows.h>
 #else #else
 # include <cctype> # include <cctype>
 # include <unistd.h>  
 # include <cstdlib> # include <cstdlib>
 # include <errno.h> # include <errno.h>
 # include <fcntl.h> # include <fcntl.h>
Line 47 
Line 50 
 # include <arpa/inet.h> # include <arpa/inet.h>
 # include <sys/socket.h> # include <sys/socket.h>
 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
   # include <unistd.h>
 #  include <sys/un.h> #  include <sys/un.h>
 # endif # endif
 #endif #endif
Line 55 
Line 59 
 #include "TLS.h" #include "TLS.h"
 #include "HTTPAcceptor.h" #include "HTTPAcceptor.h"
 #include "HTTPConnection.h" #include "HTTPConnection.h"
   #include "Tracer.h"
   #include <Pegasus/Common/MessageLoader.h> //l10n
   
   #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
   #include "OS400ConvertChar.h"
   #endif
  
 PEGASUS_USING_STD; PEGASUS_USING_STD;
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
   static int MAX_CONNECTION_QUEUE_LENGTH = -1;
   
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // HTTPAcceptorRep // HTTPAcceptorRep
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
 struct HTTPAcceptorRep  class HTTPAcceptorRep
   {
   public:
       HTTPAcceptorRep(Boolean local)
       {
           if (local)
 { {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
       struct sockaddr_un address;              address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
               address_size = sizeof(struct sockaddr_un);
   #else
               PEGASUS_ASSERT(false);
   #endif
           }
           else
           {
               address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
               address_size = sizeof(struct sockaddr_in);
           }
       }
   
       struct sockaddr* address;
   
   #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
      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 #else
       struct sockaddr_in address;     int address_size;
 #endif #endif
         Mutex _connection_mut;
   
       Sint32 socket;       Sint32 socket;
       Array<HTTPConnection*> connections;       Array<HTTPConnection*> connections;
 }; };
Line 83 
Line 121 
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
 HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueueService* outputMessageQueue)  HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
    : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),                             MessageQueue* outputMessageQueue,
      _monitor(monitor), _outputMessageQueue(outputMessageQueue),                             Boolean localConnection,
      _rep(0), _sslcontext(NULL)                             Uint32 portNumber,
                              SSLContext * sslcontext,
                              Boolean exportConnection)
      : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
        _monitor(monitor),
        _outputMessageQueue(outputMessageQueue),
        _rep(0),
        _entry_index(-1),
        _localConnection(localConnection),
        _portNumber(portNumber),
        _sslcontext(sslcontext),
        _exportConnection(exportConnection)
 { {
   
    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(Monitor* monitor, MessageQueueService* outputMessageQueue,  
                            SSLContext * sslcontext)  
    :       Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  
            _monitor(monitor), _outputMessageQueue(outputMessageQueue),  
            _rep(0),  
            _sslcontext(sslcontext)  
 {  
    Socket::initializeInterface();  
 } }
  
 HTTPAcceptor::~HTTPAcceptor() HTTPAcceptor::~HTTPAcceptor()
 { {
    unbind();    unbind();
      // ATTN: Is this correct in a multi-HTTPAcceptor server?
    Socket::uninitializeInterface();    Socket::uninitializeInterface();
 } }
  
Line 129 
Line 203 
          else          else
          {          {
             // ATTN! this can't happen!             // ATTN! this can't happen!
               Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                 "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");
          }          }
  
          break;          break;
Line 139 
Line 215 
          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];
Line 148 
Line 226 
             {             {
                _monitor->unsolicitSocketMessages(socket);                _monitor->unsolicitSocketMessages(socket);
                _rep->connections.remove(i);                _rep->connections.remove(i);
                while (connection->refcount.value()) { }  
                delete connection;                delete connection;
                break;                break;
             }             }
          }          }
            _rep->_connection_mut.unlock();
            break;
       }       }
  
       default:       default:
       // ATTN: need unexpected message error!       // ATTN: need unexpected message error!
         Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
              "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
       break;       break;
    };    };
  
Line 169 
Line 250 
    Message* message = dequeue();    Message* message = dequeue();
  
    if (!message)    if (!message)
      {
         Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
              "HTTPAcceptor::handleEnqueue(): No message on queue.");
       return;       return;
      }
  
    handleEnqueue(message);    handleEnqueue(message);
  
 } }
  
 void HTTPAcceptor::bind(Uint32 portNumber)  void HTTPAcceptor::bind()
 { {
    if (_rep)     if (_rep){
       throw BindFailed("HTTPAcceptor already bound");          //l10n
         //throw BindFailedException("HTTPAcceptor already bound");
  
    _rep = new HTTPAcceptorRep;        MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
                                  "HTTPAcceptor already bound");
  
    _portNumber = portNumber;        Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
              "HTTPAcceptor::bind: HTTPAcceptor already bound.");
         throw BindFailedException(parms);
      }
   
      _rep = new HTTPAcceptorRep(_localConnection);
  
    // bind address    // bind address
    _bind();    _bind();
Line 200 
Line 292 
  
    // Create address:    // Create address:
  
    memset(&_rep->address, 0, sizeof(_rep->address));     memset(_rep->address, 0, sizeof(*_rep->address));
  
      if (_localConnection)
      {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
    _rep->address.sun_family = AF_UNIX;         reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
    strcpy(_rep->address.sun_path, "/var/opt/wbem/cimxml.socket");             AF_UNIX;
    ::unlink(_rep->address.sun_path);         strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_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
    _rep->address.sin_addr.s_addr = INADDR_ANY;         PEGASUS_ASSERT(false);
    _rep->address.sin_family = AF_INET;  
    _rep->address.sin_port = htons(_portNumber);  
 #endif #endif
      }
      else
      {
          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);
      }
  
    // Create socket:    // Create socket:
  
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET     if (_localConnection)
      {
    _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);    _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
 #else     }
      else
      {
    _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);    _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 #endif     }
  
    if (_rep->socket < 0)    if (_rep->socket < 0)
    {    {
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
       throw BindFailed("Failed to create socket");        //l10n
         //throw BindFailedException("Failed to create socket");
         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
                                  "Failed to create socket");
         Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
              "HTTPAcceptor::_bind _rep->socket < 0");
         throw BindFailedException(parms);
    }    }
  
   
   // set the close-on-exec bit for this file handle.
   // any unix that forks needs this bit set.
   #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
      int sock_flags;
    if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
      {
          PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                     "HTTPAcceptor::_bind: fcntl(F_GETFD) failed");
      }
      else
      {
         sock_flags |= FD_CLOEXEC;
         if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
         {
          PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                     "HTTPAcceptor::_bind: 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
Line 237 
Line 375 
    if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,    if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
                   (char *)&opt, sizeof(opt)) < 0)                   (char *)&opt, sizeof(opt)) < 0)
    {    {
         Socket::close(_rep->socket);
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
       throw BindFailed("Failed to set socket option");        //l10n
         //throw BindFailedException("Failed to set socket option");
         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
                                  "Failed to set socket option");
         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                      "HTTPAcceptor::_bind: Failed to set socket option.");
         throw BindFailedException(parms);
    }    }
  
    // Bind socket to port:    // Bind socket to port:
  
    if (::bind(_rep->socket,     if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
               reinterpret_cast<struct sockaddr*>(&_rep->address),  
               sizeof(_rep->address)) < 0)  
    {    {
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
       throw BindFailed("Failed to bind socket");        //l10n
         //throw BindFailedException("Failed to bind socket");
         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
                                  "Failed to bind socket");
         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                           "HTTPAcceptor::_bind: Failed to bind socket.");
         throw BindFailedException(parms);
    }    }
  
    // Set up listening on the given socket:    // Set up listening on the given socket:
  
    int const MAX_CONNECTION_QUEUE_LENGTH = 5;     //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;
       throw BindFailed("Failed to bind socket");        //l10n
         //throw BindFailedException("Failed to bind socket");
         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
                                  "Failed to bind socket");
         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                     "HTTPAcceptor::_bind: Failed to bind socket(1).");
         throw BindFailedException(parms);
    }    }
  
    // 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");        //l10n
         //throw BindFailedException("Failed to solicit socket messaeges");
         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
                                  "Failed to solicit socket messaeges");
         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                     "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
         throw BindFailedException(parms);
    }    }
 } }
  
Line 290 
Line 451 
    if (_rep)    if (_rep)
    {    {
       // unregister the socket       // unregister the socket
       _monitor->unsolicitSocketMessages(_rep->socket);  
         // ATTN - comment out - see CIMServer::stopClientConnection()
         //_monitor->unsolicitSocketMessages(_rep->socket);
  
       // close the socket       // close the socket
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
    }    }
      else
      {
         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                           "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
      }
 } }
  
 /** /**
Line 306 
Line 474 
    {    {
       _bind();       _bind();
    }    }
      else
      {
         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                           "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
      }
 } }
  
 /** /**
Line 313 
Line 486 
 */ */
 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()
Line 329 
Line 503 
    if (_rep)    if (_rep)
    {    {
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
   
         if (_localConnection)
         {
   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
            ::unlink(
                reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
   #else
            PEGASUS_ASSERT(false);
   #endif
         }
   
       delete _rep;       delete _rep;
       _rep = 0;       _rep = 0;
    }    }
      else
      {
         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                 "HTTPAcceptor::unbind failure _rep is null." );
      }
 } }
  
 void HTTPAcceptor::destroyConnections() void HTTPAcceptor::destroyConnections()
 { {
   
   
    // 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];
Line 354 
Line 547 
    }    }
  
    _rep->connections.clear();    _rep->connections.clear();
      _rep->_connection_mut.unlock();
 } }
  
 void HTTPAcceptor::_acceptConnection() void HTTPAcceptor::_acceptConnection()
Line 367 
Line 561 
  
    // Accept the connection (populate the address):    // Accept the connection (populate the address):
  
    sockaddr_in address;     struct sockaddr* accept_address;
   #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX)     size_t address_size;
    size_t n = sizeof(address);  #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 #else
    int n = sizeof(address);     int address_size;
 #endif #endif
  
 #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)     if (_localConnection)
    Sint32 socket = accept(     {
       _rep->socket, (struct sockaddr*)&address, (socklen_t *)&n);  #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
          accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
          address_size = sizeof(struct sockaddr_un);
 #else #else
    Sint32 socket = accept(_rep->socket, reinterpret_cast<struct sockaddr*>(&address), &n);         PEGASUS_ASSERT(false);
 #endif #endif
      }
      else
      {
          accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
          address_size = sizeof(struct sockaddr_in);
      }
   
      Sint32 socket = accept(_rep->socket, accept_address, &address_size);
   
      delete accept_address;
  
    if (socket < 0)    if (socket < 0)
    {    {
       if (getenv("PEGASUS_TRACE"))  
          cerr <<"HTTPAcceptor: accept() failed" << endl;  
  
          Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
                      "HTTPAcceptor - accept() failure.  errno: $0"
                      ,errno);
   
          PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                           "HTTPAcceptor: accept() failed");
       return;       return;
    }    }
  
    // Create a new conection and add it to the connection list:  // set the close on exec flag
   #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
      int sock_flags;
    if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
      {
          PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                           "HTTPAcceptor: fcntl(F_GETFD) failed");
      }
      else
      {
         sock_flags |= FD_CLOEXEC;
         if (fcntl(socket, F_SETFD, sock_flags) < 0)
         {
          PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                           "HTTPAcceptor: fcntl(F_SETFD) failed");
         }
      }
   #endif
  
    MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);  
    if (mp_socket->accept() < 0) {  
       if (getenv("PEGASUS_TRACE"))  
          cerr <<"HTTPAcceptor: SSL_accept() failed" << endl;  
  
      Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
                  "HTTPAcceptor - accept() success.  Socket: $1"
                  ,socket);
   
      // Create a new conection and add it to the connection list:
   
      AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, _sslcontext, _exportConnection));
      if (mp_socket->accept() < 0)
      {
          PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                           "HTTPAcceptor: SSL_accept() failed");
       return;       return;
    }    }
  
    HTTPConnection* connection = new HTTPConnection(     HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
       _monitor, mp_socket, this, static_cast<MessageQueue *>(_outputMessageQueue));         this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
  
    // Solicit events on this new connection's socket:    // Solicit events on this new connection's socket:
      int index;
  
    if (!_monitor->solicitSocketMessages(     if (-1 ==  (index = _monitor->solicitSocketMessages(
           socket,           socket,
           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
         // an error message to Client application.
         Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
             "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
       delete connection;       delete connection;
       Socket::close(socket);       Socket::close(socket);
         return;
    }    }
  
    // Save the socket for cleanup later:     mp_socket.release();
  
      // 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();
   }
   
   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;
       pegasus_socket temp(&sf, _sslcontext);
   #else
       bsd_socket_factory sf;
       pegasus_socket temp(&sf);
   #endif
       _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.17  
changed lines
  Added in v.1.49.2.1

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2