// // Find file in specified list of directories // INT_32 MainProcess::FindFile(const STLW::vector<STLW::string> & vDirectories, const STLW::string & sFilename, STLW::string & sFullpath) { STLW::vector<STLW::string>::const_iterator itvDirectories = vDirectories.begin(); while (itvDirectories != vDirectories.end()) { sFullpath.erase(); const STLW::string & sDir(*itvDirectories); if (sDir.size()) { sFullpath.assign(sDir); if (sDir[sDir.size() - 1] != '/') { sFullpath.append(1, '/'); } } sFullpath.append(sFilename); const INT_64 iFileHandle = File::Open(sFullpath.c_str(), OpenMode::READ); if (iFileHandle != -1) { File::Close(iFileHandle); return 0; } ++itvDirectories; } return -1; }
ServiceConfig::State ServiceConfig::ParseNetworks(const VariantNC & oData, const STLW::string & sBranch, ServiceConfig & oServiceConfig, IPv4Map & oIPv4Map, Logger & oLogger) { const STLW::vector<STLW::string> vNetworks = oData[sBranch]; STLW::vector<STLW::string>::const_iterator itvNetworks = vNetworks.begin(); while (itvNetworks != vNetworks.end()) { // IPv4 if (itvNetworks -> find(".") != STLW::string::npos) { if (oIPv4Map.AddNet(*itvNetworks) != IPMap::OK) { oLogger.Emerg("Invalid format of parameter `Service/%s/%s`: invalid network `%s`", oServiceConfig.name.c_str(), sBranch.c_str(), itvNetworks -> c_str()); return CONFIG_ERROR; } } // IPv6, TBD else if (itvNetworks -> find(":") != STLW::string::npos) { oLogger.Emerg("Invalid format of parameter `Service/%s/%s`: IPv6 networks `%s` not supported yet", oServiceConfig.name.c_str(), sBranch.c_str(), itvNetworks -> c_str()); } ++itvNetworks; } return OK; }
// // Set of directories where included templates should be found // void CTPP2FileSourceLoader::SetIncludeDirs(const STLW::vector<STLW::string> & vIIncludeDirs) { { STLW::vector<STLW::string> vTMP; vIncludeDirs.swap(vTMP); } STLW::vector<STLW::string>::const_iterator itvIIncludeDirs = vIIncludeDirs.begin(); while (itvIIncludeDirs != vIIncludeDirs.end()) { if (itvIIncludeDirs -> length() != 0) { vIncludeDirs.push_back(*itvIIncludeDirs); } ++itvIIncludeDirs; } vIncludeDirs.push_back(""); }
static STLW::string GetBaseDir(const STLW::string & szTemplateName, STLW::string & sNormalizedFileName) { if (szTemplateName.length() == 0) { return ""; } STLW::vector<STLW::string> vCurrentDir; CCHAR_P sBegin = szTemplateName.c_str(); CCHAR_P szEnd = szTemplateName.c_str() + szTemplateName.length(); CCHAR_P sIter = sBegin; while (sIter != szEnd) { if (*sIter == '/') { if (sIter != sBegin) { STLW::string sTMP(sBegin, sIter); if (sTMP == "/." || sTMP == "/") { ;; } else if (sTMP == "/..") { STLW::vector<STLW::string>::iterator itEnd = vCurrentDir.end(); if (vCurrentDir.begin() == itEnd) { return ""; } vCurrentDir.erase(--itEnd); } else { vCurrentDir.push_back(sTMP); } } sBegin = sIter; } ++sIter; } STLW::string sTMP(sBegin, sIter); if (sTMP == "/") { return ""; } STLW::string sResult; for (UINT_32 iI = 0; iI < vCurrentDir.size(); ++iI) { sResult.append(vCurrentDir[iI]); } sNormalizedFileName.assign(sResult); sNormalizedFileName.append(sTMP); sResult.append("/"); return sResult; }
// // Get configuration from variant data type // ServiceConfig::State ServiceConfig::GetConfig(const VariantNC & oData, ServiceConfig & oServiceConfig, Logger & oLogger) { // Allow connection from specified IP's or subnets if (ParseNetworks(oData, "AllowConnect", oServiceConfig, oServiceConfig.ipv4_allowed_networks, oLogger) != OK) { return CONFIG_ERROR; } // Deny connection from specified IP's or subnets if (ParseNetworks(oData, "DenyConnect", oServiceConfig, oServiceConfig.ipv4_denied_networks, oLogger) != OK) { return CONFIG_ERROR; } // Order of networks check oServiceConfig.allow_deny_order = ALLOW_DENY; const STLW::vector<STLW::string> vDenyAllow = oData["AllowDenyOrder"]; if (!vDenyAllow.empty() && vDenyAllow[0] != "") { if (vDenyAllow.size() != 2) { oLogger.Emerg("Invalid format of parameter `Service/%s/AllowDenyOrder`: need `allow deny` or `deny allow`", oServiceConfig.name.c_str()); return CONFIG_ERROR; } if (Unicode::CompareIgnoreCase(vDenyAllow[0].data(), vDenyAllow[0].size(), "deny", sizeof("deny") - 1) == 0) { oServiceConfig.allow_deny_order = DENY_ALLOW; } } // Listen to inteface STLW::vector<STLW::string> vListen; ConfigHelper::GetList(oData["Listen"], vListen); STLW::vector<STLW::string>::const_iterator itvListen = vListen.begin(); while(itvListen != vListen.end()) { ListenInterface oInterface; ConfigHelper::State oRC = ConfigHelper::ParseAddress(*itvListen, oInterface.af, oInterface.address, oInterface.port); if (oRC != ConfigHelper::OK) { oLogger.Emerg("Invalid address: `%s`", itvListen -> c_str()); return CONFIG_ERROR; } oServiceConfig.listen.push_back(oInterface); ++itvListen; } // Socket listen queue oServiceConfig.listen_queue = oData["MaxQueueLength"]; if (oServiceConfig.listen_queue == 0) { oLogger.Emerg("Invalid format of parameter `Service/%s/MaxQueueLength` not set", oServiceConfig.name.c_str()); return CONFIG_ERROR; } // Read buffer size oServiceConfig.recv_buffer_size = ConfigHelper::ParseSize(oData["RecvBufferSize"]); if (oServiceConfig.recv_buffer_size == 0 || oServiceConfig.recv_buffer_size == UINT_32(-1)) { oLogger.Emerg("Invalid format of parameter `Service/%s/RecvBufferSize` not set", oServiceConfig.name.c_str()); return CONFIG_ERROR; } // Maximum number of connections for this service oServiceConfig.max_clients = oData["MaxClients"]; if (oServiceConfig.max_clients == 0) { oLogger.Warn("Parameter `Service/%s/MaxClients`: not set", oServiceConfig.name.c_str()); } // Number of active clients oServiceConfig.active_clients = 0; // Read/Write timeout oServiceConfig.io_timeout = ConfigHelper::ParseTimeout(oData["IOTimeout"]) / 1000.0; if (oServiceConfig.io_timeout == 0) { oLogger.Emerg("Parameter `Service/%s/IOTimeout`: need to set positive value", oServiceConfig.name.c_str()); return CONFIG_ERROR; } #ifdef IRIS_TLS_SUPPORT // TLS parameters oServiceConfig.enable_ssl_tls = ConfigHelper::ParseBool(oData["EnableTLSSSL"]); if (oServiceConfig.enable_ssl_tls) { // File with the RSA certificate in PEM format. oServiceConfig.tls_cert_file = oData["TLSCertFile"]; // File with the RSA private key in PEM format oServiceConfig.tls_key_file = oData["TLSKeyFile"]; // File with the DH data oServiceConfig.dh_file.assign(oData["DHFile"]); // SSL Ciphers oServiceConfig.ciphers.assign(oData["SSLCiphers"]); if (oServiceConfig.tls_cert_file.size() != oServiceConfig.tls_key_file.size()) { oLogger.Emerg("Number of files `Service/%s/TLSCertFile` and Service/%s/TLSKeyFile` must be equal", oServiceConfig.name.c_str()); return CONFIG_ERROR; } // Use Transport Level Security at connection time oServiceConfig.use_tls = ConfigHelper::ParseBool(oData["UseTLS"]); // Allow upgrade an existing insecure connection to a secure connection using SSL/TLS oServiceConfig.start_tls = ConfigHelper::ParseBool(oData["StartTLS"]); // Prefer to user server ciphers oServiceConfig.prefer_server_ciphers = ConfigHelper::ParseBool(oData["PreferServerCiphers"], true); } #endif // IRIS_TLS_SUPPORT // Handler name oServiceConfig.handler_name.assign(oData["Handler"]); // Handler object oServiceConfig.handler = NULL; return OK; }
int main(int argc, char ** argv) { if (argc != 3 && argc != 2) { fprintf(stderr, "usage: %s config_file.conf [output file]\n", argv[0]); return EX_SOFTWARE; } FILE * FOUT = stdout; if (argc == 3) { FOUT = fopen(argv[2], "w"); if (FOUT == NULL) { fprintf(stderr, "FATAL: Can't open `%s` for writing\n", argv[2]); return EX_SOFTWARE; } } LoggerFile oLogger(stderr); VariantNC oVariant; STLW::vector<STLW::string> vIncludeFiles; STLW::vector<STLW::string> vConfigs; STLW::set<STLW::string> sSections; ConfigHelper::State eState = ConfigHelper::ParseConfigFile(argv[1], vIncludeFiles, vConfigs, sSections, oVariant, oLogger); if (eState != ConfigHelper::OK) { return EX_SOFTWARE; } STLW::stringstream sStream; VariantNC::ConstIterator itoSections = oVariant.Begin(); while (itoSections != oVariant.End()) { VariantNC::ConstIterator itoSectionId = itoSections -> second.Begin(); while (itoSectionId != itoSections -> second.End()) { sStream << itoSections -> first << " " << itoSectionId -> first << "\n{\n"; VariantNC::ConstIterator itoPairs = itoSectionId -> second.Begin(); UINT_64 iMaxKeyLength = 0; while (itoPairs != itoSectionId -> second.End()) { if (iMaxKeyLength < itoPairs -> first.size()) { iMaxKeyLength = itoPairs -> first.size(); } ++itoPairs; } iMaxKeyLength += 1; itoPairs = itoSectionId -> second.Begin(); while (itoPairs != itoSectionId -> second.End()) { sStream << '\t' << EscapeString(itoPairs -> first) << STLW::string(iMaxKeyLength - itoPairs -> first.size(), ' '); if (itoPairs -> second.Type() == VariantNC::STRING) { sStream << ' ' << EscapeString(itoPairs -> second.Str()) << ";\n"; } else { UINT_64 iLineLength = itoPairs -> first.size(); for (UINT_64 iPos = 0; iPos < itoPairs -> second.Size(); ++iPos) { iLineLength += itoPairs -> second[iPos].Size(); } for (UINT_64 iPos = 0; iPos < itoPairs -> second.Size(); ++iPos) { if (iPos == 0 || iLineLength < 80) { sStream << ' ' << EscapeString(itoPairs -> second[iPos].Str()); if (iLineLength >= 80 && iPos != itoPairs -> second.Size() - 1) { sStream << '\n'; } } else { sStream << '\t' << STLW::string(iMaxKeyLength + 1, ' ') << EscapeString(itoPairs -> second[iPos].Str()); if (iPos != itoPairs -> second.Size() - 1) { sStream << '\n'; } } } sStream << ";\n"; } ++itoPairs; } sStream << "};\n\n"; ++itoSectionId; } ++itoSections; } STLW::vector<STLW::string>::const_iterator itvIncludeFiles = vIncludeFiles.begin(); while (itvIncludeFiles != vIncludeFiles.end()) { sStream << "Include " << EscapeString(*itvIncludeFiles) << ";\n"; ++itvIncludeFiles; } sStream << "\n"; STLW::vector<STLW::string>::const_iterator itvConfigs = vConfigs.begin(); while (itvConfigs != vConfigs.end()) { sStream << "Execute " << EscapeString(*itvConfigs) << ";\n"; ++itvConfigs; } sStream << "\n"; fprintf(stdout, "%s", sStream.str().c_str()); if (argc == 3) { fclose(FOUT); } fclose(stdin); fclose(stdout); fclose(stderr); return EX_OK; }
// // Load modules // INT_32 MainProcess::LoadModule(const STLW::string & sModuleType, const STLW::string & sModuleName, const STLW::string & sLibrary, const STLW::string & sDriver, const VariantNC & oModuleConfig, const STLW::vector<STLW::string> & vLibexecDirs, Logger & oLogger) { oLogger.Info("Opening `%s/%s` from library `%s`", sModuleType.c_str(), sModuleName.c_str(), sLibrary.c_str()); STLW::string sFullpath; INT_32 iRC = FindFile(vLibexecDirs, sLibrary, sFullpath); if (iRC == -1) { STLW::string sDirList; STLW::vector<STLW::string>::const_iterator itvLibexecDirs = vLibexecDirs.begin(); for (;;) { sDirList += "`" + *itvLibexecDirs + "` "; ++itvLibexecDirs; if (itvLibexecDirs == vLibexecDirs.end()) { break; } sDirList += ", "; } oLogger.Emerg("Can't find library `%s` in LibexecDirs(%s) ", sLibrary.c_str(), sDirList.c_str()); return -1; } oLogger.Info("Library `%s` found here: `%s`", sLibrary.c_str(), sFullpath.c_str()); Object * pObject = oGlobalContext.loader.GetObject(sFullpath.c_str(), sDriver.c_str()); if (pObject == NULL) { oLogger.Emerg("Can't load object `%s` from file `%s`", sDriver.c_str(), sFullpath.c_str()); return -1; } // Check type of object const STLW::string sObjectType = pObject -> GetObjectType(); if (Unicode::CompareIgnoreCase(sObjectType.data(), sObjectType.size(), sModuleType.data(), sModuleType.size()) != 0) { oLogger.Emerg("Need type `%s`, but object `%s` loaded from file `%s` has type `%s`", sModuleType.c_str(), pObject -> GetObjectName(), sFullpath.c_str(), pObject -> GetObjectType()); delete pObject; return -1; } oLogger.Info("Object `%s` with type `%s` loaded from file `%s`", pObject -> GetObjectName(), pObject -> GetObjectType(), sFullpath.c_str()); // Initialize module iRC = static_cast<Module *>(pObject) -> InitModule(oGlobalContext, oModuleConfig, oSigHandler, oLogger); if (iRC != 0) { oLogger.Emerg("Can't initialize module `%s` from file `%s`", sModuleName.c_str(), sFullpath.c_str()); delete pObject; return -1; } const STLW::string sFullName = sModuleType + '/' + sModuleName; vModules.push_back(sFullName); // Store object in factory if(oGlobalContext.factory.AddObject(sFullName, pObject) == NULL) { oLogger.Emerg("Can't add module `%s` from file `%s`", sModuleName.c_str(), sFullpath.c_str()); static_cast<Module *>(pObject) -> DestroyModule(oGlobalContext, oSigHandler, oLogger); delete pObject; return -1; } return 0; }
// // Run main process // INT_32 MainProcess::Run() { // Create main event context MainLoopContext oMainContext(oGlobalContext); // Check number of listeners Listeners::iterator itvListeners = vListeners.begin(); if (itvListeners == vListeners.end()) { oGlobalContext.error_log -> Emerg("No listeners found"); return -1; } // Find smallest timeout oMainContext.timeout_check_interval = itvListeners -> service_config -> io_timeout; while(itvListeners != vListeners.end()) { if (oMainContext.timeout_check_interval > itvListeners -> service_config -> io_timeout) { oMainContext.timeout_check_interval = itvListeners -> service_config -> io_timeout; } ++itvListeners; } // Need double precision if (oMainContext.timeout_check_interval != -1) { oMainContext.timeout_check_interval /= 2; } oGlobalContext.error_log -> Info("Timeout check interval set to %f sec", oMainContext.timeout_check_interval); // Contextes for thread watchers STLW::vector<AcceptLoopContext *> vContextes; // Shutdown accept sockets when SIGTERM catched and shutdown all sockets when SIGINT catched MainLoopSignalHandler oMainLoopSignalHandler(oMainContext, vContextes); oSigHandler.RegisterHandler(SIGINT, &oMainLoopSignalHandler); oSigHandler.RegisterHandler(SIGTERM, &oMainLoopSignalHandler); // Create group of threads with network listeners ThreadGroup<AcceptLoopWorker> oThreadGroup; // Create threads for(UINT_32 iPos = 0; iPos < oGlobalContext.config.network_threads; ++iPos) { AcceptLoopContext * pAcceptLoopContext = new AcceptLoopContext(oMainContext); vContextes.push_back(pAcceptLoopContext); INT_32 iCPUNum = -1; if (oGlobalContext.config.bind_network_threads_to_cpu) { iCPUNum = iPos; } oThreadGroup.CreateThread(new AcceptLoopWorker(pAcceptLoopContext, iCPUNum)); } // Create watcher one per each server socket STLW::vector<MainLoopEventWatcher *> vWatchers; itvListeners = vListeners.begin(); while(itvListeners != vListeners.end()) { vWatchers.push_back(new MainLoopEventWatcher(oMainContext, vContextes, itvListeners -> socket, itvListeners -> service_config)); ++itvListeners; } // Wait for events oGlobalContext.error_log -> Info("Staring main loop"); oMainContext.main_loop.Loop(); oGlobalContext.error_log -> Info("Shutting down all watchers"); // Clear garbage and exit STLW::vector<MainLoopEventWatcher *>::iterator itvWatchers = vWatchers.begin(); while (itvWatchers != vWatchers.end()) { delete *itvWatchers; ++itvWatchers; } // Remove signal handlers oSigHandler.RemoveHandler(SIGINT, &oMainLoopSignalHandler); oSigHandler.RemoveHandler(SIGTERM, &oMainLoopSignalHandler); oGlobalContext.error_log -> Info("Waiting for network threads"); return 0; }