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 $
35 #include "user_impl.h"
36 #include "settings_impl.h"
37 #include "stg_timer.h"
39 #include "stg/users.h"
40 #include "stg/common.h"
41 #include "stg/scriptexecuter.h"
42 #include "stg/tariff.h"
43 #include "stg/tariffs.h"
44 #include "stg/admin.h"
54 #include <unistd.h> // access
59 std::string dirsToString(const bool * dirs)
62 for (size_t i = 0; i < DIR_NUM; i++)
63 res += dirs[i] ? '1' : '0';
67 void dirsFromBits(bool * dirs, uint32_t bits)
69 for (size_t i = 0; i < DIR_NUM; i++)
70 dirs[i] = bits & (1 << i);
75 #ifdef USE_ABSTRACT_SETTINGS
76 USER_IMPL::USER_IMPL(const SETTINGS * s,
82 property(s->GetScriptsDir()),
83 WriteServLog(GetStgLogger()),
87 connected(__connected),
90 lastIPForDisconnect(0),
97 authorizedModificationTime(0),
100 lastWriteDetailedStat(0),
104 lastCashAdd(property.lastCashAdd),
105 passiveTime(property.passiveTime),
106 lastCashAddTime(property.lastCashAddTime),
107 freeMb(property.freeMb),
108 lastActivityTime(property.lastActivityTime),
109 password(property.password),
110 passive(property.passive),
111 disabled(property.disabled),
112 disabledDetailStat(property.disabledDetailStat),
113 alwaysOnline(property.alwaysOnline),
114 tariffName(property.tariffName),
115 nextTariff(property.nextTariff),
116 address(property.address),
118 group(property.group),
119 email(property.email),
120 phone(property.phone),
121 realName(property.realName),
122 credit(property.credit),
123 creditExpire(property.creditExpire),
125 userdata0(property.userdata0),
126 userdata1(property.userdata1),
127 userdata2(property.userdata2),
128 userdata3(property.userdata3),
129 userdata4(property.userdata4),
130 userdata5(property.userdata5),
131 userdata6(property.userdata6),
132 userdata7(property.userdata7),
133 userdata8(property.userdata8),
134 userdata9(property.userdata9),
135 passiveNotifier(this),
136 disabledNotifier(this),
137 tariffNotifier(this),
144 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
150 property(s->GetScriptsDir()),
151 WriteServLog(GetStgLogger()),
155 connected(__connected),
158 lastIPForDisconnect(0),
165 authorizedModificationTime(0),
168 lastWriteDetailedStat(0),
172 lastCashAdd(property.lastCashAdd),
173 passiveTime(property.passiveTime),
174 lastCashAddTime(property.lastCashAddTime),
175 freeMb(property.freeMb),
176 lastActivityTime(property.lastActivityTime),
177 password(property.password),
178 passive(property.passive),
179 disabled(property.disabled),
180 disabledDetailStat(property.disabledDetailStat),
181 alwaysOnline(property.alwaysOnline),
182 tariffName(property.tariffName),
183 nextTariff(property.nextTariff),
184 address(property.address),
186 group(property.group),
187 email(property.email),
188 phone(property.phone),
189 realName(property.realName),
190 credit(property.credit),
191 creditExpire(property.creditExpire),
193 userdata0(property.userdata0),
194 userdata1(property.userdata1),
195 userdata2(property.userdata2),
196 userdata3(property.userdata3),
197 userdata4(property.userdata4),
198 userdata5(property.userdata5),
199 userdata6(property.userdata6),
200 userdata7(property.userdata7),
201 userdata8(property.userdata8),
202 userdata9(property.userdata9),
203 passiveNotifier(this),
204 disabledNotifier(this),
205 tariffNotifier(this),
212 //-----------------------------------------------------------------------------
213 void USER_IMPL::Init()
215 password = "*_EMPTY_PASSWORD_*";
216 tariffName = NO_TARIFF_NAME;
218 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
219 lastWriteDetailedStat = stgTime;
221 property.tariffName.AddBeforeNotifier(&tariffNotifier);
222 property.passive.AddBeforeNotifier(&passiveNotifier);
223 property.disabled.AddAfterNotifier(&disabledNotifier);
224 property.cash.AddBeforeNotifier(&cashNotifier);
225 ips.AddAfterNotifier(&ipNotifier);
227 pthread_mutexattr_t attr;
228 pthread_mutexattr_init(&attr);
229 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
230 pthread_mutex_init(&mutex, &attr);
232 //-----------------------------------------------------------------------------
233 USER_IMPL::USER_IMPL(const USER_IMPL & u)
236 property(u.settings->GetScriptsDir()),
237 WriteServLog(GetStgLogger()),
242 connected(__connected),
243 userIDGenerator(u.userIDGenerator),
244 __currIP(u.__currIP),
246 lastIPForDisconnect(0),
247 pingTime(u.pingTime),
248 sysAdmin(u.sysAdmin),
252 traffStat(u.traffStat),
253 traffStatSaved(u.traffStatSaved),
254 settings(u.settings),
255 authorizedModificationTime(u.authorizedModificationTime),
256 messages(u.messages),
258 lastWriteStat(u.lastWriteStat),
259 lastWriteDetailedStat(u.lastWriteDetailedStat),
263 lastCashAdd(property.lastCashAdd),
264 passiveTime(property.passiveTime),
265 lastCashAddTime(property.lastCashAddTime),
266 freeMb(property.freeMb),
267 lastActivityTime(property.lastActivityTime),
268 password(property.password),
269 passive(property.passive),
270 disabled(property.disabled),
271 disabledDetailStat(property.disabledDetailStat),
272 alwaysOnline(property.alwaysOnline),
273 tariffName(property.tariffName),
274 nextTariff(property.nextTariff),
275 address(property.address),
277 group(property.group),
278 email(property.email),
279 phone(property.phone),
280 realName(property.realName),
281 credit(property.credit),
282 creditExpire(property.creditExpire),
284 userdata0(property.userdata0),
285 userdata1(property.userdata1),
286 userdata2(property.userdata2),
287 userdata3(property.userdata3),
288 userdata4(property.userdata4),
289 userdata5(property.userdata5),
290 userdata6(property.userdata6),
291 userdata7(property.userdata7),
292 userdata8(property.userdata8),
293 userdata9(property.userdata9),
296 passiveNotifier(this),
297 disabledNotifier(this),
298 tariffNotifier(this),
305 property.tariffName.AddBeforeNotifier(&tariffNotifier);
306 property.passive.AddBeforeNotifier(&passiveNotifier);
307 property.disabled.AddAfterNotifier(&disabledNotifier);
308 property.cash.AddBeforeNotifier(&cashNotifier);
309 ips.AddAfterNotifier(&ipNotifier);
311 property.SetProperties(u.property);
313 pthread_mutexattr_t attr;
314 pthread_mutexattr_init(&attr);
315 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
316 pthread_mutex_init(&mutex, &attr);
318 //-----------------------------------------------------------------------------
319 USER_IMPL::~USER_IMPL()
321 property.tariffName.DelBeforeNotifier(&tariffNotifier);
322 property.passive.DelBeforeNotifier(&passiveNotifier);
323 property.disabled.DelAfterNotifier(&disabledNotifier);
324 property.cash.DelBeforeNotifier(&cashNotifier);
325 pthread_mutex_destroy(&mutex);
327 //-----------------------------------------------------------------------------
328 void USER_IMPL::SetLogin(const std::string & l)
330 STG_LOCKER lock(&mutex);
331 assert(login.empty() && "Login is already set");
333 id = userIDGenerator.GetNextID();
335 //-----------------------------------------------------------------------------
336 int USER_IMPL::ReadConf()
338 STG_LOCKER lock(&mutex);
341 if (store->RestoreUserConf(&conf, login))
343 WriteServLog("Cannot read conf for user %s.", login.c_str());
344 WriteServLog("%s", store->GetStrError().c_str());
345 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
346 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
350 property.SetConf(conf);
352 tariff = tariffs->FindByName(tariffName);
355 WriteServLog("Cannot read user %s. Tariff %s not exist.",
356 login.c_str(), property.tariffName.Get().c_str());
360 std::vector<STG_MSG_HDR> hdrsList;
362 if (store->GetMessageHdrs(&hdrsList, login))
364 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
365 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
367 store->GetStrError().c_str());
371 std::vector<STG_MSG_HDR>::const_iterator it;
372 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
375 if (store->GetMessage(it->id, &msg, login) == 0)
377 messages.push_back(msg);
383 //-----------------------------------------------------------------------------
384 int USER_IMPL::ReadStat()
386 STG_LOCKER lock(&mutex);
389 if (store->RestoreUserStat(&stat, login))
391 WriteServLog("Cannot read stat for user %s.", login.c_str());
392 WriteServLog("%s", store->GetStrError().c_str());
393 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
394 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
398 property.SetStat(stat);
402 //-----------------------------------------------------------------------------
403 int USER_IMPL::WriteConf()
405 STG_LOCKER lock(&mutex);
406 USER_CONF conf(property.GetConf());
408 printfd(__FILE__, "USER::WriteConf()\n");
410 if (store->SaveUserConf(conf, login))
412 WriteServLog("Cannot write conf for user %s.", login.c_str());
413 WriteServLog("%s", store->GetStrError().c_str());
414 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
415 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
421 //-----------------------------------------------------------------------------
422 int USER_IMPL::WriteStat()
424 STG_LOCKER lock(&mutex);
425 USER_STAT stat(property.GetStat());
427 if (store->SaveUserStat(stat, login))
429 WriteServLog("Cannot write stat for user %s.", login.c_str());
430 WriteServLog("%s", store->GetStrError().c_str());
431 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
432 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
436 lastWriteStat = stgTime;
440 //-----------------------------------------------------------------------------
441 int USER_IMPL::WriteMonthStat()
443 STG_LOCKER lock(&mutex);
444 time_t tt = stgTime - 3600;
446 localtime_r(&tt, &t1);
448 USER_STAT stat(property.GetStat());
449 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
451 WriteServLog("Cannot write month stat for user %s.", login.c_str());
452 WriteServLog("%s", store->GetStrError().c_str());
453 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
454 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
460 //-----------------------------------------------------------------------------
461 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
463 STG_LOCKER lock(&mutex);
465 * Authorize user. It only means that user will be authorized. Nothing more.
466 * User can be connected or disconnected while authorized.
467 * Example: user is authorized but disconnected due to 0 money or blocking
471 * TODO: in fact "authorization" means allowing access to a service. What we
472 * call "authorization" here, int STG, is "authentication". So this should be
477 * Prevent double authorization by identical authorizers
479 if (authorizedBy.find(auth) != authorizedBy.end())
485 dirsFromBits(enabledDirs, dirs);
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 presents in IP-index.
500 // If it's not our IP - report it.
503 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
510 if (users->IsIPInIndex(ip))
512 // Address is already present in IP-index.
513 errorStr = "IP address " + inet_ntostring(ip) + " is 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) + " does not belong to user " + login;
530 if (authorizedBy.empty())
531 authorizedModificationTime = stgTime;
532 authorizedBy.insert(auth);
538 //-----------------------------------------------------------------------------
539 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
541 STG_LOCKER lock(&mutex);
543 * Authorizer tries to unauthorize user, that was not authorized by it
545 if (!authorizedBy.erase(auth))
548 authorizedModificationTime = stgTime;
550 if (authorizedBy.empty())
552 lastDisconnectReason = reason;
553 lastIPForDisconnect = currIP;
554 currIP = 0; // DelUser in traffcounter
558 //-----------------------------------------------------------------------------
559 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
561 STG_LOCKER lock(&mutex);
562 // Is this user authorized by specified authorizer?
563 return authorizedBy.find(auth) != authorizedBy.end();
565 //-----------------------------------------------------------------------------
566 std::vector<std::string> USER_IMPL::GetAuthorizers() const
568 STG_LOCKER lock(&mutex);
569 std::vector<std::string> list;
570 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
573 //-----------------------------------------------------------------------------
574 void USER_IMPL::Connect(bool fakeConnect)
577 * Connect user to Internet. This function is differ from Authorize() !!!
580 STG_LOCKER lock(&mutex);
584 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
586 if (access(scriptOnConnect.c_str(), X_OK) == 0)
588 std::string dirs = dirsToString(enabledDirs);
590 std::string scriptOnConnectParams;
591 strprintf(&scriptOnConnectParams,
592 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
593 scriptOnConnect.c_str(),
595 inet_ntostring(currIP).c_str(),
600 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
601 while (it != settings->GetScriptParams().end())
603 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
607 ScriptExec(scriptOnConnectParams.c_str());
611 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
617 if (store->WriteUserConnect(login, currIP))
619 WriteServLog("Cannot write connect for user %s.", login.c_str());
620 WriteServLog("%s", store->GetStrError().c_str());
624 lastIPForDisconnect = currIP;
626 //-----------------------------------------------------------------------------
627 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
630 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
633 STG_LOCKER lock(&mutex);
635 if (!lastIPForDisconnect)
637 printfd(__FILE__, "lastIPForDisconnect\n");
643 lastDisconnectReason = reason;
644 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
646 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
648 std::string dirs = dirsToString(enabledDirs);
650 std::string scriptOnDisonnectParams;
651 strprintf(&scriptOnDisonnectParams,
652 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
653 scriptOnDisonnect.c_str(),
655 inet_ntostring(lastIPForDisconnect).c_str(),
660 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
661 while (it != settings->GetScriptParams().end())
663 scriptOnDisonnectParams += " \"" + GetParamValue(it->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 sessionUpload.Reset();
692 sessionDownload.Reset();
693 sessionUploadModTime = stgTime;
694 sessionDownloadModTime = stgTime;
696 //-----------------------------------------------------------------------------
697 void USER_IMPL::Run()
699 STG_LOCKER lock(&mutex);
701 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
703 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
706 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
708 WriteServLog("User: %s. Credit expired.", login.c_str());
714 if (passive.ConstData()
715 && (stgTime % 30 == 0)
716 && (passiveTime.ModificationTime() != stgTime))
718 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
719 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
722 if (!authorizedBy.empty())
725 property.Stat().lastActivityTime = stgTime;
727 if (!connected && IsInetable())
730 if (connected && !IsInetable())
733 Disconnect(false, "disabled");
735 Disconnect(false, "passive");
737 Disconnect(false, "no cash");
740 if (stgTime - lastScanMessages > 10)
743 lastScanMessages = stgTime;
749 Disconnect(false, "not authorized");
753 //-----------------------------------------------------------------------------
754 void USER_IMPL::UpdatePingTime(time_t t)
756 STG_LOCKER lock(&mutex);
762 //-----------------------------------------------------------------------------
763 bool USER_IMPL::IsInetable()
765 if (disabled || passive)
768 if (settings->GetFreeMbAllowInet())
774 if (settings->GetShowFeeInCash() || tariff == NULL)
775 return (cash >= -credit);
777 return (cash - tariff->GetFee() >= -credit);
779 //-----------------------------------------------------------------------------
780 std::string USER_IMPL::GetEnabledDirs() const
782 return dirsToString(enabledDirs);
784 //-----------------------------------------------------------------------------
785 #ifdef TRAFF_STAT_WITH_PORTS
786 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
788 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
791 STG_LOCKER lock(&mutex);
793 if (!connected || tariff == NULL)
799 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
800 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
804 int tt = tariff->GetTraffType();
805 if (tt == TARIFF::TRAFF_UP ||
806 tt == TARIFF::TRAFF_UP_DOWN ||
807 // Check NEW traff data
808 (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
811 if (traff < threshold &&
812 traff + len >= threshold)
814 // cash = partBeforeThreshold * priceBeforeThreshold +
815 // partAfterThreshold * priceAfterThreshold
816 int64_t before = threshold - traff; // Chunk part before threshold
817 int64_t after = len - before; // Chunk part after threshold
818 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
819 down.ConstData()[dir],
822 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
823 down.ConstData()[dir],
829 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
830 down.ConstData()[dir],
835 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
837 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
838 cost = dc - freeMb.ConstData();
840 // Direct access to internal data structures via friend-specifier
841 property.Stat().freeMb -= dc;
842 property.Stat().cash -= cost;
848 sessionUpload[dir] += len;
849 sessionUploadModTime = stgTime;
853 if (!settings->GetWriteFreeMbTraffCost() &&
854 freeMb.ConstData() >= 0)
857 #ifdef TRAFF_STAT_WITH_PORTS
858 IP_DIR_PAIR idp(ip, dir, port);
860 IP_DIR_PAIR idp(ip, dir);
863 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
864 lb = traffStat.lower_bound(idp);
865 if (lb == traffStat.end() || lb->first != idp)
869 STAT_NODE(len, 0, cost)));
873 lb->second.cash += cost;
874 lb->second.up += len;
877 //-----------------------------------------------------------------------------
878 #ifdef TRAFF_STAT_WITH_PORTS
879 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
881 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
884 STG_LOCKER lock(&mutex);
886 if (!connected || tariff == NULL)
892 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
893 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
897 int tt = tariff->GetTraffType();
898 if (tt == TARIFF::TRAFF_DOWN ||
899 tt == TARIFF::TRAFF_UP_DOWN ||
900 // Check NEW traff data
901 (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
904 if (traff < threshold &&
905 traff + len >= threshold)
907 // cash = partBeforeThreshold * priceBeforeThreshold +
908 // partAfterThreshold * priceAfterThreshold
909 int64_t before = threshold - traff; // Chunk part before threshold
910 int64_t after = len - before; // Chunk part after threshold
911 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
912 down.ConstData()[dir], // Traff before chunk
915 tariff->GetPriceWithTraffType(up.ConstData()[dir],
916 dt[dir], // Traff after chunk
922 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
923 down.ConstData()[dir],
928 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
930 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
931 cost = dc - freeMb.ConstData();
933 property.Stat().freeMb -= dc;
934 property.Stat().cash -= cost;
940 sessionDownload[dir] += len;
941 sessionDownloadModTime = stgTime;
945 if (!settings->GetWriteFreeMbTraffCost() &&
946 freeMb.ConstData() >= 0)
949 #ifdef TRAFF_STAT_WITH_PORTS
950 IP_DIR_PAIR idp(ip, dir, port);
952 IP_DIR_PAIR idp(ip, dir);
955 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
956 lb = traffStat.lower_bound(idp);
957 if (lb == traffStat.end() || lb->first != idp)
961 STAT_NODE(0, len, cost)));
965 lb->second.cash += cost;
966 lb->second.down += len;
969 //-----------------------------------------------------------------------------
970 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
972 STG_LOCKER lock(&mutex);
973 currIP.AddBeforeNotifier(notifier);
975 //-----------------------------------------------------------------------------
976 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
978 STG_LOCKER lock(&mutex);
979 currIP.DelBeforeNotifier(notifier);
981 //-----------------------------------------------------------------------------
982 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
984 STG_LOCKER lock(&mutex);
985 currIP.AddAfterNotifier(notifier);
987 //-----------------------------------------------------------------------------
988 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
990 STG_LOCKER lock(&mutex);
991 currIP.DelAfterNotifier(notifier);
993 //-----------------------------------------------------------------------------
994 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
996 STG_LOCKER lock(&mutex);
997 connected.AddBeforeNotifier(notifier);
999 //-----------------------------------------------------------------------------
1000 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1002 STG_LOCKER lock(&mutex);
1003 connected.DelBeforeNotifier(notifier);
1005 //-----------------------------------------------------------------------------
1006 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1008 STG_LOCKER lock(&mutex);
1009 connected.AddAfterNotifier(notifier);
1011 //-----------------------------------------------------------------------------
1012 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1014 STG_LOCKER lock(&mutex);
1015 connected.DelAfterNotifier(notifier);
1017 //-----------------------------------------------------------------------------
1018 void USER_IMPL::OnAdd()
1020 STG_LOCKER lock(&mutex);
1022 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1024 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1026 std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
1028 ScriptExec(scriptOnAddParams.c_str());
1032 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1035 //-----------------------------------------------------------------------------
1036 void USER_IMPL::OnDelete()
1038 STG_LOCKER lock(&mutex);
1040 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1042 if (access(scriptOnDel.c_str(), X_OK) == 0)
1044 std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
1046 ScriptExec(scriptOnDelParams.c_str());
1050 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1055 //-----------------------------------------------------------------------------
1056 int USER_IMPL::WriteDetailStat(bool hard)
1058 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1060 if (!traffStatSaved.second.empty())
1062 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1064 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1065 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1066 WriteServLog("%s", store->GetStrError().c_str());
1069 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1075 STG_LOCKER lock(&mutex);
1079 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1081 if (ts.size() && !disabledDetailStat)
1083 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1085 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1086 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1087 WriteServLog("%s", store->GetStrError().c_str());
1090 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1091 STG_LOCKER lock(&mutex);
1092 traffStatSaved.second.swap(ts);
1093 traffStatSaved.first = lastWriteDetailedStat;
1098 lastWriteDetailedStat = stgTime;
1101 //-----------------------------------------------------------------------------
1102 double USER_IMPL::GetPassiveTimePart() const
1104 STG_LOCKER lock(&mutex);
1106 static int daysInMonth[12] =
1107 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1111 localtime_r(&t, &tms);
1113 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1115 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1118 secMonth += 24 * 3600;
1121 time_t dt = secMonth - passiveTime;
1126 return static_cast<double>(dt) / secMonth;
1128 //-----------------------------------------------------------------------------
1129 void USER_IMPL::SetPassiveTimeAsNewUser()
1131 STG_LOCKER lock(&mutex);
1135 localtime_r(&t, &tm);
1136 int daysCurrMon = DaysInCurrentMonth();
1137 double pt = tm.tm_mday - 1;
1140 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1142 //-----------------------------------------------------------------------------
1143 void USER_IMPL::MidnightResetSessionStat()
1145 STG_LOCKER lock(&mutex);
1149 Disconnect(true, "fake");
1153 //-----------------------------------------------------------------------------
1154 void USER_IMPL::ProcessNewMonth()
1156 STG_LOCKER lock(&mutex);
1159 Disconnect(true, "fake");
1163 property.Stat().monthUp.Reset();
1164 property.Stat().monthDown.Reset();
1170 if (nextTariff.ConstData() != "")
1172 const TARIFF * nt = tariffs->FindByName(nextTariff);
1174 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1175 login.c_str(), property.tariffName.Get().c_str());
1177 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1182 //-----------------------------------------------------------------------------
1183 void USER_IMPL::ProcessDayFeeSpread()
1185 STG_LOCKER lock(&mutex);
1187 if (passive.ConstData() || tariff == NULL)
1190 if (tariff->GetPeriod() != TARIFF::MONTH)
1193 double fee = tariff->GetFee() / DaysInCurrentMonth();
1195 if (std::fabs(fee) < 1.0e-3)
1199 switch (settings->GetFeeChargeType())
1202 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1205 if (c + credit >= 0)
1206 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1209 if (c + credit >= fee)
1210 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1214 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1219 //-----------------------------------------------------------------------------
1220 void USER_IMPL::ProcessDayFee()
1222 STG_LOCKER lock(&mutex);
1227 if (tariff->GetPeriod() != TARIFF::MONTH)
1230 double passiveTimePart = 1.0;
1231 if (!settings->GetFullFee())
1233 passiveTimePart = GetPassiveTimePart();
1237 if (passive.ConstData())
1239 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1243 double fee = tariff->GetFee() * passiveTimePart;
1247 if (std::fabs(fee) < 1.0e-3)
1254 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1261 switch (settings->GetFeeChargeType())
1264 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1268 if (c + credit >= 0)
1270 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1275 if (c + credit >= fee)
1277 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1284 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1290 //-----------------------------------------------------------------------------
1291 void USER_IMPL::ProcessDailyFee()
1293 STG_LOCKER lock(&mutex);
1295 if (passive.ConstData() || tariff == NULL)
1298 if (tariff->GetPeriod() != TARIFF::DAY)
1301 double fee = tariff->GetFee();
1307 switch (settings->GetFeeChargeType())
1310 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1313 if (c + credit >= 0)
1314 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1317 if (c + credit >= fee)
1318 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1323 //-----------------------------------------------------------------------------
1324 void USER_IMPL::SetPrepaidTraff()
1327 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1329 //-----------------------------------------------------------------------------
1330 int USER_IMPL::AddMessage(STG_MSG * msg)
1332 STG_LOCKER lock(&mutex);
1334 if (SendMessage(*msg))
1336 if (store->AddMessage(msg, login))
1338 errorStr = store->GetStrError();
1339 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1340 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1343 messages.push_back(*msg);
1347 if (msg->header.repeat > 0)
1349 msg->header.repeat--;
1351 //TODO: gcc v. 4.x generate ICE on x86_64
1352 msg->header.lastSendTime = static_cast<int>(time(NULL));
1354 msg->header.lastSendTime = static_cast<int>(stgTime);
1356 if (store->AddMessage(msg, login))
1358 errorStr = store->GetStrError();
1359 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1360 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1363 messages.push_back(*msg);
1368 //-----------------------------------------------------------------------------
1369 int USER_IMPL::SendMessage(STG_MSG & msg) const
1371 // No lock `cause we are already locked from caller
1373 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1374 while (it != authorizedBy.end())
1376 if (!(*it++)->SendMessage(msg, currIP))
1382 //TODO: gcc v. 4.x generate ICE on x86_64
1383 msg.header.lastSendTime = static_cast<int>(time(NULL));
1385 msg.header.lastSendTime = static_cast<int>(stgTime);
1387 msg.header.repeat--;
1391 //-----------------------------------------------------------------------------
1392 void USER_IMPL::ScanMessage()
1394 // No lock `cause we are already locked from caller
1395 // We need not check for the authorizedBy `cause it has already checked by caller
1397 std::list<STG_MSG>::iterator it(messages.begin());
1398 while (it != messages.end())
1400 if (settings->GetMessageTimeout() > 0 &&
1401 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1404 if (store->DelMessage(it->header.id, login))
1406 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1407 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1409 messages.erase(it++);
1412 if (it->GetNextSendTime() <= stgTime)
1414 if (SendMessage(*it))
1416 // We need to check all messages in queue for timeout
1420 if (it->header.repeat < 0)
1422 if (store->DelMessage(it->header.id, login))
1424 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1425 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1427 messages.erase(it++);
1431 if (store->EditMessage(*it, login))
1433 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1434 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1445 //-----------------------------------------------------------------------------
1446 std::string USER_IMPL::GetParamValue(const std::string & name) const
1448 std::string lowerName = ToLower(name);
1449 if (lowerName == "id")
1451 std::ostringstream stream;
1453 return stream.str();
1455 if (lowerName == "login") return login;
1456 if (lowerName == "currip") return currIP.ToString();
1457 if (lowerName == "enableddirs") return GetEnabledDirs();
1458 if (lowerName == "tariff") return property.tariffName;
1459 if (property.Exists(lowerName))
1460 return property.GetPropertyValue(lowerName);
1463 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1467 //-----------------------------------------------------------------------------
1468 //-----------------------------------------------------------------------------
1469 //-----------------------------------------------------------------------------
1470 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1472 if (newPassive && !oldPassive && user->tariff != NULL)
1473 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1479 //-----------------------------------------------------------------------------
1480 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1482 if (oldValue && !newValue && user->GetConnected())
1483 user->Disconnect(false, "disabled");
1484 else if (!oldValue && newValue && user->IsInetable())
1485 user->Connect(false);
1487 //-----------------------------------------------------------------------------
1488 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1490 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1491 user->Disconnect(false, "Change tariff");
1492 user->tariff = user->tariffs->FindByName(newTariff);
1493 if (user->settings->GetReconnectOnTariffChange() &&
1494 !user->authorizedBy.empty() &&
1496 user->Connect(false);
1498 //-----------------------------------------------------------------------------
1499 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1501 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1502 user->lastCashAdd = newCash - oldCash;
1504 //-----------------------------------------------------------------------------
1505 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1507 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1508 if (user->connected)
1509 user->Disconnect(false, "Change IP");
1510 if (!user->authorizedBy.empty() && user->IsInetable())
1511 user->Connect(false);