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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2