]> git.stg.codes - stg.git/blob - projects/stargazer/user_impl.cpp
Reduction in code in method GetParamValue, correcting methods USER_IMPL::Disconnect...
[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             }
606
607         ScriptExec(scriptOnConnectParams.c_str());
608         }
609     else
610         {
611         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
612         }
613
614     connected = true;
615     }
616
617 if (store->WriteUserConnect(login, currIP))
618     {
619     WriteServLog("Cannot write connect for user %s.", login.c_str());
620     WriteServLog("%s", store->GetStrError().c_str());
621     }
622
623 if (!fakeConnect)
624     lastIPForDisconnect = currIP;
625 }
626 //-----------------------------------------------------------------------------
627 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
628 {
629 /*
630  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
631  */
632
633 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
634
635 if (!lastIPForDisconnect)
636     {
637     printfd(__FILE__, "lastIPForDisconnect\n");
638     return;
639     }
640
641 if (!fakeDisconnect)
642     {
643     std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
644
645     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
646         {
647         char dirsStr[DIR_NUM + 1];
648         dirsStr[DIR_NUM] = 0;
649         for (int i = 0; i < DIR_NUM; i++)
650             {
651             dirsStr[i] = enabledDirs[i] ? '1' : '0';
652             }
653
654         std::string scriptOnDisonnectParams;
655         strprintf(&scriptOnDisonnectParams,
656                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
657                 scriptOnDisonnect.c_str(),
658                 login.c_str(),
659                 inet_ntostring(lastIPForDisconnect).c_str(),
660                 cash.ConstData(),
661                 id,
662                 dirsStr);
663
664         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
665         while (it != settings->GetScriptParams().end())
666             {
667             scriptOnDisonnectParams += GetParamValue(it->c_str());
668             }
669
670         ScriptExec(scriptOnDisonnectParams.c_str());
671         }
672     else
673         {
674         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
675         }
676
677     connected = false;
678     }
679
680 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
681     {
682     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
683     WriteServLog("%s", store->GetStrError().c_str());
684     }
685
686 if (!fakeDisconnect)
687     lastIPForDisconnect = 0;
688
689 DIR_TRAFF zeroSesssion;
690
691 sessionUpload = zeroSesssion;
692 sessionDownload = zeroSesssion;
693 }
694 //-----------------------------------------------------------------------------
695 void USER_IMPL::PrintUser() const
696 {
697 //return;
698 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
699 std::cout << "============================================================" << std::endl;
700 std::cout << "id=" << id << std::endl;
701 std::cout << "login=" << login << std::endl;
702 std::cout << "password=" << password << std::endl;
703 std::cout << "passive=" << passive << std::endl;
704 std::cout << "disabled=" << disabled << std::endl;
705 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
706 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
707 std::cout << "tariffName=" << tariffName << std::endl;
708 std::cout << "address=" << address << std::endl;
709 std::cout << "phone=" << phone << std::endl;
710 std::cout << "email=" << email << std::endl;
711 std::cout << "note=" << note << std::endl;
712 std::cout << "realName=" <<realName << std::endl;
713 std::cout << "group=" << group << std::endl;
714 std::cout << "credit=" << credit << std::endl;
715 std::cout << "nextTariff=" << nextTariff << std::endl;
716 std::cout << "userdata0" << userdata0 << std::endl;
717 std::cout << "userdata1" << userdata1 << std::endl;
718 std::cout << "creditExpire=" << creditExpire << std::endl;
719 std::cout << "ips=" << ips << std::endl;
720 std::cout << "------------------------" << std::endl;
721 std::cout << "up=" << up << std::endl;
722 std::cout << "down=" << down << std::endl;
723 std::cout << "cash=" << cash << std::endl;
724 std::cout << "freeMb=" << freeMb << std::endl;
725 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
726 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
727 std::cout << "passiveTime=" << passiveTime << std::endl;
728 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
729 std::cout << "============================================================" << std::endl;
730 }
731 //-----------------------------------------------------------------------------
732 void USER_IMPL::Run()
733 {
734 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
735
736 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
737     {
738     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
739     WriteStat();
740     }
741 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
742     {
743     WriteServLog("User: %s. Credit expired.", login.c_str());
744     credit = 0;
745     creditExpire = 0;
746     WriteConf();
747     }
748
749 if (passive.ConstData()
750     && (stgTime % 30 == 0)
751     && (passiveTime.ModificationTime() != stgTime))
752     {
753     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
754     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
755     }
756
757 if (!authorizedBy.empty())
758     {
759     if (connected)
760         {
761         property.Stat().lastActivityTime = stgTime;
762         }
763     if (!connected && IsInetable())
764         {
765         Connect();
766         }
767     if (connected && !IsInetable())
768         {
769         if (disabled)
770             Disconnect(false, "disabled");
771         else if (passive)
772             Disconnect(false, "passive");
773         else
774             Disconnect(false, "no cash");
775         }
776
777     if (stgTime - lastScanMessages > 10)
778         {
779         ScanMessage();
780         lastScanMessages = stgTime;
781         }
782     }
783 else
784     {
785     if (connected)
786         {
787         Disconnect(false, "not authorized");
788         }
789     }
790
791 }
792 //-----------------------------------------------------------------------------
793 void USER_IMPL::UpdatePingTime(time_t t)
794 {
795 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
796 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
797 if (t)
798     pingTime = t;
799 else
800     pingTime = stgTime;
801 }
802 //-----------------------------------------------------------------------------
803 bool USER_IMPL::IsInetable()
804 {
805 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
806
807 if (disabled || passive)
808     return false;
809
810 if (settings->GetFreeMbAllowInet())
811     {
812     if (freeMb >= 0)
813         return true;
814     }
815
816 if (settings->GetShowFeeInCash() || tariff == NULL)
817     {
818     return (cash >= -credit);
819     }
820
821 return (cash - tariff->GetFee() >= -credit);
822 }
823 //-----------------------------------------------------------------------------
824 std::string USER_IMPL::GetEnabledDirs()
825 {
826 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
827
828 std::string dirs = "";
829 for(int i = 0; i < DIR_NUM; i++)
830     dirs += enabledDirs[i] ? "1" : "0";
831 return dirs;
832 }
833 //-----------------------------------------------------------------------------
834 #ifdef TRAFF_STAT_WITH_PORTS
835 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
836 #else
837 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
838 #endif
839 {
840 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
841
842 if (!connected || tariff == NULL)
843     return;
844
845 double cost = 0;
846 DIR_TRAFF dt(up);
847
848 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
849 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
850
851 dt[dir] += len;
852
853 int tt = tariff->GetTraffType();
854 if (tt == TRAFF_UP ||
855     tt == TRAFF_UP_DOWN ||
856     // Check NEW traff data
857     (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
858     {
859     double dc = 0;
860     if (traff < threshold &&
861         traff + len >= threshold)
862         {
863         // cash = partBeforeThreshold * priceBeforeThreshold +
864         //        partAfterThreshold * priceAfterThreshold
865         int64_t before = threshold - traff; // Chunk part before threshold
866         int64_t after = len - before; // Chunk part after threshold
867         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
868                                            down.ConstData()[dir],
869                                            dir,
870                                            stgTime) * before +
871              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
872                                            down.ConstData()[dir],
873                                            dir,
874                                            stgTime) * after;
875         }
876     else
877         {
878         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
879                                            down.ConstData()[dir],
880                                            dir,
881                                            stgTime) * len;
882         }
883
884     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
885         cost = dc;
886     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
887         cost = dc - freeMb.ConstData();
888
889     // Direct access to internal data structures via friend-specifier
890     property.Stat().freeMb -= dc;
891     property.Stat().cash -= cost;
892     cash.ModifyTime();
893     freeMb.ModifyTime();
894     }
895
896 up = dt;
897 sessionUpload[dir] += len;
898
899 //Add detailed stat
900
901 if (!settings->GetWriteFreeMbTraffCost() &&
902      freeMb.ConstData() >= 0)
903     cost = 0;
904
905 #ifdef TRAFF_STAT_WITH_PORTS
906 IP_DIR_PAIR idp(ip, dir, port);
907 #else
908 IP_DIR_PAIR idp(ip, dir);
909 #endif
910
911 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
912 lb = traffStat.lower_bound(idp);
913 if (lb == traffStat.end() || lb->first != idp)
914     {
915     traffStat.insert(lb,
916                      std::make_pair(idp,
917                                     STAT_NODE(len, 0, cost)));
918     }
919 else
920     {
921     lb->second.cash += cost;
922     lb->second.up += len;
923     }
924 }
925 //-----------------------------------------------------------------------------
926 #ifdef TRAFF_STAT_WITH_PORTS
927 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
928 #else
929 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
930 #endif
931 {
932 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
933
934 if (!connected || tariff == NULL)
935     return;
936
937 double cost = 0;
938 DIR_TRAFF dt(down);
939
940 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
941 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
942
943 dt[dir] += len;
944
945 int tt = tariff->GetTraffType();
946 if (tt == TRAFF_DOWN ||
947     tt == TRAFF_UP_DOWN ||
948     // Check NEW traff data
949     (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
950     {
951     double dc = 0;
952     if (traff < threshold &&
953         traff + len >= threshold)
954         {
955         // cash = partBeforeThreshold * priceBeforeThreshold +
956         //        partAfterThreshold * priceAfterThreshold
957         int64_t before = threshold - traff; // Chunk part before threshold
958         int64_t after = len - before; // Chunk part after threshold
959         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
960                                            down.ConstData()[dir], // Traff before chunk
961                                            dir,
962                                            stgTime) * before +
963              tariff->GetPriceWithTraffType(up.ConstData()[dir],
964                                            dt[dir], // Traff after chunk
965                                            dir,
966                                            stgTime) * after;
967         }
968     else
969         {
970         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
971                                            down.ConstData()[dir],
972                                            dir,
973                                            stgTime) * len;
974         }
975
976     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
977         cost = dc;
978     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
979         cost = dc - freeMb.ConstData();
980
981     property.Stat().freeMb -= dc;
982     property.Stat().cash -= cost;
983     cash.ModifyTime();
984     freeMb.ModifyTime();
985     }
986
987 down = dt;
988 sessionDownload[dir] += len;
989
990 //Add detailed stat
991
992 if (!settings->GetWriteFreeMbTraffCost() &&
993      freeMb.ConstData() >= 0)
994     cost = 0;
995
996 #ifdef TRAFF_STAT_WITH_PORTS
997 IP_DIR_PAIR idp(ip, dir, port);
998 #else
999 IP_DIR_PAIR idp(ip, dir);
1000 #endif
1001
1002 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
1003 lb = traffStat.lower_bound(idp);
1004 if (lb == traffStat.end() || lb->first != idp)
1005     {
1006     traffStat.insert(lb,
1007                      std::make_pair(idp,
1008                                     STAT_NODE(0, len, cost)));
1009     }
1010 else
1011     {
1012     lb->second.cash += cost;
1013     lb->second.down += len;
1014     }
1015 }
1016 //-----------------------------------------------------------------------------
1017 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1018 {
1019 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1020 currIP.AddBeforeNotifier(notifier);
1021 }
1022 //-----------------------------------------------------------------------------
1023 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1024 {
1025 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1026 currIP.DelBeforeNotifier(notifier);
1027 }
1028 //-----------------------------------------------------------------------------
1029 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1030 {
1031 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1032 currIP.AddAfterNotifier(notifier);
1033 }
1034 //-----------------------------------------------------------------------------
1035 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1036 {
1037 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1038 currIP.DelAfterNotifier(notifier);
1039 }
1040 //-----------------------------------------------------------------------------
1041 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1042 {
1043 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1044 connected.AddBeforeNotifier(notifier);
1045 }
1046 //-----------------------------------------------------------------------------
1047 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1048 {
1049 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1050 connected.DelBeforeNotifier(notifier);
1051 }
1052 //-----------------------------------------------------------------------------
1053 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1054 {
1055 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1056 connected.AddAfterNotifier(notifier);
1057 }
1058 //-----------------------------------------------------------------------------
1059 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1060 {
1061 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1062 connected.DelAfterNotifier(notifier);
1063 }
1064 //-----------------------------------------------------------------------------
1065 void USER_IMPL::OnAdd()
1066 {
1067 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1068
1069 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1070
1071 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1072     {
1073     std::string scriptOnAddParams;
1074     strprintf(&scriptOnAddParams,
1075             "%s \"%s\"",
1076             scriptOnAdd.c_str(),
1077             login.c_str());
1078
1079     ScriptExec(scriptOnAddParams.c_str());
1080     }
1081 else
1082     {
1083     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1084     }
1085 }
1086 //-----------------------------------------------------------------------------
1087 void USER_IMPL::OnDelete()
1088 {
1089 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1090
1091 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1092
1093 if (access(scriptOnDel.c_str(), X_OK) == 0)
1094     {
1095     std::string scriptOnDelParams;
1096     strprintf(&scriptOnDelParams,
1097             "%s \"%s\"",
1098             scriptOnDel.c_str(),
1099             login.c_str());
1100
1101     ScriptExec(scriptOnDelParams.c_str());
1102     }
1103 else
1104     {
1105     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1106     }
1107
1108 Run();
1109 }
1110 //-----------------------------------------------------------------------------
1111 int USER_IMPL::WriteDetailStat(bool hard)
1112 {
1113 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1114
1115 if (!traffStatSaved.second.empty())
1116     {
1117     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1118         {
1119         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1120         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1121         WriteServLog("%s", store->GetStrError().c_str());
1122         return -1;
1123         }
1124     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1125     }
1126
1127 TRAFF_STAT ts;
1128
1129     {
1130     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1131     ts.swap(traffStat);
1132     }
1133
1134 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1135
1136 if (ts.size() && !disabledDetailStat)
1137     {
1138     if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1139         {
1140         printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1141         WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1142         WriteServLog("%s", store->GetStrError().c_str());
1143         if (!hard)
1144             {
1145             printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1146             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1147             traffStatSaved.second.swap(ts);
1148             traffStatSaved.first = lastWriteDetailedStat;
1149             }
1150         return -1;
1151         }
1152     }
1153 lastWriteDetailedStat = stgTime;
1154 return 0;
1155 }
1156 //-----------------------------------------------------------------------------
1157 double USER_IMPL::GetPassiveTimePart() const
1158 {
1159 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1160
1161 static int daysInMonth[12] =
1162 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1163
1164 struct tm tms;
1165 time_t t = stgTime;
1166 localtime_r(&t, &tms);
1167
1168 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1169
1170 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1171     {
1172     // Leap year
1173     secMonth += 24 * 3600;
1174     }
1175
1176 time_t dt = secMonth - passiveTime;
1177
1178 if (dt < 0)
1179     dt = 0;
1180
1181 return static_cast<double>(dt) / secMonth;
1182 }
1183 //-----------------------------------------------------------------------------
1184 void USER_IMPL::SetPassiveTimeAsNewUser()
1185 {
1186 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1187
1188 time_t t = stgTime;
1189 struct tm tm;
1190 localtime_r(&t, &tm);
1191 int daysCurrMon = DaysInCurrentMonth();
1192 double pt = tm.tm_mday - 1;
1193 pt /= daysCurrMon;
1194
1195 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1196 }
1197 //-----------------------------------------------------------------------------
1198 void USER_IMPL::MidnightResetSessionStat()
1199 {
1200 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1201
1202 if (connected)
1203     {
1204     Disconnect(true, "fake");
1205     Connect(true);
1206     }
1207 }
1208 //-----------------------------------------------------------------------------
1209 void USER_IMPL::ProcessNewMonth()
1210 {
1211 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1212 //  Reset traff
1213 if (connected)
1214     {
1215     Disconnect(true, "fake");
1216     }
1217 DIR_TRAFF zeroTarff;
1218
1219 WriteMonthStat();
1220
1221 up = zeroTarff;
1222 down = zeroTarff;
1223
1224 if (connected)
1225     {
1226     Connect(true);
1227     }
1228
1229 //  Set new tariff
1230 if (nextTariff.ConstData() != "")
1231     {
1232     const TARIFF * nt;
1233     nt = tariffs->FindByName(nextTariff);
1234     if (nt == NULL)
1235         {
1236         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1237                      login.c_str(), property.tariffName.Get().c_str());
1238         }
1239     else
1240         {
1241         property.tariffName.Set(nextTariff, sysAdmin, login, store);
1242         //tariff = nt;
1243         }
1244     ResetNextTariff();
1245     WriteConf();
1246     }
1247 }
1248 //-----------------------------------------------------------------------------
1249 void USER_IMPL::ProcessDayFeeSpread()
1250 {
1251 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1252
1253 if (passive.ConstData() || tariff == NULL)
1254     return;
1255
1256 double fee = tariff->GetFee() / DaysInCurrentMonth();
1257
1258 if (std::fabs(fee) < 1.0e-3)
1259     return;
1260
1261 double c = cash;
1262 switch (settings->GetFeeChargeType())
1263     {
1264     case 0:
1265         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1266         break;
1267     case 1:
1268         if (c + credit >= 0)
1269             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1270         break;
1271     case 2:
1272         if (c + credit >= fee)
1273             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1274         break;
1275     case 3:
1276         if (c >= 0)
1277             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1278         break;
1279     }
1280 ResetPassiveTime();
1281 }
1282 //-----------------------------------------------------------------------------
1283 void USER_IMPL::ProcessDayFee()
1284 {
1285 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1286
1287 if (tariff == NULL)
1288     return;
1289
1290 double passiveTimePart = 1.0;
1291 if (!settings->GetFullFee())
1292     {
1293     passiveTimePart = GetPassiveTimePart();
1294     }
1295 else
1296     {
1297     if (passive.ConstData())
1298         {
1299         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1300         return;
1301         }
1302     }
1303 double fee = tariff->GetFee() * passiveTimePart;
1304
1305 ResetPassiveTime();
1306
1307 if (std::fabs(fee) < 1.0e-3)
1308     {
1309     SetPrepaidTraff();
1310     return;
1311     }
1312
1313 double c = cash;
1314 printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
1315         login.c_str(),
1316         cash.ConstData(),
1317         credit.ConstData(),
1318         tariff->GetFee(),
1319         passiveTimePart,
1320         fee);
1321 switch (settings->GetFeeChargeType())
1322     {
1323     case 0:
1324         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1325         SetPrepaidTraff();
1326         break;
1327     case 1:
1328         if (c + credit >= 0)
1329             {
1330             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1331             SetPrepaidTraff();
1332             }
1333         break;
1334     case 2:
1335         if (c + credit >= fee)
1336             {
1337             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1338             SetPrepaidTraff();
1339             }
1340         break;
1341     case 3:
1342         if (c >= 0)
1343             {
1344             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1345             SetPrepaidTraff();
1346             }
1347         break;
1348     }
1349 }
1350 //-----------------------------------------------------------------------------
1351 void USER_IMPL::SetPrepaidTraff()
1352 {
1353 if (tariff != NULL)
1354     property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1355 }
1356 //-----------------------------------------------------------------------------
1357 int USER_IMPL::AddMessage(STG_MSG * msg)
1358 {
1359 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1360
1361 if (SendMessage(*msg))
1362     {
1363     if (store->AddMessage(msg, login))
1364         {
1365         errorStr = store->GetStrError();
1366         WriteServLog("Error adding message: '%s'", errorStr.c_str());
1367         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1368         return -1;
1369         }
1370     messages.push_back(*msg);
1371     }
1372 else
1373     {
1374     if (msg->header.repeat > 0)
1375         {
1376         msg->header.repeat--;
1377         #ifndef DEBUG
1378         //TODO: gcc v. 4.x generate ICE on x86_64
1379         msg->header.lastSendTime = static_cast<int>(time(NULL));
1380         #else
1381         msg->header.lastSendTime = static_cast<int>(stgTime);
1382         #endif
1383         if (store->AddMessage(msg, login))
1384             {
1385             errorStr = store->GetStrError();
1386             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1387             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1388             return -1;
1389             }
1390         messages.push_back(*msg);
1391         }
1392     }
1393 return 0;
1394 }
1395 //-----------------------------------------------------------------------------
1396 int USER_IMPL::SendMessage(STG_MSG & msg) const
1397 {
1398 // No lock `cause we are already locked from caller
1399 int ret = -1;
1400 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1401 while (it != authorizedBy.end())
1402     {
1403     if (!(*it++)->SendMessage(msg, currIP))
1404         ret = 0;
1405     }
1406 if (!ret)
1407     {
1408 #ifndef DEBUG
1409     //TODO: gcc v. 4.x generate ICE on x86_64
1410     msg.header.lastSendTime = static_cast<int>(time(NULL));
1411 #else
1412     msg.header.lastSendTime = static_cast<int>(stgTime);
1413 #endif
1414     msg.header.repeat--;
1415     }
1416 return ret;
1417 }
1418 //-----------------------------------------------------------------------------
1419 void USER_IMPL::ScanMessage()
1420 {
1421 // No lock `cause we are already locked from caller
1422 // We need not check for the authorizedBy `cause it has already checked by caller
1423
1424 std::list<STG_MSG>::iterator it(messages.begin());
1425 while (it != messages.end())
1426     {
1427     if (settings->GetMessageTimeout() > 0 &&
1428         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1429         {
1430         // Timeout exceeded
1431         if (store->DelMessage(it->header.id, login))
1432             {
1433             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1434             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1435             }
1436         messages.erase(it++);
1437         continue;
1438         }
1439     if (it->GetNextSendTime() <= stgTime)
1440         {
1441         if (SendMessage(*it))
1442             {
1443             // We need to check all messages in queue for timeout
1444             ++it;
1445             continue;
1446             }
1447         if (it->header.repeat < 0)
1448             {
1449             if (store->DelMessage(it->header.id, login))
1450                 {
1451                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1452                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1453                 }
1454             messages.erase(it++);
1455             }
1456         else
1457             {
1458             if (store->EditMessage(*it, login))
1459                 {
1460                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1461                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1462                 }
1463             ++it;
1464             }
1465         }
1466     else
1467         {
1468         ++it;
1469         }
1470     }
1471 }
1472 //-----------------------------------------------------------------------------
1473 std::string USER_IMPL::GetParamValue(const std::string & name) const
1474 {
1475 if (name == "freeMb")       return property.freeMb.ToString();
1476 if (name == "passive")      return property.passive.ToString();
1477 if (name == "disabled")     return property.disabled.ToString();
1478 if (name == "alwaysOnline") return property.alwaysOnline.ToString();
1479 if (name == "tariffName")   return property.tariffName;
1480 if (name == "nextTariff")   return property.nextTariff;
1481 if (name == "address")      return property.address;
1482 if (name == "note")         return property.note;
1483 if (name == "group")        return property.group;
1484 if (name == "email")        return property.email;
1485 if (name == "phone")        return property.phone;
1486 if (name == "realName")     return property.realName;
1487 if (name == "credit")       return property.credit.ToString();
1488 if (name == "userdata0")    return property.userdata0;
1489 if (name == "userdata1")    return property.userdata1;
1490 if (name == "userdata2")    return property.userdata2;
1491 if (name == "userdata3")    return property.userdata3;
1492 if (name == "userdata4")    return property.userdata4;
1493 if (name == "userdata5")    return property.userdata5;
1494 if (name == "userdata6")    return property.userdata6;
1495 if (name == "userdata7")    return property.userdata7;
1496 if (name == "userdata8")    return property.userdata8;
1497 if (name == "userdata9")    return property.userdata9;
1498 //if (name == "cash")         return property.cash.ToString();
1499 //if (name == "id")
1500 //    {
1501 //    std::stringstream stream;
1502 //    stream << id;
1503 //    return stream.str();;
1504 //    }
1505 //if (name == "login")        return login;
1506 //if (name == "ip")           return currIP.ToString();
1507 }
1508 //-----------------------------------------------------------------------------
1509 //-----------------------------------------------------------------------------
1510 //-----------------------------------------------------------------------------
1511 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1512 {
1513 if (newPassive && !oldPassive && user->tariff != NULL)
1514     user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1515                             user->sysAdmin,
1516                             user->login,
1517                             user->store,
1518                             "Freeze");
1519 }
1520 //-----------------------------------------------------------------------------
1521 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1522 {
1523 if (oldValue && !newValue && user->GetConnected())
1524     {
1525     user->Disconnect(false, "disabled");
1526     }
1527 else if (!oldValue && newValue && user->IsInetable())
1528     {
1529     user->Connect(false);
1530     }
1531
1532 }
1533 //-----------------------------------------------------------------------------
1534 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1535 {
1536 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1537     user->Disconnect(false, "Change tariff");
1538 user->tariff = user->tariffs->FindByName(newTariff);
1539 if (user->settings->GetReconnectOnTariffChange() &&
1540     !user->authorizedBy.empty() &&
1541     user->IsInetable())
1542     user->Connect(false);
1543 }
1544 //-----------------------------------------------------------------------------
1545 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1546 {
1547 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1548 user->lastCashAdd = newCash - oldCash;
1549 }
1550 //-----------------------------------------------------------------------------
1551 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1552 {
1553     printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1554     if (user->connected)
1555         user->Disconnect(false, "Change IP");
1556     if (!user->authorizedBy.empty() && user->IsInetable())
1557         user->Connect(false);
1558 }
1559 //-----------------------------------------------------------------------------