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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2