(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 w.white       1.81.8.1 #include "Socket.h"
 53 mike          1.2      
 54 david.dillard 1.78     #ifdef PEGASUS_OS_TYPE_WINDOWS
 55 mday          1.12     #include <windows.h>
 56 mike          1.2      #else
 57                        # include <cctype>
 58                        # include <cstdlib>
 59                        # include <errno.h>
 60                        # include <fcntl.h>
 61                        # include <netdb.h>
 62                        # include <netinet/in.h>
 63 mike          1.79     # include <netinet/tcp.h>
 64 mike          1.2      # include <arpa/inet.h>
 65                        # include <sys/socket.h>
 66 h.sterling    1.63     # ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
 67 kumpf         1.26     # include <unistd.h>
 68 kumpf         1.11     #  include <sys/un.h>
 69                        # endif
 70 mike          1.2      #endif
 71                        
 72                        #include "Socket.h"
 73                        #include "TLS.h"
 74                        #include "HTTPAcceptor.h"
 75                        #include "HTTPConnection.h"
 76 kumpf         1.19     #include "Tracer.h"
 77 humberto      1.30     #include <Pegasus/Common/MessageLoader.h> //l10n
 78 mike          1.2      
 79 chuck         1.38     #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
 80                        #include "OS400ConvertChar.h"
 81                        #endif
 82                        
 83 mike          1.79     
 84 mike          1.2      PEGASUS_USING_STD;
 85                        
 86                        PEGASUS_NAMESPACE_BEGIN
 87                        
 88 david.dillard 1.65     
 89 a.arora       1.51     static int MAX_CONNECTION_QUEUE_LENGTH = -1;
 90                        
 91 mike          1.2      ////////////////////////////////////////////////////////////////////////////////
 92                        //
 93                        // HTTPAcceptorRep
 94                        //
 95                        ////////////////////////////////////////////////////////////////////////////////
 96                        
 97 kumpf         1.25     class HTTPAcceptorRep
 98 mike          1.2      {
 99 kumpf         1.25     public:
100                            HTTPAcceptorRep(Boolean local)
101                            {
102                                if (local)
103                                {
104 j.alex        1.81.8.2 #ifndef PEGASUS_OS_TYPE_WINDOWS
105 h.sterling    1.63     #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
106 j.alex        1.81.8.2 
107 kumpf         1.25                 address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
108                                    address_size = sizeof(struct sockaddr_un);
109 kumpf         1.11     #else
110 kumpf         1.25                 PEGASUS_ASSERT(false);
111 kumpf         1.11     #endif
112 j.alex        1.81.8.2 
113                        #endif
114 david.dillard 1.64             }
115 kumpf         1.25             else
116                                {
117                                    address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
118                                    address_size = sizeof(struct sockaddr_in);
119                                }
120                            }
121 konrad.r      1.69         ~HTTPAcceptorRep()
122                            {
123 david.dillard 1.73             delete address;
124 konrad.r      1.69         }
125 kumpf         1.25         struct sockaddr* address;
126                        
127 mike          1.77         PEGASUS_SOCKLEN_T address_size;
128                            Mutex _connection_mut;
129 david.dillard 1.64     
130 mike          1.77         PEGASUS_SOCKET socket;
131 j.alex        1.81.8.2 #ifdef PEGASUS_OS_TYPE_WINDOWS
132                            NamedPipeServer* namedPipeServer;
133                        #endif
134 w.white       1.81.8.1     Array<HTTPConnection*> connections;   
135 j.alex        1.81.8.2  /*
136                        #ifdef PEGASUS_OS_TYPE_WINDOWS
137                              // This method creates and connects to a named pipe
138                            void createNamedPipe();
139                            NamedPipeServer* namedPipeServer;
140                            void _acceptNamedPipeConnection(NamedPipeMessage* namedPipeMessage);
141                        #endif
142                        */
143 w.white       1.81.8.1 
144                        
145 mike          1.2      };
146                        
147 mike          1.79     //------------------------------------------------------------------------------
148                        //
149                        // _setTCPNoDelay()
150                        //
151                        //------------------------------------------------------------------------------
152                        
153                        inline void _setTCPNoDelay(PEGASUS_SOCKET socket)
154                        {
155                            // This function disables "Nagle's Algorithm" also known as "the TCP delay
156                            // algorithm", which causes read operations to obtain whatever data is
157                            // already in the input queue and then wait a little longer to see if 
158                            // more data arrives. This algorithm optimizes the case in which data is 
159                            // sent in only one direction but severely impairs performance of round 
160                            // trip servers. Disabling TCP delay is a standard technique for round 
161                            // trip servers.
162                        
163                           int opt = 1;
164                           setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
165                        }
166                        
167 mike          1.2      ////////////////////////////////////////////////////////////////////////////////
168                        //
169                        // HTTPAcceptor
170                        //
171                        ////////////////////////////////////////////////////////////////////////////////
172                        
173 kumpf         1.25     HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
174                                                   MessageQueue* outputMessageQueue,
175                                                   Boolean localConnection,
176                                                   Uint32 portNumber,
177 kumpf         1.49                                SSLContext * sslcontext,
178 nag.boranna   1.59                                Boolean exportConnection,
179                                                   ReadWriteSem* sslContextObjectLock)
180 kumpf         1.25        : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR),  // ATTN: Need unique names?
181                             _monitor(monitor),
182                             _outputMessageQueue(outputMessageQueue),
183                             _rep(0),
184                             _entry_index(-1),
185                             _localConnection(localConnection),
186                             _portNumber(portNumber),
187 kumpf         1.49          _sslcontext(sslcontext),
188 nag.boranna   1.59          _exportConnection(exportConnection),
189                             _sslContextObjectLock(sslContextObjectLock)
190 mike          1.2      {
191 mday          1.7         Socket::initializeInterface();
192 david.dillard 1.64     
193 a.arora       1.51        /*
194                                Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH differently.  Some platforms interpret
195                                the value literally, while others multiply a fudge factor. When the server is under
196                                stress from multiple clients with multiple requests, toggling this number may prevent clients from
197                                being dropped.  Instead of hard coding the value, we allow an environment variable to be set which
198                                specifies a number greater than the maximum concurrent client connections possible.  If this environment
199                                var is not specified, then MAX_CONNECTION_QUEUE_LENGTH = 15.
200                           */
201                        
202                        //To engage runtime backlog queue length: uncomment the following block AND comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
203                        
204                        /*
205                           if(MAX_CONNECTION_QUEUE_LENGTH == -1){
206                        #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
207                        #pragma convert(37)
208 h.sterling    1.63         const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
209                            EtoA(env);
210 a.arora       1.51     #pragma convert(0)
211                        #else
212 h.sterling    1.63         const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
213 a.arora       1.51     #endif
214 h.sterling    1.63         if(!env){
215                                MAX_CONNECTION_QUEUE_LENGTH = 15;
216 david.dillard 1.64         }else{
217 h.sterling    1.63             char *end = NULL;
218                                MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
219                                if(*end)
220                                    MAX_CONNECTION_QUEUE_LENGTH = 15;
221                                cout << " MAX_CONNECTION_QUEUE_LENGTH = " << MAX_CONNECTION_QUEUE_LENGTH << endl;
222                            }
223 a.arora       1.51        }
224                        */
225                           MAX_CONNECTION_QUEUE_LENGTH = 15;
226 david.dillard 1.64     
227 mike          1.2      }
228                        
229                        HTTPAcceptor::~HTTPAcceptor()
230                        {
231 konrad.r      1.70        destroyConnections();
232 mday          1.7         unbind();
233 kumpf         1.25        // ATTN: Is this correct in a multi-HTTPAcceptor server?
234 mday          1.7         Socket::uninitializeInterface();
235 mike          1.2      }
236                        
237 mday          1.7      void HTTPAcceptor::handleEnqueue(Message *message)
238 mike          1.2      {
239 mday          1.7         if (! message)
240                              return;
241 david.dillard 1.64     
242 konrad.r      1.68        PEGASUS_ASSERT(_rep != 0);
243 mday          1.7         switch (message->getType())
244                           {
245                              case SOCKET_MESSAGE:
246                              {
247 w.white       1.81.8.1           SocketMessage* socketMessage = (SocketMessage*)message;
248 david.dillard 1.64     
249 w.white       1.81.8.1          // If this is a connection request:
250 h.sterling    1.63     
251 w.white       1.81.8.1          if (socketMessage->socket == _rep->socket &&
252                                     socketMessage->events & SocketMessage::READ)
253                                 {
254                                     _acceptConnection();
255                                 }
256                                 else
257                                 {
258                                    // ATTN! this can't happen!
259 kumpf         1.44                 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
260                                      "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");
261 w.white       1.81.8.1          }
262                        
263                                 break;
264                              }
265 j.alex        1.81.8.2  #ifdef PEGASUS_OS_TYPE_WINDOWS
266 w.white       1.81.8.1       case NAMEDPIPE_MESSAGE:
267                              {
268                                  NamedPipeMessage* namedPipeMessage = (NamedPipeMessage*)message;
269                        
270                                 // If this is a connection request:
271                        
272 j.alex        1.81.8.3          if (((namedPipeMessage->namedPipe.getPipe()) == ( _rep->namedPipeServer->getPipe())) &&
273                                 (namedPipeMessage->events & NamedPipeMessage::READ))
274 w.white       1.81.8.1          {
275 j.alex        1.81.8.2              _acceptNamedPipeConnection();
276 w.white       1.81.8.1          }
277 j.alex        1.81.8.3          else
278 w.white       1.81.8.1          {
279                                    // ATTN! this can't happen!
280                                    Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
281 j.alex        1.81.8.2               "HTTPAcceptor::handleEnqueue: Invalid NAMEDPIPE_MESSAGE received.");
282                                 } 
283 j.alex        1.81.8.3          
284 w.white       1.81.8.1          break;
285 mday          1.7      
286                              }
287 j.alex        1.81.8.2 #endif
288                             // may Need to close connection for Named Pipe too.....??
289                             case CLOSE_CONNECTION_MESSAGE:
290 mday          1.7            {
291 david.dillard 1.64          CloseConnectionMessage* closeConnectionMessage
292 h.sterling    1.63             = (CloseConnectionMessage*)message;
293                        
294                             AutoMutex autoMut(_rep->_connection_mut);
295 david.dillard 1.64     
296 h.sterling    1.63          for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
297                             {
298 david.dillard 1.64             HTTPConnection* connection = _rep->connections[i];
299 david.dillard 1.74             PEGASUS_SOCKET socket = connection->getSocket();
300 mday          1.7      
301 h.sterling    1.63             if (socket == closeConnectionMessage->socket)
302                                {
303                                   _monitor->unsolicitSocketMessages(socket);
304                                   _rep->connections.remove(i);
305 kumpf         1.17                    delete connection;
306 h.sterling    1.63                break;
307                                }
308                             }
309 david.dillard 1.64     
310 h.sterling    1.63          break;
311 mday          1.7            }
312 mike          1.2      
313 kumpf         1.10           default:
314                              // ATTN: need unexpected message error!
315 kumpf         1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
316                                   "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
317 mday          1.7            break;
318                           };
319 mike          1.2      
320 mday          1.7         delete message;
321                        }
322 mike          1.2      
323                        
324 mday          1.7      void HTTPAcceptor::handleEnqueue()
325                        {
326                           Message* message = dequeue();
327 mike          1.2      
328 mday          1.7         if (!message)
329 kumpf         1.44        {
330                              Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
331                                   "HTTPAcceptor::handleEnqueue(): No message on queue.");
332 mday          1.7            return;
333 kumpf         1.44        }
334 david.dillard 1.64     
335 mday          1.7         handleEnqueue(message);
336 mike          1.2      
337                        }
338                        
339 kumpf         1.25     void HTTPAcceptor::bind()
340 mike          1.2      {
341 humberto      1.30        if (_rep){
342 h.sterling    1.63         //l10n
343 david.dillard 1.64           //throw BindFailedException("HTTPAcceptor already bound");
344 humberto      1.34     
345 humberto      1.30           MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
346 h.sterling    1.63                        "HTTPAcceptor already bound");
347 humberto      1.34     
348 kumpf         1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
349                                   "HTTPAcceptor::bind: HTTPAcceptor already bound.");
350 humberto      1.30           throw BindFailedException(parms);
351                           }
352 mike          1.2      
353 kumpf         1.25        _rep = new HTTPAcceptorRep(_localConnection);
354 mike          1.2      
355 mday          1.7         // bind address
356                           _bind();
357 mike          1.2      
358 mday          1.7         return;
359 mike          1.2      }
360                        
361                        /**
362 mday          1.7         _bind - creates a new server socket and bind socket to the port address.
363 h.sterling    1.63        If PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET is not defined, the port number is ignored and
364 kumpf         1.11        a domain socket is bound.
365 mike          1.2      */
366                        void HTTPAcceptor::_bind()
367                        {
368 w.white       1.81.8.1     PEGASUS_STD(cout) << "in HTTPAcceptor::_bind at the begining" << PEGASUS_STD(endl);
369 j.alex        1.81.8.2     PEGASUS_STD(cout) << "in HTTPAcceptor::_bind before ASSERT" << PEGASUS_STD(endl);
370 mike          1.2      
371 konrad.r      1.68        PEGASUS_ASSERT(_rep != 0);
372 mday          1.7         // Create address:
373 mike          1.2      
374 j.alex        1.81.8.2    PEGASUS_STD(cout) << "in HTTPAcceptor::_bind before memset" << PEGASUS_STD(endl);
375                        
376                        
377                        #ifdef PEGASUS_OS_TYPE_WINDOWS
378                           if (!_localConnection)
379                           {
380                               memset(_rep->address, 0, sizeof(*_rep->address));
381                           }
382                        #else
383 kumpf         1.25        memset(_rep->address, 0, sizeof(*_rep->address));
384 j.alex        1.81.8.2 #endif
385                        
386                           PEGASUS_STD(cout) << "in HTTPAcceptor::_bind After memset" << PEGASUS_STD(endl);
387                        
388                           
389                           if (_localConnection)
390                           {
391 kumpf         1.6      
392 j.alex        1.81.8.2 #ifdef PEGASUS_OS_TYPE_WINDOWS
393                               PEGASUS_STD(cout) << "in HTTPAcceptor::_bind before calling _createNamedPipe() " << PEGASUS_STD(endl);
394                               // _rep->createNamedPipe();
395 w.white       1.81.8.1        _createNamedPipe();
396                               PEGASUS_STD(cout) << "in HTTPAcceptor::_bind after calling _createNamedPipe() " << PEGASUS_STD(endl);
397 j.alex        1.81.8.2 // Not sure if we need to continue to bind non local domain sockets in windows.....
398 w.white       1.81.8.1        return;
399 j.alex        1.81.8.2 // #else
400                        #endif
401 w.white       1.81.8.1 
402 j.alex        1.81.8.2 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET 
403                           
404 w.white       1.81.8.1         reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
405 kumpf         1.25                AF_UNIX;
406                               strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
407 w.white       1.81.8.1               PEGASUS_LOCAL_DOMAIN_SOCKET_PATH); 
408 chuck         1.38     #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
409                               AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
410                        #endif
411 kumpf         1.25            ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
412 kumpf         1.6      #else
413 kumpf         1.25            PEGASUS_ASSERT(false);
414 kumpf         1.11     #endif
415 kumpf         1.25        }
416                           else
417                           {
418                               reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_addr.s_addr =
419                                   INADDR_ANY;
420                               reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_family =
421                                   AF_INET;
422                               reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_port =
423                                   htons(_portNumber);
424                           }
425 mike          1.2      
426 mday          1.7         // Create socket:
427 david.dillard 1.64     
428 kumpf         1.25        if (_localConnection)
429                           {
430                               _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
431                           }
432                           else
433                           {
434                               _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
435 mike          1.79     
436                               _setTCPNoDelay(_rep->socket);
437 kumpf         1.25        }
438 mike          1.2      
439 mday          1.7         if (_rep->socket < 0)
440                           {
441                              delete _rep;
442                              _rep = 0;
443 humberto      1.30           //l10n
444                              //throw BindFailedException("Failed to create socket");
445                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
446 h.sterling    1.63                        "Failed to create socket");
447 kumpf         1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
448                                   "HTTPAcceptor::_bind _rep->socket < 0");
449 humberto      1.30           throw BindFailedException(parms);
450 mday          1.7         }
451                        
452 mday          1.28     
453                        // set the close-on-exec bit for this file handle.
454 david.dillard 1.64     // any unix that forks needs this bit set.
455 david.dillard 1.78     #if !defined PEGASUS_OS_TYPE_WINDOWS && !defined(PEGASUS_OS_VMS)
456 mday          1.28        int sock_flags;
457                         if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
458                           {
459 kumpf         1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
460                                          "HTTPAcceptor::_bind: fcntl(F_GETFD) failed");
461 mday          1.28        }
462                           else
463                           {
464                              sock_flags |= FD_CLOEXEC;
465                              if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
466                              {
467 kumpf         1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
468                                          "HTTPAcceptor::_bind: fcntl(F_SETFD) failed");
469 mday          1.28           }
470                           }
471 david.dillard 1.64     #endif
472 mday          1.28     
473                        
474 mday          1.7         //
475                           // Set the socket option SO_REUSEADDR to reuse the socket address so
476                           // that we can rebind to a new socket using the same address when we
477                           // need to resume the cimom as a result of a timeout during a Shutdown
478                           // operation.
479                           //
480                           int opt=1;
481                           if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
482 h.sterling    1.63               (char *)&opt, sizeof(opt)) < 0)
483 mday          1.7         {
484 mday          1.28           Socket::close(_rep->socket);
485 mday          1.7            delete _rep;
486                              _rep = 0;
487 humberto      1.30           //l10n
488                              //throw BindFailedException("Failed to set socket option");
489                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
490 h.sterling    1.63                        "Failed to set socket option");
491 kumpf         1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
492                                           "HTTPAcceptor::_bind: Failed to set socket option.");
493 humberto      1.30           throw BindFailedException(parms);
494 mday          1.7         }
495                        
496 david.dillard 1.64     
497                           //
498 mday          1.7         // Bind socket to port:
499 david.dillard 1.64        //
500 kumpf         1.25        if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
501 mday          1.7         {
502                              Socket::close(_rep->socket);
503                              delete _rep;
504                              _rep = 0;
505 humberto      1.30           //l10n
506                              //throw BindFailedException("Failed to bind socket");
507                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
508 h.sterling    1.63                        "Failed to bind socket");
509 kumpf         1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
510                                                "HTTPAcceptor::_bind: Failed to bind socket.");
511 humberto      1.30           throw BindFailedException(parms);
512 mday          1.7         }
513                        
514 david.dillard 1.64     
515                           //
516                           // Get the actual port value used if the caller specified a port value of 0.
517                           //
518                           if ( _portNumber == 0 )
519                           {
520                              sockaddr_in buf;
521 david.dillard 1.65           PEGASUS_SOCKLEN_T bufSize = sizeof(buf);
522 david.dillard 1.64           if ( getsockname(_rep->socket, reinterpret_cast<sockaddr *>(&buf), &bufSize) == 0 )
523                              {
524                                  _portNumber = ntohs(buf.sin_port);
525                              }
526                           }
527                        
528                        
529 w.otsuka      1.54        //
530                           //  Change permissions on Linux local domain socket to allow writes by others.
531                           //
532 h.sterling    1.63     #if !defined(PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET) && defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
533 w.otsuka      1.54        if (_localConnection)
534                           {
535 david.dillard 1.64          if (::chmod( PEGASUS_LOCAL_DOMAIN_SOCKET_PATH,
536                                          S_IRUSR | S_IWUSR | S_IXUSR |
537 w.otsuka      1.54                       S_IRGRP | S_IWGRP | S_IXGRP |
538                                          S_IROTH | S_IWOTH | S_IXOTH ) < 0 )
539                             {
540                               Socket::close(_rep->socket);
541                               delete _rep;
542                               _rep = 0;
543                               //l10n
544                               //throw BindFailedException("Failed to bind socket");
545                               MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
546 h.sterling    1.63                        "Failed to bind socket");
547 w.otsuka      1.54            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
548                                      "HTTPAcceptor::_bind: Failed to set domain socket permissions.");
549                               throw BindFailedException(parms);
550                             }
551                           }
552                        #endif
553                        
554 kumpf         1.11        // Set up listening on the given socket:
555 mday          1.7      
556 a.arora       1.51        //int const MAX_CONNECTION_QUEUE_LENGTH = 15;
557 mday          1.7      
558                           if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
559                           {
560                              Socket::close(_rep->socket);
561                              delete _rep;
562                              _rep = 0;
563 humberto      1.30           //l10n
564                              //throw BindFailedException("Failed to bind socket");
565                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
566 h.sterling    1.63                        "Failed to bind socket");
567 kumpf         1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
568                                          "HTTPAcceptor::_bind: Failed to bind socket(1).");
569 humberto      1.30           throw BindFailedException(parms);
570 mday          1.7         }
571                        
572                           // Register to receive SocketMessages on this socket:
573                        
574 mday          1.21        if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
575 h.sterling    1.63           _rep->socket,
576                              SocketMessage::READ | SocketMessage::EXCEPTION,
577 david.dillard 1.64           getQueueId(),
578 h.sterling    1.63           Monitor::ACCEPTOR)))
579 mday          1.7         {
580                              Socket::close(_rep->socket);
581                              delete _rep;
582                              _rep = 0;
583 humberto      1.30           //l10n
584                              //throw BindFailedException("Failed to solicit socket messaeges");
585                              MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
586 h.sterling    1.63                        "Failed to solicit socket messaeges");
587 kumpf         1.44           PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
588                                          "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
589 humberto      1.30           throw BindFailedException(parms);
590 mday          1.7         }
591 j.alex        1.81.8.2    PEGASUS_STD(cout) << "in HTTPAcceptor::_bind at the End" << PEGASUS_STD(endl);
592                        
593 mike          1.2      }
594                        
595                        /**
596 mday          1.7         closeConnectionSocket - close the server listening socket to disallow
597                           new client connections.
598 mike          1.2      */
599                        void HTTPAcceptor::closeConnectionSocket()
600                        {
601 mday          1.7         if (_rep)
602                           {
603                              // unregister the socket
604 kumpf         1.35     
605                              // ATTN - comment out - see CIMServer::stopClientConnection()
606                              //_monitor->unsolicitSocketMessages(_rep->socket);
607 mday          1.7      
608                              // close the socket
609                              Socket::close(_rep->socket);
610 j.alex        1.67           // Unlink Local Domain Socket Bug# 3312
611                              if (_localConnection)
612                              {
613                        #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
614 denise.eckstein 1.71               PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
615 j.alex          1.67                             "HTTPAcceptor::closeConnectionSocket Unlinking local connection." );
616                                   ::unlink(
617                                       reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
618                          #else
619                                   PEGASUS_ASSERT(false);
620                          #endif
621                                }
622                          
623 mday            1.7         }
624 kumpf           1.44        else
625                             {
626                                PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
627                                                  "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
628                             }
629 mike            1.2      }
630                          
631                          /**
632 mday            1.7         reopenConnectionSocket - creates a new server socket.
633 mike            1.2      */
634                          void HTTPAcceptor::reopenConnectionSocket()
635                          {
636 mday            1.7         if (_rep)
637                             {
638                                _bind();
639                             }
640 kumpf           1.44        else
641                             {
642                                PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
643                                                  "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
644                             }
645 mike            1.2      }
646                          
647                          /**
648 mday            1.7         getOutstandingRequestCount - returns the number of outstanding requests.
649 mike            1.2      */
650 david.dillard   1.64     Uint32 HTTPAcceptor::getOutstandingRequestCount() const
651 mike            1.2      {
652 mday            1.28        Uint32 count = 0;
653 konrad.r        1.68        if (_rep)
654 mday            1.7         {
655 konrad.r        1.68           AutoMutex autoMut(_rep->_connection_mut);
656                                if (_rep->connections.size() > 0)
657                                {
658                                   HTTPConnection* connection = _rep->connections[0];
659                                   count = connection->getRequestCount();
660                                }
661 mday            1.7         }
662 mday            1.28        return count;
663 mike            1.2      }
664                          
665 david.dillard   1.64     
666                          /**
667                              getPortNumber - returns the port number used for the connection
668                          */
669                          Uint32 HTTPAcceptor::getPortNumber() const
670                          {
671                              return _portNumber;
672                          }
673                          
674 mike            1.2      void HTTPAcceptor::unbind()
675                          {
676 mday            1.7         if (_rep)
677                             {
678 david.dillard   1.64           _portNumber = 0;
679 mday            1.7            Socket::close(_rep->socket);
680 kumpf           1.25     
681                                if (_localConnection)
682                                {
683 h.sterling      1.63     #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
684 kumpf           1.25              ::unlink(
685                                       reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
686                          #else
687                                   PEGASUS_ASSERT(false);
688                          #endif
689                                }
690                          
691 mday            1.7            delete _rep;
692                                _rep = 0;
693                             }
694 kumpf           1.44        else
695                             {
696                                PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
697                                        "HTTPAcceptor::unbind failure _rep is null." );
698                             }
699 mike            1.2      }
700                          
701                          void HTTPAcceptor::destroyConnections()
702                          {
703 konrad.r        1.68        if (_rep)
704                             {
705                               // For each connection created by this object:
706 mday            1.28     
707 konrad.r        1.68          AutoMutex autoMut(_rep->_connection_mut);
708                               for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
709                               {
710                                  HTTPConnection* connection = _rep->connections[i];
711 david.dillard   1.74             PEGASUS_SOCKET socket = connection->getSocket();
712 mike            1.2      
713 konrad.r        1.68             // Unsolicit SocketMessages:
714 mike            1.2      
715 konrad.r        1.68             _monitor->unsolicitSocketMessages(socket);
716 mike            1.2      
717 konrad.r        1.68             // Destroy the connection (causing it to close):
718 mike            1.2      
719 mike            1.75             while (connection->refcount.get()) { }
720 konrad.r        1.68             delete connection;
721                               }
722 mike            1.2      
723 konrad.r        1.68          _rep->connections.clear();
724 mday            1.7         }
725 mike            1.2      }
726                          
727                          void HTTPAcceptor::_acceptConnection()
728                          {
729 mday            1.7         // This function cannot be called on an invalid socket!
730 mike            1.2      
731 mday            1.7         PEGASUS_ASSERT(_rep != 0);
732 mike            1.2      
733 mday            1.7         if (!_rep)
734                                return;
735 mike            1.2      
736 mday            1.7         // Accept the connection (populate the address):
737 mike            1.2      
738 kumpf           1.25        struct sockaddr* accept_address;
739 mike            1.77        PEGASUS_SOCKLEN_T address_size;
740 mike            1.2      
741 kumpf           1.25        if (_localConnection)
742                             {
743 h.sterling      1.63     #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
744 kumpf           1.25            accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
745                                 address_size = sizeof(struct sockaddr_un);
746 mike            1.2      #else
747 kumpf           1.25            PEGASUS_ASSERT(false);
748 mike            1.2      #endif
749 kumpf           1.25        }
750                             else
751                             {
752                                 accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
753                                 address_size = sizeof(struct sockaddr_in);
754                             }
755                          
756 david.dillard   1.73        PEGASUS_SOCKET socket = accept(_rep->socket, accept_address, &address_size);
757 kumpf           1.25     
758                             delete accept_address;
759 mike            1.2      
760 mday            1.7         if (socket < 0)
761                             {
762 mday            1.36     
763 david           1.27            Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
764 h.sterling      1.63                "HTTPAcceptor - accept() failure.  errno: $0"
765                                     ,errno);
766 david           1.27     
767 kumpf           1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
768 kumpf           1.19                             "HTTPAcceptor: accept() failed");
769 mday            1.7            return;
770                             }
771 david           1.27     
772 david.dillard   1.64     // set the close on exec flag
773 david.dillard   1.78     #if !defined(PEGASUS_OS_TYPE_WINDOWS) && !defined(PEGASUS_OS_VMS)
774 mday            1.28        int sock_flags;
775                           if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
776                             {
777 kumpf           1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
778 mday            1.28                             "HTTPAcceptor: fcntl(F_GETFD) failed");
779                             }
780                             else
781                             {
782                                sock_flags |= FD_CLOEXEC;
783                                if (fcntl(socket, F_SETFD, sock_flags) < 0)
784                                {
785 kumpf           1.44            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
786 mday            1.28                             "HTTPAcceptor: fcntl(F_SETFD) failed");
787                                }
788                             }
789 david.dillard   1.64     #endif
790 mday            1.28     
791                          
792 mike            1.76        PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0,
793                                 "HTTPAcceptor - accept() success.  Socket: $1" ,socket));
794 mike            1.2      
795 kumpf           1.72        AutoPtr<MP_Socket> mp_socket(new MP_Socket(
796                                 socket, _sslcontext, _sslContextObjectLock, _exportConnection));
797 mike            1.2      
798 kumpf           1.72        // Perform the SSL handshake, if applicable.  Make the socket non-blocking
799                             // for this operation so we can send it back to the Monitor's select() loop
800                             // if it takes a while.
801                          
802                             mp_socket->disableBlocking();
803                             Sint32 socketAcceptStatus = mp_socket->accept();
804                             mp_socket->enableBlocking();
805 nag.boranna     1.59     
806 kumpf           1.72        if (socketAcceptStatus < 0)
807 kumpf           1.19        {
808 nag.boranna     1.61            PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
809 kumpf           1.19                             "HTTPAcceptor: SSL_accept() failed");
810 nag.boranna     1.61            mp_socket->close();
811                                 return;
812 mday            1.7         }
813 mike            1.2      
814 kumpf           1.72        // Create a new connection and add it to the connection list:
815                          
816 david.dillard   1.64        HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
817 kumpf           1.49            this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
818 mike            1.2      
819 kumpf           1.72        if (socketAcceptStatus == 0)
820                             {
821                                 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
822                                     "HTTPAcceptor: SSL_accept() pending");
823                                 connection->_acceptPending = true;
824                             }
825                          
826 mday            1.7         // Solicit events on this new connection's socket:
827 mday            1.21        int index;
828 david.dillard   1.64     
829 mday            1.22        if (-1 ==  (index = _monitor->solicitSocketMessages(
830 h.sterling      1.63           connection->getSocket(),
831                                SocketMessage::READ | SocketMessage::EXCEPTION,
832                                connection->getQueueId(), Monitor::CONNECTION)) )
833 mday            1.7         {
834 kumpf           1.37           // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
835                                // an error message to Client application.
836 kumpf           1.44           Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
837                                    "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
838 mday            1.7            delete connection;
839                                Socket::close(socket);
840 kumpf           1.37           return;
841 mday            1.7         }
842 a.arora         1.48     
843 mday            1.7         // Save the socket for cleanup later:
844 mday            1.21        connection->_entry_index = index;
845 a.arora         1.50        AutoMutex autoMut(_rep->_connection_mut);
846 mday            1.7         _rep->connections.append(connection);
847 mike            1.2      }
848 mday            1.32     
849 j.alex          1.81.8.2 #ifdef PEGASUS_OS_TYPE_WINDOWS
850 w.white         1.81.8.1 void HTTPAcceptor::_createNamedPipe()
851                          {
852                              PEGASUS_STD(cout) << "in HTTPAcceptor::_createNamedPipe() at the begining" << PEGASUS_STD(endl);
853                          
854 j.alex          1.81.8.2     _rep->namedPipeServer = new NamedPipeServer("\\\\.\\pipe\\MyNamedPipe");
855 w.white         1.81.8.1     PEGASUS_STD(cout) << "in HTTPAcceptor::_createNamedPipe() after calling the pipe server constructor" << PEGASUS_STD(endl);
856                              
857                             
858                          
859                              // Register to receive Messages on Connection pipe:
860                                  
861                             if ( -1 == ( _entry_index = _monitor->solicitPipeMessages(
862 j.alex          1.81.8.2       *_rep->namedPipeServer,
863                                NamedPipeMessage::READ | NamedPipeMessage::EXCEPTION,
864 w.white         1.81.8.1       getQueueId(),
865                                Monitor::ACCEPTOR)))
866                             {
867 j.alex          1.81.8.2        ::CloseHandle(_rep->namedPipeServer->getPipe());
868                                 delete _rep;
869                                 _rep = 0;
870                                 //l10n
871                                 //throw BindFailedException("Failed to solicit socket messaeges");
872                                 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
873                                              "Failed to solicit socket messaeges");
874                                 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
875                                             "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
876                                 throw BindFailedException(parms);
877                          
878 w.white         1.81.8.1        PEGASUS_STD(cout) << "in HTTPAcceptor::_createNamedPipe() _monitor->solicitSocketMessages failed" << PEGASUS_STD(endl);
879                          
880                             }
881                          
882                             PEGASUS_STD(cout) << "in HTTPAcceptor::_createNamedPipe() at the end" << PEGASUS_STD(endl);
883                             return; 
884                          
885                          }
886 j.alex          1.81.8.2 #endif
887 w.white         1.81.8.1 
888 j.alex          1.81.8.2 
889                          #ifdef PEGASUS_OS_TYPE_WINDOWS
890                          void HTTPAcceptor::_acceptNamedPipeConnection()
891 w.white         1.81.8.1 {
892 j.alex          1.81.8.2     PEGASUS_ASSERT(_rep != 0);
893                          
894                              if (!_rep)
895                                 return;
896                          
897 w.white         1.81.8.1     cout <<"In HTTPAcceptor::_acceptNamedPipeConnection " << endl;
898                          
899 j.alex          1.81.8.2    // shouldnt we be using the private var....
900                               //                 _namedPipeServer->accept()
901                          
902                              NamedPipeServerEndPiont nPSEndPoint = _rep->namedPipeServer->accept();
903                              // Registerpe to receive Messages on Connection pipe:
904 w.white         1.81.8.1 
905 j.alex          1.81.8.2     cout << " In _acceptNamedPipeConnection -- after calling namedPipeServer->accept()" << endl;
906                          
907                              HTTPConnection* connection = new HTTPConnection(_monitor, nPSEndPoint,
908                                  this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
909                          
910                              /*  NOT SURE WHAT TO DO HERE  ....
911                              if (socketAcceptStatus == 0)
912                              {
913                                  PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
914                                      "HTTPAcceptor: SSL_accept() pending");
915                                  connection->_acceptPending = true;
916                              }
917                          
918                              */
919                          
920                              // Solicit events on this new connection's socket:
921                              int index;
922                          
923                              if (-1 ==  (index = _monitor->solicitPipeMessages(
924                                 connection->getNamedPipe(),
925                                 NamedPipeMessage::READ | NamedPipeMessage::EXCEPTION,
926 j.alex          1.81.8.2        connection->getQueueId(), Monitor::CONNECTION)) )
927                              {
928                                 // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
929                                 // an error message to Client application.
930                                 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
931                                     "HTTPAcceptor::_acceptPipeConnection: Attempt to allocate entry in _entries table failed.");
932                                 delete connection;
933                                 //  May have to close the PIPE here...
934                                 //Socket::close(socket);
935                                 return;
936                              }
937                          
938                              // Save the socket for cleanup later:
939                              connection->_entry_index = index;
940                              AutoMutex autoMut(_rep->_connection_mut);
941                              _rep->connections.append(connection);
942                          
943                            PEGASUS_STD(cout)
944                                 << "in HTTPAcceptor::_acceptNamedPipeConnection() at the end" << PEGASUS_STD(endl);
945 w.white         1.81.8.1 
946                          
947                          }
948 j.alex          1.81.8.2 #endif
949 w.white         1.81.8.1 
950 mike            1.2      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2