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