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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2