Exemple #1
0
//
// 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;
}
int main(int argc, char ** argv)
{
	const char * szConfigFile = NULL;
	if (argc == 1)
	{
		fprintf(stderr, "Global config not given, ");
		szConfigFile = getenv("CAS_GLOBAL_CONFIG");
		if (szConfigFile != NULL)
		{
			fprintf(stderr, " using %s from ENVIRONMENT", szConfigFile);
		}
		else
		{
			szConfigFile = CAS_GLOBAL_CONFIG_FILE;
			fprintf(stderr, " using %s as DEFAULT\n", szConfigFile);
		}
	}
	else if (argc == 2) { szConfigFile = argv[1]; }
	else { fprintf(stderr, "usage: %s [global-config.xml]\n", argv[0]); return EX_USAGE; }

	FILE * F = fopen(szConfigFile, "rb");
	if (F == NULL) { fprintf(stderr, "ERROR: Cannot open `%s` for reading: %s\n", szConfigFile, strerror(errno)); return EX_SOFTWARE; }

	// Store path to file as include directory
	CCHAR_P szTMP = szConfigFile + strlen(szConfigFile);
	while (szTMP != szConfigFile && *szTMP != '/' && *szTMP != '\\') { --szTMP; }

	STLW::vector<STLW::string> vIncludeDirs;
	if (szTMP != szConfigFile) { vIncludeDirs.push_back(STLW::string(szConfigFile, (szTMP - szConfigFile))); }

	try
	{
		ASGlobalConfig oGlobalConfig;
		ASGlobalConfigHandler oHandler(oGlobalConfig, vIncludeDirs);
		ASXMLParser oParser(&oHandler);
		if (oParser.ParseFile(F) == -1)
		{
			fprintf(stderr, "ERROR: In file %s: %s\n", szConfigFile, oHandler.GetError().c_str());
			return EX_CONFIG;
		}
		fclose(F);

		fprintf(stdout, "  Libexec dirs:\n");
		UINT_32 iI = 0;
		for(; iI < oGlobalConfig.libexec_dirs.size(); ++iI)
		{
			fprintf(stdout, "      %s\n", oGlobalConfig.libexec_dirs[iI].c_str());
		}
		fprintf(stdout, "\n  Modules:\n");
		for(iI = 0; iI < oGlobalConfig.modules_list.size(); ++iI)
		{

			fprintf(stdout, "      Name:         %s\n"
			                "      Type:         %s\n",
			                                            oGlobalConfig.modules_list[iI].name.c_str(),
			                                            oGlobalConfig.modules_list[iI].moduletype.c_str());

			STLW::string sTMP = CheckFile(oGlobalConfig.libexec_dirs, oGlobalConfig.modules_list[iI].library);
			if (sTMP.size() == 0)
			{
				fprintf(stdout, "      *** ERROR: Cannot find Library file: %s\n", oGlobalConfig.modules_list[iI].library.c_str());
			}
			else
			{
				fprintf(stdout, "      Library file: %s\n", CheckFile(oGlobalConfig.libexec_dirs, oGlobalConfig.modules_list[iI].library).c_str());
			}
			STLW::string sData = Dump(oGlobalConfig.modules_list[iI].configuration);
			if (!sData.empty() && sData != "\"\"\n") { fprintf(stdout, "      Configuration: %s\n", sData.c_str()); }
			// TBD
			fprintf(stdout, "\n");
		}
	}
        catch(STLW::exception &e) { fprintf(stderr, "ERROR: %s\n", e.what()); return EX_SOFTWARE; }
        catch(...)                { fprintf(stderr, "ERROR: Ouch!\n"); return EX_SOFTWARE; }

	fclose(stdin);
	fclose(stdout);
	fclose(stderr);

return EX_OK;
}
//
// 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;
}
Exemple #8
0
//
// 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;
}
Exemple #9
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;
}