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