]> git.stg.codes - stg.git/blob - projects/stargazer/settings_impl.cpp
Help book chapter 2 complete
[stg.git] / projects / stargazer / settings_impl.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
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 General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Date: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23  */
24
25 /*
26 $Revision: 1.45 $
27 $Date: 2010/08/19 13:42:30 $
28 $Author: faust $
29 */
30
31 #include <cstring>
32 #include <cerrno>
33 #include <string>
34
35 #include "stg/logger.h"
36 #include "stg/dotconfpp.h"
37 #include "settings_impl.h"
38
39 using namespace std;
40
41 //-----------------------------------------------------------------------------
42 SETTINGS_IMPL::SETTINGS_IMPL()
43     : strError(),
44       modulesPath("/usr/lib/stg"),
45       dirName(DIR_NUM),
46       confDir("/etc/stargazer"),
47       scriptsDir("/etc/stargazer"),
48       rules("/etc/stargazer/rules"),
49       logFile("/var/log/stargazer.log"),
50       pidFile("/var/run/stargazer.pid"),
51       monitorDir("/var/stargazer/monitoring"),
52       monitoring(false),
53       detailStatWritePeriod(dsPeriod_1_6),
54       statWritePeriod(10),
55       stgExecMsgKey(5555),
56       executersNum(1),
57       fullFee(false),
58       dayFee(0),
59       dayResetTraff(0),
60       spreadFee(false),
61       freeMbAllowInet(false),
62       dayFeeIsLastDay(false),
63       writeFreeMbTraffCost(false),
64       showFeeInCash(true),
65       messageTimeout(0),
66       feeChargeType(0),
67       reconnectOnTariffChange(false),
68       modulesSettings(),
69       storeModuleSettings(),
70       logger(GetStgLogger())
71 {
72 }
73 //-----------------------------------------------------------------------------
74 SETTINGS_IMPL::SETTINGS_IMPL(const std::string & cd)
75     : strError(),
76       modulesPath("/usr/lib/stg"),
77       dirName(DIR_NUM),
78       confDir(cd),
79       scriptsDir(cd),
80       rules(cd + "/rules"),
81       logFile("/var/log/stargazer.log"),
82       pidFile("/var/run/stargazer.pid"),
83       monitorDir("/var/stargazer/monitoring"),
84       monitoring(false),
85       detailStatWritePeriod(dsPeriod_1_6),
86       statWritePeriod(10),
87       stgExecMsgKey(5555),
88       executersNum(1),
89       fullFee(false),
90       dayFee(0),
91       dayResetTraff(0),
92       spreadFee(false),
93       freeMbAllowInet(false),
94       dayFeeIsLastDay(false),
95       writeFreeMbTraffCost(false),
96       showFeeInCash(true),
97       messageTimeout(0),
98       feeChargeType(0),
99       reconnectOnTariffChange(false),
100       modulesSettings(),
101       storeModuleSettings(),
102       logger(GetStgLogger())
103 {
104 }
105 //-----------------------------------------------------------------------------
106 SETTINGS_IMPL::SETTINGS_IMPL(const SETTINGS_IMPL & rval)
107     : strError(),
108       modulesPath(rval.modulesPath),
109       dirName(rval.dirName),
110       confDir(rval.confDir),
111       scriptsDir(rval.scriptsDir),
112       rules(rval.rules),
113       logFile(rval.logFile),
114       pidFile(rval.pidFile),
115       monitorDir(rval.monitorDir),
116       monitoring(rval.monitoring),
117       detailStatWritePeriod(rval.detailStatWritePeriod),
118       statWritePeriod(rval.statWritePeriod),
119       stgExecMsgKey(rval.stgExecMsgKey),
120       executersNum(rval.executersNum),
121       fullFee(rval.fullFee),
122       dayFee(rval.dayFee),
123       dayResetTraff(rval.dayResetTraff),
124       spreadFee(rval.spreadFee),
125       freeMbAllowInet(rval.freeMbAllowInet),
126       dayFeeIsLastDay(rval.dayFeeIsLastDay),
127       writeFreeMbTraffCost(rval.writeFreeMbTraffCost),
128       showFeeInCash(rval.showFeeInCash),
129       messageTimeout(rval.messageTimeout),
130       feeChargeType(rval.feeChargeType),
131       reconnectOnTariffChange(rval.reconnectOnTariffChange),
132       modulesSettings(rval.modulesSettings),
133       storeModuleSettings(rval.storeModuleSettings),
134       logger(GetStgLogger())
135 {
136 }
137 //-----------------------------------------------------------------------------
138 int SETTINGS_IMPL::ParseYesNo(const string & value, bool * val)
139 {
140 if (0 == strcasecmp(value.c_str(), "yes"))
141     {
142     *val = true;
143     return 0;
144     }
145 if (0 == strcasecmp(value.c_str(), "no"))
146     {
147     *val = false;
148     return 0;
149     }
150
151 strError = "Incorrect value \'" + value + "\'.";
152 return -1;
153 }
154 //-----------------------------------------------------------------------------
155 int SETTINGS_IMPL::ParseInt(const string & value, int * val)
156 {
157 if (str2x<int>(value, *val))
158     {
159     strError = "Cannot convert \'" + value + "\' to integer.";
160     return -1;
161     }
162 return 0;
163 }
164 //-----------------------------------------------------------------------------
165 int SETTINGS_IMPL::ParseUnsigned(const string & value, unsigned * val)
166 {
167 if (str2x<unsigned>(value, *val))
168     {
169     strError = "Cannot convert \'" + value + "\' to unsigned integer.";
170     return -1;
171     }
172 return 0;
173 }
174 //-----------------------------------------------------------------------------
175 int SETTINGS_IMPL::ParseIntInRange(const string & value, int min, int max, int * val)
176 {
177 if (ParseInt(value, val) != 0)
178     return -1;
179
180 if (*val < min || *val > max)
181     {
182     strError = "Value \'" + value + "\' out of range.";
183     return -1;
184     }
185
186 return 0;
187 }
188 //-----------------------------------------------------------------------------
189 int SETTINGS_IMPL::ParseUnsignedInRange(const string & value, unsigned min, unsigned max, unsigned * val)
190 {
191 if (ParseUnsigned(value, val) != 0)
192     return -1;
193
194 if (*val < min || *val > max)
195     {
196     strError = "Value \'" + value + "\' out of range.";
197     return -1;
198     }
199
200 return 0;
201 }
202 //-----------------------------------------------------------------------------
203 int SETTINGS_IMPL::ParseModuleSettings(const DOTCONFDocumentNode * node, vector<PARAM_VALUE> * params)
204 {
205 const DOTCONFDocumentNode * childNode;
206 PARAM_VALUE pv;
207 const char * value;
208
209 pv.param = node->getName();
210
211 if (node->getValue(1))
212     {
213     strError = "Unexpected value \'" + string(node->getValue(1)) + "\'.";
214     return -1;
215     }
216
217 value = node->getValue(0);
218
219 if (!value)
220     {
221     strError = "Module name expected.";
222     return -1;
223     }
224
225 childNode = node->getChildNode();
226 while (childNode)
227     {
228     pv.param = childNode->getName();
229     int i = 0;
230     while ((value = childNode->getValue(i++)) != NULL)
231         {
232         pv.value.push_back(value);
233         }
234     params->push_back(pv);
235     pv.value.clear();
236     childNode = childNode->getNextNode();
237     }
238
239 return 0;
240 }
241 //-----------------------------------------------------------------------------
242 void SETTINGS_IMPL::ErrorCallback(void * data, const char * buf)
243 {
244     printfd(__FILE__, "SETTINGS_IMPL::ErrorCallback() - %s\n", buf);
245     SETTINGS_IMPL * settings = static_cast<SETTINGS_IMPL *>(data);
246     settings->logger("%s", buf);
247 }
248 //-----------------------------------------------------------------------------
249 int SETTINGS_IMPL::ReadSettings()
250 {
251 const char * requiredOptions[] = {
252     "ModulesPath",
253     "Modules",
254     "StoreModule",
255     "Rules",
256     "LogFile",
257     "DetailStatWritePeriod",
258     "DayFee",
259     "DayResetTraff",
260     "SpreadFee",
261     "FreeMbAllowInet",
262     "DayFeeIsLastDay",
263     "WriteFreeMbTraffCost",
264     NULL
265     };
266 int storeModulesCount = 0;
267 modulesSettings.clear();
268
269 DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
270 conf.setErrorCallback(SETTINGS_IMPL::ErrorCallback, this);
271 conf.setRequiredOptionNames(requiredOptions);
272 string confFile = confDir + "/stargazer.conf";
273
274 if(conf.setContent(confFile.c_str()) != 0)
275     {
276     strError = "Cannot read file " + confFile;
277     return -1;
278     }
279
280 const DOTCONFDocumentNode * node = conf.getFirstNode();
281
282 while (node)
283     {
284     if (strcasecmp(node->getName(), "ScriptDir") == 0)
285         {
286         scriptsDir = node->getValue(0);
287         }
288
289     if (strcasecmp(node->getName(), "LogFile") == 0)
290         {
291         logFile = node->getValue(0);
292         }
293
294     if (strcasecmp(node->getName(), "PIDFile") == 0)
295         {
296         pidFile = node->getValue(0);
297         }
298
299     if (strcasecmp(node->getName(), "ModulesPath") == 0)
300         {
301         modulesPath = node->getValue(0);
302         }
303
304     if (strcasecmp(node->getName(), "Rules") == 0)
305         {
306         rules = node->getValue(0);
307         }
308
309     if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
310         {
311         if (ParseDetailStatWritePeriod(node->getValue(0)) != 0)
312             {
313             strError = "Incorrect DetailStatWritePeriod value: \'" + string(node->getValue(0)) + "\'";
314             return -1;
315             }
316         }
317
318     if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
319         {
320         if (ParseUnsignedInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0)
321             {
322             strError = "Incorrect StatWritePeriod value: \'" + string(node->getValue(0)) + "\'";
323             return -1;
324             }
325         }
326
327     if (strcasecmp(node->getName(), "ExecMsgKey") == 0)
328         {
329         if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0)
330             {
331             strError = "Incorrect ExecMsgKey value: \'" + string(node->getValue(0)) + "\'";
332             return -1;
333             }
334         }
335
336     if (strcasecmp(node->getName(), "ExecutersNum") == 0)
337         {
338         if (ParseUnsignedInRange(node->getValue(0), 1, 1024, &executersNum) != 0)
339             {
340             strError = "Incorrect ExecutersNum value: \'" + string(node->getValue(0)) + "\'";
341             return -1;
342             }
343         }
344
345     if (strcasecmp(node->getName(), "DayFee") == 0)
346         {
347         if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayFee) != 0)
348             {
349             strError = "Incorrect DayFee value: \'" + string(node->getValue(0)) + "\'";
350             return -1;
351             }
352         }
353
354     if (strcasecmp(node->getName(), "FullFee") == 0)
355         {
356         if (ParseYesNo(node->getValue(0), &fullFee) != 0)
357             {
358             strError = "Incorrect FullFee value: \'" + string(node->getValue(0)) + "\'";
359             return -1;
360             }
361         }
362
363     if (strcasecmp(node->getName(), "DayResetTraff") == 0)
364         {
365         if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0)
366             {
367             strError = "Incorrect DayResetTraff value: \'" + string(node->getValue(0)) + "\'";
368             return -1;
369             }
370         }
371
372     if (strcasecmp(node->getName(), "SpreadFee") == 0)
373         {
374         if (ParseYesNo(node->getValue(0), &spreadFee) != 0)
375             {
376             strError = "Incorrect SpreadFee value: \'" + string(node->getValue(0)) + "\'";
377             return -1;
378             }
379         }
380
381     if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0)
382         {
383         if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0)
384             {
385             strError = "Incorrect FreeMbAllowInet value: \'" + string(node->getValue(0)) + "\'";
386             return -1;
387             }
388         }
389
390     if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0)
391         {
392         if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0)
393             {
394             strError = "Incorrect DayFeeIsLastDay value: \'" + string(node->getValue(0)) + "\'";
395             return -1;
396             }
397         }
398
399     if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
400         {
401         if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
402             {
403             strError = "Incorrect WriteFreeMbTraffCost value: \'" + string(node->getValue(0)) + "\'";
404             return -1;
405             }
406         }
407
408     if (strcasecmp(node->getName(), "ShowFeeInCash") == 0)
409         {
410         if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0)
411             {
412             strError = "Incorrect ShowFeeInCash value: \'" + string(node->getValue(0)) + "\'";
413             return -1;
414             }
415         }
416
417     if (strcasecmp(node->getName(), "MonitorDir") == 0)
418         {
419         monitorDir = node->getValue(0);
420         struct stat stat;
421         monitoring = false;
422
423         if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode))
424             {
425             monitoring = true;
426             }
427         }
428
429     if (strcasecmp(node->getName(), "MessageTimeout") == 0)
430         {
431         if (ParseUnsigned(node->getValue(0), &messageTimeout) != 0)
432             {
433             strError = "Incorrect MessageTimeout value: \'" + string(node->getValue(0)) + "\'";
434             return -1;
435             }
436         }
437
438     if (strcasecmp(node->getName(), "FeeChargeType") == 0)
439         {
440         if (ParseUnsignedInRange(node->getValue(0), 0, 2, &feeChargeType) != 0)
441             {
442             strError = "Incorrect FeeChargeType value: \'" + string(node->getValue(0)) + "\'";
443             return -1;
444             }
445         }
446
447     if (strcasecmp(node->getName(), "ReconnectOnTariffChange") == 0)
448         {
449         if (ParseYesNo(node->getValue(0), &reconnectOnTariffChange) != 0)
450             {
451             strError = "Incorrect ReconnectOnTariffChange value: \'" + string(node->getValue(0)) + "\'";
452             return -1;
453             }
454         }
455
456     if (strcasecmp(node->getName(), "DirNames") == 0)
457         {
458         const DOTCONFDocumentNode * child = node->getChildNode();
459         if (child)
460             {
461             const DOTCONFDocumentNode * dirNameNode;
462             dirName.reserve(DIR_NUM);
463             for (int i = 0; i < DIR_NUM; i++)
464                 {
465                 char strDirName[12];
466                 sprintf(strDirName, "DirName%d", i);
467                 dirNameNode = conf.findNode(strDirName, node);
468                 if (dirNameNode && dirNameNode->getValue(0))
469                     {
470                     dirName[i] = dirNameNode->getValue(0);
471                     }
472                 }
473             }
474         }
475
476     if (strcasecmp(node->getName(), "StoreModule") == 0)
477         {
478         if (node->getValue(1))
479             {
480             strError = "Unexpected \'" + string(node->getValue(1)) + "\'.";
481             return -1;
482             }
483
484         if (storeModulesCount)
485             {
486             strError = "Should be only one StoreModule.";
487             return -1;
488             }
489         storeModulesCount++;
490
491         storeModuleSettings.moduleName = node->getValue(0);
492         ParseModuleSettings(node, &storeModuleSettings.moduleParams);
493         }
494
495     if (strcasecmp(node->getName(), "Modules") == 0)
496         {
497         if (node->getValue(0))
498             {
499             strError = "Unexpected \'" + string(node->getValue(0)) + "\'.";
500             return -1;
501             }
502         const DOTCONFDocumentNode * child = node->getChildNode();
503         while (child)
504             {
505             if (strcasecmp(child->getName(), "Module") != 0)
506                 {
507                 child = child->getNextNode();
508                 continue;
509                 }
510             MODULE_SETTINGS modSettings;
511             modSettings.moduleParams.clear();
512             modSettings.moduleName = child->getValue();
513
514             ParseModuleSettings(child, &modSettings.moduleParams);
515
516             modulesSettings.push_back(modSettings);
517
518             child = child->getNextNode();
519             }
520         }
521
522     node = node->getNextNode();
523     }
524
525 return 0;
526 }
527 //-----------------------------------------------------------------------------
528 int SETTINGS_IMPL::ParseDetailStatWritePeriod(const string & detailStatPeriodStr)
529 {
530 if (detailStatPeriodStr == "1")
531     {
532     detailStatWritePeriod = dsPeriod_1;
533     return 0;
534     }
535 else if (detailStatPeriodStr == "1/2")
536     {
537     detailStatWritePeriod = dsPeriod_1_2;
538     return 0;
539     }
540 else if (detailStatPeriodStr == "1/4")
541     {
542     detailStatWritePeriod = dsPeriod_1_4;
543     return 0;
544     }
545 else if (detailStatPeriodStr == "1/6")
546     {
547     detailStatWritePeriod = dsPeriod_1_6;
548     return 0;
549     }
550
551 return -1;
552 }
553 //-----------------------------------------------------------------------------