(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 mike  1.2  //
 30            //%/////////////////////////////////////////////////////////////////////////////
 31            
 32            #include "Config.h"
 33 kumpf 1.15 #include "Constants.h"
 34 mike  1.2  #include <iostream>
 35            #include "Socket.h"
 36            
 37            #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC
 38 mday  1.12 #include <windows.h>
 39 mike  1.2  #else
 40            # include <cctype>
 41            # include <unistd.h>
 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            #  include <sys/un.h>
 51            # endif
 52 mike  1.2  #endif
 53            
 54            #include "Socket.h"
 55            #include "TLS.h"
 56            #include "HTTPAcceptor.h"
 57            #include "HTTPConnection.h"
 58 kumpf 1.19 #include "Tracer.h"
 59 mike  1.2  
 60            PEGASUS_USING_STD;
 61            
 62            PEGASUS_NAMESPACE_BEGIN
 63            
 64            ////////////////////////////////////////////////////////////////////////////////
 65            //
 66            // HTTPAcceptorRep
 67            //
 68            ////////////////////////////////////////////////////////////////////////////////
 69            
 70            struct HTTPAcceptorRep
 71            {
 72 kumpf 1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
 73                  struct sockaddr_un address;
 74            #else
 75 mday  1.7        struct sockaddr_in address;
 76 kumpf 1.11 #endif
 77 mday  1.23.2.1       Mutex _connection_mut;
 78                      
 79 mday  1.7            Sint32 socket;
 80                      Array<HTTPConnection*> connections;
 81 mike  1.2      };
 82                
 83                ////////////////////////////////////////////////////////////////////////////////
 84                //
 85                // HTTPAcceptor
 86                //
 87                ////////////////////////////////////////////////////////////////////////////////
 88                
 89 kumpf 1.18     HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue)
 90 kumpf 1.15        : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), 
 91 mday  1.7           _monitor(monitor), _outputMessageQueue(outputMessageQueue), 
 92 mday  1.21          _rep(0), _sslcontext(NULL), _entry_index(-1)
 93 mike  1.2      {
 94 mday  1.5      
 95 mday  1.23.2.1    _inet_address[0] = 0x00;
 96 mday  1.7         Socket::initializeInterface();
 97 mike  1.2      }
 98                
 99 kumpf 1.18     HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue,
100 mike  1.2                                 SSLContext * sslcontext)
101 kumpf 1.15        :       Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), 
102 mday  1.16     	   _monitor(monitor), _outputMessageQueue(outputMessageQueue), 
103                	   _rep(0),
104 mday  1.21     	   _sslcontext(sslcontext),
105                	   _entry_index(-1)
106 mike  1.2      {
107 mday  1.23.2.1    _inet_address[0] = 0x00;
108                   Socket::initializeInterface();
109                }
110                
111                HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue,
112                                           SSLContext * sslcontext, 
113                			   char *inet_address)
114                   :       Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), 
115                	   _monitor(monitor), _outputMessageQueue(outputMessageQueue), 
116                	   _rep(0),
117                	   _sslcontext(sslcontext),
118                	   _entry_index(-1)
119                {
120                   strncpy(_inet_address, inet_address, 16);
121                   _inet_address[16] = 0x00;
122 mday  1.7         Socket::initializeInterface();
123 mike  1.2      }
124                
125                HTTPAcceptor::~HTTPAcceptor()
126                {
127 mday  1.7         unbind();
128                   Socket::uninitializeInterface();
129 mike  1.2      }
130                
131 mday  1.7      void HTTPAcceptor::handleEnqueue(Message *message)
132 mike  1.2      {
133 mday  1.7         if (! message)
134                      return;
135                   
136                   switch (message->getType())
137                   {
138                      case SOCKET_MESSAGE:
139                      {
140                	 SocketMessage* socketMessage = (SocketMessage*)message;
141 mday  1.16     	 
142 mday  1.7      	 // If this is a connection request:
143                
144                	 if (socketMessage->socket == _rep->socket &&
145                	     socketMessage->events | SocketMessage::READ)
146                	 {
147                	    _acceptConnection();
148                	 }
149                	 else
150                	 {
151                	    // ATTN! this can't happen!
152                	 }
153                
154                	 break;
155                      }
156                
157                      case CLOSE_CONNECTION_MESSAGE:
158                      {
159                	 CloseConnectionMessage* closeConnectionMessage 
160                	    = (CloseConnectionMessage*)message;
161                
162 mday  1.23.2.1 	 _rep->_connection_mut.lock(pegasus_thread_self());
163                	 
164 mday  1.7      	 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
165                	 {
166                	    HTTPConnection* connection = _rep->connections[i];	
167                	    Sint32 socket = connection->getSocket();
168 mday  1.23.2.1 	    
169 mday  1.7      	    if (socket == closeConnectionMessage->socket)
170 mike  1.2      	    {
171 mday  1.7      	       _monitor->unsolicitSocketMessages(socket);
172                	       _rep->connections.remove(i);
173 kumpf 1.17                    delete connection;
174 mday  1.23.2.1 	       PEGASUS_STD(cout) << "Closing HTTP Connection; Current Connection Table Size: " <<
175                	       _rep->connections.size() << PEGASUS_STD(endl);
176 mday  1.7      	       break;
177 mike  1.2      	    }
178 mday  1.7      	 }
179 mday  1.23.2.1 	 _rep->_connection_mut.unlock();
180                
181 mday  1.7            }
182 mike  1.2      
183 kumpf 1.10           default:
184                      // ATTN: need unexpected message error!
185 mday  1.7            break;
186                   };
187 mike  1.2      
188 mday  1.7         delete message;
189                }
190 mike  1.2      
191                
192 mday  1.7      void HTTPAcceptor::handleEnqueue()
193                {
194                   Message* message = dequeue();
195 mike  1.2      
196 mday  1.7         if (!message)
197                      return;
198                   
199                   handleEnqueue(message);
200 mike  1.2      
201                }
202                
203                void HTTPAcceptor::bind(Uint32 portNumber)
204                {
205 mday  1.7         if (_rep)
206 kumpf 1.23           throw BindFailedException("HTTPAcceptor already bound");
207 mike  1.2      
208 mday  1.7         _rep = new HTTPAcceptorRep;
209 mike  1.2      
210 mday  1.7         _portNumber = portNumber;
211 mike  1.2      
212 mday  1.7         // bind address
213                   _bind();
214 mike  1.2      
215 mday  1.7         return;
216 mike  1.2      }
217                
218                /**
219 mday  1.7         _bind - creates a new server socket and bind socket to the port address.
220 kumpf 1.11        If PEGASUS_LOCAL_DOMAIN_SOCKET is defined, the port number is ignored and
221                   a domain socket is bound.
222 mike  1.2      */
223                void HTTPAcceptor::_bind()
224                {
225                
226 mday  1.7         // Create address:
227 mike  1.2      
228 mday  1.7         memset(&_rep->address, 0, sizeof(_rep->address));
229 kumpf 1.6      
230 kumpf 1.11     #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
231                   _rep->address.sun_family = AF_UNIX;
232                   strcpy(_rep->address.sun_path, "/var/opt/wbem/cimxml.socket");
233                   ::unlink(_rep->address.sun_path);
234 kumpf 1.6      #else
235 mday  1.23.2.1    if(_inet_address[0] != 0x00)
236                   {
237                      _rep->address.sin_addr.s_addr = inet_addr(_inet_address);
238                      cout << "binding to " << _inet_address << endl;
239                      
240                   }
241                   else 
242                   {
243                      _rep->address.sin_addr.s_addr = INADDR_ANY;
244                   }
245                   
246 mday  1.7         _rep->address.sin_family = AF_INET;
247                   _rep->address.sin_port = htons(_portNumber);
248 kumpf 1.11     #endif
249 mike  1.2      
250 mday  1.7         // Create socket:
251 mike  1.2          
252 kumpf 1.11     #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
253                   _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
254                #else
255 mday  1.7         _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
256 kumpf 1.11     #endif
257 mike  1.2      
258 mday  1.7         if (_rep->socket < 0)
259                   {
260                      delete _rep;
261                      _rep = 0;
262 kumpf 1.23           throw BindFailedException("Failed to create socket");
263 mday  1.7         }
264                
265                   //
266                   // Set the socket option SO_REUSEADDR to reuse the socket address so
267                   // that we can rebind to a new socket using the same address when we
268                   // need to resume the cimom as a result of a timeout during a Shutdown
269                   // operation.
270                   //
271                   int opt=1;
272                   if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
273                		  (char *)&opt, sizeof(opt)) < 0)
274                   {
275                      delete _rep;
276                      _rep = 0;
277 kumpf 1.23           throw BindFailedException("Failed to set socket option");
278 mday  1.7         }
279                
280                   // Bind socket to port:
281                
282                   if (::bind(_rep->socket, 
283 kumpf 1.10     	      reinterpret_cast<struct sockaddr*>(&_rep->address), 
284 mday  1.7      	      sizeof(_rep->address)) < 0)
285                   {
286                      Socket::close(_rep->socket);
287                      delete _rep;
288                      _rep = 0;
289 kumpf 1.23           throw BindFailedException("Failed to bind socket");
290 mday  1.7         }
291                
292 kumpf 1.11        // Set up listening on the given socket:
293 mday  1.7      
294                   int const MAX_CONNECTION_QUEUE_LENGTH = 5;
295                
296                   if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
297                   {
298                      Socket::close(_rep->socket);
299                      delete _rep;
300                      _rep = 0;
301 kumpf 1.23           throw BindFailedException("Failed to bind socket");
302 mday  1.7         }
303                
304                   // Register to receive SocketMessages on this socket:
305                
306 mday  1.21        if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
307 mday  1.7      	  _rep->socket,
308                	  SocketMessage::READ | SocketMessage::EXCEPTION,
309 mday  1.16     	  getQueueId(), 
310 mday  1.21     	  Monitor::ACCEPTOR)))
311 mday  1.7         {
312                      Socket::close(_rep->socket);
313                      delete _rep;
314                      _rep = 0;
315 kumpf 1.23           throw BindFailedException("Failed to solicit socket messaeges");
316 mday  1.7         }
317 mike  1.2      }
318                
319                /**
320 mday  1.7         closeConnectionSocket - close the server listening socket to disallow
321                   new client connections.
322 mike  1.2      */
323                void HTTPAcceptor::closeConnectionSocket()
324                {
325 mday  1.7         if (_rep)
326                   {
327                      // unregister the socket
328                      _monitor->unsolicitSocketMessages(_rep->socket);
329                
330                      // close the socket
331                      Socket::close(_rep->socket);
332                   }
333 mike  1.2      }
334                
335                /**
336 mday  1.7         reopenConnectionSocket - creates a new server socket.
337 mike  1.2      */
338                void HTTPAcceptor::reopenConnectionSocket()
339                {
340 mday  1.7         if (_rep)
341                   {
342                      _bind();
343                   }
344 mike  1.2      }
345                
346                /**
347 mday  1.7         getOutstandingRequestCount - returns the number of outstanding requests.
348 mike  1.2      */
349                Uint32 HTTPAcceptor::getOutstandingRequestCount()
350                {
351 mday  1.23.2.1    Uint32 count = 0;
352                   
353                   _rep->_connection_mut.lock(pegasus_thread_self());
354 mday  1.7         if (_rep->connections.size() > 0)
355                   {
356                      HTTPConnection* connection = _rep->connections[0];	
357 mday  1.23.2.1       count = connection->getRequestCount();
358 mday  1.7         }
359 mday  1.23.2.1    _rep->_connection_mut.unlock();
360                   return count;
361                   
362 mike  1.2      }
363                
364                void HTTPAcceptor::unbind()
365                {
366 mday  1.7         if (_rep)
367                   {
368                      Socket::close(_rep->socket);
369                      delete _rep;
370                      _rep = 0;
371                   }
372 mike  1.2      }
373                
374                void HTTPAcceptor::destroyConnections()
375                {
376 mday  1.7         // For each connection created by this object:
377 mike  1.2      
378 mday  1.23.2.1    _rep->_connection_mut.lock(pegasus_thread_self());
379 mday  1.7         for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
380                   {
381                      HTTPConnection* connection = _rep->connections[i];	
382                      Sint32 socket = connection->getSocket();
383 mike  1.2      
384 mday  1.7            // Unsolicit SocketMessages:
385 mike  1.2      
386 mday  1.7            _monitor->unsolicitSocketMessages(socket);
387 mike  1.2      
388 mday  1.7            // Destroy the connection (causing it to close):
389 mike  1.2      
390 kumpf 1.17           while (connection->refcount.value()) { }
391 mday  1.7            delete connection;
392                   }
393 mike  1.2      
394 mday  1.7         _rep->connections.clear();
395 mday  1.23.2.1    _rep->_connection_mut.unlock();
396 mike  1.2      }
397                
398                void HTTPAcceptor::_acceptConnection()
399                {
400 mday  1.7         // This function cannot be called on an invalid socket!
401 mike  1.2      
402 mday  1.7         PEGASUS_ASSERT(_rep != 0);
403 mike  1.2      
404 mday  1.7         if (!_rep)
405                      return;
406 mike  1.2      
407 mday  1.7         // Accept the connection (populate the address):
408 mike  1.2      
409 mday  1.7         sockaddr_in address;
410 mike  1.2      
411 sage  1.4      #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX)
412 mday  1.7         size_t n = sizeof(address);
413 mike  1.2      #else
414 mday  1.7         int n = sizeof(address);
415 mike  1.2      #endif
416                
417 mday  1.23.2.1 
418 kumpf 1.14     #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
419 mday  1.7         Sint32 socket = accept(
420                      _rep->socket, (struct sockaddr*)&address, (socklen_t *)&n);
421 mike  1.2      #else
422 kumpf 1.10        Sint32 socket = accept(_rep->socket, reinterpret_cast<struct sockaddr*>(&address), &n);
423 mike  1.2      #endif
424                
425 mday  1.23.2.1 
426                
427 mday  1.7         if (socket < 0)
428                   {
429 kumpf 1.19            PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
430                                        "HTTPAcceptor: accept() failed");
431 mday  1.7            return;
432                   }
433 mday  1.23.2.1 #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
434                   if( _inet_address[0] != 0x00)
435                   {
436                      if( 1023 < htons(address.sin_port) )
437                      {
438                	 shutdown(socket, 2);
439                	 Socket::close(socket);
440                	 return;
441                      }
442                   }
443                   
444                #endif
445 mday  1.7         // Create a new conection and add it to the connection list:
446 mike  1.2      
447 mday  1.7         MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);
448 kumpf 1.19        if (mp_socket->accept() < 0) 
449                   {
450                       PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
451                                        "HTTPAcceptor: SSL_accept() failed");
452 mday  1.7            return;
453                   }
454 mike  1.2      
455 mday  1.7         HTTPConnection* connection = new HTTPConnection(
456 mday  1.16           _monitor, mp_socket, this, static_cast<MessageQueue *>(_outputMessageQueue));
457 mike  1.2      
458 mday  1.7         // Solicit events on this new connection's socket:
459 mday  1.21        int index;
460                   
461 mday  1.23.2.1    if (! (index = _monitor->solicitSocketMessages(
462 mday  1.7      	  socket,
463                	  SocketMessage::READ | SocketMessage::EXCEPTION,
464 mday  1.21     	  connection->getQueueId(), Monitor::CONNECTION)) )
465 mday  1.7         {
466                      delete connection;
467                      Socket::close(socket);
468                   }
469 mike  1.2      
470 mday  1.7         // Save the socket for cleanup later:
471 mday  1.21        connection->_entry_index = index;
472 mday  1.23.2.1       _rep->_connection_mut.lock(pegasus_thread_self());
473 mday  1.7         _rep->connections.append(connection);
474 mday  1.23.2.1    _rep->_connection_mut.unlock();
475                   PEGASUS_STD(cout) << "Creating new HTTP Connection; Current Connection Table Size: " <<
476                   _rep->connections.size() << " entries" << endl;
477                   
478 mike  1.2      }
479                
480                PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2