espcfg.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #pragma warning( disable : 4786 )
  15. #ifdef _WIN32
  16. //#define ESP_SUPPORT_DALI_CONFIG
  17. //CRT
  18. #include <process.h>
  19. #endif
  20. //Jlib
  21. #include "jliball.hpp"
  22. //SCM Interfaces
  23. #include "esp.hpp"
  24. #include "espplugin.hpp"
  25. #include "espplugin.ipp"
  26. #include "espcfg.ipp"
  27. #include "xslprocessor.hpp"
  28. #include "espcontext.hpp"
  29. #include <dalienv.hpp>
  30. /*
  31. #if defined(USING_MPATROL)
  32. #define ESP_BUILTIN
  33. #endif
  34. */
  35. //#define ESP_BUILTIN
  36. extern "C" {
  37. ESP_FACTORY IEspService * esp_service_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process);
  38. ESP_FACTORY IEspRpcBinding * esp_binding_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process);
  39. ESP_FACTORY IEspProtocol * esp_protocol_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process);
  40. };
  41. #ifdef ESP_BUILTIN
  42. builtin espdirect;
  43. #endif
  44. // add suffix and prefix when necessary
  45. void fixPlugin(StringBuffer& plugin)
  46. {
  47. if (stricmp(plugin.str()+plugin.length()-sizeof(SharedObjectExtension)+1,SharedObjectExtension)==0)
  48. return;
  49. plugin.insert(0,SharedObjectPrefix);
  50. plugin.append(SharedObjectExtension);
  51. }
  52. void CEspConfig::loadBuiltIns()
  53. {
  54. #ifdef ESP_BUILTIN
  55. espdirect.prot = esp_protocol_factory;
  56. espdirect.bind = esp_binding_factory;
  57. espdirect.serv = esp_service_factory;
  58. #endif
  59. }
  60. builtin *CEspConfig::getBuiltIn(string name)
  61. {
  62. #ifdef ESP_BUILTIN
  63. //if (name.compare("pixall.dll")==0 || name.compare("pixall.so")==0)
  64. return &espdirect;
  65. #else //ESP_DIRECT
  66. return NULL;
  67. #endif
  68. }
  69. StringBuffer &CVSBuildToEspVersion(char const * tag, StringBuffer & out)
  70. {
  71. unsigned build = 0;
  72. unsigned subbuild = 0;
  73. while(!isdigit(*tag))
  74. {
  75. if(!*tag) break;
  76. tag++;
  77. }
  78. while(isdigit(*tag))
  79. {
  80. if(!*tag) break;
  81. build = 10*build + (*tag-'0');
  82. tag++;
  83. }
  84. if(isalpha(*tag))
  85. {
  86. if(islower(*tag))
  87. subbuild = *tag-'a'+1;
  88. else
  89. subbuild = *tag-'A'+1;
  90. }
  91. out.append(build/10).append('.').append(build%10).append(subbuild);
  92. return out;
  93. }
  94. CEspConfig::CEspConfig(IProperties* inputs, IPropertyTree* envpt, IPropertyTree* procpt, bool isDali)
  95. {
  96. hsami_=0;
  97. serverstatus=NULL;
  98. useDali=false;
  99. if(inputs)
  100. m_inputs.setown(inputs);
  101. if(!envpt || !procpt)
  102. return;
  103. m_envpt.setown(envpt);
  104. m_cfg.setown(procpt);
  105. loadBuiltIns();
  106. // load options
  107. const char* level = m_cfg->queryProp("@logLevel");
  108. m_options.logLevel = level ? atoi(level) : LogMin;
  109. m_options.logReq = m_cfg->getPropBool("@logRequests", false);
  110. m_options.logResp = m_cfg->getPropBool("@logResponses", false);
  111. m_options.frameTitle.set(m_cfg->queryProp("@name"));
  112. m_options.slowProcessingTime = m_cfg->getPropInt("@slowProcessingTime", 30) * 1000; //in msec
  113. #ifdef USE_ENV_CONF_FILE
  114. // load environment parameters
  115. StringBuffer envConfFile, envXMLFile;
  116. const char* configFile = m_cfg->queryProp("EnvironmentConfFile");
  117. if (configFile && *configFile)
  118. {
  119. envConfFile.append(configFile);
  120. }
  121. else
  122. {
  123. envConfFile.append("/etc/LexisNexis/environment.conf");
  124. }
  125. const char* envFromDali = m_cfg->queryProp("@environmentNotFromDali");
  126. if (envFromDali && !stricmp(envFromDali, "true"))
  127. {
  128. const char* envXML = m_cfg->queryProp("EnvironmentXMLFile");
  129. if (envXML && *envXML)
  130. {
  131. envXMLFile.append(envXML);
  132. }
  133. else
  134. {
  135. envXMLFile.append("environment.xml");
  136. }
  137. }
  138. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  139. factory->createEnvironmentByFile(envConfFile.str(), envXMLFile.str());
  140. #endif
  141. if (!m_cfg->getProp("@name", m_process))
  142. {
  143. ERRLOG("EspProcess name not found");
  144. }
  145. else
  146. {
  147. DBGLOG("ESP process name [%s]", m_process.str());
  148. IPropertyTreeIterator *pt_iter = NULL;
  149. StringBuffer daliservers;
  150. if (m_cfg->getProp("@daliServers", daliservers))
  151. initDali(daliservers.str());
  152. #ifndef _DEBUG
  153. startPerformanceMonitor(m_cfg->getPropInt("@perfReportDelay", 60)*1000);
  154. #endif
  155. //get the local computer name:
  156. m_cfg->getProp("@computer", m_computer);
  157. //get the local computer information:
  158. StringBuffer xpath;
  159. xpath.appendf("Hardware/Computer[@name=\"%s\"]", m_computer.str());
  160. IPropertyTree *computer = m_envpt->queryPropTree(xpath.str());
  161. if (computer)
  162. {
  163. StringBuffer address;
  164. computer->getProp("@netAddress", address);
  165. int port = m_cfg->getPropInt("@port", 1500);
  166. if(strcmp(address.str(), ".") == 0)
  167. {
  168. GetHostName(address.clear());
  169. }
  170. m_address.set(address.str(), (unsigned short) port);
  171. }
  172. xpath.clear();
  173. xpath.append("EspService");
  174. pt_iter = m_cfg->getElements(xpath.str());
  175. if (pt_iter!=NULL)
  176. {
  177. IPropertyTree *ptree = NULL;
  178. pt_iter->first();
  179. while(pt_iter->isValid())
  180. {
  181. ptree = &pt_iter->query();
  182. if (ptree)
  183. {
  184. srv_cfg *svcfg = new srv_cfg;
  185. ptree->getProp("@name", svcfg->name);
  186. ptree->getProp("@type", svcfg->type);
  187. ptree->getProp("@plugin", svcfg->plugin);
  188. fixPlugin(svcfg->plugin);
  189. map<string, srv_cfg*>::value_type en(svcfg->name.str(), svcfg);
  190. m_services.insert(en);
  191. }
  192. pt_iter->next();
  193. }
  194. pt_iter->Release();
  195. pt_iter=NULL;
  196. }
  197. xpath.clear();
  198. xpath.append("EspProtocol");
  199. pt_iter = m_cfg->getElements(xpath.str());
  200. if (pt_iter!=NULL)
  201. {
  202. IPropertyTree *ptree = NULL;
  203. pt_iter->first();
  204. while(pt_iter->isValid())
  205. {
  206. ptree = &pt_iter->query();
  207. if (ptree)
  208. {
  209. protocol_cfg *pcfg = new protocol_cfg;
  210. ptree->getProp("@name", pcfg->name);
  211. ptree->getProp("@plugin", pcfg->plugin);
  212. fixPlugin(pcfg->plugin);
  213. ptree->getProp("@type", pcfg->type);
  214. map<string, protocol_cfg*>::value_type en(pcfg->name.str(), pcfg);
  215. m_protocols.insert(en);
  216. }
  217. pt_iter->next();
  218. }
  219. pt_iter->Release();
  220. pt_iter=NULL;
  221. }
  222. xpath.clear();
  223. xpath.append("EspBinding");
  224. pt_iter = m_cfg->getElements(xpath.str());
  225. if (pt_iter!=NULL)
  226. {
  227. IPropertyTree *ptree = NULL;
  228. pt_iter->first();
  229. while(pt_iter->isValid())
  230. {
  231. ptree = &pt_iter->query();
  232. if (ptree)
  233. {
  234. binding_cfg *bcfg = new binding_cfg;
  235. ptree->getProp("@name", bcfg->name);
  236. ptree->getProp("@type", bcfg->type);
  237. ptree->getProp("@plugin", bcfg->plugin);
  238. fixPlugin(bcfg->plugin);
  239. bcfg->isDefault = ptree->getPropBool("@defaultBinding", false);
  240. StringBuffer addr;
  241. ptree->getProp("@netAddress", addr);
  242. if(strcmp(addr.str(), ".") == 0)
  243. {
  244. bcfg->address.append("0.0.0.0");
  245. }
  246. else
  247. {
  248. bcfg->address.append(addr.str());
  249. }
  250. StringBuffer portstr;
  251. ptree->getProp("@port", portstr);
  252. bcfg->port = atoi(portstr.str());
  253. ptree->getProp("@service", bcfg->service_name);
  254. ptree->getProp("@protocol", bcfg->protocol_name);
  255. m_bindings.push_back(bcfg);
  256. }
  257. pt_iter->next();
  258. }
  259. pt_iter->Release();
  260. pt_iter=NULL;
  261. }
  262. }
  263. }
  264. void CEspConfig::sendAlert(int severity, char const * descr, char const * subject) const
  265. {
  266. }
  267. void CEspConfig::initDali(const char *servers)
  268. {
  269. if (servers!=NULL && *servers!=0 && !daliClientActive())
  270. {
  271. DBGLOG("Initializing DALI client [servers = %s]", servers);
  272. useDali=true;
  273. // Create server group
  274. Owned<IGroup> serverGroup = createIGroup(servers, DALI_SERVER_PORT);
  275. if (!serverGroup)
  276. throw MakeStringException(0, "Could not instantiate dali IGroup");
  277. // Initialize client process
  278. if (!initClientProcess(serverGroup, DCR_EspServer))
  279. throw MakeStringException(0, "Could not initialize dali client");
  280. setPasswordsFromSDS();
  281. serverstatus = new CSDSServerStatus("ESPserver");
  282. }
  283. }
  284. void CEspConfig::initPtree(const char *location, bool isDali)
  285. {
  286. IPropertyTree* cfg = createPTreeFromXMLFile(location, ipt_caseInsensitive);
  287. if (cfg)
  288. {
  289. cfg->addProp("@config", location);
  290. m_envpt.setown(cfg);
  291. }
  292. }
  293. void CEspConfig::loadBinding(binding_cfg &xcfg)
  294. {
  295. map<string, srv_cfg*>::iterator sit = m_services.find(xcfg.service_name.str());
  296. map<string, protocol_cfg*>::iterator pit = m_protocols.find(xcfg.protocol_name.str());
  297. IEspService *isrv = NULL;
  298. IEspProtocol *iprot = NULL;
  299. if(sit == m_services.end())
  300. {
  301. DBGLOG("Warning: Service %s not found for the binding", xcfg.service_name.str());
  302. }
  303. else
  304. {
  305. isrv = (*sit).second->srv;
  306. }
  307. if(pit == m_protocols.end())
  308. {
  309. throw MakeStringException(-1, "Protocol %s not found for the binding", xcfg.protocol_name.str());
  310. }
  311. else
  312. {
  313. iprot = (*pit).second->prot;
  314. if (iprot)
  315. {
  316. esp_binding_factory_t xproc = NULL;
  317. if(isrv != NULL)
  318. xcfg.service.setown(LINK(isrv));
  319. xcfg.protocol.setown(LINK(iprot));
  320. builtin *pdirect = getBuiltIn(xcfg.plugin.str());
  321. if (pdirect)
  322. {
  323. xproc = pdirect->bind;
  324. }
  325. else
  326. {
  327. Owned<IEspPlugin> pplg = getPlugin(xcfg.plugin.str());
  328. if (pplg)
  329. {
  330. xproc = (esp_binding_factory_t) pplg->getProcAddress("esp_binding_factory");
  331. }
  332. }
  333. if (xproc)
  334. {
  335. IEspRpcBinding* bind = xproc(xcfg.name.str(), xcfg.type.str(), m_envpt.get(), m_process.str());
  336. if (bind)
  337. DBGLOG("Load binding %s (type: %s, process: %s) succeeded", xcfg.name.str(), xcfg.type.str(), m_process.str());
  338. else
  339. ERRLOG("Failed to load binding %s (type: %s, process: %s)", xcfg.name.str(), xcfg.type.str(), m_process.str());
  340. xcfg.bind.setown(bind);
  341. if (serverstatus)
  342. {
  343. IPropertyTree *stTree= serverstatus->queryProperties()->addPropTree("ESPservice", createPTree("ESPservice", ipt_caseInsensitive));
  344. if (stTree)
  345. {
  346. stTree->setProp("@type", xcfg.service->getServiceType());
  347. stTree->setProp("@name", xcfg.service_name.str());
  348. stTree->setPropInt("@port", xcfg.port);
  349. }
  350. serverstatus->commitProperties();
  351. }
  352. }
  353. else
  354. throw MakeStringException(-1, "procedure esp_binding_factory can't be loaded");
  355. }
  356. else
  357. {
  358. throw MakeStringException(-1, "Protocol %s wasn't loaded correctly for the binding", xcfg.protocol_name.str());
  359. }
  360. }
  361. }
  362. void CEspConfig::loadProtocol(protocol_cfg &xcfg)
  363. {
  364. esp_protocol_factory_t xproc = NULL;
  365. builtin *pdirect = getBuiltIn(xcfg.plugin.str());
  366. if (pdirect)
  367. xproc = pdirect->prot;
  368. else
  369. {
  370. Owned<IEspPlugin> pplg = getPlugin(xcfg.plugin.str());
  371. if (pplg)
  372. {
  373. xproc = (esp_protocol_factory_t) pplg->getProcAddress("esp_protocol_factory");
  374. }
  375. }
  376. if (xproc)
  377. {
  378. xcfg.prot.setown(xproc(xcfg.name.str(), xcfg.type.str(), m_envpt.get(), m_process.str()));
  379. if (xcfg.prot)
  380. xcfg.prot->init(m_envpt.get(), m_process.str(), xcfg.name.str());
  381. }
  382. else
  383. throw MakeStringException(-1, "procedure esp_protocol_factory can't be loaded");
  384. }
  385. void CEspConfig::loadService(srv_cfg &xcfg)
  386. {
  387. esp_service_factory_t xproc = NULL;
  388. builtin *pdirect = getBuiltIn(xcfg.plugin.str());
  389. if (pdirect)
  390. xproc = pdirect->serv;
  391. else
  392. {
  393. Owned<IEspPlugin> pplg = getPlugin(xcfg.plugin.str());
  394. if (pplg)
  395. xproc = (esp_service_factory_t) pplg->getProcAddress("esp_service_factory");
  396. }
  397. if (xproc)
  398. xcfg.srv.setown(xproc(xcfg.name.str(), xcfg.type.str(), m_envpt.get(), m_process.str()));
  399. else
  400. throw MakeStringException(-1, "procedure esp_service_factory can't be loaded");
  401. }
  402. void CEspConfig::loadServices()
  403. {
  404. map<string, srv_cfg*>::iterator iter = m_services.begin();
  405. while (iter!=m_services.end())
  406. {
  407. loadService(*(iter->second));
  408. iter++;
  409. }
  410. }
  411. void CEspConfig::loadProtocols()
  412. {
  413. map<string, protocol_cfg*>::iterator iter = m_protocols.begin();
  414. while (iter!=m_protocols.end())
  415. {
  416. loadProtocol(*(iter->second));
  417. iter++;
  418. }
  419. }
  420. void CEspConfig::loadBindings()
  421. {
  422. list<binding_cfg*>::iterator iter = m_bindings.begin();
  423. while (iter!=m_bindings.end())
  424. {
  425. loadBinding(**iter);
  426. iter++;
  427. }
  428. }
  429. class ESPxsltIncludeHandler : public CInterface, implements IIncludeHandler
  430. {
  431. public:
  432. // IMPLEMENT_IINTERFACE;
  433. virtual void Link() const
  434. {
  435. CInterface::Link();
  436. }
  437. virtual bool Release() const
  438. {
  439. return CInterface::Release();
  440. }
  441. ESPxsltIncludeHandler()
  442. {
  443. }
  444. ~ESPxsltIncludeHandler()
  445. {
  446. }
  447. inline bool fileExists(StringBuffer &filename)
  448. {
  449. return (checkFileExists(filename.str()) || checkFileExists(filename.toUpperCase().str()) || checkFileExists(filename.toLowerCase().str()));
  450. }
  451. inline bool fileRead(const char *filename, MemoryBuffer &buff)
  452. {
  453. Owned<IFile> fi=createIFile(filename);
  454. if (fi)
  455. {
  456. Owned<IFileIO> fio=fi->open(IFOread);
  457. if (fio)
  458. {
  459. offset_t len=fio->size();
  460. if (fio->read(0, len, buff.reserveTruncate(len))==len)
  461. return true;
  462. }
  463. }
  464. buff.clear();
  465. return false;
  466. }
  467. const char *pastLast(const char *src, const char *fnd)
  468. {
  469. int fndlen=(fnd) ? strlen(fnd) : 0;
  470. int srclen=(src) ? strlen(src) : 0;
  471. if (fndlen && srclen)
  472. {
  473. while (srclen--)
  474. {
  475. if (!strnicmp(src+srclen, fnd, fndlen))
  476. return src+srclen+fndlen;
  477. }
  478. }
  479. return NULL;
  480. }
  481. //IIncludeHandler
  482. bool getInclude(const char* includename, MemoryBuffer& includebuf, bool& pathOnly)
  483. {
  484. if(!includename)
  485. return false;
  486. pathOnly = true;
  487. includebuf.clear();
  488. const char *finger=pastLast(includename, "esp/xslt/");
  489. if (finger)
  490. {
  491. StringBuffer filepath;
  492. if (fileExists(filepath.append(getCFD()).append("smc_xslt/").append(finger)) || fileExists(filepath.clear().append(getCFD()).append("xslt/").append(finger)))
  493. {
  494. includebuf.append(filepath.length(), filepath.str());
  495. return true;
  496. }
  497. }
  498. else
  499. {
  500. // First of all, it's better to use absolute path to specify the include, like /esp/xslt/ui_overrides.xslt.
  501. // When you specify the include as relative path, for example ./ui_overrides.xslt
  502. // the path will be expanded (by xmllib's source resolver) to its full path, beginning with file://
  503. // on windows it looks like: file:///C:/playground/esp_lsb2/xslt/ui_overrides.xslt
  504. // on linux: file:///home/yma/playground/esp_lsb2/xslt/ui_overrides.xslt
  505. char dir[_MAX_PATH];
  506. GetCurrentDirectory(sizeof(dir), dir);
  507. #ifdef _WIN32
  508. for(int i = 0; i < _MAX_PATH; i++)
  509. {
  510. if(dir[i] == '\0')
  511. break;
  512. else if(dir[i] == PATHSEPCHAR)
  513. dir[i] = '/';
  514. }
  515. #endif
  516. finger = strstr(includename, dir);
  517. if(finger)
  518. {
  519. finger += strlen(dir) + 1;
  520. StringBuffer filepath(finger);
  521. if (fileExists(filepath))
  522. {
  523. includebuf.append(filepath.length(), filepath.str());
  524. return true;
  525. }
  526. }
  527. }
  528. return false;
  529. }
  530. };
  531. ESPxsltIncludeHandler g_includeHandler;
  532. void CEspConfig::bindServer(IEspServer &server, IEspContainer &container)
  533. {
  534. list<binding_cfg*>::iterator bit = m_bindings.begin();
  535. while (bit != m_bindings.end())
  536. {
  537. binding_cfg *pbfg = *bit;
  538. if (pbfg && pbfg->bind && pbfg->service && pbfg->protocol)
  539. {
  540. map<string, protocol_cfg*>::iterator pit = m_protocols.find(pbfg->protocol_name.str());
  541. if(pit == m_protocols.end())
  542. DBGLOG("Protocol %s not found for binding %s", pbfg->protocol_name.str(), pbfg->name.str());
  543. else
  544. {
  545. Owned<IXslProcessor> xslp=getXslProcessor();
  546. if (xslp)
  547. {
  548. xslp->setDefIncludeHandler(dynamic_cast<IIncludeHandler*>(&g_includeHandler));
  549. pbfg->bind->setXslProcessor(xslp);
  550. }
  551. pbfg->bind->setContainer(&container);
  552. pbfg->service->setContainer(&container);
  553. pbfg->protocol->setContainer(&container);
  554. pbfg->bind->addProtocol(pbfg->protocol->getProtocolName(), *pbfg->protocol.get());
  555. if(pbfg->service != NULL)
  556. pbfg->bind->addService(pbfg->service->getServiceType(), pbfg->address.str(), pbfg->port, *pbfg->service.get());
  557. IEspProtocol* prot = (*pit).second->prot;
  558. server.addBinding(pbfg->name.str(), pbfg->address.str(), pbfg->port, *prot, *(pbfg->bind.get()), pbfg->isDefault, m_cfg.get());
  559. }
  560. }
  561. else
  562. {
  563. ERRLOG("Binding %s wasn't loaded correctly", pbfg->name.str());
  564. }
  565. bit++;
  566. }
  567. }
  568. void CEspConfig::unloadBindings()
  569. {
  570. list<binding_cfg*>::iterator iter = m_bindings.begin();
  571. while (iter!=m_bindings.end())
  572. {
  573. binding_cfg *bcfg = *iter;
  574. if(bcfg!=NULL)
  575. {
  576. bcfg->protocol.clear();
  577. bcfg->bind.clear();
  578. bcfg->service.clear();
  579. delete bcfg;
  580. }
  581. iter++;
  582. }
  583. m_bindings.clear();
  584. }
  585. void CEspConfig::unloadServices()
  586. {
  587. map<string, srv_cfg*>::iterator srvi = m_services.begin();
  588. while (srvi!=m_services.end())
  589. {
  590. srv_cfg* scfg = srvi->second;
  591. if(scfg)
  592. {
  593. scfg->cfg.clear();
  594. scfg->srv.clear();
  595. delete scfg;
  596. }
  597. srvi++;
  598. }
  599. m_services.clear();
  600. }
  601. void CEspConfig::unloadProtocols()
  602. {
  603. map<string, protocol_cfg*>::iterator proti = m_protocols.begin();
  604. while (proti!=m_protocols.end())
  605. {
  606. protocol_cfg *pcfg = proti->second;
  607. if(pcfg)
  608. {
  609. pcfg->prot.clear();
  610. pcfg->cfg.clear();
  611. delete pcfg;
  612. }
  613. proti++;
  614. }
  615. m_protocols.clear();
  616. }
  617. IEspPlugin* CEspConfig::getPlugin(const char* name)
  618. {
  619. if(!name || !*name)
  620. return NULL;
  621. ForEachItemIn(x, m_plugins)
  622. {
  623. IEspPlugin* plgn = &m_plugins.item(x);
  624. if(plgn && stricmp(name, plgn->getName()) == 0)
  625. {
  626. return LINK(plgn);
  627. }
  628. }
  629. Owned<IEspPlugin> pplg = loadPlugin(name);
  630. if(pplg)
  631. {
  632. pplg->Link(); //YMA: intentional leak. Unloading DLLs during ESP shutdown causes all kinds of issues.
  633. m_plugins.append(*LINK(pplg));
  634. return LINK(pplg);
  635. }
  636. return NULL;
  637. }