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