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

  1 mike  1.2 //%/////////////////////////////////////////////////////////////////////////////
  2           //
  3 kumpf 1.20 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
  4 mike  1.2  // The Open Group, Tivoli Systems
  5            //
  6            // Permission is hereby granted, free of charge, to any person obtaining a copy
  7 kumpf 1.20 // of this software and associated documentation files (the "Software"), to
  8            // deal in the Software without restriction, including without limitation the
  9            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 10 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 11            // furnished to do so, subject to the following conditions:
 12            // 
 13 kumpf 1.20 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 14 mike  1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 15            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 16 kumpf 1.20 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 17            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 18            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 19 mike  1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 20            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 21            //
 22            //==============================================================================
 23            //
 24            // Author: Mike Brasher (mbrasher@bmc.com)
 25            //
 26            // Modified By:
 27            //         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
 28 kumpf 1.6  //         Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
 29 david 1.27 //         Dave Rosckes (rosckes@us.ibm.com)
 30 mike  1.2  //
 31            //%/////////////////////////////////////////////////////////////////////////////
 32            
 33            #include "Config.h"
 34 kumpf 1.15 #include "Constants.h"
 35 mike  1.2  #include <iostream>
 36            #include "Socket.h"
 37            
 38            #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC
 39 mday  1.12 #include <windows.h>
 40 mike  1.2  #else
 41            # include <cctype>
 42            # include <cstdlib>
 43            # include <errno.h>
 44            # include <fcntl.h>
 45            # include <netdb.h>
 46            # include <netinet/in.h>
 47            # include <arpa/inet.h>
 48            # include <sys/socket.h>
 49 kumpf 1.11 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
 50 kumpf 1.26 # include <unistd.h>
 51 kumpf 1.11 #  include <sys/un.h>
 52            # endif
 53 mike  1.2  #endif
 54            
 55            #include "Socket.h"
 56            #include "TLS.h"
 57            #include "HTTPAcceptor.h"
 58            #include "HTTPConnection.h"
 59 kumpf 1.19 #include "Tracer.h"
 60 humberto 1.30 #include <Pegasus/Common/MessageLoader.h> //l10n
 61 mike     1.2  
 62               PEGASUS_USING_STD;
 63               
 64               PEGASUS_NAMESPACE_BEGIN
 65               
 66               ////////////////////////////////////////////////////////////////////////////////
 67               //
 68               // HTTPAcceptorRep
 69               //
 70               ////////////////////////////////////////////////////////////////////////////////
 71               
 72 kumpf    1.25 class HTTPAcceptorRep
 73 mike     1.2  {
 74 kumpf    1.25 public:
 75                   HTTPAcceptorRep(Boolean local)
 76                   {
 77                       if (local)
 78                       {
 79 kumpf    1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
 80 kumpf    1.25             address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
 81                           address_size = sizeof(struct sockaddr_un);
 82 kumpf    1.11 #else
 83 kumpf    1.25             PEGASUS_ASSERT(false);
 84 kumpf    1.11 #endif
 85 david    1.27         }  
 86 kumpf    1.25         else
 87                       {
 88                           address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
 89                           address_size = sizeof(struct sockaddr_in);
 90                       }
 91                   }
 92               
 93                   struct sockaddr* address;
 94               
 95               #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
 96                  size_t address_size;
 97 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))
 98 kumpf        1.25    socklen_t address_size;
 99                   #else
100                      int address_size;
101                   #endif
102 mday         1.28       Mutex _connection_mut;
103                         
104                         Sint32 socket;
105                         Array<HTTPConnection*> connections;
106 mike         1.2  };
107                   
108                   ////////////////////////////////////////////////////////////////////////////////
109                   //
110                   // HTTPAcceptor
111                   //
112                   ////////////////////////////////////////////////////////////////////////////////
113                   
114 kumpf        1.25 HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
115                                              MessageQueue* outputMessageQueue,
116                                              Boolean localConnection,
117                                              Uint32 portNumber,
118 mike         1.2                             SSLContext * sslcontext)
119 kumpf        1.25    : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
120                        _monitor(monitor),
121                        _outputMessageQueue(outputMessageQueue),
122                        _rep(0),
123                        _entry_index(-1),
124                        _localConnection(localConnection),
125                        _portNumber(portNumber),
126                        _sslcontext(sslcontext)
127 mike         1.2  {
128 mday         1.7     Socket::initializeInterface();
129 mike         1.2  }
130                   
131                   HTTPAcceptor::~HTTPAcceptor()
132                   {
133 mday         1.7     unbind();
134 kumpf        1.25    // ATTN: Is this correct in a multi-HTTPAcceptor server?
135 mday         1.7     Socket::uninitializeInterface();
136 mike         1.2  }
137                   
138 mday         1.7  void HTTPAcceptor::handleEnqueue(Message *message)
139 mike         1.2  {
140 mday         1.7     if (! message)
141                         return;
142                      
143                      switch (message->getType())
144                      {
145                         case SOCKET_MESSAGE:
146                         {
147                   	 SocketMessage* socketMessage = (SocketMessage*)message;
148 mday         1.32  	 
149 mday         1.7  	 // If this is a connection request:
150                   
151                   	 if (socketMessage->socket == _rep->socket &&
152                   	     socketMessage->events | SocketMessage::READ)
153                   	 {
154                   	    _acceptConnection();
155                   	 }
156                   	 else
157                   	 {
158                   	    // ATTN! this can't happen!
159                   	 }
160                   
161                   	 break;
162                         }
163                   
164                         case CLOSE_CONNECTION_MESSAGE:
165                         {
166                   	 CloseConnectionMessage* closeConnectionMessage 
167                   	    = (CloseConnectionMessage*)message;
168                   
169 mday         1.28 	 _rep->_connection_mut.lock(pegasus_thread_self());
170                   	 
171 mday         1.7  	 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
172                   	 {
173                   	    HTTPConnection* connection = _rep->connections[i];	
174                   	    Sint32 socket = connection->getSocket();
175 mike         1.2  
176 mday         1.7  	    if (socket == closeConnectionMessage->socket)
177 mike         1.2  	    {
178 mday         1.7  	       _monitor->unsolicitSocketMessages(socket);
179                   	       _rep->connections.remove(i);
180 kumpf        1.17                delete connection;
181 mday         1.7  	       break;
182 mike         1.2  	    }
183 mday         1.7  	 }
184 mday         1.28 	 _rep->_connection_mut.unlock();
185 mday         1.7        }
186 mike         1.2  
187 kumpf        1.10       default:
188                         // ATTN: need unexpected message error!
189 mday         1.7        break;
190                      };
191 mike         1.2  
192 mday         1.7     delete message;
193                   }
194 mike         1.2  
195                   
196 mday         1.7  void HTTPAcceptor::handleEnqueue()
197                   {
198                      Message* message = dequeue();
199 mike         1.2  
200 mday         1.7     if (!message)
201                         return;
202                      
203                      handleEnqueue(message);
204 mike         1.2  
205                   }
206                   
207 kumpf        1.25 void HTTPAcceptor::bind()
208 mike         1.2  {
209 humberto     1.30    if (_rep){
210                      	//l10n
211                         //throw BindFailedException("HTTPAcceptor already bound");  
212                         String s0 = "HTTPAcceptor";
213                         MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
214                         						   "$0 already bound",
215                         						   s0);
216                         throw BindFailedException(parms);
217                      }
218 mike         1.2  
219 kumpf        1.25    _rep = new HTTPAcceptorRep(_localConnection);
220 mike         1.2  
221 mday         1.7     // bind address
222                      _bind();
223 mike         1.2  
224 mday         1.7     return;
225 mike         1.2  }
226                   
227                   /**
228 mday         1.7     _bind - creates a new server socket and bind socket to the port address.
229 kumpf        1.11    If PEGASUS_LOCAL_DOMAIN_SOCKET is defined, the port number is ignored and
230                      a domain socket is bound.
231 mike         1.2  */
232                   void HTTPAcceptor::_bind()
233                   {
234                   
235 mday         1.7     // Create address:
236 mike         1.2  
237 kumpf        1.25    memset(_rep->address, 0, sizeof(*_rep->address));
238 kumpf        1.6  
239 kumpf        1.25    if (_localConnection)
240                      {
241 kumpf        1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
242 kumpf        1.25        reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
243                              AF_UNIX;
244                          strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
245                                 PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
246                          ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
247 kumpf        1.6  #else
248 kumpf        1.25        PEGASUS_ASSERT(false);
249 kumpf        1.11 #endif
250 kumpf        1.25    }
251                      else
252                      {
253                          reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_addr.s_addr =
254                              INADDR_ANY;
255                          reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_family =
256                              AF_INET;
257                          reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_port =
258                              htons(_portNumber);
259                      }
260 mike         1.2  
261 mday         1.7     // Create socket:
262 mike         1.2      
263 kumpf        1.25    if (_localConnection)
264                      {
265                          _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
266                      }
267                      else
268                      {
269                          _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
270                      }
271 mike         1.2  
272 mday         1.7     if (_rep->socket < 0)
273                      {
274                         delete _rep;
275                         _rep = 0;
276 humberto     1.30       //l10n
277                         //throw BindFailedException("Failed to create socket");
278                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
279                         						   "Failed to create socket");
280                         throw BindFailedException(parms);
281 mday         1.7     }
282                   
283 mday         1.28 
284                   // set the close-on-exec bit for this file handle.
285                   // any unix that forks needs this bit set. 
286                   #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
287                      int sock_flags;
288                    if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
289                      {
290                          PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
291                                           "HTTPAcceptor: fcntl(F_GETFD) failed");
292                      }
293                      else
294                      {
295                         sock_flags |= FD_CLOEXEC;
296                         if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
297                         {
298                          PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
299                                           "HTTPAcceptor: fcntl(F_SETFD) failed");
300                         }
301                      }
302                   #endif 
303                   
304 mday         1.28 
305 mday         1.7     //
306                      // Set the socket option SO_REUSEADDR to reuse the socket address so
307                      // that we can rebind to a new socket using the same address when we
308                      // need to resume the cimom as a result of a timeout during a Shutdown
309                      // operation.
310                      //
311                      int opt=1;
312                      if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
313                   		  (char *)&opt, sizeof(opt)) < 0)
314                      {
315 mday         1.28       Socket::close(_rep->socket);
316 mday         1.7        delete _rep;
317                         _rep = 0;
318 humberto     1.30       //l10n
319                         //throw BindFailedException("Failed to set socket option");
320                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
321                         						   "Failed to set socket option");
322                         throw BindFailedException(parms);
323 mday         1.7     }
324                   
325                      // Bind socket to port:
326                   
327 kumpf        1.25    if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
328 mday         1.7     {
329                         Socket::close(_rep->socket);
330                         delete _rep;
331                         _rep = 0;
332 humberto     1.30       //l10n
333                         //throw BindFailedException("Failed to bind socket");
334                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
335                         						   "Failed to bind socket");
336                         throw BindFailedException(parms);
337 mday         1.7     }
338                   
339 kumpf        1.11    // Set up listening on the given socket:
340 mday         1.7  
341                      int const MAX_CONNECTION_QUEUE_LENGTH = 5;
342                   
343                      if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
344                      {
345                         Socket::close(_rep->socket);
346                         delete _rep;
347                         _rep = 0;
348 humberto     1.30       //l10n
349                         //throw BindFailedException("Failed to bind socket");
350                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
351                         						   "Failed to bind socket");
352                         throw BindFailedException(parms);
353 mday         1.7     }
354                   
355                      // Register to receive SocketMessages on this socket:
356                   
357 mday         1.21    if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
358 mday         1.7  	  _rep->socket,
359                   	  SocketMessage::READ | SocketMessage::EXCEPTION,
360 mday         1.16 	  getQueueId(), 
361 mday         1.21 	  Monitor::ACCEPTOR)))
362 mday         1.7     {
363                         Socket::close(_rep->socket);
364                         delete _rep;
365                         _rep = 0;
366 humberto     1.30       //l10n
367                         //throw BindFailedException("Failed to solicit socket messaeges");
368                         MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
369                         						   "Failed to solicit socket messaeges");
370                         throw BindFailedException(parms);
371 mday         1.7     }
372 mike         1.2  }
373                   
374                   /**
375 mday         1.7     closeConnectionSocket - close the server listening socket to disallow
376                      new client connections.
377 mike         1.2  */
378                   void HTTPAcceptor::closeConnectionSocket()
379                   {
380 mday         1.7     if (_rep)
381                      {
382                         // unregister the socket
383                         _monitor->unsolicitSocketMessages(_rep->socket);
384                   
385                         // close the socket
386                         Socket::close(_rep->socket);
387                      }
388 mike         1.2  }
389                   
390                   /**
391 mday         1.7     reopenConnectionSocket - creates a new server socket.
392 mike         1.2  */
393                   void HTTPAcceptor::reopenConnectionSocket()
394                   {
395 mday         1.7     if (_rep)
396                      {
397                         _bind();
398                      }
399 mike         1.2  }
400                   
401                   /**
402 mday         1.7     getOutstandingRequestCount - returns the number of outstanding requests.
403 mike         1.2  */
404                   Uint32 HTTPAcceptor::getOutstandingRequestCount()
405                   {
406 mday         1.28    Uint32 count = 0;
407                      
408                      _rep->_connection_mut.lock(pegasus_thread_self());
409 mday         1.7     if (_rep->connections.size() > 0)
410                      {
411                         HTTPConnection* connection = _rep->connections[0];	
412 mday         1.28       count = connection->getRequestCount();
413 mday         1.7     }
414 mday         1.28    _rep->_connection_mut.unlock();
415                      return count;
416 mike         1.2  }
417                   
418                   void HTTPAcceptor::unbind()
419                   {
420 mday         1.7     if (_rep)
421                      {
422                         Socket::close(_rep->socket);
423 kumpf        1.25 
424                         if (_localConnection)
425                         {
426                   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
427                            ::unlink(
428                                reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
429                   #else
430                            PEGASUS_ASSERT(false);
431                   #endif
432                         }
433                   
434 mday         1.7        delete _rep;
435                         _rep = 0;
436                      }
437 mike         1.2  }
438                   
439                   void HTTPAcceptor::destroyConnections()
440                   {
441 mday         1.28 
442                   
443 mday         1.7     // For each connection created by this object:
444 mike         1.2  
445 mday         1.28    _rep->_connection_mut.lock(pegasus_thread_self());
446 mday         1.7     for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
447                      {
448                         HTTPConnection* connection = _rep->connections[i];	
449                         Sint32 socket = connection->getSocket();
450 mike         1.2  
451 mday         1.7        // Unsolicit SocketMessages:
452 mike         1.2  
453 mday         1.7        _monitor->unsolicitSocketMessages(socket);
454 mike         1.2  
455 mday         1.7        // Destroy the connection (causing it to close):
456 mike         1.2  
457 kumpf        1.17       while (connection->refcount.value()) { }
458 mday         1.7        delete connection;
459                      }
460 mike         1.2  
461 mday         1.7     _rep->connections.clear();
462 mday         1.28    _rep->_connection_mut.unlock();
463 mike         1.2  }
464                   
465                   void HTTPAcceptor::_acceptConnection()
466                   {
467 mday         1.7     // This function cannot be called on an invalid socket!
468 mike         1.2  
469 mday         1.7     PEGASUS_ASSERT(_rep != 0);
470 mike         1.2  
471 mday         1.7     if (!_rep)
472                         return;
473 mike         1.2  
474 mday         1.7     // Accept the connection (populate the address):
475 mike         1.2  
476 kumpf        1.25    struct sockaddr* accept_address;
477                   #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
478                      size_t address_size;
479 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))
480 kumpf        1.25    socklen_t address_size;
481 mike         1.2  #else
482 kumpf        1.25    int address_size;
483 mike         1.2  #endif
484                   
485 kumpf        1.25    if (_localConnection)
486                      {
487                   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
488                          accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
489                          address_size = sizeof(struct sockaddr_un);
490 mike         1.2  #else
491 kumpf        1.25        PEGASUS_ASSERT(false);
492 mike         1.2  #endif
493 kumpf        1.25    }
494                      else
495                      {
496                          accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
497                          address_size = sizeof(struct sockaddr_in);
498                      }
499                   
500                      Sint32 socket = accept(_rep->socket, accept_address, &address_size);
501                   
502                      delete accept_address;
503 mike         1.2  
504 mday         1.7     if (socket < 0)
505                      {
506 david        1.27        Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
507                   		   "HTTPAcceptor - accept() failure.  errno: $0"
508                   		   ,errno);
509                   
510 kumpf        1.19        PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
511                                           "HTTPAcceptor: accept() failed");
512 mday         1.7        return;
513                      }
514 david        1.27 
515 mday         1.28 // set the close on exec flag 
516                   #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
517                      int sock_flags;
518                    if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
519                      {
520                          PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
521                                           "HTTPAcceptor: fcntl(F_GETFD) failed");
522                      }
523                      else
524                      {
525                         sock_flags |= FD_CLOEXEC;
526                         if (fcntl(socket, F_SETFD, sock_flags) < 0)
527                         {
528                          PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
529                                           "HTTPAcceptor: fcntl(F_SETFD) failed");
530                         }
531                      }
532                   #endif 
533                   
534                   
535 david        1.27    Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
536                   	       "HTTPAcceptor - accept() success.  Socket: $1"
537                   	       ,socket);
538 mike         1.2  
539 mday         1.7     // Create a new conection and add it to the connection list:
540 mike         1.2  
541 mday         1.7     MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);
542 kumpf        1.19    if (mp_socket->accept() < 0) 
543                      {
544                          PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
545                                           "HTTPAcceptor: SSL_accept() failed");
546 mday         1.7        return;
547                      }
548 mike         1.2  
549 mday         1.7     HTTPConnection* connection = new HTTPConnection(
550 mday         1.16       _monitor, mp_socket, this, static_cast<MessageQueue *>(_outputMessageQueue));
551 mike         1.2  
552 mday         1.7     // Solicit events on this new connection's socket:
553 mday         1.21    int index;
554                      
555 mday         1.22    if (-1 ==  (index = _monitor->solicitSocketMessages(
556 mday         1.7  	  socket,
557                   	  SocketMessage::READ | SocketMessage::EXCEPTION,
558 mday         1.21 	  connection->getQueueId(), Monitor::CONNECTION)) )
559 mday         1.7     {
560                         delete connection;
561                         Socket::close(socket);
562                      }
563 mike         1.2  
564 mday         1.7     // Save the socket for cleanup later:
565 mday         1.21    connection->_entry_index = index;
566 mday         1.28       _rep->_connection_mut.lock(pegasus_thread_self());
567 mday         1.7     _rep->connections.append(connection);
568 mday         1.28    _rep->_connection_mut.unlock();
569 mike         1.2  }
570 mday         1.32 
571                   AsyncDQueue<pegasus_acceptor> pegasus_acceptor::acceptors(true, 0);
572                   
573                   pegasus_acceptor::pegasus_acceptor(monitor_2* monitor, 
574                   				   MessageQueue* outputMessageQueue, 
575                   				   Boolean localConnection, 
576                   				   Uint32 portNumber,
577                   				   SSLContext* sslcontext)
578                     : _monitor(monitor), _outputMessageQueue(outputMessageQueue),
579                       _localConnection(localConnection), _portNumber(portNumber),
580                       _sslcontext(sslcontext), connections(true, 0)
581                   {
582                     
583                        Socket::initializeInterface();
584                        try {
585                          acceptors.insert_first(this);
586                        }
587                        catch(...){
588                        }
589                        
590                   }
591 mday         1.32 
592                   pegasus_acceptor::~pegasus_acceptor(void)
593                   {
594                      unbind();
595                      Socket::uninitializeInterface();
596                      try {
597                        acceptors.remove(this);
598                      }
599                      catch(...){
600                      }
601                      
602                   }
603                   
604                   
605                   void pegasus_acceptor::bind()
606                   {
607                   
608                     PEGASUS_SOCKLEN_SIZE addr_size;
609                     struct sockaddr *addr;
610                     struct sockaddr_in addr_in;
611                   # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
612 mday         1.32   struct sockaddr_un addr_un;
613                   #endif 
614                   
615                     memset(&addr_in, 0, sizeof(addr_in));
616                     addr_in.sin_addr.s_addr = INADDR_ANY;
617                     addr_in.sin_family = AF_INET;
618                     addr_in.sin_port = htons(_portNumber);
619                     addr = (struct sockaddr*) &addr_in;
620                     addr_size = sizeof(addr_in);
621                     
622                     // first step: determine which kind of socket factory to initialize, 
623                     // then create the socket and bind it to an address
624                     if(_localConnection == true){
625                   #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
626                       unix_socket_factory sf;
627                       pegasus_socket temp(&sf);
628                       _listener = temp;
629                       
630                       memset(&addr_un, 0, sizeof(addr_un));
631                       addr.sun_family = AF_UNIX;
632                       strcpy(addr.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
633 mday         1.32     addr = (struct sockaddr*) &addr_un;
634                       addr_size = sizeof(addr_un);
635                       _listener.socket(AF_UNIX, SOCK_STREAM, 0);
636                   #else 
637                       bsd_socket_factory sf;
638                       pegasus_socket temp(&sf);
639                       _listener = temp;
640                       _listener.socket(AF_UNIX, SOCK_STREAM, 0);
641                   #endif 
642                     }
643                     else if( _sslcontext != 0 ) {
644                   #ifdef PEGASUS_HAS_SSL
645                       ssl_socket_factory sf;
646                   #else
647                       bsd_socket_factory sf;
648                   #endif
649                       pegasus_socket temp(&sf);
650                       _listener = temp;
651                       _listener.socket(PF_INET, SOCK_STREAM, 0);
652                     }
653                     else {
654 mday         1.32     bsd_socket_factory sf;
655                       pegasus_socket temp(&sf);
656                       _listener = temp;
657                       _listener.socket(PF_INET, SOCK_STREAM, 0);
658                     }
659                     
660                     _listener.bind((struct sockaddr*)addr, addr_size);
661                       
662                     // second step: listen on the socket 
663                   
664                     _listener.listen(5);
665                     
666                     // third step: add this listening socket to the monitor
667                   
668                      _monitor->tickle();
669                      _monitor->add_entry(_listener, LISTEN, this, this);
670                   }
671                   
672                   
673                   /** Unbind from the given port.
674                    */
675 mday         1.32 void pegasus_acceptor::unbind()
676                   {
677                     // remove the socket from the monitor
678                     _monitor->remove_entry((Sint32)_listener);
679                     
680                     // close the socket
681                     _listener.close();
682                   }
683                   
684                   
685                         /** Close the connection socket.
686                          */
687                   void pegasus_acceptor::closeConnectionSocket()
688                   {
689                     unbind();
690                   }
691                   
692                   
693                         /** Reopen the connection socket.
694                          */
695                   void pegasus_acceptor::reopenConnectionSocket()
696 mday         1.32 {
697                     bind();
698                   }
699                   
700                   
701                     /** Returns the number of outstanding requests
702                      */
703                   Uint32 pegasus_acceptor::getOutstandingRequestCount()
704                   {
705                     return _monitor->getOutstandingRequestCount();
706                   }
707                   
708                   Boolean pegasus_acceptor::operator ==(const pegasus_acceptor& pa)
709                   {
710                     if(this == &pa)
711                       return true;
712                     return false;
713                   }
714                   
715                   Boolean pegasus_acceptor::operator ==(void* pa)
716                   {
717 mday         1.32   if((void*)this == pa)
718                       return true;
719                     return false;
720                   }
721                   
722                   
723                   pegasus_acceptor* pegasus_acceptor::find_acceptor(Boolean local, Uint32 port)
724                   {
725                     pegasus_acceptor* temp = 0;
726                     
727                     try {
728                       acceptors.try_lock(pegasus_thread_self());
729                       temp = acceptors.next(temp);
730                       while(temp){
731                         if( local == true ){
732                   	if(temp->_localConnection){
733                   	  acceptors.unlock();
734                   	  return temp;
735                   	}
736                         }
737                         if(temp->_localConnection == local && temp->_portNumber ==port){
738 mday         1.32 	acceptors.unlock();
739                   	return temp;
740                         }
741                         temp = acceptors.next(temp);
742                       }
743                       acceptors.unlock();
744                     }
745                     catch(...){
746                     }
747                     return temp;
748                   }
749                   
750                   class m2e_rep;
751                   
752                   void pegasus_acceptor::accept_dispatch(monitor_2_entry *entry)
753                   {
754                     pegasus_acceptor* myself = (pegasus_acceptor*)entry->get_accept();
755                     
756                     HTTPConnection2* connection = new HTTPConnection2(entry->_rep->psock, myself->_outputMessageQueue);
757                     
758                     // set the entry's dispatch parameter to point to the connection object
759 mday         1.32   entry->set_dispatch ((void*)connection);
760                   
761                     try {
762                       myself->connections.insert_first(connection);
763                     }
764                     catch(...){
765                     }
766                   }
767                   
768 mike         1.2  
769                   PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2