]> git.stg.codes - stg.git/blob - projects/stargazer/user_impl.cpp
f3228738b92913039488bb568f4f845699ac717b
[stg.git] / projects / stargazer / user_impl.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  *    Date: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23  */
24
25 /*
26  $Revision: 1.101 $
27  $Date: 2010/11/03 10:50:03 $
28  $Author: faust $
29  */
30
31 #ifndef _GNU_SOURCE
32 #define _GNU_SOURCE
33 #endif
34
35 #include <pthread.h>
36 #include <unistd.h> // access
37
38 #include <cassert>
39 #include <cstdlib>
40 #include <cmath>
41
42 #include "stg/users.h"
43 #include "stg/common.h"
44 #include "stg/scriptexecuter.h"
45 #include "stg/tariff.h"
46 #include "stg/tariffs.h"
47 #include "stg/admin.h"
48 #include "user_impl.h"
49 #include "settings_impl.h"
50 #include "stg_timer.h"
51
52 #ifdef USE_ABSTRACT_SETTINGS
53 USER_IMPL::USER_IMPL(const SETTINGS * s,
54            const STORE * st,
55            const TARIFFS * t,
56            const ADMIN * a,
57            const USERS * u)
58     : USER(),
59       users(u),
60       property(s->GetScriptsDir()),
61       WriteServLog(GetStgLogger()),
62       lastScanMessages(0),
63       login(),
64       id(0),
65       __connected(0),
66       connected(__connected),
67       enabledDirs(),
68       userIDGenerator(),
69       __currIP(0),
70       currIP(__currIP),
71       lastIPForDisconnect(0),
72       pingTime(0),
73       sysAdmin(a),
74       store(st),
75       tariffs(t),
76       tariff(NULL),
77       traffStat(),
78       traffStatSaved(),
79       settings(s),
80       authorizedBy(),
81       messages(),
82       deleted(false),
83       lastWriteStat(0),
84       lastWriteDetailedStat(0),
85       cash(property.cash),
86       up(property.up),
87       down(property.down),
88       lastCashAdd(property.lastCashAdd),
89       passiveTime(property.passiveTime),
90       lastCashAddTime(property.lastCashAddTime),
91       freeMb(property.freeMb),
92       lastActivityTime(property.lastActivityTime),
93       password(property.password),
94       passive(property.passive),
95       disabled(property.disabled),
96       disabledDetailStat(property.disabledDetailStat),
97       alwaysOnline(property.alwaysOnline),
98       tariffName(property.tariffName),
99       nextTariff(property.nextTariff),
100       address(property.address),
101       note(property.note),
102       group(property.group),
103       email(property.email),
104       phone(property.phone),
105       realName(property.realName),
106       credit(property.credit),
107       creditExpire(property.creditExpire),
108       ips(property.ips),
109       userdata0(property.userdata0),
110       userdata1(property.userdata1),
111       userdata2(property.userdata2),
112       userdata3(property.userdata3),
113       userdata4(property.userdata4),
114       userdata5(property.userdata5),
115       userdata6(property.userdata6),
116       userdata7(property.userdata7),
117       userdata8(property.userdata8),
118       userdata9(property.userdata9),
119       sessionUpload(),
120       sessionDownload(),
121       passiveNotifier(this),
122       tariffNotifier(this),
123       cashNotifier(this),
124       ipNotifier(this),
125       mutex(),
126       errorStr()
127 {
128 password = "*_EMPTY_PASSWORD_*";
129 tariffName = NO_TARIFF_NAME;
130 ips = StrToIPS("*");
131 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
132 lastWriteDetailedStat = stgTime;
133
134 property.tariffName.AddBeforeNotifier(&tariffNotifier);
135 property.passive.AddBeforeNotifier(&passiveNotifier);
136 property.disabled.AddAfterNotifier(&disabledNotifier);
137 property.cash.AddBeforeNotifier(&cashNotifier);
138 ips.AddAfterNotifier(&ipNotifier);
139
140 pthread_mutexattr_t attr;
141 pthread_mutexattr_init(&attr);
142 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
143 pthread_mutex_init(&mutex, &attr);
144 }
145 #else
146 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
147                      const STORE * st,
148                      const TARIFFS * t,
149                      const ADMIN * a,
150                      const USERS * u)
151     : USER(),
152       users(u),
153       property(s->GetScriptsDir()),
154       WriteServLog(GetStgLogger()),
155       lastScanMessages(0),
156       login(),
157       id(0),
158       __connected(0),
159       connected(__connected),
160       enabledDirs(),
161       userIDGenerator(),
162       __currIP(0),
163       currIP(__currIP),
164       lastIPForDisconnect(0),
165       pingTime(0),
166       sysAdmin(a),
167       store(st),
168       tariffs(t),
169       tariff(NULL),
170       traffStat(),
171       traffStatSaved(),
172       settings(s),
173       authorizedBy(),
174       messages(),
175       deleted(false),
176       lastWriteStat(0),
177       lastWriteDetailedStat(0),
178       cash(property.cash),
179       up(property.up),
180       down(property.down),
181       lastCashAdd(property.lastCashAdd),
182       passiveTime(property.passiveTime),
183       lastCashAddTime(property.lastCashAddTime),
184       freeMb(property.freeMb),
185       lastActivityTime(property.lastActivityTime),
186       password(property.password),
187       passive(property.passive),
188       disabled(property.disabled),
189       disabledDetailStat(property.disabledDetailStat),
190       alwaysOnline(property.alwaysOnline),
191       tariffName(property.tariffName),
192       nextTariff(property.nextTariff),
193       address(property.address),
194       note(property.note),
195       group(property.group),
196       email(property.email),
197       phone(property.phone),
198       realName(property.realName),
199       credit(property.credit),
200       creditExpire(property.creditExpire),
201       ips(property.ips),
202       userdata0(property.userdata0),
203       userdata1(property.userdata1),
204       userdata2(property.userdata2),
205       userdata3(property.userdata3),
206       userdata4(property.userdata4),
207       userdata5(property.userdata5),
208       userdata6(property.userdata6),
209       userdata7(property.userdata7),
210       userdata8(property.userdata8),
211       userdata9(property.userdata9),
212       sessionUpload(),
213       sessionDownload(),
214       passiveNotifier(this),
215       disabledNotifier(this),
216       tariffNotifier(this),
217       cashNotifier(this),
218       ipNotifier(this),
219       mutex(),
220       errorStr()
221 {
222 password = "*_EMPTY_PASSWORD_*";
223 tariffName = NO_TARIFF_NAME;
224 ips = StrToIPS("*");
225 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
226 lastWriteDetailedStat = stgTime;
227
228 property.tariffName.AddBeforeNotifier(&tariffNotifier);
229 property.passive.AddBeforeNotifier(&passiveNotifier);
230 property.disabled.AddAfterNotifier(&disabledNotifier);
231 property.cash.AddBeforeNotifier(&cashNotifier);
232 ips.AddAfterNotifier(&ipNotifier);
233
234 pthread_mutexattr_t attr;
235 pthread_mutexattr_init(&attr);
236 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
237 pthread_mutex_init(&mutex, &attr);
238 }
239 #endif
240 //-----------------------------------------------------------------------------
241 USER_IMPL::USER_IMPL(const USER_IMPL & u)
242     : USER(),
243       users(u.users),
244       property(u.settings->GetScriptsDir()),
245       WriteServLog(GetStgLogger()),
246       lastScanMessages(0),
247       login(u.login),
248       id(u.id),
249       __connected(0),
250       connected(__connected),
251       enabledDirs(),
252       userIDGenerator(u.userIDGenerator),
253       __currIP(u.__currIP),
254       currIP(__currIP),
255       lastIPForDisconnect(0),
256       pingTime(u.pingTime),
257       sysAdmin(u.sysAdmin),
258       store(u.store),
259       tariffs(u.tariffs),
260       tariff(u.tariff),
261       traffStat(u.traffStat),
262       traffStatSaved(u.traffStatSaved),
263       settings(u.settings),
264       authorizedBy(),
265       messages(u.messages),
266       deleted(u.deleted),
267       lastWriteStat(u.lastWriteStat),
268       lastWriteDetailedStat(u.lastWriteDetailedStat),
269       cash(property.cash),
270       up(property.up),
271       down(property.down),
272       lastCashAdd(property.lastCashAdd),
273       passiveTime(property.passiveTime),
274       lastCashAddTime(property.lastCashAddTime),
275       freeMb(property.freeMb),
276       lastActivityTime(property.lastActivityTime),
277       password(property.password),
278       passive(property.passive),
279       disabled(property.disabled),
280       disabledDetailStat(property.disabledDetailStat),
281       alwaysOnline(property.alwaysOnline),
282       tariffName(property.tariffName),
283       nextTariff(property.nextTariff),
284       address(property.address),
285       note(property.note),
286       group(property.group),
287       email(property.email),
288       phone(property.phone),
289       realName(property.realName),
290       credit(property.credit),
291       creditExpire(property.creditExpire),
292       ips(property.ips),
293       userdata0(property.userdata0),
294       userdata1(property.userdata1),
295       userdata2(property.userdata2),
296       userdata3(property.userdata3),
297       userdata4(property.userdata4),
298       userdata5(property.userdata5),
299       userdata6(property.userdata6),
300       userdata7(property.userdata7),
301       userdata8(property.userdata8),
302       userdata9(property.userdata9),
303       sessionUpload(),
304       sessionDownload(),
305       passiveNotifier(this),
306       disabledNotifier(this),
307       tariffNotifier(this),
308       cashNotifier(this),
309       ipNotifier(this),
310       mutex(),
311       errorStr()
312 {
313 if (&u == this)
314     return;
315
316 property.tariffName.AddBeforeNotifier(&tariffNotifier);
317 property.passive.AddBeforeNotifier(&passiveNotifier);
318 property.disabled.AddAfterNotifier(&disabledNotifier);
319 property.cash.AddBeforeNotifier(&cashNotifier);
320 ips.AddAfterNotifier(&ipNotifier);
321
322 property.SetProperties(u.property);
323
324 pthread_mutexattr_t attr;
325 pthread_mutexattr_init(&attr);
326 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
327 pthread_mutex_init(&mutex, &attr);
328 }
329 //-----------------------------------------------------------------------------
330 USER_IMPL::~USER_IMPL()
331 {
332 property.tariffName.DelBeforeNotifier(&tariffNotifier);
333 property.passive.DelBeforeNotifier(&passiveNotifier);
334 property.disabled.DelAfterNotifier(&disabledNotifier);
335 property.cash.DelBeforeNotifier(&cashNotifier);
336 pthread_mutex_destroy(&mutex);
337 }
338 //-----------------------------------------------------------------------------
339 void USER_IMPL::SetLogin(const std::string & l)
340 {
341 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
342 assert(login.empty() && "Login is already set");
343 login = l;
344 id = userIDGenerator.GetNextID();
345 }
346 //-----------------------------------------------------------------------------
347 int USER_IMPL::ReadConf()
348 {
349 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
350 USER_CONF conf;
351
352 if (store->RestoreUserConf(&conf, login))
353     {
354     WriteServLog("Cannot read conf for user %s.", login.c_str());
355     WriteServLog("%s", store->GetStrError().c_str());
356     printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
357     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
358     return -1;
359     }
360
361 property.SetConf(conf);
362
363 tariff = tariffs->FindByName(tariffName);
364 if (tariff == NULL)
365     {
366     WriteServLog("Cannot read user %s. Tariff %s not exist.",
367                  login.c_str(), property.tariffName.Get().c_str());
368     return -1;
369     }
370
371 std::vector<STG_MSG_HDR> hdrsList;
372
373 if (store->GetMessageHdrs(&hdrsList, login))
374     {
375     printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
376     WriteServLog("Cannot read user %s. Error reading message headers: %s.",
377                  login.c_str(),
378                  store->GetStrError().c_str());
379     return -1;
380     }
381
382 std::vector<STG_MSG_HDR>::const_iterator it;
383 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
384     {
385     STG_MSG msg;
386     if (store->GetMessage(it->id, &msg, login) == 0)
387         {
388         messages.push_back(msg);
389         }
390     }
391
392 return 0;
393 }
394 //-----------------------------------------------------------------------------
395 int USER_IMPL::ReadStat()
396 {
397 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
398 USER_STAT stat;
399
400 if (store->RestoreUserStat(&stat, login))
401     {
402     WriteServLog("Cannot read stat for user %s.", login.c_str());
403     WriteServLog("%s", store->GetStrError().c_str());
404     printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
405     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
406     return -1;
407     }
408
409 property.SetStat(stat);
410
411 return 0;
412 }
413 //-----------------------------------------------------------------------------
414 int USER_IMPL::WriteConf()
415 {
416 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
417 USER_CONF conf(property.GetConf());
418
419 printfd(__FILE__, "USER::WriteConf()\n");
420
421 if (store->SaveUserConf(conf, login))
422     {
423     WriteServLog("Cannot write conf for user %s.", login.c_str());
424     WriteServLog("%s", store->GetStrError().c_str());
425     printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
426     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
427     return -1;
428     }
429
430 return 0;
431 }
432 //-----------------------------------------------------------------------------
433 int USER_IMPL::WriteStat()
434 {
435 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
436 USER_STAT stat(property.GetStat());
437
438 if (store->SaveUserStat(stat, login))
439     {
440     WriteServLog("Cannot write stat for user %s.", login.c_str());
441     WriteServLog("%s", store->GetStrError().c_str());
442     printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
443     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
444     return -1;
445     }
446
447 lastWriteStat = stgTime;
448
449 return 0;
450 }
451 //-----------------------------------------------------------------------------
452 int USER_IMPL::WriteMonthStat()
453 {
454 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
455 time_t tt = stgTime - 3600;
456 struct tm t1;
457 localtime_r(&tt, &t1);
458
459 USER_STAT stat(property.GetStat());
460 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
461     {
462     WriteServLog("Cannot write month stat for user %s.", login.c_str());
463     WriteServLog("%s", store->GetStrError().c_str());
464     printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
465     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
466     return -1;
467     }
468
469 return 0;
470 }
471 //-----------------------------------------------------------------------------
472 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
473 {
474 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
475 /*
476  *  Authorize user. It only means that user will be authorized. Nothing more.
477  *  User can be connected or disconnected while authorized.
478  *  Example: user is authorized but disconnected due to 0 money or blocking
479  */
480
481 /*
482  * Prevent double authorization by identical authorizers
483  */
484 if (authorizedBy.find(auth) != authorizedBy.end())
485     return 0;
486
487 if (!ip)
488     return -1;
489
490 for (int i = 0; i < DIR_NUM; i++)
491     {
492     enabledDirs[i] = dirs & (1 << i);
493     }
494
495 if (!authorizedBy.empty())
496     {
497     if (currIP != ip)
498         {
499         //  We are already authorized, but with different IP address
500         errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
501         return -1;
502         }
503
504     USER * u = NULL;
505     if (!users->FindByIPIdx(ip, &u))
506         {
507         //  Address is already present in IP-index
508         //  If it's not our IP - throw an error
509         if (u != this)
510             {
511             errorStr = "IP address " + inet_ntostring(ip) + " already in use";
512             return -1;
513             }
514         }
515     }
516 else
517     {
518     if (users->IsIPInIndex(ip))
519         {
520         //  Address is already present in IP-index
521         errorStr = "IP address " + inet_ntostring(ip) + " already in use";
522         return -1;
523         }
524
525     if (ips.ConstData().IsIPInIPS(ip))
526         {
527         currIP = ip;
528         lastIPForDisconnect = currIP;
529         }
530     else
531         {
532         printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
533         errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
534         return -1;
535         }
536     }
537
538 authorizedBy.insert(auth);
539
540 ScanMessage();
541
542 return 0;
543 }
544 //-----------------------------------------------------------------------------
545 void USER_IMPL::Unauthorize(const AUTH * auth)
546 {
547 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
548 /*
549  *  Authorizer tries to unauthorize user, that was not authorized by it
550  */
551 if (!authorizedBy.erase(auth))
552     return;
553
554 if (authorizedBy.empty())
555     {
556     lastIPForDisconnect = currIP;
557     currIP = 0; // DelUser in traffcounter
558     return;
559     }
560 }
561 //-----------------------------------------------------------------------------
562 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
563 {
564 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
565 //  Is this user authorized by specified authorizer?
566 return authorizedBy.find(auth) != authorizedBy.end();
567 }
568 //-----------------------------------------------------------------------------
569 void USER_IMPL::Connect(bool fakeConnect)
570 {
571 /*
572  *  Connect user to Internet. This function is differ from Authorize() !!!
573  */
574
575 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
576
577 if (!fakeConnect)
578     {
579     std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
580
581     if (access(scriptOnConnect.c_str(), X_OK) == 0)
582         {
583         char dirsStr[DIR_NUM + 1];
584         dirsStr[DIR_NUM] = 0;
585         for (int i = 0; i < DIR_NUM; i++)
586             {
587             dirsStr[i] = enabledDirs[i] ? '1' : '0';
588             }
589
590         std::string scriptOnConnectParams;
591
592         strprintf(&scriptOnConnectParams,
593                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
594                 scriptOnConnect.c_str(),
595                 login.c_str(),
596                 inet_ntostring(currIP).c_str(),
597                 cash.ConstData(),
598                 id,
599                 dirsStr);
600
601         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
602         while (it != settings->GetScriptParams().end())
603             {
604             scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
605             ++it;
606             }
607
608         ScriptExec(scriptOnConnectParams.c_str());
609         }
610     else
611         {
612         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
613         }
614
615     connected = true;
616     }
617
618 if (store->WriteUserConnect(login, currIP))
619     {
620     WriteServLog("Cannot write connect for user %s.", login.c_str());
621     WriteServLog("%s", store->GetStrError().c_str());
622     }
623
624 if (!fakeConnect)
625     lastIPForDisconnect = currIP;
626 }
627 //-----------------------------------------------------------------------------
628 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
629 {
630 /*
631  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
632  */
633
634 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
635
636 if (!lastIPForDisconnect)
637     {
638     printfd(__FILE__, "lastIPForDisconnect\n");
639     return;
640     }
641
642 if (!fakeDisconnect)
643     {
644     std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
645
646     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
647         {
648         char dirsStr[DIR_NUM + 1];
649         dirsStr[DIR_NUM] = 0;
650         for (int i = 0; i < DIR_NUM; i++)
651             {
652             dirsStr[i] = enabledDirs[i] ? '1' : '0';
653             }
654
655         std::string scriptOnDisonnectParams;
656         strprintf(&scriptOnDisonnectParams,
657                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
658                 scriptOnDisonnect.c_str(),
659                 login.c_str(),
660                 inet_ntostring(lastIPForDisconnect).c_str(),
661                 cash.ConstData(),
662                 id,
663                 dirsStr);
664
665         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
666         while (it != settings->GetScriptParams().end())
667             {
668             scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
669             ++it;
670             }
671
672         ScriptExec(scriptOnDisonnectParams.c_str());
673         }
674     else
675         {
676         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
677         }
678
679     connected = false;
680     }
681
682 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
683     {
684     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
685     WriteServLog("%s", store->GetStrError().c_str());
686     }
687
688 if (!fakeDisconnect)
689     lastIPForDisconnect = 0;
690
691 DIR_TRAFF zeroSesssion;
692
693 sessionUpload = zeroSesssion;
694 sessionDownload = zeroSesssion;
695 }
696 //-----------------------------------------------------------------------------
697 void USER_IMPL::PrintUser() const
698 {
699 //return;
700 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
701 std::cout << "============================================================" << std::endl;
702 std::cout << "id=" << id << std::endl;
703 std::cout << "login=" << login << std::endl;
704 std::cout << "password=" << password << std::endl;
705 std::cout << "passive=" << passive << std::endl;
706 std::cout << "disabled=" << disabled << std::endl;
707 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
708 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
709 std::cout << "tariffName=" << tariffName << std::endl;
710 std::cout << "address=" << address << std::endl;
711 std::cout << "phone=" << phone << std::endl;
712 std::cout << "email=" << email << std::endl;
713 std::cout << "note=" << note << std::endl;
714 std::cout << "realName=" <<realName << std::endl;
715 std::cout << "group=" << group << std::endl;
716 std::cout << "credit=" << credit << std::endl;
717 std::cout << "nextTariff=" << nextTariff << std::endl;
718 std::cout << "userdata0" << userdata0 << std::endl;
719 std::cout << "userdata1" << userdata1 << std::endl;
720 std::cout << "creditExpire=" << creditExpire << std::endl;
721 std::cout << "ips=" << ips << std::endl;
722 std::cout << "------------------------" << std::endl;
723 std::cout << "up=" << up << std::endl;
724 std::cout << "down=" << down << std::endl;
725 std::cout << "cash=" << cash << std::endl;
726 std::cout << "freeMb=" << freeMb << std::endl;
727 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
728 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
729 std::cout << "passiveTime=" << passiveTime << std::endl;
730 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
731 std::cout << "============================================================" << std::endl;
732 }
733 //-----------------------------------------------------------------------------
734 void USER_IMPL::Run()
735 {
736 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
737
738 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
739     {
740     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
741     WriteStat();
742     }
743 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
744     {
745     WriteServLog("User: %s. Credit expired.", login.c_str());
746     credit = 0;
747     creditExpire = 0;
748     WriteConf();
749     }
750
751 if (passive.ConstData()
752     && (stgTime % 30 == 0)
753     && (passiveTime.ModificationTime() != stgTime))
754     {
755     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
756     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
757     }
758
759 if (!authorizedBy.empty())
760     {
761     if (connected)
762         {
763         property.Stat().lastActivityTime = stgTime;
764         }
765     if (!connected && IsInetable())
766         {
767         Connect();
768         }
769     if (connected && !IsInetable())
770         {
771         if (disabled)
772             Disconnect(false, "disabled");
773         else if (passive)
774             Disconnect(false, "passive");
775         else
776             Disconnect(false, "no cash");
777         }
778
779     if (stgTime - lastScanMessages > 10)
780         {
781         ScanMessage();
782         lastScanMessages = stgTime;
783         }
784     }
785 else
786     {
787     if (connected)
788         {
789         Disconnect(false, "not authorized");
790         }
791     }
792
793 }
794 //-----------------------------------------------------------------------------
795 void USER_IMPL::UpdatePingTime(time_t t)
796 {
797 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
798 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
799 if (t)
800     pingTime = t;
801 else
802     pingTime = stgTime;
803 }
804 //-----------------------------------------------------------------------------
805 bool USER_IMPL::IsInetable()
806 {
807 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
808
809 if (disabled || passive)
810     return false;
811
812 if (settings->GetFreeMbAllowInet())
813     {
814     if (freeMb >= 0)
815         return true;
816     }
817
818 if (settings->GetShowFeeInCash() || tariff == NULL)
819     {
820     return (cash >= -credit);
821     }
822
823 return (cash - tariff->GetFee() >= -credit);
824 }
825 //-----------------------------------------------------------------------------
826 std::string USER_IMPL::GetEnabledDirs() const
827 {
828 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
829
830 std::string dirs = "";
831 for(int i = 0; i < DIR_NUM; i++)
832     dirs += enabledDirs[i] ? "1" : "0";
833 return dirs;
834 }
835 //-----------------------------------------------------------------------------
836 #ifdef TRAFF_STAT_WITH_PORTS
837 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
838 #else
839 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
840 #endif
841 {
842 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
843
844 if (!connected || tariff == NULL)
845     return;
846
847 double cost = 0;
848 DIR_TRAFF dt(up);
849
850 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
851 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
852
853 dt[dir] += len;
854
855 int tt = tariff->GetTraffType();
856 if (tt == TRAFF_UP ||
857     tt == TRAFF_UP_DOWN ||
858     // Check NEW traff data
859     (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
860     {
861     double dc = 0;
862     if (traff < threshold &&
863         traff + len >= threshold)
864         {
865         // cash = partBeforeThreshold * priceBeforeThreshold +
866         //        partAfterThreshold * priceAfterThreshold
867         int64_t before = threshold - traff; // Chunk part before threshold
868         int64_t after = len - before; // Chunk part after threshold
869         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
870                                            down.ConstData()[dir],
871                                            dir,
872                                            stgTime) * before +
873              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
874                                            down.ConstData()[dir],
875                                            dir,
876                                            stgTime) * after;
877         }
878     else
879         {
880         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
881                                            down.ConstData()[dir],
882                                            dir,
883                                            stgTime) * len;
884         }
885
886     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
887         cost = dc;
888     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
889         cost = dc - freeMb.ConstData();
890
891     // Direct access to internal data structures via friend-specifier
892     property.Stat().freeMb -= dc;
893     property.Stat().cash -= cost;
894     cash.ModifyTime();
895     freeMb.ModifyTime();
896     }
897
898 up = dt;
899 sessionUpload[dir] += len;
900
901 //Add detailed stat
902
903 if (!settings->GetWriteFreeMbTraffCost() &&
904      freeMb.ConstData() >= 0)
905     cost = 0;
906
907 #ifdef TRAFF_STAT_WITH_PORTS
908 IP_DIR_PAIR idp(ip, dir, port);
909 #else
910 IP_DIR_PAIR idp(ip, dir);
911 #endif
912
913 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
914 lb = traffStat.lower_bound(idp);
915 if (lb == traffStat.end() || lb->first != idp)
916     {
917     traffStat.insert(lb,
918                      std::make_pair(idp,
919                                     STAT_NODE(len, 0, cost)));
920     }
921 else
922     {
923     lb->second.cash += cost;
924     lb->second.up += len;
925     }
926 }
927 //-----------------------------------------------------------------------------
928 #ifdef TRAFF_STAT_WITH_PORTS
929 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
930 #else
931 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
932 #endif
933 {
934 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
935
936 if (!connected || tariff == NULL)
937     return;
938
939 double cost = 0;
940 DIR_TRAFF dt(down);
941
942 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
943 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
944
945 dt[dir] += len;
946
947 int tt = tariff->GetTraffType();
948 if (tt == TRAFF_DOWN ||
949     tt == TRAFF_UP_DOWN ||
950     // Check NEW traff data
951     (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
952     {
953     double dc = 0;
954     if (traff < threshold &&
955         traff + len >= threshold)
956         {
957         // cash = partBeforeThreshold * priceBeforeThreshold +
958         //        partAfterThreshold * priceAfterThreshold
959         int64_t before = threshold - traff; // Chunk part before threshold
960         int64_t after = len - before; // Chunk part after threshold
961         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
962                                            down.ConstData()[dir], // Traff before chunk
963                                            dir,
964                                            stgTime) * before +
965              tariff->GetPriceWithTraffType(up.ConstData()[dir],
966                                            dt[dir], // Traff after chunk
967                                            dir,
968                                            stgTime) * after;
969         }
970     else
971         {
972         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
973                                            down.ConstData()[dir],
974                                            dir,
975                                            stgTime) * len;
976         }
977
978     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
979         cost = dc;
980     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
981         cost = dc - freeMb.ConstData();
982
983     property.Stat().freeMb -= dc;
984     property.Stat().cash -= cost;
985     cash.ModifyTime();
986     freeMb.ModifyTime();
987     }
988
989 down = dt;
990 sessionDownload[dir] += len;
991
992 //Add detailed stat
993
994 if (!settings->GetWriteFreeMbTraffCost() &&
995      freeMb.ConstData() >= 0)
996     cost = 0;
997
998 #ifdef TRAFF_STAT_WITH_PORTS
999 IP_DIR_PAIR idp(ip, dir, port);
1000 #else
1001 IP_DIR_PAIR idp(ip, dir);
1002 #endif
1003
1004 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
1005 lb = traffStat.lower_bound(idp);
1006 if (lb == traffStat.end() || lb->first != idp)
1007     {
1008     traffStat.insert(lb,
1009                      std::make_pair(idp,
1010                                     STAT_NODE(0, len, cost)));
1011     }
1012 else
1013     {
1014     lb->second.cash += cost;
1015     lb->second.down += len;
1016     }
1017 }
1018 //-----------------------------------------------------------------------------
1019 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1020 {
1021 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1022 currIP.AddBeforeNotifier(notifier);
1023 }
1024 //-----------------------------------------------------------------------------
1025 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1026 {
1027 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1028 currIP.DelBeforeNotifier(notifier);
1029 }
1030 //-----------------------------------------------------------------------------
1031 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1032 {
1033 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1034 currIP.AddAfterNotifier(notifier);
1035 }
1036 //-----------------------------------------------------------------------------
1037 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1038 {
1039 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1040 currIP.DelAfterNotifier(notifier);
1041 }
1042 //-----------------------------------------------------------------------------
1043 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1044 {
1045 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1046 connected.AddBeforeNotifier(notifier);
1047 }
1048 //-----------------------------------------------------------------------------
1049 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1050 {
1051 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1052 connected.DelBeforeNotifier(notifier);
1053 }
1054 //-----------------------------------------------------------------------------
1055 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1056 {
1057 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1058 connected.AddAfterNotifier(notifier);
1059 }
1060 //-----------------------------------------------------------------------------
1061 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1062 {
1063 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1064 connected.DelAfterNotifier(notifier);
1065 }
1066 //-----------------------------------------------------------------------------
1067 void USER_IMPL::OnAdd()
1068 {
1069 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1070
1071 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1072
1073 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1074     {
1075     std::string scriptOnAddParams;
1076     strprintf(&scriptOnAddParams,
1077             "%s \"%s\"",
1078             scriptOnAdd.c_str(),
1079             login.c_str());
1080
1081     ScriptExec(scriptOnAddParams.c_str());
1082     }
1083 else
1084     {
1085     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1086     }
1087 }
1088 //-----------------------------------------------------------------------------
1089 void USER_IMPL::OnDelete()
1090 {
1091 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1092
1093 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1094
1095 if (access(scriptOnDel.c_str(), X_OK) == 0)
1096     {
1097     std::string scriptOnDelParams;
1098     strprintf(&scriptOnDelParams,
1099             "%s \"%s\"",
1100             scriptOnDel.c_str(),
1101             login.c_str());
1102
1103     ScriptExec(scriptOnDelParams.c_str());
1104     }
1105 else
1106     {
1107     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1108     }
1109
1110 Run();
1111 }
1112 //-----------------------------------------------------------------------------
1113 int USER_IMPL::WriteDetailStat(bool hard)
1114 {
1115 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1116
1117 if (!traffStatSaved.second.empty())
1118     {
1119     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1120         {
1121         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1122         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1123         WriteServLog("%s", store->GetStrError().c_str());
1124         return -1;
1125         }
1126     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1127     }
1128
1129 TRAFF_STAT ts;
1130
1131     {
1132     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1133     ts.swap(traffStat);
1134     }
1135
1136 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1137
1138 if (ts.size() && !disabledDetailStat)
1139     {
1140     if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1141         {
1142         printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1143         WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1144         WriteServLog("%s", store->GetStrError().c_str());
1145         if (!hard)
1146             {
1147             printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1148             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1149             traffStatSaved.second.swap(ts);
1150             traffStatSaved.first = lastWriteDetailedStat;
1151             }
1152         return -1;
1153         }
1154     }
1155 lastWriteDetailedStat = stgTime;
1156 return 0;
1157 }
1158 //-----------------------------------------------------------------------------
1159 double USER_IMPL::GetPassiveTimePart() const
1160 {
1161 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1162
1163 static int daysInMonth[12] =
1164 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1165
1166 struct tm tms;
1167 time_t t = stgTime;
1168 localtime_r(&t, &tms);
1169
1170 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1171
1172 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1173     {
1174     // Leap year
1175     secMonth += 24 * 3600;
1176     }
1177
1178 time_t dt = secMonth - passiveTime;
1179
1180 if (dt < 0)
1181     dt = 0;
1182
1183 return static_cast<double>(dt) / secMonth;
1184 }
1185 //-----------------------------------------------------------------------------
1186 void USER_IMPL::SetPassiveTimeAsNewUser()
1187 {
1188 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1189
1190 time_t t = stgTime;
1191 struct tm tm;
1192 localtime_r(&t, &tm);
1193 int daysCurrMon = DaysInCurrentMonth();
1194 double pt = tm.tm_mday - 1;
1195 pt /= daysCurrMon;
1196
1197 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1198 }
1199 //-----------------------------------------------------------------------------
1200 void USER_IMPL::MidnightResetSessionStat()
1201 {
1202 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1203
1204 if (connected)
1205     {
1206     Disconnect(true, "fake");
1207     Connect(true);
1208     }
1209 }
1210 //-----------------------------------------------------------------------------
1211 void USER_IMPL::ProcessNewMonth()
1212 {
1213 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1214 //  Reset traff
1215 if (connected)
1216     {
1217     Disconnect(true, "fake");
1218     }
1219 DIR_TRAFF zeroTarff;
1220
1221 WriteMonthStat();
1222
1223 up = zeroTarff;
1224 down = zeroTarff;
1225
1226 if (connected)
1227     {
1228     Connect(true);
1229     }
1230
1231 //  Set new tariff
1232 if (nextTariff.ConstData() != "")
1233     {
1234     const TARIFF * nt;
1235     nt = tariffs->FindByName(nextTariff);
1236     if (nt == NULL)
1237         {
1238         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1239                      login.c_str(), property.tariffName.Get().c_str());
1240         }
1241     else
1242         {
1243         property.tariffName.Set(nextTariff, sysAdmin, login, store);
1244         //tariff = nt;
1245         }
1246     ResetNextTariff();
1247     WriteConf();
1248     }
1249 }
1250 //-----------------------------------------------------------------------------
1251 void USER_IMPL::ProcessDayFeeSpread()
1252 {
1253 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1254
1255 if (passive.ConstData() || tariff == NULL)
1256     return;
1257
1258 double fee = tariff->GetFee() / DaysInCurrentMonth();
1259
1260 if (std::fabs(fee) < 1.0e-3)
1261     return;
1262
1263 double c = cash;
1264 switch (settings->GetFeeChargeType())
1265     {
1266     case 0:
1267         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1268         break;
1269     case 1:
1270         if (c + credit >= 0)
1271             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1272         break;
1273     case 2:
1274         if (c + credit >= fee)
1275             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1276         break;
1277     case 3:
1278         if (c >= 0)
1279             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1280         break;
1281     }
1282 ResetPassiveTime();
1283 }
1284 //-----------------------------------------------------------------------------
1285 void USER_IMPL::ProcessDayFee()
1286 {
1287 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1288
1289 if (tariff == NULL)
1290     return;
1291
1292 double passiveTimePart = 1.0;
1293 if (!settings->GetFullFee())
1294     {
1295     passiveTimePart = GetPassiveTimePart();
1296     }
1297 else
1298     {
1299     if (passive.ConstData())
1300         {
1301         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1302         return;
1303         }
1304     }
1305 double fee = tariff->GetFee() * passiveTimePart;
1306
1307 ResetPassiveTime();
1308
1309 if (std::fabs(fee) < 1.0e-3)
1310     {
1311     SetPrepaidTraff();
1312     return;
1313     }
1314
1315 double c = cash;
1316 printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
1317         login.c_str(),
1318         cash.ConstData(),
1319         credit.ConstData(),
1320         tariff->GetFee(),
1321         passiveTimePart,
1322         fee);
1323 switch (settings->GetFeeChargeType())
1324     {
1325     case 0:
1326         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1327         SetPrepaidTraff();
1328         break;
1329     case 1:
1330         if (c + credit >= 0)
1331             {
1332             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1333             SetPrepaidTraff();
1334             }
1335         break;
1336     case 2:
1337         if (c + credit >= fee)
1338             {
1339             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1340             SetPrepaidTraff();
1341             }
1342         break;
1343     case 3:
1344         if (c >= 0)
1345             {
1346             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1347             SetPrepaidTraff();
1348             }
1349         break;
1350     }
1351 }
1352 //-----------------------------------------------------------------------------
1353 void USER_IMPL::SetPrepaidTraff()
1354 {
1355 if (tariff != NULL)
1356     property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1357 }
1358 //-----------------------------------------------------------------------------
1359 int USER_IMPL::AddMessage(STG_MSG * msg)
1360 {
1361 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1362
1363 if (SendMessage(*msg))
1364     {
1365     if (store->AddMessage(msg, login))
1366         {
1367         errorStr = store->GetStrError();
1368         WriteServLog("Error adding message: '%s'", errorStr.c_str());
1369         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1370         return -1;
1371         }
1372     messages.push_back(*msg);
1373     }
1374 else
1375     {
1376     if (msg->header.repeat > 0)
1377         {
1378         msg->header.repeat--;
1379         #ifndef DEBUG
1380         //TODO: gcc v. 4.x generate ICE on x86_64
1381         msg->header.lastSendTime = static_cast<int>(time(NULL));
1382         #else
1383         msg->header.lastSendTime = static_cast<int>(stgTime);
1384         #endif
1385         if (store->AddMessage(msg, login))
1386             {
1387             errorStr = store->GetStrError();
1388             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1389             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1390             return -1;
1391             }
1392         messages.push_back(*msg);
1393         }
1394     }
1395 return 0;
1396 }
1397 //-----------------------------------------------------------------------------
1398 int USER_IMPL::SendMessage(STG_MSG & msg) const
1399 {
1400 // No lock `cause we are already locked from caller
1401 int ret = -1;
1402 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1403 while (it != authorizedBy.end())
1404     {
1405     if (!(*it++)->SendMessage(msg, currIP))
1406         ret = 0;
1407     }
1408 if (!ret)
1409     {
1410 #ifndef DEBUG
1411     //TODO: gcc v. 4.x generate ICE on x86_64
1412     msg.header.lastSendTime = static_cast<int>(time(NULL));
1413 #else
1414     msg.header.lastSendTime = static_cast<int>(stgTime);
1415 #endif
1416     msg.header.repeat--;
1417     }
1418 return ret;
1419 }
1420 //-----------------------------------------------------------------------------
1421 void USER_IMPL::ScanMessage()
1422 {
1423 // No lock `cause we are already locked from caller
1424 // We need not check for the authorizedBy `cause it has already checked by caller
1425
1426 std::list<STG_MSG>::iterator it(messages.begin());
1427 while (it != messages.end())
1428     {
1429     if (settings->GetMessageTimeout() > 0 &&
1430         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1431         {
1432         // Timeout exceeded
1433         if (store->DelMessage(it->header.id, login))
1434             {
1435             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1436             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1437             }
1438         messages.erase(it++);
1439         continue;
1440         }
1441     if (it->GetNextSendTime() <= stgTime)
1442         {
1443         if (SendMessage(*it))
1444             {
1445             // We need to check all messages in queue for timeout
1446             ++it;
1447             continue;
1448             }
1449         if (it->header.repeat < 0)
1450             {
1451             if (store->DelMessage(it->header.id, login))
1452                 {
1453                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1454                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1455                 }
1456             messages.erase(it++);
1457             }
1458         else
1459             {
1460             if (store->EditMessage(*it, login))
1461                 {
1462                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1463                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1464                 }
1465             ++it;
1466             }
1467         }
1468     else
1469         {
1470         ++it;
1471         }
1472     }
1473 }
1474 //-----------------------------------------------------------------------------
1475 std::string USER_IMPL::GetParamValue(const std::string & name) const
1476 {
1477 if (name == "id")
1478     {
1479     std::ostringstream stream;
1480     stream << id;
1481     return stream.str();
1482     }
1483 if (name == "login")        return login;
1484 if (name == "ip")           return currIP.ToString();
1485 if (name == "enabledDirs")  return GetEnabledDirs();
1486 return property.GetPropertyValue(name);
1487 }
1488 //-----------------------------------------------------------------------------
1489 //-----------------------------------------------------------------------------
1490 //-----------------------------------------------------------------------------
1491 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1492 {
1493 if (newPassive && !oldPassive && user->tariff != NULL)
1494     user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1495                             user->sysAdmin,
1496                             user->login,
1497                             user->store,
1498                             "Freeze");
1499 }
1500 //-----------------------------------------------------------------------------
1501 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1502 {
1503 if (oldValue && !newValue && user->GetConnected())
1504     {
1505     user->Disconnect(false, "disabled");
1506     }
1507 else if (!oldValue && newValue && user->IsInetable())
1508     {
1509     user->Connect(false);
1510     }
1511
1512 }
1513 //-----------------------------------------------------------------------------
1514 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1515 {
1516 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1517     user->Disconnect(false, "Change tariff");
1518 user->tariff = user->tariffs->FindByName(newTariff);
1519 if (user->settings->GetReconnectOnTariffChange() &&
1520     !user->authorizedBy.empty() &&
1521     user->IsInetable())
1522     user->Connect(false);
1523 }
1524 //-----------------------------------------------------------------------------
1525 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1526 {
1527 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1528 user->lastCashAdd = newCash - oldCash;
1529 }
1530 //-----------------------------------------------------------------------------
1531 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1532 {
1533     printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1534     if (user->connected)
1535         user->Disconnect(false, "Change IP");
1536     if (!user->authorizedBy.empty() && user->IsInetable())
1537         user->Connect(false);
1538 }
1539 //-----------------------------------------------------------------------------