(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 w.otsuka     1.52.2.1    //
410                          //  Change permissions on Linux local domain socket to allow writes by others.
411                          //
412                       #if defined(PEGASUS_LOCAL_DOMAIN_SOCKET) && defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
413                          if (_localConnection)
414                          {
415                            if (::chmod( PEGASUS_LOCAL_DOMAIN_SOCKET_PATH, 
416                                         S_IRUSR | S_IWUSR | S_IXUSR | 
417                                         S_IRGRP | S_IWGRP | S_IXGRP |
418                                         S_IROTH | S_IWOTH | S_IXOTH ) < 0 )
419                            {
420                              Socket::close(_rep->socket);
421                              delete _rep;
422                              _rep = 0;
423                              //l10n
424                              //throw BindFailedException("Failed to bind socket");
425                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
426                        			       "Failed to bind socket");
427                              PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
428                                     "HTTPAcceptor::_bind: Failed to set domain socket permissions.");
429                              throw BindFailedException(parms);
430 w.otsuka     1.52.2.1      }
431                          }
432                       #endif
433                       
434 kumpf        1.11        // Set up listening on the given socket:
435 mday         1.7      
436 a.arora      1.51        //int const MAX_CONNECTION_QUEUE_LENGTH = 15;
437 mday         1.7      
438                          if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
439                          {
440                             Socket::close(_rep->socket);
441                             delete _rep;
442                             _rep = 0;
443 humberto     1.30           //l10n
444                             //throw BindFailedException("Failed to bind socket");
445                             MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
446 humberto     1.34     			       "Failed to bind socket");
447 kumpf        1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
448                                         "HTTPAcceptor::_bind: Failed to bind socket(1).");
449 humberto     1.30           throw BindFailedException(parms);
450 mday         1.7         }
451                       
452                          // Register to receive SocketMessages on this socket:
453                       
454 mday         1.21        if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
455 mday         1.7      	  _rep->socket,
456                       	  SocketMessage::READ | SocketMessage::EXCEPTION,
457 mday         1.16     	  getQueueId(), 
458 mday         1.21     	  Monitor::ACCEPTOR)))
459 mday         1.7         {
460                             Socket::close(_rep->socket);
461                             delete _rep;
462                             _rep = 0;
463 humberto     1.30           //l10n
464                             //throw BindFailedException("Failed to solicit socket messaeges");
465                             MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
466 humberto     1.34     			       "Failed to solicit socket messaeges");
467 kumpf        1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
468                                         "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
469 humberto     1.30           throw BindFailedException(parms);
470 mday         1.7         }
471 mike         1.2      }
472                       
473                       /**
474 mday         1.7         closeConnectionSocket - close the server listening socket to disallow
475                          new client connections.
476 mike         1.2      */
477                       void HTTPAcceptor::closeConnectionSocket()
478                       {
479 mday         1.7         if (_rep)
480                          {
481                             // unregister the socket
482 kumpf        1.35     
483                             // ATTN - comment out - see CIMServer::stopClientConnection()
484                             //_monitor->unsolicitSocketMessages(_rep->socket);
485 mday         1.7      
486                             // close the socket
487                             Socket::close(_rep->socket);
488                          }
489 kumpf        1.44        else
490                          {
491                             PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
492                                               "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
493                          }
494 mike         1.2      }
495                       
496                       /**
497 mday         1.7         reopenConnectionSocket - creates a new server socket.
498 mike         1.2      */
499                       void HTTPAcceptor::reopenConnectionSocket()
500                       {
501 mday         1.7         if (_rep)
502                          {
503                             _bind();
504                          }
505 kumpf        1.44        else
506                          {
507                             PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
508                                               "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
509                          }
510 mike         1.2      }
511                       
512                       /**
513 mday         1.7         getOutstandingRequestCount - returns the number of outstanding requests.
514 mike         1.2      */
515                       Uint32 HTTPAcceptor::getOutstandingRequestCount()
516                       {
517 mday         1.28        Uint32 count = 0;
518                          
519 a.arora      1.50        AutoMutex autoMut(_rep->_connection_mut);
520 mday         1.7         if (_rep->connections.size() > 0)
521                          {
522                             HTTPConnection* connection = _rep->connections[0];	
523 mday         1.28           count = connection->getRequestCount();
524 mday         1.7         }
525 a.arora      1.50        
526 mday         1.28        return count;
527 mike         1.2      }
528                       
529                       void HTTPAcceptor::unbind()
530                       {
531 mday         1.7         if (_rep)
532                          {
533                             Socket::close(_rep->socket);
534 kumpf        1.25     
535                             if (_localConnection)
536                             {
537                       #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
538                                ::unlink(
539                                    reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
540                       #else
541                                PEGASUS_ASSERT(false);
542                       #endif
543                             }
544                       
545 mday         1.7            delete _rep;
546                             _rep = 0;
547                          }
548 kumpf        1.44        else
549                          {
550                             PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
551                                     "HTTPAcceptor::unbind failure _rep is null." );
552                          }
553 mike         1.2      }
554                       
555                       void HTTPAcceptor::destroyConnections()
556                       {
557 mday         1.28     
558                       
559 mday         1.7         // For each connection created by this object:
560 mike         1.2      
561 a.arora      1.50        AutoMutex autoMut(_rep->_connection_mut);
562 mday         1.7         for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
563                          {
564                             HTTPConnection* connection = _rep->connections[i];	
565                             Sint32 socket = connection->getSocket();
566 mike         1.2      
567 mday         1.7            // Unsolicit SocketMessages:
568 mike         1.2      
569 mday         1.7            _monitor->unsolicitSocketMessages(socket);
570 mike         1.2      
571 mday         1.7            // Destroy the connection (causing it to close):
572 mike         1.2      
573 kumpf        1.17           while (connection->refcount.value()) { }
574 mday         1.7            delete connection;
575                          }
576 mike         1.2      
577 mday         1.7         _rep->connections.clear();
578 a.arora      1.50        
579 mike         1.2      }
580                       
581                       void HTTPAcceptor::_acceptConnection()
582                       {
583 mday         1.7         // This function cannot be called on an invalid socket!
584 mike         1.2      
585 mday         1.7         PEGASUS_ASSERT(_rep != 0);
586 mike         1.2      
587 mday         1.7         if (!_rep)
588                             return;
589 mike         1.2      
590 mday         1.7         // Accept the connection (populate the address):
591 mike         1.2      
592 kumpf        1.25        struct sockaddr* accept_address;
593                       #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
594                          size_t address_size;
595 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))
596 kumpf        1.25        socklen_t address_size;
597 mike         1.2      #else
598 kumpf        1.25        int address_size;
599 mike         1.2      #endif
600                       
601 kumpf        1.25        if (_localConnection)
602                          {
603                       #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
604                              accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
605                              address_size = sizeof(struct sockaddr_un);
606 mike         1.2      #else
607 kumpf        1.25            PEGASUS_ASSERT(false);
608 mike         1.2      #endif
609 kumpf        1.25        }
610                          else
611                          {
612                              accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
613                              address_size = sizeof(struct sockaddr_in);
614                          }
615                       
616                          Sint32 socket = accept(_rep->socket, accept_address, &address_size);
617                       
618                          delete accept_address;
619 mike         1.2      
620 mday         1.7         if (socket < 0)
621                          {
622 mday         1.36     
623 david        1.27            Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
624                       		   "HTTPAcceptor - accept() failure.  errno: $0"
625                       		   ,errno);
626                       
627 kumpf        1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
628 kumpf        1.19                             "HTTPAcceptor: accept() failed");
629 mday         1.7            return;
630                          }
631 david        1.27     
632 mday         1.28     // set the close on exec flag 
633                       #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
634                          int sock_flags;
635                        if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
636                          {
637 kumpf        1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
638 mday         1.28                             "HTTPAcceptor: fcntl(F_GETFD) failed");
639                          }
640                          else
641                          {
642                             sock_flags |= FD_CLOEXEC;
643                             if (fcntl(socket, F_SETFD, sock_flags) < 0)
644                             {
645 kumpf        1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
646 mday         1.28                             "HTTPAcceptor: fcntl(F_SETFD) failed");
647                             }
648                          }
649                       #endif 
650                       
651                       
652 david        1.27        Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
653                       	       "HTTPAcceptor - accept() success.  Socket: $1"
654                       	       ,socket);
655 mike         1.2      
656 mday         1.7         // Create a new conection and add it to the connection list:
657 mike         1.2      
658 kumpf        1.49        AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, _sslcontext, _exportConnection));
659 kumpf        1.19        if (mp_socket->accept() < 0) 
660                          {
661 kumpf        1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
662 kumpf        1.19                             "HTTPAcceptor: SSL_accept() failed");
663 mday         1.7            return;
664                          }
665 mike         1.2      
666 kumpf        1.49        HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket, 
667                              this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
668 mike         1.2      
669 mday         1.7         // Solicit events on this new connection's socket:
670 mday         1.21        int index;
671                          
672 mday         1.22        if (-1 ==  (index = _monitor->solicitSocketMessages(
673 mday         1.7      	  socket,
674                       	  SocketMessage::READ | SocketMessage::EXCEPTION,
675 mday         1.21     	  connection->getQueueId(), Monitor::CONNECTION)) )
676 mday         1.7         {
677 kumpf        1.37           // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
678                             // an error message to Client application.
679 kumpf        1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
680                                 "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
681 mday         1.7            delete connection;
682                             Socket::close(socket);
683 kumpf        1.37           return;
684 mday         1.7         }
685 a.arora      1.48     
686                          mp_socket.release();
687 mike         1.2      
688 mday         1.7         // Save the socket for cleanup later:
689 mday         1.21        connection->_entry_index = index;
690 a.arora      1.50        AutoMutex autoMut(_rep->_connection_mut);
691 mday         1.7         _rep->connections.append(connection);
692 a.arora      1.50        
693 mike         1.2      }
694 mday         1.32     
695                       AsyncDQueue<pegasus_acceptor> pegasus_acceptor::acceptors(true, 0);
696                       
697 mday         1.39     void pegasus_acceptor::close_all_acceptors(void)
698                       {
699                          try 
700                          {
701                             pegasus_acceptor* temp = acceptors.remove_first();
702                             while(temp)
703                             {
704                       	 delete temp;
705                       	 temp = acceptors.remove_first();
706                             }
707                          }
708                          catch(...)
709                          {
710                          }
711                          
712                       }
713                       
714                       
715                       
716 mday         1.32     pegasus_acceptor::pegasus_acceptor(monitor_2* monitor, 
717                       				   MessageQueue* outputMessageQueue, 
718                       				   Boolean localConnection, 
719                       				   Uint32 portNumber,
720                       				   SSLContext* sslcontext)
721                         : _monitor(monitor), _outputMessageQueue(outputMessageQueue),
722                           _localConnection(localConnection), _portNumber(portNumber),
723                           _sslcontext(sslcontext), connections(true, 0)
724                       {
725                         
726                            Socket::initializeInterface();
727                            try {
728                              acceptors.insert_first(this);
729                            }
730                            catch(...){
731                            }
732                            
733                       }
734                       
735                       pegasus_acceptor::~pegasus_acceptor(void)
736                       {
737 mday         1.32        unbind();
738                          Socket::uninitializeInterface();
739                          try {
740                            acceptors.remove(this);
741                          }
742                          catch(...){
743                          }
744                          
745                       }
746                       
747                       
748                       void pegasus_acceptor::bind()
749                       {
750                       
751                         PEGASUS_SOCKLEN_SIZE addr_size;
752                         struct sockaddr *addr;
753                         struct sockaddr_in addr_in;
754                       # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
755                         struct sockaddr_un addr_un;
756                       #endif 
757                       
758 mday         1.32       memset(&addr_in, 0, sizeof(addr_in));
759                         addr_in.sin_addr.s_addr = INADDR_ANY;
760                         addr_in.sin_family = AF_INET;
761                         addr_in.sin_port = htons(_portNumber);
762                         addr = (struct sockaddr*) &addr_in;
763                         addr_size = sizeof(addr_in);
764                         
765                         // first step: determine which kind of socket factory to initialize, 
766                         // then create the socket and bind it to an address
767                         if(_localConnection == true){
768                       #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
769                           unix_socket_factory sf;
770                           pegasus_socket temp(&sf);
771                           _listener = temp;
772                           
773                           memset(&addr_un, 0, sizeof(addr_un));
774 mday         1.33         addr_un.sun_family = AF_UNIX;
775                           strcpy(addr_un.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
776 chuck        1.38     #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
777                           AtoE(addr_un.sun_path);
778                       #endif
779 mday         1.32         addr = (struct sockaddr*) &addr_un;
780                           addr_size = sizeof(addr_un);
781                           _listener.socket(AF_UNIX, SOCK_STREAM, 0);
782                       #else 
783                           bsd_socket_factory sf;
784                           pegasus_socket temp(&sf);
785                           _listener = temp;
786                           _listener.socket(AF_UNIX, SOCK_STREAM, 0);
787                       #endif 
788                         }
789                         else if( _sslcontext != 0 ) {
790                       #ifdef PEGASUS_HAS_SSL
791                           ssl_socket_factory sf;
792 konrad.r     1.47         pegasus_socket temp(&sf, _sslcontext);
793 mday         1.32     #else
794                           bsd_socket_factory sf;
795 konrad.r     1.47         pegasus_socket temp(&sf);
796 mday         1.32     #endif
797                           _listener = temp;
798                           _listener.socket(PF_INET, SOCK_STREAM, 0);
799                         }
800                         else {
801                           bsd_socket_factory sf;
802                           pegasus_socket temp(&sf);
803                           _listener = temp;
804                           _listener.socket(PF_INET, SOCK_STREAM, 0);
805                         }
806                         
807                         _listener.bind((struct sockaddr*)addr, addr_size);
808                           
809                         // second step: listen on the socket 
810                       
811                         _listener.listen(5);
812                         
813                         // third step: add this listening socket to the monitor
814                       
815                          _monitor->tickle();
816                          _monitor->add_entry(_listener, LISTEN, this, this);
817 mday         1.32     }
818                       
819                       
820                       /** Unbind from the given port.
821                        */
822                       void pegasus_acceptor::unbind()
823                       {
824                         // remove the socket from the monitor
825                         _monitor->remove_entry((Sint32)_listener);
826                         
827                         // close the socket
828                         _listener.close();
829                       }
830                       
831                       
832                             /** Close the connection socket.
833                              */
834                       void pegasus_acceptor::closeConnectionSocket()
835                       {
836                         unbind();
837                       }
838 mday         1.32     
839                       
840                             /** Reopen the connection socket.
841                              */
842                       void pegasus_acceptor::reopenConnectionSocket()
843                       {
844                         bind();
845                       }
846                       
847                       
848                         /** Returns the number of outstanding requests
849                          */
850                       Uint32 pegasus_acceptor::getOutstandingRequestCount()
851                       {
852                         return _monitor->getOutstandingRequestCount();
853                       }
854                       
855                       Boolean pegasus_acceptor::operator ==(const pegasus_acceptor& pa)
856                       {
857                         if(this == &pa)
858                           return true;
859 mday         1.32       return false;
860                       }
861                       
862                       Boolean pegasus_acceptor::operator ==(void* pa)
863                       {
864                         if((void*)this == pa)
865                           return true;
866                         return false;
867                       }
868                       
869                       
870                       pegasus_acceptor* pegasus_acceptor::find_acceptor(Boolean local, Uint32 port)
871                       {
872                         pegasus_acceptor* temp = 0;
873                         
874                         try {
875                           acceptors.try_lock(pegasus_thread_self());
876                           temp = acceptors.next(temp);
877                           while(temp){
878                             if( local == true ){
879                       	if(temp->_localConnection){
880 mday         1.32     	  acceptors.unlock();
881                       	  return temp;
882                       	}
883                             }
884                             if(temp->_localConnection == local && temp->_portNumber ==port){
885                       	acceptors.unlock();
886                       	return temp;
887                             }
888                             temp = acceptors.next(temp);
889                           }
890                           acceptors.unlock();
891                         }
892                         catch(...){
893                         }
894                         return temp;
895                       }
896                       
897                       class m2e_rep;
898                       
899                       void pegasus_acceptor::accept_dispatch(monitor_2_entry *entry)
900                       {
901 mday         1.32       pegasus_acceptor* myself = (pegasus_acceptor*)entry->get_accept();
902                         
903                         HTTPConnection2* connection = new HTTPConnection2(entry->_rep->psock, myself->_outputMessageQueue);
904                         
905                         // set the entry's dispatch parameter to point to the connection object
906                         entry->set_dispatch ((void*)connection);
907                       
908 mday         1.36       monitor_2::insert_connection(connection);
909 mday         1.39       
910 mday         1.32     }
911                       
912 mike         1.2      
913                       PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2