1 karl 1.12 //%2003////////////////////////////////////////////////////////////////////////
|
2 kumpf 1.1 //
|
3 karl 1.12 // 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 // IBM Corp.; EMC Corporation, The Open Group.
|
7 kumpf 1.1 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
|
14 kumpf 1.3 //
|
15 kumpf 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
16 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
17 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //==============================================================================
25 //
|
26 tony 1.8 // Author: Dong Xiang, EMC Corporation (xiang_dong@emc.com)
|
27 kumpf 1.1 //
|
28 dj.gorey 1.14 // Modified By: Dan Gorey (djgorey@us.ibm.com)
|
29 kumpf 1.1 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
|
32 tony 1.8 #include "CIMListener.h"
|
33 kumpf 1.1
|
34 tony 1.8 #include <Pegasus/Common/Exception.h>
35 #include <Pegasus/Common/SSLContext.h>
36 #include <Pegasus/Common/Monitor.h>
|
37 kumpf 1.1 #include <Pegasus/Common/HTTPAcceptor.h>
|
38 kumpf 1.11 #include <Pegasus/Common/PegasusVersion.h>
|
39 kumpf 1.2
|
40 kumpf 1.1 #include <Pegasus/ExportServer/CIMExportResponseEncoder.h>
41 #include <Pegasus/ExportServer/CIMExportRequestDecoder.h>
42
|
43 tony 1.8 #include <Pegasus/Consumer/CIMIndicationConsumer.h>
44 #include <Pegasus/Listener/CIMListenerIndicationDispatcher.h>
45
46 PEGASUS_NAMESPACE_BEGIN
47 /////////////////////////////////////////////////////////////////////////////
48 // CIMListenerService
49 /////////////////////////////////////////////////////////////////////////////
50 class CIMListenerService
51 {
52 public:
53 CIMListenerService(Uint32 portNumber, SSLContext* sslContext=NULL);
54 CIMListenerService(CIMListenerService& svc);
55 ~CIMListenerService();
56
57 void init();
58 /** bind to the port
59 */
60 void bind();
61 /** runForever Main runloop for the server.
62 */
63 void runForever();
64 tony 1.8
65 /** Call to gracefully shutdown the server. The server connection socket
66 will be closed to disable new connections from clients.
67 */
68 void stopClientConnection();
69
70 /** Call to gracefully shutdown the server. It is called when the server
71 has been stopped and is ready to be shutdown. Next time runForever()
72 is called, the server shuts down.
73 */
74 void shutdown();
75
76 /** Return true if the server has shutdown, false otherwise.
77 */
78 Boolean terminated() { return _dieNow; };
79
80 /** Call to resume the sever.
81 */
82 void resume();
83
84 /** Call to set the CIMServer state. Also inform the appropriate
85 tony 1.8 message queues about the current state of the CIMServer.
86 */
87 void setState(Uint32 state);
88
89 Uint32 getOutstandingRequestCount();
90
91 /** Returns the indication listener dispatcher
92 */
93 CIMListenerIndicationDispatcher* getIndicationDispatcher() const;
94
95 /** Returns the indication listener dispatcher
96 */
97 void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher);
98
99 static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _listener_routine(void *param);
100
101 private:
102 Uint32 _portNumber;
103 SSLContext* _sslContext;
|
104 dj.gorey 1.15 #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
|
105 tony 1.8 Monitor* _monitor;
106 HTTPAcceptor* _acceptor;
|
107 dj.gorey 1.14 #else
108 monitor_2* _monitor;
109 pegasus_acceptor* _acceptor;
110 #endif
111
112 Boolean _dieNow;
|
113 tony 1.8
114 CIMListenerIndicationDispatcher* _dispatcher;
115
116 CIMExportResponseEncoder* _responseEncoder;
117 CIMExportRequestDecoder* _requestDecoder;
118
119 };
120
121 CIMListenerService::CIMListenerService(Uint32 portNumber, SSLContext* sslContext)
122 :_portNumber(portNumber)
123 ,_sslContext(sslContext)
124 ,_monitor(NULL)
125 ,_acceptor(NULL)
126 ,_dieNow(false)
127 ,_dispatcher(NULL)
128 ,_responseEncoder(NULL)
129 ,_requestDecoder(NULL)
130 {
131 }
132
133 CIMListenerService::CIMListenerService(CIMListenerService& svc)
134 tony 1.8 :_portNumber(svc._portNumber)
135 ,_sslContext(svc._sslContext)
136 ,_monitor(NULL)
137 ,_acceptor(NULL)
138 ,_dieNow(svc._dieNow)
139 ,_dispatcher(NULL)
140 ,_responseEncoder(NULL)
141 ,_requestDecoder(NULL)
142 {
143 }
144 CIMListenerService::~CIMListenerService()
145 {
146 // if port is alive, clean up the port
147 //if(_sslContext!=NULL)
148 // delete _sslContext;
149
150 if(_responseEncoder!=NULL)
151 delete _responseEncoder;
152
153 if(_requestDecoder!=NULL)
154 delete _requestDecoder;
|
155 kumpf 1.1
|
156 tony 1.8 //if(_dispatcher!=NULL)
157 // delete _dispatcher;
|
158 kumpf 1.1
|
159 tony 1.8 if(_monitor!=NULL)
160 delete _monitor;
|
161 kumpf 1.1
|
162 tony 1.8 if(_acceptor!=NULL)
163 delete _acceptor;
164 }
|
165 kumpf 1.1
|
166 tony 1.8 void CIMListenerService::init()
|
167 kumpf 1.1 {
|
168 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::init");
|
169 kumpf 1.1
|
170 dj.gorey 1.15 #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
|
171 tony 1.8 _monitor = new Monitor(true);
|
172 dj.gorey 1.14 #else
173 _monitor = new monitor_2();
174 #endif
175
|
176 tony 1.8 //_dispatcher = new CIMListenerIndicationDispatcher();
|
177 kumpf 1.1
|
178 tony 1.8 _responseEncoder = new CIMExportResponseEncoder();
179 _requestDecoder = new CIMExportRequestDecoder(
180 _dispatcher,
181 _responseEncoder->getQueueId());
182
|
183 dj.gorey 1.15 #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
|
184 dj.gorey 1.14 _acceptor = new HTTPAcceptor(
|
185 tony 1.8 _monitor,
186 _requestDecoder,
187 false,
188 _portNumber,
|
189 kumpf 1.19 _sslContext,
190 false);
|
191 dj.gorey 1.14 #else
192 _acceptor = new pegasus_acceptor(_monitor,
193 _requestDecoder,
194 false,
195 _portNumber,
196 _sslContext);
197 #endif
|
198 kumpf 1.1
|
199 tony 1.8 bind();
|
200 kumpf 1.1
|
201 tony 1.8 PEG_METHOD_EXIT();
202 }
203 void CIMListenerService::bind()
204 {
205 if(_acceptor!=NULL)
206 { // Bind to the port
207 _acceptor->bind();
208
209 PEGASUS_STD(cout) << "Listening on HTTP port " << _portNumber << PEGASUS_STD(endl);
210
211 //listener.addAcceptor(false, portNumberHttp, false);
212 Logger::put(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION,
213 "Listening on HTTP port $0.", _portNumber);
|
214 kumpf 1.1
|
215 tony 1.8 }
216 }
217 void CIMListenerService::runForever()
218 {
219 static int modulator = 0;
|
220 kumpf 1.1
|
221 tony 1.8 if(!_dieNow)
222 {
|
223 dj.gorey 1.15 #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
|
224 dj.gorey 1.14 if(false == _monitor->run(100))
225 {
|
226 tony 1.8 modulator++;
227 if(!(modulator % 5000) )
228 {
229 try
230 {
231 //MessageQueueService::_check_idle_flag = 1;
232 //MessageQueueService::_polling_sem.signal();
|
233 kumpf 1.13 MessageQueueService::get_thread_pool()->kill_idle_threads();
|
234 tony 1.8 }
235 catch(...)
236 {
237 }
238 }
239 }
240 /*
241 if (handleShutdownSignal)
242 {
243 Tracer::trace(TRC_SERVER, Tracer::LEVEL3,
244 "CIMServer::runForever - signal received. Shutting down.");
245
246 ShutdownService::getInstance(this)->shutdown(true, 10, false);
247 handleShutdownSignal = false;
248 }
249 */
|
250 dj.gorey 1.14 #else
251 _monitor->run();
252 #endif
253 }
|
254 tony 1.8 }
|
255 kumpf 1.1
|
256 tony 1.8 void CIMListenerService::shutdown()
257 {
258 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::shutdown()");
|
259 kumpf 1.1
|
260 tony 1.8 _dieNow = true;
|
261 kumpf 1.1
|
262 kumpf 1.4 PEG_METHOD_EXIT();
|
263 kumpf 1.1 }
264
|
265 tony 1.8 void CIMListenerService::resume()
|
266 kumpf 1.1 {
|
267 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()");
|
268 kumpf 1.1
|
269 tony 1.8 if(_acceptor!=NULL)
270 _acceptor->reopenConnectionSocket();
|
271 kumpf 1.1
|
272 kumpf 1.4 PEG_METHOD_EXIT();
|
273 kumpf 1.1 }
274
|
275 tony 1.8 void CIMListenerService::stopClientConnection()
|
276 kumpf 1.1 {
|
277 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::stopClientConnection()");
|
278 kumpf 1.1
|
279 kumpf 1.10 // tell Monitor to stop listening for client connections
|
280 dj.gorey 1.15 #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
|
281 kumpf 1.10 _monitor->stopListeningForConnections();
|
282 dj.gorey 1.14 #else
283 _monitor->stop();
284 #endif
|
285 kumpf 1.10
286 //
287 // Wait 150 milliseconds to allow time for the Monitor to stop
288 // listening for client connections.
289 //
290 // This wait time is the timeout value for the select() call
291 // in the Monitor's run() method (currently set to 100
292 // milliseconds) plus a delta of 50 milliseconds. The reason
293 // for the wait here is to make sure that the Monitor entries
294 // are updated before closing the connection sockets.
295 //
296 pegasus_sleep(150);
297
|
298 tony 1.8 if(_acceptor!=NULL)
299 _acceptor->closeConnectionSocket();
|
300 kumpf 1.1
|
301 kumpf 1.4 PEG_METHOD_EXIT();
|
302 kumpf 1.1 }
303
|
304 tony 1.8
305 CIMListenerIndicationDispatcher* CIMListenerService::getIndicationDispatcher() const
|
306 kumpf 1.1 {
|
307 tony 1.8 return _dispatcher;
308 }
309 void CIMListenerService::setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher)
310 {
311 _dispatcher = dispatcher;
|
312 kumpf 1.1 }
313
|
314 tony 1.8 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL CIMListenerService::_listener_routine(void *param)
|
315 kumpf 1.1 {
|
316 tony 1.8 CIMListenerService *svc = reinterpret_cast<CIMListenerService *>(param);
|
317 kumpf 1.1
|
318 chuck 1.17 // svc->init(); bug 1394
|
319 tony 1.8 while(!svc->terminated())
320 {
|
321 dudhe.girish 1.18 #if defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
322 pthread_testcancel();
323 #endif
|
324 tony 1.8 svc->runForever();
325 }
326 delete svc;
327
328 return 0;
329 }
330 static struct timeval create_time = {0, 1};
331 static struct timeval destroy_time = {15, 0};
332 static struct timeval deadlock_time = {0, 0};
333
334 /////////////////////////////////////////////////////////////////////////////
335 // CIMListenerRep
336 /////////////////////////////////////////////////////////////////////////////
337 class CIMListenerRep
338 {
339 public:
340 CIMListenerRep(Uint32 portNumber, SSLContext* sslContext=NULL);
341 ~CIMListenerRep();
342
343 Uint32 getPortNumber() const;
344
345 tony 1.8 SSLContext* getSSLContext() const;
346 void setSSLContext(SSLContext* sslContext);
347
348 void start();
349 void stop();
350
351 Boolean isAlive();
352
353 Boolean addConsumer(CIMIndicationConsumer* consumer);
354 Boolean removeConsumer(CIMIndicationConsumer* consumer);
355
356 private:
357 Uint32 _portNumber;
358 SSLContext* _sslContext;
359
360 CIMListenerIndicationDispatcher* _dispatcher;
361 ThreadPool* _thread_pool;
362 };
363
364 CIMListenerRep::CIMListenerRep(Uint32 portNumber, SSLContext* sslContext)
365 :_portNumber(portNumber)
366 tony 1.8 ,_sslContext(sslContext)
367 ,_dispatcher(new CIMListenerIndicationDispatcher())
368 ,_thread_pool(NULL)
369 {
370 }
371 CIMListenerRep::~CIMListenerRep()
372 {
373 // if port is alive, clean up the port
374 if(_sslContext!=NULL)
375 delete _sslContext;
376
377 if(_dispatcher!=NULL)
378 delete _dispatcher;
379
380 if(_thread_pool!=NULL)
381 delete _thread_pool;
382 }
383
384 Uint32 CIMListenerRep::getPortNumber() const
385 {
386 return _portNumber;
387 tony 1.8 }
|
388 kumpf 1.1
|
389 tony 1.8 SSLContext* CIMListenerRep::getSSLContext() const
390 {
391 return _sslContext;
|
392 kumpf 1.1 }
|
393 tony 1.8 void CIMListenerRep::setSSLContext(SSLContext* sslContext)
394 {
395 if(_sslContext!=NULL)
396 delete _sslContext;
|
397 kumpf 1.1
|
398 tony 1.8 _sslContext = sslContext;
399 }
400 void CIMListenerRep::start()
|
401 kumpf 1.1 {
|
402 tony 1.8 // spawn a thread to do this
403 if(_thread_pool==NULL)
404 {
|
405 chuck 1.17 CIMListenerService* svc = new CIMListenerService(_portNumber,_sslContext);
406 try
407 {
408 // Try to initialize the service (bug 1394)
409 svc->setIndicationDispatcher(_dispatcher);
410 svc->init();
411 }
412 catch(...)
413 {
414 // Error. Exit without creating the ThreadPool, so that this listener
415 // is not 'alive'
416 delete svc;
417 throw;
418 }
419
|
420 tony 1.8 _thread_pool = new ThreadPool(0, "Listener", 0, 1,
421 create_time, destroy_time, deadlock_time);
422
423 _thread_pool->allocate_and_awaken(svc,CIMListenerService::_listener_routine);
424
425 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
426 Logger::INFORMATION,
427 "CIMListener started");
|
428 kumpf 1.1
|
429 tony 1.8 PEGASUS_STD(cerr) << "CIMlistener started" << PEGASUS_STD(endl);
430 }
431 }
|
432 kumpf 1.1
|
433 tony 1.8 void CIMListenerRep::stop()
434 {
435 if(_thread_pool!=NULL)
436 { // stop the thread
437
438 delete _thread_pool;
|
439 chuck 1.16 _thread_pool = NULL;
|
440 tony 1.8
441 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
442 Logger::INFORMATION,
443 "CIMListener stopped");
444 }
|
445 kumpf 1.1 }
446
|
447 tony 1.8 Boolean CIMListenerRep::isAlive()
|
448 kumpf 1.1 {
|
449 tony 1.8 return (_thread_pool!=NULL)?true:false;
450 }
|
451 kumpf 1.1
|
452 tony 1.8 Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer* consumer)
453 {
454 return _dispatcher->addConsumer(consumer);
455 }
456 Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer* consumer)
457 {
458 return _dispatcher->removeConsumer(consumer);
459 }
|
460 kumpf 1.1
|
461 tony 1.8 /////////////////////////////////////////////////////////////////////////////
462 // CIMListener
463 /////////////////////////////////////////////////////////////////////////////
464 CIMListener::CIMListener(Uint32 portNumber, SSLContext* sslContext)
465 :_rep(new CIMListenerRep(portNumber,sslContext))
466 {
467 }
468 CIMListener::~CIMListener()
469 {
470 if(_rep!=NULL)
|
471 tony 1.9 delete static_cast<CIMListenerRep*>(_rep);
|
472 tony 1.8 _rep=NULL;
473 }
474
475 Uint32 CIMListener::getPortNumber() const
476 {
477 return static_cast<CIMListenerRep*>(_rep)->getPortNumber();
|
478 kumpf 1.1 }
479
|
480 tony 1.8 SSLContext* CIMListener::getSSLContext() const
481 {
482 return static_cast<CIMListenerRep*>(_rep)->getSSLContext();
483 }
484 void CIMListener::setSSLContext(SSLContext* sslContext)
485 {
486 static_cast<CIMListenerRep*>(_rep)->setSSLContext(sslContext);
487 }
488 void CIMListener::start()
|
489 kumpf 1.1 {
|
490 tony 1.8 static_cast<CIMListenerRep*>(_rep)->start();
491 }
492 void CIMListener::stop()
493 {
494 static_cast<CIMListenerRep*>(_rep)->stop();
495 }
|
496 kumpf 1.1
|
497 tony 1.8 Boolean CIMListener::isAlive()
498 {
499 return static_cast<CIMListenerRep*>(_rep)->isAlive();
500 }
|
501 kumpf 1.1
|
502 tony 1.8 Boolean CIMListener::addConsumer(CIMIndicationConsumer* consumer)
503 {
504 return static_cast<CIMListenerRep*>(_rep)->addConsumer(consumer);
505 }
506 Boolean CIMListener::removeConsumer(CIMIndicationConsumer* consumer)
507 {
508 return static_cast<CIMListenerRep*>(_rep)->removeConsumer(consumer);
|
509 kumpf 1.1 }
510
511 PEGASUS_NAMESPACE_END
|