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
44 #include "stg/users.h"
45 #include "stg/common.h"
46 #include "stg/scriptexecuter.h"
47 #include "stg/tariff.h"
48 #include "stg/tariffs.h"
49 #include "stg/admin.h"
50 #include "user_impl.h"
51 #include "settings_impl.h"
52 #include "stg_timer.h"
54 #ifdef USE_ABSTRACT_SETTINGS
55 USER_IMPL::USER_IMPL(const SETTINGS * s,
62 property(s->GetScriptsDir()),
63 WriteServLog(GetStgLogger()),
68 connected(__connected),
73 lastIPForDisconnect(0),
86 lastWriteDetailedStat(0),
90 lastCashAdd(property.lastCashAdd),
91 passiveTime(property.passiveTime),
92 lastCashAddTime(property.lastCashAddTime),
93 freeMb(property.freeMb),
94 lastActivityTime(property.lastActivityTime),
95 password(property.password),
96 passive(property.passive),
97 disabled(property.disabled),
98 disabledDetailStat(property.disabledDetailStat),
99 alwaysOnline(property.alwaysOnline),
100 tariffName(property.tariffName),
101 nextTariff(property.nextTariff),
102 address(property.address),
104 group(property.group),
105 email(property.email),
106 phone(property.phone),
107 realName(property.realName),
108 credit(property.credit),
109 creditExpire(property.creditExpire),
111 userdata0(property.userdata0),
112 userdata1(property.userdata1),
113 userdata2(property.userdata2),
114 userdata3(property.userdata3),
115 userdata4(property.userdata4),
116 userdata5(property.userdata5),
117 userdata6(property.userdata6),
118 userdata7(property.userdata7),
119 userdata8(property.userdata8),
120 userdata9(property.userdata9),
123 passiveNotifier(this),
124 tariffNotifier(this),
130 password = "*_EMPTY_PASSWORD_*";
131 tariffName = NO_TARIFF_NAME;
133 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
134 lastWriteDetailedStat = stgTime;
136 property.tariffName.AddBeforeNotifier(&tariffNotifier);
137 property.passive.AddBeforeNotifier(&passiveNotifier);
138 property.disabled.AddAfterNotifier(&disabledNotifier);
139 property.cash.AddBeforeNotifier(&cashNotifier);
140 ips.AddAfterNotifier(&ipNotifier);
142 pthread_mutexattr_t attr;
143 pthread_mutexattr_init(&attr);
144 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
145 pthread_mutex_init(&mutex, &attr);
148 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
155 property(s->GetScriptsDir()),
156 WriteServLog(GetStgLogger()),
161 connected(__connected),
166 lastIPForDisconnect(0),
179 lastWriteDetailedStat(0),
183 lastCashAdd(property.lastCashAdd),
184 passiveTime(property.passiveTime),
185 lastCashAddTime(property.lastCashAddTime),
186 freeMb(property.freeMb),
187 lastActivityTime(property.lastActivityTime),
188 password(property.password),
189 passive(property.passive),
190 disabled(property.disabled),
191 disabledDetailStat(property.disabledDetailStat),
192 alwaysOnline(property.alwaysOnline),
193 tariffName(property.tariffName),
194 nextTariff(property.nextTariff),
195 address(property.address),
197 group(property.group),
198 email(property.email),
199 phone(property.phone),
200 realName(property.realName),
201 credit(property.credit),
202 creditExpire(property.creditExpire),
204 userdata0(property.userdata0),
205 userdata1(property.userdata1),
206 userdata2(property.userdata2),
207 userdata3(property.userdata3),
208 userdata4(property.userdata4),
209 userdata5(property.userdata5),
210 userdata6(property.userdata6),
211 userdata7(property.userdata7),
212 userdata8(property.userdata8),
213 userdata9(property.userdata9),
216 passiveNotifier(this),
217 disabledNotifier(this),
218 tariffNotifier(this),
224 password = "*_EMPTY_PASSWORD_*";
225 tariffName = NO_TARIFF_NAME;
227 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
228 lastWriteDetailedStat = stgTime;
230 property.tariffName.AddBeforeNotifier(&tariffNotifier);
231 property.passive.AddBeforeNotifier(&passiveNotifier);
232 property.disabled.AddAfterNotifier(&disabledNotifier);
233 property.cash.AddBeforeNotifier(&cashNotifier);
234 ips.AddAfterNotifier(&ipNotifier);
236 pthread_mutexattr_t attr;
237 pthread_mutexattr_init(&attr);
238 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
239 pthread_mutex_init(&mutex, &attr);
242 //-----------------------------------------------------------------------------
243 USER_IMPL::USER_IMPL(const USER_IMPL & u)
246 property(u.settings->GetScriptsDir()),
247 WriteServLog(GetStgLogger()),
252 connected(__connected),
254 userIDGenerator(u.userIDGenerator),
255 __currIP(u.__currIP),
257 lastIPForDisconnect(0),
258 pingTime(u.pingTime),
259 sysAdmin(u.sysAdmin),
263 traffStat(u.traffStat),
264 traffStatSaved(u.traffStatSaved),
265 settings(u.settings),
267 messages(u.messages),
269 lastWriteStat(u.lastWriteStat),
270 lastWriteDetailedStat(u.lastWriteDetailedStat),
274 lastCashAdd(property.lastCashAdd),
275 passiveTime(property.passiveTime),
276 lastCashAddTime(property.lastCashAddTime),
277 freeMb(property.freeMb),
278 lastActivityTime(property.lastActivityTime),
279 password(property.password),
280 passive(property.passive),
281 disabled(property.disabled),
282 disabledDetailStat(property.disabledDetailStat),
283 alwaysOnline(property.alwaysOnline),
284 tariffName(property.tariffName),
285 nextTariff(property.nextTariff),
286 address(property.address),
288 group(property.group),
289 email(property.email),
290 phone(property.phone),
291 realName(property.realName),
292 credit(property.credit),
293 creditExpire(property.creditExpire),
295 userdata0(property.userdata0),
296 userdata1(property.userdata1),
297 userdata2(property.userdata2),
298 userdata3(property.userdata3),
299 userdata4(property.userdata4),
300 userdata5(property.userdata5),
301 userdata6(property.userdata6),
302 userdata7(property.userdata7),
303 userdata8(property.userdata8),
304 userdata9(property.userdata9),
307 passiveNotifier(this),
308 disabledNotifier(this),
309 tariffNotifier(this),
318 property.tariffName.AddBeforeNotifier(&tariffNotifier);
319 property.passive.AddBeforeNotifier(&passiveNotifier);
320 property.disabled.AddAfterNotifier(&disabledNotifier);
321 property.cash.AddBeforeNotifier(&cashNotifier);
322 ips.AddAfterNotifier(&ipNotifier);
324 property.SetProperties(u.property);
326 pthread_mutexattr_t attr;
327 pthread_mutexattr_init(&attr);
328 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
329 pthread_mutex_init(&mutex, &attr);
331 //-----------------------------------------------------------------------------
332 USER_IMPL::~USER_IMPL()
334 property.tariffName.DelBeforeNotifier(&tariffNotifier);
335 property.passive.DelBeforeNotifier(&passiveNotifier);
336 property.disabled.DelAfterNotifier(&disabledNotifier);
337 property.cash.DelBeforeNotifier(&cashNotifier);
338 pthread_mutex_destroy(&mutex);
340 //-----------------------------------------------------------------------------
341 void USER_IMPL::SetLogin(const std::string & l)
343 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
344 assert(login.empty() && "Login is already set");
346 id = userIDGenerator.GetNextID();
348 //-----------------------------------------------------------------------------
349 int USER_IMPL::ReadConf()
351 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
354 if (store->RestoreUserConf(&conf, login))
356 WriteServLog("Cannot read conf for user %s.", login.c_str());
357 WriteServLog("%s", store->GetStrError().c_str());
358 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
359 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
363 property.SetConf(conf);
365 tariff = tariffs->FindByName(tariffName);
368 WriteServLog("Cannot read user %s. Tariff %s not exist.",
369 login.c_str(), property.tariffName.Get().c_str());
373 std::vector<STG_MSG_HDR> hdrsList;
375 if (store->GetMessageHdrs(&hdrsList, login))
377 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
378 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
380 store->GetStrError().c_str());
384 std::vector<STG_MSG_HDR>::const_iterator it;
385 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
388 if (store->GetMessage(it->id, &msg, login) == 0)
390 messages.push_back(msg);
396 //-----------------------------------------------------------------------------
397 int USER_IMPL::ReadStat()
399 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
402 if (store->RestoreUserStat(&stat, login))
404 WriteServLog("Cannot read stat for user %s.", login.c_str());
405 WriteServLog("%s", store->GetStrError().c_str());
406 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
407 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
411 property.SetStat(stat);
415 //-----------------------------------------------------------------------------
416 int USER_IMPL::WriteConf()
418 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
419 USER_CONF conf(property.GetConf());
421 printfd(__FILE__, "USER::WriteConf()\n");
423 if (store->SaveUserConf(conf, login))
425 WriteServLog("Cannot write conf for user %s.", login.c_str());
426 WriteServLog("%s", store->GetStrError().c_str());
427 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
428 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
434 //-----------------------------------------------------------------------------
435 int USER_IMPL::WriteStat()
437 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
438 USER_STAT stat(property.GetStat());
440 if (store->SaveUserStat(stat, login))
442 WriteServLog("Cannot write stat for user %s.", login.c_str());
443 WriteServLog("%s", store->GetStrError().c_str());
444 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
445 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
449 lastWriteStat = stgTime;
453 //-----------------------------------------------------------------------------
454 int USER_IMPL::WriteMonthStat()
456 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
457 time_t tt = stgTime - 3600;
459 localtime_r(&tt, &t1);
461 USER_STAT stat(property.GetStat());
462 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
464 WriteServLog("Cannot write month stat for user %s.", login.c_str());
465 WriteServLog("%s", store->GetStrError().c_str());
466 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
467 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
473 //-----------------------------------------------------------------------------
474 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
476 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
478 * Authorize user. It only means that user will be authorized. Nothing more.
479 * User can be connected or disconnected while authorized.
480 * Example: user is authorized but disconnected due to 0 money or blocking
484 * Prevent double authorization by identical authorizers
486 if (authorizedBy.find(auth) != authorizedBy.end())
492 for (int i = 0; i < DIR_NUM; i++)
494 enabledDirs[i] = dirs & (1 << i);
497 if (!authorizedBy.empty())
501 // We are already authorized, but with different IP address
502 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
507 if (!users->FindByIPIdx(ip, &u))
509 // Address is already present in IP-index
510 // If it's not our IP - throw an error
513 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
520 if (users->IsIPInIndex(ip))
522 // Address is already present in IP-index
523 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
527 if (ips.ConstData().IsIPInIPS(ip))
530 lastIPForDisconnect = currIP;
534 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
535 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
540 authorizedBy.insert(auth);
546 //-----------------------------------------------------------------------------
547 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
549 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
551 * Authorizer tries to unauthorize user, that was not authorized by it
553 if (!authorizedBy.erase(auth))
556 if (authorizedBy.empty())
558 lastDisconnectReason = reason;
559 lastIPForDisconnect = currIP;
560 currIP = 0; // DelUser in traffcounter
564 //-----------------------------------------------------------------------------
565 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
567 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
568 // Is this user authorized by specified authorizer?
569 return authorizedBy.find(auth) != authorizedBy.end();
571 //-----------------------------------------------------------------------------
572 std::vector<std::string> USER_IMPL::GetAuthorizers() const
574 std::vector<std::string> list;
575 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
578 //-----------------------------------------------------------------------------
579 void USER_IMPL::Connect(bool fakeConnect)
582 * Connect user to Internet. This function is differ from Authorize() !!!
585 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
589 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
591 if (access(scriptOnConnect.c_str(), X_OK) == 0)
593 char dirsStr[DIR_NUM + 1];
594 dirsStr[DIR_NUM] = 0;
595 for (int i = 0; i < DIR_NUM; i++)
597 dirsStr[i] = enabledDirs[i] ? '1' : '0';
600 std::string scriptOnConnectParams;
601 strprintf(&scriptOnConnectParams,
602 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
603 scriptOnConnect.c_str(),
605 inet_ntostring(currIP).c_str(),
610 ScriptExec(scriptOnConnectParams.c_str());
614 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
620 if (store->WriteUserConnect(login, currIP))
622 WriteServLog("Cannot write connect for user %s.", login.c_str());
623 WriteServLog("%s", store->GetStrError().c_str());
627 lastIPForDisconnect = currIP;
629 //-----------------------------------------------------------------------------
630 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
633 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
636 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
638 if (!lastIPForDisconnect)
640 printfd(__FILE__, "lastIPForDisconnect\n");
646 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
648 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
650 char dirsStr[DIR_NUM + 1];
651 dirsStr[DIR_NUM] = 0;
652 for (int i = 0; i < DIR_NUM; i++)
654 dirsStr[i] = enabledDirs[i] ? '1' : '0';
657 std::string scriptOnDisonnectParams;
658 strprintf(&scriptOnDisonnectParams,
659 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
660 scriptOnDisonnect.c_str(),
662 inet_ntostring(lastIPForDisconnect).c_str(),
667 ScriptExec(scriptOnDisonnectParams.c_str());
671 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
677 std::string reasonMessage(reason);
678 if (!lastDisconnectReason.empty())
679 reasonMessage += ": " + lastDisconnectReason;
681 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
682 cash, freeMb, reasonMessage))
684 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
685 WriteServLog("%s", store->GetStrError().c_str());
689 lastIPForDisconnect = 0;
691 DIR_TRAFF zeroSesssion;
693 sessionUpload = zeroSesssion;
694 sessionDownload = zeroSesssion;
696 //-----------------------------------------------------------------------------
697 void USER_IMPL::PrintUser() const
700 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
701 std::cout << "============================================================" << std::endl;
702 std::cout << "id=" << id << std::endl;
703 std::cout << "login=" << login << std::endl;
704 std::cout << "password=" << password << std::endl;
705 std::cout << "passive=" << passive << std::endl;
706 std::cout << "disabled=" << disabled << std::endl;
707 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
708 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
709 std::cout << "tariffName=" << tariffName << std::endl;
710 std::cout << "address=" << address << std::endl;
711 std::cout << "phone=" << phone << std::endl;
712 std::cout << "email=" << email << std::endl;
713 std::cout << "note=" << note << std::endl;
714 std::cout << "realName=" <<realName << std::endl;
715 std::cout << "group=" << group << std::endl;
716 std::cout << "credit=" << credit << std::endl;
717 std::cout << "nextTariff=" << nextTariff << std::endl;
718 std::cout << "userdata0" << userdata0 << std::endl;
719 std::cout << "userdata1" << userdata1 << std::endl;
720 std::cout << "creditExpire=" << creditExpire << std::endl;
721 std::cout << "ips=" << ips << std::endl;
722 std::cout << "------------------------" << std::endl;
723 std::cout << "up=" << up << std::endl;
724 std::cout << "down=" << down << std::endl;
725 std::cout << "cash=" << cash << std::endl;
726 std::cout << "freeMb=" << freeMb << std::endl;
727 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
728 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
729 std::cout << "passiveTime=" << passiveTime << std::endl;
730 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
731 std::cout << "============================================================" << std::endl;
733 //-----------------------------------------------------------------------------
734 void USER_IMPL::Run()
736 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
738 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
740 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
743 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
745 WriteServLog("User: %s. Credit expired.", login.c_str());
751 if (passive.ConstData()
752 && (stgTime % 30 == 0)
753 && (passiveTime.ModificationTime() != stgTime))
755 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
756 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
759 if (!authorizedBy.empty())
763 property.Stat().lastActivityTime = stgTime;
765 if (!connected && IsInetable())
769 if (connected && !IsInetable())
772 Disconnect(false, "disabled");
774 Disconnect(false, "passive");
776 Disconnect(false, "no cash");
779 if (stgTime - lastScanMessages > 10)
782 lastScanMessages = stgTime;
789 Disconnect(false, "not authorized");
794 //-----------------------------------------------------------------------------
795 void USER_IMPL::UpdatePingTime(time_t t)
797 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
798 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
804 //-----------------------------------------------------------------------------
805 bool USER_IMPL::IsInetable()
807 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
809 if (disabled || passive)
812 if (settings->GetFreeMbAllowInet())
818 if (settings->GetShowFeeInCash() || tariff == NULL)
820 return (cash >= -credit);
823 return (cash - tariff->GetFee() >= -credit);
825 //-----------------------------------------------------------------------------
826 std::string USER_IMPL::GetEnabledDirs()
828 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
830 std::string dirs = "";
831 for(int i = 0; i < DIR_NUM; i++)
832 dirs += enabledDirs[i] ? "1" : "0";
835 //-----------------------------------------------------------------------------
836 #ifdef TRAFF_STAT_WITH_PORTS
837 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
839 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
842 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
844 if (!connected || tariff == NULL)
850 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
851 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
855 int tt = tariff->GetTraffType();
856 if (tt == TRAFF_UP ||
857 tt == TRAFF_UP_DOWN ||
858 // Check NEW traff data
859 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
862 if (traff < threshold &&
863 traff + len >= threshold)
865 // cash = partBeforeThreshold * priceBeforeThreshold +
866 // partAfterThreshold * priceAfterThreshold
867 int64_t before = threshold - traff; // Chunk part before threshold
868 int64_t after = len - before; // Chunk part after threshold
869 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
870 down.ConstData()[dir],
873 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
874 down.ConstData()[dir],
880 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
881 down.ConstData()[dir],
886 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
888 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
889 cost = dc - freeMb.ConstData();
891 // Direct access to internal data structures via friend-specifier
892 property.Stat().freeMb -= dc;
893 property.Stat().cash -= cost;
899 sessionUpload[dir] += len;
903 if (!settings->GetWriteFreeMbTraffCost() &&
904 freeMb.ConstData() >= 0)
907 #ifdef TRAFF_STAT_WITH_PORTS
908 IP_DIR_PAIR idp(ip, dir, port);
910 IP_DIR_PAIR idp(ip, dir);
913 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
914 lb = traffStat.lower_bound(idp);
915 if (lb == traffStat.end() || lb->first != idp)
919 STAT_NODE(len, 0, cost)));
923 lb->second.cash += cost;
924 lb->second.up += len;
927 //-----------------------------------------------------------------------------
928 #ifdef TRAFF_STAT_WITH_PORTS
929 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
931 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
934 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
936 if (!connected || tariff == NULL)
942 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
943 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
947 int tt = tariff->GetTraffType();
948 if (tt == TRAFF_DOWN ||
949 tt == TRAFF_UP_DOWN ||
950 // Check NEW traff data
951 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
954 if (traff < threshold &&
955 traff + len >= threshold)
957 // cash = partBeforeThreshold * priceBeforeThreshold +
958 // partAfterThreshold * priceAfterThreshold
959 int64_t before = threshold - traff; // Chunk part before threshold
960 int64_t after = len - before; // Chunk part after threshold
961 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
962 down.ConstData()[dir], // Traff before chunk
965 tariff->GetPriceWithTraffType(up.ConstData()[dir],
966 dt[dir], // Traff after chunk
972 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
973 down.ConstData()[dir],
978 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
980 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
981 cost = dc - freeMb.ConstData();
983 property.Stat().freeMb -= dc;
984 property.Stat().cash -= cost;
990 sessionDownload[dir] += len;
994 if (!settings->GetWriteFreeMbTraffCost() &&
995 freeMb.ConstData() >= 0)
998 #ifdef TRAFF_STAT_WITH_PORTS
999 IP_DIR_PAIR idp(ip, dir, port);
1001 IP_DIR_PAIR idp(ip, dir);
1004 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
1005 lb = traffStat.lower_bound(idp);
1006 if (lb == traffStat.end() || lb->first != idp)
1008 traffStat.insert(lb,
1010 STAT_NODE(0, len, cost)));
1014 lb->second.cash += cost;
1015 lb->second.down += len;
1018 //-----------------------------------------------------------------------------
1019 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1021 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1022 currIP.AddBeforeNotifier(notifier);
1024 //-----------------------------------------------------------------------------
1025 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1027 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1028 currIP.DelBeforeNotifier(notifier);
1030 //-----------------------------------------------------------------------------
1031 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1033 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1034 currIP.AddAfterNotifier(notifier);
1036 //-----------------------------------------------------------------------------
1037 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1039 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1040 currIP.DelAfterNotifier(notifier);
1042 //-----------------------------------------------------------------------------
1043 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1045 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1046 connected.AddBeforeNotifier(notifier);
1048 //-----------------------------------------------------------------------------
1049 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1051 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1052 connected.DelBeforeNotifier(notifier);
1054 //-----------------------------------------------------------------------------
1055 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1057 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1058 connected.AddAfterNotifier(notifier);
1060 //-----------------------------------------------------------------------------
1061 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1063 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1064 connected.DelAfterNotifier(notifier);
1066 //-----------------------------------------------------------------------------
1067 void USER_IMPL::OnAdd()
1069 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1071 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1073 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1075 std::string scriptOnAddParams;
1076 strprintf(&scriptOnAddParams,
1078 scriptOnAdd.c_str(),
1081 ScriptExec(scriptOnAddParams.c_str());
1085 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1088 //-----------------------------------------------------------------------------
1089 void USER_IMPL::OnDelete()
1091 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1093 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1095 if (access(scriptOnDel.c_str(), X_OK) == 0)
1097 std::string scriptOnDelParams;
1098 strprintf(&scriptOnDelParams,
1100 scriptOnDel.c_str(),
1103 ScriptExec(scriptOnDelParams.c_str());
1107 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1112 //-----------------------------------------------------------------------------
1113 int USER_IMPL::WriteDetailStat(bool hard)
1115 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1117 if (!traffStatSaved.second.empty())
1119 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1121 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1122 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1123 WriteServLog("%s", store->GetStrError().c_str());
1126 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1132 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1136 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1138 if (ts.size() && !disabledDetailStat)
1140 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1142 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1143 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1144 WriteServLog("%s", store->GetStrError().c_str());
1147 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1148 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1149 traffStatSaved.second.swap(ts);
1150 traffStatSaved.first = lastWriteDetailedStat;
1155 lastWriteDetailedStat = stgTime;
1158 //-----------------------------------------------------------------------------
1159 double USER_IMPL::GetPassiveTimePart() const
1161 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1163 static int daysInMonth[12] =
1164 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1168 localtime_r(&t, &tms);
1170 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1172 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1175 secMonth += 24 * 3600;
1178 time_t dt = secMonth - passiveTime;
1183 return static_cast<double>(dt) / secMonth;
1185 //-----------------------------------------------------------------------------
1186 void USER_IMPL::SetPassiveTimeAsNewUser()
1188 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1192 localtime_r(&t, &tm);
1193 int daysCurrMon = DaysInCurrentMonth();
1194 double pt = tm.tm_mday - 1;
1197 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1199 //-----------------------------------------------------------------------------
1200 void USER_IMPL::MidnightResetSessionStat()
1202 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1206 Disconnect(true, "fake");
1210 //-----------------------------------------------------------------------------
1211 void USER_IMPL::ProcessNewMonth()
1213 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1217 Disconnect(true, "fake");
1219 DIR_TRAFF zeroTarff;
1232 if (nextTariff.ConstData() != "")
1235 nt = tariffs->FindByName(nextTariff);
1238 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1239 login.c_str(), property.tariffName.Get().c_str());
1243 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1250 //-----------------------------------------------------------------------------
1251 void USER_IMPL::ProcessDayFeeSpread()
1253 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1255 if (passive.ConstData() || tariff == NULL)
1258 double fee = tariff->GetFee() / DaysInCurrentMonth();
1260 if (std::fabs(fee) < 1.0e-3)
1264 switch (settings->GetFeeChargeType())
1267 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1270 if (c + credit >= 0)
1271 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1274 if (c + credit >= fee)
1275 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1279 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1284 //-----------------------------------------------------------------------------
1285 void USER_IMPL::ProcessDayFee()
1287 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1292 double passiveTimePart = 1.0;
1293 if (!settings->GetFullFee())
1295 passiveTimePart = GetPassiveTimePart();
1299 if (passive.ConstData())
1301 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1305 double fee = tariff->GetFee() * passiveTimePart;
1309 if (std::fabs(fee) < 1.0e-3)
1316 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1323 switch (settings->GetFeeChargeType())
1326 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1330 if (c + credit >= 0)
1332 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1337 if (c + credit >= fee)
1339 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1346 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1352 //-----------------------------------------------------------------------------
1353 void USER_IMPL::SetPrepaidTraff()
1356 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1358 //-----------------------------------------------------------------------------
1359 int USER_IMPL::AddMessage(STG_MSG * msg)
1361 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1363 if (SendMessage(*msg))
1365 if (store->AddMessage(msg, login))
1367 errorStr = store->GetStrError();
1368 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1369 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1372 messages.push_back(*msg);
1376 if (msg->header.repeat > 0)
1378 msg->header.repeat--;
1380 //TODO: gcc v. 4.x generate ICE on x86_64
1381 msg->header.lastSendTime = static_cast<int>(time(NULL));
1383 msg->header.lastSendTime = static_cast<int>(stgTime);
1385 if (store->AddMessage(msg, login))
1387 errorStr = store->GetStrError();
1388 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1389 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1392 messages.push_back(*msg);
1397 //-----------------------------------------------------------------------------
1398 int USER_IMPL::SendMessage(STG_MSG & msg) const
1400 // No lock `cause we are already locked from caller
1402 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1403 while (it != authorizedBy.end())
1405 if (!(*it++)->SendMessage(msg, currIP))
1411 //TODO: gcc v. 4.x generate ICE on x86_64
1412 msg.header.lastSendTime = static_cast<int>(time(NULL));
1414 msg.header.lastSendTime = static_cast<int>(stgTime);
1416 msg.header.repeat--;
1420 //-----------------------------------------------------------------------------
1421 void USER_IMPL::ScanMessage()
1423 // No lock `cause we are already locked from caller
1424 // We need not check for the authorizedBy `cause it has already checked by caller
1426 std::list<STG_MSG>::iterator it(messages.begin());
1427 while (it != messages.end())
1429 if (settings->GetMessageTimeout() > 0 &&
1430 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1433 if (store->DelMessage(it->header.id, login))
1435 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1436 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1438 messages.erase(it++);
1441 if (it->GetNextSendTime() <= stgTime)
1443 if (SendMessage(*it))
1445 // We need to check all messages in queue for timeout
1449 if (it->header.repeat < 0)
1451 if (store->DelMessage(it->header.id, login))
1453 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1454 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1456 messages.erase(it++);
1460 if (store->EditMessage(*it, login))
1462 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1463 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1474 //-----------------------------------------------------------------------------
1475 //-----------------------------------------------------------------------------
1476 //-----------------------------------------------------------------------------
1477 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1479 if (newPassive && !oldPassive && user->tariff != NULL)
1480 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1486 //-----------------------------------------------------------------------------
1487 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1489 if (oldValue && !newValue && user->GetConnected())
1491 user->Disconnect(false, "disabled");
1493 else if (!oldValue && newValue && user->IsInetable())
1495 user->Connect(false);
1499 //-----------------------------------------------------------------------------
1500 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1502 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1503 user->Disconnect(false, "Change tariff");
1504 user->tariff = user->tariffs->FindByName(newTariff);
1505 if (user->settings->GetReconnectOnTariffChange() &&
1506 !user->authorizedBy.empty() &&
1508 user->Connect(false);
1510 //-----------------------------------------------------------------------------
1511 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1513 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1514 user->lastCashAdd = newCash - oldCash;
1516 //-----------------------------------------------------------------------------
1517 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1519 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1520 if (user->connected)
1521 user->Disconnect(false, "Change IP");
1522 if (!user->authorizedBy.empty() && user->IsInetable())
1523 user->Connect(false);
1525 //-----------------------------------------------------------------------------