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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2