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 tony 1.8 svc->init();
318 while(!svc->terminated())
319 {
320 svc->runForever();
321 }
322 delete svc;
323
324 return 0;
325 }
326 static struct timeval create_time = {0, 1};
327 static struct timeval destroy_time = {15, 0};
328 static struct timeval deadlock_time = {0, 0};
329
330 /////////////////////////////////////////////////////////////////////////////
331 // CIMListenerRep
332 /////////////////////////////////////////////////////////////////////////////
333 class CIMListenerRep
334 {
335 public:
336 CIMListenerRep(Uint32 portNumber, SSLContext* sslContext=NULL);
337 ~CIMListenerRep();
338 tony 1.8
339 Uint32 getPortNumber() const;
340
341 SSLContext* getSSLContext() const;
342 void setSSLContext(SSLContext* sslContext);
343
344 void start();
345 void stop();
346
347 Boolean isAlive();
348
349 Boolean addConsumer(CIMIndicationConsumer* consumer);
350 Boolean removeConsumer(CIMIndicationConsumer* consumer);
351
352 private:
353 Uint32 _portNumber;
354 SSLContext* _sslContext;
355
356 CIMListenerIndicationDispatcher* _dispatcher;
357 ThreadPool* _thread_pool;
358 };
359 tony 1.8
360 CIMListenerRep::CIMListenerRep(Uint32 portNumber, SSLContext* sslContext)
361 :_portNumber(portNumber)
362 ,_sslContext(sslContext)
363 ,_dispatcher(new CIMListenerIndicationDispatcher())
364 ,_thread_pool(NULL)
365 {
366 }
367 CIMListenerRep::~CIMListenerRep()
368 {
369 // if port is alive, clean up the port
370 if(_sslContext!=NULL)
371 delete _sslContext;
372
373 if(_dispatcher!=NULL)
374 delete _dispatcher;
375
376 if(_thread_pool!=NULL)
377 delete _thread_pool;
378 }
379
380 tony 1.8 Uint32 CIMListenerRep::getPortNumber() const
381 {
382 return _portNumber;
383 }
|
384 kumpf 1.1
|
385 tony 1.8 SSLContext* CIMListenerRep::getSSLContext() const
386 {
387 return _sslContext;
|
388 kumpf 1.1 }
|
389 tony 1.8 void CIMListenerRep::setSSLContext(SSLContext* sslContext)
390 {
391 if(_sslContext!=NULL)
392 delete _sslContext;
|
393 kumpf 1.1
|
394 tony 1.8 _sslContext = sslContext;
395 }
396 void CIMListenerRep::start()
|
397 kumpf 1.1 {
|
398 tony 1.8 // spawn a thread to do this
399 if(_thread_pool==NULL)
400 {
401 _thread_pool = new ThreadPool(0, "Listener", 0, 1,
402 create_time, destroy_time, deadlock_time);
403
404 CIMListenerService* svc = new CIMListenerService(_portNumber,_sslContext);
405 svc->setIndicationDispatcher(_dispatcher);
406
407 _thread_pool->allocate_and_awaken(svc,CIMListenerService::_listener_routine);
408
409 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
410 Logger::INFORMATION,
411 "CIMListener started");
|
412 kumpf 1.1
|
413 tony 1.8 PEGASUS_STD(cerr) << "CIMlistener started" << PEGASUS_STD(endl);
414 }
415 }
|
416 kumpf 1.1
|
417 tony 1.8 void CIMListenerRep::stop()
418 {
419 if(_thread_pool!=NULL)
420 { // stop the thread
421
422 delete _thread_pool;
423
424 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
425 Logger::INFORMATION,
426 "CIMListener stopped");
427 }
|
428 kumpf 1.1 }
429
|
430 tony 1.8 Boolean CIMListenerRep::isAlive()
|
431 kumpf 1.1 {
|
432 tony 1.8 return (_thread_pool!=NULL)?true:false;
433 }
|
434 kumpf 1.1
|
435 tony 1.8 Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer* consumer)
436 {
437 return _dispatcher->addConsumer(consumer);
438 }
439 Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer* consumer)
440 {
441 return _dispatcher->removeConsumer(consumer);
442 }
|
443 kumpf 1.1
|
444 tony 1.8 /////////////////////////////////////////////////////////////////////////////
445 // CIMListener
446 /////////////////////////////////////////////////////////////////////////////
447 CIMListener::CIMListener(Uint32 portNumber, SSLContext* sslContext)
448 :_rep(new CIMListenerRep(portNumber,sslContext))
449 {
450 }
451 CIMListener::~CIMListener()
452 {
453 if(_rep!=NULL)
|
454 tony 1.9 delete static_cast<CIMListenerRep*>(_rep);
|
455 tony 1.8 _rep=NULL;
456 }
457
458 Uint32 CIMListener::getPortNumber() const
459 {
460 return static_cast<CIMListenerRep*>(_rep)->getPortNumber();
|
461 kumpf 1.1 }
462
|
463 tony 1.8 SSLContext* CIMListener::getSSLContext() const
464 {
465 return static_cast<CIMListenerRep*>(_rep)->getSSLContext();
466 }
467 void CIMListener::setSSLContext(SSLContext* sslContext)
468 {
469 static_cast<CIMListenerRep*>(_rep)->setSSLContext(sslContext);
470 }
471 void CIMListener::start()
|
472 kumpf 1.1 {
|
473 tony 1.8 static_cast<CIMListenerRep*>(_rep)->start();
474 }
475 void CIMListener::stop()
476 {
477 static_cast<CIMListenerRep*>(_rep)->stop();
478 }
|
479 kumpf 1.1
|
480 tony 1.8 Boolean CIMListener::isAlive()
481 {
482 return static_cast<CIMListenerRep*>(_rep)->isAlive();
483 }
|
484 kumpf 1.1
|
485 tony 1.8 Boolean CIMListener::addConsumer(CIMIndicationConsumer* consumer)
486 {
487 return static_cast<CIMListenerRep*>(_rep)->addConsumer(consumer);
488 }
489 Boolean CIMListener::removeConsumer(CIMIndicationConsumer* consumer)
490 {
491 return static_cast<CIMListenerRep*>(_rep)->removeConsumer(consumer);
|
492 kumpf 1.1 }
493
494 PEGASUS_NAMESPACE_END
|