]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/rscript/rscript.cpp
Log all SIGHUP-related activity.
[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
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, __FILE__, __LINE__);
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(GetUserParam(rsu.user, *it));
432     if (params.length() + parameter.length() > RS_PARAMS_LEN - 1)
433         break;
434     params += parameter + " ";
435     }
436 strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
437 packetTail.params[RS_PARAMS_LEN - 1] = 0;
438
439 assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
440
441 Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
442
443 return false;
444 }
445 //-----------------------------------------------------------------------------
446 bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const
447 {
448 char buffer[RS_MAX_PACKET_LEN];
449
450 memset(buffer, 0, sizeof(buffer));
451
452 if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
453     {
454     printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
455     return true;
456     }
457
458 std::for_each(
459         rsu.routers.begin(),
460         rsu.routers.end(),
461         PacketSender(sock, buffer, sizeof(buffer), static_cast<uint16_t>(htons(rsSettings.GetPort())))
462         );
463
464 return false;
465 }
466 //-----------------------------------------------------------------------------
467 bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const
468 {
469 char buffer[RS_MAX_PACKET_LEN];
470
471 if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
472     {
473     printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
474     return true;
475     }
476
477 struct sockaddr_in sendAddr;
478
479 sendAddr.sin_family = AF_INET;
480 sendAddr.sin_port = static_cast<uint16_t>(htons(rsSettings.GetPort()));
481 sendAddr.sin_addr.s_addr = routerIP;
482
483 ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
484
485 if (res < 0)
486     logger("sendto error: %s", strerror(errno));
487
488 return (res != sizeof(buffer));
489 }
490 //-----------------------------------------------------------------------------
491 bool REMOTE_SCRIPT::GetUsers()
492 {
493 USER_PTR u;
494
495 int h = users->OpenSearch();
496 assert(h && "USERS::OpenSearch is always correct");
497
498 while (!users->SearchNext(h, &u))
499     {
500     SetUserNotifiers(u);
501     }
502
503 users->CloseSearch(h);
504 return false;
505 }
506 //-----------------------------------------------------------------------------
507 std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
508 {
509 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
510 for (size_t i = 0; i < netRouters.size(); ++i)
511     {
512     if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
513         {
514         return netRouters[i].routers;
515         }
516     }
517 return std::vector<uint32_t>();
518 }
519 //-----------------------------------------------------------------------------
520 std::string REMOTE_SCRIPT::GetUserParam(USER_PTR u, const std::string & paramName) const
521 {
522 std::string value = "";
523 if (strcasecmp(paramName.c_str(), "cash") == 0)
524     strprintf(&value, "%f", u->GetProperty().cash.Get());
525 else
526 if (strcasecmp(paramName.c_str(), "freeMb") == 0)
527     strprintf(&value, "%f", u->GetProperty().freeMb.Get());
528 else
529 if (strcasecmp(paramName.c_str(), "passive") == 0)
530     strprintf(&value, "%d", u->GetProperty().passive.Get());
531 else
532 if (strcasecmp(paramName.c_str(), "disabled") == 0)
533     strprintf(&value, "%d", u->GetProperty().disabled.Get());
534 else
535 if (strcasecmp(paramName.c_str(), "alwaysOnline") == 0)
536     strprintf(&value, "%d", u->GetProperty().alwaysOnline.Get());
537 else
538 if (strcasecmp(paramName.c_str(), "tariffName") == 0 ||
539     strcasecmp(paramName.c_str(), "tariff") == 0)
540     value = "\"" + u->GetProperty().tariffName.Get() + "\"";
541 else
542 if (strcasecmp(paramName.c_str(), "nextTariff") == 0)
543     value = "\"" + u->GetProperty().nextTariff.Get() + "\"";
544 else
545 if (strcasecmp(paramName.c_str(), "address") == 0)
546     value = "\"" + u->GetProperty().address.Get() + "\"";
547 else
548 if (strcasecmp(paramName.c_str(), "note") == 0)
549     value = "\"" + u->GetProperty().note.Get() + "\"";
550 else
551 if (strcasecmp(paramName.c_str(), "group") == 0)
552     value = "\"" + u->GetProperty().group.Get() + "\"";
553 else
554 if (strcasecmp(paramName.c_str(), "email") == 0)
555     value = "\"" + u->GetProperty().email.Get() + "\"";
556 else
557 if (strcasecmp(paramName.c_str(), "realName") == 0)
558     value = "\"" + u->GetProperty().realName.Get() + "\"";
559 else
560 if (strcasecmp(paramName.c_str(), "credit") == 0)
561     strprintf(&value, "%f", u->GetProperty().credit.Get());
562 else
563 if (strcasecmp(paramName.c_str(), "userdata0") == 0)
564     value = "\"" + u->GetProperty().userdata0.Get() + "\"";
565 else
566 if (strcasecmp(paramName.c_str(), "userdata1") == 0)
567     value = "\"" + u->GetProperty().userdata1.Get() + "\"";
568 else
569 if (strcasecmp(paramName.c_str(), "userdata2") == 0)
570     value = "\"" + u->GetProperty().userdata2.Get() + "\"";
571 else
572 if (strcasecmp(paramName.c_str(), "userdata3") == 0)
573     value = "\"" + u->GetProperty().userdata3.Get() + "\"";
574 else
575 if (strcasecmp(paramName.c_str(), "userdata4") == 0)
576     value = "\"" + u->GetProperty().userdata4.Get() + "\"";
577 else
578 if (strcasecmp(paramName.c_str(), "userdata5") == 0)
579     value = "\"" + u->GetProperty().userdata5.Get() + "\"";
580 else
581 if (strcasecmp(paramName.c_str(), "userdata6") == 0)
582     value = "\"" + u->GetProperty().userdata6.Get() + "\"";
583 else
584 if (strcasecmp(paramName.c_str(), "userdata7") == 0)
585     value = "\"" + u->GetProperty().userdata7.Get() + "\"";
586 else
587 if (strcasecmp(paramName.c_str(), "userdata8") == 0)
588     value = "\"" + u->GetProperty().userdata8.Get() + "\"";
589 else
590 if (strcasecmp(paramName.c_str(), "userdata9") == 0)
591     value = "\"" + u->GetProperty().userdata9.Get() + "\"";
592 else
593 if (strcasecmp(paramName.c_str(), "enabledDirs") == 0)
594     value = u->GetEnabledDirs();
595 else
596     printfd(__FILE__, "Unknown value name: %s\n", paramName.c_str());
597 return value;
598 }
599 //-----------------------------------------------------------------------------
600 void REMOTE_SCRIPT::SetUserNotifiers(USER_PTR u)
601 {
602 ipNotifierList.push_front(RS::IP_NOTIFIER(*this, u));
603 connNotifierList.push_front(RS::CONNECTED_NOTIFIER(*this, u));
604 }
605 //-----------------------------------------------------------------------------
606 void REMOTE_SCRIPT::UnSetUserNotifiers(USER_PTR u)
607 {
608 ipNotifierList.erase(std::remove_if(ipNotifierList.begin(),
609                                     ipNotifierList.end(),
610                                     USER_IS<IP_NOTIFIER>(u)),
611                      ipNotifierList.end());
612 connNotifierList.erase(std::remove_if(connNotifierList.begin(),
613                                       connNotifierList.end(),
614                                       USER_IS<CONNECTED_NOTIFIER>(u)),
615                        connNotifierList.end());
616
617 }
618 //-----------------------------------------------------------------------------
619 void REMOTE_SCRIPT::AddRSU(USER_PTR user)
620 {
621 RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
622 Send(rsu);
623
624 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
625 authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
626 }
627 //-----------------------------------------------------------------------------
628 void REMOTE_SCRIPT::DelRSU(USER_PTR user)
629 {
630 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
631 const std::map<uint32_t, RS::USER>::iterator it(
632         authorizedUsers.find(user->GetCurrIP())
633         );
634 if (it != authorizedUsers.end())
635     {
636     Send(it->second, true);
637     authorizedUsers.erase(it);
638     }
639 }
640 //-----------------------------------------------------------------------------
641 void RS::IP_NOTIFIER::Notify(const uint32_t & /*oldValue*/, const uint32_t & newValue)
642 {
643 if (newValue)
644     rs.AddRSU(user);
645 else
646     rs.DelRSU(user);
647 }
648 //-----------------------------------------------------------------------------
649 void RS::CONNECTED_NOTIFIER::Notify(const bool & /*oldValue*/, const bool & newValue)
650 {
651 if (newValue)
652     rs.AddRSU(user);
653 else
654     rs.DelRSU(user);
655 }
656 //-----------------------------------------------------------------------------
657 void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const
658 {
659 unsigned char keyL[PASSWD_LEN];  // Пароль для шифровки
660 memset(keyL, 0, PASSWD_LEN);
661 strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
662 Blowfish_Init(ctx, keyL, PASSWD_LEN);
663 }
664 //-----------------------------------------------------------------------------
665 void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const
666 {
667 if (dst != src)
668     memcpy(dst, src, len8 * 8);
669 for (size_t i = 0; i < len8; ++i)
670     Blowfish_Encrypt(ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
671 }
672 //-----------------------------------------------------------------------------