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