]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/rscript/rscript.cpp
Add a script to run cppcheck over all projects.
[stg.git] / projects / stargazer / plugins / other / rscript / rscript.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  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
20  */
21
22 #include "rscript.h"
23
24 #include "ur_functor.h"
25 #include "send_functor.h"
26
27 #include "stg/common.h"
28 #include "stg/locker.h"
29 #include "stg/users.h"
30 #include "stg/user_property.h"
31 #include "stg/plugin_creator.h"
32 #include "stg/logger.h"
33
34 #include <algorithm>
35
36 #include <csignal>
37 #include <cassert>
38 #include <cstdlib>
39 #include <cerrno>
40 #include <cstring>
41
42 #include <sys/time.h>
43 #include <netinet/ip.h>
44
45 extern volatile time_t stgTime;
46
47 using RS::REMOTE_SCRIPT;
48
49 namespace {
50
51 template<typename T>
52 struct USER_IS
53 {
54     explicit USER_IS(USER_PTR u) : user(u) {}
55     bool operator()(const T & notifier) { return notifier.GetUser() == user; }
56
57     USER_PTR user;
58 };
59
60 PLUGIN_CREATOR<REMOTE_SCRIPT> rsc;
61
62 } // namespace anonymous
63
64 extern "C" PLUGIN * GetPlugin();
65 //-----------------------------------------------------------------------------
66 //-----------------------------------------------------------------------------
67 //-----------------------------------------------------------------------------
68 //-----------------------------------------------------------------------------
69 //-----------------------------------------------------------------------------
70 //-----------------------------------------------------------------------------
71 PLUGIN * GetPlugin()
72 {
73 return rsc.GetPlugin();
74 }
75 //-----------------------------------------------------------------------------
76 //-----------------------------------------------------------------------------
77 //-----------------------------------------------------------------------------
78 RS::SETTINGS::SETTINGS()
79     : sendPeriod(0),
80       port(0)
81 {
82 }
83 //-----------------------------------------------------------------------------
84 int RS::SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
85 {
86 int p;
87 PARAM_VALUE pv;
88 std::vector<PARAM_VALUE>::const_iterator pvi;
89 netRouters.clear();
90 ///////////////////////////
91 pv.param = "Port";
92 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
93 if (pvi == s.moduleParams.end() || pvi->value.empty())
94     {
95     errorStr = "Parameter \'Port\' not found.";
96     printfd(__FILE__, "Parameter 'Port' not found\n");
97     return -1;
98     }
99 if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
100     {
101     errorStr = "Cannot parse parameter \'Port\': " + errorStr;
102     printfd(__FILE__, "Cannot parse parameter 'Port'\n");
103     return -1;
104     }
105 port = static_cast<uint16_t>(p);
106 ///////////////////////////
107 pv.param = "SendPeriod";
108 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
109 if (pvi == s.moduleParams.end() || pvi->value.empty())
110     {
111     errorStr = "Parameter \'SendPeriod\' not found.";
112     printfd(__FILE__, "Parameter 'SendPeriod' not found\n");
113     return -1;
114     }
115
116 if (ParseIntInRange(pvi->value[0], 5, 600, &sendPeriod))
117     {
118     errorStr = "Cannot parse parameter \'SendPeriod\': " + errorStr;
119     printfd(__FILE__, "Cannot parse parameter 'SendPeriod'\n");
120     return -1;
121     }
122 ///////////////////////////
123 pv.param = "UserParams";
124 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
125 if (pvi == s.moduleParams.end() || pvi->value.empty())
126     {
127     errorStr = "Parameter \'UserParams\' not found.";
128     printfd(__FILE__, "Parameter 'UserParams' not found\n");
129     return -1;
130     }
131 userParams = pvi->value;
132 ///////////////////////////
133 pv.param = "Password";
134 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
135 if (pvi == s.moduleParams.end() || pvi->value.empty())
136     {
137     errorStr = "Parameter \'Password\' not found.";
138     printfd(__FILE__, "Parameter 'Password' not found\n");
139     return -1;
140     }
141 password = pvi->value[0];
142 ///////////////////////////
143 pv.param = "SubnetFile";
144 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
145 if (pvi == s.moduleParams.end() || pvi->value.empty())
146     {
147     errorStr = "Parameter \'SubnetFile\' not found.";
148     printfd(__FILE__, "Parameter 'SubnetFile' not found\n");
149     return -1;
150     }
151 subnetFile = pvi->value[0];
152
153 NRMapParser nrMapParser;
154
155 if (!nrMapParser.ReadFile(subnetFile))
156     {
157     netRouters = nrMapParser.GetMap();
158     }
159 else
160     {
161     GetStgLogger()("mod_rscript: error opening subnets file '%s'", subnetFile.c_str());
162     }
163
164 return 0;
165 }
166 //-----------------------------------------------------------------------------
167 //-----------------------------------------------------------------------------
168 //-----------------------------------------------------------------------------
169 REMOTE_SCRIPT::REMOTE_SCRIPT()
170     : ctx(),
171       ipNotifierList(),
172       connNotifierList(),
173       authorizedUsers(),
174       errorStr(),
175       rsSettings(),
176       settings(),
177       sendPeriod(15),
178       halfPeriod(8),
179       nonstop(false),
180       isRunning(false),
181       users(NULL),
182       netRouters(),
183       thread(),
184       mutex(),
185       sock(0),
186       onAddUserNotifier(*this),
187       onDelUserNotifier(*this),
188       logger(GetPluginLogger(GetStgLogger(), "rscript"))
189 {
190 pthread_mutex_init(&mutex, NULL);
191 }
192 //-----------------------------------------------------------------------------
193 REMOTE_SCRIPT::~REMOTE_SCRIPT()
194 {
195 pthread_mutex_destroy(&mutex);
196 }
197 //-----------------------------------------------------------------------------
198 void * REMOTE_SCRIPT::Run(void * d)
199 {
200 sigset_t signalSet;
201 sigfillset(&signalSet);
202 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
203
204 REMOTE_SCRIPT * rs = static_cast<REMOTE_SCRIPT *>(d);
205
206 rs->isRunning = true;
207
208 while (rs->nonstop)
209     {
210     rs->PeriodicSend();
211     sleep(2);
212     }
213
214 rs->isRunning = false;
215 return NULL;
216 }
217 //-----------------------------------------------------------------------------
218 int REMOTE_SCRIPT::ParseSettings()
219 {
220 int ret = rsSettings.ParseSettings(settings);
221 if (ret)
222     errorStr = rsSettings.GetStrError();
223
224 sendPeriod = rsSettings.GetSendPeriod();
225 halfPeriod = sendPeriod / 2;
226
227 return ret;
228 }
229 //-----------------------------------------------------------------------------
230 int REMOTE_SCRIPT::Start()
231 {
232 netRouters = rsSettings.GetSubnetsMap();
233
234 InitEncrypt(&ctx, rsSettings.GetPassword());
235
236 users->AddNotifierUserAdd(&onAddUserNotifier);
237 users->AddNotifierUserDel(&onDelUserNotifier);
238
239 nonstop = true;
240
241 if (GetUsers())
242     {
243     return -1;
244     }
245
246 if (PrepareNet())
247     {
248     return -1;
249     }
250
251 if (!isRunning)
252     {
253     if (pthread_create(&thread, NULL, Run, this))
254         {
255         errorStr = "Cannot create thread.";
256         logger("Cannot create thread.");
257         printfd(__FILE__, "Cannot create thread\n");
258         return -1;
259         }
260     }
261
262 errorStr = "";
263 return 0;
264 }
265 //-----------------------------------------------------------------------------
266 int REMOTE_SCRIPT::Stop()
267 {
268 if (!IsRunning())
269     return 0;
270
271 nonstop = false;
272
273 std::for_each(
274         authorizedUsers.begin(),
275         authorizedUsers.end(),
276         DisconnectUser(*this)
277         );
278
279 FinalizeNet();
280
281 if (isRunning)
282     {
283     //5 seconds to thread stops itself
284     for (int i = 0; i < 25 && isRunning; i++)
285         {
286         struct timespec ts = {0, 200000000};
287         nanosleep(&ts, NULL);
288         }
289     }
290
291 users->DelNotifierUserDel(&onDelUserNotifier);
292 users->DelNotifierUserAdd(&onAddUserNotifier);
293
294 if (isRunning)
295     {
296     logger("Cannot stop thread.");
297     return -1;
298     }
299
300 return 0;
301 }
302 //-----------------------------------------------------------------------------
303 int REMOTE_SCRIPT::Reload(const MODULE_SETTINGS & /*ms*/)
304 {
305 NRMapParser nrMapParser;
306
307 if (nrMapParser.ReadFile(rsSettings.GetMapFileName()))
308     {
309     errorStr = nrMapParser.GetErrorStr();
310     logger("Map file reading error: %s", errorStr.c_str());
311     return -1;
312     }
313
314     {
315     STG_LOCKER lock(&mutex);
316
317     printfd(__FILE__, "REMOTE_SCRIPT::Reload()\n");
318
319     netRouters = nrMapParser.GetMap();
320     }
321
322 std::for_each(authorizedUsers.begin(),
323               authorizedUsers.end(),
324               UpdateRouter(*this));
325
326 logger("%s reloaded successfully.", rsSettings.GetMapFileName().c_str());
327 printfd(__FILE__, "REMOTE_SCRIPT::Reload() %s reloaded successfully.\n");
328
329 return 0;
330 }
331 //-----------------------------------------------------------------------------
332 bool REMOTE_SCRIPT::PrepareNet()
333 {
334 sock = socket(AF_INET, SOCK_DGRAM, 0);
335
336 if (sock < 0)
337     {
338     errorStr = "Cannot create socket.";
339     logger("Canot create a socket: %s", strerror(errno));
340     printfd(__FILE__, "Cannot create socket\n");
341     return true;
342     }
343
344 return false;
345 }
346 //-----------------------------------------------------------------------------
347 bool REMOTE_SCRIPT::FinalizeNet()
348 {
349 close(sock);
350 return false;
351 }
352 //-----------------------------------------------------------------------------
353 void REMOTE_SCRIPT::PeriodicSend()
354 {
355 STG_LOCKER lock(&mutex);
356
357 std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
358 while (it != authorizedUsers.end())
359     {
360     if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod)
361         {
362         Send(it->second);
363         }
364     ++it;
365     }
366 }
367 //-----------------------------------------------------------------------------
368 #ifdef NDEBUG
369 bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, RS::USER & rsu, bool forceDisconnect) const
370 #else
371 bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, RS::USER & rsu, bool forceDisconnect) const
372 #endif
373 {
374 RS::PACKET_HEADER packetHead;
375
376 memset(packetHead.padding, 0, sizeof(packetHead.padding));
377 strcpy((char*)packetHead.magic, RS_ID);
378 packetHead.protoVer[0] = '0';
379 packetHead.protoVer[1] = '2';
380 if (forceDisconnect)
381     {
382     packetHead.packetType = RS_DISCONNECT_PACKET;
383     printfd(__FILE__, "RSCRIPT: force disconnect for '%s'\n", rsu.user->GetLogin().c_str());
384     }
385 else
386     {
387     if (rsu.shortPacketsCount % MAX_SHORT_PCKT == 0)
388         {
389         //SendLong
390         packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET;
391         if (rsu.user->IsInetable())
392             printfd(__FILE__, "RSCRIPT: connect for '%s'\n", rsu.user->GetLogin().c_str());
393         else
394             printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
395         }
396     else
397         {
398         //SendShort
399         packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET;
400         if (rsu.user->IsInetable())
401             printfd(__FILE__, "RSCRIPT: alive for '%s'\n", rsu.user->GetLogin().c_str());
402         else
403             printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
404         }
405     }
406 rsu.shortPacketsCount++;
407 rsu.lastSentTime = stgTime;
408
409 packetHead.ip = htonl(rsu.ip);
410 packetHead.id = htonl(rsu.user->GetID());
411 strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
412 packetHead.login[RS_LOGIN_LEN - 1] = 0;
413
414 memcpy(buf, &packetHead, sizeof(packetHead));
415
416 if (packetHead.packetType == RS_ALIVE_PACKET)
417     {
418     return false;
419     }
420
421 RS::PACKET_TAIL packetTail;
422
423 memset(packetTail.padding, 0, sizeof(packetTail.padding));
424 strcpy((char*)packetTail.magic, RS_ID);
425 std::vector<std::string>::const_iterator it;
426 std::string params;
427 for(it = rsSettings.GetUserParams().begin();
428     it != rsSettings.GetUserParams().end();
429     ++it)
430     {
431     std::string parameter(rsu.user->GetParamValue(it->c_str()));
432     if (params.length() + parameter.length() > RS_PARAMS_LEN - 1)
433     {
434         logger("Script params string length %d exceeds the limit of %d symbols.", params.length() + parameter.length(), RS_PARAMS_LEN);
435         break;
436     }
437     params += parameter + " ";
438     }
439 strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
440 packetTail.params[RS_PARAMS_LEN - 1] = 0;
441
442 assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
443
444 Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
445
446 return false;
447 }
448 //-----------------------------------------------------------------------------
449 bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const
450 {
451 char buffer[RS_MAX_PACKET_LEN];
452
453 memset(buffer, 0, sizeof(buffer));
454
455 if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
456     {
457     printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
458     return true;
459     }
460
461 std::for_each(
462         rsu.routers.begin(),
463         rsu.routers.end(),
464         PacketSender(sock, buffer, sizeof(buffer), static_cast<uint16_t>(htons(rsSettings.GetPort())))
465         );
466
467 return false;
468 }
469 //-----------------------------------------------------------------------------
470 bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const
471 {
472 char buffer[RS_MAX_PACKET_LEN];
473
474 if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
475     {
476     printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
477     return true;
478     }
479
480 struct sockaddr_in sendAddr;
481
482 sendAddr.sin_family = AF_INET;
483 sendAddr.sin_port = static_cast<uint16_t>(htons(rsSettings.GetPort()));
484 sendAddr.sin_addr.s_addr = routerIP;
485
486 ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
487
488 if (res < 0)
489     logger("sendto error: %s", strerror(errno));
490
491 return (res != sizeof(buffer));
492 }
493 //-----------------------------------------------------------------------------
494 bool REMOTE_SCRIPT::GetUsers()
495 {
496 USER_PTR u;
497
498 int h = users->OpenSearch();
499 assert(h && "USERS::OpenSearch is always correct");
500
501 while (!users->SearchNext(h, &u))
502     {
503     SetUserNotifiers(u);
504     }
505
506 users->CloseSearch(h);
507 return false;
508 }
509 //-----------------------------------------------------------------------------
510 std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
511 {
512 STG_LOCKER lock(&mutex);
513 for (size_t i = 0; i < netRouters.size(); ++i)
514     {
515     if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
516         {
517         return netRouters[i].routers;
518         }
519     }
520 return std::vector<uint32_t>();
521 }
522 //-----------------------------------------------------------------------------
523 void REMOTE_SCRIPT::SetUserNotifiers(USER_PTR u)
524 {
525 ipNotifierList.push_front(RS::IP_NOTIFIER(*this, u));
526 connNotifierList.push_front(RS::CONNECTED_NOTIFIER(*this, u));
527 }
528 //-----------------------------------------------------------------------------
529 void REMOTE_SCRIPT::UnSetUserNotifiers(USER_PTR u)
530 {
531 ipNotifierList.erase(std::remove_if(ipNotifierList.begin(),
532                                     ipNotifierList.end(),
533                                     USER_IS<IP_NOTIFIER>(u)),
534                      ipNotifierList.end());
535 connNotifierList.erase(std::remove_if(connNotifierList.begin(),
536                                       connNotifierList.end(),
537                                       USER_IS<CONNECTED_NOTIFIER>(u)),
538                        connNotifierList.end());
539
540 }
541 //-----------------------------------------------------------------------------
542 void REMOTE_SCRIPT::AddRSU(USER_PTR user)
543 {
544 RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
545 Send(rsu);
546
547 STG_LOCKER lock(&mutex);
548 authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
549 }
550 //-----------------------------------------------------------------------------
551 void REMOTE_SCRIPT::DelRSU(USER_PTR user)
552 {
553 STG_LOCKER lock(&mutex);
554 std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
555 while (it != authorizedUsers.end())
556     {
557     if (it->second.user == user)
558         {
559         Send(it->second, true);
560         authorizedUsers.erase(it);
561         return;
562         }
563     ++it;
564     }
565 /*const std::map<uint32_t, RS::USER>::iterator it(
566         authorizedUsers.find(user->GetCurrIP())
567         );
568 if (it != authorizedUsers.end())
569     {
570     Send(it->second, true);
571     authorizedUsers.erase(it);
572     }*/
573 }
574 //-----------------------------------------------------------------------------
575 void RS::IP_NOTIFIER::Notify(const uint32_t & /*oldValue*/, const uint32_t & newValue)
576 {
577 if (newValue)
578     rs.AddRSU(user);
579 else
580     rs.DelRSU(user);
581 }
582 //-----------------------------------------------------------------------------
583 void RS::CONNECTED_NOTIFIER::Notify(const bool & /*oldValue*/, const bool & newValue)
584 {
585 if (newValue)
586     rs.AddRSU(user);
587 else
588     rs.DelRSU(user);
589 }
590 //-----------------------------------------------------------------------------
591 void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const
592 {
593 unsigned char keyL[PASSWD_LEN];  // Пароль для шифровки
594 memset(keyL, 0, PASSWD_LEN);
595 strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
596 Blowfish_Init(ctx, keyL, PASSWD_LEN);
597 }
598 //-----------------------------------------------------------------------------
599 void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const
600 {
601 if (dst != src)
602     memcpy(dst, src, len8 * 8);
603 for (size_t i = 0; i < len8; ++i)
604     Blowfish_Encrypt(ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
605 }
606 //-----------------------------------------------------------------------------