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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2