(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.50 and 1.81.8.12

version 1.50, 2004/08/12 10:47:43 version 1.81.8.12, 2006/10/18 04:24:42
Line 1 
Line 1 
 //%2003////////////////////////////////////////////////////////////////////////  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development  // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.  // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.; // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
 // IBM Corp.; EMC Corporation, The Open Group. // IBM Corp.; EMC Corporation, The Open Group.
   // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; Symantec Corporation; The Open Group.
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
Line 31 
Line 37 
 //         Dave Rosckes (rosckes@us.ibm.com) //         Dave Rosckes (rosckes@us.ibm.com)
 //         Denise Eckstein (denise.eckstein@hp.com) //         Denise Eckstein (denise.eckstein@hp.com)
 //         Alagaraja Ramasubramanian (alags_raj@in.ibm.com) for Bug#1090 //         Alagaraja Ramasubramanian (alags_raj@in.ibm.com) for Bug#1090
   //          Amit Arora, IBM (amita@in.ibm.com) for Bug#2541
   //          Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
   //          Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)
   //          Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2065
   //          David Dillard, Symantec Corp. (david_dillard@symantec.com)
   //          John Alex, IBM (johnalex@us.ibm.com) for Bug#3312
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
Line 39 
Line 51 
 #include <iostream> #include <iostream>
 #include "Socket.h" #include "Socket.h"
  
 #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC  #ifdef PEGASUS_OS_TYPE_WINDOWS
 #include <windows.h> #include <windows.h>
 #else #else
 # include <cctype> # include <cctype>
Line 48 
Line 60 
 # include <fcntl.h> # include <fcntl.h>
 # include <netdb.h> # include <netdb.h>
 # include <netinet/in.h> # include <netinet/in.h>
   # include <netinet/tcp.h>
 # include <arpa/inet.h> # include <arpa/inet.h>
 # include <sys/socket.h> # include <sys/socket.h>
 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
 # include <unistd.h> # include <unistd.h>
 #  include <sys/un.h> #  include <sys/un.h>
 # endif # endif
Line 67 
Line 81 
 #include "OS400ConvertChar.h" #include "OS400ConvertChar.h"
 #endif #endif
  
   
 PEGASUS_USING_STD; PEGASUS_USING_STD;
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
   
   static int MAX_CONNECTION_QUEUE_LENGTH = -1;
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // HTTPAcceptorRep // HTTPAcceptorRep
Line 84 
Line 102 
     {     {
         if (local)         if (local)
         {         {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  
   #ifndef PEGASUS_OS_TYPE_WINDOWS
   # ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
   
             address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);             address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
             address_size = sizeof(struct sockaddr_un);             address_size = sizeof(struct sockaddr_un);
 #else #else
             PEGASUS_ASSERT(false);             PEGASUS_ASSERT(false);
 #endif #endif
   
   #endif
         }         }
         else         else
         {         {
Line 97 
Line 120 
             address_size = sizeof(struct sockaddr_in);             address_size = sizeof(struct sockaddr_in);
         }         }
     }     }
       ~HTTPAcceptorRep()
       {
           delete address;
       }
     struct sockaddr* address;     struct sockaddr* address;
  
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)      PEGASUS_SOCKLEN_T address_size;
    size_t address_size;  
 #elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || (defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC) && !defined(SUNOS_5_6))  
    socklen_t address_size;  
 #else  
    int address_size;  
 #endif  
       Mutex _connection_mut;       Mutex _connection_mut;
  
       Sint32 socket;      PEGASUS_SOCKET socket;
   
   // Added for NamedPipe implementation for windows
   #if defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET)
       NamedPipeServer* namedPipeServer;
   #endif
       Array<HTTPConnection*> connections;       Array<HTTPConnection*> connections;
 }; };
  
   //------------------------------------------------------------------------------
   //
   // _setTCPNoDelay()
   //
   //------------------------------------------------------------------------------
   
   inline void _setTCPNoDelay(PEGASUS_SOCKET socket)
   {
       // This function disables "Nagle's Algorithm" also known as "the TCP delay
       // algorithm", which causes read operations to obtain whatever data is
       // already in the input queue and then wait a little longer to see if
       // more data arrives. This algorithm optimizes the case in which data is
       // sent in only one direction but severely impairs performance of round
       // trip servers. Disabling TCP delay is a standard technique for round
       // trip servers.
   
      int opt = 1;
      setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
   }
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // HTTPAcceptor // HTTPAcceptor
Line 124 
Line 169 
                            Boolean localConnection,                            Boolean localConnection,
                            Uint32 portNumber,                            Uint32 portNumber,
                            SSLContext * sslcontext,                            SSLContext * sslcontext,
                            Boolean exportConnection)                             Boolean exportConnection,
                              ReadWriteSem* sslContextObjectLock)
    : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?    : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
      _monitor(monitor),      _monitor(monitor),
      _outputMessageQueue(outputMessageQueue),      _outputMessageQueue(outputMessageQueue),
Line 133 
Line 179 
      _localConnection(localConnection),      _localConnection(localConnection),
      _portNumber(portNumber),      _portNumber(portNumber),
      _sslcontext(sslcontext),      _sslcontext(sslcontext),
      _exportConnection(exportConnection)       _exportConnection(exportConnection),
        _sslContextObjectLock(sslContextObjectLock)
 { {
    Socket::initializeInterface();    Socket::initializeInterface();
   
      /*
           Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH differently.  Some platforms interpret
           the value literally, while others multiply a fudge factor. When the server is under
           stress from multiple clients with multiple requests, toggling this number may prevent clients from
           being dropped.  Instead of hard coding the value, we allow an environment variable to be set which
           specifies a number greater than the maximum concurrent client connections possible.  If this environment
           var is not specified, then MAX_CONNECTION_QUEUE_LENGTH = 15.
      */
   
   //To engage runtime backlog queue length: uncomment the following block AND comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
   
   /*
      if(MAX_CONNECTION_QUEUE_LENGTH == -1){
   #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
   #pragma convert(37)
       const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
       EtoA(env);
   #pragma convert(0)
   #else
       const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
   #endif
       if(!env){
           MAX_CONNECTION_QUEUE_LENGTH = 15;
       }else{
           char *end = NULL;
           MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
           if(*end)
               MAX_CONNECTION_QUEUE_LENGTH = 15;
           cout << " MAX_CONNECTION_QUEUE_LENGTH = " << MAX_CONNECTION_QUEUE_LENGTH << endl;
       }
      }
   */
      MAX_CONNECTION_QUEUE_LENGTH = 15;
   
 } }
  
 HTTPAcceptor::~HTTPAcceptor() HTTPAcceptor::~HTTPAcceptor()
 { {
      destroyConnections();
    unbind();    unbind();
    // ATTN: Is this correct in a multi-HTTPAcceptor server?    // ATTN: Is this correct in a multi-HTTPAcceptor server?
    Socket::uninitializeInterface();    Socket::uninitializeInterface();
Line 150 
Line 233 
    if (! message)    if (! message)
       return;       return;
  
      PEGASUS_ASSERT(_rep != 0);
    switch (message->getType())    switch (message->getType())
    {    {
       case SOCKET_MESSAGE:       case SOCKET_MESSAGE:
Line 159 
Line 243 
          // If this is a connection request:          // If this is a connection request:
  
          if (socketMessage->socket == _rep->socket &&          if (socketMessage->socket == _rep->socket &&
              socketMessage->events | SocketMessage::READ)               socketMessage->events & SocketMessage::READ)
          {          {
             _acceptConnection();             _acceptConnection();
          }          }
Line 173 
Line 257 
          break;          break;
       }       }
  
   // Added for NamedPipe implementation for windows
   #if defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET)
         case NAMEDPIPE_MESSAGE:
         {
            NamedPipeMessage* namedPipeMessage = (NamedPipeMessage*)message;
   
            if (((namedPipeMessage->namedPipe.getPipe()) == ( _rep->namedPipeServer->getPipe())) &&
                (namedPipeMessage->events & NamedPipeMessage::READ))
            {
                _acceptNamedPipeConnection();
            }
            else
            {
               // ATTN! this can't happen!
               Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                 "HTTPAcceptor::handleEnqueue: Invalid NAMEDPIPE_MESSAGE received.");
            }
            break;
         }
   #endif
        // may Need to close connection for Named Pipe too.....??
       case CLOSE_CONNECTION_MESSAGE:       case CLOSE_CONNECTION_MESSAGE:
       {       {
          CloseConnectionMessage* closeConnectionMessage          CloseConnectionMessage* closeConnectionMessage
Line 183 
Line 288 
          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();  // Added for NamedPipe implementation for windows
   #if defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET)
               if(!connection->isNamedPipeConnection())
               {
   #endif
                   PEGASUS_SOCKET socket = connection->getSocket();
  
             if (socket == closeConnectionMessage->socket)             if (socket == closeConnectionMessage->socket)
             {             {
Line 192 
Line 302 
                delete connection;                delete connection;
                break;                break;
             }             }
   // Added for NamedPipe implementation for windows
   #if defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET)
               }
               else
               {
                   NamedPipe namedPipe = connection->getNamedPipe();
                   //NamedPipeMessage* namedPipeMessage = (NamedPipeMessage*)message;
   
                   if (namedPipe.getPipe() == closeConnectionMessage->namedPipe.getPipe())
                   {
                       _monitor->unsolicitPipeMessages(namedPipe);
                       _rep->connections.remove(i);
                       delete connection;
                       break;
                   }
               }
   #endif
          }          }
  
          break;          break;
Line 247 
Line 374 
  
 /** /**
    _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 ignored and
    a domain socket is bound.    a domain socket is bound.
 */ */
 void HTTPAcceptor::_bind() void HTTPAcceptor::_bind()
 { {
   #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
       {
           AutoMutex automut(Monitor::_cout_mut);
           PEGASUS_STD(cout) << "in HTTPAcceptor::_bind at the begining" << PEGASUS_STD(endl);
           PEGASUS_STD(cout) << "in HTTPAcceptor::_bind before ASSERT" << PEGASUS_STD(endl);
       }
   #endif
      PEGASUS_ASSERT(_rep != 0);
    // Create address:    // Create address:
   #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
      {
          AutoMutex automut(Monitor::_cout_mut);
          PEGASUS_STD(cout) << "in HTTPAcceptor::_bind before memset" << PEGASUS_STD(endl);
      }
   #endif
  
   
   #if defined PEGASUS_OS_TYPE_WINDOWS
      if (!_localConnection)
      {
   #endif
    memset(_rep->address, 0, sizeof(*_rep->address));    memset(_rep->address, 0, sizeof(*_rep->address));
   #if defined PEGASUS_OS_TYPE_WINDOWS
      }
   #endif
   
   #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
      {
          AutoMutex automut(Monitor::_cout_mut);
          PEGASUS_STD(cout) << "in HTTPAcceptor::_bind After memset" << PEGASUS_STD(endl);
      }
   #endif
  
    if (_localConnection)    if (_localConnection)
    {    {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  // Added for NamedPipe implementation for windows
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
   
   # ifdef PEGASUS_OS_TYPE_WINDOWS
   #  ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
          {
              AutoMutex automut(Monitor::_cout_mut);
              PEGASUS_STD(cout) << "in HTTPAcceptor::_bind before calling _createNamedPipe() "
                                << PEGASUS_STD(endl);
          }
   #  endif
          _createNamedPipe();
   # ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
          {
              AutoMutex automut(Monitor::_cout_mut);
              PEGASUS_STD(cout) << "in HTTPAcceptor::_bind after calling _createNamedPipe() " << PEGASUS_STD(endl);
          }
   # endif
          return;
   # else // Other than Windows platform
        reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =        reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
            AF_UNIX;            AF_UNIX;
        strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,         strcpy(
              reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
               PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);               PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
   
 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
        AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);        AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
 #endif #endif
        ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);        ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
   # endif
   
 #else #else
        PEGASUS_ASSERT(false);        PEGASUS_ASSERT(false);
 #endif #endif
Line 283 
Line 461 
    }    }
  
    // Create socket:    // Create socket:
   
    if (_localConnection)    if (_localConnection)
    {    {
        _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);        _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
Line 291 
Line 468 
    else    else
    {    {
        _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);        _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
   
          _setTCPNoDelay(_rep->socket);
    }    }
  
    if (_rep->socket < 0)    if (_rep->socket < 0)
Line 309 
Line 488 
  
 // set the close-on-exec bit for this file handle. // set the close-on-exec bit for this file handle.
 // any unix that forks needs this bit set. // any unix that forks needs this bit set.
 #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC  #if !defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_OS_VMS)
    int sock_flags;    int sock_flags;
  if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)  if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
    {    {
Line 327 
Line 506 
    }    }
 #endif #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 350 
Line 528 
       throw BindFailedException(parms);       throw BindFailedException(parms);
    }    }
  
      //
    // Bind socket to port:    // Bind socket to port:
      //
    if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)    if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
    {    {
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
Line 366 
Line 545 
       throw BindFailedException(parms);       throw BindFailedException(parms);
    }    }
  
    // Set up listening on the given socket:     //
      // Get the actual port value used if the caller specified a port value of 0.
      //
      if ( _portNumber == 0 )
      {
         sockaddr_in buf;
         PEGASUS_SOCKLEN_T bufSize = sizeof(buf);
         if ( getsockname(_rep->socket, reinterpret_cast<sockaddr *>(&buf), &bufSize) == 0 )
         {
             _portNumber = ntohs(buf.sin_port);
         }
      }
  
    int const MAX_CONNECTION_QUEUE_LENGTH = 15;     //
      //  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)
      if (_localConnection)
      {
        if (::chmod( PEGASUS_LOCAL_DOMAIN_SOCKET_PATH,
                     S_IRUSR | S_IWUSR | S_IXUSR |
                     S_IRGRP | S_IWGRP | S_IXGRP |
                     S_IROTH | S_IWOTH | S_IXOTH ) < 0 )
        {
          Socket::close(_rep->socket);
          delete _rep;
          _rep = 0;
          //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 set domain socket permissions.");
          throw BindFailedException(parms);
        }
      }
   #endif
   
      // Set up listening on the given socket:
      //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)
    {    {
Line 403 
Line 619 
                   "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");                   "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
       throw BindFailedException(parms);       throw BindFailedException(parms);
    }    }
   #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
      {
          AutoMutex automut(Monitor::_cout_mut);
          PEGASUS_STD(cout) << "in HTTPAcceptor::_bind at the End" << PEGASUS_STD(endl);
      }
   #endif
   
 } }
  
 /** /**
Line 420 
Line 643 
  
       // close the socket       // close the socket
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
         // Unlink Local Domain Socket Bug# 3312
         if (_localConnection)
         {
   #ifndef PEGASUS_OS_TYPE_WINDOWS
   # ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
             PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
                           "HTTPAcceptor::closeConnectionSocket Unlinking local connection." );
            ::unlink(
                reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
   # else
            PEGASUS_ASSERT(false);
   # endif
   #endif
         }
   
    }    }
    else    else
    {    {
Line 447 
Line 685 
 /** /**
    getOutstandingRequestCount - returns the number of outstanding requests.    getOutstandingRequestCount - returns the number of outstanding requests.
 */ */
 Uint32 HTTPAcceptor::getOutstandingRequestCount()  Uint32 HTTPAcceptor::getOutstandingRequestCount() const
 { {
    Uint32 count = 0;    Uint32 count = 0;
      if (_rep)
      {
    AutoMutex autoMut(_rep->_connection_mut);    AutoMutex autoMut(_rep->_connection_mut);
    if (_rep->connections.size() > 0)    if (_rep->connections.size() > 0)
    {    {
       HTTPConnection* connection = _rep->connections[0];       HTTPConnection* connection = _rep->connections[0];
       count = connection->getRequestCount();       count = connection->getRequestCount();
    }    }
      }
    return count;    return count;
 } }
  
   
   /**
       getPortNumber - returns the port number used for the connection
   */
   Uint32 HTTPAcceptor::getPortNumber() const
   {
       return _portNumber;
   }
   
 void HTTPAcceptor::unbind() void HTTPAcceptor::unbind()
 { {
    if (_rep)    if (_rep)
    {    {
         _portNumber = 0;
       Socket::close(_rep->socket);       Socket::close(_rep->socket);
  
       if (_localConnection)       if (_localConnection)
       {       {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
   # ifndef PEGASUS_OS_TYPE_WINDOWS
   
          ::unlink(          ::unlink(
              reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);              reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
   # endif
 #else #else
          PEGASUS_ASSERT(false);          PEGASUS_ASSERT(false);
 #endif #endif
Line 489 
Line 741 
  
 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);    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();  // Added for NamedPipe implementation for windows
   #if defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET)
           if(!connection->isNamedPipeConnection())
           {
   #endif
               PEGASUS_SOCKET socket = connection->getSocket();
  
       // Unsolicit SocketMessages:       // Unsolicit SocketMessages:
  
       _monitor->unsolicitSocketMessages(socket);       _monitor->unsolicitSocketMessages(socket);
  
   // Added for NamedPipe implementation for windows
       // Destroy the connection (causing it to close):       // Destroy the connection (causing it to close):
   #if defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET)
       while (connection->refcount.value()) { }          }
           else
           {
               NamedPipe namedPipe = connection->getNamedPipe();
               _monitor->unsolicitPipeMessages(namedPipe);
           }
   #endif
           while (connection->refcount.get()) { }
       delete connection;       delete connection;
    }    }
  
    _rep->connections.clear();    _rep->connections.clear();
      }
 } }
  
 void HTTPAcceptor::_acceptConnection() void HTTPAcceptor::_acceptConnection()
Line 523 
Line 788 
       return;       return;
  
    // Accept the connection (populate the address):    // Accept the connection (populate the address):
   
    struct sockaddr* accept_address;    struct sockaddr* accept_address;
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)     PEGASUS_SOCKLEN_T address_size;
    size_t address_size;  
 #elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || (defined(PEGASUS_OS_SOLARIS) && !defined(SUNOS_5_6))  
    socklen_t address_size;  
 #else  
    int address_size;  
 #endif  
  
    if (_localConnection)    if (_localConnection)
    {    {
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET  #ifndef PEGASUS_OS_TYPE_WINDOWS
   # ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
        accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);        accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
        address_size = sizeof(struct sockaddr_un);        address_size = sizeof(struct sockaddr_un);
 #else #else
        PEGASUS_ASSERT(false);        PEGASUS_ASSERT(false);
 #endif #endif
   #endif
    }    }
    else    else
    {    {
Line 548 
Line 808 
        address_size = sizeof(struct sockaddr_in);        address_size = sizeof(struct sockaddr_in);
    }    }
  
    Sint32 socket = accept(_rep->socket, accept_address, &address_size);     PEGASUS_SOCKET socket = accept(_rep->socket, accept_address, &address_size);
  
    delete accept_address;    delete accept_address;
  
Line 565 
Line 825 
    }    }
  
 // set the close on exec flag // set the close on exec flag
 #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC  #if !defined(PEGASUS_OS_TYPE_WINDOWS) && !defined(PEGASUS_OS_VMS)
    int sock_flags;    int sock_flags;
  if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)  if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
    {    {
Line 584 
Line 844 
 #endif #endif
  
  
    Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,     PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0,
                "HTTPAcceptor - accept() success.  Socket: $1"         "HTTPAcceptor - accept() success.  Socket: $1" ,socket));
                ,socket);  
  
    // Create a new conection and add it to the connection list:     AutoPtr<MP_Socket> mp_socket(new MP_Socket(
          socket, _sslcontext, _sslContextObjectLock, _exportConnection));
  
    AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, _sslcontext, _exportConnection));     // Perform the SSL handshake, if applicable.  Make the socket non-blocking
    if (mp_socket->accept() < 0)     // 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_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                         "HTTPAcceptor: SSL_accept() failed");                         "HTTPAcceptor: SSL_accept() failed");
          mp_socket->close();
       return;       return;
    }    }
  
      // Create a new connection and add it to the connection list:
   
    HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,    HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
        this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);        this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
  
      if (socketAcceptStatus == 0)
      {
          PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
              "HTTPAcceptor: SSL_accept() pending");
          connection->_acceptPending = true;
      }
   
    // Solicit events on this new connection's socket:    // Solicit events on this new connection's socket:
    int index;    int index;
  
    if (-1 ==  (index = _monitor->solicitSocketMessages(    if (-1 ==  (index = _monitor->solicitSocketMessages(
           socket,        connection->getSocket(),
           SocketMessage::READ | SocketMessage::EXCEPTION,           SocketMessage::READ | SocketMessage::EXCEPTION,
           connection->getQueueId(), Monitor::CONNECTION)) )           connection->getQueueId(), Monitor::CONNECTION)) )
    {    {
Line 618 
Line 895 
       return;       return;
    }    }
  
    mp_socket.release();  
   
    // Save the socket for cleanup later:    // Save the socket for cleanup later:
    connection->_entry_index = index;    connection->_entry_index = index;
    AutoMutex autoMut(_rep->_connection_mut);    AutoMutex autoMut(_rep->_connection_mut);
    _rep->connections.append(connection);    _rep->connections.append(connection);
   
 } }
  
 AsyncDQueue<pegasus_acceptor> pegasus_acceptor::acceptors(true, 0);  // Added for NamedPipe implementation for windows
   #if defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET)
 void pegasus_acceptor::close_all_acceptors(void)  void HTTPAcceptor::_createNamedPipe()
 {  
    try  
    {    {
       pegasus_acceptor* temp = acceptors.remove_first();  #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
       while(temp)  
       {       {
          delete temp;          AutoMutex automut(Monitor::_cout_mut);
          temp = acceptors.remove_first();          PEGASUS_STD(cout) << "Entering  HTTPAcceptor::_createNamedPipe()." << PEGASUS_STD(endl);
       }  
    }    }
    catch(...)  #endif
       _rep->namedPipeServer = new NamedPipeServer(PEGASUS_NAMEDPIPE_PATH);
   #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
    {    {
           AutoMutex automut(Monitor::_cout_mut);
           PEGASUS_STD(cout) << "in HTTPAcceptor::_createNamedPipe() after calling the pipe server constructor" << PEGASUS_STD(endl);
    }    }
  
 }  
   
   
   
 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)  
 { {
           AutoMutex automut(Monitor::_cout_mut);
      Socket::initializeInterface();          cout << "Named pipe...in _createNamedPipe..." << _rep->namedPipeServer->getPipe() << endl;
      try {  
        acceptors.insert_first(this);  
      }  
      catch(...){  
      }  
   
 } }
   #endif
       // Register to receive Messages on Connection pipe:
  
 pegasus_acceptor::~pegasus_acceptor(void)     if ( -1 == ( _entry_index = _monitor->solicitPipeMessages(
         *_rep->namedPipeServer,
         NamedPipeMessage::READ | NamedPipeMessage::EXCEPTION,
         getQueueId(),
         Monitor::ACCEPTOR)))
 { {
    unbind();         ::CloseHandle(_rep->namedPipeServer->getPipe());
    Socket::uninitializeInterface();         delete _rep;
    try {         _rep = 0;
      acceptors.remove(this);         //l10n
    }         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
    catch(...){                      "Failed to solicit socket messaeges");
    }         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
                      "HTTPAcceptor::_bind: Failed to solicit pipe messages(2).");
 }         throw BindFailedException(parms);
   #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
   
 void pegasus_acceptor::bind()  
 { {
              AutoMutex automut(Monitor::_cout_mut); //added
   PEGASUS_SOCKLEN_SIZE addr_size;             PEGASUS_STD(cout) << "in HTTPAcceptor::_createNamedPipe() _monitor->solicitSocketMessages failed"
   struct sockaddr *addr;                               << PEGASUS_STD(endl);
   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 #endif
     _listener = temp;  
     _listener.socket(PF_INET, SOCK_STREAM, 0);  
   }   }
   else {  #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
     bsd_socket_factory sf;     {
     pegasus_socket temp(&sf);         AutoMutex automut(Monitor::_cout_mut);
     _listener = temp;         PEGASUS_STD(cout) << "Leaving  HTTPAcceptor::_createNamedPipe()." << PEGASUS_STD(endl);
     _listener.socket(PF_INET, SOCK_STREAM, 0);  
   }   }
   #endif
   _listener.bind((struct sockaddr*)addr, addr_size);     return;
   
   // 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);  
 } }
  
   void HTTPAcceptor::_acceptNamedPipeConnection()
 /** Unbind from the given port.  
  */  
 void pegasus_acceptor::unbind()  
 { {
   // remove the socket from the monitor      PEGASUS_ASSERT(_rep != 0);
   _monitor->remove_entry((Sint32)_listener);  
   
   // close the socket  
   _listener.close();  
 }  
   
  
       /** Close the connection socket.      if (!_rep)
        */         return;
 void pegasus_acceptor::closeConnectionSocket()  #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
 { {
   unbind();          AutoMutex automut(Monitor::_cout_mut);
           cout <<"In HTTPAcceptor::_acceptNamedPipeConnection " << endl;
 } }
   #endif
  
  
       /** Reopen the connection socket.      NamedPipeServerEndPiont nPSEndPoint = _rep->namedPipeServer->accept();
        */      // Register to receive Messages on Connection pipe:
 void pegasus_acceptor::reopenConnectionSocket()  #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
 { {
   bind();          AutoMutex automut(Monitor::_cout_mut);
 }          cout << " In _acceptNamedPipeConnection -- after calling namedPipeServer->accept()" << endl;
   
   
   /** Returns the number of outstanding requests  
    */  
 Uint32 pegasus_acceptor::getOutstandingRequestCount()  
 {  
   return _monitor->getOutstandingRequestCount();  
 } }
   #endif
       HTTPConnection* connection = new HTTPConnection(_monitor, nPSEndPoint,
           this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
  
 Boolean pegasus_acceptor::operator ==(const pegasus_acceptor& pa)      // Solicit events on this new connection's socket:
       int index;
   #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
 { {
   if(this == &pa)          AutoMutex automut(Monitor::_cout_mut);
     return true;          cout << endl << connection->getNamedPipe().getName() << " has a this as a QueueID " <<
   return false;           connection->getQueueId() << endl;
 } }
   #endif
 Boolean pegasus_acceptor::operator ==(void* pa)      if (-1 ==  (index = _monitor->solicitPipeMessages(
          connection->getNamedPipe(),
          NamedPipeMessage::READ | NamedPipeMessage::EXCEPTION,
          connection->getQueueId(), Monitor::ACCEPTOR)) )
 { {
   if((void*)this == pa)         // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
     return true;         // an error message to Client application.
   return false;         Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
              "HTTPAcceptor::_acceptPipeConnection: Attempt to allocate entry in _entries table failed.");
          delete connection;
          return;
 } }
  
       // Save the socket for cleanup later:
 pegasus_acceptor* pegasus_acceptor::find_acceptor(Boolean local, Uint32 port)      connection->_entry_index = index;
       AutoMutex autoMut(_rep->_connection_mut);
       _rep->connections.append(connection);
   #ifdef PEGASUS_LOCALDOMAINSOCKET_DEBUG
 { {
   pegasus_acceptor* temp = 0;        AutoMutex automut(Monitor::_cout_mut);
         PEGASUS_STD(cout)
   try {         << "in HTTPAcceptor::_acceptNamedPipeConnection() at the end" << PEGASUS_STD(endl);
     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(...){  #endif
   }  
   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);  
   
 } }
   #endif
  
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.50  
changed lines
  Added in v.1.81.8.12

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2