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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2