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"
49 #include "stg_timer.h"
51 #ifdef USE_ABSTRACT_SETTINGS
52 USER_IMPL::USER_IMPL(const SETTINGS * s,
59 property(s->GetScriptsDir()),
60 WriteServLog(GetStgLogger()),
64 connected(__connected),
68 lastIPForDisconnect(0),
77 lastCashAdd(property.lastCashAdd),
78 passiveTime(property.passiveTime),
79 lastCashAddTime(property.lastCashAddTime),
80 freeMb(property.freeMb),
81 lastActivityTime(property.lastActivityTime),
82 password(property.password),
83 passive(property.passive),
84 disabled(property.disabled),
85 disabledDetailStat(property.disabledDetailStat),
86 alwaysOnline(property.alwaysOnline),
87 tariffName(property.tariffName),
88 nextTariff(property.nextTariff),
89 address(property.address),
91 group(property.group),
92 email(property.email),
93 phone(property.phone),
94 realName(property.realName),
95 credit(property.credit),
96 creditExpire(property.creditExpire),
98 userdata0(property.userdata0),
99 userdata1(property.userdata1),
100 userdata2(property.userdata2),
101 userdata3(property.userdata3),
102 userdata4(property.userdata4),
103 userdata5(property.userdata5),
104 userdata6(property.userdata6),
105 userdata7(property.userdata7),
106 userdata8(property.userdata8),
107 userdata9(property.userdata9),
108 passiveNotifier(this),
109 tariffNotifier(this),
115 password = "*_EMPTY_PASSWORD_*";
116 tariffName = NO_TARIFF_NAME;
120 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
121 lastWriteDetailedStat = stgTime;
123 property.tariffName.AddBeforeNotifier(&tariffNotifier);
124 property.passive.AddBeforeNotifier(&passiveNotifier);
125 property.cash.AddBeforeNotifier(&cashNotifier);
126 ips.AddAfterNotifier(&ipNotifier);
128 lastScanMessages = 0;
130 pthread_mutexattr_t attr;
131 pthread_mutexattr_init(&attr);
132 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
133 pthread_mutex_init(&mutex, &attr);
136 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
143 property(s->GetScriptsDir()),
144 WriteServLog(GetStgLogger()),
148 connected(__connected),
152 lastIPForDisconnect(0),
161 lastCashAdd(property.lastCashAdd),
162 passiveTime(property.passiveTime),
163 lastCashAddTime(property.lastCashAddTime),
164 freeMb(property.freeMb),
165 lastActivityTime(property.lastActivityTime),
166 password(property.password),
167 passive(property.passive),
168 disabled(property.disabled),
169 disabledDetailStat(property.disabledDetailStat),
170 alwaysOnline(property.alwaysOnline),
171 tariffName(property.tariffName),
172 nextTariff(property.nextTariff),
173 address(property.address),
175 group(property.group),
176 email(property.email),
177 phone(property.phone),
178 realName(property.realName),
179 credit(property.credit),
180 creditExpire(property.creditExpire),
182 userdata0(property.userdata0),
183 userdata1(property.userdata1),
184 userdata2(property.userdata2),
185 userdata3(property.userdata3),
186 userdata4(property.userdata4),
187 userdata5(property.userdata5),
188 userdata6(property.userdata6),
189 userdata7(property.userdata7),
190 userdata8(property.userdata8),
191 userdata9(property.userdata9),
192 passiveNotifier(this),
193 tariffNotifier(this),
199 password = "*_EMPTY_PASSWORD_*";
200 tariffName = NO_TARIFF_NAME;
204 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
205 lastWriteDetailedStat = stgTime;
207 property.tariffName.AddBeforeNotifier(&tariffNotifier);
208 property.passive.AddBeforeNotifier(&passiveNotifier);
209 property.cash.AddBeforeNotifier(&cashNotifier);
210 ips.AddAfterNotifier(&ipNotifier);
212 lastScanMessages = 0;
214 pthread_mutexattr_t attr;
215 pthread_mutexattr_init(&attr);
216 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
217 pthread_mutex_init(&mutex, &attr);
220 //-----------------------------------------------------------------------------
221 USER_IMPL::USER_IMPL(const USER_IMPL & u)
224 property(u.settings->GetScriptsDir()),
225 WriteServLog(GetStgLogger()),
228 __connected(u.__connected),
229 connected(__connected),
230 __currIP(u.__currIP),
232 lastIPForDisconnect(0),
233 pingTime(u.pingTime),
234 sysAdmin(u.sysAdmin),
241 lastCashAdd(property.lastCashAdd),
242 passiveTime(property.passiveTime),
243 lastCashAddTime(property.lastCashAddTime),
244 freeMb(property.freeMb),
245 lastActivityTime(property.lastActivityTime),
246 password(property.password),
247 passive(property.passive),
248 disabled(property.disabled),
249 disabledDetailStat(property.disabledDetailStat),
250 alwaysOnline(property.alwaysOnline),
251 tariffName(property.tariffName),
252 nextTariff(property.nextTariff),
253 address(property.address),
255 group(property.group),
256 email(property.email),
257 phone(property.phone),
258 realName(property.realName),
259 credit(property.credit),
260 creditExpire(property.creditExpire),
262 userdata0(property.userdata0),
263 userdata1(property.userdata1),
264 userdata2(property.userdata2),
265 userdata3(property.userdata3),
266 userdata4(property.userdata4),
267 userdata5(property.userdata5),
268 userdata6(property.userdata6),
269 userdata7(property.userdata7),
270 userdata8(property.userdata8),
271 userdata9(property.userdata9),
272 passiveNotifier(this),
273 tariffNotifier(this),
284 lastWriteStat = u.lastWriteStat;
285 lastWriteDetailedStat = u.lastWriteDetailedStat;
287 settings = u.settings;
289 property.tariffName.AddBeforeNotifier(&tariffNotifier);
290 property.passive.AddBeforeNotifier(&passiveNotifier);
291 property.cash.AddBeforeNotifier(&cashNotifier);
292 ips.AddAfterNotifier(&ipNotifier);
294 lastScanMessages = 0;
296 property.SetProperties(u.property);
298 pthread_mutexattr_t attr;
299 pthread_mutexattr_init(&attr);
300 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
301 pthread_mutex_init(&mutex, &attr);
303 //-----------------------------------------------------------------------------
304 USER_IMPL::~USER_IMPL()
306 property.passive.DelBeforeNotifier(&passiveNotifier);
307 property.tariffName.DelBeforeNotifier(&tariffNotifier);
308 pthread_mutex_destroy(&mutex);
310 //-----------------------------------------------------------------------------
311 void USER_IMPL::SetLogin(string const & l)
313 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
314 assert(login.empty() && "Login is already set");
316 id = userIDGenerator.GetNextID();
318 //-----------------------------------------------------------------------------
319 int USER_IMPL::ReadConf()
321 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
324 if (store->RestoreUserConf(&conf, login))
326 WriteServLog("Cannot read conf for user %s.", login.c_str());
327 WriteServLog("%s", store->GetStrError().c_str());
328 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
329 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
333 property.SetConf(conf);
335 tariff = tariffs->FindByName(tariffName);
338 WriteServLog("Cannot read user %s. Tariff %s not exist.",
339 login.c_str(), property.tariffName.Get().c_str());
343 std::vector<STG_MSG_HDR> hdrsList;
345 if (store->GetMessageHdrs(&hdrsList, login))
347 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
348 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
350 store->GetStrError().c_str());
354 std::vector<STG_MSG_HDR>::const_iterator it;
355 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
358 if (store->GetMessage(it->id, &msg, login) == 0)
360 messages.push_back(msg);
366 //-----------------------------------------------------------------------------
367 int USER_IMPL::ReadStat()
369 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
372 if (store->RestoreUserStat(&stat, login))
374 WriteServLog("Cannot read stat for user %s.", login.c_str());
375 WriteServLog("%s", store->GetStrError().c_str());
376 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
377 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
381 property.SetStat(stat);
385 //-----------------------------------------------------------------------------
386 int USER_IMPL::WriteConf()
388 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
389 USER_CONF conf(property.GetConf());
391 printfd(__FILE__, "USER::WriteConf()\n");
393 if (store->SaveUserConf(conf, login))
395 WriteServLog("Cannot write conf for user %s.", login.c_str());
396 WriteServLog("%s", store->GetStrError().c_str());
397 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
398 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
404 //-----------------------------------------------------------------------------
405 int USER_IMPL::WriteStat()
407 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
408 USER_STAT stat(property.GetStat());
410 if (store->SaveUserStat(stat, login))
412 WriteServLog("Cannot write stat for user %s.", login.c_str());
413 WriteServLog("%s", store->GetStrError().c_str());
414 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
415 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
419 lastWriteStat = stgTime;
423 //-----------------------------------------------------------------------------
424 int USER_IMPL::WriteMonthStat()
426 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
427 time_t tt = stgTime - 3600;
429 localtime_r(&tt, &t1);
431 USER_STAT stat(property.GetStat());
432 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
434 WriteServLog("Cannot write month stat for user %s.", login.c_str());
435 WriteServLog("%s", store->GetStrError().c_str());
436 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
437 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
443 //-----------------------------------------------------------------------------
444 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
446 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
448 * Authorize user. It only means that user will be authorized. Nothing more.
449 * User can be connected or disconnected while authorized.
450 * Example: user is authorized but disconnected due to 0 money or blocking
454 * Prevent double authorization by identical authorizers
456 if (authorizedBy.find(auth) != authorizedBy.end())
462 for (int i = 0; i < DIR_NUM; i++)
464 enabledDirs[i] = dirs & (1 << i);
467 if (authorizedBy.size())
471 // We are already authorized, but with different IP address
472 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
477 if (!users->FindByIPIdx(ip, &u))
479 // Address is already present in IP-index
480 // If it's not our IP - throw an error
483 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
490 if (users->IsIPInIndex(ip))
492 // Address is already present in IP-index
493 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
497 if (ips.ConstData().IsIPInIPS(ip))
500 lastIPForDisconnect = currIP;
504 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
505 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
510 authorizedBy.insert(auth);
516 //-----------------------------------------------------------------------------
517 void USER_IMPL::Unauthorize(const AUTH * auth)
519 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
521 * Authorizer tries to unauthorize user, that was not authorized by it
523 if (!authorizedBy.erase(auth))
526 if (authorizedBy.empty())
528 lastIPForDisconnect = currIP;
529 currIP = 0; // DelUser in traffcounter
533 //-----------------------------------------------------------------------------
534 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
536 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
537 // Is this user authorized by specified authorizer?
538 return authorizedBy.find(auth) != authorizedBy.end();
540 //-----------------------------------------------------------------------------
541 void USER_IMPL::Connect(bool fakeConnect)
544 * Connect user to Internet. This function is differ from Authorize() !!!
547 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
551 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
553 if (access(scriptOnConnect.c_str(), X_OK) == 0)
555 char dirsStr[DIR_NUM + 1];
556 dirsStr[DIR_NUM] = 0;
557 for (int i = 0; i < DIR_NUM; i++)
559 dirsStr[i] = enabledDirs[i] ? '1' : '0';
562 string scriptOnConnectParams;
563 strprintf(&scriptOnConnectParams,
564 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
565 scriptOnConnect.c_str(),
567 inet_ntostring(currIP).c_str(),
572 ScriptExec(scriptOnConnectParams.c_str());
576 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
582 if (store->WriteUserConnect(login, currIP))
584 WriteServLog("Cannot write connect for user %s.", login.c_str());
585 WriteServLog("%s", store->GetStrError().c_str());
589 lastIPForDisconnect = currIP;
591 //-----------------------------------------------------------------------------
592 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
595 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
598 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
600 if (!lastIPForDisconnect)
602 printfd(__FILE__, "lastIPForDisconnect\n");
608 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
610 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
612 char dirsStr[DIR_NUM + 1];
613 dirsStr[DIR_NUM] = 0;
614 for (int i = 0; i < DIR_NUM; i++)
616 dirsStr[i] = enabledDirs[i] ? '1' : '0';
619 string scriptOnDisonnectParams;
620 strprintf(&scriptOnDisonnectParams,
621 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
622 scriptOnDisonnect.c_str(),
624 inet_ntostring(lastIPForDisconnect).c_str(),
629 ScriptExec(scriptOnDisonnectParams.c_str());
633 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
639 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
641 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
642 WriteServLog("%s", store->GetStrError().c_str());
646 lastIPForDisconnect = 0;
648 DIR_TRAFF zeroSesssion;
650 sessionUpload = zeroSesssion;
651 sessionDownload = zeroSesssion;
653 //-----------------------------------------------------------------------------
654 void USER_IMPL::PrintUser() const
657 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
658 cout << "============================================================" << endl;
659 cout << "id=" << id << endl;
660 cout << "login=" << login << endl;
661 cout << "password=" << password << endl;
662 cout << "passive=" << passive << endl;
663 cout << "disabled=" << disabled << endl;
664 cout << "disabledDetailStat=" << disabledDetailStat << endl;
665 cout << "alwaysOnline=" << alwaysOnline << endl;
666 cout << "tariffName=" << tariffName << endl;
667 cout << "address=" << address << endl;
668 cout << "phone=" << phone << endl;
669 cout << "email=" << email << endl;
670 cout << "note=" << note << endl;
671 cout << "realName=" <<realName << endl;
672 cout << "group=" << group << endl;
673 cout << "credit=" << credit << endl;
674 cout << "nextTariff=" << nextTariff << endl;
675 cout << "userdata0" << userdata0 << endl;
676 cout << "userdata1" << userdata1 << endl;
677 cout << "creditExpire=" << creditExpire << endl;
678 cout << "ips=" << ips << endl;
679 cout << "------------------------" << endl;
680 cout << "up=" << up << endl;
681 cout << "down=" << down << endl;
682 cout << "cash=" << cash << endl;
683 cout << "freeMb=" << freeMb << endl;
684 cout << "lastCashAdd=" << lastCashAdd << endl;
685 cout << "lastCashAddTime=" << lastCashAddTime << endl;
686 cout << "passiveTime=" << passiveTime << endl;
687 cout << "lastActivityTime=" << lastActivityTime << endl;
688 cout << "============================================================" << endl;
690 //-----------------------------------------------------------------------------
691 void USER_IMPL::Run()
693 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
695 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
697 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
700 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
702 WriteServLog("User: %s. Credit expired.", login.c_str());
708 if (passive.ConstData()
709 && (stgTime % 30 == 0)
710 && (passiveTime.ModificationTime() != stgTime))
712 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
713 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
716 if (!authorizedBy.empty())
720 property.Stat().lastActivityTime = stgTime;
722 if (!connected && IsInetable())
726 if (connected && !IsInetable())
729 Disconnect(false, "disabled");
731 Disconnect(false, "passive");
733 Disconnect(false, "no cash");
736 if (stgTime - lastScanMessages > 10)
739 lastScanMessages = stgTime;
746 Disconnect(false, "not authorized");
751 //-----------------------------------------------------------------------------
752 void USER_IMPL::UpdatePingTime(time_t t)
754 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
755 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
761 //-----------------------------------------------------------------------------
762 bool USER_IMPL::IsInetable()
764 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
766 if (disabled || passive)
769 if (settings->GetFreeMbAllowInet())
775 if (settings->GetShowFeeInCash() || tariff == NULL)
777 return (cash >= -credit);
780 return (cash - tariff->GetFee() >= -credit);
782 //-----------------------------------------------------------------------------
783 string USER_IMPL::GetEnabledDirs()
785 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
788 for(int i = 0; i < DIR_NUM; i++)
789 dirs += enabledDirs[i] ? "1" : "0";
792 //-----------------------------------------------------------------------------
793 #ifdef TRAFF_STAT_WITH_PORTS
794 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
796 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
799 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
801 if (!connected || tariff == NULL)
807 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
808 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
812 int tt = tariff->GetTraffType();
813 if (tt == TRAFF_UP ||
814 tt == TRAFF_UP_DOWN ||
815 // Check NEW traff data
816 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
819 if (traff < threshold &&
820 traff + len >= threshold)
822 // cash = partBeforeThreshold * priceBeforeThreshold +
823 // partAfterThreshold * priceAfterThreshold
824 int64_t before = threshold - traff; // Chunk part before threshold
825 int64_t after = len - before; // Chunk part after threshold
826 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
827 down.ConstData()[dir],
830 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
831 down.ConstData()[dir],
837 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
838 down.ConstData()[dir],
843 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
845 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
846 cost = dc - freeMb.ConstData();
848 // Direct access to internal data structures via friend-specifier
849 property.Stat().freeMb -= dc;
850 property.Stat().cash -= cost;
856 sessionUpload[dir] += len;
860 if (!settings->GetWriteFreeMbTraffCost() &&
861 freeMb.ConstData() >= 0)
864 #ifdef TRAFF_STAT_WITH_PORTS
865 IP_DIR_PAIR idp(ip, dir, port);
867 IP_DIR_PAIR idp(ip, dir);
870 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
871 lb = traffStat.lower_bound(idp);
872 if (lb == traffStat.end() || lb->first != idp)
875 pair<IP_DIR_PAIR, STAT_NODE>(idp,
876 STAT_NODE(len, 0, cost)));
880 lb->second.cash += cost;
881 lb->second.up += len;
884 //-----------------------------------------------------------------------------
885 #ifdef TRAFF_STAT_WITH_PORTS
886 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
888 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
891 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
893 if (!connected || tariff == NULL)
899 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
900 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
904 int tt = tariff->GetTraffType();
905 if (tt == TRAFF_DOWN ||
906 tt == TRAFF_UP_DOWN ||
907 // Check NEW traff data
908 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
911 if (traff < threshold &&
912 traff + len >= threshold)
914 // cash = partBeforeThreshold * priceBeforeThreshold +
915 // partAfterThreshold * priceAfterThreshold
916 int64_t before = threshold - traff; // Chunk part before threshold
917 int64_t after = len - before; // Chunk part after threshold
918 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
919 down.ConstData()[dir], // Traff before chunk
922 tariff->GetPriceWithTraffType(up.ConstData()[dir],
923 dt[dir], // Traff after chunk
929 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
930 down.ConstData()[dir],
935 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
937 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
938 cost = dc - freeMb.ConstData();
940 property.Stat().freeMb -= dc;
941 property.Stat().cash -= cost;
947 sessionDownload[dir] += len;
951 if (!settings->GetWriteFreeMbTraffCost() &&
952 freeMb.ConstData() >= 0)
955 #ifdef TRAFF_STAT_WITH_PORTS
956 IP_DIR_PAIR idp(ip, dir, port);
958 IP_DIR_PAIR idp(ip, dir);
961 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
962 lb = traffStat.lower_bound(idp);
963 if (lb == traffStat.end() || lb->first != idp)
966 pair<IP_DIR_PAIR, STAT_NODE>(idp,
967 STAT_NODE(0, len, cost)));
971 lb->second.cash += cost;
972 lb->second.down += len;
975 //-----------------------------------------------------------------------------
976 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
978 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
979 currIP.AddBeforeNotifier(n);
981 //-----------------------------------------------------------------------------
982 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
984 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
985 currIP.DelBeforeNotifier(n);
987 //-----------------------------------------------------------------------------
988 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
990 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
991 currIP.AddAfterNotifier(n);
993 //-----------------------------------------------------------------------------
994 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
996 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
997 currIP.DelAfterNotifier(n);
999 //-----------------------------------------------------------------------------
1000 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1002 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1003 connected.AddBeforeNotifier(n);
1005 //-----------------------------------------------------------------------------
1006 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1008 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1009 connected.DelBeforeNotifier(n);
1011 //-----------------------------------------------------------------------------
1012 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1014 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1015 connected.AddAfterNotifier(n);
1017 //-----------------------------------------------------------------------------
1018 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1020 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1021 connected.DelAfterNotifier(n);
1023 //-----------------------------------------------------------------------------
1024 void USER_IMPL::OnAdd()
1026 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1028 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1030 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1032 string scriptOnAddParams;
1033 strprintf(&scriptOnAddParams,
1035 scriptOnAdd.c_str(),
1038 ScriptExec(scriptOnAddParams.c_str());
1042 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1045 //-----------------------------------------------------------------------------
1046 void USER_IMPL::OnDelete()
1048 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1050 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1052 if (access(scriptOnDel.c_str(), X_OK) == 0)
1054 string scriptOnDelParams;
1055 strprintf(&scriptOnDelParams,
1057 scriptOnDel.c_str(),
1060 ScriptExec(scriptOnDelParams.c_str());
1064 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1069 //-----------------------------------------------------------------------------
1070 int USER_IMPL::WriteDetailStat(bool hard)
1072 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1074 if (!traffStatSaved.second.empty())
1076 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1078 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1079 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1080 WriteServLog("%s", store->GetStrError().c_str());
1083 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1089 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1093 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1095 if (ts.size() && !disabledDetailStat)
1097 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1099 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1100 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1101 WriteServLog("%s", store->GetStrError().c_str());
1104 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1105 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1106 traffStatSaved.second.swap(ts);
1107 traffStatSaved.first = lastWriteDetailedStat;
1112 lastWriteDetailedStat = stgTime;
1115 //-----------------------------------------------------------------------------
1116 double USER_IMPL::GetPassiveTimePart() const
1118 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1120 static int daysInMonth[12] =
1121 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1125 localtime_r(&t, &tms);
1127 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1129 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1132 secMonth += 24 * 3600;
1135 int dt = secMonth - passiveTime;
1140 return double(dt) / (secMonth);
1142 //-----------------------------------------------------------------------------
1143 void USER_IMPL::SetPassiveTimeAsNewUser()
1145 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1149 localtime_r(&t, &tm);
1150 int daysCurrMon = DaysInCurrentMonth();
1151 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1153 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1155 //-----------------------------------------------------------------------------
1156 void USER_IMPL::MidnightResetSessionStat()
1158 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1162 Disconnect(true, "fake");
1166 //-----------------------------------------------------------------------------
1167 void USER_IMPL::ProcessNewMonth()
1169 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1173 Disconnect(true, "fake");
1175 DIR_TRAFF zeroTarff;
1188 if (nextTariff.ConstData() != "")
1191 nt = tariffs->FindByName(nextTariff);
1194 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1195 login.c_str(), property.tariffName.Get().c_str());
1199 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1206 //-----------------------------------------------------------------------------
1207 void USER_IMPL::ProcessDayFeeSpread()
1209 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1211 if (passive.ConstData() || tariff == NULL)
1214 double fee = tariff->GetFee() / DaysInCurrentMonth();
1220 switch (settings->GetFeeChargeType())
1223 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1227 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1231 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1236 //-----------------------------------------------------------------------------
1237 void USER_IMPL::ProcessDayFee()
1239 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1244 double passiveTimePart = 1.0;
1245 if (!settings->GetFullFee())
1247 passiveTimePart = GetPassiveTimePart();
1251 if (passive.ConstData())
1253 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1257 double fee = tariff->GetFee() * passiveTimePart;
1268 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1273 switch (settings->GetFeeChargeType())
1276 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1282 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1289 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1295 //-----------------------------------------------------------------------------
1296 void USER_IMPL::SetPrepaidTraff()
1299 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1301 //-----------------------------------------------------------------------------
1302 int USER_IMPL::AddMessage(STG_MSG * msg)
1304 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1306 if (SendMessage(*msg))
1308 if (store->AddMessage(msg, login))
1310 errorStr = store->GetStrError();
1311 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1312 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1315 messages.push_back(*msg);
1319 if (msg->header.repeat > 0)
1321 msg->header.repeat--;
1323 //TODO: gcc v. 4.x generate ICE on x86_64
1324 msg->header.lastSendTime = time(NULL);
1326 msg->header.lastSendTime = stgTime;
1328 if (store->AddMessage(msg, login))
1330 errorStr = store->GetStrError();
1331 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1332 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1335 messages.push_back(*msg);
1340 //-----------------------------------------------------------------------------
1341 int USER_IMPL::SendMessage(STG_MSG & msg) const
1343 // No lock `cause we are already locked from caller
1345 set<const AUTH*>::iterator it(authorizedBy.begin());
1346 while (it != authorizedBy.end())
1348 if (!(*it++)->SendMessage(msg, currIP))
1354 //TODO: gcc v. 4.x generate ICE on x86_64
1355 msg.header.lastSendTime = time(NULL);
1357 msg.header.lastSendTime = stgTime;
1359 msg.header.repeat--;
1363 //-----------------------------------------------------------------------------
1364 void USER_IMPL::ScanMessage()
1366 // No lock `cause we are already locked from caller
1367 // We need not check for the authorizedBy `cause it has already checked by caller
1369 std::list<STG_MSG>::iterator it(messages.begin());
1370 while (it != messages.end())
1372 if (settings->GetMessageTimeout() > 0 &&
1373 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1376 if (store->DelMessage(it->header.id, login))
1378 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1379 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1381 messages.erase(it++);
1384 if (it->GetNextSendTime() <= stgTime)
1386 if (SendMessage(*it))
1388 // We need to check all messages in queue for timeout
1392 if (it->header.repeat < 0)
1394 if (store->DelMessage(it->header.id, login))
1396 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1397 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1399 messages.erase(it++);
1403 if (store->EditMessage(*it, login))
1405 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1406 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1417 //-----------------------------------------------------------------------------
1418 //-----------------------------------------------------------------------------
1419 //-----------------------------------------------------------------------------
1420 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1422 if (newPassive && !oldPassive && user->tariff != NULL)
1423 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1429 //-----------------------------------------------------------------------------
1430 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1432 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1433 user->Disconnect(false, "Change tariff");
1434 user->tariff = user->tariffs->FindByName(newTariff);
1435 if (user->settings->GetReconnectOnTariffChange() &&
1436 !user->authorizedBy.empty() &&
1438 user->Connect(false);
1440 //-----------------------------------------------------------------------------
1441 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1443 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1444 user->lastCashAdd = newCash - oldCash;
1446 //-----------------------------------------------------------------------------
1447 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1449 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1450 if (user->connected)
1451 user->Disconnect(false, "Change IP");
1452 if (!user->authorizedBy.empty() && user->IsInetable())
1453 user->Connect(false);
1455 //-----------------------------------------------------------------------------