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());
351 std::vector<STG_MSG_HDR>::const_iterator it;
352 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
355 if (store->GetMessage(it->id, &msg, login) == 0)
357 messages.push_back(msg);
363 //-----------------------------------------------------------------------------
364 int USER_IMPL::ReadStat()
366 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
369 if (store->RestoreUserStat(&stat, login))
371 WriteServLog("Cannot read stat for user %s.", login.c_str());
372 WriteServLog("%s", store->GetStrError().c_str());
373 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
374 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
378 property.SetStat(stat);
382 //-----------------------------------------------------------------------------
383 int USER_IMPL::WriteConf()
385 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
386 USER_CONF conf(property.GetConf());
388 printfd(__FILE__, "USER::WriteConf()\n");
390 if (store->SaveUserConf(conf, login))
392 WriteServLog("Cannot write conf for user %s.", login.c_str());
393 WriteServLog("%s", store->GetStrError().c_str());
394 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
395 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
401 //-----------------------------------------------------------------------------
402 int USER_IMPL::WriteStat()
404 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
405 USER_STAT stat(property.GetStat());
407 if (store->SaveUserStat(stat, login))
409 WriteServLog("Cannot write stat for user %s.", login.c_str());
410 WriteServLog("%s", store->GetStrError().c_str());
411 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
412 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
416 lastWriteStat = stgTime;
420 //-----------------------------------------------------------------------------
421 int USER_IMPL::WriteMonthStat()
423 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
424 time_t tt = stgTime - 3600;
426 localtime_r(&tt, &t1);
428 USER_STAT stat(property.GetStat());
429 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
431 WriteServLog("Cannot write month stat for user %s.", login.c_str());
432 WriteServLog("%s", store->GetStrError().c_str());
433 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
434 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
440 //-----------------------------------------------------------------------------
441 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
443 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
445 * Authorize user. It only means that user will be authorized. Nothing more.
446 * User can be connected or disconnected while authorized.
447 * Example: user is authorized but disconnected due to 0 money or blocking
451 * Prevent double authorization by identical authorizers
453 if (authorizedBy.find(auth) != authorizedBy.end())
459 for (int i = 0; i < DIR_NUM; i++)
461 enabledDirs[i] = dirs & (1 << i);
464 if (authorizedBy.size())
468 // We are already authorized, but with different IP address
469 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
474 if (!users->FindByIPIdx(ip, &u))
476 // Address is already present in IP-index
477 // If it's not our IP - throw an error
480 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
487 if (users->IsIPInIndex(ip))
489 // Address is already present in IP-index
490 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
494 if (ips.ConstData().IsIPInIPS(ip))
497 lastIPForDisconnect = currIP;
501 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
502 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
507 authorizedBy.insert(auth);
513 //-----------------------------------------------------------------------------
514 void USER_IMPL::Unauthorize(const AUTH * auth)
516 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
518 * Authorizer tries to unauthorize user, that was not authorized by it
520 if (!authorizedBy.erase(auth))
523 if (authorizedBy.empty())
525 lastIPForDisconnect = currIP;
526 currIP = 0; // DelUser in traffcounter
530 //-----------------------------------------------------------------------------
531 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
533 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
534 // Is this user authorized by specified authorizer?
535 return authorizedBy.find(auth) != authorizedBy.end();
537 //-----------------------------------------------------------------------------
538 void USER_IMPL::Connect(bool fakeConnect)
541 * Connect user to Internet. This function is differ from Authorize() !!!
544 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
548 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
550 if (access(scriptOnConnect.c_str(), X_OK) == 0)
552 char dirsStr[DIR_NUM + 1];
553 dirsStr[DIR_NUM] = 0;
554 for (int i = 0; i < DIR_NUM; i++)
556 dirsStr[i] = enabledDirs[i] ? '1' : '0';
559 string scriptOnConnectParams;
560 strprintf(&scriptOnConnectParams,
561 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
562 scriptOnConnect.c_str(),
564 inet_ntostring(currIP).c_str(),
569 ScriptExec(scriptOnConnectParams);
573 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
579 if (store->WriteUserConnect(login, currIP))
581 WriteServLog("Cannot write connect for user %s.", login.c_str());
582 WriteServLog("%s", store->GetStrError().c_str());
586 lastIPForDisconnect = currIP;
588 //-----------------------------------------------------------------------------
589 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
592 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
595 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
597 if (!lastIPForDisconnect)
599 printfd(__FILE__, "lastIPForDisconnect\n");
605 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
607 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
609 char dirsStr[DIR_NUM + 1];
610 dirsStr[DIR_NUM] = 0;
611 for (int i = 0; i < DIR_NUM; i++)
613 dirsStr[i] = enabledDirs[i] ? '1' : '0';
616 string scriptOnDisonnectParams;
617 strprintf(&scriptOnDisonnectParams,
618 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
619 scriptOnDisonnect.c_str(),
621 inet_ntostring(lastIPForDisconnect).c_str(),
626 ScriptExec(scriptOnDisonnectParams);
630 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
636 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
638 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
639 WriteServLog("%s", store->GetStrError().c_str());
643 lastIPForDisconnect = 0;
645 DIR_TRAFF zeroSesssion;
647 sessionUpload = zeroSesssion;
648 sessionDownload = zeroSesssion;
650 //-----------------------------------------------------------------------------
651 void USER_IMPL::PrintUser() const
654 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
655 cout << "============================================================" << endl;
656 cout << "id=" << id << endl;
657 cout << "login=" << login << endl;
658 cout << "password=" << password << endl;
659 cout << "passive=" << passive << endl;
660 cout << "disabled=" << disabled << endl;
661 cout << "disabledDetailStat=" << disabledDetailStat << endl;
662 cout << "alwaysOnline=" << alwaysOnline << endl;
663 cout << "tariffName=" << tariffName << endl;
664 cout << "address=" << address << endl;
665 cout << "phone=" << phone << endl;
666 cout << "email=" << email << endl;
667 cout << "note=" << note << endl;
668 cout << "realName=" <<realName << endl;
669 cout << "group=" << group << endl;
670 cout << "credit=" << credit << endl;
671 cout << "nextTariff=" << nextTariff << endl;
672 cout << "userdata0" << userdata0 << endl;
673 cout << "userdata1" << userdata1 << endl;
674 cout << "creditExpire=" << creditExpire << endl;
675 cout << "ips=" << ips << endl;
676 cout << "------------------------" << endl;
677 cout << "up=" << up << endl;
678 cout << "down=" << down << endl;
679 cout << "cash=" << cash << endl;
680 cout << "freeMb=" << freeMb << endl;
681 cout << "lastCashAdd=" << lastCashAdd << endl;
682 cout << "lastCashAddTime=" << lastCashAddTime << endl;
683 cout << "passiveTime=" << passiveTime << endl;
684 cout << "lastActivityTime=" << lastActivityTime << endl;
685 cout << "============================================================" << endl;
687 //-----------------------------------------------------------------------------
688 void USER_IMPL::Run()
690 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
692 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
694 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
697 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
699 WriteServLog("User: %s. Credit expired.", login.c_str());
705 if (passive.ConstData()
706 && (stgTime % 30 == 0)
707 && (passiveTime.ModificationTime() != stgTime))
709 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
710 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
713 if (!authorizedBy.empty())
717 property.Stat().lastActivityTime = stgTime;
719 if (!connected && IsInetable())
723 if (connected && !IsInetable())
726 Disconnect(false, "disabled");
728 Disconnect(false, "passive");
730 Disconnect(false, "no cash");
733 if (stgTime - lastScanMessages > 10)
736 lastScanMessages = stgTime;
743 Disconnect(false, "not authorized");
748 //-----------------------------------------------------------------------------
749 void USER_IMPL::UpdatePingTime(time_t t)
751 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
752 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
758 //-----------------------------------------------------------------------------
759 bool USER_IMPL::IsInetable()
761 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
763 if (disabled || passive)
766 if (settings->GetFreeMbAllowInet())
772 if (settings->GetShowFeeInCash() || tariff == NULL)
774 return (cash >= -credit);
777 return (cash - tariff->GetFee() >= -credit);
779 //-----------------------------------------------------------------------------
780 string USER_IMPL::GetEnabledDirs()
782 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
785 for(int i = 0; i < DIR_NUM; i++)
786 dirs += enabledDirs[i] ? "1" : "0";
789 //-----------------------------------------------------------------------------
790 #ifdef TRAFF_STAT_WITH_PORTS
791 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
793 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
796 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
798 if (!connected || tariff == NULL)
804 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
805 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
809 int tt = tariff->GetTraffType();
810 if (tt == TRAFF_UP ||
811 tt == TRAFF_UP_DOWN ||
812 // Check NEW traff data
813 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
816 if (traff < threshold &&
817 traff + len >= threshold)
819 // cash = partBeforeThreshold * priceBeforeThreshold +
820 // partAfterThreshold * priceAfterThreshold
821 int64_t before = threshold - traff; // Chunk part before threshold
822 int64_t after = len - before; // Chunk part after threshold
823 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
824 down.ConstData()[dir],
827 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
828 down.ConstData()[dir],
834 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
835 down.ConstData()[dir],
840 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
842 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
843 cost = dc - freeMb.ConstData();
845 // Direct access to internal data structures via friend-specifier
846 property.Stat().freeMb -= dc;
847 property.Stat().cash -= cost;
853 sessionUpload[dir] += len;
857 if (!settings->GetWriteFreeMbTraffCost() &&
858 freeMb.ConstData() >= 0)
861 #ifdef TRAFF_STAT_WITH_PORTS
862 IP_DIR_PAIR idp(ip, dir, port);
864 IP_DIR_PAIR idp(ip, dir);
867 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
868 lb = traffStat.lower_bound(idp);
869 if (lb == traffStat.end() || lb->first != idp)
872 pair<IP_DIR_PAIR, STAT_NODE>(idp,
873 STAT_NODE(len, 0, cost)));
877 lb->second.cash += cost;
878 lb->second.up += len;
881 //-----------------------------------------------------------------------------
882 #ifdef TRAFF_STAT_WITH_PORTS
883 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
885 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
888 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
890 if (!connected || tariff == NULL)
896 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
897 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
901 int tt = tariff->GetTraffType();
902 if (tt == TRAFF_DOWN ||
903 tt == TRAFF_UP_DOWN ||
904 // Check NEW traff data
905 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
908 if (traff < threshold &&
909 traff + len >= threshold)
911 // cash = partBeforeThreshold * priceBeforeThreshold +
912 // partAfterThreshold * priceAfterThreshold
913 int64_t before = threshold - traff; // Chunk part before threshold
914 int64_t after = len - before; // Chunk part after threshold
915 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
916 down.ConstData()[dir], // Traff before chunk
919 tariff->GetPriceWithTraffType(up.ConstData()[dir],
920 dt[dir], // Traff after chunk
926 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
927 down.ConstData()[dir],
932 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
934 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
935 cost = dc - freeMb.ConstData();
937 property.Stat().freeMb -= dc;
938 property.Stat().cash -= cost;
944 sessionDownload[dir] += len;
948 if (!settings->GetWriteFreeMbTraffCost() &&
949 freeMb.ConstData() >= 0)
952 #ifdef TRAFF_STAT_WITH_PORTS
953 IP_DIR_PAIR idp(ip, dir, port);
955 IP_DIR_PAIR idp(ip, dir);
958 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
959 lb = traffStat.lower_bound(idp);
960 if (lb == traffStat.end() || lb->first != idp)
963 pair<IP_DIR_PAIR, STAT_NODE>(idp,
964 STAT_NODE(0, len, cost)));
968 lb->second.cash += cost;
969 lb->second.down += len;
972 //-----------------------------------------------------------------------------
973 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
975 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
976 currIP.AddBeforeNotifier(n);
978 //-----------------------------------------------------------------------------
979 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
981 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
982 currIP.DelBeforeNotifier(n);
984 //-----------------------------------------------------------------------------
985 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
987 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
988 currIP.AddAfterNotifier(n);
990 //-----------------------------------------------------------------------------
991 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
993 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
994 currIP.DelAfterNotifier(n);
996 //-----------------------------------------------------------------------------
997 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
999 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1000 connected.AddBeforeNotifier(n);
1002 //-----------------------------------------------------------------------------
1003 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1005 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1006 connected.DelBeforeNotifier(n);
1008 //-----------------------------------------------------------------------------
1009 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1011 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1012 connected.AddAfterNotifier(n);
1014 //-----------------------------------------------------------------------------
1015 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1017 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1018 connected.DelAfterNotifier(n);
1020 //-----------------------------------------------------------------------------
1021 void USER_IMPL::OnAdd()
1023 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1025 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1027 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1029 string scriptOnAddParams;
1030 strprintf(&scriptOnAddParams,
1032 scriptOnAdd.c_str(),
1035 ScriptExec(scriptOnAddParams);
1039 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1042 //-----------------------------------------------------------------------------
1043 void USER_IMPL::OnDelete()
1045 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1047 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1049 if (access(scriptOnDel.c_str(), X_OK) == 0)
1051 string scriptOnDelParams;
1052 strprintf(&scriptOnDelParams,
1054 scriptOnDel.c_str(),
1057 ScriptExec(scriptOnDelParams);
1061 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1066 //-----------------------------------------------------------------------------
1067 int USER_IMPL::WriteDetailStat(bool hard)
1069 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1071 if (!traffStatSaved.second.empty())
1073 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1075 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1076 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1077 WriteServLog("%s", store->GetStrError().c_str());
1080 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1086 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1090 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1092 if (ts.size() && !disabledDetailStat)
1094 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1096 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1097 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1098 WriteServLog("%s", store->GetStrError().c_str());
1101 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1102 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1103 traffStatSaved.second.swap(ts);
1104 traffStatSaved.first = lastWriteDetailedStat;
1109 lastWriteDetailedStat = stgTime;
1112 //-----------------------------------------------------------------------------
1113 double USER_IMPL::GetPassiveTimePart() const
1115 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1117 static int daysInMonth[12] =
1118 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1122 localtime_r(&t, &tms);
1124 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1126 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1129 secMonth += 24 * 3600;
1132 int dt = secMonth - passiveTime;
1137 return double(dt) / (secMonth);
1139 //-----------------------------------------------------------------------------
1140 void USER_IMPL::SetPassiveTimeAsNewUser()
1142 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1146 localtime_r(&t, &tm);
1147 int daysCurrMon = DaysInCurrentMonth();
1148 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1150 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1152 //-----------------------------------------------------------------------------
1153 void USER_IMPL::MidnightResetSessionStat()
1155 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1159 Disconnect(true, "fake");
1163 //-----------------------------------------------------------------------------
1164 void USER_IMPL::ProcessNewMonth()
1166 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1170 Disconnect(true, "fake");
1172 DIR_TRAFF zeroTarff;
1185 if (nextTariff.ConstData() != "")
1188 nt = tariffs->FindByName(nextTariff);
1191 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1192 login.c_str(), property.tariffName.Get().c_str());
1196 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1203 //-----------------------------------------------------------------------------
1204 void USER_IMPL::ProcessDayFeeSpread()
1206 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1208 if (passive.ConstData() || tariff == NULL)
1211 double fee = tariff->GetFee() / DaysInCurrentMonth();
1217 switch (settings->GetFeeChargeType())
1220 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1224 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1228 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1233 //-----------------------------------------------------------------------------
1234 void USER_IMPL::ProcessDayFee()
1236 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1241 double passiveTimePart = 1.0;
1242 if (!settings->GetFullFee())
1244 passiveTimePart = GetPassiveTimePart();
1248 if (passive.ConstData())
1250 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1254 double fee = tariff->GetFee() * passiveTimePart;
1265 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1270 switch (settings->GetFeeChargeType())
1273 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1279 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1286 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1292 //-----------------------------------------------------------------------------
1293 void USER_IMPL::SetPrepaidTraff()
1296 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1298 //-----------------------------------------------------------------------------
1299 int USER_IMPL::AddMessage(STG_MSG * msg)
1301 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1303 if (SendMessage(*msg))
1305 if (store->AddMessage(msg, login))
1307 errorStr = store->GetStrError();
1308 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1309 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1312 messages.push_back(*msg);
1316 if (msg->header.repeat > 0)
1318 msg->header.repeat--;
1320 //TODO: gcc v. 4.x generate ICE on x86_64
1321 msg->header.lastSendTime = time(NULL);
1323 msg->header.lastSendTime = stgTime;
1325 if (store->AddMessage(msg, login))
1327 errorStr = store->GetStrError();
1328 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1329 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1332 messages.push_back(*msg);
1337 //-----------------------------------------------------------------------------
1338 int USER_IMPL::SendMessage(STG_MSG & msg) const
1340 // No lock `cause we are already locked from caller
1342 set<const AUTH*>::iterator it(authorizedBy.begin());
1343 while (it != authorizedBy.end())
1345 if (!(*it++)->SendMessage(msg, currIP))
1351 //TODO: gcc v. 4.x generate ICE on x86_64
1352 msg.header.lastSendTime = time(NULL);
1354 msg.header.lastSendTime = stgTime;
1356 msg.header.repeat--;
1360 //-----------------------------------------------------------------------------
1361 void USER_IMPL::ScanMessage()
1363 // No lock `cause we are already locked from caller
1364 // We need not check for the authorizedBy `cause it has already checked by caller
1366 std::list<STG_MSG>::iterator it(messages.begin());
1367 while (it != messages.end())
1369 if (settings->GetMessageTimeout() > 0 &&
1370 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1373 if (store->DelMessage(it->header.id, login))
1375 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1376 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1378 messages.erase(it++);
1381 if (it->GetNextSendTime() <= stgTime)
1383 if (SendMessage(*it))
1385 // We need to check all messages in queue for timeout
1389 if (it->header.repeat < 0)
1391 if (store->DelMessage(it->header.id, login))
1393 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1394 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1396 messages.erase(it++);
1400 if (store->EditMessage(*it, login))
1402 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1403 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1414 //-----------------------------------------------------------------------------
1415 //-----------------------------------------------------------------------------
1416 //-----------------------------------------------------------------------------
1417 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1419 if (newPassive && !oldPassive && user->tariff != NULL)
1420 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1426 //-----------------------------------------------------------------------------
1427 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1429 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1430 user->Disconnect(false, "Change tariff");
1431 user->tariff = user->tariffs->FindByName(newTariff);
1432 if (user->settings->GetReconnectOnTariffChange() &&
1433 !user->authorizedBy.empty() &&
1435 user->Connect(false);
1437 //-----------------------------------------------------------------------------
1438 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1440 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1441 user->lastCashAdd = newCash - oldCash;
1443 //-----------------------------------------------------------------------------
1444 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1446 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1447 if (user->connected)
1448 user->Disconnect(false, "Change IP");
1449 if (!user->authorizedBy.empty() && user->IsInetable())
1450 user->Connect(false);
1452 //-----------------------------------------------------------------------------