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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2