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.
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.
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
22 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
27 $Date: 2010/11/03 10:50:03 $
36 #include <unistd.h> // access
41 #include "stg/users.h"
42 #include "stg/common.h"
43 #include "stg/scriptexecuter.h"
44 #include "stg/tariff.h"
45 #include "stg/tariffs.h"
46 #include "stg/admin.h"
47 #include "user_impl.h"
48 #include "settings_impl.h"
50 #ifdef USE_ABSTRACT_SETTINGS
51 USER_IMPL::USER_IMPL(const SETTINGS * s,
57 property(s->GetScriptsDir()),
58 WriteServLog(GetStgLogger()),
62 connected(__connected),
66 lastIPForDisconnect(0),
75 lastCashAdd(property.lastCashAdd),
76 passiveTime(property.passiveTime),
77 lastCashAddTime(property.lastCashAddTime),
78 freeMb(property.freeMb),
79 lastActivityTime(property.lastActivityTime),
80 password(property.password),
81 passive(property.passive),
82 disabled(property.disabled),
83 disabledDetailStat(property.disabledDetailStat),
84 alwaysOnline(property.alwaysOnline),
85 tariffName(property.tariffName),
86 nextTariff(property.nextTariff),
87 address(property.address),
89 group(property.group),
90 email(property.email),
91 phone(property.phone),
92 realName(property.realName),
93 credit(property.credit),
94 creditExpire(property.creditExpire),
96 userdata0(property.userdata0),
97 userdata1(property.userdata1),
98 userdata2(property.userdata2),
99 userdata3(property.userdata3),
100 userdata4(property.userdata4),
101 userdata5(property.userdata5),
102 userdata6(property.userdata6),
103 userdata7(property.userdata7),
104 userdata8(property.userdata8),
105 userdata9(property.userdata9),
106 passiveNotifier(this),
107 tariffNotifier(this),
113 password = "*_EMPTY_PASSWORD_*";
114 tariffName = NO_TARIFF_NAME;
118 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
119 lastWriteDetailedStat = stgTime;
121 property.tariffName.AddBeforeNotifier(&tariffNotifier);
122 property.passive.AddBeforeNotifier(&passiveNotifier);
123 property.cash.AddBeforeNotifier(&cashNotifier);
124 ips.AddAfterNotifier(&ipNotifier);
126 lastScanMessages = 0;
128 pthread_mutexattr_t attr;
129 pthread_mutexattr_init(&attr);
130 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
131 pthread_mutex_init(&mutex, &attr);
134 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
140 property(s->GetScriptsDir()),
141 WriteServLog(GetStgLogger()),
145 connected(__connected),
149 lastIPForDisconnect(0),
158 lastCashAdd(property.lastCashAdd),
159 passiveTime(property.passiveTime),
160 lastCashAddTime(property.lastCashAddTime),
161 freeMb(property.freeMb),
162 lastActivityTime(property.lastActivityTime),
163 password(property.password),
164 passive(property.passive),
165 disabled(property.disabled),
166 disabledDetailStat(property.disabledDetailStat),
167 alwaysOnline(property.alwaysOnline),
168 tariffName(property.tariffName),
169 nextTariff(property.nextTariff),
170 address(property.address),
172 group(property.group),
173 email(property.email),
174 phone(property.phone),
175 realName(property.realName),
176 credit(property.credit),
177 creditExpire(property.creditExpire),
179 userdata0(property.userdata0),
180 userdata1(property.userdata1),
181 userdata2(property.userdata2),
182 userdata3(property.userdata3),
183 userdata4(property.userdata4),
184 userdata5(property.userdata5),
185 userdata6(property.userdata6),
186 userdata7(property.userdata7),
187 userdata8(property.userdata8),
188 userdata9(property.userdata9),
189 passiveNotifier(this),
190 tariffNotifier(this),
196 password = "*_EMPTY_PASSWORD_*";
197 tariffName = NO_TARIFF_NAME;
201 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
202 lastWriteDetailedStat = stgTime;
204 property.tariffName.AddBeforeNotifier(&tariffNotifier);
205 property.passive.AddBeforeNotifier(&passiveNotifier);
206 property.cash.AddBeforeNotifier(&cashNotifier);
207 ips.AddAfterNotifier(&ipNotifier);
209 lastScanMessages = 0;
211 pthread_mutexattr_t attr;
212 pthread_mutexattr_init(&attr);
213 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
214 pthread_mutex_init(&mutex, &attr);
217 //-----------------------------------------------------------------------------
218 USER_IMPL::USER_IMPL(const USER_IMPL & u)
220 property(u.settings->GetScriptsDir()),
221 WriteServLog(GetStgLogger()),
224 __connected(u.__connected),
225 connected(__connected),
226 __currIP(u.__currIP),
228 lastIPForDisconnect(0),
229 pingTime(u.pingTime),
230 sysAdmin(u.sysAdmin),
237 lastCashAdd(property.lastCashAdd),
238 passiveTime(property.passiveTime),
239 lastCashAddTime(property.lastCashAddTime),
240 freeMb(property.freeMb),
241 lastActivityTime(property.lastActivityTime),
242 password(property.password),
243 passive(property.passive),
244 disabled(property.disabled),
245 disabledDetailStat(property.disabledDetailStat),
246 alwaysOnline(property.alwaysOnline),
247 tariffName(property.tariffName),
248 nextTariff(property.nextTariff),
249 address(property.address),
251 group(property.group),
252 email(property.email),
253 phone(property.phone),
254 realName(property.realName),
255 credit(property.credit),
256 creditExpire(property.creditExpire),
258 userdata0(property.userdata0),
259 userdata1(property.userdata1),
260 userdata2(property.userdata2),
261 userdata3(property.userdata3),
262 userdata4(property.userdata4),
263 userdata5(property.userdata5),
264 userdata6(property.userdata6),
265 userdata7(property.userdata7),
266 userdata8(property.userdata8),
267 userdata9(property.userdata9),
268 passiveNotifier(this),
269 tariffNotifier(this),
280 lastWriteStat = u.lastWriteStat;
281 lastWriteDetailedStat = u.lastWriteDetailedStat;
283 settings = u.settings;
285 property.tariffName.AddBeforeNotifier(&tariffNotifier);
286 property.passive.AddBeforeNotifier(&passiveNotifier);
287 property.cash.AddBeforeNotifier(&cashNotifier);
288 ips.AddAfterNotifier(&ipNotifier);
290 lastScanMessages = 0;
292 property.SetProperties(u.property);
294 pthread_mutexattr_t attr;
295 pthread_mutexattr_init(&attr);
296 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
297 pthread_mutex_init(&mutex, &attr);
299 //-----------------------------------------------------------------------------
300 USER_IMPL::~USER_IMPL()
302 property.passive.DelBeforeNotifier(&passiveNotifier);
303 property.tariffName.DelBeforeNotifier(&tariffNotifier);
304 pthread_mutex_destroy(&mutex);
306 //-----------------------------------------------------------------------------
307 void USER_IMPL::SetLogin(string const & l)
309 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
310 assert(login.empty() && "Login is already set");
312 id = userIDGenerator.GetNextID();
314 //-----------------------------------------------------------------------------
315 int USER_IMPL::ReadConf()
317 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
320 if (store->RestoreUserConf(&conf, login))
322 WriteServLog("Cannot read conf for user %s.", login.c_str());
323 WriteServLog("%s", store->GetStrError().c_str());
324 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
325 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
329 property.SetConf(conf);
331 tariff = tariffs->FindByName(tariffName);
334 WriteServLog("Cannot read user %s. Tariff %s not exist.",
335 login.c_str(), property.tariffName.Get().c_str());
339 std::vector<STG_MSG_HDR> hdrsList;
341 if (store->GetMessageHdrs(&hdrsList, login))
343 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
347 std::vector<STG_MSG_HDR>::const_iterator it;
348 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
351 if (store->GetMessage(it->id, &msg, login) == 0)
353 messages.push_back(msg);
359 //-----------------------------------------------------------------------------
360 int USER_IMPL::ReadStat()
362 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
365 if (store->RestoreUserStat(&stat, login))
367 WriteServLog("Cannot read stat for user %s.", login.c_str());
368 WriteServLog("%s", store->GetStrError().c_str());
369 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
370 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
374 property.SetStat(stat);
378 //-----------------------------------------------------------------------------
379 int USER_IMPL::WriteConf()
381 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
382 USER_CONF conf(property.GetConf());
384 printfd(__FILE__, "USER::WriteConf()\n");
386 if (store->SaveUserConf(conf, login))
388 WriteServLog("Cannot write conf for user %s.", login.c_str());
389 WriteServLog("%s", store->GetStrError().c_str());
390 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
391 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
397 //-----------------------------------------------------------------------------
398 int USER_IMPL::WriteStat()
400 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
401 USER_STAT stat(property.GetStat());
403 if (store->SaveUserStat(stat, login))
405 WriteServLog("Cannot write stat for user %s.", login.c_str());
406 WriteServLog("%s", store->GetStrError().c_str());
407 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
408 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
412 lastWriteStat = stgTime;
416 //-----------------------------------------------------------------------------
417 int USER_IMPL::WriteMonthStat()
419 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
420 time_t tt = stgTime - 3600;
422 localtime_r(&tt, &t1);
424 USER_STAT stat(property.GetStat());
425 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
427 WriteServLog("Cannot write month stat for user %s.", login.c_str());
428 WriteServLog("%s", store->GetStrError().c_str());
429 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
430 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
436 //-----------------------------------------------------------------------------
437 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
439 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
441 * Authorize user. It only means that user will be authorized. Nothing more.
442 * User can be connected or disconnected while authorized.
443 * Example: user is authorized but disconnected due to 0 money or blocking
447 * Prevent double authorization by identical authorizers
449 if (authorizedBy.find(auth) != authorizedBy.end())
455 for (int i = 0; i < DIR_NUM; i++)
457 enabledDirs[i] = dirs & (1 << i);
460 if (authorizedBy.size())
464 // We are already authorized, but with different IP address
465 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
470 if (!users->FindByIPIdx(ip, &u))
472 // Address is already present in IP-index
473 // If it's not our IP - throw an error
476 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
483 if (users->IsIPInIndex(ip))
485 // Address is already present in IP-index
486 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
490 if (ips.ConstData().IsIPInIPS(ip))
493 lastIPForDisconnect = currIP;
497 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
498 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
503 authorizedBy.insert(auth);
509 //-----------------------------------------------------------------------------
510 void USER_IMPL::Unauthorize(const AUTH * auth)
512 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
514 * Authorizer tries to unauthorize user, that was not authorized by it
516 if (!authorizedBy.erase(auth))
519 if (authorizedBy.empty())
521 lastIPForDisconnect = currIP;
522 currIP = 0; // DelUser in traffcounter
526 //-----------------------------------------------------------------------------
527 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
529 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
530 // Is this user authorized by specified authorizer?
531 return authorizedBy.find(auth) != authorizedBy.end();
533 //-----------------------------------------------------------------------------
534 void USER_IMPL::Connect(bool fakeConnect)
537 * Connect user to Internet. This function is differ from Authorize() !!!
540 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
544 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
546 if (access(scriptOnConnect.c_str(), X_OK) == 0)
548 char dirsStr[DIR_NUM + 1];
549 dirsStr[DIR_NUM] = 0;
550 for (int i = 0; i < DIR_NUM; i++)
552 dirsStr[i] = enabledDirs[i] ? '1' : '0';
555 string scriptOnConnectParams;
556 strprintf(&scriptOnConnectParams,
557 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
558 scriptOnConnect.c_str(),
560 inet_ntostring(currIP).c_str(),
565 ScriptExec(scriptOnConnectParams);
569 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
575 if (store->WriteUserConnect(login, currIP))
577 WriteServLog("Cannot write connect for user %s.", login.c_str());
578 WriteServLog("%s", store->GetStrError().c_str());
582 lastIPForDisconnect = currIP;
584 //-----------------------------------------------------------------------------
585 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
588 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
591 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
593 if (!lastIPForDisconnect)
595 printfd(__FILE__, "lastIPForDisconnect\n");
601 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
603 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
605 char dirsStr[DIR_NUM + 1];
606 dirsStr[DIR_NUM] = 0;
607 for (int i = 0; i < DIR_NUM; i++)
609 dirsStr[i] = enabledDirs[i] ? '1' : '0';
612 string scriptOnDisonnectParams;
613 strprintf(&scriptOnDisonnectParams,
614 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
615 scriptOnDisonnect.c_str(),
617 inet_ntostring(lastIPForDisconnect).c_str(),
622 ScriptExec(scriptOnDisonnectParams);
626 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
632 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
634 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
635 WriteServLog("%s", store->GetStrError().c_str());
639 lastIPForDisconnect = 0;
641 DIR_TRAFF zeroSesssion;
643 sessionUpload = zeroSesssion;
644 sessionDownload = zeroSesssion;
646 //-----------------------------------------------------------------------------
647 void USER_IMPL::PrintUser() const
650 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
651 cout << "============================================================" << endl;
652 cout << "id=" << id << endl;
653 cout << "login=" << login << endl;
654 cout << "password=" << password << endl;
655 cout << "passive=" << passive << endl;
656 cout << "disabled=" << disabled << endl;
657 cout << "disabledDetailStat=" << disabledDetailStat << endl;
658 cout << "alwaysOnline=" << alwaysOnline << endl;
659 cout << "tariffName=" << tariffName << endl;
660 cout << "address=" << address << endl;
661 cout << "phone=" << phone << endl;
662 cout << "email=" << email << endl;
663 cout << "note=" << note << endl;
664 cout << "realName=" <<realName << endl;
665 cout << "group=" << group << endl;
666 cout << "credit=" << credit << endl;
667 cout << "nextTariff=" << nextTariff << endl;
668 cout << "userdata0" << userdata0 << endl;
669 cout << "userdata1" << userdata1 << endl;
670 cout << "creditExpire=" << creditExpire << endl;
671 cout << "ips=" << ips << endl;
672 cout << "------------------------" << endl;
673 cout << "up=" << up << endl;
674 cout << "down=" << down << endl;
675 cout << "cash=" << cash << endl;
676 cout << "freeMb=" << freeMb << endl;
677 cout << "lastCashAdd=" << lastCashAdd << endl;
678 cout << "lastCashAddTime=" << lastCashAddTime << endl;
679 cout << "passiveTime=" << passiveTime << endl;
680 cout << "lastActivityTime=" << lastActivityTime << endl;
681 cout << "============================================================" << endl;
683 //-----------------------------------------------------------------------------
684 void USER_IMPL::Run()
686 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
688 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
690 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
693 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
695 WriteServLog("User: %s. Credit expired.", login.c_str());
701 if (passive.ConstData()
702 && (stgTime % 30 == 0)
703 && (passiveTime.ModificationTime() != stgTime))
705 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
706 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
709 if (!authorizedBy.empty())
713 property.Stat().lastActivityTime = stgTime;
715 if (!connected && IsInetable())
719 if (connected && !IsInetable())
722 Disconnect(false, "disabled");
724 Disconnect(false, "passive");
726 Disconnect(false, "no cash");
729 if (stgTime - lastScanMessages > 10)
732 lastScanMessages = stgTime;
739 Disconnect(false, "not authorized");
744 //-----------------------------------------------------------------------------
745 void USER_IMPL::UpdatePingTime(time_t t)
747 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
748 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
754 //-----------------------------------------------------------------------------
755 bool USER_IMPL::IsInetable()
757 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
759 if (disabled || passive)
762 if (settings->GetFreeMbAllowInet())
768 if (settings->GetShowFeeInCash() || tariff == NULL)
770 return (cash >= -credit);
773 return (cash - tariff->GetFee() >= -credit);
775 //-----------------------------------------------------------------------------
776 string USER_IMPL::GetEnabledDirs()
778 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
781 for(int i = 0; i < DIR_NUM; i++)
782 dirs += enabledDirs[i] ? "1" : "0";
785 //-----------------------------------------------------------------------------
786 #ifdef TRAFF_STAT_WITH_PORTS
787 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
789 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
792 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
794 if (!connected || tariff == NULL)
800 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
801 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
805 int tt = tariff->GetTraffType();
806 if (tt == TRAFF_UP ||
807 tt == TRAFF_UP_DOWN ||
808 // Check NEW traff data
809 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
812 if (traff < threshold &&
813 traff + len >= threshold)
815 // cash = partBeforeThreshold * priceBeforeThreshold +
816 // partAfterThreshold * priceAfterThreshold
817 int64_t before = threshold - traff; // Chunk part before threshold
818 int64_t after = len - before; // Chunk part after threshold
819 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
820 down.ConstData()[dir],
823 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
824 down.ConstData()[dir],
830 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
831 down.ConstData()[dir],
836 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
838 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
839 cost = dc - freeMb.ConstData();
841 // Direct access to internal data structures via friend-specifier
842 property.Stat().freeMb -= dc;
843 property.Stat().cash -= cost;
849 sessionUpload[dir] += len;
853 if (!settings->GetWriteFreeMbTraffCost() &&
854 freeMb.ConstData() >= 0)
857 #ifdef TRAFF_STAT_WITH_PORTS
858 IP_DIR_PAIR idp(ip, dir, port);
860 IP_DIR_PAIR idp(ip, dir);
863 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
864 lb = traffStat.lower_bound(idp);
865 if (lb == traffStat.end() || lb->first != idp)
868 pair<IP_DIR_PAIR, STAT_NODE>(idp,
869 STAT_NODE(len, 0, cost)));
873 lb->second.cash += cost;
874 lb->second.up += len;
877 //-----------------------------------------------------------------------------
878 #ifdef TRAFF_STAT_WITH_PORTS
879 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
881 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
884 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
886 if (!connected || tariff == NULL)
892 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
893 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
897 int tt = tariff->GetTraffType();
898 if (tt == TRAFF_DOWN ||
899 tt == TRAFF_UP_DOWN ||
900 // Check NEW traff data
901 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
904 if (traff < threshold &&
905 traff + len >= threshold)
907 // cash = partBeforeThreshold * priceBeforeThreshold +
908 // partAfterThreshold * priceAfterThreshold
909 int64_t before = threshold - traff; // Chunk part before threshold
910 int64_t after = len - before; // Chunk part after threshold
911 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
912 down.ConstData()[dir], // Traff before chunk
915 tariff->GetPriceWithTraffType(up.ConstData()[dir],
916 dt[dir], // Traff after chunk
922 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
923 down.ConstData()[dir],
928 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
930 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
931 cost = dc - freeMb.ConstData();
933 property.Stat().freeMb -= dc;
934 property.Stat().cash -= cost;
940 sessionDownload[dir] += len;
944 if (!settings->GetWriteFreeMbTraffCost() &&
945 freeMb.ConstData() >= 0)
948 #ifdef TRAFF_STAT_WITH_PORTS
949 IP_DIR_PAIR idp(ip, dir, port);
951 IP_DIR_PAIR idp(ip, dir);
954 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
955 lb = traffStat.lower_bound(idp);
956 if (lb == traffStat.end() || lb->first != idp)
959 pair<IP_DIR_PAIR, STAT_NODE>(idp,
960 STAT_NODE(0, len, cost)));
964 lb->second.cash += cost;
965 lb->second.down += len;
968 //-----------------------------------------------------------------------------
969 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
971 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
972 currIP.AddBeforeNotifier(n);
974 //-----------------------------------------------------------------------------
975 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
977 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
978 currIP.DelBeforeNotifier(n);
980 //-----------------------------------------------------------------------------
981 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
983 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
984 currIP.AddAfterNotifier(n);
986 //-----------------------------------------------------------------------------
987 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
989 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
990 currIP.DelAfterNotifier(n);
992 //-----------------------------------------------------------------------------
993 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
995 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
996 connected.AddBeforeNotifier(n);
998 //-----------------------------------------------------------------------------
999 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1001 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1002 connected.DelBeforeNotifier(n);
1004 //-----------------------------------------------------------------------------
1005 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1007 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1008 connected.AddAfterNotifier(n);
1010 //-----------------------------------------------------------------------------
1011 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1013 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1014 connected.DelAfterNotifier(n);
1016 //-----------------------------------------------------------------------------
1017 void USER_IMPL::OnAdd()
1019 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1021 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1023 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1025 string scriptOnAddParams;
1026 strprintf(&scriptOnAddParams,
1028 scriptOnAdd.c_str(),
1031 ScriptExec(scriptOnAddParams);
1035 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1038 //-----------------------------------------------------------------------------
1039 void USER_IMPL::OnDelete()
1041 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1043 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1045 if (access(scriptOnDel.c_str(), X_OK) == 0)
1047 string scriptOnDelParams;
1048 strprintf(&scriptOnDelParams,
1050 scriptOnDel.c_str(),
1053 ScriptExec(scriptOnDelParams);
1057 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1062 //-----------------------------------------------------------------------------
1063 int USER_IMPL::WriteDetailStat(bool hard)
1065 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1067 if (!traffStatSaved.second.empty())
1069 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1071 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1072 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1073 WriteServLog("%s", store->GetStrError().c_str());
1076 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1082 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1086 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1088 if (ts.size() && !disabledDetailStat)
1090 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1092 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1093 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1094 WriteServLog("%s", store->GetStrError().c_str());
1097 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1098 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1099 traffStatSaved.second.swap(ts);
1100 traffStatSaved.first = lastWriteDetailedStat;
1105 lastWriteDetailedStat = stgTime;
1108 //-----------------------------------------------------------------------------
1109 double USER_IMPL::GetPassiveTimePart() const
1111 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1113 static int daysInMonth[12] =
1114 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1118 localtime_r(&t, &tms);
1120 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1122 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1125 secMonth += 24 * 3600;
1128 int dt = secMonth - passiveTime;
1133 return double(dt) / (secMonth);
1135 //-----------------------------------------------------------------------------
1136 void USER_IMPL::SetPassiveTimeAsNewUser()
1138 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1142 localtime_r(&t, &tm);
1143 int daysCurrMon = DaysInCurrentMonth();
1144 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1146 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1148 //-----------------------------------------------------------------------------
1149 void USER_IMPL::MidnightResetSessionStat()
1151 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1155 Disconnect(true, "fake");
1159 //-----------------------------------------------------------------------------
1160 void USER_IMPL::ProcessNewMonth()
1162 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1166 Disconnect(true, "fake");
1168 DIR_TRAFF zeroTarff;
1181 if (nextTariff.ConstData() != "")
1184 nt = tariffs->FindByName(nextTariff);
1187 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1188 login.c_str(), property.tariffName.Get().c_str());
1192 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1199 //-----------------------------------------------------------------------------
1200 void USER_IMPL::ProcessDayFeeSpread()
1202 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1204 if (passive.ConstData() || tariff == NULL)
1207 double fee = tariff->GetFee() / DaysInCurrentMonth();
1213 switch (settings->GetFeeChargeType())
1216 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1220 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1224 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1229 //-----------------------------------------------------------------------------
1230 void USER_IMPL::ProcessDayFee()
1232 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1237 double passiveTimePart = 1.0;
1238 if (!settings->GetFullFee())
1240 passiveTimePart = GetPassiveTimePart();
1244 if (passive.ConstData())
1246 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1250 double fee = tariff->GetFee() * passiveTimePart;
1261 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1266 switch (settings->GetFeeChargeType())
1269 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1275 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1282 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1288 //-----------------------------------------------------------------------------
1289 void USER_IMPL::SetPrepaidTraff()
1292 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1294 //-----------------------------------------------------------------------------
1295 int USER_IMPL::AddMessage(STG_MSG * msg)
1297 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1299 if (SendMessage(*msg))
1301 if (store->AddMessage(msg, login))
1303 errorStr = store->GetStrError();
1304 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1305 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1308 messages.push_back(*msg);
1312 if (msg->header.repeat > 0)
1314 msg->header.repeat--;
1316 //TODO: gcc v. 4.x generate ICE on x86_64
1317 msg->header.lastSendTime = time(NULL);
1319 msg->header.lastSendTime = stgTime;
1321 if (store->AddMessage(msg, login))
1323 errorStr = store->GetStrError();
1324 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1325 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1328 messages.push_back(*msg);
1333 //-----------------------------------------------------------------------------
1334 int USER_IMPL::SendMessage(STG_MSG & msg) const
1336 // No lock `cause we are already locked from caller
1338 set<const AUTH*>::iterator it(authorizedBy.begin());
1339 while (it != authorizedBy.end())
1341 if (!(*it++)->SendMessage(msg, currIP))
1347 //TODO: gcc v. 4.x generate ICE on x86_64
1348 msg.header.lastSendTime = time(NULL);
1350 msg.header.lastSendTime = stgTime;
1352 msg.header.repeat--;
1356 //-----------------------------------------------------------------------------
1357 void USER_IMPL::ScanMessage()
1359 // No lock `cause we are already locked from caller
1360 // We need not check for the authorizedBy `cause it has already checked by caller
1362 std::list<STG_MSG>::iterator it(messages.begin());
1363 while (it != messages.end())
1365 if (settings->GetMessageTimeout() > 0 &&
1366 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1369 if (store->DelMessage(it->header.id, login))
1371 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1372 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1374 messages.erase(it++);
1377 if (it->GetNextSendTime() <= stgTime)
1379 if (SendMessage(*it))
1381 // We need to check all messages in queue for timeout
1385 if (it->header.repeat < 0)
1387 if (store->DelMessage(it->header.id, login))
1389 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1390 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1392 messages.erase(it++);
1396 if (store->EditMessage(*it, login))
1398 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1399 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1410 //-----------------------------------------------------------------------------
1411 //-----------------------------------------------------------------------------
1412 //-----------------------------------------------------------------------------
1413 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1415 if (newPassive && !oldPassive && user->tariff != NULL)
1416 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1422 //-----------------------------------------------------------------------------
1423 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1425 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1426 user->Disconnect(true, "Change tariff");
1427 user->tariff = user->tariffs->FindByName(newTariff);
1428 if (user->settings->GetReconnectOnTariffChange() && user->IsInetable())
1429 user->Connect(true);
1431 //-----------------------------------------------------------------------------
1432 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1434 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1435 user->lastCashAdd = newCash - oldCash;
1437 //-----------------------------------------------------------------------------
1438 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1440 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1441 if (user->connected)
1442 user->Disconnect(true, "Change IP");
1443 if (user->IsInetable())
1444 user->Connect(true);
1446 //-----------------------------------------------------------------------------