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 _sslContext);
|
190 dj.gorey 1.14 #else
191 _acceptor = new pegasus_acceptor(_monitor,
192 _requestDecoder,
193 false,
194 _portNumber,
195 _sslContext);
196 #endif
|
197 kumpf 1.1
|
198 tony 1.8 bind();
|
199 kumpf 1.1
|
200 tony 1.8 PEG_METHOD_EXIT();
201 }
202 void CIMListenerService::bind()
203 {
204 if(_acceptor!=NULL)
205 { // Bind to the port
206 _acceptor->bind();
207
208 PEGASUS_STD(cout) << "Listening on HTTP port " << _portNumber << PEGASUS_STD(endl);
209
210 //listener.addAcceptor(false, portNumberHttp, false);
211 Logger::put(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION,
212 "Listening on HTTP port $0.", _portNumber);
|
213 kumpf 1.1
|
214 tony 1.8 }
215 }
216 void CIMListenerService::runForever()
217 {
218 static int modulator = 0;
|
219 kumpf 1.1
|
220 tony 1.8 if(!_dieNow)
221 {
|
222 dj.gorey 1.15 #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
|
223 dj.gorey 1.14 if(false == _monitor->run(100))
224 {
|
225 tony 1.8 modulator++;
226 if(!(modulator % 5000) )
227 {
228 try
229 {
230 //MessageQueueService::_check_idle_flag = 1;
231 //MessageQueueService::_polling_sem.signal();
|
232 kumpf 1.13 MessageQueueService::get_thread_pool()->kill_idle_threads();
|
233 tony 1.8 }
234 catch(...)
235 {
236 }
237 }
238 }
239 /*
240 if (handleShutdownSignal)
241 {
242 Tracer::trace(TRC_SERVER, Tracer::LEVEL3,
243 "CIMServer::runForever - signal received. Shutting down.");
244
245 ShutdownService::getInstance(this)->shutdown(true, 10, false);
246 handleShutdownSignal = false;
247 }
248 */
|
249 dj.gorey 1.14 #else
250 _monitor->run();
251 #endif
252 }
|
253 tony 1.8 }
|
254 kumpf 1.1
|
255 tony 1.8 void CIMListenerService::shutdown()
256 {
257 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::shutdown()");
|
258 kumpf 1.1
|
259 tony 1.8 _dieNow = true;
|
260 kumpf 1.1
|
261 kumpf 1.4 PEG_METHOD_EXIT();
|
262 kumpf 1.1 }
263
|
264 tony 1.8 void CIMListenerService::resume()
|
265 kumpf 1.1 {
|
266 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()");
|
267 kumpf 1.1
|
268 tony 1.8 if(_acceptor!=NULL)
269 _acceptor->reopenConnectionSocket();
|
270 kumpf 1.1
|
271 kumpf 1.4 PEG_METHOD_EXIT();
|
272 kumpf 1.1 }
273
|
274 tony 1.8 void CIMListenerService::stopClientConnection()
|
275 kumpf 1.1 {
|
276 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::stopClientConnection()");
|
277 kumpf 1.1
|
278 kumpf 1.10 // tell Monitor to stop listening for client connections
|
279 dj.gorey 1.15 #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
|
280 kumpf 1.10 _monitor->stopListeningForConnections();
|
281 dj.gorey 1.14 #else
282 _monitor->stop();
283 #endif
|
284 kumpf 1.10
285 //
286 // Wait 150 milliseconds to allow time for the Monitor to stop
287 // listening for client connections.
288 //
289 // This wait time is the timeout value for the select() call
290 // in the Monitor's run() method (currently set to 100
291 // milliseconds) plus a delta of 50 milliseconds. The reason
292 // for the wait here is to make sure that the Monitor entries
293 // are updated before closing the connection sockets.
294 //
295 pegasus_sleep(150);
296
|
297 tony 1.8 if(_acceptor!=NULL)
298 _acceptor->closeConnectionSocket();
|
299 kumpf 1.1
|
300 kumpf 1.4 PEG_METHOD_EXIT();
|
301 kumpf 1.1 }
302
|
303 tony 1.8
304 CIMListenerIndicationDispatcher* CIMListenerService::getIndicationDispatcher() const
|
305 kumpf 1.1 {
|
306 tony 1.8 return _dispatcher;
307 }
308 void CIMListenerService::setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher)
309 {
310 _dispatcher = dispatcher;
|
311 kumpf 1.1 }
312
|
313 tony 1.8 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL CIMListenerService::_listener_routine(void *param)
|
314 kumpf 1.1 {
|
315 tony 1.8 CIMListenerService *svc = reinterpret_cast<CIMListenerService *>(param);
|
316 kumpf 1.1
|
317 chuck 1.17 // svc->init(); bug 1394
|
318 tony 1.8 while(!svc->terminated())
319 {
|
320 dudhe.girish 1.18 #if defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
321 pthread_testcancel();
322 #endif
|
323 tony 1.8 svc->runForever();
324 }
325 delete svc;
326
327 return 0;
328 }
329 static struct timeval create_time = {0, 1};
330 static struct timeval destroy_time = {15, 0};
331 static struct timeval deadlock_time = {0, 0};
332
333 /////////////////////////////////////////////////////////////////////////////
334 // CIMListenerRep
335 /////////////////////////////////////////////////////////////////////////////
336 class CIMListenerRep
337 {
338 public:
339 CIMListenerRep(Uint32 portNumber, SSLContext* sslContext=NULL);
340 ~CIMListenerRep();
341
342 Uint32 getPortNumber() const;
343
344 tony 1.8 SSLContext* getSSLContext() const;
345 void setSSLContext(SSLContext* sslContext);
346
347 void start();
348 void stop();
349
350 Boolean isAlive();
351
352 Boolean addConsumer(CIMIndicationConsumer* consumer);
353 Boolean removeConsumer(CIMIndicationConsumer* consumer);
354
355 private:
356 Uint32 _portNumber;
357 SSLContext* _sslContext;
358
359 CIMListenerIndicationDispatcher* _dispatcher;
360 ThreadPool* _thread_pool;
361 };
362
363 CIMListenerRep::CIMListenerRep(Uint32 portNumber, SSLContext* sslContext)
364 :_portNumber(portNumber)
365 tony 1.8 ,_sslContext(sslContext)
366 ,_dispatcher(new CIMListenerIndicationDispatcher())
367 ,_thread_pool(NULL)
368 {
369 }
370 CIMListenerRep::~CIMListenerRep()
371 {
372 // if port is alive, clean up the port
373 if(_sslContext!=NULL)
374 delete _sslContext;
375
376 if(_dispatcher!=NULL)
377 delete _dispatcher;
378
379 if(_thread_pool!=NULL)
380 delete _thread_pool;
381 }
382
383 Uint32 CIMListenerRep::getPortNumber() const
384 {
385 return _portNumber;
386 tony 1.8 }
|
387 kumpf 1.1
|
388 tony 1.8 SSLContext* CIMListenerRep::getSSLContext() const
389 {
390 return _sslContext;
|
391 kumpf 1.1 }
|
392 tony 1.8 void CIMListenerRep::setSSLContext(SSLContext* sslContext)
393 {
394 if(_sslContext!=NULL)
395 delete _sslContext;
|
396 kumpf 1.1
|
397 tony 1.8 _sslContext = sslContext;
398 }
399 void CIMListenerRep::start()
|
400 kumpf 1.1 {
|
401 tony 1.8 // spawn a thread to do this
402 if(_thread_pool==NULL)
403 {
|
404 chuck 1.17 CIMListenerService* svc = new CIMListenerService(_portNumber,_sslContext);
405 try
406 {
407 // Try to initialize the service (bug 1394)
408 svc->setIndicationDispatcher(_dispatcher);
409 svc->init();
410 }
411 catch(...)
412 {
413 // Error. Exit without creating the ThreadPool, so that this listener
414 // is not 'alive'
415 delete svc;
416 throw;
417 }
418
|
419 tony 1.8 _thread_pool = new ThreadPool(0, "Listener", 0, 1,
420 create_time, destroy_time, deadlock_time);
421
422 _thread_pool->allocate_and_awaken(svc,CIMListenerService::_listener_routine);
423
424 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
425 Logger::INFORMATION,
426 "CIMListener started");
|
427 kumpf 1.1
|
428 tony 1.8 PEGASUS_STD(cerr) << "CIMlistener started" << PEGASUS_STD(endl);
429 }
430 }
|
431 kumpf 1.1
|
432 tony 1.8 void CIMListenerRep::stop()
433 {
434 if(_thread_pool!=NULL)
435 { // stop the thread
436
437 delete _thread_pool;
|
438 chuck 1.16 _thread_pool = NULL;
|
439 tony 1.8
440 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
441 Logger::INFORMATION,
442 "CIMListener stopped");
443 }
|
444 kumpf 1.1 }
445
|
446 tony 1.8 Boolean CIMListenerRep::isAlive()
|
447 kumpf 1.1 {
|
448 tony 1.8 return (_thread_pool!=NULL)?true:false;
449 }
|
450 kumpf 1.1
|
451 tony 1.8 Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer* consumer)
452 {
453 return _dispatcher->addConsumer(consumer);
454 }
455 Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer* consumer)
456 {
457 return _dispatcher->removeConsumer(consumer);
458 }
|
459 kumpf 1.1
|
460 tony 1.8 /////////////////////////////////////////////////////////////////////////////
461 // CIMListener
462 /////////////////////////////////////////////////////////////////////////////
463 CIMListener::CIMListener(Uint32 portNumber, SSLContext* sslContext)
464 :_rep(new CIMListenerRep(portNumber,sslContext))
465 {
466 }
467 CIMListener::~CIMListener()
468 {
469 if(_rep!=NULL)
|
470 tony 1.9 delete static_cast<CIMListenerRep*>(_rep);
|
471 tony 1.8 _rep=NULL;
472 }
473
474 Uint32 CIMListener::getPortNumber() const
475 {
476 return static_cast<CIMListenerRep*>(_rep)->getPortNumber();
|
477 kumpf 1.1 }
478
|
479 tony 1.8 SSLContext* CIMListener::getSSLContext() const
480 {
481 return static_cast<CIMListenerRep*>(_rep)->getSSLContext();
482 }
483 void CIMListener::setSSLContext(SSLContext* sslContext)
484 {
485 static_cast<CIMListenerRep*>(_rep)->setSSLContext(sslContext);
486 }
487 void CIMListener::start()
|
488 kumpf 1.1 {
|
489 tony 1.8 static_cast<CIMListenerRep*>(_rep)->start();
490 }
491 void CIMListener::stop()
492 {
493 static_cast<CIMListenerRep*>(_rep)->stop();
494 }
|
495 kumpf 1.1
|
496 tony 1.8 Boolean CIMListener::isAlive()
497 {
498 return static_cast<CIMListenerRep*>(_rep)->isAlive();
499 }
|
500 kumpf 1.1
|
501 tony 1.8 Boolean CIMListener::addConsumer(CIMIndicationConsumer* consumer)
502 {
503 return static_cast<CIMListenerRep*>(_rep)->addConsumer(consumer);
504 }
505 Boolean CIMListener::removeConsumer(CIMIndicationConsumer* consumer)
506 {
507 return static_cast<CIMListenerRep*>(_rep)->removeConsumer(consumer);
|
508 kumpf 1.1 }
509
510 PEGASUS_NAMESPACE_END
|