]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/rscript/rscript.cpp
Fixed problems with connect/disconnect notification.
[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 const time_t stgTime;
42
43 #define RS_MAX_ROUTERS  (100)
44
45 using RS::REMOTE_SCRIPT;
46
47 namespace {
48
49 template<typename T>
50 struct USER_IS
51 {
52     USER_IS(USER_PTR u) : user(u) {}
53     bool operator()(const T & notifier) { return notifier.GetUser() == user; }
54
55     USER_PTR user;
56 };
57
58 } // namespace anonymous
59
60 //-----------------------------------------------------------------------------
61 //-----------------------------------------------------------------------------
62 //-----------------------------------------------------------------------------
63 PLUGIN_CREATOR<REMOTE_SCRIPT> rsc;
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 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 = 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 return 0;
328 }
329 //-----------------------------------------------------------------------------
330 bool REMOTE_SCRIPT::PrepareNet()
331 {
332 sock = socket(AF_INET, SOCK_DGRAM, 0);
333
334 if (sock < 0)
335     {
336     errorStr = "Cannot create socket.";
337     logger("Canot create a socket: %s", strerror(errno));
338     printfd(__FILE__, "Cannot create socket\n");
339     return true;
340     }
341
342 return false;
343 }
344 //-----------------------------------------------------------------------------
345 bool REMOTE_SCRIPT::FinalizeNet()
346 {
347 close(sock);
348 return false;
349 }
350 //-----------------------------------------------------------------------------
351 void REMOTE_SCRIPT::PeriodicSend()
352 {
353 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
354
355 map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
356 while (it != authorizedUsers.end())
357     {
358     if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod)
359         {
360         Send(it->second);
361         }
362     ++it;
363     }
364 }
365 //-----------------------------------------------------------------------------
366 #ifdef NDEBUG
367 bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, RS::USER & rsu, bool forceDisconnect) const
368 #else
369 bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, RS::USER & rsu, bool forceDisconnect) const
370 #endif
371 {
372 RS::PACKET_HEADER packetHead;
373
374 memset(packetHead.padding, 0, sizeof(packetHead.padding));
375 strcpy((char*)packetHead.magic, RS_ID);
376 packetHead.protoVer[0] = '0';
377 packetHead.protoVer[1] = '2';
378 if (forceDisconnect)
379     {
380     packetHead.packetType = RS_DISCONNECT_PACKET;
381     printfd(__FILE__, "RSCRIPT: force disconnect for '%s'\n", rsu.user->GetLogin().c_str());
382     }
383 else
384     {
385     if (rsu.shortPacketsCount % MAX_SHORT_PCKT == 0)
386         {
387         //SendLong
388         packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET;
389         if (rsu.user->IsInetable())
390             printfd(__FILE__, "RSCRIPT: connect for '%s'\n", rsu.user->GetLogin().c_str());
391         else
392             printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
393         }
394     else
395         {
396         //SendShort
397         packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET;
398         if (rsu.user->IsInetable())
399             printfd(__FILE__, "RSCRIPT: alive for '%s'\n", rsu.user->GetLogin().c_str());
400         else
401             printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
402         }
403     }
404 rsu.shortPacketsCount++;
405 rsu.lastSentTime = stgTime;
406
407 packetHead.ip = htonl(rsu.ip);
408 packetHead.id = htonl(rsu.user->GetID());
409 strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
410 packetHead.login[RS_LOGIN_LEN - 1] = 0;
411
412 memcpy(buf, &packetHead, sizeof(packetHead));
413
414 if (packetHead.packetType == RS_ALIVE_PACKET)
415     {
416     return false;
417     }
418
419 RS::PACKET_TAIL packetTail;
420
421 memset(packetTail.padding, 0, sizeof(packetTail.padding));
422 strcpy((char*)packetTail.magic, RS_ID);
423 vector<string>::const_iterator it;
424 std::string params;
425 for(it = rsSettings.GetUserParams().begin();
426     it != rsSettings.GetUserParams().end();
427     ++it)
428     {
429     std::string parameter(GetUserParam(rsu.user, *it));
430     if (params.length() + parameter.length() > RS_PARAMS_LEN - 1)
431         break;
432     params += parameter + " ";
433     }
434 strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
435 packetTail.params[RS_PARAMS_LEN - 1] = 0;
436
437 assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
438
439 Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
440
441 return false;
442 }
443 //-----------------------------------------------------------------------------
444 bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const
445 {
446 char buffer[RS_MAX_PACKET_LEN];
447
448 memset(buffer, 0, sizeof(buffer));
449
450 if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
451     {
452     printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
453     return true;
454     }
455
456 std::for_each(
457         rsu.routers.begin(),
458         rsu.routers.end(),
459         PacketSender(sock, buffer, sizeof(buffer), htons(rsSettings.GetPort()))
460         );
461
462 return false;
463 }
464 //-----------------------------------------------------------------------------
465 bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const
466 {
467 char buffer[RS_MAX_PACKET_LEN];
468
469 if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
470     {
471     printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
472     return true;
473     }
474
475 struct sockaddr_in sendAddr;
476
477 sendAddr.sin_family = AF_INET;
478 sendAddr.sin_port = htons(rsSettings.GetPort());
479 sendAddr.sin_addr.s_addr = routerIP;
480
481 int res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
482
483 if (res < 0)
484     logger("sendto error: %s", strerror(errno));
485
486 return (res != sizeof(buffer));
487 }
488 //-----------------------------------------------------------------------------
489 bool REMOTE_SCRIPT::GetUsers()
490 {
491 USER_PTR u;
492
493 int h = users->OpenSearch();
494 assert(h && "USERS::OpenSearch is always correct");
495
496 while (!users->SearchNext(h, &u))
497     {
498     SetUserNotifiers(u);
499     }
500
501 users->CloseSearch(h);
502 return false;
503 }
504 //-----------------------------------------------------------------------------
505 void REMOTE_SCRIPT::ChangedIP(USER_PTR u, uint32_t oldIP, uint32_t newIP)
506 {
507 /*
508  * When ip changes process looks like:
509  * old => 0, 0 => new
510  *
511  */
512 if (newIP)
513     {
514     RS::USER rsu(IP2Routers(newIP), u);
515     Send(rsu);
516
517     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
518     authorizedUsers.insert(std::make_pair(newIP, rsu));
519     }
520 else
521     {
522     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
523     const map<uint32_t, RS::USER>::iterator it(
524             authorizedUsers.find(oldIP)
525             );
526     if (it != authorizedUsers.end())
527         {
528         Send(it->second, true);
529         authorizedUsers.erase(it);
530         }
531     }
532 }
533 //-----------------------------------------------------------------------------
534 std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
535 {
536 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
537 for (size_t i = 0; i < netRouters.size(); ++i)
538     {
539     if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
540         {
541         return netRouters[i].routers;
542         }
543     }
544 return std::vector<uint32_t>();
545 }
546 //-----------------------------------------------------------------------------
547 string REMOTE_SCRIPT::GetUserParam(USER_PTR u, const string & paramName) const
548 {
549 string value = "";
550 if (strcasecmp(paramName.c_str(), "cash") == 0)
551     strprintf(&value, "%f", u->GetProperty().cash.Get());
552 else
553 if (strcasecmp(paramName.c_str(), "freeMb") == 0)
554     strprintf(&value, "%f", u->GetProperty().freeMb.Get());
555 else
556 if (strcasecmp(paramName.c_str(), "passive") == 0)
557     strprintf(&value, "%d", u->GetProperty().passive.Get());
558 else
559 if (strcasecmp(paramName.c_str(), "disabled") == 0)
560     strprintf(&value, "%d", u->GetProperty().disabled.Get());
561 else
562 if (strcasecmp(paramName.c_str(), "alwaysOnline") == 0)
563     strprintf(&value, "%d", u->GetProperty().alwaysOnline.Get());
564 else
565 if (strcasecmp(paramName.c_str(), "tariffName") == 0 ||
566     strcasecmp(paramName.c_str(), "tariff") == 0)
567     value = "\"" + u->GetProperty().tariffName.Get() + "\"";
568 else
569 if (strcasecmp(paramName.c_str(), "nextTariff") == 0)
570     value = "\"" + u->GetProperty().nextTariff.Get() + "\"";
571 else
572 if (strcasecmp(paramName.c_str(), "address") == 0)
573     value = "\"" + u->GetProperty().address.Get() + "\"";
574 else
575 if (strcasecmp(paramName.c_str(), "note") == 0)
576     value = "\"" + u->GetProperty().note.Get() + "\"";
577 else
578 if (strcasecmp(paramName.c_str(), "group") == 0)
579     value = "\"" + u->GetProperty().group.Get() + "\"";
580 else
581 if (strcasecmp(paramName.c_str(), "email") == 0)
582     value = "\"" + u->GetProperty().email.Get() + "\"";
583 else
584 if (strcasecmp(paramName.c_str(), "realName") == 0)
585     value = "\"" + u->GetProperty().realName.Get() + "\"";
586 else
587 if (strcasecmp(paramName.c_str(), "credit") == 0)
588     strprintf(&value, "%f", u->GetProperty().credit.Get());
589 else
590 if (strcasecmp(paramName.c_str(), "userdata0") == 0)
591     value = "\"" + u->GetProperty().userdata0.Get() + "\"";
592 else
593 if (strcasecmp(paramName.c_str(), "userdata1") == 0)
594     value = "\"" + u->GetProperty().userdata1.Get() + "\"";
595 else
596 if (strcasecmp(paramName.c_str(), "userdata2") == 0)
597     value = "\"" + u->GetProperty().userdata2.Get() + "\"";
598 else
599 if (strcasecmp(paramName.c_str(), "userdata3") == 0)
600     value = "\"" + u->GetProperty().userdata3.Get() + "\"";
601 else
602 if (strcasecmp(paramName.c_str(), "userdata4") == 0)
603     value = "\"" + u->GetProperty().userdata4.Get() + "\"";
604 else
605 if (strcasecmp(paramName.c_str(), "userdata5") == 0)
606     value = "\"" + u->GetProperty().userdata5.Get() + "\"";
607 else
608 if (strcasecmp(paramName.c_str(), "userdata6") == 0)
609     value = "\"" + u->GetProperty().userdata6.Get() + "\"";
610 else
611 if (strcasecmp(paramName.c_str(), "userdata7") == 0)
612     value = "\"" + u->GetProperty().userdata7.Get() + "\"";
613 else
614 if (strcasecmp(paramName.c_str(), "userdata8") == 0)
615     value = "\"" + u->GetProperty().userdata8.Get() + "\"";
616 else
617 if (strcasecmp(paramName.c_str(), "userdata9") == 0)
618     value = "\"" + u->GetProperty().userdata9.Get() + "\"";
619 else
620 if (strcasecmp(paramName.c_str(), "enabledDirs") == 0)
621     value = u->GetEnabledDirs();
622 else
623     printfd(__FILE__, "Unknown value name: %s\n", paramName.c_str());
624 return value;
625 }
626 //-----------------------------------------------------------------------------
627 void REMOTE_SCRIPT::SetUserNotifiers(USER_PTR u)
628 {
629 ipNotifierList.push_front(RS::IP_NOTIFIER(*this, u));
630 connNotifierList.push_front(RS::CONNECTED_NOTIFIER(*this, u));
631 }
632 //-----------------------------------------------------------------------------
633 void REMOTE_SCRIPT::UnSetUserNotifiers(USER_PTR u)
634 {
635 ipNotifierList.erase(std::remove_if(ipNotifierList.begin(),
636                                     ipNotifierList.end(),
637                                     USER_IS<IP_NOTIFIER>(u)),
638                      ipNotifierList.end());
639 connNotifierList.erase(std::remove_if(connNotifierList.begin(),
640                                       connNotifierList.end(),
641                                       USER_IS<CONNECTED_NOTIFIER>(u)),
642                        connNotifierList.end());
643
644 }
645 //-----------------------------------------------------------------------------
646 void REMOTE_SCRIPT::AddRSU(USER_PTR user)
647 {
648 RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
649 Send(rsu);
650
651 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
652 authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
653 }
654 //-----------------------------------------------------------------------------
655 void REMOTE_SCRIPT::DelRSU(USER_PTR user)
656 {
657 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
658 const map<uint32_t, RS::USER>::iterator it(
659         authorizedUsers.find(user->GetCurrIP())
660         );
661 if (it != authorizedUsers.end())
662     {
663     Send(it->second, true);
664     authorizedUsers.erase(it);
665     }
666 }
667 //-----------------------------------------------------------------------------
668 void RS::IP_NOTIFIER::Notify(const uint32_t & /*oldValue*/, const uint32_t & newValue)
669 {
670 //rs.ChangedIP(user, oldValue, newValue);
671 if (newValue)
672     rs.AddRSU(user);
673 else
674     rs.DelRSU(user);
675 }
676 //-----------------------------------------------------------------------------
677 void RS::CONNECTED_NOTIFIER::Notify(const bool & /*oldValue*/, const bool & newValue)
678 {
679 if (newValue)
680     rs.AddRSU(user);
681 else
682     rs.DelRSU(user);
683 }
684 //-----------------------------------------------------------------------------
685 void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const string & password) const
686 {
687 unsigned char keyL[PASSWD_LEN];  // Пароль для шифровки
688 memset(keyL, 0, PASSWD_LEN);
689 strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
690 Blowfish_Init(ctx, keyL, PASSWD_LEN);
691 }
692 //-----------------------------------------------------------------------------
693 void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, size_t len8) const
694 {
695 if (dst != src)
696     memcpy(dst, src, len8 * 8);
697 for (size_t i = 0; i < len8; ++i)
698     Blowfish_Encrypt(ctx, (uint32_t *)(dst + i * 8), (uint32_t *)(dst + i * 8 + 4));
699 }
700 //-----------------------------------------------------------------------------