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

  1 martin 1.57 //%LICENSE////////////////////////////////////////////////////////////////
  2 martin 1.58 //
  3 martin 1.57 // Licensed to The Open Group (TOG) under one or more contributor license
  4             // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  5             // this work for additional information regarding copyright ownership.
  6             // Each contributor licenses this file to you under the OpenPegasus Open
  7             // Source License; you may not use this file except in compliance with the
  8             // License.
  9 martin 1.58 //
 10 martin 1.57 // Permission is hereby granted, free of charge, to any person obtaining a
 11             // copy of this software and associated documentation files (the "Software"),
 12             // to deal in the Software without restriction, including without limitation
 13             // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 14             // and/or sell copies of the Software, and to permit persons to whom the
 15             // Software is furnished to do so, subject to the following conditions:
 16 martin 1.58 //
 17 martin 1.57 // The above copyright notice and this permission notice shall be included
 18             // in all copies or substantial portions of the Software.
 19 martin 1.58 //
 20 martin 1.57 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 21 martin 1.58 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 22 martin 1.57 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 23             // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 24             // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 25             // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 26             // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27 martin 1.58 //
 28 martin 1.57 //////////////////////////////////////////////////////////////////////////
 29 kumpf  1.1  //
 30             //%/////////////////////////////////////////////////////////////////////////////
 31             
 32 tony   1.8  #include "CIMListener.h"
 33             #include <Pegasus/Common/Exception.h>
 34             #include <Pegasus/Common/SSLContext.h>
 35             #include <Pegasus/Common/Monitor.h>
 36 kumpf  1.1  #include <Pegasus/Common/HTTPAcceptor.h>
 37 jsafrane 1.60 #include <Pegasus/Common/HostAddress.h>
 38 kumpf    1.11 #include <Pegasus/Common/PegasusVersion.h>
 39 konrad.r 1.38 #include <Pegasus/Common/MessageLoader.h>
 40 kumpf    1.44 #include <Pegasus/Common/Time.h>
 41 kumpf    1.1  #include <Pegasus/ExportServer/CIMExportResponseEncoder.h>
 42               #include <Pegasus/ExportServer/CIMExportRequestDecoder.h>
 43 tony     1.8  #include <Pegasus/Consumer/CIMIndicationConsumer.h>
 44               #include <Pegasus/Listener/CIMListenerIndicationDispatcher.h>
 45               
 46               PEGASUS_NAMESPACE_BEGIN
 47 mike     1.41 
 48               ////////////////////////////////////////////////////////////////////////////////
 49               //
 50 tony     1.8  // CIMListenerService
 51 mike     1.41 //
 52               ////////////////////////////////////////////////////////////////////////////////
 53               
 54 tony     1.8  class CIMListenerService
 55               {
 56               public:
 57 jsafrane 1.60     CIMListenerService(
 58                       const String &listenAddress,
 59                       Uint32 portNumber,
 60                       SSLContext * sslContext = NULL);
 61 mike     1.41     CIMListenerService(Uint32 portNumber, SSLContext * sslContext = NULL);
 62                   CIMListenerService(CIMListenerService & svc);
 63                   ~CIMListenerService();
 64               
 65                   void init();
 66               
 67                   /** bind to the port
 68                   */
 69                   void bind();
 70               
 71                   /** runForever Main runloop for the server.
 72                   */
 73                   void runForever();
 74               
 75                   /** Call to gracefully shutdown the server.  The server connection socket
 76                       will be closed to disable new connections from clients.
 77                   */
 78                   void stopClientConnection();
 79               
 80                   /** Call to gracefully shutdown the server.  It is called when the server
 81                       has been stopped and is ready to be shutdown.  Next time runForever()
 82 mike     1.41         is called, the server shuts down.
 83                   */
 84                   void shutdown();
 85               
 86                   /** Return true if the server has shutdown, false otherwise.
 87                   */
 88                   Boolean terminated() const
 89                   {
 90                       return _dieNow;
 91                   };
 92 david.dillard 1.34 
 93 mike          1.41     /** Call to resume the sever.
 94                        */
 95                        void resume();
 96                    
 97                        /** Call to set the CIMServer state.  Also inform the appropriate
 98                            message queues about the current state of the CIMServer.
 99                        */
100                        void setState(Uint32 state);
101                    
102                        Uint32 getOutstandingRequestCount();
103                    
104                        /** Returns the indication listener dispatcher
105                        */
106                        CIMListenerIndicationDispatcher *getIndicationDispatcher() const;
107                    
108                        /** Returns the indication listener dispatcher
109                        */
110                        void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher);
111                    
112 jsafrane      1.60     /** Returns the bind address.
113                        */
114                        String getListenAddress() const;
115                    
116 mike          1.41     /** Returns the port number being used.
117                        */
118                        Uint32 getPortNumber() const;
119                    
120 karl          1.49     static ThreadReturnType PEGASUS_THREAD_CDECL
121 mike          1.41     _listener_routine(void *param);
122 tony          1.8  
123                    private:
124 jsafrane      1.60     String _listenAddress;
125 mike          1.41     Uint32 _portNumber;
126                        SSLContext *_sslContext;
127 ouyang.jian   1.54     ReadWriteSem _sslContextObjectLock;
128 mike          1.41     Monitor *_monitor;
129                        Mutex _monitorMutex;
130 dave.sudlik   1.48     HTTPAcceptor *_ip6Acceptor;
131                        HTTPAcceptor *_ip4Acceptor;
132 mike          1.41     Boolean _dieNow;
133                        CIMListenerIndicationDispatcher *_dispatcher;
134                        CIMExportResponseEncoder *_responseEncoder;
135                        CIMExportRequestDecoder *_requestDecoder;
136 tony          1.8  };
137                    
138 mike          1.41 CIMListenerService::CIMListenerService(
139 jsafrane      1.60     const String &listenAddress,
140 karl          1.49     Uint32 portNumber,
141 mike          1.41     SSLContext * sslContext)
142                        :
143 jsafrane      1.60     _listenAddress(listenAddress),
144                        _portNumber(portNumber),
145                        _sslContext(sslContext),
146                        _monitor(NULL),
147                        _ip6Acceptor(NULL),
148                        _ip4Acceptor(NULL),
149                        _dieNow(false),
150                        _dispatcher(NULL),
151                        _responseEncoder(NULL),
152                        _requestDecoder(NULL)
153                    {
154                    }
155                    
156                    CIMListenerService::CIMListenerService(
157                        Uint32 portNumber,
158                        SSLContext * sslContext)
159                        :
160                        _listenAddress(),
161 karl          1.49     _portNumber(portNumber),
162                        _sslContext(sslContext),
163 mike          1.41     _monitor(NULL),
164 dave.sudlik   1.48     _ip6Acceptor(NULL),
165                        _ip4Acceptor(NULL),
166 karl          1.49     _dieNow(false),
167                        _dispatcher(NULL),
168 mike          1.41     _responseEncoder(NULL),
169                        _requestDecoder(NULL)
170 tony          1.8  {
171                    }
172                    
173 mike          1.41 CIMListenerService::CIMListenerService(CIMListenerService & svc) :
174 jsafrane      1.60     _listenAddress(svc._listenAddress),
175 karl          1.49     _portNumber(svc._portNumber),
176                        _sslContext(svc._sslContext),
177 mike          1.41     _monitor(NULL),
178 dave.sudlik   1.48     _ip6Acceptor(NULL),
179                        _ip4Acceptor(NULL),
180 karl          1.49     _dieNow(svc._dieNow),
181 mike          1.41     _dispatcher(NULL),
182 karl          1.49     _responseEncoder(NULL),
183 mike          1.41     _requestDecoder(NULL)
184 tony          1.8  {
185                    }
186 mike          1.41 
187 tony          1.8  CIMListenerService::~CIMListenerService()
188                    {
189 kumpf         1.36     delete _responseEncoder;
190                        delete _requestDecoder;
191 dave.sudlik   1.48     delete _ip6Acceptor;
192                        delete _ip4Acceptor;
193 kumpf         1.36     delete _monitor;
194 tony          1.8  }
195 kumpf         1.1  
196 tony          1.8  void CIMListenerService::init()
197 kumpf         1.1  {
198 mike          1.41     PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::init");
199 kumpf         1.1  
200 mike          1.41     if (NULL == _monitor)
201                            _monitor = new Monitor();
202 david.dillard 1.31 
203 mike          1.41     // _dispatcher = new CIMListenerIndicationDispatcher();
204 kumpf         1.1  
205 mike          1.41     if (NULL == _responseEncoder)
206                            _responseEncoder = new CIMExportResponseEncoder();
207 tony          1.8  
208 mike          1.41     if (NULL == _requestDecoder)
209                        {
210                            _requestDecoder = new CIMExportRequestDecoder(
211                                _dispatcher, _responseEncoder->getQueueId());
212                        }
213 jsafrane      1.60 
214                        HostAddress listenAddress;
215                        Boolean listenAddressEmpty = _listenAddress == String::EMPTY;
216                        if (!listenAddressEmpty)
217                            listenAddress.setHostAddress(_listenAddress);
218                    
219 dave.sudlik   1.48 #ifdef PEGASUS_ENABLE_IPV6
220 jsafrane      1.60     if (System::isIPv6StackActive() &&
221                           (listenAddressEmpty ||
222                           (listenAddress.isValid() &&
223                            listenAddress.getAddressType() == HostAddress::AT_IPV6)))
224 dave.sudlik   1.48     {
225 venkat.puvvada 1.50         if (NULL == _ip6Acceptor)
226                             {
227 ouyang.jian    1.54             if (NULL == _sslContext)
228                                 {
229                                     _ip6Acceptor = new HTTPAcceptor(
230                                             _monitor, _requestDecoder,
231                                             HTTPAcceptor::IPV6_CONNECTION,
232 jsafrane       1.60                         _portNumber, 0, 0,
233                                             listenAddressEmpty ? 0 : &listenAddress);
234 ouyang.jian    1.54             }
235                                 else
236                                 {
237                                     _ip6Acceptor = new HTTPAcceptor(
238                                             _monitor, _requestDecoder,
239                                             HTTPAcceptor::IPV6_CONNECTION,
240 jsafrane       1.60                         _portNumber, _sslContext, &_sslContextObjectLock,
241                                             listenAddressEmpty ? 0 : &listenAddress);
242 ouyang.jian    1.54             }
243 venkat.puvvada 1.50         }
244 dave.sudlik    1.48     }
245 venkat.puvvada 1.50 #ifndef PEGASUS_OS_TYPE_WINDOWS
246 kumpf          1.59     else
247 venkat.puvvada 1.50 #endif
248 dave.sudlik    1.48 #endif
249                         if (NULL == _ip4Acceptor)
250 mike           1.41     {
251 ouyang.jian    1.54         if (NULL == _sslContext)
252                             {
253                                 _ip4Acceptor = new HTTPAcceptor(
254                                         _monitor, _requestDecoder,
255                                         HTTPAcceptor::IPV4_CONNECTION,
256 jsafrane       1.60                     _portNumber, 0, 0,
257                                         listenAddressEmpty ? 0 : &listenAddress);
258 ouyang.jian    1.54         }
259                             else
260                             {
261                                 _ip4Acceptor = new HTTPAcceptor(
262                                         _monitor, _requestDecoder,
263                                         HTTPAcceptor::IPV4_CONNECTION,
264 jsafrane       1.60                     _portNumber, _sslContext, &_sslContextObjectLock,
265                                         listenAddressEmpty ? 0 : &listenAddress);
266 ouyang.jian    1.54         }
267 mike           1.41     }
268                         bind();
269                     
270                         PEG_METHOD_EXIT();
271 tony           1.8  }
272 david.dillard  1.34 
273 tony           1.8  void CIMListenerService::bind()
274                     {
275 dave.sudlik    1.48     if (_ip6Acceptor != NULL)
276 mike           1.41     {
277 dave.sudlik    1.48         _ip6Acceptor->bind();
278                     
279                             Logger::put(
280                                 Logger::STANDARD_LOG,
281                                 System::CIMLISTENER,
282                                 Logger::INFORMATION,
283                                 "IPV6, Listening on HTTP port $0.",
284                                 _portNumber);
285                         }
286                         if (_ip4Acceptor != NULL)
287                         {
288                             _ip4Acceptor->bind();
289 kumpf          1.1  
290 mike           1.41         Logger::put(
291 karl           1.49             Logger::STANDARD_LOG,
292 mike           1.41             System::CIMLISTENER,
293 karl           1.49             Logger::INFORMATION,
294 dave.sudlik    1.48             "IPV4, Listening on HTTP for port $0.",
295 mike           1.41             _portNumber);
296 chuck          1.20     }
297 tony           1.8  }
298 chuck          1.20 
299 tony           1.8  void CIMListenerService::runForever()
300                     {
301 mike           1.41     if (!_dieNow)
302 dj.gorey       1.14     {
303 kumpf          1.43         _monitor->run(500000);
304                             static struct timeval lastIdleCleanupTime = {0, 0};
305                             struct timeval now;
306 kumpf          1.44         Time::gettimeofday(&now);
307 kumpf          1.43         if (now.tv_sec - lastIdleCleanupTime.tv_sec > 300)
308 mike           1.41         {
309 kumpf          1.43             lastIdleCleanupTime.tv_sec = now.tv_sec;
310 mike           1.41             try
311                                 {
312                                     MessageQueueService::get_thread_pool()->cleanupIdleThreads();
313                                 }
314                                 catch(...)
315                                 {
316                                     // Ignore!
317                                 }
318                             }
319 chuck          1.20     }
320 tony           1.8  }
321 kumpf          1.1  
322 tony           1.8  void CIMListenerService::shutdown()
323                     {
324                         PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::shutdown()");
325 kumpf          1.1  
326 mike           1.41     // This logic signals the thread currently executing _listener_routine()
327 karl           1.49     // to exit. That function deletes this instance of CIMListenerService,
328                         // which deletes the _monitor member. We use a mutex to keep it from
329 mike           1.41     // deleting the monitor until after tickle has been called.
330                         {
331                             AutoMutex am(_monitorMutex);
332                             _dieNow = true;
333                             _monitor->tickle();
334                         }
335 kumpf          1.1  
336 kumpf          1.4      PEG_METHOD_EXIT();
337 kumpf          1.1  }
338                     
339 tony           1.8  void CIMListenerService::resume()
340 kumpf          1.1  {
341 tony           1.8      PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()");
342 dave.sudlik    1.48     if (_ip6Acceptor != NULL)
343                         {
344                             _ip6Acceptor->reopenConnectionSocket();
345                         }
346                         if (_ip4Acceptor != NULL)
347                         {
348                             _ip4Acceptor->reopenConnectionSocket();
349                         }
350 kumpf          1.4      PEG_METHOD_EXIT();
351 kumpf          1.1  }
352                     
353 tony           1.8  void CIMListenerService::stopClientConnection()
354 kumpf          1.1  {
355 mike           1.41     PEG_METHOD_ENTER(
356                             TRC_LISTENER,
357                             "CIMListenerService::stopClientConnection()");
358 kumpf          1.1  
359 kumpf          1.10     // tell Monitor to stop listening for client connections
360 chuck          1.22     _monitor->stopListeningForConnections(true);
361 dave.sudlik    1.48     if (_ip6Acceptor != NULL)
362                         {
363                             _ip6Acceptor->closeConnectionSocket();
364                         }
365                         if (_ip4Acceptor != NULL)
366                         {
367                             _ip4Acceptor->closeConnectionSocket();
368                         }
369 kumpf          1.4      PEG_METHOD_EXIT();
370 kumpf          1.1  }
371                     
372 chuck          1.23 Uint32 CIMListenerService::getOutstandingRequestCount()
373                     {
374 dave.sudlik    1.48     Uint32 cnt = 0;
375 venkat.puvvada 1.50 
376                         if (_ip6Acceptor)
377                         {
378                             cnt = _ip6Acceptor->getOutstandingRequestCount();
379                         }
380                     
381                         if (_ip4Acceptor)
382                         {
383                             cnt += _ip4Acceptor->getOutstandingRequestCount();
384                         }
385 dave.sudlik    1.48 
386                         return cnt;
387 chuck          1.23 }
388 tony           1.8  
389 karl           1.49 CIMListenerIndicationDispatcher*
390 mike           1.41 CIMListenerService::getIndicationDispatcher() const
391 kumpf          1.1  {
392 david.dillard  1.32     return _dispatcher;
393 tony           1.8  }
394 david.dillard  1.34 
395 mike           1.41 void CIMListenerService::setIndicationDispatcher(
396                         CIMListenerIndicationDispatcher* dispatcher)
397 tony           1.8  {
398 david.dillard  1.32     _dispatcher = dispatcher;
399 kumpf          1.1  }
400                     
401 jsafrane       1.60 String CIMListenerService::getListenAddress() const
402                     {
403                         bool listenAddressEmpty = _listenAddress == String::EMPTY;
404                     
405                         if (listenAddressEmpty && _ip6Acceptor != 0)
406                             return _ip6Acceptor->getListenAddress();
407                         else if (listenAddressEmpty && _ip4Acceptor != 0)
408                             return _ip4Acceptor->getListenAddress();
409                     
410                         return _listenAddress;
411                     }
412                     
413 david.dillard  1.34 Uint32 CIMListenerService::getPortNumber() const
414                     {
415                         Uint32 portNumber = _portNumber;
416                     
417 dave.sudlik    1.48     if ((portNumber == 0) && (_ip6Acceptor != 0))
418 david.dillard  1.34     {
419 dave.sudlik    1.48         portNumber = _ip6Acceptor->getPortNumber();
420 david.dillard  1.34     }
421 venkat.puvvada 1.50     else if ((portNumber == 0) && (_ip4Acceptor != 0))
422 dave.sudlik    1.48     {
423                             portNumber = _ip4Acceptor->getPortNumber();
424                         }
425 david.dillard  1.34 
426 mike           1.41     return (portNumber);
427 david.dillard  1.34 }
428                     
429 karl           1.49 ThreadReturnType PEGASUS_THREAD_CDECL
430 mike           1.41 CIMListenerService::_listener_routine(void *param)
431 kumpf          1.1  {
432 mike           1.41     CIMListenerService *svc = reinterpret_cast < CIMListenerService * >(param);
433 kumpf          1.1  
434 mike           1.41     try
435 david.dillard  1.32     {
436 mike           1.41         // svc->init(); bug 1394
437                             while (!svc->terminated())
438                             {
439 mike           1.46 #if defined(PEGASUS_OS_DARWIN)
440 mike           1.41             pthread_testcancel();
441 chuck          1.20 #endif
442 mike           1.41             svc->runForever();
443                             }
444 david.dillard  1.32     }
445 mike           1.41     catch(...)
446                         {
447 marek          1.55         PEG_TRACE_CSTRING(TRC_SERVER, Tracer::LEVEL1,
448 mike           1.41                       "Unknown exception thrown in _listener_routine.");
449                         }
450                     
451                         // CAUTION: deleting the service also deletes the monitor whose tickle()
452                         // method may still be executing in another thread. This line of code was
453                         // most likely reached when the CIMListenerService::shutdown() method set
454                         // _dieNow to true and called Monitor::tickle(). We must wait until we
455                         // can obtain the _monitorMutex, indicating that we are no longer inside
456                         // Monitor::tickle().
457 mike           1.42     svc->_monitorMutex.lock();
458 mike           1.41     svc->_monitorMutex.unlock();
459                         delete svc;
460                     
461 david.dillard  1.32     return 0;
462 tony           1.8  }
463                     
464 mike           1.41 ////////////////////////////////////////////////////////////////////////////////
465                     //
466 tony           1.8  // CIMListenerRep
467 mike           1.41 //
468                     ////////////////////////////////////////////////////////////////////////////////
469                     
470 tony           1.8  class CIMListenerRep
471                     {
472                     public:
473 jsafrane       1.60     CIMListenerRep(
474                             const String &listenAddress,
475                             Uint32 portNumber,
476                             SSLContext* sslContext = NULL);
477 mike           1.41     CIMListenerRep(Uint32 portNumber, SSLContext * sslContext = NULL);
478                         ~CIMListenerRep();
479 tony           1.8  
480 jsafrane       1.60     String getListenAddress() const;
481 mike           1.41     Uint32 getPortNumber() const;
482 tony           1.8  
483 mike           1.41     SSLContext *getSSLContext() const;
484                         void setSSLContext(SSLContext * sslContext);
485 david.dillard  1.31 
486 mike           1.41     void start();
487                         void stop();
488 tony           1.8  
489 mike           1.41     Boolean isAlive();
490 tony           1.8  
491 mike           1.41     Boolean addConsumer(CIMIndicationConsumer * consumer);
492                         Boolean removeConsumer(CIMIndicationConsumer * consumer);
493 tony           1.8  
494                     private:
495 mike           1.41     Boolean waitForPendingRequests(Uint32 shutdownTimeout);
496 chuck          1.23 
497 jsafrane       1.60     String _listenAddress;
498 mike           1.41     Uint32 _portNumber;
499                         SSLContext *_sslContext;
500 tony           1.8  
501 mike           1.41     CIMListenerIndicationDispatcher *_dispatcher;
502                         ThreadPool *_thread_pool;
503                         CIMListenerService *_svc;
504                         Semaphore *_listener_sem;
505 tony           1.8  };
506                     
507 mike           1.41 CIMListenerRep::CIMListenerRep(
508 jsafrane       1.60     const String &listenAddress,
509 karl           1.49     Uint32 portNumber,
510 mike           1.41     SSLContext * sslContext)
511                         :
512 jsafrane       1.60     _listenAddress(listenAddress),
513                         _portNumber(portNumber),
514                         _sslContext(sslContext),
515                         _dispatcher(new CIMListenerIndicationDispatcher()),
516                         _thread_pool(NULL),
517                         _svc(NULL),
518                         _listener_sem(NULL)
519                     {
520                     }
521                     
522                     CIMListenerRep::CIMListenerRep(
523                         Uint32 portNumber,
524                         SSLContext * sslContext)
525                         :
526                         _listenAddress(),
527 karl           1.49     _portNumber(portNumber),
528 mike           1.41     _sslContext(sslContext),
529 karl           1.49     _dispatcher(new CIMListenerIndicationDispatcher()),
530 mike           1.41     _thread_pool(NULL),
531 karl           1.49     _svc(NULL),
532 mike           1.41     _listener_sem(NULL)
533 tony           1.8  {
534                     }
535 david.dillard  1.31 
536 tony           1.8  CIMListenerRep::~CIMListenerRep()
537                     {
538 kumpf          1.51     stop();
539 chuck          1.20 
540                         delete _sslContext;
541                         delete _dispatcher;
542                         delete _thread_pool;
543                         delete _listener_sem;
544 tony           1.8  
545 mike           1.41     // don't delete _svc, this is deleted by _listener_routine
546 tony           1.8  }
547                     
548 jsafrane       1.60 String CIMListenerRep::getListenAddress() const
549                     {
550                         return !_svc ? _listenAddress : _svc->getListenAddress();
551                     }
552                     
553 tony           1.8  Uint32 CIMListenerRep::getPortNumber() const
554                     {
555 david.dillard  1.34     Uint32 portNumber;
556                     
557 mike           1.41     if (_svc == 0)
558 david.dillard  1.34         portNumber = _portNumber;
559 mike           1.41     else
560                             portNumber = _svc->getPortNumber();
561 david.dillard  1.34 
562                         return portNumber;
563 tony           1.8  }
564 kumpf          1.1  
565 mike           1.41 SSLContext *CIMListenerRep::getSSLContext() const
566 tony           1.8  {
567 david.dillard  1.31     return _sslContext;
568 kumpf          1.1  }
569 david.dillard  1.31 
570 mike           1.41 void CIMListenerRep::setSSLContext(SSLContext * sslContext)
571 tony           1.8  {
572 david.dillard  1.31     delete _sslContext;
573                         _sslContext = sslContext;
574                     }
575 kumpf          1.1  
576 tony           1.8  void CIMListenerRep::start()
577 kumpf          1.1  {
578 david.dillard  1.31     // spawn a thread to do this
579 mike           1.41     if (_thread_pool == 0)
580 chuck          1.20     {
581 mike           1.41         AutoPtr < CIMListenerService >
582 jsafrane       1.60             svc(new CIMListenerService(_listenAddress, _portNumber,
583                                         _sslContext));
584 chuck          1.20 
585 david.dillard  1.31         svc->setIndicationDispatcher(_dispatcher);
586                             svc->init();
587 chuck          1.20 
588 mike           1.41         struct timeval deallocateWait = { 15, 0 };
589                             AutoPtr < ThreadPool >
590                                 threadPool(new ThreadPool(0, "Listener", 0, 1, deallocateWait));
591                             AutoPtr < Semaphore > sem(new Semaphore(0));
592                     
593                             if (threadPool->allocate_and_awaken(
594 karl           1.49             svc.get(), CIMListenerService::_listener_routine, sem.get())
595 mike           1.41             != PEGASUS_THREAD_OK)
596                             {
597 marek          1.47             PEG_TRACE_CSTRING(
598 karl           1.49                 TRC_SERVER,
599 marek          1.53                 Tracer::LEVEL1,
600 mike           1.41                 "Could not allocate thread for "
601                                     "CIMListenerService::_listener_routine.");
602                                 throw
603                                     Exception(MessageLoaderParms(
604                                         "Listener.CIMListener.CANNOT_ALLOCATE_THREAD",
605                                         "Could not allocate thread."));
606 konrad.r       1.38         }
607 mike           1.41 
608                             Logger::put(
609 karl           1.49             Logger::STANDARD_LOG,
610 mike           1.41             System::CIMLISTENER,
611 karl           1.49             Logger::INFORMATION,
612 mike           1.41             "CIMListener started");
613 david.dillard  1.31 
614                             _svc = svc.release();
615                             _thread_pool = threadPool.release();
616                             _listener_sem = sem.release();
617                         }
618 tony           1.8  }
619 kumpf          1.1  
620 tony           1.8  void CIMListenerRep::stop()
621                     {
622 mike           1.41     if (_thread_pool != NULL)
623 chuck          1.20     {
624 karl           1.49         //
625 mike           1.41         // Graceful shutdown of the listener service
626 karl           1.49         //
627 mike           1.41 
628                             // Block incoming export requests and unbind the port
629                             _svc->stopClientConnection();
630                     
631                             // Wait until pending export requests in the server are done.
632                             waitForPendingRequests(10);
633                     
634                             // Shutdown the CIMListenerService
635                             _svc->shutdown();
636 chuck          1.20 
637 mike           1.41         // Wait for the _listener_routine thread to exit.
638                             // The thread could be delivering an export, so give it 3sec.
639                             // Note that _listener_routine deletes the CIMListenerService,
640                             // so no need to delete _svc.
641 kumpf          1.56         if (!_listener_sem->time_wait(3000))
642 mike           1.41         {
643                                 // No need to do anything, the thread pool will be deleted below
644                                 // to cancel the _listener_routine thread if it is still running.
645                             }
646 david.dillard  1.31 
647 mike           1.41         delete _listener_sem;
648                             _listener_sem = NULL;
649 chuck          1.20 
650 karl           1.49         // Delete the thread pool.  This cancels the listener thread if it is
651 mike           1.41         // still
652                             // running.
653                             delete _thread_pool;
654                             _thread_pool = NULL;
655                     
656                             Logger::put(
657                                 Logger::STANDARD_LOG, System::CIMLISTENER,
658                                 Logger::INFORMATION, "CIMListener stopped");
659                         }
660 kumpf          1.1  }
661                     
662 tony           1.8  Boolean CIMListenerRep::isAlive()
663 kumpf          1.1  {
664 mike           1.41     return (_thread_pool != NULL) ? true : false;
665 tony           1.8  }
666 kumpf          1.1  
667 mike           1.41 Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer * consumer)
668 tony           1.8  {
669 mike           1.41     return _dispatcher->addConsumer(consumer);
670 tony           1.8  }
671 mike           1.41 
672                     Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer * consumer)
673 tony           1.8  {
674 mike           1.41     return _dispatcher->removeConsumer(consumer);
675 tony           1.8  }
676 kumpf          1.1  
677 chuck          1.23 Boolean CIMListenerRep::waitForPendingRequests(Uint32 shutdownTimeout)
678                     {
679 mike           1.41     // Wait for 10 sec max
680                         Uint32 reqCount;
681                         Uint32 countDown = shutdownTimeout * 10;
682                     
683                         for (; countDown > 0; countDown--)
684                         {
685                             reqCount = _svc->getOutstandingRequestCount();
686                             if (reqCount > 0)
687 mike           1.42             Threads::sleep(100);
688 mike           1.41         else
689                                 return true;
690                         }
691 david.dillard  1.31 
692 mike           1.41     return false;
693 david.dillard  1.31 }
694 chuck          1.23 
695 tony           1.8  /////////////////////////////////////////////////////////////////////////////
696 mike           1.41 //
697 tony           1.8  // CIMListener
698 mike           1.41 //
699 tony           1.8  /////////////////////////////////////////////////////////////////////////////
700 mike           1.41 
701                     CIMListener::CIMListener(
702 jsafrane       1.60     const String &listenAddress,
703                         Uint32 portNumber,
704                         SSLContext* sslContext)
705                         :
706                         _rep(new CIMListenerRep(listenAddress, portNumber, sslContext))
707                     {
708                     }
709                     
710                     CIMListener::CIMListener(
711 karl           1.49     Uint32 portNumber,
712                         SSLContext * sslContext)
713 mike           1.41     :
714                         _rep(new CIMListenerRep(portNumber, sslContext))
715 tony           1.8  {
716                     }
717 mike           1.41 
718 tony           1.8  CIMListener::~CIMListener()
719                     {
720 mike           1.41     if (_rep != NULL)
721                             delete static_cast < CIMListenerRep * >(_rep);
722                         _rep = NULL;
723 tony           1.8  }
724 david.dillard  1.31 
725 jsafrane       1.60 String CIMListener::getListenAddress() const
726                     {
727                         return static_cast < CIMListenerRep * >(_rep)->getListenAddress();
728                     }
729                     
730 tony           1.8  Uint32 CIMListener::getPortNumber() const
731                     {
732 mike           1.41     return static_cast < CIMListenerRep * >(_rep)->getPortNumber();
733 kumpf          1.1  }
734                     
735 mike           1.41 SSLContext *CIMListener::getSSLContext() const
736 tony           1.8  {
737 mike           1.41     return static_cast < CIMListenerRep * >(_rep)->getSSLContext();
738 tony           1.8  }
739 mike           1.41 
740                     void CIMListener::setSSLContext(SSLContext * sslContext)
741 tony           1.8  {
742 mike           1.41     static_cast < CIMListenerRep * >(_rep)->setSSLContext(sslContext);
743 tony           1.8  }
744 mike           1.41 
745 tony           1.8  void CIMListener::start()
746 kumpf          1.1  {
747 mike           1.41     static_cast < CIMListenerRep * >(_rep)->start();
748 tony           1.8  }
749 mike           1.41 
750 tony           1.8  void CIMListener::stop()
751                     {
752 mike           1.41     static_cast < CIMListenerRep * >(_rep)->stop();
753 tony           1.8  }
754 kumpf          1.1  
755 aruran.ms      1.35 Boolean CIMListener::isAlive() const
756 tony           1.8  {
757 mike           1.41     return static_cast < CIMListenerRep * >(_rep)->isAlive();
758 tony           1.8  }
759 kumpf          1.1  
760 mike           1.41 Boolean CIMListener::addConsumer(CIMIndicationConsumer * consumer)
761 tony           1.8  {
762 mike           1.41     return static_cast < CIMListenerRep * >(_rep)->addConsumer(consumer);
763 tony           1.8  }
764 mike           1.41 
765                     Boolean CIMListener::removeConsumer(CIMIndicationConsumer * consumer)
766 tony           1.8  {
767 mike           1.41     return static_cast < CIMListenerRep * >(_rep)->removeConsumer(consumer);
768 kumpf          1.1  }
769                     
770                     PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2