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