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

  1 karl  1.80 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.52 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.43 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.52 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.57 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.80 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15 kumpf 1.20 // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20 karl  1.80 // 
 21 kumpf 1.20 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 mike  1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24 kumpf 1.20 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27 mike  1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31            //
 32            // Author: Mike Brasher (mbrasher@bmc.com)
 33            //
 34            // Modified By:
 35 david.dillard 1.64 //          Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
 36                    //          Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
 37                    //          Dave Rosckes (rosckes@us.ibm.com)
 38                    //          Denise Eckstein (denise.eckstein@hp.com)
 39                    //          Alagaraja Ramasubramanian (alags_raj@in.ibm.com) for Bug#1090
 40                    //          Amit Arora, IBM (amita@in.ibm.com) for Bug#2541
 41                    //          Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 42                    //          Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)
 43                    //          Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2065
 44 david.dillard 1.74 //          David Dillard, Symantec Corp. (david_dillard@symantec.com)
 45 j.alex        1.67 //          John Alex, IBM (johnalex@us.ibm.com) for Bug#3312
 46 mike          1.2  //
 47                    //%/////////////////////////////////////////////////////////////////////////////
 48                    
 49                    #include "Config.h"
 50 kumpf         1.15 #include "Constants.h"
 51 mike          1.2  #include <iostream>
 52                    
 53 mike          1.82 #include "Network.h"
 54 mike          1.2  #include "Socket.h"
 55                    #include "TLS.h"
 56                    #include "HTTPAcceptor.h"
 57                    #include "HTTPConnection.h"
 58 kumpf         1.19 #include "Tracer.h"
 59 humberto      1.30 #include <Pegasus/Common/MessageLoader.h> //l10n
 60 mike          1.2  
 61 chuck         1.38 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
 62 mike          1.84.2.1 #include "EBCDIC_OS400.h"
 63 chuck         1.38     #endif
 64                        
 65 mike          1.79     
 66 mike          1.2      PEGASUS_USING_STD;
 67                        
 68                        PEGASUS_NAMESPACE_BEGIN
 69                        
 70 david.dillard 1.65     
 71 a.arora       1.51     static int MAX_CONNECTION_QUEUE_LENGTH = -1;
 72                        
 73 mike          1.2      ////////////////////////////////////////////////////////////////////////////////
 74                        //
 75                        // HTTPAcceptorRep
 76                        //
 77                        ////////////////////////////////////////////////////////////////////////////////
 78                        
 79 kumpf         1.25     class HTTPAcceptorRep
 80 mike          1.2      {
 81 kumpf         1.25     public:
 82                            HTTPAcceptorRep(Boolean local)
 83                            {
 84                                if (local)
 85                                {
 86 h.sterling    1.63     #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
 87 kumpf         1.25                 address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
 88                                    address_size = sizeof(struct sockaddr_un);
 89 kumpf         1.11     #else
 90 kumpf         1.25                 PEGASUS_ASSERT(false);
 91 kumpf         1.11     #endif
 92 david.dillard 1.64             }
 93 kumpf         1.25             else
 94                                {
 95                                    address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
 96                                    address_size = sizeof(struct sockaddr_in);
 97                                }
 98                            }
 99 konrad.r      1.69         ~HTTPAcceptorRep()
100                            {
101 david.dillard 1.73             delete address;
102 konrad.r      1.69         }
103 kumpf         1.25         struct sockaddr* address;
104                        
105 mike          1.83         SocketLength address_size;
106 mike          1.77         Mutex _connection_mut;
107 david.dillard 1.64     
108 mike          1.82         SocketHandle socket;
109 mike          1.77         Array<HTTPConnection*> connections;
110 mike          1.2      };
111                        
112 mike          1.79     //------------------------------------------------------------------------------
113                        //
114                        // _setTCPNoDelay()
115                        //
116                        //------------------------------------------------------------------------------
117                        
118 mike          1.82     inline void _setTCPNoDelay(SocketHandle socket)
119 mike          1.79     {
120                            // This function disables "Nagle's Algorithm" also known as "the TCP delay
121                            // algorithm", which causes read operations to obtain whatever data is
122                            // already in the input queue and then wait a little longer to see if 
123                            // more data arrives. This algorithm optimizes the case in which data is 
124                            // sent in only one direction but severely impairs performance of round 
125                            // trip servers. Disabling TCP delay is a standard technique for round 
126                            // trip servers.
127                        
128                           int opt = 1;
129                           setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
130                        }
131                        
132 mike          1.2      ////////////////////////////////////////////////////////////////////////////////
133                        //
134                        // HTTPAcceptor
135                        //
136                        ////////////////////////////////////////////////////////////////////////////////
137                        
138 kumpf         1.25     HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
139                                                   MessageQueue* outputMessageQueue,
140                                                   Boolean localConnection,
141                                                   Uint32 portNumber,
142 kumpf         1.49                                SSLContext * sslcontext,
143 nag.boranna   1.59                                Boolean exportConnection,
144                                                   ReadWriteSem* sslContextObjectLock)
145 kumpf         1.25        : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
146                             _monitor(monitor),
147                             _outputMessageQueue(outputMessageQueue),
148                             _rep(0),
149                             _entry_index(-1),
150                             _localConnection(localConnection),
151                             _portNumber(portNumber),
152 kumpf         1.49          _sslcontext(sslcontext),
153 nag.boranna   1.59          _exportConnection(exportConnection),
154                             _sslContextObjectLock(sslContextObjectLock)
155 mike          1.2      {
156 mday          1.7         Socket::initializeInterface();
157 david.dillard 1.64     
158 a.arora       1.51        /*
159                                Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH differently.  Some platforms interpret
160                                the value literally, while others multiply a fudge factor. When the server is under
161                                stress from multiple clients with multiple requests, toggling this number may prevent clients from
162                                being dropped.  Instead of hard coding the value, we allow an environment variable to be set which
163                                specifies a number greater than the maximum concurrent client connections possible.  If this environment
164                                var is not specified, then MAX_CONNECTION_QUEUE_LENGTH = 15.
165                           */
166                        
167                        //To engage runtime backlog queue length: uncomment the following block AND comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
168                        
169                        /*
170                           if(MAX_CONNECTION_QUEUE_LENGTH == -1){
171                        #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
172                        #pragma convert(37)
173 h.sterling    1.63         const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
174                            EtoA(env);
175 a.arora       1.51     #pragma convert(0)
176                        #else
177 h.sterling    1.63         const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
178 a.arora       1.51     #endif
179 h.sterling    1.63         if(!env){
180                                MAX_CONNECTION_QUEUE_LENGTH = 15;
181 david.dillard 1.64         }else{
182 h.sterling    1.63             char *end = NULL;
183                                MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
184                                if(*end)
185                                    MAX_CONNECTION_QUEUE_LENGTH = 15;
186                                cout << " MAX_CONNECTION_QUEUE_LENGTH = " << MAX_CONNECTION_QUEUE_LENGTH << endl;
187                            }
188 a.arora       1.51        }
189                        */
190                           MAX_CONNECTION_QUEUE_LENGTH = 15;
191 david.dillard 1.64     
192 mike          1.2      }
193                        
194                        HTTPAcceptor::~HTTPAcceptor()
195                        {
196 konrad.r      1.70        destroyConnections();
197 mday          1.7         unbind();
198 kumpf         1.25        // ATTN: Is this correct in a multi-HTTPAcceptor server?
199 mday          1.7         Socket::uninitializeInterface();
200 mike          1.2      }
201                        
202 mday          1.7      void HTTPAcceptor::handleEnqueue(Message *message)
203 mike          1.2      {
204 mday          1.7         if (! message)
205                              return;
206 david.dillard 1.64     
207 konrad.r      1.68        PEGASUS_ASSERT(_rep != 0);
208 mday          1.7         switch (message->getType())
209                           {
210                              case SOCKET_MESSAGE:
211                              {
212 h.sterling    1.63          SocketMessage* socketMessage = (SocketMessage*)message;
213 david.dillard 1.64     
214 h.sterling    1.63          // If this is a connection request:
215                        
216                             if (socketMessage->socket == _rep->socket &&
217                                 socketMessage->events & SocketMessage::READ)
218                             {
219                                _acceptConnection();
220                             }
221                             else
222                             {
223                                // ATTN! this can't happen!
224 kumpf         1.44                 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
225                                      "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");
226 h.sterling    1.63          }
227 mday          1.7      
228 h.sterling    1.63          break;
229 mday          1.7            }
230                        
231                              case CLOSE_CONNECTION_MESSAGE:
232                              {
233 david.dillard 1.64          CloseConnectionMessage* closeConnectionMessage
234 h.sterling    1.63             = (CloseConnectionMessage*)message;
235                        
236                             AutoMutex autoMut(_rep->_connection_mut);
237 david.dillard 1.64     
238 h.sterling    1.63          for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
239                             {
240 david.dillard 1.64             HTTPConnection* connection = _rep->connections[i];
241 mike          1.82             SocketHandle socket = connection->getSocket();
242 mday          1.7      
243 h.sterling    1.63             if (socket == closeConnectionMessage->socket)
244                                {
245                                   _monitor->unsolicitSocketMessages(socket);
246                                   _rep->connections.remove(i);
247 kumpf         1.17                    delete connection;
248 h.sterling    1.63                break;
249                                }
250                             }
251 david.dillard 1.64     
252 h.sterling    1.63          break;
253 mday          1.7            }
254 mike          1.2      
255 kumpf         1.10           default:
256                              // ATTN: need unexpected message error!
257 kumpf         1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
258                                   "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
259 mday          1.7            break;
260                           };
261 mike          1.2      
262 mday          1.7         delete message;
263                        }
264 mike          1.2      
265                        
266 mday          1.7      void HTTPAcceptor::handleEnqueue()
267                        {
268                           Message* message = dequeue();
269 mike          1.2      
270 mday          1.7         if (!message)
271 kumpf         1.44        {
272                              Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
273                                   "HTTPAcceptor::handleEnqueue(): No message on queue.");
274 mday          1.7            return;
275 kumpf         1.44        }
276 david.dillard 1.64     
277 mday          1.7         handleEnqueue(message);
278 mike          1.2      
279                        }
280                        
281 kumpf         1.25     void HTTPAcceptor::bind()
282 mike          1.2      {
283 humberto      1.30        if (_rep){
284 h.sterling    1.63         //l10n
285 david.dillard 1.64           //throw BindFailedException("HTTPAcceptor already bound");
286 humberto      1.34     
287 humberto      1.30           MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
288 h.sterling    1.63                        "HTTPAcceptor already bound");
289 humberto      1.34     
290 kumpf         1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
291                                   "HTTPAcceptor::bind: HTTPAcceptor already bound.");
292 humberto      1.30           throw BindFailedException(parms);
293                           }
294 mike          1.2      
295 kumpf         1.25        _rep = new HTTPAcceptorRep(_localConnection);
296 mike          1.2      
297 mday          1.7         // bind address
298                           _bind();
299 mike          1.2      
300 mday          1.7         return;
301 mike          1.2      }
302                        
303                        /**
304 mday          1.7         _bind - creates a new server socket and bind socket to the port address.
305 h.sterling    1.63        If PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET is not defined, the port number is ignored and
306 kumpf         1.11        a domain socket is bound.
307 mike          1.2      */
308                        void HTTPAcceptor::_bind()
309                        {
310                        
311 konrad.r      1.68        PEGASUS_ASSERT(_rep != 0);
312 mday          1.7         // Create address:
313 mike          1.2      
314 kumpf         1.25        memset(_rep->address, 0, sizeof(*_rep->address));
315 kumpf         1.6      
316 kumpf         1.25        if (_localConnection)
317                           {
318 h.sterling    1.63     #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
319 kumpf         1.25            reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
320                                   AF_UNIX;
321                               strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
322                                      PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
323 chuck         1.38     #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
324                               AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
325                        #endif
326 kumpf         1.25            ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
327 kumpf         1.6      #else
328 kumpf         1.25            PEGASUS_ASSERT(false);
329 kumpf         1.11     #endif
330 kumpf         1.25        }
331                           else
332                           {
333                               reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_addr.s_addr =
334                                   INADDR_ANY;
335                               reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_family =
336                                   AF_INET;
337                               reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_port =
338                                   htons(_portNumber);
339                           }
340 mike          1.2      
341 mday          1.7         // Create socket:
342 david.dillard 1.64     
343 kumpf         1.25        if (_localConnection)
344                           {
345                               _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
346                           }
347                           else
348                           {
349                               _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
350 mike          1.79     
351                               _setTCPNoDelay(_rep->socket);
352 kumpf         1.25        }
353 mike          1.2      
354 mday          1.7         if (_rep->socket < 0)
355                           {
356                              delete _rep;
357                              _rep = 0;
358 humberto      1.30           //l10n
359                              //throw BindFailedException("Failed to create socket");
360                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
361 h.sterling    1.63                        "Failed to create socket");
362 kumpf         1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
363                                   "HTTPAcceptor::_bind _rep->socket < 0");
364 humberto      1.30           throw BindFailedException(parms);
365 mday          1.7         }
366                        
367 mday          1.28     
368                        // set the close-on-exec bit for this file handle.
369 david.dillard 1.64     // any unix that forks needs this bit set.
370 david.dillard 1.78     #if !defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_OS_VMS)
371 mday          1.28        int sock_flags;
372                         if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
373                           {
374 kumpf         1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
375                                          "HTTPAcceptor::_bind: fcntl(F_GETFD) failed");
376 mday          1.28        }
377                           else
378                           {
379                              sock_flags |= FD_CLOEXEC;
380                              if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
381                              {
382 kumpf         1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
383                                          "HTTPAcceptor::_bind: fcntl(F_SETFD) failed");
384 mday          1.28           }
385                           }
386 david.dillard 1.64     #endif
387 mday          1.28     
388                        
389 mday          1.7         //
390                           // Set the socket option SO_REUSEADDR to reuse the socket address so
391                           // that we can rebind to a new socket using the same address when we
392                           // need to resume the cimom as a result of a timeout during a Shutdown
393                           // operation.
394                           //
395                           int opt=1;
396                           if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
397 h.sterling    1.63               (char *)&opt, sizeof(opt)) < 0)
398 mday          1.7         {
399 mday          1.28           Socket::close(_rep->socket);
400 mday          1.7            delete _rep;
401                              _rep = 0;
402 humberto      1.30           //l10n
403                              //throw BindFailedException("Failed to set socket option");
404                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
405 h.sterling    1.63                        "Failed to set socket option");
406 kumpf         1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
407                                           "HTTPAcceptor::_bind: Failed to set socket option.");
408 humberto      1.30           throw BindFailedException(parms);
409 mday          1.7         }
410                        
411 david.dillard 1.64     
412                           //
413 mday          1.7         // Bind socket to port:
414 david.dillard 1.64        //
415 kumpf         1.25        if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
416 mday          1.7         {
417                              Socket::close(_rep->socket);
418                              delete _rep;
419                              _rep = 0;
420 humberto      1.30           //l10n
421                              //throw BindFailedException("Failed to bind socket");
422                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
423 h.sterling    1.63                        "Failed to bind socket");
424 kumpf         1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
425                                                "HTTPAcceptor::_bind: Failed to bind socket.");
426 humberto      1.30           throw BindFailedException(parms);
427 mday          1.7         }
428                        
429 david.dillard 1.64     
430                           //
431                           // Get the actual port value used if the caller specified a port value of 0.
432                           //
433                           if ( _portNumber == 0 )
434                           {
435                              sockaddr_in buf;
436 mike          1.83           SocketLength bufSize = sizeof(buf);
437 david.dillard 1.64           if ( getsockname(_rep->socket, reinterpret_cast<sockaddr *>(&buf), &bufSize) == 0 )
438                              {
439                                  _portNumber = ntohs(buf.sin_port);
440                              }
441                           }
442                        
443                        
444 w.otsuka      1.54        //
445                           //  Change permissions on Linux local domain socket to allow writes by others.
446                           //
447 h.sterling    1.63     #if !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET) && defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
448 w.otsuka      1.54        if (_localConnection)
449                           {
450 david.dillard 1.64          if (::chmod( PEGASUS_LOCAL_DOMAIN_SOCKET_PATH,
451                                          S_IRUSR | S_IWUSR | S_IXUSR |
452 w.otsuka      1.54                       S_IRGRP | S_IWGRP | S_IXGRP |
453                                          S_IROTH | S_IWOTH | S_IXOTH ) < 0 )
454                             {
455                               Socket::close(_rep->socket);
456                               delete _rep;
457                               _rep = 0;
458                               //l10n
459                               //throw BindFailedException("Failed to bind socket");
460                               MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
461 h.sterling    1.63                        "Failed to bind socket");
462 w.otsuka      1.54            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
463                                      "HTTPAcceptor::_bind: Failed to set domain socket permissions.");
464                               throw BindFailedException(parms);
465                             }
466                           }
467                        #endif
468                        
469 kumpf         1.11        // Set up listening on the given socket:
470 mday          1.7      
471 a.arora       1.51        //int const MAX_CONNECTION_QUEUE_LENGTH = 15;
472 mday          1.7      
473                           if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
474                           {
475                              Socket::close(_rep->socket);
476                              delete _rep;
477                              _rep = 0;
478 humberto      1.30           //l10n
479                              //throw BindFailedException("Failed to bind socket");
480                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
481 h.sterling    1.63                        "Failed to bind socket");
482 kumpf         1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
483                                          "HTTPAcceptor::_bind: Failed to bind socket(1).");
484 humberto      1.30           throw BindFailedException(parms);
485 mday          1.7         }
486                        
487                           // Register to receive SocketMessages on this socket:
488                        
489 mday          1.21        if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
490 h.sterling    1.63           _rep->socket,
491                              SocketMessage::READ | SocketMessage::EXCEPTION,
492 david.dillard 1.64           getQueueId(),
493 h.sterling    1.63           Monitor::ACCEPTOR)))
494 mday          1.7         {
495                              Socket::close(_rep->socket);
496                              delete _rep;
497                              _rep = 0;
498 humberto      1.30           //l10n
499                              //throw BindFailedException("Failed to solicit socket messaeges");
500                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
501 h.sterling    1.63                        "Failed to solicit socket messaeges");
502 kumpf         1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
503                                          "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
504 humberto      1.30           throw BindFailedException(parms);
505 mday          1.7         }
506 mike          1.2      }
507                        
508                        /**
509 mday          1.7         closeConnectionSocket - close the server listening socket to disallow
510                           new client connections.
511 mike          1.2      */
512                        void HTTPAcceptor::closeConnectionSocket()
513                        {
514 mday          1.7         if (_rep)
515                           {
516                              // unregister the socket
517 kumpf         1.35     
518                              // ATTN - comment out - see CIMServer::stopClientConnection()
519                              //_monitor->unsolicitSocketMessages(_rep->socket);
520 mday          1.7      
521                              // close the socket
522                              Socket::close(_rep->socket);
523 j.alex        1.67           // Unlink Local Domain Socket Bug# 3312
524                              if (_localConnection)
525                              {
526                        #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
527 denise.eckstein 1.71               PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
528 j.alex          1.67                             "HTTPAcceptor::closeConnectionSocket Unlinking local connection." );
529                                   ::unlink(
530                                       reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
531                          #else
532                                   PEGASUS_ASSERT(false);
533                          #endif
534                                }
535                          
536 mday            1.7         }
537 kumpf           1.44        else
538                             {
539                                PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
540                                                  "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
541                             }
542 mike            1.2      }
543                          
544                          /**
545 mday            1.7         reopenConnectionSocket - creates a new server socket.
546 mike            1.2      */
547                          void HTTPAcceptor::reopenConnectionSocket()
548                          {
549 mday            1.7         if (_rep)
550                             {
551                                _bind();
552                             }
553 kumpf           1.44        else
554                             {
555                                PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
556                                                  "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
557                             }
558 mike            1.2      }
559                          
560                          /**
561 mday            1.7         getOutstandingRequestCount - returns the number of outstanding requests.
562 mike            1.2      */
563 david.dillard   1.64     Uint32 HTTPAcceptor::getOutstandingRequestCount() const
564 mike            1.2      {
565 mday            1.28        Uint32 count = 0;
566 konrad.r        1.68        if (_rep)
567 mday            1.7         {
568 konrad.r        1.68           AutoMutex autoMut(_rep->_connection_mut);
569                                if (_rep->connections.size() > 0)
570                                {
571                                   HTTPConnection* connection = _rep->connections[0];
572                                   count = connection->getRequestCount();
573                                }
574 mday            1.7         }
575 mday            1.28        return count;
576 mike            1.2      }
577                          
578 david.dillard   1.64     
579                          /**
580                              getPortNumber - returns the port number used for the connection
581                          */
582                          Uint32 HTTPAcceptor::getPortNumber() const
583                          {
584                              return _portNumber;
585                          }
586                          
587 marek           1.84     void HTTPAcceptor::setSocketWriteTimeout(Uint32 socketWriteTimeout)
588                          {
589                              _socketWriteTimeout = socketWriteTimeout;
590                          }
591                          
592 mike            1.2      void HTTPAcceptor::unbind()
593                          {
594 mday            1.7         if (_rep)
595                             {
596 david.dillard   1.64           _portNumber = 0;
597 mday            1.7            Socket::close(_rep->socket);
598 kumpf           1.25     
599                                if (_localConnection)
600                                {
601 h.sterling      1.63     #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
602 kumpf           1.25              ::unlink(
603                                       reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
604                          #else
605                                   PEGASUS_ASSERT(false);
606                          #endif
607                                }
608                          
609 mday            1.7            delete _rep;
610                                _rep = 0;
611                             }
612 kumpf           1.44        else
613                             {
614                                PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
615                                        "HTTPAcceptor::unbind failure _rep is null." );
616                             }
617 mike            1.2      }
618                          
619                          void HTTPAcceptor::destroyConnections()
620                          {
621 konrad.r        1.68        if (_rep)
622                             {
623                               // For each connection created by this object:
624 mday            1.28     
625 konrad.r        1.68          AutoMutex autoMut(_rep->_connection_mut);
626                               for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
627                               {
628                                  HTTPConnection* connection = _rep->connections[i];
629 mike            1.82             SocketHandle socket = connection->getSocket();
630 mike            1.2      
631 konrad.r        1.68             // Unsolicit SocketMessages:
632 mike            1.2      
633 konrad.r        1.68             _monitor->unsolicitSocketMessages(socket);
634 mike            1.2      
635 konrad.r        1.68             // Destroy the connection (causing it to close):
636 mike            1.2      
637 mike            1.75             while (connection->refcount.get()) { }
638 konrad.r        1.68             delete connection;
639                               }
640 mike            1.2      
641 konrad.r        1.68          _rep->connections.clear();
642 mday            1.7         }
643 mike            1.2      }
644                          
645                          void HTTPAcceptor::_acceptConnection()
646                          {
647 mday            1.7         // This function cannot be called on an invalid socket!
648 mike            1.2      
649 mday            1.7         PEGASUS_ASSERT(_rep != 0);
650 mike            1.2      
651 mday            1.7         if (!_rep)
652                                return;
653 mike            1.2      
654 mday            1.7         // Accept the connection (populate the address):
655 mike            1.2      
656 kumpf           1.25        struct sockaddr* accept_address;
657 mike            1.83        SocketLength address_size;
658 mike            1.2      
659 kumpf           1.25        if (_localConnection)
660                             {
661 h.sterling      1.63     #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
662 kumpf           1.25            accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
663                                 address_size = sizeof(struct sockaddr_un);
664 mike            1.2      #else
665 kumpf           1.25            PEGASUS_ASSERT(false);
666 mike            1.2      #endif
667 kumpf           1.25        }
668                             else
669                             {
670                                 accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
671                                 address_size = sizeof(struct sockaddr_in);
672                             }
673                          
674 mike            1.82        SocketHandle socket = accept(_rep->socket, accept_address, &address_size);
675 kumpf           1.25     
676                             delete accept_address;
677 mike            1.2      
678 mday            1.7         if (socket < 0)
679                             {
680 mday            1.36     
681 david           1.27            Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
682 h.sterling      1.63                "HTTPAcceptor - accept() failure.  errno: $0"
683                                     ,errno);
684 david           1.27     
685 kumpf           1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
686 kumpf           1.19                             "HTTPAcceptor: accept() failed");
687 mday            1.7            return;
688                             }
689 david           1.27     
690 david.dillard   1.64     // set the close on exec flag
691 david.dillard   1.78     #if !defined(PEGASUS_OS_TYPE_WINDOWS) && !defined(PEGASUS_OS_VMS)
692 mday            1.28        int sock_flags;
693                           if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
694                             {
695 kumpf           1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
696 mday            1.28                             "HTTPAcceptor: fcntl(F_GETFD) failed");
697                             }
698                             else
699                             {
700                                sock_flags |= FD_CLOEXEC;
701                                if (fcntl(socket, F_SETFD, sock_flags) < 0)
702                                {
703 kumpf           1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
704 mday            1.28                             "HTTPAcceptor: fcntl(F_SETFD) failed");
705                                }
706                             }
707 david.dillard   1.64     #endif
708 mday            1.28     
709                          
710 mike            1.76        PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0,
711                                 "HTTPAcceptor - accept() success.  Socket: $1" ,socket));
712 mike            1.2      
713 kumpf           1.72        AutoPtr<MP_Socket> mp_socket(new MP_Socket(
714                                 socket, _sslcontext, _sslContextObjectLock, _exportConnection));
715 mike            1.2      
716 marek           1.84        mp_socket->setSocketWriteTimeout(_socketWriteTimeout);
717                          
718 kumpf           1.72        // Perform the SSL handshake, if applicable.  Make the socket non-blocking
719                             // for this operation so we can send it back to the Monitor's select() loop
720                             // if it takes a while.
721                          
722                             mp_socket->disableBlocking();
723                             Sint32 socketAcceptStatus = mp_socket->accept();
724                             mp_socket->enableBlocking();
725 nag.boranna     1.59     
726 kumpf           1.72        if (socketAcceptStatus < 0)
727 kumpf           1.19        {
728 nag.boranna     1.61            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
729 kumpf           1.19                             "HTTPAcceptor: SSL_accept() failed");
730 nag.boranna     1.61            mp_socket->close();
731                                 return;
732 mday            1.7         }
733 mike            1.2      
734 kumpf           1.72        // Create a new connection and add it to the connection list:
735                          
736 david.dillard   1.64        HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
737 kumpf           1.49            this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
738 mike            1.2      
739 kumpf           1.72        if (socketAcceptStatus == 0)
740                             {
741                                 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
742                                     "HTTPAcceptor: SSL_accept() pending");
743                                 connection->_acceptPending = true;
744                             }
745                          
746 mday            1.7         // Solicit events on this new connection's socket:
747 mday            1.21        int index;
748 david.dillard   1.64     
749 mday            1.22        if (-1 ==  (index = _monitor->solicitSocketMessages(
750 h.sterling      1.63           connection->getSocket(),
751                                SocketMessage::READ | SocketMessage::EXCEPTION,
752                                connection->getQueueId(), Monitor::CONNECTION)) )
753 mday            1.7         {
754 kumpf           1.37           // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
755                                // an error message to Client application.
756 kumpf           1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
757                                    "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
758 mday            1.7            delete connection;
759                                Socket::close(socket);
760 kumpf           1.37           return;
761 mday            1.7         }
762 a.arora         1.48     
763 mday            1.7         // Save the socket for cleanup later:
764 mday            1.21        connection->_entry_index = index;
765 a.arora         1.50        AutoMutex autoMut(_rep->_connection_mut);
766 mday            1.7         _rep->connections.append(connection);
767 mike            1.2      }
768 mday            1.32     
769 mike            1.2      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2