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,
58 property(s->GetScriptsDir()),
59 WriteServLog(GetStgLogger()),
63 connected(__connected),
67 lastIPForDisconnect(0),
76 lastCashAdd(property.lastCashAdd),
77 passiveTime(property.passiveTime),
78 lastCashAddTime(property.lastCashAddTime),
79 freeMb(property.freeMb),
80 lastActivityTime(property.lastActivityTime),
81 password(property.password),
82 passive(property.passive),
83 disabled(property.disabled),
84 disabledDetailStat(property.disabledDetailStat),
85 alwaysOnline(property.alwaysOnline),
86 tariffName(property.tariffName),
87 nextTariff(property.nextTariff),
88 address(property.address),
90 group(property.group),
91 email(property.email),
92 phone(property.phone),
93 realName(property.realName),
94 credit(property.credit),
95 creditExpire(property.creditExpire),
97 userdata0(property.userdata0),
98 userdata1(property.userdata1),
99 userdata2(property.userdata2),
100 userdata3(property.userdata3),
101 userdata4(property.userdata4),
102 userdata5(property.userdata5),
103 userdata6(property.userdata6),
104 userdata7(property.userdata7),
105 userdata8(property.userdata8),
106 userdata9(property.userdata9),
107 passiveNotifier(this),
108 tariffNotifier(this),
114 password = "*_EMPTY_PASSWORD_*";
115 tariffName = NO_TARIFF_NAME;
119 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
120 lastWriteDetailedStat = stgTime;
122 property.tariffName.AddBeforeNotifier(&tariffNotifier);
123 property.passive.AddBeforeNotifier(&passiveNotifier);
124 property.cash.AddBeforeNotifier(&cashNotifier);
125 ips.AddAfterNotifier(&ipNotifier);
127 lastScanMessages = 0;
129 pthread_mutexattr_t attr;
130 pthread_mutexattr_init(&attr);
131 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
132 pthread_mutex_init(&mutex, &attr);
135 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
141 property(s->GetScriptsDir()),
142 WriteServLog(GetStgLogger()),
146 connected(__connected),
150 lastIPForDisconnect(0),
159 lastCashAdd(property.lastCashAdd),
160 passiveTime(property.passiveTime),
161 lastCashAddTime(property.lastCashAddTime),
162 freeMb(property.freeMb),
163 lastActivityTime(property.lastActivityTime),
164 password(property.password),
165 passive(property.passive),
166 disabled(property.disabled),
167 disabledDetailStat(property.disabledDetailStat),
168 alwaysOnline(property.alwaysOnline),
169 tariffName(property.tariffName),
170 nextTariff(property.nextTariff),
171 address(property.address),
173 group(property.group),
174 email(property.email),
175 phone(property.phone),
176 realName(property.realName),
177 credit(property.credit),
178 creditExpire(property.creditExpire),
180 userdata0(property.userdata0),
181 userdata1(property.userdata1),
182 userdata2(property.userdata2),
183 userdata3(property.userdata3),
184 userdata4(property.userdata4),
185 userdata5(property.userdata5),
186 userdata6(property.userdata6),
187 userdata7(property.userdata7),
188 userdata8(property.userdata8),
189 userdata9(property.userdata9),
190 passiveNotifier(this),
191 tariffNotifier(this),
197 password = "*_EMPTY_PASSWORD_*";
198 tariffName = NO_TARIFF_NAME;
202 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
203 lastWriteDetailedStat = stgTime;
205 property.tariffName.AddBeforeNotifier(&tariffNotifier);
206 property.passive.AddBeforeNotifier(&passiveNotifier);
207 property.cash.AddBeforeNotifier(&cashNotifier);
208 ips.AddAfterNotifier(&ipNotifier);
210 lastScanMessages = 0;
212 pthread_mutexattr_t attr;
213 pthread_mutexattr_init(&attr);
214 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
215 pthread_mutex_init(&mutex, &attr);
218 //-----------------------------------------------------------------------------
219 USER_IMPL::USER_IMPL(const USER_IMPL & u)
221 property(u.settings->GetScriptsDir()),
222 WriteServLog(GetStgLogger()),
225 __connected(u.__connected),
226 connected(__connected),
227 __currIP(u.__currIP),
229 lastIPForDisconnect(0),
230 pingTime(u.pingTime),
231 sysAdmin(u.sysAdmin),
238 lastCashAdd(property.lastCashAdd),
239 passiveTime(property.passiveTime),
240 lastCashAddTime(property.lastCashAddTime),
241 freeMb(property.freeMb),
242 lastActivityTime(property.lastActivityTime),
243 password(property.password),
244 passive(property.passive),
245 disabled(property.disabled),
246 disabledDetailStat(property.disabledDetailStat),
247 alwaysOnline(property.alwaysOnline),
248 tariffName(property.tariffName),
249 nextTariff(property.nextTariff),
250 address(property.address),
252 group(property.group),
253 email(property.email),
254 phone(property.phone),
255 realName(property.realName),
256 credit(property.credit),
257 creditExpire(property.creditExpire),
259 userdata0(property.userdata0),
260 userdata1(property.userdata1),
261 userdata2(property.userdata2),
262 userdata3(property.userdata3),
263 userdata4(property.userdata4),
264 userdata5(property.userdata5),
265 userdata6(property.userdata6),
266 userdata7(property.userdata7),
267 userdata8(property.userdata8),
268 userdata9(property.userdata9),
269 passiveNotifier(this),
270 tariffNotifier(this),
281 lastWriteStat = u.lastWriteStat;
282 lastWriteDetailedStat = u.lastWriteDetailedStat;
284 settings = u.settings;
286 property.tariffName.AddBeforeNotifier(&tariffNotifier);
287 property.passive.AddBeforeNotifier(&passiveNotifier);
288 property.cash.AddBeforeNotifier(&cashNotifier);
289 ips.AddAfterNotifier(&ipNotifier);
291 lastScanMessages = 0;
293 property.SetProperties(u.property);
295 pthread_mutexattr_t attr;
296 pthread_mutexattr_init(&attr);
297 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
298 pthread_mutex_init(&mutex, &attr);
300 //-----------------------------------------------------------------------------
301 USER_IMPL::~USER_IMPL()
303 property.passive.DelBeforeNotifier(&passiveNotifier);
304 property.tariffName.DelBeforeNotifier(&tariffNotifier);
305 pthread_mutex_destroy(&mutex);
307 //-----------------------------------------------------------------------------
308 void USER_IMPL::SetLogin(string const & l)
310 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
311 assert(login.empty() && "Login is already set");
313 id = userIDGenerator.GetNextID();
315 //-----------------------------------------------------------------------------
316 int USER_IMPL::ReadConf()
318 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
321 if (store->RestoreUserConf(&conf, login))
323 WriteServLog("Cannot read conf for user %s.", login.c_str());
324 WriteServLog("%s", store->GetStrError().c_str());
325 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
326 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
330 property.SetConf(conf);
332 tariff = tariffs->FindByName(tariffName);
335 WriteServLog("Cannot read user %s. Tariff %s not exist.",
336 login.c_str(), property.tariffName.Get().c_str());
340 std::vector<STG_MSG_HDR> hdrsList;
342 if (store->GetMessageHdrs(&hdrsList, login))
344 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
348 std::vector<STG_MSG_HDR>::const_iterator it;
349 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
352 if (store->GetMessage(it->id, &msg, login) == 0)
354 messages.push_back(msg);
360 //-----------------------------------------------------------------------------
361 int USER_IMPL::ReadStat()
363 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
366 if (store->RestoreUserStat(&stat, login))
368 WriteServLog("Cannot read stat for user %s.", login.c_str());
369 WriteServLog("%s", store->GetStrError().c_str());
370 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
371 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
375 property.SetStat(stat);
379 //-----------------------------------------------------------------------------
380 int USER_IMPL::WriteConf()
382 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
383 USER_CONF conf(property.GetConf());
385 printfd(__FILE__, "USER::WriteConf()\n");
387 if (store->SaveUserConf(conf, login))
389 WriteServLog("Cannot write conf for user %s.", login.c_str());
390 WriteServLog("%s", store->GetStrError().c_str());
391 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
392 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
398 //-----------------------------------------------------------------------------
399 int USER_IMPL::WriteStat()
401 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
402 USER_STAT stat(property.GetStat());
404 if (store->SaveUserStat(stat, login))
406 WriteServLog("Cannot write stat for user %s.", login.c_str());
407 WriteServLog("%s", store->GetStrError().c_str());
408 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
409 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
413 lastWriteStat = stgTime;
417 //-----------------------------------------------------------------------------
418 int USER_IMPL::WriteMonthStat()
420 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
421 time_t tt = stgTime - 3600;
423 localtime_r(&tt, &t1);
425 USER_STAT stat(property.GetStat());
426 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
428 WriteServLog("Cannot write month stat for user %s.", login.c_str());
429 WriteServLog("%s", store->GetStrError().c_str());
430 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
431 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
437 //-----------------------------------------------------------------------------
438 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
440 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
442 * Authorize user. It only means that user will be authorized. Nothing more.
443 * User can be connected or disconnected while authorized.
444 * Example: user is authorized but disconnected due to 0 money or blocking
448 * Prevent double authorization by identical authorizers
450 if (authorizedBy.find(auth) != authorizedBy.end())
456 for (int i = 0; i < DIR_NUM; i++)
458 enabledDirs[i] = dirs & (1 << i);
461 if (authorizedBy.size())
465 // We are already authorized, but with different IP address
466 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
471 if (!users->FindByIPIdx(ip, &u))
473 // Address is already present in IP-index
474 // If it's not our IP - throw an error
477 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
484 if (users->IsIPInIndex(ip))
486 // Address is already present in IP-index
487 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
491 if (ips.ConstData().IsIPInIPS(ip))
494 lastIPForDisconnect = currIP;
498 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
499 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
504 authorizedBy.insert(auth);
510 //-----------------------------------------------------------------------------
511 void USER_IMPL::Unauthorize(const AUTH * auth)
513 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
515 * Authorizer tries to unauthorize user, that was not authorized by it
517 if (!authorizedBy.erase(auth))
520 if (authorizedBy.empty())
522 lastIPForDisconnect = currIP;
523 currIP = 0; // DelUser in traffcounter
527 //-----------------------------------------------------------------------------
528 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
530 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
531 // Is this user authorized by specified authorizer?
532 return authorizedBy.find(auth) != authorizedBy.end();
534 //-----------------------------------------------------------------------------
535 void USER_IMPL::Connect(bool fakeConnect)
538 * Connect user to Internet. This function is differ from Authorize() !!!
541 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
545 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
547 if (access(scriptOnConnect.c_str(), X_OK) == 0)
549 char dirsStr[DIR_NUM + 1];
550 dirsStr[DIR_NUM] = 0;
551 for (int i = 0; i < DIR_NUM; i++)
553 dirsStr[i] = enabledDirs[i] ? '1' : '0';
556 string scriptOnConnectParams;
557 strprintf(&scriptOnConnectParams,
558 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
559 scriptOnConnect.c_str(),
561 inet_ntostring(currIP).c_str(),
566 ScriptExec(scriptOnConnectParams);
570 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
576 if (store->WriteUserConnect(login, currIP))
578 WriteServLog("Cannot write connect for user %s.", login.c_str());
579 WriteServLog("%s", store->GetStrError().c_str());
583 lastIPForDisconnect = currIP;
585 //-----------------------------------------------------------------------------
586 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
589 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
592 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
594 if (!lastIPForDisconnect)
596 printfd(__FILE__, "lastIPForDisconnect\n");
602 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
604 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
606 char dirsStr[DIR_NUM + 1];
607 dirsStr[DIR_NUM] = 0;
608 for (int i = 0; i < DIR_NUM; i++)
610 dirsStr[i] = enabledDirs[i] ? '1' : '0';
613 string scriptOnDisonnectParams;
614 strprintf(&scriptOnDisonnectParams,
615 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
616 scriptOnDisonnect.c_str(),
618 inet_ntostring(lastIPForDisconnect).c_str(),
623 ScriptExec(scriptOnDisonnectParams);
627 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
633 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
635 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
636 WriteServLog("%s", store->GetStrError().c_str());
640 lastIPForDisconnect = 0;
642 DIR_TRAFF zeroSesssion;
644 sessionUpload = zeroSesssion;
645 sessionDownload = zeroSesssion;
647 //-----------------------------------------------------------------------------
648 void USER_IMPL::PrintUser() const
651 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
652 cout << "============================================================" << endl;
653 cout << "id=" << id << endl;
654 cout << "login=" << login << endl;
655 cout << "password=" << password << endl;
656 cout << "passive=" << passive << endl;
657 cout << "disabled=" << disabled << endl;
658 cout << "disabledDetailStat=" << disabledDetailStat << endl;
659 cout << "alwaysOnline=" << alwaysOnline << endl;
660 cout << "tariffName=" << tariffName << endl;
661 cout << "address=" << address << endl;
662 cout << "phone=" << phone << endl;
663 cout << "email=" << email << endl;
664 cout << "note=" << note << endl;
665 cout << "realName=" <<realName << endl;
666 cout << "group=" << group << endl;
667 cout << "credit=" << credit << endl;
668 cout << "nextTariff=" << nextTariff << endl;
669 cout << "userdata0" << userdata0 << endl;
670 cout << "userdata1" << userdata1 << endl;
671 cout << "creditExpire=" << creditExpire << endl;
672 cout << "ips=" << ips << endl;
673 cout << "------------------------" << endl;
674 cout << "up=" << up << endl;
675 cout << "down=" << down << endl;
676 cout << "cash=" << cash << endl;
677 cout << "freeMb=" << freeMb << endl;
678 cout << "lastCashAdd=" << lastCashAdd << endl;
679 cout << "lastCashAddTime=" << lastCashAddTime << endl;
680 cout << "passiveTime=" << passiveTime << endl;
681 cout << "lastActivityTime=" << lastActivityTime << endl;
682 cout << "============================================================" << endl;
684 //-----------------------------------------------------------------------------
685 void USER_IMPL::Run()
687 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
689 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
691 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
694 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
696 WriteServLog("User: %s. Credit expired.", login.c_str());
702 if (passive.ConstData()
703 && (stgTime % 30 == 0)
704 && (passiveTime.ModificationTime() != stgTime))
706 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
707 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
710 if (!authorizedBy.empty())
714 property.Stat().lastActivityTime = stgTime;
716 if (!connected && IsInetable())
720 if (connected && !IsInetable())
723 Disconnect(false, "disabled");
725 Disconnect(false, "passive");
727 Disconnect(false, "no cash");
730 if (stgTime - lastScanMessages > 10)
733 lastScanMessages = stgTime;
740 Disconnect(false, "not authorized");
745 //-----------------------------------------------------------------------------
746 void USER_IMPL::UpdatePingTime(time_t t)
748 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
749 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
755 //-----------------------------------------------------------------------------
756 bool USER_IMPL::IsInetable()
758 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
760 if (disabled || passive)
763 if (settings->GetFreeMbAllowInet())
769 if (settings->GetShowFeeInCash() || tariff == NULL)
771 return (cash >= -credit);
774 return (cash - tariff->GetFee() >= -credit);
776 //-----------------------------------------------------------------------------
777 string USER_IMPL::GetEnabledDirs()
779 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
782 for(int i = 0; i < DIR_NUM; i++)
783 dirs += enabledDirs[i] ? "1" : "0";
786 //-----------------------------------------------------------------------------
787 #ifdef TRAFF_STAT_WITH_PORTS
788 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
790 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
793 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
795 if (!connected || tariff == NULL)
801 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
802 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
806 int tt = tariff->GetTraffType();
807 if (tt == TRAFF_UP ||
808 tt == TRAFF_UP_DOWN ||
809 // Check NEW traff data
810 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
813 if (traff < threshold &&
814 traff + len >= threshold)
816 // cash = partBeforeThreshold * priceBeforeThreshold +
817 // partAfterThreshold * priceAfterThreshold
818 int64_t before = threshold - traff; // Chunk part before threshold
819 int64_t after = len - before; // Chunk part after threshold
820 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
821 down.ConstData()[dir],
824 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
825 down.ConstData()[dir],
831 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
832 down.ConstData()[dir],
837 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
839 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
840 cost = dc - freeMb.ConstData();
842 // Direct access to internal data structures via friend-specifier
843 property.Stat().freeMb -= dc;
844 property.Stat().cash -= cost;
850 sessionUpload[dir] += len;
854 if (!settings->GetWriteFreeMbTraffCost() &&
855 freeMb.ConstData() >= 0)
858 #ifdef TRAFF_STAT_WITH_PORTS
859 IP_DIR_PAIR idp(ip, dir, port);
861 IP_DIR_PAIR idp(ip, dir);
864 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
865 lb = traffStat.lower_bound(idp);
866 if (lb == traffStat.end() || lb->first != idp)
869 pair<IP_DIR_PAIR, STAT_NODE>(idp,
870 STAT_NODE(len, 0, cost)));
874 lb->second.cash += cost;
875 lb->second.up += len;
878 //-----------------------------------------------------------------------------
879 #ifdef TRAFF_STAT_WITH_PORTS
880 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
882 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
885 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
887 if (!connected || tariff == NULL)
893 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
894 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
898 int tt = tariff->GetTraffType();
899 if (tt == TRAFF_DOWN ||
900 tt == TRAFF_UP_DOWN ||
901 // Check NEW traff data
902 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
905 if (traff < threshold &&
906 traff + len >= threshold)
908 // cash = partBeforeThreshold * priceBeforeThreshold +
909 // partAfterThreshold * priceAfterThreshold
910 int64_t before = threshold - traff; // Chunk part before threshold
911 int64_t after = len - before; // Chunk part after threshold
912 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
913 down.ConstData()[dir], // Traff before chunk
916 tariff->GetPriceWithTraffType(up.ConstData()[dir],
917 dt[dir], // Traff after chunk
923 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
924 down.ConstData()[dir],
929 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
931 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
932 cost = dc - freeMb.ConstData();
934 property.Stat().freeMb -= dc;
935 property.Stat().cash -= cost;
941 sessionDownload[dir] += len;
945 if (!settings->GetWriteFreeMbTraffCost() &&
946 freeMb.ConstData() >= 0)
949 #ifdef TRAFF_STAT_WITH_PORTS
950 IP_DIR_PAIR idp(ip, dir, port);
952 IP_DIR_PAIR idp(ip, dir);
955 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
956 lb = traffStat.lower_bound(idp);
957 if (lb == traffStat.end() || lb->first != idp)
960 pair<IP_DIR_PAIR, STAT_NODE>(idp,
961 STAT_NODE(0, len, cost)));
965 lb->second.cash += cost;
966 lb->second.down += len;
969 //-----------------------------------------------------------------------------
970 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
972 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
973 currIP.AddBeforeNotifier(n);
975 //-----------------------------------------------------------------------------
976 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
978 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
979 currIP.DelBeforeNotifier(n);
981 //-----------------------------------------------------------------------------
982 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
984 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
985 currIP.AddAfterNotifier(n);
987 //-----------------------------------------------------------------------------
988 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
990 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
991 currIP.DelAfterNotifier(n);
993 //-----------------------------------------------------------------------------
994 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
996 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
997 connected.AddBeforeNotifier(n);
999 //-----------------------------------------------------------------------------
1000 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1002 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1003 connected.DelBeforeNotifier(n);
1005 //-----------------------------------------------------------------------------
1006 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1008 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1009 connected.AddAfterNotifier(n);
1011 //-----------------------------------------------------------------------------
1012 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1014 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1015 connected.DelAfterNotifier(n);
1017 //-----------------------------------------------------------------------------
1018 void USER_IMPL::OnAdd()
1020 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1022 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1024 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1026 string scriptOnAddParams;
1027 strprintf(&scriptOnAddParams,
1029 scriptOnAdd.c_str(),
1032 ScriptExec(scriptOnAddParams);
1036 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1039 //-----------------------------------------------------------------------------
1040 void USER_IMPL::OnDelete()
1042 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1044 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1046 if (access(scriptOnDel.c_str(), X_OK) == 0)
1048 string scriptOnDelParams;
1049 strprintf(&scriptOnDelParams,
1051 scriptOnDel.c_str(),
1054 ScriptExec(scriptOnDelParams);
1058 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1063 //-----------------------------------------------------------------------------
1064 int USER_IMPL::WriteDetailStat(bool hard)
1066 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1068 if (!traffStatSaved.second.empty())
1070 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1072 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1073 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1074 WriteServLog("%s", store->GetStrError().c_str());
1077 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1083 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1087 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1089 if (ts.size() && !disabledDetailStat)
1091 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1093 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1094 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1095 WriteServLog("%s", store->GetStrError().c_str());
1098 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1099 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1100 traffStatSaved.second.swap(ts);
1101 traffStatSaved.first = lastWriteDetailedStat;
1106 lastWriteDetailedStat = stgTime;
1109 //-----------------------------------------------------------------------------
1110 double USER_IMPL::GetPassiveTimePart() const
1112 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1114 static int daysInMonth[12] =
1115 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1119 localtime_r(&t, &tms);
1121 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1123 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1126 secMonth += 24 * 3600;
1129 int dt = secMonth - passiveTime;
1134 return double(dt) / (secMonth);
1136 //-----------------------------------------------------------------------------
1137 void USER_IMPL::SetPassiveTimeAsNewUser()
1139 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1143 localtime_r(&t, &tm);
1144 int daysCurrMon = DaysInCurrentMonth();
1145 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1147 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1149 //-----------------------------------------------------------------------------
1150 void USER_IMPL::MidnightResetSessionStat()
1152 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1156 Disconnect(true, "fake");
1160 //-----------------------------------------------------------------------------
1161 void USER_IMPL::ProcessNewMonth()
1163 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1167 Disconnect(true, "fake");
1169 DIR_TRAFF zeroTarff;
1182 if (nextTariff.ConstData() != "")
1185 nt = tariffs->FindByName(nextTariff);
1188 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1189 login.c_str(), property.tariffName.Get().c_str());
1193 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1200 //-----------------------------------------------------------------------------
1201 void USER_IMPL::ProcessDayFeeSpread()
1203 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1205 if (passive.ConstData() || tariff == NULL)
1208 double fee = tariff->GetFee() / DaysInCurrentMonth();
1214 switch (settings->GetFeeChargeType())
1217 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1221 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1225 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1230 //-----------------------------------------------------------------------------
1231 void USER_IMPL::ProcessDayFee()
1233 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1238 double passiveTimePart = 1.0;
1239 if (!settings->GetFullFee())
1241 passiveTimePart = GetPassiveTimePart();
1245 if (passive.ConstData())
1247 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1251 double fee = tariff->GetFee() * passiveTimePart;
1262 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1267 switch (settings->GetFeeChargeType())
1270 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1276 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1283 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1289 //-----------------------------------------------------------------------------
1290 void USER_IMPL::SetPrepaidTraff()
1293 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1295 //-----------------------------------------------------------------------------
1296 int USER_IMPL::AddMessage(STG_MSG * msg)
1298 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1300 if (SendMessage(*msg))
1302 if (store->AddMessage(msg, login))
1304 errorStr = store->GetStrError();
1305 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1306 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1309 messages.push_back(*msg);
1313 if (msg->header.repeat > 0)
1315 msg->header.repeat--;
1317 //TODO: gcc v. 4.x generate ICE on x86_64
1318 msg->header.lastSendTime = time(NULL);
1320 msg->header.lastSendTime = stgTime;
1322 if (store->AddMessage(msg, login))
1324 errorStr = store->GetStrError();
1325 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1326 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1329 messages.push_back(*msg);
1334 //-----------------------------------------------------------------------------
1335 int USER_IMPL::SendMessage(STG_MSG & msg) const
1337 // No lock `cause we are already locked from caller
1339 set<const AUTH*>::iterator it(authorizedBy.begin());
1340 while (it != authorizedBy.end())
1342 if (!(*it++)->SendMessage(msg, currIP))
1348 //TODO: gcc v. 4.x generate ICE on x86_64
1349 msg.header.lastSendTime = time(NULL);
1351 msg.header.lastSendTime = stgTime;
1353 msg.header.repeat--;
1357 //-----------------------------------------------------------------------------
1358 void USER_IMPL::ScanMessage()
1360 // No lock `cause we are already locked from caller
1361 // We need not check for the authorizedBy `cause it has already checked by caller
1363 std::list<STG_MSG>::iterator it(messages.begin());
1364 while (it != messages.end())
1366 if (settings->GetMessageTimeout() > 0 &&
1367 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1370 if (store->DelMessage(it->header.id, login))
1372 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1373 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1375 messages.erase(it++);
1378 if (it->GetNextSendTime() <= stgTime)
1380 if (SendMessage(*it))
1382 // We need to check all messages in queue for timeout
1386 if (it->header.repeat < 0)
1388 if (store->DelMessage(it->header.id, login))
1390 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1391 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1393 messages.erase(it++);
1397 if (store->EditMessage(*it, login))
1399 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1400 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1411 //-----------------------------------------------------------------------------
1412 //-----------------------------------------------------------------------------
1413 //-----------------------------------------------------------------------------
1414 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1416 if (newPassive && !oldPassive && user->tariff != NULL)
1417 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1423 //-----------------------------------------------------------------------------
1424 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1426 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1427 user->Disconnect(false, "Change tariff");
1428 user->tariff = user->tariffs->FindByName(newTariff);
1429 if (user->settings->GetReconnectOnTariffChange() &&
1430 !user->authorizedBy.empty() &&
1432 user->Connect(false);
1434 //-----------------------------------------------------------------------------
1435 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1437 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1438 user->lastCashAdd = newCash - oldCash;
1440 //-----------------------------------------------------------------------------
1441 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1443 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1444 if (user->connected)
1445 user->Disconnect(false, "Change IP");
1446 if (!user->authorizedBy.empty() && user->IsInetable())
1447 user->Connect(false);
1449 //-----------------------------------------------------------------------------