X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/8c6fa3fbaccc22127280bf77a48fab5a3ee0716e..46b0747592074017ff0ea4b33d4a7194235886e5:/stargazer/settings_impl.cpp diff --git a/stargazer/settings_impl.cpp b/stargazer/settings_impl.cpp new file mode 100644 index 00000000..be7d66a4 --- /dev/null +++ b/stargazer/settings_impl.cpp @@ -0,0 +1,521 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + */ + +#include "settings_impl.h" + +#include "stg/logger.h" +#include "stg/dotconfpp.h" +#include "stg/common.h" +#include "stg/const.h" + +#include +#include +#include + +namespace +{ + +struct Error : public std::runtime_error +{ + Error(const std::string& message) : runtime_error(message) {} +}; + +std::vector toValues(const DOTCONFDocumentNode& node) +{ + std::vector values; + + size_t i = 0; + const char* value = NULL; + while ((value = node.getValue(i++)) != NULL) + values.push_back(value); + + return values; +} + +std::vector toPVS(const DOTCONFDocumentNode& node) +{ + std::vector pvs; + + const DOTCONFDocumentNode* child = node.getChildNode(); + while (child != NULL) + { + if (child->getName() == NULL) + continue; + + if (child->getChildNode() == NULL) + pvs.push_back(PARAM_VALUE(child->getName(), toValues(*child))); + else + pvs.push_back(PARAM_VALUE(child->getName(), toValues(*child), toPVS(*child))); + + child = child->getNextNode(); + } + + return pvs; +} + +unsigned toPeriod(const char* value) +{ + if (value == NULL) + throw Error("No detail stat period value."); + + std::string period(value); + if (period == "1") + return dsPeriod_1; + else if (period == "1/2") + return dsPeriod_1_2; + else if (period == "1/4") + return dsPeriod_1_4; + else if (period == "1/6") + return dsPeriod_1_6; + + throw Error("Invalid detail stat period value: '" + period + "'. Should be one of '1', '1/2', '1/4' or '1/6'."); +} + +} + +//----------------------------------------------------------------------------- +SETTINGS_IMPL::SETTINGS_IMPL(const std::string & cd) + : modulesPath("/usr/lib/stg"), + dirName(DIR_NUM), + confDir(cd.empty() ? "/etc/stargazer" : cd), + scriptsDir(confDir), + rules(confDir + "/rules"), + logFile("/var/log/stargazer.log"), + pidFile("/var/run/stargazer.pid"), + monitorDir("/var/stargazer/monitoring"), + monitoring(false), + detailStatWritePeriod(dsPeriod_1_6), + statWritePeriod(10), + stgExecMsgKey(5555), + executersNum(1), + fullFee(false), + dayFee(0), + dayResetTraff(0), + spreadFee(false), + freeMbAllowInet(false), + dayFeeIsLastDay(false), + stopOnError(true), + writeFreeMbTraffCost(false), + showFeeInCash(true), + messageTimeout(0), + feeChargeType(0), + reconnectOnTariffChange(false), + disableSessionLog(false), + logger(GetStgLogger()) +{ + filterParamsLog.push_back("*"); +} +//----------------------------------------------------------------------------- +SETTINGS_IMPL::SETTINGS_IMPL(const SETTINGS_IMPL & rval) + : modulesPath(rval.modulesPath), + dirName(rval.dirName), + confDir(rval.confDir), + scriptsDir(rval.scriptsDir), + rules(rval.rules), + logFile(rval.logFile), + pidFile(rval.pidFile), + monitorDir(rval.monitorDir), + monitoring(rval.monitoring), + detailStatWritePeriod(rval.detailStatWritePeriod), + statWritePeriod(rval.statWritePeriod), + stgExecMsgKey(rval.stgExecMsgKey), + executersNum(rval.executersNum), + fullFee(rval.fullFee), + dayFee(rval.dayFee), + dayResetTraff(rval.dayResetTraff), + spreadFee(rval.spreadFee), + freeMbAllowInet(rval.freeMbAllowInet), + dayFeeIsLastDay(rval.dayFeeIsLastDay), + stopOnError(rval.stopOnError), + writeFreeMbTraffCost(rval.writeFreeMbTraffCost), + showFeeInCash(rval.showFeeInCash), + messageTimeout(rval.messageTimeout), + feeChargeType(rval.feeChargeType), + reconnectOnTariffChange(rval.reconnectOnTariffChange), + disableSessionLog(rval.disableSessionLog), + filterParamsLog(rval.filterParamsLog), + modulesSettings(rval.modulesSettings), + storeModuleSettings(rval.storeModuleSettings), + logger(GetStgLogger()) +{ +} +//----------------------------------------------------------------------------- +SETTINGS_IMPL & SETTINGS_IMPL::operator=(const SETTINGS_IMPL & rhs) +{ + modulesPath = rhs.modulesPath; + dirName = rhs.dirName; + confDir = rhs.confDir; + scriptsDir = rhs.scriptsDir; + rules = rhs.rules; + logFile = rhs.logFile; + pidFile = rhs.pidFile; + monitorDir = rhs.monitorDir; + scriptParams = rhs.scriptParams; + monitoring = rhs.monitoring; + detailStatWritePeriod = rhs.detailStatWritePeriod; + statWritePeriod = rhs.statWritePeriod; + stgExecMsgKey = rhs.stgExecMsgKey; + executersNum = rhs.executersNum; + fullFee = rhs.fullFee; + dayFee = rhs.dayFee; + dayResetTraff = rhs.dayResetTraff; + spreadFee = rhs.spreadFee; + freeMbAllowInet = rhs.freeMbAllowInet; + dayFeeIsLastDay = rhs.dayFeeIsLastDay; + stopOnError = rhs.stopOnError; + writeFreeMbTraffCost = rhs.writeFreeMbTraffCost; + showFeeInCash = rhs.showFeeInCash; + messageTimeout = rhs.messageTimeout; + feeChargeType = rhs.feeChargeType; + reconnectOnTariffChange = rhs.reconnectOnTariffChange; + disableSessionLog = rhs.disableSessionLog; + filterParamsLog = rhs.filterParamsLog; + + modulesSettings = rhs.modulesSettings; + storeModuleSettings = rhs.storeModuleSettings; + return *this; +} +//----------------------------------------------------------------------------- +void SETTINGS_IMPL::ErrorCallback(void * data, const char * buf) +{ + printfd(__FILE__, "SETTINGS_IMPL::ErrorCallback() - %s\n", buf); + SETTINGS_IMPL * settings = static_cast(data); + settings->logger("%s", buf); +} +//----------------------------------------------------------------------------- +int SETTINGS_IMPL::ReadSettings() +{ +const char * requiredOptions[] = { + "ModulesPath", + "Modules", + "StoreModule", + "Rules", + "LogFile", + "DetailStatWritePeriod", + "DayFee", + "DayResetTraff", + "SpreadFee", + "FreeMbAllowInet", + "DayFeeIsLastDay", + "WriteFreeMbTraffCost", + NULL + }; +int storeModulesCount = 0; +modulesSettings.clear(); + +DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE); +conf.setErrorCallback(SETTINGS_IMPL::ErrorCallback, this); +conf.setRequiredOptionNames(requiredOptions); +std::string confFile = confDir + "/stargazer.conf"; + +if(conf.setContent(confFile.c_str()) != 0) + { + strError = "Cannot read file " + confFile; + return -1; + } + +const DOTCONFDocumentNode * node = conf.getFirstNode(); + +while (node) + { + if (strcasecmp(node->getName(), "ScriptDir") == 0) + { + scriptsDir = node->getValue(0); + } + + if (strcasecmp(node->getName(), "LogFile") == 0) + { + logFile = node->getValue(0); + } + + if (strcasecmp(node->getName(), "PIDFile") == 0) + { + pidFile = node->getValue(0); + } + + if (strcasecmp(node->getName(), "ModulesPath") == 0) + { + modulesPath = node->getValue(0); + } + + if (strcasecmp(node->getName(), "Rules") == 0) + { + rules = node->getValue(0); + } + + if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0) + { + try + { + detailStatWritePeriod = toPeriod(node->getValue(0)); + } + catch (const Error& error) + { + strError = error.what(); + return -1; + } + } + + if (strcasecmp(node->getName(), "StatWritePeriod") == 0) + { + if (ParseUnsignedInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0) + { + strError = "Incorrect StatWritePeriod value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "ExecMsgKey") == 0) + { + if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0) + { + strError = "Incorrect ExecMsgKey value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "ExecutersNum") == 0) + { + if (ParseUnsignedInRange(node->getValue(0), 1, 1024, &executersNum) != 0) + { + strError = "Incorrect ExecutersNum value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "DayFee") == 0) + { + if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayFee) != 0) + { + strError = "Incorrect DayFee value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "FullFee") == 0) + { + if (ParseYesNo(node->getValue(0), &fullFee) != 0) + { + strError = "Incorrect FullFee value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "DayResetTraff") == 0) + { + if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0) + { + strError = "Incorrect DayResetTraff value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "SpreadFee") == 0) + { + if (ParseYesNo(node->getValue(0), &spreadFee) != 0) + { + strError = "Incorrect SpreadFee value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0) + { + if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0) + { + strError = "Incorrect FreeMbAllowInet value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0) + { + if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0) + { + strError = "Incorrect DayFeeIsLastDay value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "StopOnError") == 0) + { + if (ParseYesNo(node->getValue(0), &stopOnError) != 0) + { + strError = "Incorrect StopOnError value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0) + { + if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0) + { + strError = "Incorrect WriteFreeMbTraffCost value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "ShowFeeInCash") == 0) + { + if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0) + { + strError = "Incorrect ShowFeeInCash value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "MonitorDir") == 0) + { + monitorDir = node->getValue(0); + struct stat stat; + monitoring = false; + + if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode)) + { + monitoring = true; + } + } + + if (strcasecmp(node->getName(), "MessageTimeout") == 0) + { + if (ParseUnsigned(node->getValue(0), &messageTimeout) != 0) + { + strError = "Incorrect MessageTimeout value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "FeeChargeType") == 0) + { + if (ParseUnsignedInRange(node->getValue(0), 0, 3, &feeChargeType) != 0) + { + strError = "Incorrect FeeChargeType value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "ReconnectOnTariffChange") == 0) + { + if (ParseYesNo(node->getValue(0), &reconnectOnTariffChange) != 0) + { + strError = "Incorrect ReconnectOnTariffChange value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "DisableSessionLog") == 0) + { + if (ParseYesNo(node->getValue(0), &disableSessionLog) != 0) + { + strError = "Incorrect DisableSessionLog value: \'" + std::string(node->getValue(0)) + "\'"; + return -1; + } + } + + if (strcasecmp(node->getName(), "FilterParamsLog") == 0) + { + filterParamsLog.clear(); + for (int i = 0; node->getValue(i) != NULL; ++i) + filterParamsLog.push_back(node->getValue(i)); + } + + if (strcasecmp(node->getName(), "DirNames") == 0) + { + const DOTCONFDocumentNode * child = node->getChildNode(); + if (child) + { + const DOTCONFDocumentNode * dirNameNode; + dirName.reserve(DIR_NUM); + for (int i = 0; i < DIR_NUM; i++) + { + char strDirName[12]; + sprintf(strDirName, "DirName%d", i); + dirNameNode = conf.findNode(strDirName, node); + if (dirNameNode && dirNameNode->getValue(0)) + { + dirName[i] = dirNameNode->getValue(0); + } + } + } + } + + if (strcasecmp(node->getName(), "StoreModule") == 0) + { + if (node->getValue(1)) + { + strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'."; + return -1; + } + + if (storeModulesCount) + { + strError = "Should be only one StoreModule."; + return -1; + } + storeModulesCount++; + + if (node->getValue(0) == NULL) + { + strError = "No module name in the StoreModule section."; + return -1; + } + storeModuleSettings.moduleName = node->getValue(0); + storeModuleSettings.moduleParams = toPVS(*node); + } + + if (strcasecmp(node->getName(), "Modules") == 0) + { + if (node->getValue(0)) + { + strError = "Unexpected \'" + std::string(node->getValue(0)) + "\'."; + return -1; + } + const DOTCONFDocumentNode * child = node->getChildNode(); + while (child) + { + if (strcasecmp(child->getName(), "Module") != 0) + { + child = child->getNextNode(); + continue; + } + + if (child->getValue(0) == NULL) + { + strError = "No module name in the Module section."; + return -1; + } + + modulesSettings.push_back(MODULE_SETTINGS(child->getValue(0), toPVS(*child))); + + child = child->getNextNode(); + } + } + + if (strcasecmp(node->getName(), "ScriptParams") == 0) + { + for (int i = 0; node->getValue(i) != NULL; ++i) + scriptParams.push_back(node->getValue(i)); + } + node = node->getNextNode(); + } + +return 0; +} +//-----------------------------------------------------------------------------