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
|