(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 1.74 //          David Dillard, Symantec Corp. (david_dillard@symantec.com)
 43 j.alex        1.67 //          John Alex, IBM (johnalex@us.ibm.com) for Bug#3312
 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 david.dillard 1.65 
 85 a.arora       1.51 static int MAX_CONNECTION_QUEUE_LENGTH = -1;
 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 konrad.r      1.69     ~HTTPAcceptorRep()
114                        {
115 david.dillard 1.73         delete address;
116 konrad.r      1.69     }
117 kumpf         1.25     struct sockaddr* address;
118                    
119 mike          1.77     PEGASUS_SOCKLEN_T address_size;
120                        Mutex _connection_mut;
121 david.dillard 1.64 
122 mike          1.77     PEGASUS_SOCKET socket;
123                        Array<HTTPConnection*> connections;
124 mike          1.2  };
125                    
126                    ////////////////////////////////////////////////////////////////////////////////
127                    //
128                    // HTTPAcceptor
129                    //
130                    ////////////////////////////////////////////////////////////////////////////////
131                    
132 kumpf         1.25 HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
133                                               MessageQueue* outputMessageQueue,
134                                               Boolean localConnection,
135                                               Uint32 portNumber,
136 kumpf         1.49                            SSLContext * sslcontext,
137 nag.boranna   1.59                            Boolean exportConnection,
138                                               ReadWriteSem* sslContextObjectLock)
139 kumpf         1.25    : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
140                         _monitor(monitor),
141                         _outputMessageQueue(outputMessageQueue),
142                         _rep(0),
143                         _entry_index(-1),
144                         _localConnection(localConnection),
145                         _portNumber(portNumber),
146 kumpf         1.49      _sslcontext(sslcontext),
147 nag.boranna   1.59      _exportConnection(exportConnection),
148                         _sslContextObjectLock(sslContextObjectLock)
149 mike          1.2  {
150 mday          1.7     Socket::initializeInterface();
151 david.dillard 1.64 
152 a.arora       1.51    /*
153                            Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH differently.  Some platforms interpret
154                            the value literally, while others multiply a fudge factor. When the server is under
155                            stress from multiple clients with multiple requests, toggling this number may prevent clients from
156                            being dropped.  Instead of hard coding the value, we allow an environment variable to be set which
157                            specifies a number greater than the maximum concurrent client connections possible.  If this environment
158                            var is not specified, then MAX_CONNECTION_QUEUE_LENGTH = 15.
159                       */
160                    
161                    //To engage runtime backlog queue length: uncomment the following block AND comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
162                    
163                    /*
164                       if(MAX_CONNECTION_QUEUE_LENGTH == -1){
165                    #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
166                    #pragma convert(37)
167 h.sterling    1.63     const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
168                        EtoA(env);
169 a.arora       1.51 #pragma convert(0)
170                    #else
171 h.sterling    1.63     const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
172 a.arora       1.51 #endif
173 h.sterling    1.63     if(!env){
174                            MAX_CONNECTION_QUEUE_LENGTH = 15;
175 david.dillard 1.64     }else{
176 h.sterling    1.63         char *end = NULL;
177                            MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
178                            if(*end)
179                                MAX_CONNECTION_QUEUE_LENGTH = 15;
180                            cout << " MAX_CONNECTION_QUEUE_LENGTH = " << MAX_CONNECTION_QUEUE_LENGTH << endl;
181                        }
182 a.arora       1.51    }
183                    */
184                       MAX_CONNECTION_QUEUE_LENGTH = 15;
185 david.dillard 1.64 
186 mike          1.2  }
187                    
188                    HTTPAcceptor::~HTTPAcceptor()
189                    {
190 konrad.r      1.70    destroyConnections();
191 mday          1.7     unbind();
192 kumpf         1.25    // ATTN: Is this correct in a multi-HTTPAcceptor server?
193 mday          1.7     Socket::uninitializeInterface();
194 mike          1.2  }
195                    
196 mday          1.7  void HTTPAcceptor::handleEnqueue(Message *message)
197 mike          1.2  {
198 mday          1.7     if (! message)
199                          return;
200 david.dillard 1.64 
201 konrad.r      1.68    PEGASUS_ASSERT(_rep != 0);
202 mday          1.7     switch (message->getType())
203                       {
204                          case SOCKET_MESSAGE:
205                          {
206 h.sterling    1.63      SocketMessage* socketMessage = (SocketMessage*)message;
207 david.dillard 1.64 
208 h.sterling    1.63      // If this is a connection request:
209                    
210                         if (socketMessage->socket == _rep->socket &&
211                             socketMessage->events & SocketMessage::READ)
212                         {
213                            _acceptConnection();
214                         }
215                         else
216                         {
217                            // ATTN! this can't happen!
218 kumpf         1.44             Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
219                                  "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");
220 h.sterling    1.63      }
221 mday          1.7  
222 h.sterling    1.63      break;
223 mday          1.7        }
224                    
225                          case CLOSE_CONNECTION_MESSAGE:
226                          {
227 david.dillard 1.64      CloseConnectionMessage* closeConnectionMessage
228 h.sterling    1.63         = (CloseConnectionMessage*)message;
229                    
230                         AutoMutex autoMut(_rep->_connection_mut);
231 david.dillard 1.64 
232 h.sterling    1.63      for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
233                         {
234 david.dillard 1.64         HTTPConnection* connection = _rep->connections[i];
235 david.dillard 1.74         PEGASUS_SOCKET socket = connection->getSocket();
236 mday          1.7  
237 h.sterling    1.63         if (socket == closeConnectionMessage->socket)
238                            {
239                               _monitor->unsolicitSocketMessages(socket);
240                               _rep->connections.remove(i);
241 kumpf         1.17                delete connection;
242 h.sterling    1.63            break;
243                            }
244                         }
245 david.dillard 1.64 
246 h.sterling    1.63      break;
247 mday          1.7        }
248 mike          1.2  
249 kumpf         1.10       default:
250                          // ATTN: need unexpected message error!
251 kumpf         1.44       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
252                               "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
253 mday          1.7        break;
254                       };
255 mike          1.2  
256 mday          1.7     delete message;
257                    }
258 mike          1.2  
259                    
260 mday          1.7  void HTTPAcceptor::handleEnqueue()
261                    {
262                       Message* message = dequeue();
263 mike          1.2  
264 mday          1.7     if (!message)
265 kumpf         1.44    {
266                          Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
267                               "HTTPAcceptor::handleEnqueue(): No message on queue.");
268 mday          1.7        return;
269 kumpf         1.44    }
270 david.dillard 1.64 
271 mday          1.7     handleEnqueue(message);
272 mike          1.2  
273                    }
274                    
275 kumpf         1.25 void HTTPAcceptor::bind()
276 mike          1.2  {
277 humberto      1.30    if (_rep){
278 h.sterling    1.63     //l10n
279 david.dillard 1.64       //throw BindFailedException("HTTPAcceptor already bound");
280 humberto      1.34 
281 humberto      1.30       MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
282 h.sterling    1.63                    "HTTPAcceptor already bound");
283 humberto      1.34 
284 kumpf         1.44       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
285                               "HTTPAcceptor::bind: HTTPAcceptor already bound.");
286 humberto      1.30       throw BindFailedException(parms);
287                       }
288 mike          1.2  
289 kumpf         1.25    _rep = new HTTPAcceptorRep(_localConnection);
290 mike          1.2  
291 mday          1.7     // bind address
292                       _bind();
293 mike          1.2  
294 mday          1.7     return;
295 mike          1.2  }
296                    
297                    /**
298 mday          1.7     _bind - creates a new server socket and bind socket to the port address.
299 h.sterling    1.63    If PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET is not defined, the port number is ignored and
300 kumpf         1.11    a domain socket is bound.
301 mike          1.2  */
302                    void HTTPAcceptor::_bind()
303                    {
304                    
305 konrad.r      1.68    PEGASUS_ASSERT(_rep != 0);
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 david.dillard 1.65       PEGASUS_SOCKLEN_T bufSize = sizeof(buf);
429 david.dillard 1.64       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 j.alex        1.67       // Unlink Local Domain Socket Bug# 3312
516                          if (_localConnection)
517                          {
518                    #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
519 denise.eckstein 1.71           PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
520 j.alex          1.67                         "HTTPAcceptor::closeConnectionSocket Unlinking local connection." );
521                               ::unlink(
522                                   reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
523                      #else
524                               PEGASUS_ASSERT(false);
525                      #endif
526                            }
527                      
528 mday            1.7     }
529 kumpf           1.44    else
530                         {
531                            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
532                                              "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
533                         }
534 mike            1.2  }
535                      
536                      /**
537 mday            1.7     reopenConnectionSocket - creates a new server socket.
538 mike            1.2  */
539                      void HTTPAcceptor::reopenConnectionSocket()
540                      {
541 mday            1.7     if (_rep)
542                         {
543                            _bind();
544                         }
545 kumpf           1.44    else
546                         {
547                            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
548                                              "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
549                         }
550 mike            1.2  }
551                      
552                      /**
553 mday            1.7     getOutstandingRequestCount - returns the number of outstanding requests.
554 mike            1.2  */
555 david.dillard   1.64 Uint32 HTTPAcceptor::getOutstandingRequestCount() const
556 mike            1.2  {
557 mday            1.28    Uint32 count = 0;
558 konrad.r        1.68    if (_rep)
559 mday            1.7     {
560 konrad.r        1.68       AutoMutex autoMut(_rep->_connection_mut);
561                            if (_rep->connections.size() > 0)
562                            {
563                               HTTPConnection* connection = _rep->connections[0];
564                               count = connection->getRequestCount();
565                            }
566 mday            1.7     }
567 mday            1.28    return count;
568 mike            1.2  }
569                      
570 david.dillard   1.64 
571                      /**
572                          getPortNumber - returns the port number used for the connection
573                      */
574                      Uint32 HTTPAcceptor::getPortNumber() const
575                      {
576                          return _portNumber;
577                      }
578                      
579 mike            1.2  void HTTPAcceptor::unbind()
580                      {
581 mday            1.7     if (_rep)
582                         {
583 david.dillard   1.64       _portNumber = 0;
584 mday            1.7        Socket::close(_rep->socket);
585 kumpf           1.25 
586                            if (_localConnection)
587                            {
588 h.sterling      1.63 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
589 kumpf           1.25          ::unlink(
590                                   reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
591                      #else
592                               PEGASUS_ASSERT(false);
593                      #endif
594                            }
595                      
596 mday            1.7        delete _rep;
597                            _rep = 0;
598                         }
599 kumpf           1.44    else
600                         {
601                            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
602                                    "HTTPAcceptor::unbind failure _rep is null." );
603                         }
604 mike            1.2  }
605                      
606                      void HTTPAcceptor::destroyConnections()
607                      {
608 konrad.r        1.68    if (_rep)
609                         {
610                           // For each connection created by this object:
611 mday            1.28 
612 konrad.r        1.68      AutoMutex autoMut(_rep->_connection_mut);
613                           for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
614                           {
615                              HTTPConnection* connection = _rep->connections[i];
616 david.dillard   1.74         PEGASUS_SOCKET socket = connection->getSocket();
617 mike            1.2  
618 konrad.r        1.68         // Unsolicit SocketMessages:
619 mike            1.2  
620 konrad.r        1.68         _monitor->unsolicitSocketMessages(socket);
621 mike            1.2  
622 konrad.r        1.68         // Destroy the connection (causing it to close):
623 mike            1.2  
624 mike            1.75         while (connection->refcount.get()) { }
625 konrad.r        1.68         delete connection;
626                           }
627 mike            1.2  
628 konrad.r        1.68      _rep->connections.clear();
629 mday            1.7     }
630 mike            1.2  }
631                      
632                      void HTTPAcceptor::_acceptConnection()
633                      {
634 mday            1.7     // This function cannot be called on an invalid socket!
635 mike            1.2  
636 mday            1.7     PEGASUS_ASSERT(_rep != 0);
637 mike            1.2  
638 mday            1.7     if (!_rep)
639                            return;
640 mike            1.2  
641 mday            1.7     // Accept the connection (populate the address):
642 mike            1.2  
643 kumpf           1.25    struct sockaddr* accept_address;
644 mike            1.77    PEGASUS_SOCKLEN_T address_size;
645 mike            1.2  
646 kumpf           1.25    if (_localConnection)
647                         {
648 h.sterling      1.63 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
649 kumpf           1.25        accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
650                             address_size = sizeof(struct sockaddr_un);
651 mike            1.2  #else
652 kumpf           1.25        PEGASUS_ASSERT(false);
653 mike            1.2  #endif
654 kumpf           1.25    }
655                         else
656                         {
657                             accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
658                             address_size = sizeof(struct sockaddr_in);
659                         }
660                      
661 david.dillard   1.73    PEGASUS_SOCKET socket = accept(_rep->socket, accept_address, &address_size);
662 kumpf           1.25 
663                         delete accept_address;
664 mike            1.2  
665 mday            1.7     if (socket < 0)
666                         {
667 mday            1.36 
668 david           1.27        Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
669 h.sterling      1.63            "HTTPAcceptor - accept() failure.  errno: $0"
670                                 ,errno);
671 david           1.27 
672 kumpf           1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
673 kumpf           1.19                         "HTTPAcceptor: accept() failed");
674 mday            1.7        return;
675                         }
676 david           1.27 
677 david.dillard   1.64 // set the close on exec flag
678 gs.keenan       1.58 #if !defined PEGASUS_PLATFORM_WIN32_IX86_MSVC && !defined(PEGASUS_OS_VMS)
679 mday            1.28    int sock_flags;
680                       if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
681                         {
682 kumpf           1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
683 mday            1.28                         "HTTPAcceptor: fcntl(F_GETFD) failed");
684                         }
685                         else
686                         {
687                            sock_flags |= FD_CLOEXEC;
688                            if (fcntl(socket, F_SETFD, sock_flags) < 0)
689                            {
690 kumpf           1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
691 mday            1.28                         "HTTPAcceptor: fcntl(F_SETFD) failed");
692                            }
693                         }
694 david.dillard   1.64 #endif
695 mday            1.28 
696                      
697 mike            1.76    PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0,
698                             "HTTPAcceptor - accept() success.  Socket: $1" ,socket));
699 mike            1.2  
700 kumpf           1.72    AutoPtr<MP_Socket> mp_socket(new MP_Socket(
701                             socket, _sslcontext, _sslContextObjectLock, _exportConnection));
702 mike            1.2  
703 kumpf           1.72    // Perform the SSL handshake, if applicable.  Make the socket non-blocking
704                         // for this operation so we can send it back to the Monitor's select() loop
705                         // if it takes a while.
706                      
707                         mp_socket->disableBlocking();
708                         Sint32 socketAcceptStatus = mp_socket->accept();
709                         mp_socket->enableBlocking();
710 nag.boranna     1.59 
711 kumpf           1.72    if (socketAcceptStatus < 0)
712 kumpf           1.19    {
713 nag.boranna     1.61        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
714 kumpf           1.19                         "HTTPAcceptor: SSL_accept() failed");
715 nag.boranna     1.61        mp_socket->close();
716                             return;
717 mday            1.7     }
718 mike            1.2  
719 kumpf           1.72    // Create a new connection and add it to the connection list:
720                      
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 kumpf           1.72    if (socketAcceptStatus == 0)
725                         {
726                             PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
727                                 "HTTPAcceptor: SSL_accept() pending");
728                             connection->_acceptPending = true;
729                         }
730                      
731 mday            1.7     // Solicit events on this new connection's socket:
732 mday            1.21    int index;
733 david.dillard   1.64 
734 mday            1.22    if (-1 ==  (index = _monitor->solicitSocketMessages(
735 h.sterling      1.63       connection->getSocket(),
736                            SocketMessage::READ | SocketMessage::EXCEPTION,
737                            connection->getQueueId(), Monitor::CONNECTION)) )
738 mday            1.7     {
739 kumpf           1.37       // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
740                            // an error message to Client application.
741 kumpf           1.44       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
742                                "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
743 mday            1.7        delete connection;
744                            Socket::close(socket);
745 kumpf           1.37       return;
746 mday            1.7     }
747 a.arora         1.48 
748 mday            1.7     // Save the socket for cleanup later:
749 mday            1.21    connection->_entry_index = index;
750 a.arora         1.50    AutoMutex autoMut(_rep->_connection_mut);
751 mday            1.7     _rep->connections.append(connection);
752 mike            1.2  }
753 mday            1.32 
754 mike            1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2