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()),
65 connected(__connected),
70 lastIPForDisconnect(0),
83 lastWriteDetailedStat(0),
87 lastCashAdd(property.lastCashAdd),
88 passiveTime(property.passiveTime),
89 lastCashAddTime(property.lastCashAddTime),
90 freeMb(property.freeMb),
91 lastActivityTime(property.lastActivityTime),
92 password(property.password),
93 passive(property.passive),
94 disabled(property.disabled),
95 disabledDetailStat(property.disabledDetailStat),
96 alwaysOnline(property.alwaysOnline),
97 tariffName(property.tariffName),
98 nextTariff(property.nextTariff),
99 address(property.address),
101 group(property.group),
102 email(property.email),
103 phone(property.phone),
104 realName(property.realName),
105 credit(property.credit),
106 creditExpire(property.creditExpire),
108 userdata0(property.userdata0),
109 userdata1(property.userdata1),
110 userdata2(property.userdata2),
111 userdata3(property.userdata3),
112 userdata4(property.userdata4),
113 userdata5(property.userdata5),
114 userdata6(property.userdata6),
115 userdata7(property.userdata7),
116 userdata8(property.userdata8),
117 userdata9(property.userdata9),
120 passiveNotifier(this),
121 tariffNotifier(this),
127 password = "*_EMPTY_PASSWORD_*";
128 tariffName = NO_TARIFF_NAME;
130 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
131 lastWriteDetailedStat = stgTime;
133 property.tariffName.AddBeforeNotifier(&tariffNotifier);
134 property.passive.AddBeforeNotifier(&passiveNotifier);
135 property.cash.AddBeforeNotifier(&cashNotifier);
136 ips.AddAfterNotifier(&ipNotifier);
138 pthread_mutexattr_t attr;
139 pthread_mutexattr_init(&attr);
140 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
141 pthread_mutex_init(&mutex, &attr);
144 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
151 property(s->GetScriptsDir()),
152 WriteServLog(GetStgLogger()),
157 connected(__connected),
162 lastIPForDisconnect(0),
175 lastWriteDetailedStat(0),
179 lastCashAdd(property.lastCashAdd),
180 passiveTime(property.passiveTime),
181 lastCashAddTime(property.lastCashAddTime),
182 freeMb(property.freeMb),
183 lastActivityTime(property.lastActivityTime),
184 password(property.password),
185 passive(property.passive),
186 disabled(property.disabled),
187 disabledDetailStat(property.disabledDetailStat),
188 alwaysOnline(property.alwaysOnline),
189 tariffName(property.tariffName),
190 nextTariff(property.nextTariff),
191 address(property.address),
193 group(property.group),
194 email(property.email),
195 phone(property.phone),
196 realName(property.realName),
197 credit(property.credit),
198 creditExpire(property.creditExpire),
200 userdata0(property.userdata0),
201 userdata1(property.userdata1),
202 userdata2(property.userdata2),
203 userdata3(property.userdata3),
204 userdata4(property.userdata4),
205 userdata5(property.userdata5),
206 userdata6(property.userdata6),
207 userdata7(property.userdata7),
208 userdata8(property.userdata8),
209 userdata9(property.userdata9),
212 passiveNotifier(this),
213 tariffNotifier(this),
219 password = "*_EMPTY_PASSWORD_*";
220 tariffName = NO_TARIFF_NAME;
222 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
223 lastWriteDetailedStat = stgTime;
225 property.tariffName.AddBeforeNotifier(&tariffNotifier);
226 property.passive.AddBeforeNotifier(&passiveNotifier);
227 property.cash.AddBeforeNotifier(&cashNotifier);
228 ips.AddAfterNotifier(&ipNotifier);
230 pthread_mutexattr_t attr;
231 pthread_mutexattr_init(&attr);
232 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
233 pthread_mutex_init(&mutex, &attr);
236 //-----------------------------------------------------------------------------
237 USER_IMPL::USER_IMPL(const USER_IMPL & u)
240 property(u.settings->GetScriptsDir()),
241 WriteServLog(GetStgLogger()),
246 connected(__connected),
248 userIDGenerator(u.userIDGenerator),
249 __currIP(u.__currIP),
251 lastIPForDisconnect(0),
252 pingTime(u.pingTime),
253 sysAdmin(u.sysAdmin),
257 traffStat(u.traffStat),
258 traffStatSaved(u.traffStatSaved),
259 settings(u.settings),
261 messages(u.messages),
263 lastWriteStat(u.lastWriteStat),
264 lastWriteDetailedStat(u.lastWriteDetailedStat),
268 lastCashAdd(property.lastCashAdd),
269 passiveTime(property.passiveTime),
270 lastCashAddTime(property.lastCashAddTime),
271 freeMb(property.freeMb),
272 lastActivityTime(property.lastActivityTime),
273 password(property.password),
274 passive(property.passive),
275 disabled(property.disabled),
276 disabledDetailStat(property.disabledDetailStat),
277 alwaysOnline(property.alwaysOnline),
278 tariffName(property.tariffName),
279 nextTariff(property.nextTariff),
280 address(property.address),
282 group(property.group),
283 email(property.email),
284 phone(property.phone),
285 realName(property.realName),
286 credit(property.credit),
287 creditExpire(property.creditExpire),
289 userdata0(property.userdata0),
290 userdata1(property.userdata1),
291 userdata2(property.userdata2),
292 userdata3(property.userdata3),
293 userdata4(property.userdata4),
294 userdata5(property.userdata5),
295 userdata6(property.userdata6),
296 userdata7(property.userdata7),
297 userdata8(property.userdata8),
298 userdata9(property.userdata9),
301 passiveNotifier(this),
302 tariffNotifier(this),
311 property.tariffName.AddBeforeNotifier(&tariffNotifier);
312 property.passive.AddBeforeNotifier(&passiveNotifier);
313 property.cash.AddBeforeNotifier(&cashNotifier);
314 ips.AddAfterNotifier(&ipNotifier);
316 property.SetProperties(u.property);
318 pthread_mutexattr_t attr;
319 pthread_mutexattr_init(&attr);
320 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
321 pthread_mutex_init(&mutex, &attr);
323 //-----------------------------------------------------------------------------
324 USER_IMPL::~USER_IMPL()
326 property.passive.DelBeforeNotifier(&passiveNotifier);
327 property.tariffName.DelBeforeNotifier(&tariffNotifier);
328 pthread_mutex_destroy(&mutex);
330 //-----------------------------------------------------------------------------
331 void USER_IMPL::SetLogin(string const & l)
333 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
334 assert(login.empty() && "Login is already set");
336 id = userIDGenerator.GetNextID();
338 //-----------------------------------------------------------------------------
339 int USER_IMPL::ReadConf()
341 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
344 if (store->RestoreUserConf(&conf, login))
346 WriteServLog("Cannot read conf for user %s.", login.c_str());
347 WriteServLog("%s", store->GetStrError().c_str());
348 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
349 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
353 property.SetConf(conf);
355 tariff = tariffs->FindByName(tariffName);
358 WriteServLog("Cannot read user %s. Tariff %s not exist.",
359 login.c_str(), property.tariffName.Get().c_str());
363 std::vector<STG_MSG_HDR> hdrsList;
365 if (store->GetMessageHdrs(&hdrsList, login))
367 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
368 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
370 store->GetStrError().c_str());
374 std::vector<STG_MSG_HDR>::const_iterator it;
375 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
378 if (store->GetMessage(it->id, &msg, login) == 0)
380 messages.push_back(msg);
386 //-----------------------------------------------------------------------------
387 int USER_IMPL::ReadStat()
389 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
392 if (store->RestoreUserStat(&stat, login))
394 WriteServLog("Cannot read stat for user %s.", login.c_str());
395 WriteServLog("%s", store->GetStrError().c_str());
396 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
397 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
401 property.SetStat(stat);
405 //-----------------------------------------------------------------------------
406 int USER_IMPL::WriteConf()
408 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
409 USER_CONF conf(property.GetConf());
411 printfd(__FILE__, "USER::WriteConf()\n");
413 if (store->SaveUserConf(conf, login))
415 WriteServLog("Cannot write conf for user %s.", login.c_str());
416 WriteServLog("%s", store->GetStrError().c_str());
417 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
418 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
424 //-----------------------------------------------------------------------------
425 int USER_IMPL::WriteStat()
427 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
428 USER_STAT stat(property.GetStat());
430 if (store->SaveUserStat(stat, login))
432 WriteServLog("Cannot write stat for user %s.", login.c_str());
433 WriteServLog("%s", store->GetStrError().c_str());
434 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
435 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
439 lastWriteStat = stgTime;
443 //-----------------------------------------------------------------------------
444 int USER_IMPL::WriteMonthStat()
446 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
447 time_t tt = stgTime - 3600;
449 localtime_r(&tt, &t1);
451 USER_STAT stat(property.GetStat());
452 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
454 WriteServLog("Cannot write month stat for user %s.", login.c_str());
455 WriteServLog("%s", store->GetStrError().c_str());
456 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
457 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
463 //-----------------------------------------------------------------------------
464 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
466 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
468 * Authorize user. It only means that user will be authorized. Nothing more.
469 * User can be connected or disconnected while authorized.
470 * Example: user is authorized but disconnected due to 0 money or blocking
474 * Prevent double authorization by identical authorizers
476 if (authorizedBy.find(auth) != authorizedBy.end())
482 for (int i = 0; i < DIR_NUM; i++)
484 enabledDirs[i] = dirs & (1 << i);
487 if (!authorizedBy.empty())
491 // We are already authorized, but with different IP address
492 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
497 if (!users->FindByIPIdx(ip, &u))
499 // Address is already present in IP-index
500 // If it's not our IP - throw an error
503 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
510 if (users->IsIPInIndex(ip))
512 // Address is already present in IP-index
513 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
517 if (ips.ConstData().IsIPInIPS(ip))
520 lastIPForDisconnect = currIP;
524 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
525 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
530 authorizedBy.insert(auth);
536 //-----------------------------------------------------------------------------
537 void USER_IMPL::Unauthorize(const AUTH * auth)
539 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
541 * Authorizer tries to unauthorize user, that was not authorized by it
543 if (!authorizedBy.erase(auth))
546 if (authorizedBy.empty())
548 lastIPForDisconnect = currIP;
549 currIP = 0; // DelUser in traffcounter
553 //-----------------------------------------------------------------------------
554 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
556 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
557 // Is this user authorized by specified authorizer?
558 return authorizedBy.find(auth) != authorizedBy.end();
560 //-----------------------------------------------------------------------------
561 void USER_IMPL::Connect(bool fakeConnect)
564 * Connect user to Internet. This function is differ from Authorize() !!!
567 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
571 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
573 if (access(scriptOnConnect.c_str(), X_OK) == 0)
575 char dirsStr[DIR_NUM + 1];
576 dirsStr[DIR_NUM] = 0;
577 for (int i = 0; i < DIR_NUM; i++)
579 dirsStr[i] = enabledDirs[i] ? '1' : '0';
582 string scriptOnConnectParams;
583 strprintf(&scriptOnConnectParams,
584 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
585 scriptOnConnect.c_str(),
587 inet_ntostring(currIP).c_str(),
592 ScriptExec(scriptOnConnectParams.c_str());
596 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
602 if (store->WriteUserConnect(login, currIP))
604 WriteServLog("Cannot write connect for user %s.", login.c_str());
605 WriteServLog("%s", store->GetStrError().c_str());
609 lastIPForDisconnect = currIP;
611 //-----------------------------------------------------------------------------
612 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
615 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
618 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
620 if (!lastIPForDisconnect)
622 printfd(__FILE__, "lastIPForDisconnect\n");
628 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
630 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
632 char dirsStr[DIR_NUM + 1];
633 dirsStr[DIR_NUM] = 0;
634 for (int i = 0; i < DIR_NUM; i++)
636 dirsStr[i] = enabledDirs[i] ? '1' : '0';
639 string scriptOnDisonnectParams;
640 strprintf(&scriptOnDisonnectParams,
641 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
642 scriptOnDisonnect.c_str(),
644 inet_ntostring(lastIPForDisconnect).c_str(),
649 ScriptExec(scriptOnDisonnectParams.c_str());
653 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
659 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
661 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
662 WriteServLog("%s", store->GetStrError().c_str());
666 lastIPForDisconnect = 0;
668 DIR_TRAFF zeroSesssion;
670 sessionUpload = zeroSesssion;
671 sessionDownload = zeroSesssion;
673 //-----------------------------------------------------------------------------
674 void USER_IMPL::PrintUser() const
677 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
678 cout << "============================================================" << endl;
679 cout << "id=" << id << endl;
680 cout << "login=" << login << endl;
681 cout << "password=" << password << endl;
682 cout << "passive=" << passive << endl;
683 cout << "disabled=" << disabled << endl;
684 cout << "disabledDetailStat=" << disabledDetailStat << endl;
685 cout << "alwaysOnline=" << alwaysOnline << endl;
686 cout << "tariffName=" << tariffName << endl;
687 cout << "address=" << address << endl;
688 cout << "phone=" << phone << endl;
689 cout << "email=" << email << endl;
690 cout << "note=" << note << endl;
691 cout << "realName=" <<realName << endl;
692 cout << "group=" << group << endl;
693 cout << "credit=" << credit << endl;
694 cout << "nextTariff=" << nextTariff << endl;
695 cout << "userdata0" << userdata0 << endl;
696 cout << "userdata1" << userdata1 << endl;
697 cout << "creditExpire=" << creditExpire << endl;
698 cout << "ips=" << ips << endl;
699 cout << "------------------------" << endl;
700 cout << "up=" << up << endl;
701 cout << "down=" << down << endl;
702 cout << "cash=" << cash << endl;
703 cout << "freeMb=" << freeMb << endl;
704 cout << "lastCashAdd=" << lastCashAdd << endl;
705 cout << "lastCashAddTime=" << lastCashAddTime << endl;
706 cout << "passiveTime=" << passiveTime << endl;
707 cout << "lastActivityTime=" << lastActivityTime << endl;
708 cout << "============================================================" << endl;
710 //-----------------------------------------------------------------------------
711 void USER_IMPL::Run()
713 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
715 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
717 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
720 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
722 WriteServLog("User: %s. Credit expired.", login.c_str());
728 if (passive.ConstData()
729 && (stgTime % 30 == 0)
730 && (passiveTime.ModificationTime() != stgTime))
732 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
733 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
736 if (!authorizedBy.empty())
740 property.Stat().lastActivityTime = stgTime;
742 if (!connected && IsInetable())
746 if (connected && !IsInetable())
749 Disconnect(false, "disabled");
751 Disconnect(false, "passive");
753 Disconnect(false, "no cash");
756 if (stgTime - lastScanMessages > 10)
759 lastScanMessages = stgTime;
766 Disconnect(false, "not authorized");
771 //-----------------------------------------------------------------------------
772 void USER_IMPL::UpdatePingTime(time_t t)
774 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
775 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
781 //-----------------------------------------------------------------------------
782 bool USER_IMPL::IsInetable()
784 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
786 if (disabled || passive)
789 if (settings->GetFreeMbAllowInet())
795 if (settings->GetShowFeeInCash() || tariff == NULL)
797 return (cash >= -credit);
800 return (cash - tariff->GetFee() >= -credit);
802 //-----------------------------------------------------------------------------
803 string USER_IMPL::GetEnabledDirs()
805 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
808 for(int i = 0; i < DIR_NUM; i++)
809 dirs += enabledDirs[i] ? "1" : "0";
812 //-----------------------------------------------------------------------------
813 #ifdef TRAFF_STAT_WITH_PORTS
814 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
816 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
819 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
821 if (!connected || tariff == NULL)
827 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
828 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
832 int tt = tariff->GetTraffType();
833 if (tt == TRAFF_UP ||
834 tt == TRAFF_UP_DOWN ||
835 // Check NEW traff data
836 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
839 if (traff < threshold &&
840 traff + len >= threshold)
842 // cash = partBeforeThreshold * priceBeforeThreshold +
843 // partAfterThreshold * priceAfterThreshold
844 int64_t before = threshold - traff; // Chunk part before threshold
845 int64_t after = len - before; // Chunk part after threshold
846 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
847 down.ConstData()[dir],
850 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
851 down.ConstData()[dir],
857 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
858 down.ConstData()[dir],
863 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
865 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
866 cost = dc - freeMb.ConstData();
868 // Direct access to internal data structures via friend-specifier
869 property.Stat().freeMb -= dc;
870 property.Stat().cash -= cost;
876 sessionUpload[dir] += len;
880 if (!settings->GetWriteFreeMbTraffCost() &&
881 freeMb.ConstData() >= 0)
884 #ifdef TRAFF_STAT_WITH_PORTS
885 IP_DIR_PAIR idp(ip, dir, port);
887 IP_DIR_PAIR idp(ip, dir);
890 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
891 lb = traffStat.lower_bound(idp);
892 if (lb == traffStat.end() || lb->first != idp)
895 pair<IP_DIR_PAIR, STAT_NODE>(idp,
896 STAT_NODE(len, 0, cost)));
900 lb->second.cash += cost;
901 lb->second.up += len;
904 //-----------------------------------------------------------------------------
905 #ifdef TRAFF_STAT_WITH_PORTS
906 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
908 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
911 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
913 if (!connected || tariff == NULL)
919 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
920 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
924 int tt = tariff->GetTraffType();
925 if (tt == TRAFF_DOWN ||
926 tt == TRAFF_UP_DOWN ||
927 // Check NEW traff data
928 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
931 if (traff < threshold &&
932 traff + len >= threshold)
934 // cash = partBeforeThreshold * priceBeforeThreshold +
935 // partAfterThreshold * priceAfterThreshold
936 int64_t before = threshold - traff; // Chunk part before threshold
937 int64_t after = len - before; // Chunk part after threshold
938 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
939 down.ConstData()[dir], // Traff before chunk
942 tariff->GetPriceWithTraffType(up.ConstData()[dir],
943 dt[dir], // Traff after chunk
949 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
950 down.ConstData()[dir],
955 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
957 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
958 cost = dc - freeMb.ConstData();
960 property.Stat().freeMb -= dc;
961 property.Stat().cash -= cost;
967 sessionDownload[dir] += len;
971 if (!settings->GetWriteFreeMbTraffCost() &&
972 freeMb.ConstData() >= 0)
975 #ifdef TRAFF_STAT_WITH_PORTS
976 IP_DIR_PAIR idp(ip, dir, port);
978 IP_DIR_PAIR idp(ip, dir);
981 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
982 lb = traffStat.lower_bound(idp);
983 if (lb == traffStat.end() || lb->first != idp)
986 pair<IP_DIR_PAIR, STAT_NODE>(idp,
987 STAT_NODE(0, len, cost)));
991 lb->second.cash += cost;
992 lb->second.down += len;
995 //-----------------------------------------------------------------------------
996 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
998 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
999 currIP.AddBeforeNotifier(n);
1001 //-----------------------------------------------------------------------------
1002 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
1004 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1005 currIP.DelBeforeNotifier(n);
1007 //-----------------------------------------------------------------------------
1008 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
1010 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1011 currIP.AddAfterNotifier(n);
1013 //-----------------------------------------------------------------------------
1014 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
1016 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1017 currIP.DelAfterNotifier(n);
1019 //-----------------------------------------------------------------------------
1020 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1022 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1023 connected.AddBeforeNotifier(n);
1025 //-----------------------------------------------------------------------------
1026 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1028 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1029 connected.DelBeforeNotifier(n);
1031 //-----------------------------------------------------------------------------
1032 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1034 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1035 connected.AddAfterNotifier(n);
1037 //-----------------------------------------------------------------------------
1038 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1040 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1041 connected.DelAfterNotifier(n);
1043 //-----------------------------------------------------------------------------
1044 void USER_IMPL::OnAdd()
1046 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1048 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1050 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1052 string scriptOnAddParams;
1053 strprintf(&scriptOnAddParams,
1055 scriptOnAdd.c_str(),
1058 ScriptExec(scriptOnAddParams.c_str());
1062 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1065 //-----------------------------------------------------------------------------
1066 void USER_IMPL::OnDelete()
1068 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1070 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1072 if (access(scriptOnDel.c_str(), X_OK) == 0)
1074 string scriptOnDelParams;
1075 strprintf(&scriptOnDelParams,
1077 scriptOnDel.c_str(),
1080 ScriptExec(scriptOnDelParams.c_str());
1084 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1089 //-----------------------------------------------------------------------------
1090 int USER_IMPL::WriteDetailStat(bool hard)
1092 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1094 if (!traffStatSaved.second.empty())
1096 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1098 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1099 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1100 WriteServLog("%s", store->GetStrError().c_str());
1103 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1109 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1113 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1115 if (ts.size() && !disabledDetailStat)
1117 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1119 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1120 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1121 WriteServLog("%s", store->GetStrError().c_str());
1124 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1125 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1126 traffStatSaved.second.swap(ts);
1127 traffStatSaved.first = lastWriteDetailedStat;
1132 lastWriteDetailedStat = stgTime;
1135 //-----------------------------------------------------------------------------
1136 double USER_IMPL::GetPassiveTimePart() const
1138 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1140 static int daysInMonth[12] =
1141 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1145 localtime_r(&t, &tms);
1147 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1149 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1152 secMonth += 24 * 3600;
1155 int dt = secMonth - passiveTime;
1160 return double(dt) / (secMonth);
1162 //-----------------------------------------------------------------------------
1163 void USER_IMPL::SetPassiveTimeAsNewUser()
1165 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1169 localtime_r(&t, &tm);
1170 int daysCurrMon = DaysInCurrentMonth();
1171 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1173 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1175 //-----------------------------------------------------------------------------
1176 void USER_IMPL::MidnightResetSessionStat()
1178 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1182 Disconnect(true, "fake");
1186 //-----------------------------------------------------------------------------
1187 void USER_IMPL::ProcessNewMonth()
1189 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1193 Disconnect(true, "fake");
1195 DIR_TRAFF zeroTarff;
1208 if (nextTariff.ConstData() != "")
1211 nt = tariffs->FindByName(nextTariff);
1214 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1215 login.c_str(), property.tariffName.Get().c_str());
1219 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1226 //-----------------------------------------------------------------------------
1227 void USER_IMPL::ProcessDayFeeSpread()
1229 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1231 if (passive.ConstData() || tariff == NULL)
1234 if (tariff->GetPeriod() != TARIFF::MONTH)
1237 double fee = tariff->GetFee() / DaysInCurrentMonth();
1243 switch (settings->GetFeeChargeType())
1246 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1249 if (c + credit >= 0)
1250 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1253 if (c + credit >= fee)
1254 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1259 //-----------------------------------------------------------------------------
1260 void USER_IMPL::ProcessDayFee()
1262 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1267 if (tariff->GetPeriod() != TARIFF::MONTH)
1270 double passiveTimePart = 1.0;
1271 if (!settings->GetFullFee())
1273 passiveTimePart = GetPassiveTimePart();
1277 if (passive.ConstData())
1279 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1283 double fee = tariff->GetFee() * passiveTimePart;
1294 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1301 switch (settings->GetFeeChargeType())
1304 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1308 if (c + credit >= 0)
1310 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1315 if (c + credit >= fee)
1317 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1323 //-----------------------------------------------------------------------------
1324 void USER_IMPL::ProcessDailyFee()
1326 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1328 if (passive.ConstData() || tariff == NULL)
1331 if (tariff->GetPeriod() != TARIFF::DAY)
1334 double fee = tariff->GetFee();
1340 switch (settings->GetFeeChargeType())
1343 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1346 if (c + credit >= 0)
1347 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1350 if (c + credit >= fee)
1351 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1356 //-----------------------------------------------------------------------------
1357 void USER_IMPL::SetPrepaidTraff()
1360 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1362 //-----------------------------------------------------------------------------
1363 int USER_IMPL::AddMessage(STG_MSG * msg)
1365 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1367 if (SendMessage(*msg))
1369 if (store->AddMessage(msg, login))
1371 errorStr = store->GetStrError();
1372 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1373 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1376 messages.push_back(*msg);
1380 if (msg->header.repeat > 0)
1382 msg->header.repeat--;
1384 //TODO: gcc v. 4.x generate ICE on x86_64
1385 msg->header.lastSendTime = time(NULL);
1387 msg->header.lastSendTime = stgTime;
1389 if (store->AddMessage(msg, login))
1391 errorStr = store->GetStrError();
1392 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1393 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1396 messages.push_back(*msg);
1401 //-----------------------------------------------------------------------------
1402 int USER_IMPL::SendMessage(STG_MSG & msg) const
1404 // No lock `cause we are already locked from caller
1406 set<const AUTH*>::iterator it(authorizedBy.begin());
1407 while (it != authorizedBy.end())
1409 if (!(*it++)->SendMessage(msg, currIP))
1415 //TODO: gcc v. 4.x generate ICE on x86_64
1416 msg.header.lastSendTime = time(NULL);
1418 msg.header.lastSendTime = stgTime;
1420 msg.header.repeat--;
1424 //-----------------------------------------------------------------------------
1425 void USER_IMPL::ScanMessage()
1427 // No lock `cause we are already locked from caller
1428 // We need not check for the authorizedBy `cause it has already checked by caller
1430 std::list<STG_MSG>::iterator it(messages.begin());
1431 while (it != messages.end())
1433 if (settings->GetMessageTimeout() > 0 &&
1434 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1437 if (store->DelMessage(it->header.id, login))
1439 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1440 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1442 messages.erase(it++);
1445 if (it->GetNextSendTime() <= stgTime)
1447 if (SendMessage(*it))
1449 // We need to check all messages in queue for timeout
1453 if (it->header.repeat < 0)
1455 if (store->DelMessage(it->header.id, login))
1457 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1458 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1460 messages.erase(it++);
1464 if (store->EditMessage(*it, login))
1466 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1467 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1478 //-----------------------------------------------------------------------------
1479 //-----------------------------------------------------------------------------
1480 //-----------------------------------------------------------------------------
1481 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1483 if (newPassive && !oldPassive && user->tariff != NULL)
1484 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1490 //-----------------------------------------------------------------------------
1491 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1493 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1494 user->Disconnect(false, "Change tariff");
1495 user->tariff = user->tariffs->FindByName(newTariff);
1496 if (user->settings->GetReconnectOnTariffChange() &&
1497 !user->authorizedBy.empty() &&
1499 user->Connect(false);
1501 //-----------------------------------------------------------------------------
1502 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1504 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1505 user->lastCashAdd = newCash - oldCash;
1507 //-----------------------------------------------------------------------------
1508 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1510 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1511 if (user->connected)
1512 user->Disconnect(false, "Change IP");
1513 if (!user->authorizedBy.empty() && user->IsInetable())
1514 user->Connect(false);
1516 //-----------------------------------------------------------------------------