(file) Return to HTTPAcceptor.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 karl  1.91 //%2006////////////////////////////////////////////////////////////////////////
  2            //
  3            // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6            // IBM Corp.; EMC Corporation, The Open Group.
  7            // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9            // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11            // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13            //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15            // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18            // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20            //
 21            // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 karl  1.91 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24            // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27            // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31            //
 32            //%/////////////////////////////////////////////////////////////////////////////
 33            
 34            #include "Config.h"
 35            #include "Constants.h"
 36            #include <iostream>
 37            
 38            #include "Network.h"
 39            #include "Socket.h"
 40            #include "TLS.h"
 41            #include "HTTPAcceptor.h"
 42            #include "HTTPConnection.h"
 43 karl  1.91 #include "Tracer.h"
 44            #include <Pegasus/Common/MessageLoader.h> //l10n
 45            
 46            #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
 47            #include "EBCDIC_OS400.h"
 48            #endif
 49            
 50            
 51            PEGASUS_USING_STD;
 52            
 53            PEGASUS_NAMESPACE_BEGIN
 54            
 55            
 56            static int MAX_CONNECTION_QUEUE_LENGTH = -1;
 57            
 58            ////////////////////////////////////////////////////////////////////////////////
 59            //
 60            // HTTPAcceptorRep
 61            //
 62            ////////////////////////////////////////////////////////////////////////////////
 63            
 64 karl  1.91 class HTTPAcceptorRep
 65            {
 66            public:
 67                HTTPAcceptorRep(Boolean local)
 68                {
 69                    if (local)
 70                    {
 71            #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
 72                        address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
 73                        address_size = sizeof(struct sockaddr_un);
 74            #else
 75                        PEGASUS_ASSERT(false);
 76            #endif
 77                    }
 78                    else
 79                    {
 80                        address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
 81                        address_size = sizeof(struct sockaddr_in);
 82                    }
 83                }
 84                ~HTTPAcceptorRep()
 85 karl  1.91     {
 86                    delete address;
 87                }
 88                struct sockaddr* address;
 89            
 90                SocketLength address_size;
 91                Mutex _connection_mut;
 92            
 93                SocketHandle socket;
 94                Array<HTTPConnection*> connections;
 95            };
 96            
 97            
 98            ////////////////////////////////////////////////////////////////////////////////
 99            //
100            // HTTPAcceptor
101            //
102            ////////////////////////////////////////////////////////////////////////////////
103            
104            HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
105                                       MessageQueue* outputMessageQueue,
106 karl  1.91                            Boolean localConnection,
107                                       Uint32 portNumber,
108                                       SSLContext * sslcontext,
109                                       ReadWriteSem* sslContextObjectLock)
110               : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
111                 _monitor(monitor),
112                 _outputMessageQueue(outputMessageQueue),
113                 _rep(0),
114                 _entry_index(-1),
115                 _localConnection(localConnection),
116                 _portNumber(portNumber),
117                 _sslcontext(sslcontext),
118                 _sslContextObjectLock(sslContextObjectLock)
119            {
120               Socket::initializeInterface();
121            
122               /*
123                    Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH differently.  Some platforms interpret
124                    the value literally, while others multiply a fudge factor. When the server is under
125                    stress from multiple clients with multiple requests, toggling this number may prevent clients from
126                    being dropped.  Instead of hard coding the value, we allow an environment variable to be set which
127 karl  1.91         specifies a number greater than the maximum concurrent client connections possible.  If this environment
128                    var is not specified, then MAX_CONNECTION_QUEUE_LENGTH = 15.
129               */
130            
131            //To engage runtime backlog queue length: uncomment the following block AND comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
132            
133            /*
134               if(MAX_CONNECTION_QUEUE_LENGTH == -1){
135            #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
136            #pragma convert(37)
137                const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
138                EtoA(env);
139            #pragma convert(0)
140            #else
141                const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
142            #endif
143                if(!env){
144                    MAX_CONNECTION_QUEUE_LENGTH = 15;
145                }else{
146                    char *end = NULL;
147                    MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
148 karl  1.91         if(*end)
149                        MAX_CONNECTION_QUEUE_LENGTH = 15;
150                    cout << " MAX_CONNECTION_QUEUE_LENGTH = " << MAX_CONNECTION_QUEUE_LENGTH << endl;
151                }
152               }
153            */
154               MAX_CONNECTION_QUEUE_LENGTH = 15;
155            
156            }
157            
158            HTTPAcceptor::~HTTPAcceptor()
159            {
160               destroyConnections();
161               unbind();
162               // ATTN: Is this correct in a multi-HTTPAcceptor server?
163               Socket::uninitializeInterface();
164            }
165            
166            void HTTPAcceptor::handleEnqueue(Message *message)
167            {
168               if (! message)
169 karl  1.91       return;
170            
171               PEGASUS_ASSERT(_rep != 0);
172               switch (message->getType())
173               {
174                  case SOCKET_MESSAGE:
175                  {
176                 SocketMessage* socketMessage = (SocketMessage*)message;
177            
178                 // If this is a connection request:
179            
180                 if (socketMessage->socket == _rep->socket &&
181                     socketMessage->events & SocketMessage::READ)
182                 {
183                    _acceptConnection();
184                 }
185                 else
186                 {
187                    // ATTN! this can't happen!
188                        Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
189                          "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");
190 karl  1.91      }
191            
192                 break;
193                  }
194            
195                  case CLOSE_CONNECTION_MESSAGE:
196                  {
197                 CloseConnectionMessage* closeConnectionMessage
198                    = (CloseConnectionMessage*)message;
199            
200                 AutoMutex autoMut(_rep->_connection_mut);
201            
202                 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
203                 {
204                    HTTPConnection* connection = _rep->connections[i];
205                    SocketHandle socket = connection->getSocket();
206            
207                    if (socket == closeConnectionMessage->socket)
208                    {
209                       _monitor->unsolicitSocketMessages(socket);
210                       _rep->connections.remove(i);
211 karl  1.91                delete connection;
212                       break;
213                    }
214                 }
215            
216                 break;
217                  }
218            
219                  default:
220                  // ATTN: need unexpected message error!
221                  Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
222                       "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
223                  break;
224               };
225            
226               delete message;
227            }
228            
229            
230            void HTTPAcceptor::handleEnqueue()
231            {
232 karl  1.91    Message* message = dequeue();
233            
234               if (!message)
235               {
236                  Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
237                       "HTTPAcceptor::handleEnqueue(): No message on queue.");
238                  return;
239               }
240            
241               handleEnqueue(message);
242            
243            }
244            
245            void HTTPAcceptor::bind()
246            {
247               if (_rep){
248                //l10n
249                  //throw BindFailedException("HTTPAcceptor already bound");
250            
251                  MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
252                               "HTTPAcceptor already bound");
253 karl  1.91 
254                  Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
255                       "HTTPAcceptor::bind: HTTPAcceptor already bound.");
256                  throw BindFailedException(parms);
257               }
258            
259               _rep = new HTTPAcceptorRep(_localConnection);
260            
261               // bind address
262               _bind();
263            
264               return;
265            }
266            
267            /**
268               _bind - creates a new server socket and bind socket to the port address.
269               If PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET is not defined, the port number is ignored and
270               a domain socket is bound.
271            */
272            void HTTPAcceptor::_bind()
273            {
274 karl  1.91 
275               PEGASUS_ASSERT(_rep != 0);
276               // Create address:
277            
278               memset(_rep->address, 0, sizeof(*_rep->address));
279            
280               if (_localConnection)
281               {
282            #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
283                   reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
284                       AF_UNIX;
285                   strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
286                          PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
287            #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
288                   AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
289            #endif
290                   ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
291            #else
292                   PEGASUS_ASSERT(false);
293            #endif
294               }
295 karl  1.91    else
296               {
297                   reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_addr.s_addr =
298                       INADDR_ANY;
299                   reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_family =
300                       AF_INET;
301                   reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_port =
302                       htons(_portNumber);
303               }
304            
305               // Create socket:
306            
307               if (_localConnection)
308               {
309                   _rep->socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
310               }
311               else
312               {
313                   _rep->socket = Socket::createSocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
314            
315               }
316 karl  1.91 
317               if (_rep->socket < 0)
318               {
319                  delete _rep;
320                  _rep = 0;
321                  //l10n
322                  //throw BindFailedException("Failed to create socket");
323                  MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
324                               "Failed to create socket");
325                  Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
326                       "HTTPAcceptor::_bind _rep->socket < 0");
327                  throw BindFailedException(parms);
328               }
329            
330            
331            // set the close-on-exec bit for this file handle.
332            // any unix that forks needs this bit set.
333            #if !defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_OS_VMS)
334               int sock_flags;
335             if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
336               {
337 karl  1.91        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
338                              "HTTPAcceptor::_bind: fcntl(F_GETFD) failed");
339               }
340               else
341               {
342                  sock_flags |= FD_CLOEXEC;
343                  if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
344                  {
345                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
346                              "HTTPAcceptor::_bind: fcntl(F_SETFD) failed");
347                  }
348               }
349            #endif
350            
351            
352               //
353               // Set the socket option SO_REUSEADDR to reuse the socket address so
354               // that we can rebind to a new socket using the same address when we
355               // need to resume the cimom as a result of a timeout during a Shutdown
356               // operation.
357               //
358 karl  1.91    int opt=1;
359               if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
360                      (char *)&opt, sizeof(opt)) < 0)
361               {
362                  Socket::close(_rep->socket);
363                  delete _rep;
364                  _rep = 0;
365                  //l10n
366                  //throw BindFailedException("Failed to set socket option");
367                  MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
368                               "Failed to set socket option");
369                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
370                               "HTTPAcceptor::_bind: Failed to set socket option.");
371                  throw BindFailedException(parms);
372               }
373            
374            
375               //
376               // Bind socket to port:
377               //
378               if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
379 karl  1.91    {
380                  Socket::close(_rep->socket);
381                  delete _rep;
382                  _rep = 0;
383                  //l10n
384                  //throw BindFailedException("Failed to bind socket");
385                  MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
386                               "Failed to bind socket");
387                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
388                                    "HTTPAcceptor::_bind: Failed to bind socket.");
389                  throw BindFailedException(parms);
390               }
391            
392            
393               //
394               // Get the actual port value used if the caller specified a port value of 0.
395               //
396               if ( _portNumber == 0 )
397               {
398                  sockaddr_in buf;
399                  SocketLength bufSize = sizeof(buf);
400 karl  1.91       if ( getsockname(_rep->socket, reinterpret_cast<sockaddr *>(&buf), &bufSize) == 0 )
401                  {
402                      _portNumber = ntohs(buf.sin_port);
403                  }
404               }
405            
406            
407               //
408               //  Change permissions on Linux local domain socket to allow writes by others.
409               //
410            #if !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET) && \
411                 ( defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
412                   defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) )
413               if (_localConnection)
414               {
415                 if (::chmod( PEGASUS_LOCAL_DOMAIN_SOCKET_PATH,
416                              S_IRUSR | S_IWUSR | S_IXUSR |
417                              S_IRGRP | S_IWGRP | S_IXGRP |
418                              S_IROTH | S_IWOTH | S_IXOTH ) < 0 )
419                 {
420                   Socket::close(_rep->socket);
421 karl  1.91        delete _rep;
422                   _rep = 0;
423                   //l10n
424                   //throw BindFailedException("Failed to bind socket");
425                   MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
426                               "Failed to bind socket");
427                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
428                          "HTTPAcceptor::_bind: Failed to set domain socket permissions.");
429                   throw BindFailedException(parms);
430                 }
431               }
432            #endif
433            
434               // Set up listening on the given socket:
435            
436               //int const MAX_CONNECTION_QUEUE_LENGTH = 15;
437            
438               if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
439               {
440                  Socket::close(_rep->socket);
441                  delete _rep;
442 karl  1.91       _rep = 0;
443                  //l10n
444                  //throw BindFailedException("Failed to bind socket");
445                  MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
446                               "Failed to bind socket");
447                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
448                              "HTTPAcceptor::_bind: Failed to bind socket(1).");
449                  throw BindFailedException(parms);
450               }
451            
452               // Register to receive SocketMessages on this socket:
453            
454               if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
455                  _rep->socket,
456                  SocketMessage::READ | SocketMessage::EXCEPTION,
457                  getQueueId(),
458                  Monitor::ACCEPTOR)))
459               {
460                  Socket::close(_rep->socket);
461                  delete _rep;
462                  _rep = 0;
463 karl  1.91       //l10n
464                  //throw BindFailedException("Failed to solicit socket messaeges");
465                  MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
466                               "Failed to solicit socket messaeges");
467                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
468                              "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
469                  throw BindFailedException(parms);
470               }
471            }
472            
473            /**
474               closeConnectionSocket - close the server listening socket to disallow
475               new client connections.
476            */
477            void HTTPAcceptor::closeConnectionSocket()
478            {
479               if (_rep)
480               {
481                  // unregister the socket
482            
483                  // ATTN - comment out - see CIMServer::stopClientConnection()
484 karl  1.91       //_monitor->unsolicitSocketMessages(_rep->socket);
485            
486                  // close the socket
487                  Socket::close(_rep->socket);
488                  // Unlink Local Domain Socket Bug# 3312
489                  if (_localConnection)
490                  {
491            #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
492                      PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
493                                    "HTTPAcceptor::closeConnectionSocket Unlinking local connection." );
494                     ::unlink(
495                         reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
496            #else
497                     PEGASUS_ASSERT(false);
498            #endif
499                  }
500            
501               }
502               else
503               {
504                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
505 karl  1.91                         "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
506               }
507            }
508            
509            /**
510               reopenConnectionSocket - creates a new server socket.
511            */
512            void HTTPAcceptor::reopenConnectionSocket()
513            {
514               if (_rep)
515               {
516                  _bind();
517               }
518               else
519               {
520                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
521                                    "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
522               }
523            }
524            
525            
526 karl  1.91 /**
527               reconnectConnectionSocket - creates a new server socket.
528            */
529            void HTTPAcceptor::reconnectConnectionSocket()
530            {
531               if (_rep)
532               {
533                  // unregister the socket
534                  _monitor->unsolicitSocketMessages(_rep->socket);
535                  // close the socket
536                  Socket::close(_rep->socket);
537                  // Unlink Local Domain Socket Bug# 3312
538                  if (_localConnection)
539                  {
540            #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
541                      PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
542                                    "HTTPAcceptor::reconnectConnectionSocket Unlinking local connection." );
543                     ::unlink(
544                         reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
545            #else
546                     PEGASUS_ASSERT(false);
547 karl  1.91 #endif
548                  }
549                  // open the socket
550                  _bind();
551               }
552               else
553               {
554                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
555                                    "HTTPAcceptor::reconnectConnectionSocket failure _rep is null." );
556               }
557            }
558            
559            /**
560               getOutstandingRequestCount - returns the number of outstanding requests.
561            */
562            Uint32 HTTPAcceptor::getOutstandingRequestCount() const
563            {
564               Uint32 count = 0;
565               if (_rep)
566               {
567                  AutoMutex autoMut(_rep->_connection_mut);
568 karl  1.91       if (_rep->connections.size() > 0)
569                  {
570                     HTTPConnection* connection = _rep->connections[0];
571                     count = connection->getRequestCount();
572                  }
573               }
574               return count;
575            }
576            
577            
578            /**
579                getPortNumber - returns the port number used for the connection
580            */
581            Uint32 HTTPAcceptor::getPortNumber() const
582            {
583                return _portNumber;
584            }
585            
586            void HTTPAcceptor::setSocketWriteTimeout(Uint32 socketWriteTimeout)
587            {
588                _socketWriteTimeout = socketWriteTimeout;
589 karl  1.91 }
590            
591            void HTTPAcceptor::unbind()
592            {
593               if (_rep)
594               {
595                  _portNumber = 0;
596                  Socket::close(_rep->socket);
597            
598                  if (_localConnection)
599                  {
600            #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
601                     ::unlink(
602                         reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
603            #else
604                     PEGASUS_ASSERT(false);
605            #endif
606                  }
607            
608                  delete _rep;
609                  _rep = 0;
610 karl  1.91    }
611               else
612               {
613                  PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
614                          "HTTPAcceptor::unbind failure _rep is null." );
615               }
616            }
617            
618            void HTTPAcceptor::destroyConnections()
619            {
620               if (_rep)
621               {
622                 // For each connection created by this object:
623            
624                 AutoMutex autoMut(_rep->_connection_mut);
625                 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
626                 {
627                    HTTPConnection* connection = _rep->connections[i];
628                    SocketHandle socket = connection->getSocket();
629            
630                    // Unsolicit SocketMessages:
631 karl  1.91 
632                    _monitor->unsolicitSocketMessages(socket);
633            
634                    // Destroy the connection (causing it to close):
635            
636                    while (connection->refcount.get()) { }
637                    delete connection;
638                 }
639            
640                 _rep->connections.clear();
641               }
642            }
643            
644            void HTTPAcceptor::_acceptConnection()
645            {
646               // This function cannot be called on an invalid socket!
647            
648               PEGASUS_ASSERT(_rep != 0);
649            
650               // Accept the connection (populate the address):
651            
652 karl  1.91    struct sockaddr* accept_address;
653               SocketLength address_size;
654            
655               if (_localConnection)
656               {
657            #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
658                   accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
659                   address_size = sizeof(struct sockaddr_un);
660            #else
661                   PEGASUS_ASSERT(false);
662            #endif
663               }
664               else
665               {
666                   accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
667                   address_size = sizeof(struct sockaddr_in);
668               }
669            
670               SocketHandle socket = accept(_rep->socket, accept_address, &address_size);
671            
672               if (socket == PEGASUS_SOCKET_ERROR)
673 karl  1.91    {
674                   // the remote connection is invalid, destroy client address.
675                   delete accept_address;
676            
677                   // TCPIP is down reconnect this acceptor
678                   if(getSocketError() == PEGASUS_NETWORK_TCPIP_STOPPED)
679                   {
680            
681                       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
682                                "Socket has an IO error. TCP/IP down. Try to reconnect." );
683            
684                       reconnectConnectionSocket();
685            
686                       return;
687                   }
688                   Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
689                       "HTTPAcceptor - accept() failure.  errno: $0"
690                       ,errno);
691            
692                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
693                                    "HTTPAcceptor: accept() failed");
694 karl  1.91       return;
695               }
696            
697               String ipAddress;
698            
699               if (_localConnection)
700               {
701                   ipAddress = "localhost";
702               }
703               else
704               {
705                   unsigned char* sa = reinterpret_cast<unsigned char*>(
706                       &reinterpret_cast<struct sockaddr_in*>(
707                           accept_address)->sin_addr.s_addr);
708                   char ipBuffer[32];
709                   sprintf(ipBuffer, "%u.%u.%u.%u", sa[0], sa[1], sa[2], sa[3]);
710                   ipAddress = ipBuffer;
711               }
712            
713               delete accept_address;
714            
715 karl  1.91 // set the close on exec flag
716            #if !defined(PEGASUS_OS_TYPE_WINDOWS) && !defined(PEGASUS_OS_VMS)
717               int sock_flags;
718             if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
719               {
720                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
721                                    "HTTPAcceptor: fcntl(F_GETFD) failed");
722               }
723               else
724               {
725                  sock_flags |= FD_CLOEXEC;
726                  if (fcntl(socket, F_SETFD, sock_flags) < 0)
727                  {
728                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
729                                    "HTTPAcceptor: fcntl(F_SETFD) failed");
730                  }
731               }
732            #endif
733            
734            
735               PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0,
736 karl  1.91        "HTTPAcceptor - accept() success.  Socket: $1" ,socket));
737            
738               AutoPtr<MP_Socket> mp_socket(new MP_Socket(
739                   socket, _sslcontext, _sslContextObjectLock));
740            
741               mp_socket->setSocketWriteTimeout(_socketWriteTimeout);
742            
743               // Perform the SSL handshake, if applicable.  Make the socket non-blocking
744               // for this operation so we can send it back to the Monitor's select() loop
745               // if it takes a while.
746            
747               mp_socket->disableBlocking();
748               Sint32 socketAcceptStatus = mp_socket->accept();
749               mp_socket->enableBlocking();
750            
751               if (socketAcceptStatus < 0)
752               {
753                   PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
754                                    "HTTPAcceptor: SSL_accept() failed");
755                   mp_socket->close();
756                   return;
757 karl  1.91    }
758            
759               // Create a new connection and add it to the connection list:
760            
761               HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
762                   ipAddress, this, static_cast<MessageQueue *>(_outputMessageQueue));
763            
764               if (socketAcceptStatus == 0)
765               {
766                   PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
767                       "HTTPAcceptor: SSL_accept() pending");
768                   connection->_acceptPending = true;
769               }
770            
771               // Solicit events on this new connection's socket:
772               int index;
773            
774               if (-1 ==  (index = _monitor->solicitSocketMessages(
775                  connection->getSocket(),
776                  SocketMessage::READ | SocketMessage::EXCEPTION,
777                  connection->getQueueId(), Monitor::CONNECTION)) )
778 karl  1.91    {
779                  // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
780                  // an error message to Client application.
781                  Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
782                      "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
783                  delete connection;
784                  Socket::close(socket);
785                  return;
786               }
787            
788               // Save the socket for cleanup later:
789               connection->_entry_index = index;
790               AutoMutex autoMut(_rep->_connection_mut);
791               _rep->connections.append(connection);
792            }
793            
794            PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2