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.2
|
37 kumpf 1.1 #include <Pegasus/ExportServer/CIMExportResponseEncoder.h>
38 #include <Pegasus/ExportServer/CIMExportRequestDecoder.h>
39
|
40 tony 1.8 #include <Pegasus/Consumer/CIMIndicationConsumer.h>
41 #include <Pegasus/Listener/CIMListenerIndicationDispatcher.h>
42
43 PEGASUS_NAMESPACE_BEGIN
44 /////////////////////////////////////////////////////////////////////////////
45 // CIMListenerService
46 /////////////////////////////////////////////////////////////////////////////
47 class CIMListenerService
48 {
49 public:
50 CIMListenerService(Uint32 portNumber, SSLContext* sslContext=NULL);
51 CIMListenerService(CIMListenerService& svc);
52 ~CIMListenerService();
53
54 void init();
55 /** bind to the port
56 */
57 void bind();
58 /** runForever Main runloop for the server.
59 */
60 void runForever();
61 tony 1.8
62 /** Call to gracefully shutdown the server. The server connection socket
63 will be closed to disable new connections from clients.
64 */
65 void stopClientConnection();
66
67 /** Call to gracefully shutdown the server. It is called when the server
68 has been stopped and is ready to be shutdown. Next time runForever()
69 is called, the server shuts down.
70 */
71 void shutdown();
72
73 /** Return true if the server has shutdown, false otherwise.
74 */
75 Boolean terminated() { return _dieNow; };
76
77 /** Call to resume the sever.
78 */
79 void resume();
80
81 /** Call to set the CIMServer state. Also inform the appropriate
82 tony 1.8 message queues about the current state of the CIMServer.
83 */
84 void setState(Uint32 state);
85
86 Uint32 getOutstandingRequestCount();
87
88 /** Returns the indication listener dispatcher
89 */
90 CIMListenerIndicationDispatcher* getIndicationDispatcher() const;
91
92 /** Returns the indication listener dispatcher
93 */
94 void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher);
95
96 static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _listener_routine(void *param);
97
98 private:
99 Uint32 _portNumber;
100 SSLContext* _sslContext;
101
102 Monitor* _monitor;
103 tony 1.8 HTTPAcceptor* _acceptor;
104 Boolean _dieNow;
105
106 CIMListenerIndicationDispatcher* _dispatcher;
107
108 CIMExportResponseEncoder* _responseEncoder;
109 CIMExportRequestDecoder* _requestDecoder;
110
111 };
112
113 CIMListenerService::CIMListenerService(Uint32 portNumber, SSLContext* sslContext)
114 :_portNumber(portNumber)
115 ,_sslContext(sslContext)
116 ,_monitor(NULL)
117 ,_acceptor(NULL)
118 ,_dieNow(false)
119 ,_dispatcher(NULL)
120 ,_responseEncoder(NULL)
121 ,_requestDecoder(NULL)
122 {
123 }
124 tony 1.8
125 CIMListenerService::CIMListenerService(CIMListenerService& svc)
126 :_portNumber(svc._portNumber)
127 ,_sslContext(svc._sslContext)
128 ,_monitor(NULL)
129 ,_acceptor(NULL)
130 ,_dieNow(svc._dieNow)
131 ,_dispatcher(NULL)
132 ,_responseEncoder(NULL)
133 ,_requestDecoder(NULL)
134 {
135 }
136 CIMListenerService::~CIMListenerService()
137 {
138 // if port is alive, clean up the port
139 //if(_sslContext!=NULL)
140 // delete _sslContext;
141
142 if(_responseEncoder!=NULL)
143 delete _responseEncoder;
144
145 tony 1.8 if(_requestDecoder!=NULL)
146 delete _requestDecoder;
|
147 kumpf 1.1
|
148 tony 1.8 //if(_dispatcher!=NULL)
149 // delete _dispatcher;
|
150 kumpf 1.1
|
151 tony 1.8 if(_monitor!=NULL)
152 delete _monitor;
|
153 kumpf 1.1
|
154 tony 1.8 if(_acceptor!=NULL)
155 delete _acceptor;
156 }
|
157 kumpf 1.1
|
158 tony 1.8 void CIMListenerService::init()
|
159 kumpf 1.1 {
|
160 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::init");
|
161 kumpf 1.1
|
162 tony 1.8 _monitor = new Monitor(true);
163 //_dispatcher = new CIMListenerIndicationDispatcher();
|
164 kumpf 1.1
|
165 tony 1.8 _responseEncoder = new CIMExportResponseEncoder();
166 _requestDecoder = new CIMExportRequestDecoder(
167 _dispatcher,
168 _responseEncoder->getQueueId());
169
170 _acceptor = new HTTPAcceptor(
171 _monitor,
172 _requestDecoder,
173 false,
174 _portNumber,
175 _sslContext);
|
176 kumpf 1.1
|
177 tony 1.8 bind();
|
178 kumpf 1.1
|
179 tony 1.8 PEG_METHOD_EXIT();
180 }
181 void CIMListenerService::bind()
182 {
183 if(_acceptor!=NULL)
184 { // Bind to the port
185 _acceptor->bind();
186
187 PEGASUS_STD(cout) << "Listening on HTTP port " << _portNumber << PEGASUS_STD(endl);
188
189 //listener.addAcceptor(false, portNumberHttp, false);
190 Logger::put(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION,
191 "Listening on HTTP port $0.", _portNumber);
|
192 kumpf 1.1
|
193 tony 1.8 }
194 }
195 void CIMListenerService::runForever()
196 {
197 static int modulator = 0;
|
198 kumpf 1.1
|
199 tony 1.8 if(!_dieNow)
200 {
201 if(false == _monitor->run(100))
202 {
203 modulator++;
204 if(!(modulator % 5000) )
205 {
206 try
207 {
208 //MessageQueueService::_check_idle_flag = 1;
209 //MessageQueueService::_polling_sem.signal();
210 _monitor->kill_idle_threads();
211 }
212 catch(...)
213 {
214 }
215 }
216 }
217 /*
218 if (handleShutdownSignal)
219 {
220 tony 1.8 Tracer::trace(TRC_SERVER, Tracer::LEVEL3,
221 "CIMServer::runForever - signal received. Shutting down.");
222
223 ShutdownService::getInstance(this)->shutdown(true, 10, false);
224 handleShutdownSignal = false;
225 }
226 */
227 }
228 }
|
229 kumpf 1.1
|
230 tony 1.8 void CIMListenerService::shutdown()
231 {
232 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::shutdown()");
|
233 kumpf 1.1
|
234 tony 1.8 _dieNow = true;
|
235 kumpf 1.1
|
236 kumpf 1.4 PEG_METHOD_EXIT();
|
237 kumpf 1.1 }
238
|
239 tony 1.8 void CIMListenerService::resume()
|
240 kumpf 1.1 {
|
241 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()");
|
242 kumpf 1.1
|
243 tony 1.8 if(_acceptor!=NULL)
244 _acceptor->reopenConnectionSocket();
|
245 kumpf 1.1
|
246 kumpf 1.4 PEG_METHOD_EXIT();
|
247 kumpf 1.1 }
248
|
249 tony 1.8 void CIMListenerService::stopClientConnection()
|
250 kumpf 1.1 {
|
251 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::stopClientConnection()");
|
252 kumpf 1.1
|
253 tony 1.8 if(_acceptor!=NULL)
254 _acceptor->closeConnectionSocket();
|
255 kumpf 1.1
|
256 kumpf 1.4 PEG_METHOD_EXIT();
|
257 kumpf 1.1 }
258
|
259 tony 1.8
260 CIMListenerIndicationDispatcher* CIMListenerService::getIndicationDispatcher() const
|
261 kumpf 1.1 {
|
262 tony 1.8 return _dispatcher;
263 }
264 void CIMListenerService::setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher)
265 {
266 _dispatcher = dispatcher;
|
267 kumpf 1.1 }
268
|
269 tony 1.8 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL CIMListenerService::_listener_routine(void *param)
|
270 kumpf 1.1 {
|
271 tony 1.8 CIMListenerService *svc = reinterpret_cast<CIMListenerService *>(param);
|
272 kumpf 1.1
|
273 tony 1.8 svc->init();
274 while(!svc->terminated())
275 {
276 svc->runForever();
277 }
278 delete svc;
279
280 return 0;
281 }
282 static struct timeval create_time = {0, 1};
283 static struct timeval destroy_time = {15, 0};
284 static struct timeval deadlock_time = {0, 0};
285
286 /////////////////////////////////////////////////////////////////////////////
287 // CIMListenerRep
288 /////////////////////////////////////////////////////////////////////////////
289 class CIMListenerRep
290 {
291 public:
292 CIMListenerRep(Uint32 portNumber, SSLContext* sslContext=NULL);
293 ~CIMListenerRep();
294 tony 1.8
295 Uint32 getPortNumber() const;
296
297 SSLContext* getSSLContext() const;
298 void setSSLContext(SSLContext* sslContext);
299
300 void start();
301 void stop();
302
303 Boolean isAlive();
304
305 Boolean addConsumer(CIMIndicationConsumer* consumer);
306 Boolean removeConsumer(CIMIndicationConsumer* consumer);
307
308 private:
309 Uint32 _portNumber;
310 SSLContext* _sslContext;
311
312 CIMListenerIndicationDispatcher* _dispatcher;
313 ThreadPool* _thread_pool;
314 };
315 tony 1.8
316 CIMListenerRep::CIMListenerRep(Uint32 portNumber, SSLContext* sslContext)
317 :_portNumber(portNumber)
318 ,_sslContext(sslContext)
319 ,_dispatcher(new CIMListenerIndicationDispatcher())
320 ,_thread_pool(NULL)
321 {
322 }
323 CIMListenerRep::~CIMListenerRep()
324 {
325 // if port is alive, clean up the port
326 if(_sslContext!=NULL)
327 delete _sslContext;
328
329 if(_dispatcher!=NULL)
330 delete _dispatcher;
331
332 if(_thread_pool!=NULL)
333 delete _thread_pool;
334 }
335
336 tony 1.8 Uint32 CIMListenerRep::getPortNumber() const
337 {
338 return _portNumber;
339 }
|
340 kumpf 1.1
|
341 tony 1.8 SSLContext* CIMListenerRep::getSSLContext() const
342 {
343 return _sslContext;
|
344 kumpf 1.1 }
|
345 tony 1.8 void CIMListenerRep::setSSLContext(SSLContext* sslContext)
346 {
347 if(_sslContext!=NULL)
348 delete _sslContext;
|
349 kumpf 1.1
|
350 tony 1.8 _sslContext = sslContext;
351 }
352 void CIMListenerRep::start()
|
353 kumpf 1.1 {
|
354 tony 1.8 // spawn a thread to do this
355 if(_thread_pool==NULL)
356 {
357 _thread_pool = new ThreadPool(0, "Listener", 0, 1,
358 create_time, destroy_time, deadlock_time);
359
360 CIMListenerService* svc = new CIMListenerService(_portNumber,_sslContext);
361 svc->setIndicationDispatcher(_dispatcher);
362
363 _thread_pool->allocate_and_awaken(svc,CIMListenerService::_listener_routine);
364
365 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
366 Logger::INFORMATION,
367 "CIMListener started");
|
368 kumpf 1.1
|
369 tony 1.8 PEGASUS_STD(cerr) << "CIMlistener started" << PEGASUS_STD(endl);
370 }
371 }
|
372 kumpf 1.1
|
373 tony 1.8 void CIMListenerRep::stop()
374 {
375 if(_thread_pool!=NULL)
376 { // stop the thread
377
378 delete _thread_pool;
379
380 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
381 Logger::INFORMATION,
382 "CIMListener stopped");
383 }
|
384 kumpf 1.1 }
385
|
386 tony 1.8 Boolean CIMListenerRep::isAlive()
|
387 kumpf 1.1 {
|
388 tony 1.8 return (_thread_pool!=NULL)?true:false;
389 }
|
390 kumpf 1.1
|
391 tony 1.8 Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer* consumer)
392 {
393 return _dispatcher->addConsumer(consumer);
394 }
395 Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer* consumer)
396 {
397 return _dispatcher->removeConsumer(consumer);
398 }
|
399 kumpf 1.1
|
400 tony 1.8 /////////////////////////////////////////////////////////////////////////////
401 // CIMListener
402 /////////////////////////////////////////////////////////////////////////////
403 CIMListener::CIMListener(Uint32 portNumber, SSLContext* sslContext)
404 :_rep(new CIMListenerRep(portNumber,sslContext))
405 {
406 }
407 CIMListener::~CIMListener()
408 {
409 if(_rep!=NULL)
410 delete _rep;
411 _rep=NULL;
412 }
413
414 Uint32 CIMListener::getPortNumber() const
415 {
416 return static_cast<CIMListenerRep*>(_rep)->getPortNumber();
|
417 kumpf 1.1 }
418
|
419 tony 1.8 SSLContext* CIMListener::getSSLContext() const
420 {
421 return static_cast<CIMListenerRep*>(_rep)->getSSLContext();
422 }
423 void CIMListener::setSSLContext(SSLContext* sslContext)
424 {
425 static_cast<CIMListenerRep*>(_rep)->setSSLContext(sslContext);
426 }
427 void CIMListener::start()
|
428 kumpf 1.1 {
|
429 tony 1.8 static_cast<CIMListenerRep*>(_rep)->start();
430 }
431 void CIMListener::stop()
432 {
433 static_cast<CIMListenerRep*>(_rep)->stop();
434 }
|
435 kumpf 1.1
|
436 tony 1.8 Boolean CIMListener::isAlive()
437 {
438 return static_cast<CIMListenerRep*>(_rep)->isAlive();
439 }
|
440 kumpf 1.1
|
441 tony 1.8 Boolean CIMListener::addConsumer(CIMIndicationConsumer* consumer)
442 {
443 return static_cast<CIMListenerRep*>(_rep)->addConsumer(consumer);
444 }
445 Boolean CIMListener::removeConsumer(CIMIndicationConsumer* consumer)
446 {
447 return static_cast<CIMListenerRep*>(_rep)->removeConsumer(consumer);
|
448 kumpf 1.1 }
449
450 PEGASUS_NAMESPACE_END
|