(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 mike    1.2  //
 37              //%/////////////////////////////////////////////////////////////////////////////
 38              
 39              #include "Config.h"
 40 kumpf   1.15 #include "Constants.h"
 41 mike    1.2  #include <iostream>
 42              #include "Socket.h"
 43              
 44              #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC
 45 mday    1.12 #include <windows.h>
 46 mike    1.2  #else
 47              # include <cctype>
 48              # include <cstdlib>
 49              # include <errno.h>
 50              # include <fcntl.h>
 51              # include <netdb.h>
 52              # include <netinet/in.h>
 53              # include <arpa/inet.h>
 54              # include <sys/socket.h>
 55 kumpf   1.11 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
 56 kumpf   1.26 # include <unistd.h>
 57 kumpf   1.11 #  include <sys/un.h>
 58              # endif
 59 mike    1.2  #endif
 60              
 61              #include "Socket.h"
 62              #include "TLS.h"
 63              #include "HTTPAcceptor.h"
 64              #include "HTTPConnection.h"
 65 kumpf   1.19 #include "Tracer.h"
 66 humberto 1.30 #include <Pegasus/Common/MessageLoader.h> //l10n
 67 mike     1.2  
 68 chuck    1.38 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
 69               #include "OS400ConvertChar.h"
 70               #endif
 71               
 72 mike     1.2  PEGASUS_USING_STD;
 73               
 74               PEGASUS_NAMESPACE_BEGIN
 75               
 76 a.arora  1.51 static int MAX_CONNECTION_QUEUE_LENGTH = -1;
 77               
 78               
 79 mike     1.2  ////////////////////////////////////////////////////////////////////////////////
 80               //
 81               // HTTPAcceptorRep
 82               //
 83               ////////////////////////////////////////////////////////////////////////////////
 84               
 85 kumpf    1.25 class HTTPAcceptorRep
 86 mike     1.2  {
 87 kumpf    1.25 public:
 88                   HTTPAcceptorRep(Boolean local)
 89                   {
 90                       if (local)
 91                       {
 92 kumpf    1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
 93 kumpf    1.25             address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
 94                           address_size = sizeof(struct sockaddr_un);
 95 kumpf    1.11 #else
 96 kumpf    1.25             PEGASUS_ASSERT(false);
 97 kumpf    1.11 #endif
 98 david    1.27         }  
 99 kumpf    1.25         else
100                       {
101                           address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
102                           address_size = sizeof(struct sockaddr_in);
103                       }
104                   }
105               
106                   struct sockaddr* address;
107               
108               #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
109                  size_t address_size;
110 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))
111 kumpf        1.25    socklen_t address_size;
112                   #else
113                      int address_size;
114                   #endif
115 mday         1.28       Mutex _connection_mut;
116                         
117                         Sint32 socket;
118                         Array<HTTPConnection*> connections;
119 mike         1.2  };
120                   
121                   ////////////////////////////////////////////////////////////////////////////////
122                   //
123                   // HTTPAcceptor
124                   //
125                   ////////////////////////////////////////////////////////////////////////////////
126                   
127 kumpf        1.25 HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
128                                              MessageQueue* outputMessageQueue,
129                                              Boolean localConnection,
130                                              Uint32 portNumber,
131 kumpf        1.49                            SSLContext * sslcontext,
132                                              Boolean exportConnection)
133 kumpf        1.25    : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
134                        _monitor(monitor),
135                        _outputMessageQueue(outputMessageQueue),
136                        _rep(0),
137                        _entry_index(-1),
138                        _localConnection(localConnection),
139                        _portNumber(portNumber),
140 kumpf        1.49      _sslcontext(sslcontext),
141                        _exportConnection(exportConnection)
142 mike         1.2  {
143 mday         1.7     Socket::initializeInterface();
144 a.arora      1.51  
145                      /*
146                           Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH differently.  Some platforms interpret
147                           the value literally, while others multiply a fudge factor. When the server is under
148                           stress from multiple clients with multiple requests, toggling this number may prevent clients from
149                           being dropped.  Instead of hard coding the value, we allow an environment variable to be set which
150                           specifies a number greater than the maximum concurrent client connections possible.  If this environment
151                           var is not specified, then MAX_CONNECTION_QUEUE_LENGTH = 15.
152                      */
153                   
154                   //To engage runtime backlog queue length: uncomment the following block AND comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
155                   
156                   /*
157                      if(MAX_CONNECTION_QUEUE_LENGTH == -1){
158                   #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
159                   #pragma convert(37)
160                      	const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
161                      	EtoA(env);
162                   #pragma convert(0)
163                   #else
164                      	const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
165 a.arora      1.51 #endif
166                   	if(!env){
167                   		MAX_CONNECTION_QUEUE_LENGTH = 15;
168                   	}else{	
169                      		char *end = NULL;
170                      		MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
171                      		if(*end)
172                   			MAX_CONNECTION_QUEUE_LENGTH = 15;
173                   		cout << " MAX_CONNECTION_QUEUE_LENGTH = " << MAX_CONNECTION_QUEUE_LENGTH << endl;
174                   	}
175                      }
176                   */
177                      MAX_CONNECTION_QUEUE_LENGTH = 15;
178                   	
179 mike         1.2  }
180                   
181                   HTTPAcceptor::~HTTPAcceptor()
182                   {
183 mday         1.7     unbind();
184 kumpf        1.25    // ATTN: Is this correct in a multi-HTTPAcceptor server?
185 mday         1.7     Socket::uninitializeInterface();
186 mike         1.2  }
187                   
188 mday         1.7  void HTTPAcceptor::handleEnqueue(Message *message)
189 mike         1.2  {
190 mday         1.7     if (! message)
191                         return;
192                      
193                      switch (message->getType())
194                      {
195                         case SOCKET_MESSAGE:
196                         {
197                   	 SocketMessage* socketMessage = (SocketMessage*)message;
198 mday         1.32  	 
199 mday         1.7  	 // If this is a connection request:
200                   
201                   	 if (socketMessage->socket == _rep->socket &&
202                   	     socketMessage->events | SocketMessage::READ)
203                   	 {
204                   	    _acceptConnection();
205                   	 }
206                   	 else
207                   	 {
208                   	    // ATTN! this can't happen!
209 kumpf        1.44             Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
210                                 "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");
211 mday         1.7  	 }
212                   
213                   	 break;
214                         }
215                   
216                         case CLOSE_CONNECTION_MESSAGE:
217                         {
218                   	 CloseConnectionMessage* closeConnectionMessage 
219                   	    = (CloseConnectionMessage*)message;
220                   
221 a.arora      1.50 	 AutoMutex autoMut(_rep->_connection_mut);
222 mday         1.28 	 
223 mday         1.7  	 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
224                   	 {
225                   	    HTTPConnection* connection = _rep->connections[i];	
226                   	    Sint32 socket = connection->getSocket();
227 mike         1.2  
228 mday         1.7  	    if (socket == closeConnectionMessage->socket)
229 mike         1.2  	    {
230 mday         1.7  	       _monitor->unsolicitSocketMessages(socket);
231                   	       _rep->connections.remove(i);
232 kumpf        1.17                delete connection;
233 mday         1.7  	       break;
234 mike         1.2  	    }
235 mday         1.7  	 }
236 a.arora      1.50 	 
237 kumpf        1.44 	 break;
238 mday         1.7        }
239 mike         1.2  
240 kumpf        1.10       default:
241                         // ATTN: need unexpected message error!
242 kumpf        1.44       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
243                              "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
244 mday         1.7        break;
245                      };
246 mike         1.2  
247 mday         1.7     delete message;
248                   }
249 mike         1.2  
250                   
251 mday         1.7  void HTTPAcceptor::handleEnqueue()
252                   {
253                      Message* message = dequeue();
254 mike         1.2  
255 mday         1.7     if (!message)
256 kumpf        1.44    {
257                         Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
258                              "HTTPAcceptor::handleEnqueue(): No message on queue.");
259 mday         1.7        return;
260 kumpf        1.44    }
261 mday         1.7     
262                      handleEnqueue(message);
263 mike         1.2  
264                   }
265                   
266 kumpf        1.25 void HTTPAcceptor::bind()
267 mike         1.2  {
268 humberto     1.30    if (_rep){
269                      	//l10n
270                         //throw BindFailedException("HTTPAcceptor already bound");  
271 humberto     1.34 
272 humberto     1.30       MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
273 humberto     1.34 			       "HTTPAcceptor already bound");
274                   
275 kumpf        1.44       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
276                              "HTTPAcceptor::bind: HTTPAcceptor already bound.");
277 humberto     1.30       throw BindFailedException(parms);
278                      }
279 mike         1.2  
280 kumpf        1.25    _rep = new HTTPAcceptorRep(_localConnection);
281 mike         1.2  
282 mday         1.7     // bind address
283                      _bind();
284 mike         1.2  
285 mday         1.7     return;
286 mike         1.2  }
287                   
288                   /**
289 mday         1.7     _bind - creates a new server socket and bind socket to the port address.
290 kumpf        1.11    If PEGASUS_LOCAL_DOMAIN_SOCKET is defined, the port number is ignored and
291                      a domain socket is bound.
292 mike         1.2  */
293                   void HTTPAcceptor::_bind()
294                   {
295                   
296 mday         1.7     // Create address:
297 mike         1.2  
298 kumpf        1.25    memset(_rep->address, 0, sizeof(*_rep->address));
299 kumpf        1.6  
300 kumpf        1.25    if (_localConnection)
301                      {
302 kumpf        1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
303 kumpf        1.25        reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
304                              AF_UNIX;
305                          strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
306                                 PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
307 chuck        1.38 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
308                          AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
309                   #endif
310 kumpf        1.25        ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
311 kumpf        1.6  #else
312 kumpf        1.25        PEGASUS_ASSERT(false);
313 kumpf        1.11 #endif
314 kumpf        1.25    }
315                      else
316                      {
317                          reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_addr.s_addr =
318                              INADDR_ANY;
319                          reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_family =
320                              AF_INET;
321                          reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_port =
322                              htons(_portNumber);
323                      }
324 mike         1.2  
325 mday         1.7     // Create socket:
326 mike         1.2      
327 kumpf        1.25    if (_localConnection)
328                      {
329                          _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
330                      }
331                      else
332                      {
333                          _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
334                      }
335 mike         1.2  
336 mday         1.7     if (_rep->socket < 0)
337                      {
338                         delete _rep;
339                         _rep = 0;
340 humberto     1.30       //l10n
341                         //throw BindFailedException("Failed to create socket");
342                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
343 humberto     1.34 			       "Failed to create socket");
344 kumpf        1.44       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
345                              "HTTPAcceptor::_bind _rep->socket < 0");
346 humberto     1.30       throw BindFailedException(parms);
347 mday         1.7     }
348                   
349 mday         1.28 
350                   // set the close-on-exec bit for this file handle.
351                   // any unix that forks needs this bit set. 
352                   #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
353                      int sock_flags;
354                    if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
355                      {
356 kumpf        1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
357                                     "HTTPAcceptor::_bind: fcntl(F_GETFD) failed");
358 mday         1.28    }
359                      else
360                      {
361                         sock_flags |= FD_CLOEXEC;
362                         if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
363                         {
364 kumpf        1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
365                                     "HTTPAcceptor::_bind: fcntl(F_SETFD) failed");
366 mday         1.28       }
367                      }
368                   #endif 
369                   
370                   
371 mday         1.7     //
372                      // Set the socket option SO_REUSEADDR to reuse the socket address so
373                      // that we can rebind to a new socket using the same address when we
374                      // need to resume the cimom as a result of a timeout during a Shutdown
375                      // operation.
376                      //
377                      int opt=1;
378                      if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
379                   		  (char *)&opt, sizeof(opt)) < 0)
380                      {
381 mday         1.28       Socket::close(_rep->socket);
382 mday         1.7        delete _rep;
383                         _rep = 0;
384 humberto     1.30       //l10n
385                         //throw BindFailedException("Failed to set socket option");
386                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
387 humberto     1.34 			       "Failed to set socket option");
388 kumpf        1.44       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
389                                      "HTTPAcceptor::_bind: Failed to set socket option.");
390 humberto     1.30       throw BindFailedException(parms);
391 mday         1.7     }
392                   
393                      // Bind socket to port:
394                   
395 kumpf        1.25    if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
396 mday         1.7     {
397                         Socket::close(_rep->socket);
398                         delete _rep;
399                         _rep = 0;
400 humberto     1.30       //l10n
401                         //throw BindFailedException("Failed to bind socket");
402                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
403 humberto     1.34 			       "Failed to bind socket");
404 kumpf        1.44       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
405                                           "HTTPAcceptor::_bind: Failed to bind socket.");
406 humberto     1.30       throw BindFailedException(parms);
407 mday         1.7     }
408                   
409 kumpf        1.11    // Set up listening on the given socket:
410 mday         1.7  
411 a.arora      1.51    //int const MAX_CONNECTION_QUEUE_LENGTH = 15;
412 mday         1.7  
413                      if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
414                      {
415                         Socket::close(_rep->socket);
416                         delete _rep;
417                         _rep = 0;
418 humberto     1.30       //l10n
419                         //throw BindFailedException("Failed to bind socket");
420                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
421 humberto     1.34 			       "Failed to bind socket");
422 kumpf        1.44       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
423                                     "HTTPAcceptor::_bind: Failed to bind socket(1).");
424 humberto     1.30       throw BindFailedException(parms);
425 mday         1.7     }
426                   
427                      // Register to receive SocketMessages on this socket:
428                   
429 mday         1.21    if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
430 mday         1.7  	  _rep->socket,
431                   	  SocketMessage::READ | SocketMessage::EXCEPTION,
432 mday         1.16 	  getQueueId(), 
433 mday         1.21 	  Monitor::ACCEPTOR)))
434 mday         1.7     {
435                         Socket::close(_rep->socket);
436                         delete _rep;
437                         _rep = 0;
438 humberto     1.30       //l10n
439                         //throw BindFailedException("Failed to solicit socket messaeges");
440                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
441 humberto     1.34 			       "Failed to solicit socket messaeges");
442 kumpf        1.44       PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
443                                     "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
444 humberto     1.30       throw BindFailedException(parms);
445 mday         1.7     }
446 mike         1.2  }
447                   
448                   /**
449 mday         1.7     closeConnectionSocket - close the server listening socket to disallow
450                      new client connections.
451 mike         1.2  */
452                   void HTTPAcceptor::closeConnectionSocket()
453                   {
454 mday         1.7     if (_rep)
455                      {
456                         // unregister the socket
457 kumpf        1.35 
458                         // ATTN - comment out - see CIMServer::stopClientConnection()
459                         //_monitor->unsolicitSocketMessages(_rep->socket);
460 mday         1.7  
461                         // close the socket
462                         Socket::close(_rep->socket);
463                      }
464 kumpf        1.44    else
465                      {
466                         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
467                                           "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
468                      }
469 mike         1.2  }
470                   
471                   /**
472 mday         1.7     reopenConnectionSocket - creates a new server socket.
473 mike         1.2  */
474                   void HTTPAcceptor::reopenConnectionSocket()
475                   {
476 mday         1.7     if (_rep)
477                      {
478                         _bind();
479                      }
480 kumpf        1.44    else
481                      {
482                         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
483                                           "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
484                      }
485 mike         1.2  }
486                   
487                   /**
488 mday         1.7     getOutstandingRequestCount - returns the number of outstanding requests.
489 mike         1.2  */
490                   Uint32 HTTPAcceptor::getOutstandingRequestCount()
491                   {
492 mday         1.28    Uint32 count = 0;
493                      
494 a.arora      1.50    AutoMutex autoMut(_rep->_connection_mut);
495 mday         1.7     if (_rep->connections.size() > 0)
496                      {
497                         HTTPConnection* connection = _rep->connections[0];	
498 mday         1.28       count = connection->getRequestCount();
499 mday         1.7     }
500 a.arora      1.50    
501 mday         1.28    return count;
502 mike         1.2  }
503                   
504                   void HTTPAcceptor::unbind()
505                   {
506 mday         1.7     if (_rep)
507                      {
508                         Socket::close(_rep->socket);
509 kumpf        1.25 
510                         if (_localConnection)
511                         {
512                   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
513                            ::unlink(
514                                reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
515                   #else
516                            PEGASUS_ASSERT(false);
517                   #endif
518                         }
519                   
520 mday         1.7        delete _rep;
521                         _rep = 0;
522                      }
523 kumpf        1.44    else
524                      {
525                         PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
526                                 "HTTPAcceptor::unbind failure _rep is null." );
527                      }
528 mike         1.2  }
529                   
530                   void HTTPAcceptor::destroyConnections()
531                   {
532 mday         1.28 
533                   
534 mday         1.7     // For each connection created by this object:
535 mike         1.2  
536 a.arora      1.50    AutoMutex autoMut(_rep->_connection_mut);
537 mday         1.7     for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
538                      {
539                         HTTPConnection* connection = _rep->connections[i];	
540                         Sint32 socket = connection->getSocket();
541 mike         1.2  
542 mday         1.7        // Unsolicit SocketMessages:
543 mike         1.2  
544 mday         1.7        _monitor->unsolicitSocketMessages(socket);
545 mike         1.2  
546 mday         1.7        // Destroy the connection (causing it to close):
547 mike         1.2  
548 kumpf        1.17       while (connection->refcount.value()) { }
549 mday         1.7        delete connection;
550                      }
551 mike         1.2  
552 mday         1.7     _rep->connections.clear();
553 a.arora      1.50    
554 mike         1.2  }
555                   
556                   void HTTPAcceptor::_acceptConnection()
557                   {
558 mday         1.7     // This function cannot be called on an invalid socket!
559 mike         1.2  
560 mday         1.7     PEGASUS_ASSERT(_rep != 0);
561 mike         1.2  
562 mday         1.7     if (!_rep)
563                         return;
564 mike         1.2  
565 mday         1.7     // Accept the connection (populate the address):
566 mike         1.2  
567 kumpf        1.25    struct sockaddr* accept_address;
568                   #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
569                      size_t address_size;
570 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))
571 kumpf        1.25    socklen_t address_size;
572 mike         1.2  #else
573 kumpf        1.25    int address_size;
574 mike         1.2  #endif
575                   
576 kumpf        1.25    if (_localConnection)
577                      {
578                   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
579                          accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
580                          address_size = sizeof(struct sockaddr_un);
581 mike         1.2  #else
582 kumpf        1.25        PEGASUS_ASSERT(false);
583 mike         1.2  #endif
584 kumpf        1.25    }
585                      else
586                      {
587                          accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
588                          address_size = sizeof(struct sockaddr_in);
589                      }
590                   
591                      Sint32 socket = accept(_rep->socket, accept_address, &address_size);
592                   
593                      delete accept_address;
594 mike         1.2  
595 mday         1.7     if (socket < 0)
596                      {
597 mday         1.36 
598 david        1.27        Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
599                   		   "HTTPAcceptor - accept() failure.  errno: $0"
600                   		   ,errno);
601                   
602 kumpf        1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
603 kumpf        1.19                         "HTTPAcceptor: accept() failed");
604 mday         1.7        return;
605                      }
606 david        1.27 
607 mday         1.28 // set the close on exec flag 
608                   #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
609                      int sock_flags;
610                    if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
611                      {
612 kumpf        1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
613 mday         1.28                         "HTTPAcceptor: fcntl(F_GETFD) failed");
614                      }
615                      else
616                      {
617                         sock_flags |= FD_CLOEXEC;
618                         if (fcntl(socket, F_SETFD, sock_flags) < 0)
619                         {
620 kumpf        1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
621 mday         1.28                         "HTTPAcceptor: fcntl(F_SETFD) failed");
622                         }
623                      }
624                   #endif 
625                   
626                   
627 david        1.27    Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
628                   	       "HTTPAcceptor - accept() success.  Socket: $1"
629                   	       ,socket);
630 mike         1.2  
631 mday         1.7     // Create a new conection and add it to the connection list:
632 mike         1.2  
633 kumpf        1.49    AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, _sslcontext, _exportConnection));
634 kumpf        1.19    if (mp_socket->accept() < 0) 
635                      {
636 kumpf        1.44        PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
637 kumpf        1.19                         "HTTPAcceptor: SSL_accept() failed");
638 mday         1.7        return;
639                      }
640 mike         1.2  
641 kumpf        1.49    HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket, 
642                          this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
643 mike         1.2  
644 mday         1.7     // Solicit events on this new connection's socket:
645 mday         1.21    int index;
646                      
647 mday         1.22    if (-1 ==  (index = _monitor->solicitSocketMessages(
648 mday         1.7  	  socket,
649                   	  SocketMessage::READ | SocketMessage::EXCEPTION,
650 mday         1.21 	  connection->getQueueId(), Monitor::CONNECTION)) )
651 mday         1.7     {
652 kumpf        1.37       // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
653                         // an error message to Client application.
654 kumpf        1.44       Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
655                             "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
656 mday         1.7        delete connection;
657                         Socket::close(socket);
658 kumpf        1.37       return;
659 mday         1.7     }
660 a.arora      1.48 
661                      mp_socket.release();
662 mike         1.2  
663 mday         1.7     // Save the socket for cleanup later:
664 mday         1.21    connection->_entry_index = index;
665 a.arora      1.50    AutoMutex autoMut(_rep->_connection_mut);
666 mday         1.7     _rep->connections.append(connection);
667 a.arora      1.50    
668 mike         1.2  }
669 mday         1.32 
670                   AsyncDQueue<pegasus_acceptor> pegasus_acceptor::acceptors(true, 0);
671                   
672 mday         1.39 void pegasus_acceptor::close_all_acceptors(void)
673                   {
674                      try 
675                      {
676                         pegasus_acceptor* temp = acceptors.remove_first();
677                         while(temp)
678                         {
679                   	 delete temp;
680                   	 temp = acceptors.remove_first();
681                         }
682                      }
683                      catch(...)
684                      {
685                      }
686                      
687                   }
688                   
689                   
690                   
691 mday         1.32 pegasus_acceptor::pegasus_acceptor(monitor_2* monitor, 
692                   				   MessageQueue* outputMessageQueue, 
693                   				   Boolean localConnection, 
694                   				   Uint32 portNumber,
695                   				   SSLContext* sslcontext)
696                     : _monitor(monitor), _outputMessageQueue(outputMessageQueue),
697                       _localConnection(localConnection), _portNumber(portNumber),
698                       _sslcontext(sslcontext), connections(true, 0)
699                   {
700                     
701                        Socket::initializeInterface();
702                        try {
703                          acceptors.insert_first(this);
704                        }
705                        catch(...){
706                        }
707                        
708                   }
709                   
710                   pegasus_acceptor::~pegasus_acceptor(void)
711                   {
712 mday         1.32    unbind();
713                      Socket::uninitializeInterface();
714                      try {
715                        acceptors.remove(this);
716                      }
717                      catch(...){
718                      }
719                      
720                   }
721                   
722                   
723                   void pegasus_acceptor::bind()
724                   {
725                   
726                     PEGASUS_SOCKLEN_SIZE addr_size;
727                     struct sockaddr *addr;
728                     struct sockaddr_in addr_in;
729                   # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
730                     struct sockaddr_un addr_un;
731                   #endif 
732                   
733 mday         1.32   memset(&addr_in, 0, sizeof(addr_in));
734                     addr_in.sin_addr.s_addr = INADDR_ANY;
735                     addr_in.sin_family = AF_INET;
736                     addr_in.sin_port = htons(_portNumber);
737                     addr = (struct sockaddr*) &addr_in;
738                     addr_size = sizeof(addr_in);
739                     
740                     // first step: determine which kind of socket factory to initialize, 
741                     // then create the socket and bind it to an address
742                     if(_localConnection == true){
743                   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
744                       unix_socket_factory sf;
745                       pegasus_socket temp(&sf);
746                       _listener = temp;
747                       
748                       memset(&addr_un, 0, sizeof(addr_un));
749 mday         1.33     addr_un.sun_family = AF_UNIX;
750                       strcpy(addr_un.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
751 chuck        1.38 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
752                       AtoE(addr_un.sun_path);
753                   #endif
754 mday         1.32     addr = (struct sockaddr*) &addr_un;
755                       addr_size = sizeof(addr_un);
756                       _listener.socket(AF_UNIX, SOCK_STREAM, 0);
757                   #else 
758                       bsd_socket_factory sf;
759                       pegasus_socket temp(&sf);
760                       _listener = temp;
761                       _listener.socket(AF_UNIX, SOCK_STREAM, 0);
762                   #endif 
763                     }
764                     else if( _sslcontext != 0 ) {
765                   #ifdef PEGASUS_HAS_SSL
766                       ssl_socket_factory sf;
767 konrad.r     1.47     pegasus_socket temp(&sf, _sslcontext);
768 mday         1.32 #else
769                       bsd_socket_factory sf;
770 konrad.r     1.47     pegasus_socket temp(&sf);
771 mday         1.32 #endif
772                       _listener = temp;
773                       _listener.socket(PF_INET, SOCK_STREAM, 0);
774                     }
775                     else {
776                       bsd_socket_factory sf;
777                       pegasus_socket temp(&sf);
778                       _listener = temp;
779                       _listener.socket(PF_INET, SOCK_STREAM, 0);
780                     }
781                     
782                     _listener.bind((struct sockaddr*)addr, addr_size);
783                       
784                     // second step: listen on the socket 
785                   
786                     _listener.listen(5);
787                     
788                     // third step: add this listening socket to the monitor
789                   
790                      _monitor->tickle();
791                      _monitor->add_entry(_listener, LISTEN, this, this);
792 mday         1.32 }
793                   
794                   
795                   /** Unbind from the given port.
796                    */
797                   void pegasus_acceptor::unbind()
798                   {
799                     // remove the socket from the monitor
800                     _monitor->remove_entry((Sint32)_listener);
801                     
802                     // close the socket
803                     _listener.close();
804                   }
805                   
806                   
807                         /** Close the connection socket.
808                          */
809                   void pegasus_acceptor::closeConnectionSocket()
810                   {
811                     unbind();
812                   }
813 mday         1.32 
814                   
815                         /** Reopen the connection socket.
816                          */
817                   void pegasus_acceptor::reopenConnectionSocket()
818                   {
819                     bind();
820                   }
821                   
822                   
823                     /** Returns the number of outstanding requests
824                      */
825                   Uint32 pegasus_acceptor::getOutstandingRequestCount()
826                   {
827                     return _monitor->getOutstandingRequestCount();
828                   }
829                   
830                   Boolean pegasus_acceptor::operator ==(const pegasus_acceptor& pa)
831                   {
832                     if(this == &pa)
833                       return true;
834 mday         1.32   return false;
835                   }
836                   
837                   Boolean pegasus_acceptor::operator ==(void* pa)
838                   {
839                     if((void*)this == pa)
840                       return true;
841                     return false;
842                   }
843                   
844                   
845                   pegasus_acceptor* pegasus_acceptor::find_acceptor(Boolean local, Uint32 port)
846                   {
847                     pegasus_acceptor* temp = 0;
848                     
849                     try {
850                       acceptors.try_lock(pegasus_thread_self());
851                       temp = acceptors.next(temp);
852                       while(temp){
853                         if( local == true ){
854                   	if(temp->_localConnection){
855 mday         1.32 	  acceptors.unlock();
856                   	  return temp;
857                   	}
858                         }
859                         if(temp->_localConnection == local && temp->_portNumber ==port){
860                   	acceptors.unlock();
861                   	return temp;
862                         }
863                         temp = acceptors.next(temp);
864                       }
865                       acceptors.unlock();
866                     }
867                     catch(...){
868                     }
869                     return temp;
870                   }
871                   
872                   class m2e_rep;
873                   
874                   void pegasus_acceptor::accept_dispatch(monitor_2_entry *entry)
875                   {
876 mday         1.32   pegasus_acceptor* myself = (pegasus_acceptor*)entry->get_accept();
877                     
878                     HTTPConnection2* connection = new HTTPConnection2(entry->_rep->psock, myself->_outputMessageQueue);
879                     
880                     // set the entry's dispatch parameter to point to the connection object
881                     entry->set_dispatch ((void*)connection);
882                   
883 mday         1.36   monitor_2::insert_connection(connection);
884 mday         1.39   
885 mday         1.32 }
886                   
887 mike         1.2  
888                   PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2