(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.1.2.8 and 1.30

version 1.1.2.8, 2001/09/13 17:30:08 version 1.30, 2003/07/31 14:28:28
Line 1 
Line 1 
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
 // //
 // 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
Line 24 
Line 24 
 // Author: Mike Brasher (mbrasher@bmc.com) // Author: Mike Brasher (mbrasher@bmc.com)
 // //
 // Modified By: // 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)
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include <iostream>  
 #include "Config.h" #include "Config.h"
   #include "Constants.h"
   #include <iostream>
 #include "Socket.h" #include "Socket.h"
  
 #ifdef PEGASUS_OS_TYPE_WINDOWS  #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC
 # include <winsock.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 43 
Line 46 
 # include <netinet/in.h> # include <netinet/in.h>
 # include <arpa/inet.h> # include <arpa/inet.h>
 # include <sys/socket.h> # include <sys/socket.h>
   # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
   # include <unistd.h>
   #  include <sys/un.h>
   # endif
 #endif #endif
  
 #include "Socket.h" #include "Socket.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
  
 PEGASUS_USING_STD; PEGASUS_USING_STD;
  
Line 59 
Line 69 
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
 struct HTTPAcceptorRep  class HTTPAcceptorRep
   {
   public:
       HTTPAcceptorRep(Boolean local)
       {
           if (local)
           {
   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
               address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
               address_size = sizeof(struct sockaddr_un);
   #else
               PEGASUS_ASSERT(false);
   #endif
           }
           else
 { {
     struct sockaddr_in address;              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)
      socklen_t address_size;
   #else
      int address_size;
   #endif
         Mutex _connection_mut;
   
     Sint32 socket;     Sint32 socket;
     Array<HTTPConnection*> connections;     Array<HTTPConnection*> connections;
 }; };
Line 72 
Line 111 
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
 HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue)  HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
     : _monitor(monitor), _outputMessageQueue(outputMessageQueue), _rep(0)                             MessageQueue* outputMessageQueue,
                              Boolean localConnection,
                              Uint32 portNumber,
                              SSLContext * sslcontext)
      : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
        _monitor(monitor),
        _outputMessageQueue(outputMessageQueue),
        _rep(0),
        _entry_index(-1),
        _localConnection(localConnection),
        _portNumber(portNumber),
        _sslcontext(sslcontext)
 { {
     Socket::initializeInterface();     Socket::initializeInterface();
 } }
Line 81 
Line 131 
 HTTPAcceptor::~HTTPAcceptor() HTTPAcceptor::~HTTPAcceptor()
 { {
     unbind();     unbind();
      // ATTN: Is this correct in a multi-HTTPAcceptor server?
     Socket::uninitializeInterface();     Socket::uninitializeInterface();
 } }
  
 void HTTPAcceptor::handleEnqueue()  void HTTPAcceptor::handleEnqueue(Message *message)
 { {
     // cout << "HTTPAcceptor::handleEnqueue()" << endl;  
   
     Message* message = dequeue();  
   
     if (!message)     if (!message)
         return;         return;
  
Line 119 
Line 166 
             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 132 
Line 181 
                     break;                     break;
                 }                 }
             }             }
            _rep->_connection_mut.unlock();
         }         }
  
         default:         default:
Line 142 
Line 192 
     delete message;     delete message;
 } }
  
 const char* HTTPAcceptor::getQueueName() const  
   void HTTPAcceptor::handleEnqueue()
 { {
     return "HTTPAcceptor";     Message* message = dequeue();
   
      if (!message)
         return;
   
      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");
         String s0 = "HTTPAcceptor";
         MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
                                                      "$0 already bound",
                                                      s0);
         throw BindFailedException(parms);
      }
   
      _rep = new HTTPAcceptorRep(_localConnection);
   
      // bind address
      _bind();
   
      return;
   }
  
     _rep = new HTTPAcceptorRep;  /**
      _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
      a domain socket is bound.
   */
   void HTTPAcceptor::_bind()
   {
  
     // Create address:     // Create address:
  
     memset(&_rep->address, 0, sizeof(_rep->address));     memset(_rep->address, 0, sizeof(*_rep->address));
     _rep->address.sin_addr.s_addr = INADDR_ANY;  
     _rep->address.sin_family = AF_INET;     if (_localConnection)
     _rep->address.sin_port = htons(portNumber);     {
   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
          reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
              AF_UNIX;
          strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
                 PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
          ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
   #else
          PEGASUS_ASSERT(false);
   #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:
  
      if (_localConnection)
      {
          _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
      }
      else
      {
     _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);     _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
      }
  
     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");
         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_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
      // that we can rebind to a new socket using the same address when we
      // need to resume the cimom as a result of a timeout during a Shutdown
      // operation.
      //
      int opt=1;
      if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
                     (char *)&opt, sizeof(opt)) < 0)
      {
         Socket::close(_rep->socket);
         delete _rep;
         _rep = 0;
         //l10n
         //throw BindFailedException("Failed to set socket option");
         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
                                                      "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)
         (struct sockaddr*)(void*)&_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 to port");        //l10n
         //throw BindFailedException("Failed to bind socket");
         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
                                                      "Failed to bind socket");
         throw BindFailedException(parms);
     }     }
  
     // Set up listening on the given port:     // Set up listening on the given socket:
  
     int const MAX_CONNECTION_QUEUE_LENGTH = 5;     int const MAX_CONNECTION_QUEUE_LENGTH = 5;
  
Line 193 
Line 345 
         Socket::close(_rep->socket);         Socket::close(_rep->socket);
         delete _rep;         delete _rep;
         _rep = 0;         _rep = 0;
         throw BindFailed("Failed to bind socket to port");        //l10n
         //throw BindFailedException("Failed to bind socket");
         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
                                                      "Failed to bind socket");
         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)))
     {     {
         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");
         throw BindFailedException(parms);
     }     }
 } }
  
   /**
      closeConnectionSocket - close the server listening socket to disallow
      new client connections.
   */
   void HTTPAcceptor::closeConnectionSocket()
   {
      if (_rep)
      {
         // unregister the socket
         _monitor->unsolicitSocketMessages(_rep->socket);
   
         // close the socket
         Socket::close(_rep->socket);
      }
   }
   
   /**
      reopenConnectionSocket - creates a new server socket.
   */
   void HTTPAcceptor::reopenConnectionSocket()
   {
      if (_rep)
      {
         _bind();
      }
   }
   
   /**
      getOutstandingRequestCount - returns the number of outstanding requests.
   */
   Uint32 HTTPAcceptor::getOutstandingRequestCount()
   {
      Uint32 count = 0;
   
      _rep->_connection_mut.lock(pegasus_thread_self());
      if (_rep->connections.size() > 0)
      {
         HTTPConnection* connection = _rep->connections[0];
         count = connection->getRequestCount();
      }
      _rep->_connection_mut.unlock();
      return count;
   }
   
 void HTTPAcceptor::unbind() void HTTPAcceptor::unbind()
 { {
     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;
     }     }
Line 222 
Line 438 
  
 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 235 
Line 454 
  
         // Destroy the connection (causing it to close):         // Destroy the connection (causing it to close):
  
         while (connection->refcount.value()) { }
         delete connection;         delete connection;
     }     }
  
     _rep->connections.clear();     _rep->connections.clear();
      _rep->_connection_mut.unlock();
 } }
  
 void HTTPAcceptor::_acceptConnection() void HTTPAcceptor::_acceptConnection()
Line 252 
Line 473 
  
     // 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)
     size_t n = sizeof(address);     size_t address_size;
   #elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
      socklen_t address_size;
 #else #else
     int n = sizeof(address);     int address_size;
 #endif #endif
  
 #if defined(PEGASUS_PLATFORM_LINUX_IX86_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, (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"))         Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
             cerr <<"HTTPAcceptor: accept() failed" << endl;                     "HTTPAcceptor - accept() failure.  errno: $0"
                      ,errno);
  
          PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
                           "HTTPAcceptor: accept() failed");
         return;         return;
     }     }
  
   // 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_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
   
   
      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:     // Create a new conection and add it to the connection list:
  
      MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);
      if (mp_socket->accept() < 0)
      {
          PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
                           "HTTPAcceptor: SSL_accept() failed");
         return;
      }
   
     HTTPConnection* connection = new HTTPConnection(     HTTPConnection* connection = new HTTPConnection(
         _monitor, socket, this, _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 (-1 ==  (index = _monitor->solicitSocketMessages(
         socket,         socket,
         SocketMessage::READ | SocketMessage::EXCEPTION,         SocketMessage::READ | SocketMessage::EXCEPTION,
         connection->getQueueId()))            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_NAMESPACE_END PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.1.2.8  
changed lines
  Added in v.1.30

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2