00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00037 #include "OW_config.h"
00038 #include "OW_CIMXMLListener.hpp"
00039 #include "OW_CIMListenerCallback.hpp"
00040 #include "OW_HTTPServer.hpp"
00041 #include "OW_XMLListener.hpp"
00042 #include "OW_HTTPException.hpp"
00043 #include "OW_Format.hpp"
00044 #include "OW_MutexLock.hpp"
00045 #include "OW_ListenerAuthenticator.hpp"
00046 #include "OW_CIMInstance.hpp"
00047 #include "OW_CIMValue.hpp"
00048 #include "OW_CIMClass.hpp"
00049 #include "OW_CIMProperty.hpp"
00050 #include "OW_RandomNumber.hpp"
00051 #include "OW_ServiceEnvironmentIFC.hpp"
00052 #include "OW_ConfigOpts.hpp"
00053 #include "OW_ServerSocket.hpp"
00054 #include "OW_SelectEngine.hpp"
00055 #include "OW_SelectableIFC.hpp"
00056 #include "OW_IOException.hpp"
00057 #include "OW_Thread.hpp"
00058 #include "OW_Assertion.hpp"
00059 #include "OW_ClientCIMOMHandle.hpp"
00060 #include "OW_CIMProtocolIFC.hpp"
00061 #include "OW_NullLogger.hpp"
00062 #include "OW_FileSystem.hpp"
00063 #include "OW_ConfigFile.hpp"
00064
00065 #include <algorithm>
00066
00067 namespace OW_NAMESPACE
00068 {
00069
00070 using namespace WBEMFlags;
00071
00072
00073
00074
00075 namespace
00076 {
00077
00078 const String COMPONENT_NAME("ow.listener.cimxml");
00079
00080 #ifdef OW_WIN32
00081 class EventSelectable : public SelectableIFC
00082 {
00083 public:
00084 EventSelectable()
00085 : SelectableIFC()
00086 , m_event(NULL)
00087 {
00088 if(!(m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL)))
00089 {
00090 OW_THROW(IOException, "Unable to create WIN32 event handle");
00091 }
00092 }
00093 ~EventSelectable()
00094 {
00095 if(m_event)
00096 {
00097 ::CloseHandle(m_event);
00098 }
00099 }
00100 Select_t getSelectObj() const
00101 {
00102 Select_t st;
00103 st.event = m_event;
00104 return st;
00105 }
00106
00107 void setEvent()
00108 {
00109 if(m_event)
00110 {
00111 if(!::SetEvent(m_event))
00112 {
00113 OW_THROW(IOException, "Signaling termination event failed");
00114 }
00115 }
00116 }
00117
00118 void resetEvent()
00119 {
00120 if(m_event)
00121 {
00122 ::ResetEvent(m_event);
00123 }
00124 }
00125
00126 private:
00127 HANDLE m_event;
00128 };
00129 typedef IntrusiveReference<EventSelectable> EventSelectableRef;
00130
00131 #endif
00132
00133 typedef std::pair<SelectableIFCRef, SelectableCallbackIFCRef> SelectablePair_t;
00134 class CIMXMLListenerServiceEnvironment : public ServiceEnvironmentIFC
00135 {
00136 public:
00137 CIMXMLListenerServiceEnvironment(
00138 const ConfigFile::ConfigMap& configItems,
00139 const AuthenticatorIFCRef& authenticator,
00140 RequestHandlerIFCRef listener,
00141 const LoggerRef& logger,
00142 Reference<Array<SelectablePair_t> > selectables)
00143 : m_configItems(configItems)
00144 , m_authenticator(authenticator)
00145 , m_XMLListener(listener)
00146 , m_logger(logger ? logger : LoggerRef(new NullLogger))
00147 , m_selectables(selectables)
00148 {
00149 setConfigItem(ConfigOpts::HTTP_SERVER_MAX_CONNECTIONS_opt, String(10), E_PRESERVE_PREVIOUS);
00150 setConfigItem(ConfigOpts::HTTP_SERVER_SINGLE_THREAD_opt, "false", E_PRESERVE_PREVIOUS);
00151 setConfigItem(ConfigOpts::HTTP_SERVER_ENABLE_DEFLATE_opt, "true", E_PRESERVE_PREVIOUS);
00152 setConfigItem(ConfigOpts::HTTP_SERVER_USE_DIGEST_opt, "false", E_PRESERVE_PREVIOUS);
00153 setConfigItem(ConfigOpts::HTTP_SERVER_USE_UDS_opt, "false", E_PRESERVE_PREVIOUS);
00154
00155
00156 setConfigItem(ConfigOpts::HTTP_SERVER_ENABLE_DEFLATE_opt, "false", E_PRESERVE_PREVIOUS);
00157 }
00158 virtual ~CIMXMLListenerServiceEnvironment() {}
00159 virtual bool authenticate(String &userName,
00160 const String &info, String &details, OperationContext& context) const
00161 {
00162
00163 if (!m_authenticator)
00164 {
00165 return false;
00166 }
00167 return m_authenticator->authenticate(userName, info, details, context);
00168 }
00169 virtual void addSelectable(const SelectableIFCRef& obj,
00170 const SelectableCallbackIFCRef& cb)
00171 {
00172 m_selectables->push_back(std::make_pair(obj, cb));
00173 }
00174
00175 struct selectableFinder
00176 {
00177 selectableFinder(const SelectableIFCRef& obj) : m_obj(obj) {}
00178 template <typename T>
00179 bool operator()(const T& x)
00180 {
00181 return x.first == m_obj;
00182 }
00183 const SelectableIFCRef& m_obj;
00184 };
00185
00186 virtual void removeSelectable(const SelectableIFCRef& obj)
00187 {
00188 m_selectables->erase(std::remove_if (m_selectables->begin(), m_selectables->end(),
00189 selectableFinder(obj)), m_selectables->end());
00190 }
00191 virtual String getConfigItem(const String &name, const String& defRetVal) const
00192 {
00193 return ConfigFile::getConfigItem(m_configItems, name, defRetVal);
00194 }
00195 virtual StringArray getMultiConfigItem(const String &itemName,
00196 const StringArray& defRetVal, const char* tokenizeSeparator) const
00197 {
00198 return ConfigFile::getMultiConfigItem(m_configItems, itemName, defRetVal, tokenizeSeparator);
00199 }
00200 virtual void setConfigItem(const String& item, const String& value, EOverwritePreviousFlag overwritePrevious)
00201 {
00202 ConfigFile::setConfigItem(m_configItems, item, value,
00203 overwritePrevious == E_OVERWRITE_PREVIOUS ? ConfigFile::E_OVERWRITE_PREVIOUS : ConfigFile::E_PRESERVE_PREVIOUS);
00204 }
00205
00206 virtual RequestHandlerIFCRef getRequestHandler(const String&) const
00207 {
00208 RequestHandlerIFCRef ref(m_XMLListener.getLibRef(),
00209 m_XMLListener->clone());
00210 ref->setEnvironment(ServiceEnvironmentIFCRef(const_cast<CIMXMLListenerServiceEnvironment*>(this)));
00211 return ref;
00212 }
00213 virtual LoggerRef getLogger() const
00214 {
00215 return getLogger(COMPONENT_NAME);
00216 }
00217 virtual LoggerRef getLogger(const String& componentName) const
00218 {
00219 LoggerRef rv(m_logger->clone());
00220 rv->setDefaultComponent(componentName);
00221 return rv;
00222 }
00223 private:
00224 ConfigFile::ConfigMap m_configItems;
00225 AuthenticatorIFCRef m_authenticator;
00226 RequestHandlerIFCRef m_XMLListener;
00227 LoggerRef m_logger;
00228 Reference<Array<SelectablePair_t> > m_selectables;
00229 };
00230 class SelectEngineThread : public Thread
00231 {
00232 public:
00233 SelectEngineThread(const Reference<Array<SelectablePair_t> >& selectables)
00234 : Thread()
00235 , m_selectables(selectables)
00236 #ifdef OW_WIN32
00237 , m_stopObject(new EventSelectable)
00238 {
00239 }
00240 #else
00241 , m_stopObject(UnnamedPipe::createUnnamedPipe())
00242 {
00243 m_stopObject->setBlocking(UnnamedPipe::E_NONBLOCKING);
00244 }
00245 #endif
00246
00250 virtual Int32 run()
00251 {
00252 SelectEngine engine;
00253 SelectableCallbackIFCRef cb(new SelectEngineStopper(engine));
00254 m_selectables->push_back(std::make_pair(m_stopObject, cb));
00255 for (size_t i = 0; i < m_selectables->size(); ++i)
00256 {
00257 engine.addSelectableObject((*m_selectables)[i].first,
00258 (*m_selectables)[i].second);
00259 }
00260 engine.go();
00261 return 0;
00262 }
00263 virtual void doCooperativeCancel()
00264 {
00265 #ifdef OW_WIN32
00266
00267
00268 m_stopObject->setEvent();
00269 #else
00270
00271
00272 if (m_stopObject->writeInt(0) == -1)
00273 {
00274 OW_THROW_ERRNO_MSG(IOException, "Writing to the termination pipe failed");
00275 }
00276 #endif
00277 }
00278
00279 private:
00280 Reference<Array<SelectablePair_t> > m_selectables;
00281 #ifdef OW_WIN32
00282 EventSelectableRef m_stopObject;
00283 #else
00284 UnnamedPipeRef m_stopObject;
00285 #endif
00286 };
00287 }
00289 CIMXMLListener::CIMXMLListener(const ConfigFile::ConfigMap& configItems,
00290 const CIMListenerCallbackRef& callback,
00291 const AuthenticatorIFCRef& authenticator,
00292 const LoggerRef& logger)
00293 : m_XMLListener(SharedLibraryRef(0), new XMLListener(callback))
00294
00295 , m_httpServer(new HTTPServer)
00296 , m_httpListenPort(0)
00297 , m_httpsListenPort(0)
00298 {
00299 Reference<Array<SelectablePair_t> >
00300 selectables(new Array<SelectablePair_t>);
00301 ServiceEnvironmentIFCRef env(new CIMXMLListenerServiceEnvironment(
00302 configItems,
00303 authenticator, m_XMLListener, logger, selectables));
00304 m_httpServer->init(env);
00305 m_httpServer->start();
00306
00307
00308
00309 m_httpListenPort = m_httpServer->getLocalHTTPAddress().getPort();
00310 m_httpsListenPort = m_httpServer->getLocalHTTPSAddress().getPort();
00311
00312 m_httpThread = new SelectEngineThread(selectables);
00313 m_httpThread->start();
00314 }
00316 CIMXMLListener::~CIMXMLListener()
00317 {
00318 try
00319 {
00320 shutdownHttpServer();
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 }
00346 catch (...)
00347 {
00348
00349 }
00350 }
00351 void
00352 CIMXMLListener::shutdownHttpServer()
00353 {
00354 if (m_httpThread)
00355 {
00356 m_httpThread->cooperativeCancel();
00357
00358 m_httpThread->join();
00359 m_httpThread = 0;
00360 }
00361 if (m_httpServer)
00362 {
00363
00364 m_httpServer->shutdown();
00365 m_httpServer = 0;
00366 }
00367 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 }
00543