(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.18 and 1.99.2.4

version 1.18, 2002/05/29 20:59:24 version 1.99.2.4, 2007/06/20 10:47:03
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)  
 //         Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@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 <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>  
 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  
 #  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"
 #include "HTTPConnection.h" #include "HTTPConnection.h"
   #include "HostAddress.h"
   #include "Tracer.h"
   #include <Pegasus/Common/MessageLoader.h>
  
 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(Uint16 connectionType)
 { {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET          if (connectionType == HTTPAcceptor::LOCAL_CONNECTION)
       struct sockaddr_un address;          {
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
               address =
                   reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
               address_size = sizeof(struct sockaddr_un);
 #else #else
       struct sockaddr_in address;              PEGASUS_ASSERT(false);
   #endif
           }
   #ifdef PEGASUS_ENABLE_IPV6
           else if (connectionType == HTTPAcceptor::IPV6_CONNECTION)
           {
               address =
                   reinterpret_cast<struct sockaddr*>(new struct sockaddr_in6);
               address_size = sizeof(struct sockaddr_in6);
           }
 #endif #endif
       Sint32 socket;          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(PEGASUS_QUEUENAME_HTTPACCEPTOR),                             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)
 { {
   
    Socket::initializeInterface();    Socket::initializeInterface();
 }  
  
 HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue,     /*
                            SSLContext * sslcontext)          Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH
    :       Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),          differently.  Some platforms interpret the value literally, while
            _monitor(monitor), _outputMessageQueue(outputMessageQueue),          others multiply a fudge factor. When the server is under stress from
            _rep(0),          multiple clients with multiple requests, toggling this number may
            _sslcontext(sslcontext)          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)
 { {
    Socket::initializeInterface();          const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
           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?
    Socket::uninitializeInterface();    Socket::uninitializeInterface();
 } }
  
Line 113 
Line 180 
    if (! message)    if (! message)
       return;       return;
  
       PEGASUS_ASSERT(_rep != 0);
    switch (message->getType())    switch (message->getType())
    {    {
       case SOCKET_MESSAGE:       case SOCKET_MESSAGE:
Line 122 
Line 190 
          // 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 136 
Line 207 
  
       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)
             {             {
                _monitor->unsolicitSocketMessages(socket);                _monitor->unsolicitSocketMessages(socket);
                _rep->connections.remove(i);                _rep->connections.remove(i);
                while (connection->refcount.value()) { }  
                delete connection;                delete connection;
                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;
 } }
Line 169 
Line 245 
    Message* message = dequeue();    Message* message = dequeue();
  
    if (!message)    if (!message)
       {
           PEG_TRACE_CSTRING(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");      {
           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_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, _rep->address_size);
  
    memset(&_rep->address, 0, sizeof(_rep->address));      if (_connectionType == LOCAL_CONNECTION)
       {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  #ifndef PEGASUS_DISABLE_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);
           ::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;  #endif
    _rep->address.sin_port = htons(_portNumber);      }
   #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 #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:
  
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET      if (_connectionType == LOCAL_CONNECTION)
    _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);      {
 #else          _rep->socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
    _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);      }
   #ifdef PEGASUS_ENABLE_IPV6
       else if (_connectionType == IPV6_CONNECTION)
       {
           _rep->socket = Socket::createSocket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
       }
 #endif #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);
       }
   
   
   // 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 237 
Line 385 
    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,      //
               reinterpret_cast<struct sockaddr*>(&_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");              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 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");          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(),
           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");          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 290 
Line 499 
    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 306 
Line 535 
    {    {
       _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::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 349 
Line 654 
  
       // 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();
 } }
   }
  
 void HTTPAcceptor::_acceptConnection() void HTTPAcceptor::_acceptConnection()
 { {
Line 362 
Line 668 
  
    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
       }
       else
       {
   #ifdef PEGASUS_ENABLE_IPV6
           accept_address =
              reinterpret_cast<struct sockaddr*>
              (new struct sockaddr_storage);
           address_size = sizeof(struct sockaddr_storage);
   #else
           accept_address =
               reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
           address_size = sizeof(struct sockaddr_in);
   #endif
       }
  
 #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)      SocketHandle socket;
    Sint32 socket = accept(  #ifdef PEGASUS_OS_TYPE_WINDOWS
       _rep->socket, (struct sockaddr*)&address, (socklen_t *)&n);      socket = accept(_rep->socket, accept_address, &address_size);
 #else #else
    Sint32 socket = accept(_rep->socket, reinterpret_cast<struct sockaddr*>(&address), &n);      while (
           ((socket = accept(_rep->socket, accept_address, &address_size)) == -1)
           && (errno == EINTR))
           ;
 #endif #endif
  
    if (socket < 0)      if (socket == PEGASUS_SOCKET_ERROR)
    {    {
       if (getenv("PEGASUS_TRACE"))          // the remote connection is invalid, destroy client address.
          cerr <<"HTTPAcceptor: accept() failed" << endl;          delete accept_address;
  
           // TCPIP is down reconnect this acceptor
           if (getSocketError() == PEGASUS_NETWORK_TCPIP_STOPPED)
           {
               PEG_TRACE_CSTRING(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,
               "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;
           while ((rc = getnameinfo(accept_address, address_size, ipBuffer,
               PEGASUS_INET6_ADDRSTR_LEN, 0, 0, NI_NUMERICHOST)) == EAI_AGAIN)
               ;
           if (rc)
           {
               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
       }
  
    // Create a new conection and add it to the connection list:      delete accept_address;
  
    MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);  // set the close on exec flag
    if (mp_socket->accept() < 0) {  #if !defined(PEGASUS_OS_TYPE_WINDOWS) && !defined(PEGASUS_OS_VMS)
       if (getenv("PEGASUS_TRACE"))      int sock_flags;
          cerr <<"HTTPAcceptor: SSL_accept() failed" << endl;      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));
   
       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.
   
       mp_socket->disableBlocking();
       Sint32 socketAcceptStatus = mp_socket->accept();
       mp_socket->enableBlocking();
   
       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, static_cast<MessageQueue *>(_outputMessageQueue));  
       HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
           ipAddress, this, static_cast<MessageQueue *>(_outputMessageQueue));
   
       if (socketAcceptStatus == 0)
       {
           PEG_TRACE_CSTRING(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;
  
    if (!_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
           // 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.18  
changed lines
  Added in v.1.99.2.4

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2