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