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,
81 const SERVICES & svcs)
84 WriteServLog(GetStgLogger()),
88 connected(__connected),
91 lastIPForDisconnect(0),
99 authorizedModificationTime(0),
102 lastWriteDetailedStat(0),
106 lastCashAdd(property.lastCashAdd),
107 passiveTime(property.passiveTime),
108 lastCashAddTime(property.lastCashAddTime),
109 freeMb(property.freeMb),
110 lastActivityTime(property.lastActivityTime),
111 password(property.password),
112 passive(property.passive),
113 disabled(property.disabled),
114 disabledDetailStat(property.disabledDetailStat),
115 alwaysOnline(property.alwaysOnline),
116 tariffName(property.tariffName),
117 nextTariff(property.nextTariff),
118 address(property.address),
120 group(property.group),
121 email(property.email),
122 phone(property.phone),
123 realName(property.realName),
124 credit(property.credit),
125 creditExpire(property.creditExpire),
127 userdata0(property.userdata0),
128 userdata1(property.userdata1),
129 userdata2(property.userdata2),
130 userdata3(property.userdata3),
131 userdata4(property.userdata4),
132 userdata5(property.userdata5),
133 userdata6(property.userdata6),
134 userdata7(property.userdata7),
135 userdata8(property.userdata8),
136 userdata9(property.userdata9),
137 sessionUploadModTime(stgTime),
138 sessionDownloadModTime(stgTime),
139 passiveNotifier(this),
140 disabledNotifier(this),
141 tariffNotifier(this),
148 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
153 const SERVICES & svcs)
156 WriteServLog(GetStgLogger()),
160 connected(__connected),
163 lastIPForDisconnect(0),
171 authorizedModificationTime(0),
174 lastWriteDetailedStat(0),
178 lastCashAdd(property.lastCashAdd),
179 passiveTime(property.passiveTime),
180 lastCashAddTime(property.lastCashAddTime),
181 freeMb(property.freeMb),
182 lastActivityTime(property.lastActivityTime),
183 password(property.password),
184 passive(property.passive),
185 disabled(property.disabled),
186 disabledDetailStat(property.disabledDetailStat),
187 alwaysOnline(property.alwaysOnline),
188 tariffName(property.tariffName),
189 nextTariff(property.nextTariff),
190 address(property.address),
192 group(property.group),
193 email(property.email),
194 phone(property.phone),
195 realName(property.realName),
196 credit(property.credit),
197 creditExpire(property.creditExpire),
199 userdata0(property.userdata0),
200 userdata1(property.userdata1),
201 userdata2(property.userdata2),
202 userdata3(property.userdata3),
203 userdata4(property.userdata4),
204 userdata5(property.userdata5),
205 userdata6(property.userdata6),
206 userdata7(property.userdata7),
207 userdata8(property.userdata8),
208 userdata9(property.userdata9),
209 sessionUploadModTime(stgTime),
210 sessionDownloadModTime(stgTime),
211 passiveNotifier(this),
212 disabledNotifier(this),
213 tariffNotifier(this),
220 //-----------------------------------------------------------------------------
221 void USER_IMPL::Init()
223 password = "*_EMPTY_PASSWORD_*";
224 tariffName = NO_TARIFF_NAME;
225 tariff = tariffs->FindByName(tariffName);
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);
241 //-----------------------------------------------------------------------------
242 USER_IMPL::USER_IMPL(const USER_IMPL & u)
245 property(*u.settings),
246 WriteServLog(GetStgLogger()),
251 connected(__connected),
252 userIDGenerator(u.userIDGenerator),
253 __currIP(u.__currIP),
255 lastIPForDisconnect(0),
256 pingTime(u.pingTime),
257 sysAdmin(u.sysAdmin),
261 m_services(u.m_services),
262 traffStat(u.traffStat),
263 traffStatSaved(u.traffStatSaved),
264 settings(u.settings),
265 authorizedModificationTime(u.authorizedModificationTime),
266 messages(u.messages),
268 lastWriteStat(u.lastWriteStat),
269 lastWriteDetailedStat(u.lastWriteDetailedStat),
273 lastCashAdd(property.lastCashAdd),
274 passiveTime(property.passiveTime),
275 lastCashAddTime(property.lastCashAddTime),
276 freeMb(property.freeMb),
277 lastActivityTime(property.lastActivityTime),
278 password(property.password),
279 passive(property.passive),
280 disabled(property.disabled),
281 disabledDetailStat(property.disabledDetailStat),
282 alwaysOnline(property.alwaysOnline),
283 tariffName(property.tariffName),
284 nextTariff(property.nextTariff),
285 address(property.address),
287 group(property.group),
288 email(property.email),
289 phone(property.phone),
290 realName(property.realName),
291 credit(property.credit),
292 creditExpire(property.creditExpire),
294 userdata0(property.userdata0),
295 userdata1(property.userdata1),
296 userdata2(property.userdata2),
297 userdata3(property.userdata3),
298 userdata4(property.userdata4),
299 userdata5(property.userdata5),
300 userdata6(property.userdata6),
301 userdata7(property.userdata7),
302 userdata8(property.userdata8),
303 userdata9(property.userdata9),
306 sessionUploadModTime(stgTime),
307 sessionDownloadModTime(stgTime),
308 passiveNotifier(this),
309 disabledNotifier(this),
310 tariffNotifier(this),
317 property.tariffName.AddBeforeNotifier(&tariffNotifier);
318 property.passive.AddBeforeNotifier(&passiveNotifier);
319 property.disabled.AddAfterNotifier(&disabledNotifier);
320 property.cash.AddBeforeNotifier(&cashNotifier);
321 ips.AddAfterNotifier(&ipNotifier);
323 property.SetProperties(u.property);
325 pthread_mutexattr_t attr;
326 pthread_mutexattr_init(&attr);
327 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
328 pthread_mutex_init(&mutex, &attr);
330 //-----------------------------------------------------------------------------
331 USER_IMPL::~USER_IMPL()
333 property.tariffName.DelBeforeNotifier(&tariffNotifier);
334 property.passive.DelBeforeNotifier(&passiveNotifier);
335 property.disabled.DelAfterNotifier(&disabledNotifier);
336 property.cash.DelBeforeNotifier(&cashNotifier);
337 pthread_mutex_destroy(&mutex);
339 //-----------------------------------------------------------------------------
340 void USER_IMPL::SetLogin(const std::string & l)
342 STG_LOCKER lock(&mutex);
343 assert(login.empty() && "Login is already set");
345 id = userIDGenerator.GetNextID();
347 //-----------------------------------------------------------------------------
348 int USER_IMPL::ReadConf()
350 STG_LOCKER lock(&mutex);
353 if (store->RestoreUserConf(&conf, login))
355 WriteServLog("Cannot read conf for user %s.", login.c_str());
356 WriteServLog("%s", store->GetStrError().c_str());
357 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
358 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
362 property.SetConf(conf);
364 tariff = tariffs->FindByName(tariffName);
367 WriteServLog("Cannot read user %s. Tariff %s not exist.",
368 login.c_str(), property.tariffName.Get().c_str());
372 std::vector<STG_MSG_HDR> hdrsList;
374 if (store->GetMessageHdrs(&hdrsList, login))
376 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
377 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
379 store->GetStrError().c_str());
383 std::vector<STG_MSG_HDR>::const_iterator it;
384 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
387 if (store->GetMessage(it->id, &msg, login) == 0)
389 messages.push_back(msg);
395 //-----------------------------------------------------------------------------
396 int USER_IMPL::ReadStat()
398 STG_LOCKER lock(&mutex);
401 if (store->RestoreUserStat(&stat, login))
403 WriteServLog("Cannot read stat for user %s.", login.c_str());
404 WriteServLog("%s", store->GetStrError().c_str());
405 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
406 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
410 property.SetStat(stat);
414 //-----------------------------------------------------------------------------
415 int USER_IMPL::WriteConf()
417 STG_LOCKER lock(&mutex);
418 USER_CONF conf(property.GetConf());
420 printfd(__FILE__, "USER::WriteConf()\n");
422 if (store->SaveUserConf(conf, login))
424 WriteServLog("Cannot write conf for user %s.", login.c_str());
425 WriteServLog("%s", store->GetStrError().c_str());
426 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
427 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
433 //-----------------------------------------------------------------------------
434 int USER_IMPL::WriteStat()
436 STG_LOCKER lock(&mutex);
437 USER_STAT stat(property.GetStat());
439 if (store->SaveUserStat(stat, login))
441 WriteServLog("Cannot write stat for user %s.", login.c_str());
442 WriteServLog("%s", store->GetStrError().c_str());
443 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
444 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
448 lastWriteStat = stgTime;
452 //-----------------------------------------------------------------------------
453 int USER_IMPL::WriteMonthStat()
455 STG_LOCKER lock(&mutex);
456 time_t tt = stgTime - 3600;
458 localtime_r(&tt, &t1);
460 USER_STAT stat(property.GetStat());
461 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
463 WriteServLog("Cannot write month stat for user %s.", login.c_str());
464 WriteServLog("%s", store->GetStrError().c_str());
465 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
466 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
472 //-----------------------------------------------------------------------------
473 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
475 STG_LOCKER lock(&mutex);
477 * Authorize user. It only means that user will be authorized. Nothing more.
478 * User can be connected or disconnected while authorized.
479 * Example: user is authorized but disconnected due to 0 money or blocking
483 * TODO: in fact "authorization" means allowing access to a service. What we
484 * call "authorization" here, int STG, is "authentication". So this should be
489 * Prevent double authorization by identical authorizers
491 if (authorizedBy.find(auth) != authorizedBy.end())
497 dirsFromBits(enabledDirs, dirs);
499 if (!authorizedBy.empty())
503 // We are already authorized, but with different IP address
504 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
509 if (!users->FindByIPIdx(ip, &u))
511 // Address presents in IP-index.
512 // If it's not our IP - report it.
515 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
522 if (users->IsIPInIndex(ip))
524 // Address is already present in IP-index.
525 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
529 if (ips.ConstData().IsIPInIPS(ip))
532 lastIPForDisconnect = currIP;
536 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
537 errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
542 if (authorizedBy.empty())
543 authorizedModificationTime = stgTime;
544 authorizedBy.insert(auth);
550 //-----------------------------------------------------------------------------
551 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
553 STG_LOCKER lock(&mutex);
555 * Authorizer tries to unauthorize user, that was not authorized by it
557 if (!authorizedBy.erase(auth))
560 authorizedModificationTime = stgTime;
562 if (authorizedBy.empty())
564 lastDisconnectReason = reason;
565 lastIPForDisconnect = currIP;
566 currIP = 0; // DelUser in traffcounter
568 Disconnect(false, "not authorized");
572 //-----------------------------------------------------------------------------
573 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
575 STG_LOCKER lock(&mutex);
576 // Is this user authorized by specified authorizer?
577 return authorizedBy.find(auth) != authorizedBy.end();
579 //-----------------------------------------------------------------------------
580 std::vector<std::string> USER_IMPL::GetAuthorizers() const
582 STG_LOCKER lock(&mutex);
583 std::vector<std::string> list;
584 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
587 //-----------------------------------------------------------------------------
588 void USER_IMPL::Connect(bool fakeConnect)
591 * Connect user to Internet. This function is differ from Authorize() !!!
594 STG_LOCKER lock(&mutex);
598 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
600 if (access(scriptOnConnect.c_str(), X_OK) == 0)
602 std::string dirs = dirsToString(enabledDirs);
604 std::string scriptOnConnectParams;
605 strprintf(&scriptOnConnectParams,
606 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
607 scriptOnConnect.c_str(),
609 inet_ntostring(currIP).c_str(),
614 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
615 while (it != settings->GetScriptParams().end())
617 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
621 ScriptExec(scriptOnConnectParams.c_str());
625 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
631 if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP))
633 WriteServLog("Cannot write connect for user %s.", login.c_str());
634 WriteServLog("%s", store->GetStrError().c_str());
638 lastIPForDisconnect = currIP;
640 //-----------------------------------------------------------------------------
641 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
644 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
647 STG_LOCKER lock(&mutex);
649 if (!lastIPForDisconnect)
651 printfd(__FILE__, "lastIPForDisconnect\n");
657 lastDisconnectReason = reason;
658 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
660 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
662 std::string dirs = dirsToString(enabledDirs);
664 std::string scriptOnDisonnectParams;
665 strprintf(&scriptOnDisonnectParams,
666 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
667 scriptOnDisonnect.c_str(),
669 inet_ntostring(lastIPForDisconnect).c_str(),
674 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
675 while (it != settings->GetScriptParams().end())
677 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
681 ScriptExec(scriptOnDisonnectParams.c_str());
685 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
691 std::string reasonMessage(reason);
692 if (!lastDisconnectReason.empty())
693 reasonMessage += ": " + lastDisconnectReason;
695 if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
696 cash, freeMb, reasonMessage))
698 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
699 WriteServLog("%s", store->GetStrError().c_str());
703 lastIPForDisconnect = 0;
705 sessionUpload.Reset();
706 sessionDownload.Reset();
707 sessionUploadModTime = stgTime;
708 sessionDownloadModTime = stgTime;
710 //-----------------------------------------------------------------------------
711 void USER_IMPL::Run()
713 STG_LOCKER lock(&mutex);
715 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
717 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
720 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
722 WriteServLog("User: %s. Credit expired.", login.c_str());
728 if (passive.ConstData()
729 && (stgTime % 30 == 0)
730 && (passiveTime.ModificationTime() != stgTime))
732 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
733 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
736 if (!authorizedBy.empty())
739 property.Stat().lastActivityTime = stgTime;
741 if (!connected && IsInetable())
744 if (connected && !IsInetable())
747 Disconnect(false, "disabled");
749 Disconnect(false, "passive");
751 Disconnect(false, "no cash");
754 if (stgTime - lastScanMessages > 10)
757 lastScanMessages = stgTime;
763 Disconnect(false, "not authorized");
767 //-----------------------------------------------------------------------------
768 void USER_IMPL::UpdatePingTime(time_t t)
770 STG_LOCKER lock(&mutex);
776 //-----------------------------------------------------------------------------
777 bool USER_IMPL::IsInetable()
779 if (disabled || passive)
782 if (settings->GetFreeMbAllowInet())
788 if (settings->GetShowFeeInCash() || tariff == NULL)
789 return (cash >= -credit);
791 return (cash - tariff->GetFee() >= -credit);
793 //-----------------------------------------------------------------------------
794 std::string USER_IMPL::GetEnabledDirs() const
796 return dirsToString(enabledDirs);
798 //-----------------------------------------------------------------------------
799 #ifdef TRAFF_STAT_WITH_PORTS
800 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
802 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
805 STG_LOCKER lock(&mutex);
807 if (!connected || tariff == NULL)
813 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
814 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
818 int tt = tariff->GetTraffType();
819 if (tt == TARIFF::TRAFF_UP ||
820 tt == TARIFF::TRAFF_UP_DOWN ||
821 // Check NEW traff data
822 (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
825 if (traff < threshold &&
826 traff + len >= threshold)
828 // cash = partBeforeThreshold * priceBeforeThreshold +
829 // partAfterThreshold * priceAfterThreshold
830 int64_t before = threshold - traff; // Chunk part before threshold
831 int64_t after = len - before; // Chunk part after threshold
832 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
833 down.ConstData()[dir],
836 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
837 down.ConstData()[dir],
843 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
844 down.ConstData()[dir],
849 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
851 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
852 cost = dc - freeMb.ConstData();
854 // Direct access to internal data structures via friend-specifier
855 property.Stat().freeMb -= dc;
856 property.Stat().cash -= cost;
862 sessionUpload[dir] += len;
863 sessionUploadModTime = stgTime;
867 if (!settings->GetWriteFreeMbTraffCost() &&
868 freeMb.ConstData() >= 0)
871 #ifdef TRAFF_STAT_WITH_PORTS
872 IP_DIR_PAIR idp(ip, dir, port);
874 IP_DIR_PAIR idp(ip, dir);
877 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
878 lb = traffStat.lower_bound(idp);
879 if (lb == traffStat.end() || lb->first != idp)
883 STAT_NODE(len, 0, cost)));
887 lb->second.cash += cost;
888 lb->second.up += len;
891 //-----------------------------------------------------------------------------
892 #ifdef TRAFF_STAT_WITH_PORTS
893 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
895 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
898 STG_LOCKER lock(&mutex);
900 if (!connected || tariff == NULL)
906 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
907 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
911 int tt = tariff->GetTraffType();
912 if (tt == TARIFF::TRAFF_DOWN ||
913 tt == TARIFF::TRAFF_UP_DOWN ||
914 // Check NEW traff data
915 (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
918 if (traff < threshold &&
919 traff + len >= threshold)
921 // cash = partBeforeThreshold * priceBeforeThreshold +
922 // partAfterThreshold * priceAfterThreshold
923 int64_t before = threshold - traff; // Chunk part before threshold
924 int64_t after = len - before; // Chunk part after threshold
925 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
926 down.ConstData()[dir], // Traff before chunk
929 tariff->GetPriceWithTraffType(up.ConstData()[dir],
930 dt[dir], // Traff after chunk
936 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
937 down.ConstData()[dir],
942 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
944 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
945 cost = dc - freeMb.ConstData();
947 property.Stat().freeMb -= dc;
948 property.Stat().cash -= cost;
954 sessionDownload[dir] += len;
955 sessionDownloadModTime = stgTime;
959 if (!settings->GetWriteFreeMbTraffCost() &&
960 freeMb.ConstData() >= 0)
963 #ifdef TRAFF_STAT_WITH_PORTS
964 IP_DIR_PAIR idp(ip, dir, port);
966 IP_DIR_PAIR idp(ip, dir);
969 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
970 lb = traffStat.lower_bound(idp);
971 if (lb == traffStat.end() || lb->first != idp)
975 STAT_NODE(0, len, cost)));
979 lb->second.cash += cost;
980 lb->second.down += len;
983 //-----------------------------------------------------------------------------
984 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
986 STG_LOCKER lock(&mutex);
987 currIP.AddBeforeNotifier(notifier);
989 //-----------------------------------------------------------------------------
990 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
992 STG_LOCKER lock(&mutex);
993 currIP.DelBeforeNotifier(notifier);
995 //-----------------------------------------------------------------------------
996 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
998 STG_LOCKER lock(&mutex);
999 currIP.AddAfterNotifier(notifier);
1001 //-----------------------------------------------------------------------------
1002 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1004 STG_LOCKER lock(&mutex);
1005 currIP.DelAfterNotifier(notifier);
1007 //-----------------------------------------------------------------------------
1008 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1010 STG_LOCKER lock(&mutex);
1011 connected.AddBeforeNotifier(notifier);
1013 //-----------------------------------------------------------------------------
1014 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1016 STG_LOCKER lock(&mutex);
1017 connected.DelBeforeNotifier(notifier);
1019 //-----------------------------------------------------------------------------
1020 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1022 STG_LOCKER lock(&mutex);
1023 connected.AddAfterNotifier(notifier);
1025 //-----------------------------------------------------------------------------
1026 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1028 STG_LOCKER lock(&mutex);
1029 connected.DelAfterNotifier(notifier);
1031 //-----------------------------------------------------------------------------
1032 void USER_IMPL::OnAdd()
1034 STG_LOCKER lock(&mutex);
1036 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1038 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1040 std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
1042 ScriptExec(scriptOnAddParams.c_str());
1046 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1049 //-----------------------------------------------------------------------------
1050 void USER_IMPL::OnDelete()
1052 STG_LOCKER lock(&mutex);
1054 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1056 if (access(scriptOnDel.c_str(), X_OK) == 0)
1058 std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
1060 ScriptExec(scriptOnDelParams.c_str());
1064 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1069 //-----------------------------------------------------------------------------
1070 int USER_IMPL::WriteDetailStat(bool hard)
1072 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1074 if (!traffStatSaved.second.empty())
1076 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1078 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1079 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1080 WriteServLog("%s", store->GetStrError().c_str());
1083 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1089 STG_LOCKER lock(&mutex);
1093 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1095 if (ts.size() && !disabledDetailStat)
1097 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1099 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1100 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1101 WriteServLog("%s", store->GetStrError().c_str());
1104 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1105 STG_LOCKER lock(&mutex);
1106 traffStatSaved.second.swap(ts);
1107 traffStatSaved.first = lastWriteDetailedStat;
1112 lastWriteDetailedStat = stgTime;
1115 //-----------------------------------------------------------------------------
1116 double USER_IMPL::GetPassiveTimePart() const
1118 STG_LOCKER lock(&mutex);
1120 static int daysInMonth[12] =
1121 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1125 localtime_r(&t, &tms);
1127 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1129 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1132 secMonth += 24 * 3600;
1135 time_t dt = secMonth - passiveTime;
1140 return static_cast<double>(dt) / secMonth;
1142 //-----------------------------------------------------------------------------
1143 void USER_IMPL::SetPassiveTimeAsNewUser()
1145 STG_LOCKER lock(&mutex);
1149 localtime_r(&t, &tm);
1150 int daysCurrMon = DaysInCurrentMonth();
1151 double pt = tm.tm_mday - 1;
1154 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1156 //-----------------------------------------------------------------------------
1157 void USER_IMPL::MidnightResetSessionStat()
1159 STG_LOCKER lock(&mutex);
1163 Disconnect(true, "fake");
1167 //-----------------------------------------------------------------------------
1168 void USER_IMPL::ProcessNewMonth()
1170 STG_LOCKER lock(&mutex);
1173 Disconnect(true, "fake");
1177 property.Stat().monthUp.Reset();
1178 property.Stat().monthDown.Reset();
1184 if (nextTariff.ConstData() != "")
1186 const TARIFF * nt = tariffs->FindByName(nextTariff);
1189 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1190 login.c_str(), property.tariffName.Get().c_str());
1194 std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime);
1195 if (message.empty())
1197 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1201 WriteServLog("Tariff change is prohibited for user %s. %s",
1210 //-----------------------------------------------------------------------------
1211 void USER_IMPL::ProcessDayFeeSpread()
1213 STG_LOCKER lock(&mutex);
1215 if (passive.ConstData() || tariff == NULL)
1218 if (tariff->GetPeriod() != TARIFF::MONTH)
1221 double fee = tariff->GetFee() / DaysInCurrentMonth();
1223 if (std::fabs(fee) < 1.0e-3)
1227 switch (settings->GetFeeChargeType())
1230 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1233 if (c + credit >= 0)
1234 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1237 if (c + credit >= fee)
1238 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1242 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1247 //-----------------------------------------------------------------------------
1248 void USER_IMPL::ProcessDayFee()
1250 STG_LOCKER lock(&mutex);
1255 if (tariff->GetPeriod() != TARIFF::MONTH)
1258 double passiveTimePart = 1.0;
1259 if (!settings->GetFullFee())
1261 passiveTimePart = GetPassiveTimePart();
1265 if (passive.ConstData())
1267 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1271 double fee = tariff->GetFee() * passiveTimePart;
1275 if (std::fabs(fee) < 1.0e-3)
1282 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1289 switch (settings->GetFeeChargeType())
1292 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1296 if (c + credit >= 0)
1298 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1303 if (c + credit >= fee)
1305 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1312 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1318 //-----------------------------------------------------------------------------
1319 void USER_IMPL::ProcessDailyFee()
1321 STG_LOCKER lock(&mutex);
1323 if (passive.ConstData() || tariff == NULL)
1326 if (tariff->GetPeriod() != TARIFF::DAY)
1329 double fee = tariff->GetFee();
1335 switch (settings->GetFeeChargeType())
1338 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1341 if (c + credit >= 0)
1342 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1345 if (c + credit >= fee)
1346 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1351 //-----------------------------------------------------------------------------
1352 void USER_IMPL::SetPrepaidTraff()
1355 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1357 //-----------------------------------------------------------------------------
1358 int USER_IMPL::AddMessage(STG_MSG * msg)
1360 STG_LOCKER lock(&mutex);
1362 if (SendMessage(*msg))
1364 if (store->AddMessage(msg, login))
1366 errorStr = store->GetStrError();
1367 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1368 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1371 messages.push_back(*msg);
1375 if (msg->header.repeat > 0)
1377 msg->header.repeat--;
1379 //TODO: gcc v. 4.x generate ICE on x86_64
1380 msg->header.lastSendTime = static_cast<int>(time(NULL));
1382 msg->header.lastSendTime = static_cast<int>(stgTime);
1384 if (store->AddMessage(msg, login))
1386 errorStr = store->GetStrError();
1387 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1388 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1391 messages.push_back(*msg);
1396 //-----------------------------------------------------------------------------
1397 int USER_IMPL::SendMessage(STG_MSG & msg) const
1399 // No lock `cause we are already locked from caller
1401 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1402 while (it != authorizedBy.end())
1404 if (!(*it++)->SendMessage(msg, currIP))
1410 //TODO: gcc v. 4.x generate ICE on x86_64
1411 msg.header.lastSendTime = static_cast<int>(time(NULL));
1413 msg.header.lastSendTime = static_cast<int>(stgTime);
1415 msg.header.repeat--;
1419 //-----------------------------------------------------------------------------
1420 void USER_IMPL::ScanMessage()
1422 // No lock `cause we are already locked from caller
1423 // We need not check for the authorizedBy `cause it has already checked by caller
1425 std::list<STG_MSG>::iterator it(messages.begin());
1426 while (it != messages.end())
1428 if (settings->GetMessageTimeout() > 0 &&
1429 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1432 if (store->DelMessage(it->header.id, login))
1434 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1435 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1437 messages.erase(it++);
1440 if (it->GetNextSendTime() <= stgTime)
1442 if (SendMessage(*it))
1444 // We need to check all messages in queue for timeout
1448 if (it->header.repeat < 0)
1450 if (store->DelMessage(it->header.id, login))
1452 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1453 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1455 messages.erase(it++);
1459 if (store->EditMessage(*it, login))
1461 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1462 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1473 //-----------------------------------------------------------------------------
1474 std::string USER_IMPL::GetParamValue(const std::string & name) const
1476 std::string lowerName = ToLower(name);
1477 if (lowerName == "id")
1479 std::ostringstream stream;
1481 return stream.str();
1483 if (lowerName == "login") return login;
1484 if (lowerName == "currip") return currIP.ToString();
1485 if (lowerName == "enableddirs") return GetEnabledDirs();
1486 if (lowerName == "tariff") return property.tariffName;
1487 if (property.Exists(lowerName))
1488 return property.GetPropertyValue(lowerName);
1491 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1495 //-----------------------------------------------------------------------------
1496 //-----------------------------------------------------------------------------
1497 //-----------------------------------------------------------------------------
1498 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1500 if (newPassive && !oldPassive && user->tariff != NULL)
1501 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1507 //-----------------------------------------------------------------------------
1508 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1510 if (oldValue && !newValue && user->GetConnected())
1511 user->Disconnect(false, "disabled");
1512 else if (!oldValue && newValue && user->IsInetable())
1513 user->Connect(false);
1515 //-----------------------------------------------------------------------------
1516 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1518 STG_LOCKER lock(&user->mutex);
1519 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1520 user->Disconnect(false, "Change tariff");
1521 user->tariff = user->tariffs->FindByName(newTariff);
1522 if (user->settings->GetReconnectOnTariffChange() &&
1523 !user->authorizedBy.empty() &&
1526 // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name.
1527 user->property.Conf().tariffName = newTariff;
1528 user->Connect(false);
1531 //-----------------------------------------------------------------------------
1532 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1534 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1535 user->lastCashAdd = newCash - oldCash;
1537 //-----------------------------------------------------------------------------
1538 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1540 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1541 if (user->connected)
1542 user->Disconnect(false, "Change IP");
1543 if (!user->authorizedBy.empty() && user->IsInetable())
1544 user->Connect(false);