]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/configuration/rpcconfig/rpcconfig.cpp
Merge branch 'master' into full-month-stats
[stg.git] / projects / stargazer / plugins / configuration / rpcconfig / rpcconfig.cpp
1 #include <unistd.h> // TODO: usleep
2
3 #include <cstdlib>
4 #include <csignal>
5
6 #include <vector>
7 #include <algorithm>
8
9 #include "stg/common.h"
10 #include "stg/admin.h"
11 #include "stg/module_settings.h"
12 #include "stg/settings.h"
13
14 #include "rpcconfig.h"
15 #include "info_methods.h"
16 #include "users_methods.h"
17 #include "tariffs_methods.h"
18 #include "admins_methods.h"
19 #include "messages_methods.h"
20
21 class RPC_CONFIG_CREATOR {
22 private:
23     RPC_CONFIG * rpcconfig;
24
25 public:
26     RPC_CONFIG_CREATOR()
27         : rpcconfig(new RPC_CONFIG())
28         {
29         }
30     ~RPC_CONFIG_CREATOR()
31         {
32         delete rpcconfig;
33         }
34
35     RPC_CONFIG * GetPlugin()
36         {
37         return rpcconfig;
38         }
39 };
40
41 RPC_CONFIG_CREATOR rpcc;
42
43 RPC_CONFIG_SETTINGS::RPC_CONFIG_SETTINGS()
44     : errorStr(),
45       port(0),
46       cookieTimeout(0)
47 {
48 }
49
50 int RPC_CONFIG_SETTINGS::ParseIntInRange(const std::string & str,
51                                          int min,
52                                          int max,
53                                          int * val)
54 {
55 if (str2x(str.c_str(), *val))
56     {
57     errorStr = "Incorrect value \'" + str + "\'.";
58     return -1;
59     }
60 if (*val < min || *val > max)
61     {
62     errorStr = "Value \'" + str + "\' out of range.";
63     return -1;
64     }
65 return 0;
66 }
67
68 int RPC_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
69 {
70 int p;
71 PARAM_VALUE pv;
72 std::vector<PARAM_VALUE>::const_iterator pvi;
73
74 pv.param = "Port";
75 pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
76 if (pvi == s.moduleParams.end())
77     {
78     errorStr = "Parameter \'Port\' not found.";
79     printfd(__FILE__, "Parameter 'Port' not found\n");
80     return -1;
81     }
82 if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
83     {
84     errorStr = "Cannot parse parameter \'Port\': " + errorStr;
85     printfd(__FILE__, "Cannot parse parameter 'Port'\n");
86     return -1;
87     }
88 port = p;
89
90 pv.param = "CookieTimeout";
91 pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
92 if (pvi == s.moduleParams.end())
93     {
94     cookieTimeout = 1800; // 30 * 60
95     }
96 else
97     {
98     if (str2x(pvi->value[0], cookieTimeout))
99         {
100         errorStr = "Incorrect value of CookieTimeout: \'" + pvi->value[0] + "\'";
101         printfd(__FILE__, "Incorrect value of 'CookieTimeout'\n");
102         return -1;
103         }
104     }
105
106 return 0;
107 }
108
109 PLUGIN * GetPlugin()
110 {
111 return rpcc.GetPlugin();
112 }
113
114 RPC_CONFIG::RPC_CONFIG()
115     : users(NULL),
116       admins(NULL),
117       tariffs(NULL),
118       store(NULL),
119       rpcServer(NULL),
120       running(false),
121       stopped(true),
122       dayFee(0)
123 {
124 }
125
126 RPC_CONFIG::~RPC_CONFIG()
127 {
128 // delete server
129 delete rpcServer;
130 }
131
132 int RPC_CONFIG::ParseSettings()
133 {
134 int ret = rpcConfigSettings.ParseSettings(settings);
135
136 if (ret)
137     errorStr = rpcConfigSettings.GetStrError();
138
139 return ret;
140 }
141
142 void RPC_CONFIG::SetStgSettings(const SETTINGS * settings)
143 {
144     dayFee = settings->GetDayFee();
145     dirNames.erase(dirNames.begin(), dirNames.end());
146     for (size_t i = 0; i < DIR_NUM; ++i) {
147         dirNames.push_back(settings->GetDirName(i));
148     }
149 }
150
151 int RPC_CONFIG::Start()
152 {
153 InitiateRegistry();
154 running = true;
155 rpcServer = new xmlrpc_c::serverAbyss(
156         rpcRegistry,
157         rpcConfigSettings.GetPort(),
158         "/var/log/stargazer_rpc.log"
159         );
160 if (pthread_create(&tid, NULL, Run, this))
161     {
162     errorStr = "Failed to create RPC thread";
163     printfd(__FILE__, "Failed to crate RPC thread\n");
164     return -1;
165     }
166 return 0;
167 }
168
169 int RPC_CONFIG::Stop()
170 {
171 running = false;
172 for (int i = 0; i < 5 && !stopped; ++i)
173     usleep(200000);
174 //rpcServer->terminate();
175 if (!stopped)
176     {
177     if (pthread_kill(tid, SIGTERM))
178         {
179         errorStr = "Failed to kill thread";
180         printfd(__FILE__, "Failed to kill thread\n");
181         }
182     for (int i = 0; i < 25 && !stopped; ++i)
183         usleep(200000);
184     if (!stopped)
185         {
186         printfd(__FILE__, "Failed to stop RPC thread\n");
187         errorStr = "Failed to stop RPC thread";
188         return -1;
189         }
190     else
191         {
192         pthread_join(tid, NULL);
193         }
194     }
195 return 0;
196 }
197
198 void * RPC_CONFIG::Run(void * rc)
199 {
200 RPC_CONFIG * config = static_cast<RPC_CONFIG *>(rc);
201
202 config->stopped = false;
203 while (config->running)
204     {
205     config->rpcServer->runOnce();
206     }
207 config->stopped = true;
208
209 return NULL;
210 }
211
212 bool RPC_CONFIG::GetAdminInfo(const std::string & cookie,
213                               ADMIN_INFO * info)
214 {
215 std::map<std::string,
216          ADMIN_INFO>::iterator it;
217
218 it = cookies.find(cookie);
219
220 if (it == cookies.end())
221     {
222     return true;
223     }
224
225 if (difftime(it->second.accessTime, time(NULL)) >
226     rpcConfigSettings.GetCookieTimeout())
227     {
228     cookies.erase(it);
229     return true;
230     }
231
232 // Update access time
233 time(&it->second.accessTime);
234 *info = it->second;
235 return false;
236 }
237
238 bool RPC_CONFIG::CheckAdmin(const std::string & login,
239                             const std::string & password,
240                             std::string * cookie)
241 {
242 ADMIN * admin = NULL;
243
244 if (!admins->AdminCorrect(login, password, &admin))
245     {
246     return true;
247     }
248
249 ADMIN_INFO info;
250 time(&info.accessTime);
251 info.admin = login;
252 info.priviledges = *admin->GetPriv();
253 *cookie = GetCookie();
254 cookies[*cookie] = info;
255
256 return false;
257 }
258
259 bool RPC_CONFIG::LogoutAdmin(const std::string & cookie)
260 {
261 std::map<std::string,
262          ADMIN_INFO>::iterator it;
263
264 it = cookies.find(cookie);
265
266 if (it == cookies.end())
267     {
268     return true;
269     }
270
271 cookies.erase(it);
272
273 return false;
274 }
275
276 std::string RPC_CONFIG::GetCookie() const
277 {
278 std::string charset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
279 std::string cookie;
280
281 for (int i = 0; i < 64; ++i)
282     {
283     cookie += charset[rand() % charset.length()];
284     };
285
286 return cookie;
287 }
288
289 void RPC_CONFIG::InitiateRegistry()
290 {
291 // manage registry
292 xmlrpc_c::methodPtr const methodInfoPtr(new METHOD_INFO(
293             tariffs,
294             users,
295             dayFee,
296             dirNames
297             ));
298 rpcRegistry.addMethod("stargazer.info", methodInfoPtr);
299
300 xmlrpc_c::methodPtr const methodLoginPtr(new METHOD_LOGIN(
301             this
302             ));
303 rpcRegistry.addMethod("stargazer.login", methodLoginPtr);
304
305 xmlrpc_c::methodPtr const methodLogoutPtr(new METHOD_LOGOUT(
306             this
307             ));
308 rpcRegistry.addMethod("stargazer.logout", methodLogoutPtr);
309
310 xmlrpc_c::methodPtr const methodGetUserPtr(new METHOD_USER_GET(
311             this,
312             users
313             ));
314 rpcRegistry.addMethod("stargazer.get_user", methodGetUserPtr);
315
316 xmlrpc_c::methodPtr const methodAddUserPtr(new METHOD_USER_ADD(
317             this,
318             admins,
319             users
320             ));
321 rpcRegistry.addMethod("stargazer.add_user", methodAddUserPtr);
322
323 xmlrpc_c::methodPtr const methodDelUserPtr(new METHOD_USER_DEL(
324             this,
325             admins,
326             users
327             ));
328 rpcRegistry.addMethod("stargazer.del_user", methodDelUserPtr);
329
330 xmlrpc_c::methodPtr const methodGetUsersPtr(new METHOD_USERS_GET(
331             this,
332             users
333             ));
334 rpcRegistry.addMethod("stargazer.get_users", methodGetUsersPtr);
335
336 xmlrpc_c::methodPtr const methodChgUserPtr(new METHOD_USER_CHG(
337             this,
338             admins,
339             tariffs,
340             store,
341             users
342             ));
343 rpcRegistry.addMethod("stargazer.chg_user", methodChgUserPtr);
344
345 xmlrpc_c::methodPtr const methodAddCashPtr(new METHOD_USER_CASH_ADD(
346             this,
347             admins,
348             store,
349             users
350             ));
351 rpcRegistry.addMethod("stargazer.add_user_cash", methodAddCashPtr);
352
353 xmlrpc_c::methodPtr const methodSetCashPtr(new METHOD_USER_CASH_SET(
354             this,
355             admins,
356             store,
357             users
358             ));
359 rpcRegistry.addMethod("stargazer.set_user_cash", methodSetCashPtr);
360
361 xmlrpc_c::methodPtr const methodTariffChangePtr(new METHOD_USER_TARIFF_CHANGE(
362             this,
363             admins,
364             tariffs,
365             store,
366             users
367             ));
368 rpcRegistry.addMethod("stargazer.chg_user_tariff", methodTariffChangePtr);
369
370 xmlrpc_c::methodPtr const methodGetTariffPtr(new METHOD_TARIFF_GET(
371             this,
372             tariffs
373             ));
374 rpcRegistry.addMethod("stargazer.get_tariff", methodGetTariffPtr);
375
376 xmlrpc_c::methodPtr const methodChgTariffPtr(new METHOD_TARIFF_CHG(
377             this,
378             admins,
379             tariffs
380             ));
381 rpcRegistry.addMethod("stargazer.chg_tariff", methodChgTariffPtr);
382
383 xmlrpc_c::methodPtr const methodGetTariffsPtr(new METHOD_TARIFFS_GET(
384             this,
385             tariffs
386             ));
387 rpcRegistry.addMethod("stargazer.get_tariffs", methodGetTariffsPtr);
388
389 xmlrpc_c::methodPtr const methodAddTariffPtr(new METHOD_TARIFF_ADD(
390             this,
391             admins,
392             tariffs
393             ));
394 rpcRegistry.addMethod("stargazer.add_tariff", methodAddTariffPtr);
395
396 xmlrpc_c::methodPtr const methodDelTariffPtr(new METHOD_TARIFF_DEL(
397             this,
398             admins,
399             tariffs,
400             users
401             ));
402 rpcRegistry.addMethod("stargazer.del_tariff", methodDelTariffPtr);
403
404 xmlrpc_c::methodPtr const methodGetAdminPtr(new METHOD_ADMIN_GET(
405             this,
406             admins
407             ));
408 rpcRegistry.addMethod("stargazer.get_admin", methodGetAdminPtr);
409
410 xmlrpc_c::methodPtr const methodAddAdminPtr(new METHOD_ADMIN_ADD(
411             this,
412             admins
413             ));
414 rpcRegistry.addMethod("stargazer.add_admin", methodAddAdminPtr);
415
416 xmlrpc_c::methodPtr const methodDelAdminPtr(new METHOD_ADMIN_DEL(
417             this,
418             admins
419             ));
420 rpcRegistry.addMethod("stargazer.del_admin", methodDelAdminPtr);
421
422 xmlrpc_c::methodPtr const methodChgAdminPtr(new METHOD_ADMIN_CHG(
423             this,
424             admins
425             ));
426 rpcRegistry.addMethod("stargazer.chg_admin", methodChgAdminPtr);
427
428 xmlrpc_c::methodPtr const methodGetAdminsPtr(new METHOD_ADMINS_GET(
429             this,
430             admins
431             ));
432 rpcRegistry.addMethod("stargazer.get_admins", methodGetAdminsPtr);
433
434 xmlrpc_c::methodPtr const methodSendMessagePtr(new METHOD_MESSAGE_SEND(
435             this,
436             users
437             ));
438 rpcRegistry.addMethod("stargazer.send_user_message", methodSendMessagePtr);
439
440 xmlrpc_c::methodPtr const methodGetOnlinIPsPtr(new METHOD_GET_ONLINE_IPS(
441             this,
442             users
443             ));
444 rpcRegistry.addMethod("stargazer.get_online_ips", methodGetOnlinIPsPtr);
445 }
446