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.disabled.AddAfterNotifier(&disabledNotifier);
136 property.cash.AddBeforeNotifier(&cashNotifier);
137 ips.AddAfterNotifier(&ipNotifier);
139 pthread_mutexattr_t attr;
140 pthread_mutexattr_init(&attr);
141 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
142 pthread_mutex_init(&mutex, &attr);
145 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
152 property(s->GetScriptsDir()),
153 WriteServLog(GetStgLogger()),
158 connected(__connected),
163 lastIPForDisconnect(0),
176 lastWriteDetailedStat(0),
180 lastCashAdd(property.lastCashAdd),
181 passiveTime(property.passiveTime),
182 lastCashAddTime(property.lastCashAddTime),
183 freeMb(property.freeMb),
184 lastActivityTime(property.lastActivityTime),
185 password(property.password),
186 passive(property.passive),
187 disabled(property.disabled),
188 disabledDetailStat(property.disabledDetailStat),
189 alwaysOnline(property.alwaysOnline),
190 tariffName(property.tariffName),
191 nextTariff(property.nextTariff),
192 address(property.address),
194 group(property.group),
195 email(property.email),
196 phone(property.phone),
197 realName(property.realName),
198 credit(property.credit),
199 creditExpire(property.creditExpire),
201 userdata0(property.userdata0),
202 userdata1(property.userdata1),
203 userdata2(property.userdata2),
204 userdata3(property.userdata3),
205 userdata4(property.userdata4),
206 userdata5(property.userdata5),
207 userdata6(property.userdata6),
208 userdata7(property.userdata7),
209 userdata8(property.userdata8),
210 userdata9(property.userdata9),
213 passiveNotifier(this),
214 disabledNotifier(this),
215 tariffNotifier(this),
221 password = "*_EMPTY_PASSWORD_*";
222 tariffName = NO_TARIFF_NAME;
224 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
225 lastWriteDetailedStat = stgTime;
227 property.tariffName.AddBeforeNotifier(&tariffNotifier);
228 property.passive.AddBeforeNotifier(&passiveNotifier);
229 property.disabled.AddAfterNotifier(&disabledNotifier);
230 property.cash.AddBeforeNotifier(&cashNotifier);
231 ips.AddAfterNotifier(&ipNotifier);
233 pthread_mutexattr_t attr;
234 pthread_mutexattr_init(&attr);
235 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
236 pthread_mutex_init(&mutex, &attr);
239 //-----------------------------------------------------------------------------
240 USER_IMPL::USER_IMPL(const USER_IMPL & u)
243 property(u.settings->GetScriptsDir()),
244 WriteServLog(GetStgLogger()),
249 connected(__connected),
251 userIDGenerator(u.userIDGenerator),
252 __currIP(u.__currIP),
254 lastIPForDisconnect(0),
255 pingTime(u.pingTime),
256 sysAdmin(u.sysAdmin),
260 traffStat(u.traffStat),
261 traffStatSaved(u.traffStatSaved),
262 settings(u.settings),
264 messages(u.messages),
266 lastWriteStat(u.lastWriteStat),
267 lastWriteDetailedStat(u.lastWriteDetailedStat),
271 lastCashAdd(property.lastCashAdd),
272 passiveTime(property.passiveTime),
273 lastCashAddTime(property.lastCashAddTime),
274 freeMb(property.freeMb),
275 lastActivityTime(property.lastActivityTime),
276 password(property.password),
277 passive(property.passive),
278 disabled(property.disabled),
279 disabledDetailStat(property.disabledDetailStat),
280 alwaysOnline(property.alwaysOnline),
281 tariffName(property.tariffName),
282 nextTariff(property.nextTariff),
283 address(property.address),
285 group(property.group),
286 email(property.email),
287 phone(property.phone),
288 realName(property.realName),
289 credit(property.credit),
290 creditExpire(property.creditExpire),
292 userdata0(property.userdata0),
293 userdata1(property.userdata1),
294 userdata2(property.userdata2),
295 userdata3(property.userdata3),
296 userdata4(property.userdata4),
297 userdata5(property.userdata5),
298 userdata6(property.userdata6),
299 userdata7(property.userdata7),
300 userdata8(property.userdata8),
301 userdata9(property.userdata9),
304 passiveNotifier(this),
305 disabledNotifier(this),
306 tariffNotifier(this),
315 property.tariffName.AddBeforeNotifier(&tariffNotifier);
316 property.passive.AddBeforeNotifier(&passiveNotifier);
317 property.disabled.AddAfterNotifier(&disabledNotifier);
318 property.cash.AddBeforeNotifier(&cashNotifier);
319 ips.AddAfterNotifier(&ipNotifier);
321 property.SetProperties(u.property);
323 pthread_mutexattr_t attr;
324 pthread_mutexattr_init(&attr);
325 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
326 pthread_mutex_init(&mutex, &attr);
328 //-----------------------------------------------------------------------------
329 USER_IMPL::~USER_IMPL()
331 property.tariffName.DelBeforeNotifier(&tariffNotifier);
332 property.passive.DelBeforeNotifier(&passiveNotifier);
333 property.disabled.DelAfterNotifier(&disabledNotifier);
334 property.cash.DelBeforeNotifier(&cashNotifier);
335 pthread_mutex_destroy(&mutex);
337 //-----------------------------------------------------------------------------
338 void USER_IMPL::SetLogin(string const & l)
340 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
341 assert(login.empty() && "Login is already set");
343 id = userIDGenerator.GetNextID();
345 //-----------------------------------------------------------------------------
346 int USER_IMPL::ReadConf()
348 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
351 if (store->RestoreUserConf(&conf, login))
353 WriteServLog("Cannot read conf for user %s.", login.c_str());
354 WriteServLog("%s", store->GetStrError().c_str());
355 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
356 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
360 property.SetConf(conf);
362 tariff = tariffs->FindByName(tariffName);
365 WriteServLog("Cannot read user %s. Tariff %s not exist.",
366 login.c_str(), property.tariffName.Get().c_str());
370 std::vector<STG_MSG_HDR> hdrsList;
372 if (store->GetMessageHdrs(&hdrsList, login))
374 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
375 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
377 store->GetStrError().c_str());
381 std::vector<STG_MSG_HDR>::const_iterator it;
382 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
385 if (store->GetMessage(it->id, &msg, login) == 0)
387 messages.push_back(msg);
393 //-----------------------------------------------------------------------------
394 int USER_IMPL::ReadStat()
396 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
399 if (store->RestoreUserStat(&stat, login))
401 WriteServLog("Cannot read stat for user %s.", login.c_str());
402 WriteServLog("%s", store->GetStrError().c_str());
403 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
404 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
408 property.SetStat(stat);
412 //-----------------------------------------------------------------------------
413 int USER_IMPL::WriteConf()
415 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
416 USER_CONF conf(property.GetConf());
418 printfd(__FILE__, "USER::WriteConf()\n");
420 if (store->SaveUserConf(conf, login))
422 WriteServLog("Cannot write conf for user %s.", login.c_str());
423 WriteServLog("%s", store->GetStrError().c_str());
424 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
425 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
431 //-----------------------------------------------------------------------------
432 int USER_IMPL::WriteStat()
434 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
435 USER_STAT stat(property.GetStat());
437 if (store->SaveUserStat(stat, login))
439 WriteServLog("Cannot write stat for user %s.", login.c_str());
440 WriteServLog("%s", store->GetStrError().c_str());
441 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
442 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
446 lastWriteStat = stgTime;
450 //-----------------------------------------------------------------------------
451 int USER_IMPL::WriteMonthStat()
453 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
454 time_t tt = stgTime - 3600;
456 localtime_r(&tt, &t1);
458 USER_STAT stat(property.GetStat());
459 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
461 WriteServLog("Cannot write month stat for user %s.", login.c_str());
462 WriteServLog("%s", store->GetStrError().c_str());
463 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
464 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
470 //-----------------------------------------------------------------------------
471 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
473 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
475 * Authorize user. It only means that user will be authorized. Nothing more.
476 * User can be connected or disconnected while authorized.
477 * Example: user is authorized but disconnected due to 0 money or blocking
481 * Prevent double authorization by identical authorizers
483 if (authorizedBy.find(auth) != authorizedBy.end())
489 for (int i = 0; i < DIR_NUM; i++)
491 enabledDirs[i] = dirs & (1 << i);
494 if (!authorizedBy.empty())
498 // We are already authorized, but with different IP address
499 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
504 if (!users->FindByIPIdx(ip, &u))
506 // Address is already present in IP-index
507 // If it's not our IP - throw an error
510 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
517 if (users->IsIPInIndex(ip))
519 // Address is already present in IP-index
520 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
524 if (ips.ConstData().IsIPInIPS(ip))
527 lastIPForDisconnect = currIP;
531 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
532 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
537 authorizedBy.insert(auth);
543 //-----------------------------------------------------------------------------
544 void USER_IMPL::Unauthorize(const AUTH * auth)
546 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
548 * Authorizer tries to unauthorize user, that was not authorized by it
550 if (!authorizedBy.erase(auth))
553 if (authorizedBy.empty())
555 lastIPForDisconnect = currIP;
556 currIP = 0; // DelUser in traffcounter
560 //-----------------------------------------------------------------------------
561 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
563 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
564 // Is this user authorized by specified authorizer?
565 return authorizedBy.find(auth) != authorizedBy.end();
567 //-----------------------------------------------------------------------------
568 void USER_IMPL::Connect(bool fakeConnect)
571 * Connect user to Internet. This function is differ from Authorize() !!!
574 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
578 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
580 if (access(scriptOnConnect.c_str(), X_OK) == 0)
582 char dirsStr[DIR_NUM + 1];
583 dirsStr[DIR_NUM] = 0;
584 for (int i = 0; i < DIR_NUM; i++)
586 dirsStr[i] = enabledDirs[i] ? '1' : '0';
589 string scriptOnConnectParams;
590 strprintf(&scriptOnConnectParams,
591 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
592 scriptOnConnect.c_str(),
594 inet_ntostring(currIP).c_str(),
599 ScriptExec(scriptOnConnectParams.c_str());
603 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
609 if (store->WriteUserConnect(login, currIP))
611 WriteServLog("Cannot write connect for user %s.", login.c_str());
612 WriteServLog("%s", store->GetStrError().c_str());
616 lastIPForDisconnect = currIP;
618 //-----------------------------------------------------------------------------
619 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
622 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
625 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
627 if (!lastIPForDisconnect)
629 printfd(__FILE__, "lastIPForDisconnect\n");
635 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
637 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
639 char dirsStr[DIR_NUM + 1];
640 dirsStr[DIR_NUM] = 0;
641 for (int i = 0; i < DIR_NUM; i++)
643 dirsStr[i] = enabledDirs[i] ? '1' : '0';
646 string scriptOnDisonnectParams;
647 strprintf(&scriptOnDisonnectParams,
648 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
649 scriptOnDisonnect.c_str(),
651 inet_ntostring(lastIPForDisconnect).c_str(),
656 ScriptExec(scriptOnDisonnectParams.c_str());
660 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
666 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
668 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
669 WriteServLog("%s", store->GetStrError().c_str());
673 lastIPForDisconnect = 0;
675 DIR_TRAFF zeroSesssion;
677 sessionUpload = zeroSesssion;
678 sessionDownload = zeroSesssion;
680 //-----------------------------------------------------------------------------
681 void USER_IMPL::PrintUser() const
684 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
685 cout << "============================================================" << endl;
686 cout << "id=" << id << endl;
687 cout << "login=" << login << endl;
688 cout << "password=" << password << endl;
689 cout << "passive=" << passive << endl;
690 cout << "disabled=" << disabled << endl;
691 cout << "disabledDetailStat=" << disabledDetailStat << endl;
692 cout << "alwaysOnline=" << alwaysOnline << endl;
693 cout << "tariffName=" << tariffName << endl;
694 cout << "address=" << address << endl;
695 cout << "phone=" << phone << endl;
696 cout << "email=" << email << endl;
697 cout << "note=" << note << endl;
698 cout << "realName=" <<realName << endl;
699 cout << "group=" << group << endl;
700 cout << "credit=" << credit << endl;
701 cout << "nextTariff=" << nextTariff << endl;
702 cout << "userdata0" << userdata0 << endl;
703 cout << "userdata1" << userdata1 << endl;
704 cout << "creditExpire=" << creditExpire << endl;
705 cout << "ips=" << ips << endl;
706 cout << "------------------------" << endl;
707 cout << "up=" << up << endl;
708 cout << "down=" << down << endl;
709 cout << "cash=" << cash << endl;
710 cout << "freeMb=" << freeMb << endl;
711 cout << "lastCashAdd=" << lastCashAdd << endl;
712 cout << "lastCashAddTime=" << lastCashAddTime << endl;
713 cout << "passiveTime=" << passiveTime << endl;
714 cout << "lastActivityTime=" << lastActivityTime << endl;
715 cout << "============================================================" << endl;
717 //-----------------------------------------------------------------------------
718 void USER_IMPL::Run()
720 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
722 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
724 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
727 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
729 WriteServLog("User: %s. Credit expired.", login.c_str());
735 if (passive.ConstData()
736 && (stgTime % 30 == 0)
737 && (passiveTime.ModificationTime() != stgTime))
739 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
740 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
743 if (!authorizedBy.empty())
747 property.Stat().lastActivityTime = stgTime;
749 if (!connected && IsInetable())
753 if (connected && !IsInetable())
756 Disconnect(false, "disabled");
758 Disconnect(false, "passive");
760 Disconnect(false, "no cash");
763 if (stgTime - lastScanMessages > 10)
766 lastScanMessages = stgTime;
773 Disconnect(false, "not authorized");
778 //-----------------------------------------------------------------------------
779 void USER_IMPL::UpdatePingTime(time_t t)
781 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
782 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
788 //-----------------------------------------------------------------------------
789 bool USER_IMPL::IsInetable()
791 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
793 if (disabled || passive)
796 if (settings->GetFreeMbAllowInet())
802 if (settings->GetShowFeeInCash() || tariff == NULL)
804 return (cash >= -credit);
807 return (cash - tariff->GetFee() >= -credit);
809 //-----------------------------------------------------------------------------
810 string USER_IMPL::GetEnabledDirs()
812 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
815 for(int i = 0; i < DIR_NUM; i++)
816 dirs += enabledDirs[i] ? "1" : "0";
819 //-----------------------------------------------------------------------------
820 #ifdef TRAFF_STAT_WITH_PORTS
821 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
823 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
826 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
828 if (!connected || tariff == NULL)
834 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
835 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
839 int tt = tariff->GetTraffType();
840 if (tt == TRAFF_UP ||
841 tt == TRAFF_UP_DOWN ||
842 // Check NEW traff data
843 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
846 if (traff < threshold &&
847 traff + len >= threshold)
849 // cash = partBeforeThreshold * priceBeforeThreshold +
850 // partAfterThreshold * priceAfterThreshold
851 int64_t before = threshold - traff; // Chunk part before threshold
852 int64_t after = len - before; // Chunk part after threshold
853 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
854 down.ConstData()[dir],
857 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
858 down.ConstData()[dir],
864 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
865 down.ConstData()[dir],
870 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
872 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
873 cost = dc - freeMb.ConstData();
875 // Direct access to internal data structures via friend-specifier
876 property.Stat().freeMb -= dc;
877 property.Stat().cash -= cost;
883 sessionUpload[dir] += len;
887 if (!settings->GetWriteFreeMbTraffCost() &&
888 freeMb.ConstData() >= 0)
891 #ifdef TRAFF_STAT_WITH_PORTS
892 IP_DIR_PAIR idp(ip, dir, port);
894 IP_DIR_PAIR idp(ip, dir);
897 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
898 lb = traffStat.lower_bound(idp);
899 if (lb == traffStat.end() || lb->first != idp)
902 pair<IP_DIR_PAIR, STAT_NODE>(idp,
903 STAT_NODE(len, 0, cost)));
907 lb->second.cash += cost;
908 lb->second.up += len;
911 //-----------------------------------------------------------------------------
912 #ifdef TRAFF_STAT_WITH_PORTS
913 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
915 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
918 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
920 if (!connected || tariff == NULL)
926 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
927 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
931 int tt = tariff->GetTraffType();
932 if (tt == TRAFF_DOWN ||
933 tt == TRAFF_UP_DOWN ||
934 // Check NEW traff data
935 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
938 if (traff < threshold &&
939 traff + len >= threshold)
941 // cash = partBeforeThreshold * priceBeforeThreshold +
942 // partAfterThreshold * priceAfterThreshold
943 int64_t before = threshold - traff; // Chunk part before threshold
944 int64_t after = len - before; // Chunk part after threshold
945 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
946 down.ConstData()[dir], // Traff before chunk
949 tariff->GetPriceWithTraffType(up.ConstData()[dir],
950 dt[dir], // Traff after chunk
956 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
957 down.ConstData()[dir],
962 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
964 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
965 cost = dc - freeMb.ConstData();
967 property.Stat().freeMb -= dc;
968 property.Stat().cash -= cost;
974 sessionDownload[dir] += len;
978 if (!settings->GetWriteFreeMbTraffCost() &&
979 freeMb.ConstData() >= 0)
982 #ifdef TRAFF_STAT_WITH_PORTS
983 IP_DIR_PAIR idp(ip, dir, port);
985 IP_DIR_PAIR idp(ip, dir);
988 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
989 lb = traffStat.lower_bound(idp);
990 if (lb == traffStat.end() || lb->first != idp)
993 pair<IP_DIR_PAIR, STAT_NODE>(idp,
994 STAT_NODE(0, len, cost)));
998 lb->second.cash += cost;
999 lb->second.down += len;
1002 //-----------------------------------------------------------------------------
1003 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1005 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1006 currIP.AddBeforeNotifier(notifier);
1008 //-----------------------------------------------------------------------------
1009 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1011 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1012 currIP.DelBeforeNotifier(notifier);
1014 //-----------------------------------------------------------------------------
1015 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1017 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1018 currIP.AddAfterNotifier(notifier);
1020 //-----------------------------------------------------------------------------
1021 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1023 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1024 currIP.DelAfterNotifier(notifier);
1026 //-----------------------------------------------------------------------------
1027 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1029 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1030 connected.AddBeforeNotifier(notifier);
1032 //-----------------------------------------------------------------------------
1033 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1035 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1036 connected.DelBeforeNotifier(notifier);
1038 //-----------------------------------------------------------------------------
1039 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1041 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1042 connected.AddAfterNotifier(notifier);
1044 //-----------------------------------------------------------------------------
1045 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1047 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1048 connected.DelAfterNotifier(notifier);
1050 //-----------------------------------------------------------------------------
1051 void USER_IMPL::OnAdd()
1053 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1055 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1057 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1059 string scriptOnAddParams;
1060 strprintf(&scriptOnAddParams,
1062 scriptOnAdd.c_str(),
1065 ScriptExec(scriptOnAddParams.c_str());
1069 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1072 //-----------------------------------------------------------------------------
1073 void USER_IMPL::OnDelete()
1075 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1077 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1079 if (access(scriptOnDel.c_str(), X_OK) == 0)
1081 string scriptOnDelParams;
1082 strprintf(&scriptOnDelParams,
1084 scriptOnDel.c_str(),
1087 ScriptExec(scriptOnDelParams.c_str());
1091 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1096 //-----------------------------------------------------------------------------
1097 int USER_IMPL::WriteDetailStat(bool hard)
1099 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1101 if (!traffStatSaved.second.empty())
1103 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1105 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1106 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1107 WriteServLog("%s", store->GetStrError().c_str());
1110 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1116 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1120 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1122 if (ts.size() && !disabledDetailStat)
1124 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1126 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1127 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1128 WriteServLog("%s", store->GetStrError().c_str());
1131 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1132 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1133 traffStatSaved.second.swap(ts);
1134 traffStatSaved.first = lastWriteDetailedStat;
1139 lastWriteDetailedStat = stgTime;
1142 //-----------------------------------------------------------------------------
1143 double USER_IMPL::GetPassiveTimePart() const
1145 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1147 static int daysInMonth[12] =
1148 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1152 localtime_r(&t, &tms);
1154 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1156 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1159 secMonth += 24 * 3600;
1162 int dt = secMonth - passiveTime;
1167 return double(dt) / (secMonth);
1169 //-----------------------------------------------------------------------------
1170 void USER_IMPL::SetPassiveTimeAsNewUser()
1172 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1176 localtime_r(&t, &tm);
1177 int daysCurrMon = DaysInCurrentMonth();
1178 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1180 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1182 //-----------------------------------------------------------------------------
1183 void USER_IMPL::MidnightResetSessionStat()
1185 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1189 Disconnect(true, "fake");
1193 //-----------------------------------------------------------------------------
1194 void USER_IMPL::ProcessNewMonth()
1196 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1200 Disconnect(true, "fake");
1202 DIR_TRAFF zeroTarff;
1215 if (nextTariff.ConstData() != "")
1218 nt = tariffs->FindByName(nextTariff);
1221 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1222 login.c_str(), property.tariffName.Get().c_str());
1226 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1233 //-----------------------------------------------------------------------------
1234 void USER_IMPL::ProcessDayFeeSpread()
1236 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1238 if (passive.ConstData() || tariff == NULL)
1241 double fee = tariff->GetFee() / DaysInCurrentMonth();
1247 switch (settings->GetFeeChargeType())
1250 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1253 if (c + credit >= 0)
1254 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1257 if (c + credit >= fee)
1258 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1262 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1267 //-----------------------------------------------------------------------------
1268 void USER_IMPL::ProcessDayFee()
1270 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1275 double passiveTimePart = 1.0;
1276 if (!settings->GetFullFee())
1278 passiveTimePart = GetPassiveTimePart();
1282 if (passive.ConstData())
1284 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1288 double fee = tariff->GetFee() * passiveTimePart;
1299 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1306 switch (settings->GetFeeChargeType())
1309 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1313 if (c + credit >= 0)
1315 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1320 if (c + credit >= fee)
1322 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1329 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1335 //-----------------------------------------------------------------------------
1336 void USER_IMPL::SetPrepaidTraff()
1339 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1341 //-----------------------------------------------------------------------------
1342 int USER_IMPL::AddMessage(STG_MSG * msg)
1344 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1346 if (SendMessage(*msg))
1348 if (store->AddMessage(msg, login))
1350 errorStr = store->GetStrError();
1351 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1352 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1355 messages.push_back(*msg);
1359 if (msg->header.repeat > 0)
1361 msg->header.repeat--;
1363 //TODO: gcc v. 4.x generate ICE on x86_64
1364 msg->header.lastSendTime = time(NULL);
1366 msg->header.lastSendTime = stgTime;
1368 if (store->AddMessage(msg, login))
1370 errorStr = store->GetStrError();
1371 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1372 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1375 messages.push_back(*msg);
1380 //-----------------------------------------------------------------------------
1381 int USER_IMPL::SendMessage(STG_MSG & msg) const
1383 // No lock `cause we are already locked from caller
1385 set<const AUTH*>::iterator it(authorizedBy.begin());
1386 while (it != authorizedBy.end())
1388 if (!(*it++)->SendMessage(msg, currIP))
1394 //TODO: gcc v. 4.x generate ICE on x86_64
1395 msg.header.lastSendTime = time(NULL);
1397 msg.header.lastSendTime = stgTime;
1399 msg.header.repeat--;
1403 //-----------------------------------------------------------------------------
1404 void USER_IMPL::ScanMessage()
1406 // No lock `cause we are already locked from caller
1407 // We need not check for the authorizedBy `cause it has already checked by caller
1409 std::list<STG_MSG>::iterator it(messages.begin());
1410 while (it != messages.end())
1412 if (settings->GetMessageTimeout() > 0 &&
1413 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1416 if (store->DelMessage(it->header.id, login))
1418 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1419 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1421 messages.erase(it++);
1424 if (it->GetNextSendTime() <= stgTime)
1426 if (SendMessage(*it))
1428 // We need to check all messages in queue for timeout
1432 if (it->header.repeat < 0)
1434 if (store->DelMessage(it->header.id, login))
1436 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1437 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1439 messages.erase(it++);
1443 if (store->EditMessage(*it, login))
1445 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1446 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1457 //-----------------------------------------------------------------------------
1458 //-----------------------------------------------------------------------------
1459 //-----------------------------------------------------------------------------
1460 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1462 if (newPassive && !oldPassive && user->tariff != NULL)
1463 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1469 //-----------------------------------------------------------------------------
1470 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1472 if (oldValue && !newValue && user->GetConnected())
1474 user->Disconnect(false, "disabled");
1476 else if (!oldValue && newValue && user->IsInetable())
1478 user->Connect(false);
1482 //-----------------------------------------------------------------------------
1483 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1485 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1486 user->Disconnect(false, "Change tariff");
1487 user->tariff = user->tariffs->FindByName(newTariff);
1488 if (user->settings->GetReconnectOnTariffChange() &&
1489 !user->authorizedBy.empty() &&
1491 user->Connect(false);
1493 //-----------------------------------------------------------------------------
1494 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1496 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1497 user->lastCashAdd = newCash - oldCash;
1499 //-----------------------------------------------------------------------------
1500 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1502 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1503 if (user->connected)
1504 user->Disconnect(false, "Change IP");
1505 if (!user->authorizedBy.empty() && user->IsInetable())
1506 user->Connect(false);
1508 //-----------------------------------------------------------------------------