(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.5 and 1.109

version 1.5, 2002/02/11 01:17:41 version 1.109, 2007/12/18 18:50:45
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // 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.
   // 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 21 
Line 29 
 // //
 //============================================================================== //==============================================================================
 // //
 // Author: Mike Brasher (mbrasher@bmc.com)  
 //  
 // Modified By:  
 //         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)  
 //  
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include "Config.h" #include "Config.h"
   #include "Constants.h"
 #include <iostream> #include <iostream>
 #include "Socket.h"  
   
 #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC  
 # include <winsock.h>  
 #else  
 # include <cctype>  
 # include <unistd.h>  
 # include <cstdlib>  
 # include <errno.h>  
 # include <fcntl.h>  
 # include <netdb.h>  
 # include <netinet/in.h>  
 # include <arpa/inet.h>  
 # include <sys/socket.h>  
 #endif  
  
   #include "Network.h"
 #include "Socket.h" #include "Socket.h"
 #include "TLS.h" #include "TLS.h"
 #include "HTTPAcceptor.h" #include "HTTPAcceptor.h"
 #include "HTTPConnection.h" #include "HTTPConnection.h"
   #include "HostAddress.h"
   #include "Tracer.h"
   #include <Pegasus/Common/MessageLoader.h>
   
   #ifdef PEGASUS_OS_PASE
   # include <as400_protos.h>
   # include <Pegasus/Common/PaseCcsid.h>
   #endif
  
 PEGASUS_USING_STD; PEGASUS_USING_STD;
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
   
   static int _maxConnectionQueueLength = -1;
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // HTTPAcceptorRep // HTTPAcceptorRep
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
 struct HTTPAcceptorRep  class HTTPAcceptorRep
   {
   public:
       HTTPAcceptorRep(Uint16 connectionType)
       {
           if (connectionType == HTTPAcceptor::LOCAL_CONNECTION)
           {
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
               address =
                   reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
               address_size = sizeof(struct sockaddr_un);
   #else
               PEGASUS_ASSERT(false);
   #endif
           }
   #ifdef PEGASUS_ENABLE_IPV6
           else if (connectionType == HTTPAcceptor::IPV6_CONNECTION)
 { {
     struct sockaddr_in address;              address =
     Sint32 socket;                  reinterpret_cast<struct sockaddr*>(new struct sockaddr_in6);
               address_size = sizeof(struct sockaddr_in6);
           }
   #endif
           else if (connectionType == HTTPAcceptor::IPV4_CONNECTION)
           {
               address =
                   reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
               address_size = sizeof(struct sockaddr_in);
           }
           else
           {
               PEGASUS_ASSERT(false);
       }
       }
   
       ~HTTPAcceptorRep()
       {
           delete address;
       }
       struct sockaddr* address;
   
       SocketLength address_size;
       Mutex _connection_mut;
   
       SocketHandle socket;
     Array<HTTPConnection*> connections;     Array<HTTPConnection*> connections;
 }; };
  
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // HTTPAcceptor // HTTPAcceptor
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
 HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue)  HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
     : Base("HTTPAcceptor", MessageQueue::getNextQueueId()),                             MessageQueue* outputMessageQueue,
       _monitor(monitor), _outputMessageQueue(outputMessageQueue),                             Uint16 connectionType,
       _rep(0), _sslcontext(NULL)                             Uint32 portNumber,
                              SSLContext * sslcontext,
                              ReadWriteSem* sslContextObjectLock)
      : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
        _monitor(monitor),
        _outputMessageQueue(outputMessageQueue),
        _rep(0),
        _entry_index(-1),
        _connectionType(connectionType),
        _portNumber(portNumber),
        _sslcontext(sslcontext),
        _sslContextObjectLock(sslContextObjectLock),
        _idleConnectionTimeoutSeconds(0)
 { {
   
     Socket::initializeInterface();     Socket::initializeInterface();
 }  
  
 HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue,     /*
                            SSLContext * sslcontext)          Platforms interpret the value of _maxConnectionQueueLength
    :       Base("HTTPAcceptor", MessageQueue::getNextQueueId()),          differently.  Some platforms interpret the value literally, while
            _monitor(monitor), _outputMessageQueue(outputMessageQueue), _rep(0),          others multiply a fudge factor. When the server is under stress from
            _sslcontext(sslcontext)          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
           _maxConnectionQueueLength = 15.
      */
   
   //To engage runtime backlog queue length: uncomment the following block AND
   //comment out the line _maxConnectionQueueLength = 15
   
   /*
       if (_maxConnectionQueueLength == -1)
 { {
     Socket::initializeInterface();          const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
           if (!env)
           {
               _maxConnectionQueueLength = 15;
           }
           else
           {
               char* end = NULL;
               _maxConnectionQueueLength = strtol(env, &end, 10);
               if (*end)
                   _maxConnectionQueueLength = 15;
               cout << " _maxConnectionQueueLength = " <<
                   _maxConnectionQueueLength << endl;
           }
       }
   */
   #ifdef PEGASUS_WMIMAPPER
       //The WMI Mapper can be used as a proxy to multiple WMI Servers.
       //If a client application simultaneously initiates connections
       //to many Windows systems, many of these connections may be routed
       //to a single WMI Mapper. A larger _maxConnectionQueueLength
       //value is required to allow these connections to be initiated
       //successfully.
       _maxConnectionQueueLength = 40;
   #else
       _maxConnectionQueueLength = 15;
   #endif
 } }
  
 HTTPAcceptor::~HTTPAcceptor() HTTPAcceptor::~HTTPAcceptor()
 { {
       destroyConnections();
     unbind();     unbind();
       // ATTN: Is this correct in a multi-HTTPAcceptor server?
     Socket::uninitializeInterface();     Socket::uninitializeInterface();
 } }
  
 void HTTPAcceptor::handleEnqueue()  void HTTPAcceptor::handleEnqueue(Message *message)
 { {
     Message* message = dequeue();  
   
     if (!message)     if (!message)
         return;         return;
  
       PEGASUS_ASSERT(_rep != 0);
     switch (message->getType())     switch (message->getType())
     {     {
         case SOCKET_MESSAGE:         case SOCKET_MESSAGE:
Line 114 
Line 206 
             // 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();
             }             }
             else             else
             {             {
                 // ATTN! this can't happen!                 // ATTN! this can't happen!
                   PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                       "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE "
                           "received.");
             }             }
  
             break;             break;
Line 128 
Line 223 
  
         case CLOSE_CONNECTION_MESSAGE:         case CLOSE_CONNECTION_MESSAGE:
         {         {
             CloseConnectionMessage* closeConnectionMessage             CloseConnectionMessage* closeConnectionMessage =
                 = (CloseConnectionMessage*)message;                 (CloseConnectionMessage*)message;
   
              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 144 
Line 241 
                     break;                     break;
                 }                 }
             }             }
   
              break;
         }         }
  
         default:         default:
             // ATTN: need unexpected message error!             // ATTN: need unexpected message error!
              PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                  "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
             break;             break;
     };      }
  
     delete message;     delete message;
 } }
  
 const char* HTTPAcceptor::getQueueName() const  
   void HTTPAcceptor::handleEnqueue()
 { {
     return "HTTPAcceptor";      Message* message = dequeue();
   
       if (!message)
       {
           PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::handleEnqueue(): No message on queue.");
           return;
 } }
  
 void HTTPAcceptor::bind(Uint32 portNumber)      handleEnqueue(message);
   }
   
   void HTTPAcceptor::bind()
 { {
     if (_rep)     if (_rep)
         throw BindFailed("HTTPAcceptor already bound");      {
           MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
               "HTTPAcceptor already bound");
  
     _rep = new HTTPAcceptorRep;          PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::bind: HTTPAcceptor already bound.");
           throw BindFailedException(parms);
       }
  
     _portNumber = portNumber;      _rep = new HTTPAcceptorRep(_connectionType);
  
     // 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_DISABLE_LOCAL_DOMAIN_SOCKET is not defined, the port number is
       ignored and a domain socket is bound.
 */ */
 void HTTPAcceptor::_bind() void HTTPAcceptor::_bind()
 { {
   #ifdef PEGASUS_OS_PASE
       // bind need ccsid is 819
       int orig_ccsid;
       orig_ccsid = _SETCCSID(-1);
       if (orig_ccsid == -1)
       {
           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               String("HTTPAcceptor::_bind: Can not get current PASE CCSID."));
           orig_ccsid = 1208;
       }
       PaseCcsid ccsid(819, orig_ccsid);
   #endif
  
       PEGASUS_ASSERT(_rep != 0);
     // Create address:     // Create address:
       memset(_rep->address, 0, _rep->address_size);
  
     memset(&_rep->address, 0, sizeof(_rep->address));      if (_connectionType == LOCAL_CONNECTION)
     _rep->address.sin_addr.s_addr = INADDR_ANY;      {
     _rep->address.sin_family = AF_INET;  #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
     _rep->address.sin_port = htons(_portNumber);          //
           // Make sure the local domain socket can be owned by the cimserver
           // user.  Otherwise, the bind may fail with a vague "bind failed"
           // error.
           //
           if (System::exists(PEGASUS_LOCAL_DOMAIN_SOCKET_PATH))
           {
               if (!System::removeFile(PEGASUS_LOCAL_DOMAIN_SOCKET_PATH))
               {
                   throw CannotRemoveFile(PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
               }
           }
   
           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);
   #else
           PEGASUS_ASSERT(false);
   #endif
       }
   #ifdef PEGASUS_ENABLE_IPV6
       else if (_connectionType == IPV6_CONNECTION)
       {
           reinterpret_cast<struct sockaddr_in6*>(_rep->address)->sin6_addr =
               in6addr_any;
           reinterpret_cast<struct sockaddr_in6*>(_rep->address)->sin6_family =
               AF_INET6;
           reinterpret_cast<struct sockaddr_in6*>(_rep->address)->sin6_port =
               htons(_portNumber);
       }
   #endif
       else if(_connectionType == IPV4_CONNECTION)
       {
           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);
       }
       else
       {
           PEGASUS_ASSERT(false);
       }
  
     // Create socket:     // Create socket:
  
     _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);      if (_connectionType == LOCAL_CONNECTION)
       {
           _rep->socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
       }
   #ifdef PEGASUS_ENABLE_IPV6
       else if (_connectionType == IPV6_CONNECTION)
       {
           _rep->socket = Socket::createSocket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
       }
   #endif
       else if (_connectionType == IPV4_CONNECTION)
       {
           _rep->socket = Socket::createSocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
       }
       else
       {
           PEGASUS_ASSERT(false);
       }
  
     if (_rep->socket < 0)     if (_rep->socket < 0)
     {     {
         delete _rep;         delete _rep;
         _rep = 0;         _rep = 0;
         throw BindFailed("Failed to create socket");          MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
               "Failed to create socket");
           PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::_bind _rep->socket < 0");
           throw BindFailedException(parms);
       }
   
       Socket::disableBlocking(_rep->socket);
   
   // set the close-on-exec bit for this file handle.
   // any unix that forks needs this bit set.
   #if !defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_OS_VMS)
       int sock_flags;
       if ((sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
       {
           PEG_TRACE_CSTRING(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_CSTRING(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
Line 208 
Line 426 
     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");          MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
               "Failed to set socket option");
           PEG_TRACE_CSTRING(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, _rep->address, _rep->address_size) < 0)
       {
           Socket::close(_rep->socket);
           delete _rep;
           _rep = 0;
           MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
               "Failed to bind socket");
           PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::_bind: Failed to bind socket.");
           throw BindFailedException(parms);
       }
   
  
     if (::bind(_rep->socket,      //
         (struct sockaddr*)(void*)&_rep->address,      // Get the actual port value used if the caller specified a port value of 0.
         sizeof(_rep->address)) < 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 (_connectionType == LOCAL_CONNECTION)
       {
           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);         Socket::close(_rep->socket);
         delete _rep;         delete _rep;
         _rep = 0;         _rep = 0;
         throw BindFailed("Failed to bind socket to port");              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
                   "Failed to bind socket");
               PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                   "HTTPAcceptor::_bind: Failed to set domain socket "
                       "permissions.");
               throw BindFailedException(parms);
     }     }
       }
   #endif
  
     // Set up listening on the given port:      // Set up listening on the given socket:
  
     int const MAX_CONNECTION_QUEUE_LENGTH = 5;      //int const _maxConnectionQueueLength = 15;
  
     if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)      if (listen(_rep->socket, _maxConnectionQueueLength) < 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");          MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
               "Failed to bind socket");
           PEG_TRACE_CSTRING(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(),
               MonitorEntry::TYPE_ACCEPTOR)))
     {     {
         Socket::close(_rep->socket);         Socket::close(_rep->socket);
         delete _rep;         delete _rep;
         _rep = 0;         _rep = 0;
         throw BindFailed("Failed to solicit socket messaeges");          MessageLoaderParms parms(
               "Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
               "Failed to solicit socket messaeges");
           PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
           throw BindFailedException(parms);
     }     }
 } }
  
Line 260 
Line 540 
     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);
           // Unlink Local Domain Socket Bug# 3312
           if (_connectionType == LOCAL_CONNECTION)
           {
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
               PEG_TRACE_CSTRING(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
       {
           PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::closeConnectionSocket failure _rep is null.");
     }     }
 } }
  
Line 276 
Line 576 
     {     {
         _bind();         _bind();
     }     }
       else
       {
           PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::reopenConnectionSocket failure _rep is null.");
       }
   }
   
   
   /**
      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 (_connectionType == LOCAL_CONNECTION)
           {
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
               PEG_TRACE_CSTRING(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_CSTRING(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;
       if (_rep)
 { {
           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];
         return(connection->getRequestCount());              count = connection->getRequestCount();
     }     }
     else      }
       return count;
   }
   
   
   /**
       getPortNumber - returns the port number used for the connection
   */
   Uint32 HTTPAcceptor::getPortNumber() const
     {     {
         return(0);      return _portNumber;
     }     }
   
   void HTTPAcceptor::setSocketWriteTimeout(Uint32 socketWriteTimeout)
   {
       _socketWriteTimeout = socketWriteTimeout;
   }
   
   void HTTPAcceptor::setIdleConnectionTimeout(Uint32 idleConnectionTimeoutSeconds)
   {
       _idleConnectionTimeoutSeconds = idleConnectionTimeoutSeconds;
 } }
  
 void HTTPAcceptor::unbind() void HTTPAcceptor::unbind()
 { {
     if (_rep)     if (_rep)
     {     {
           _portNumber = 0;
         Socket::close(_rep->socket);         Socket::close(_rep->socket);
   
           if (_connectionType == LOCAL_CONNECTION)
           {
   #ifndef PEGASUS_DISABLE_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_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor::unbind failure _rep is null." );
       }
 } }
  
 void HTTPAcceptor::destroyConnections() void HTTPAcceptor::destroyConnections()
 { {
       if (_rep)
       {
     // For each connection created by this object:     // For each connection created by this object:
  
           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 319 
Line 700 
  
         // Destroy the connection (causing it to close):         // Destroy the connection (causing it to close):
  
               while (connection->refcount.get()) { }
         delete connection;         delete connection;
     }     }
  
     _rep->connections.clear();     _rep->connections.clear();
 } }
   }
  
 void HTTPAcceptor::_acceptConnection() void HTTPAcceptor::_acceptConnection()
 { {
Line 331 
Line 714 
  
     PEGASUS_ASSERT(_rep != 0);     PEGASUS_ASSERT(_rep != 0);
  
     if (!_rep)  
         return;  
   
     // Accept the connection (populate the address):     // Accept the connection (populate the address):
  
     sockaddr_in address;      struct sockaddr* accept_address;
       SocketLength address_size;
  
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX)      if (_connectionType == LOCAL_CONNECTION)
     size_t n = sizeof(address);      {
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
           accept_address =
               reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
           address_size = sizeof(struct sockaddr_un);
 #else #else
     int n = sizeof(address);          PEGASUS_ASSERT(false);
 #endif #endif
       }
 #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU)      else
     Sint32 socket = accept(      {
         _rep->socket, (struct sockaddr*)&address, (socklen_t *)&n);  #ifdef PEGASUS_ENABLE_IPV6
           accept_address =
              reinterpret_cast<struct sockaddr*>
              (new struct sockaddr_storage);
           address_size = sizeof(struct sockaddr_storage);
 #else #else
     Sint32 socket = accept(_rep->socket, (struct sockaddr*)&address, &n);          accept_address =
               reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
           address_size = sizeof(struct sockaddr_in);
 #endif #endif
       }
   
       // It is not necessary to handle EINTR errors from this accept() call.
       // An EINTR error should not occur on a non-blocking socket.  If the
       // listen socket is blocking and EINTR occurs, the new socket connection
       // is not accepted here.
  
     if (socket < 0)      // EAGAIN errors are also not handled here.  An EAGAIN error should not
       // occur after select() indicates that the listen socket is available for
       // reading.  If the accept() fails with an EAGAIN error code, a new
       // connection is not accepted here.
   
       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;
   
           // TCPIP is down reconnect this acceptor
           if (getSocketError() == PEGASUS_NETWORK_TCPIP_STOPPED)
     {     {
         if (getenv("PEGASUS_TRACE"))              PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
             cerr <<"HTTPAcceptor: accept() failed" << endl;                  "Socket has an IO error. TCP/IP down. Try to reconnect.");
   
               reconnectConnectionSocket();
   
               return;
           }
  
           Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
               "HTTPAcceptor - accept() failure.  errno: $0", errno);
   
           PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "HTTPAcceptor: accept() failed");
           return;
       }
   
       String ipAddress;
   
       if (_connectionType == LOCAL_CONNECTION)
       {
           ipAddress = "localhost";
       }
       else
       {
   #ifdef PEGASUS_ENABLE_IPV6
           char ipBuffer[PEGASUS_INET6_ADDRSTR_LEN];
           int rc;
           if ((rc = System::getNameInfo(accept_address,
                   address_size,
                   ipBuffer,
                   PEGASUS_INET6_ADDRSTR_LEN,
                   0,
                   0,
                   NI_NUMERICHOST)))
           {
               Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
                   "HTTPAcceptor - getnameinfo() failure.  rc: $0", rc);
   
               PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                   "HTTPAcceptor: getnameinfo() failed");
               delete accept_address;
               Socket::close(socket);
         return;         return;
     }     }
           ipAddress = ipBuffer;
   #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;
   #endif
       }
   
       delete accept_address;
   
   // set the close on exec flag
   #if !defined(PEGASUS_OS_TYPE_WINDOWS) && !defined(PEGASUS_OS_VMS)
       int sock_flags;
       if ((sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
       {
           PEG_TRACE_CSTRING(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_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                   "HTTPAcceptor: fcntl(F_SETFD) failed");
           }
       }
   #endif
   
   
       PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0,
           "HTTPAcceptor - accept() success.  Socket: $1" ,socket));
   
       SharedPtr<MP_Socket> mp_socket(new MP_Socket(
           socket, _sslcontext, _sslContextObjectLock, ipAddress));
  
     // Create a new conection and add it to the connection list:      mp_socket->disableBlocking();
       mp_socket->setSocketWriteTimeout(_socketWriteTimeout);
  
     MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);      // Perform the SSL handshake, if applicable.
     if (mp_socket->accept() < 0) {  
         if (getenv("PEGASUS_TRACE"))  
             cerr <<"HTTPAcceptor: SSL_accept() failed" << endl;  
  
       Sint32 socketAcceptStatus = mp_socket->accept();
   
       if (socketAcceptStatus < 0)
       {
           PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
               "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, _outputMessageQueue);  
       HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
           ipAddress, this, static_cast<MessageQueue *>(_outputMessageQueue));
   
       if (_idleConnectionTimeoutSeconds)
       {
           connection->_idleConnectionTimeoutSeconds =
               _idleConnectionTimeoutSeconds;
           Time::gettimeofday(&connection->_idleStartTime);
       }
   
       if (socketAcceptStatus == 0)
       {
           PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL2,
               "HTTPAcceptor: SSL_accept() pending");
           connection->_acceptPending = true;
           Time::gettimeofday(&connection->_acceptPendingStartTime);
       }
  
     // 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,              connection->getSocket(),
         SocketMessage::READ | SocketMessage::EXCEPTION,         SocketMessage::READ | SocketMessage::EXCEPTION,
         connection->getQueueId()))              connection->getQueueId(), MonitorEntry::TYPE_CONNECTION)) )
     {     {
           // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
           // an error message to Client application.
           PEG_TRACE_CSTRING(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:     // Save the socket for cleanup later:
       connection->_entry_index = index;
       AutoMutex autoMut(_rep->_connection_mut);
     _rep->connections.append(connection);     _rep->connections.append(connection);
 } }
  


Legend:
Removed from v.1.5  
changed lines
  Added in v.1.109

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2