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

  1 r.kieninger 1.89 //%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 r.kieninger 1.89 // 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 r.kieninger 1.89 #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 r.kieninger 1.89 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 r.kieninger 1.89     {
 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 r.kieninger 1.89                            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 r.kieninger 1.89         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 r.kieninger 1.89         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 r.kieninger 1.89       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 r.kieninger 1.89      }
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 r.kieninger 1.89                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 r.kieninger 1.89    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 r.kieninger 1.89 
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 r.kieninger 1.89 
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 r.kieninger 1.89    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 r.kieninger 1.89 
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 r.kieninger 1.89        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 r.kieninger 1.89    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 r.kieninger 1.89    {
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 r.kieninger 1.89       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 r.kieninger 1.90 #if !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET) && \
411                       ( defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
412                         defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) )
413 r.kieninger 1.89    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                         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 r.kieninger 1.89    // 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                        _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 r.kieninger 1.89       _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                        //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 r.kieninger 1.89 */
477                  void HTTPAcceptor::closeConnectionSocket()
478                  {
479                     if (_rep)
480                     {
481                        // unregister the socket
482                  
483                        // ATTN - comment out - see CIMServer::stopClientConnection()
484                        //_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 r.kieninger 1.89          PEGASUS_ASSERT(false);
498                  #endif
499                        }
500                  
501                     }
502                     else
503                     {
504                        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
505                                          "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 r.kieninger 1.89    else
519                     {
520                        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
521                                          "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
522                     }
523                  }
524                  
525                  
526                  /**
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 r.kieninger 1.89       {
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                  #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 r.kieninger 1.89    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                        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 r.kieninger 1.89 Uint32 HTTPAcceptor::getPortNumber() const
582                  {
583                      return _portNumber;
584                  }
585                  
586                  void HTTPAcceptor::setSocketWriteTimeout(Uint32 socketWriteTimeout)
587                  {
588                      _socketWriteTimeout = socketWriteTimeout;
589                  }
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 r.kieninger 1.89              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                     }
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 r.kieninger 1.89 
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                  
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 r.kieninger 1.89 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                     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 r.kieninger 1.89    {
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                     {
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 r.kieninger 1.89            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                        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 r.kieninger 1.89                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                  // 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 r.kieninger 1.89        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                         "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 r.kieninger 1.89    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                     }
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 r.kieninger 1.89 
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                     {
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 r.kieninger 1.89    _rep->connections.append(connection);
792                  }
793                  
794                  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2