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
56 #ifdef USE_ABSTRACT_SETTINGS
57 USER_IMPL::USER_IMPL(const SETTINGS * s,
63 property(s->GetScriptsDir()),
64 WriteServLog(GetStgLogger()),
68 connected(__connected),
71 lastIPForDisconnect(0),
78 authorizedModificationTime(0),
81 lastWriteDetailedStat(0),
85 lastCashAdd(property.lastCashAdd),
86 passiveTime(property.passiveTime),
87 lastCashAddTime(property.lastCashAddTime),
88 freeMb(property.freeMb),
89 lastActivityTime(property.lastActivityTime),
90 password(property.password),
91 passive(property.passive),
92 disabled(property.disabled),
93 disabledDetailStat(property.disabledDetailStat),
94 alwaysOnline(property.alwaysOnline),
95 tariffName(property.tariffName),
96 nextTariff(property.nextTariff),
97 address(property.address),
99 group(property.group),
100 email(property.email),
101 phone(property.phone),
102 realName(property.realName),
103 credit(property.credit),
104 creditExpire(property.creditExpire),
106 userdata0(property.userdata0),
107 userdata1(property.userdata1),
108 userdata2(property.userdata2),
109 userdata3(property.userdata3),
110 userdata4(property.userdata4),
111 userdata5(property.userdata5),
112 userdata6(property.userdata6),
113 userdata7(property.userdata7),
114 userdata8(property.userdata8),
115 userdata9(property.userdata9),
116 passiveNotifier(this),
117 disabledNotifier(this),
118 tariffNotifier(this),
125 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
131 property(s->GetScriptsDir()),
132 WriteServLog(GetStgLogger()),
136 connected(__connected),
139 lastIPForDisconnect(0),
146 authorizedModificationTime(0),
149 lastWriteDetailedStat(0),
153 lastCashAdd(property.lastCashAdd),
154 passiveTime(property.passiveTime),
155 lastCashAddTime(property.lastCashAddTime),
156 freeMb(property.freeMb),
157 lastActivityTime(property.lastActivityTime),
158 password(property.password),
159 passive(property.passive),
160 disabled(property.disabled),
161 disabledDetailStat(property.disabledDetailStat),
162 alwaysOnline(property.alwaysOnline),
163 tariffName(property.tariffName),
164 nextTariff(property.nextTariff),
165 address(property.address),
167 group(property.group),
168 email(property.email),
169 phone(property.phone),
170 realName(property.realName),
171 credit(property.credit),
172 creditExpire(property.creditExpire),
174 userdata0(property.userdata0),
175 userdata1(property.userdata1),
176 userdata2(property.userdata2),
177 userdata3(property.userdata3),
178 userdata4(property.userdata4),
179 userdata5(property.userdata5),
180 userdata6(property.userdata6),
181 userdata7(property.userdata7),
182 userdata8(property.userdata8),
183 userdata9(property.userdata9),
184 passiveNotifier(this),
185 disabledNotifier(this),
186 tariffNotifier(this),
193 //-----------------------------------------------------------------------------
194 void USER_IMPL::Init()
196 password = "*_EMPTY_PASSWORD_*";
197 tariffName = NO_TARIFF_NAME;
199 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
200 lastWriteDetailedStat = stgTime;
202 property.tariffName.AddBeforeNotifier(&tariffNotifier);
203 property.passive.AddBeforeNotifier(&passiveNotifier);
204 property.disabled.AddAfterNotifier(&disabledNotifier);
205 property.cash.AddBeforeNotifier(&cashNotifier);
206 ips.AddAfterNotifier(&ipNotifier);
208 pthread_mutexattr_t attr;
209 pthread_mutexattr_init(&attr);
210 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
211 pthread_mutex_init(&mutex, &attr);
213 //-----------------------------------------------------------------------------
214 USER_IMPL::USER_IMPL(const USER_IMPL & u)
217 property(u.settings->GetScriptsDir()),
218 WriteServLog(GetStgLogger()),
223 connected(__connected),
224 userIDGenerator(u.userIDGenerator),
225 __currIP(u.__currIP),
227 lastIPForDisconnect(0),
228 pingTime(u.pingTime),
229 sysAdmin(u.sysAdmin),
233 traffStat(u.traffStat),
234 traffStatSaved(u.traffStatSaved),
235 settings(u.settings),
236 authorizedModificationTime(u.authorizedModificationTime),
237 messages(u.messages),
239 lastWriteStat(u.lastWriteStat),
240 lastWriteDetailedStat(u.lastWriteDetailedStat),
244 lastCashAdd(property.lastCashAdd),
245 passiveTime(property.passiveTime),
246 lastCashAddTime(property.lastCashAddTime),
247 freeMb(property.freeMb),
248 lastActivityTime(property.lastActivityTime),
249 password(property.password),
250 passive(property.passive),
251 disabled(property.disabled),
252 disabledDetailStat(property.disabledDetailStat),
253 alwaysOnline(property.alwaysOnline),
254 tariffName(property.tariffName),
255 nextTariff(property.nextTariff),
256 address(property.address),
258 group(property.group),
259 email(property.email),
260 phone(property.phone),
261 realName(property.realName),
262 credit(property.credit),
263 creditExpire(property.creditExpire),
265 userdata0(property.userdata0),
266 userdata1(property.userdata1),
267 userdata2(property.userdata2),
268 userdata3(property.userdata3),
269 userdata4(property.userdata4),
270 userdata5(property.userdata5),
271 userdata6(property.userdata6),
272 userdata7(property.userdata7),
273 userdata8(property.userdata8),
274 userdata9(property.userdata9),
277 passiveNotifier(this),
278 disabledNotifier(this),
279 tariffNotifier(this),
286 property.tariffName.AddBeforeNotifier(&tariffNotifier);
287 property.passive.AddBeforeNotifier(&passiveNotifier);
288 property.disabled.AddAfterNotifier(&disabledNotifier);
289 property.cash.AddBeforeNotifier(&cashNotifier);
290 ips.AddAfterNotifier(&ipNotifier);
292 property.SetProperties(u.property);
294 pthread_mutexattr_t attr;
295 pthread_mutexattr_init(&attr);
296 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
297 pthread_mutex_init(&mutex, &attr);
299 //-----------------------------------------------------------------------------
300 USER_IMPL::~USER_IMPL()
302 property.tariffName.DelBeforeNotifier(&tariffNotifier);
303 property.passive.DelBeforeNotifier(&passiveNotifier);
304 property.disabled.DelAfterNotifier(&disabledNotifier);
305 property.cash.DelBeforeNotifier(&cashNotifier);
306 pthread_mutex_destroy(&mutex);
308 //-----------------------------------------------------------------------------
309 void USER_IMPL::SetLogin(const std::string & l)
311 STG_LOCKER lock(&mutex);
312 assert(login.empty() && "Login is already set");
314 id = userIDGenerator.GetNextID();
316 //-----------------------------------------------------------------------------
317 int USER_IMPL::ReadConf()
319 STG_LOCKER lock(&mutex);
322 if (store->RestoreUserConf(&conf, login))
324 WriteServLog("Cannot read conf for user %s.", login.c_str());
325 WriteServLog("%s", store->GetStrError().c_str());
326 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
327 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
331 property.SetConf(conf);
333 tariff = tariffs->FindByName(tariffName);
336 WriteServLog("Cannot read user %s. Tariff %s not exist.",
337 login.c_str(), property.tariffName.Get().c_str());
341 std::vector<STG_MSG_HDR> hdrsList;
343 if (store->GetMessageHdrs(&hdrsList, login))
345 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
346 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
348 store->GetStrError().c_str());
352 std::vector<STG_MSG_HDR>::const_iterator it;
353 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
356 if (store->GetMessage(it->id, &msg, login) == 0)
358 messages.push_back(msg);
364 //-----------------------------------------------------------------------------
365 int USER_IMPL::ReadStat()
367 STG_LOCKER lock(&mutex);
370 if (store->RestoreUserStat(&stat, login))
372 WriteServLog("Cannot read stat for user %s.", login.c_str());
373 WriteServLog("%s", store->GetStrError().c_str());
374 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
375 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
379 property.SetStat(stat);
383 //-----------------------------------------------------------------------------
384 int USER_IMPL::WriteConf()
386 STG_LOCKER lock(&mutex);
387 USER_CONF conf(property.GetConf());
389 printfd(__FILE__, "USER::WriteConf()\n");
391 if (store->SaveUserConf(conf, login))
393 WriteServLog("Cannot write conf for user %s.", login.c_str());
394 WriteServLog("%s", store->GetStrError().c_str());
395 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
396 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
402 //-----------------------------------------------------------------------------
403 int USER_IMPL::WriteStat()
405 STG_LOCKER lock(&mutex);
406 USER_STAT stat(property.GetStat());
408 if (store->SaveUserStat(stat, login))
410 WriteServLog("Cannot write stat for user %s.", login.c_str());
411 WriteServLog("%s", store->GetStrError().c_str());
412 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
413 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
417 lastWriteStat = stgTime;
421 //-----------------------------------------------------------------------------
422 int USER_IMPL::WriteMonthStat()
424 STG_LOCKER lock(&mutex);
425 time_t tt = stgTime - 3600;
427 localtime_r(&tt, &t1);
429 USER_STAT stat(property.GetStat());
430 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
432 WriteServLog("Cannot write month stat for user %s.", login.c_str());
433 WriteServLog("%s", store->GetStrError().c_str());
434 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
435 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
441 //-----------------------------------------------------------------------------
442 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
444 STG_LOCKER lock(&mutex);
446 * Authorize user. It only means that user will be authorized. Nothing more.
447 * User can be connected or disconnected while authorized.
448 * Example: user is authorized but disconnected due to 0 money or blocking
452 * Prevent double authorization by identical authorizers
454 if (authorizedBy.find(auth) != authorizedBy.end())
460 for (int i = 0; i < DIR_NUM; i++)
462 enabledDirs[i] = dirs & (1 << i);
465 if (!authorizedBy.empty())
469 // We are already authorized, but with different IP address
470 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
475 if (!users->FindByIPIdx(ip, &u))
477 // Address is already present in IP-index
478 // If it's not our IP - throw an error
481 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
488 if (users->IsIPInIndex(ip))
490 // Address is already present in IP-index
491 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
495 if (ips.ConstData().IsIPInIPS(ip))
498 lastIPForDisconnect = currIP;
502 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
503 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
508 if (authorizedBy.empty())
509 authorizedModificationTime = stgTime;
510 authorizedBy.insert(auth);
516 //-----------------------------------------------------------------------------
517 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
519 STG_LOCKER lock(&mutex);
521 * Authorizer tries to unauthorize user, that was not authorized by it
523 if (!authorizedBy.erase(auth))
526 if (authorizedBy.empty())
528 authorizedModificationTime = stgTime;
529 lastDisconnectReason = reason;
530 lastIPForDisconnect = currIP;
531 currIP = 0; // DelUser in traffcounter
535 //-----------------------------------------------------------------------------
536 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
538 STG_LOCKER lock(&mutex);
539 // Is this user authorized by specified authorizer?
540 return authorizedBy.find(auth) != authorizedBy.end();
542 //-----------------------------------------------------------------------------
543 std::vector<std::string> USER_IMPL::GetAuthorizers() const
545 std::vector<std::string> list;
546 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
549 //-----------------------------------------------------------------------------
550 void USER_IMPL::Connect(bool fakeConnect)
553 * Connect user to Internet. This function is differ from Authorize() !!!
556 STG_LOCKER lock(&mutex);
560 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
562 if (access(scriptOnConnect.c_str(), X_OK) == 0)
564 char dirsStr[DIR_NUM + 1];
565 dirsStr[DIR_NUM] = 0;
566 for (int i = 0; i < DIR_NUM; i++)
568 dirsStr[i] = enabledDirs[i] ? '1' : '0';
571 std::string scriptOnConnectParams;
573 strprintf(&scriptOnConnectParams,
574 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
575 scriptOnConnect.c_str(),
577 inet_ntostring(currIP).c_str(),
582 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
583 while (it != settings->GetScriptParams().end())
585 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
589 ScriptExec(scriptOnConnectParams.c_str());
593 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
599 if (store->WriteUserConnect(login, currIP))
601 WriteServLog("Cannot write connect for user %s.", login.c_str());
602 WriteServLog("%s", store->GetStrError().c_str());
606 lastIPForDisconnect = currIP;
608 //-----------------------------------------------------------------------------
609 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
612 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
615 STG_LOCKER lock(&mutex);
617 if (!lastIPForDisconnect)
619 printfd(__FILE__, "lastIPForDisconnect\n");
625 lastDisconnectReason = reason;
626 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
628 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
630 char dirsStr[DIR_NUM + 1];
631 dirsStr[DIR_NUM] = 0;
632 for (int i = 0; i < DIR_NUM; i++)
634 dirsStr[i] = enabledDirs[i] ? '1' : '0';
637 std::string scriptOnDisonnectParams;
638 strprintf(&scriptOnDisonnectParams,
639 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
640 scriptOnDisonnect.c_str(),
642 inet_ntostring(lastIPForDisconnect).c_str(),
647 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
648 while (it != settings->GetScriptParams().end())
650 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
654 ScriptExec(scriptOnDisonnectParams.c_str());
658 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
664 std::string reasonMessage(reason);
665 if (!lastDisconnectReason.empty())
666 reasonMessage += ": " + lastDisconnectReason;
668 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
669 cash, freeMb, reasonMessage))
671 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
672 WriteServLog("%s", store->GetStrError().c_str());
676 lastIPForDisconnect = 0;
678 DIR_TRAFF zeroSesssion;
680 sessionUpload = zeroSesssion;
681 sessionDownload = zeroSesssion;
682 sessionUploadModTime = stgTime;
683 sessionDownloadModTime = stgTime;
685 //-----------------------------------------------------------------------------
686 void USER_IMPL::PrintUser() const
689 STG_LOCKER lock(&mutex);
690 std::cout << "============================================================" << std::endl;
691 std::cout << "id=" << id << std::endl;
692 std::cout << "login=" << login << std::endl;
693 std::cout << "password=" << password << std::endl;
694 std::cout << "passive=" << passive << std::endl;
695 std::cout << "disabled=" << disabled << std::endl;
696 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
697 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
698 std::cout << "tariffName=" << tariffName << std::endl;
699 std::cout << "address=" << address << std::endl;
700 std::cout << "phone=" << phone << std::endl;
701 std::cout << "email=" << email << std::endl;
702 std::cout << "note=" << note << std::endl;
703 std::cout << "realName=" <<realName << std::endl;
704 std::cout << "group=" << group << std::endl;
705 std::cout << "credit=" << credit << std::endl;
706 std::cout << "nextTariff=" << nextTariff << std::endl;
707 std::cout << "userdata0" << userdata0 << std::endl;
708 std::cout << "userdata1" << userdata1 << std::endl;
709 std::cout << "creditExpire=" << creditExpire << std::endl;
710 std::cout << "ips=" << ips << std::endl;
711 std::cout << "------------------------" << std::endl;
712 std::cout << "up=" << up << std::endl;
713 std::cout << "down=" << down << std::endl;
714 std::cout << "cash=" << cash << std::endl;
715 std::cout << "freeMb=" << freeMb << std::endl;
716 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
717 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
718 std::cout << "passiveTime=" << passiveTime << std::endl;
719 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
720 std::cout << "============================================================" << std::endl;
722 //-----------------------------------------------------------------------------
723 void USER_IMPL::Run()
725 STG_LOCKER lock(&mutex);
727 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
729 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
732 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
734 WriteServLog("User: %s. Credit expired.", login.c_str());
740 if (passive.ConstData()
741 && (stgTime % 30 == 0)
742 && (passiveTime.ModificationTime() != stgTime))
744 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
745 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
748 if (!authorizedBy.empty())
752 property.Stat().lastActivityTime = stgTime;
754 if (!connected && IsInetable())
758 if (connected && !IsInetable())
761 Disconnect(false, "disabled");
763 Disconnect(false, "passive");
765 Disconnect(false, "no cash");
768 if (stgTime - lastScanMessages > 10)
771 lastScanMessages = stgTime;
778 Disconnect(false, "not authorized");
783 //-----------------------------------------------------------------------------
784 void USER_IMPL::UpdatePingTime(time_t t)
786 STG_LOCKER lock(&mutex);
787 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
793 //-----------------------------------------------------------------------------
794 bool USER_IMPL::IsInetable()
796 //STG_LOCKER lock(&mutex);
798 if (disabled || passive)
801 if (settings->GetFreeMbAllowInet())
807 if (settings->GetShowFeeInCash() || tariff == NULL)
809 return (cash >= -credit);
812 return (cash - tariff->GetFee() >= -credit);
814 //-----------------------------------------------------------------------------
815 std::string USER_IMPL::GetEnabledDirs() const
817 //STG_LOCKER lock(&mutex);
819 std::string dirs = "";
820 for(int i = 0; i < DIR_NUM; i++)
821 dirs += enabledDirs[i] ? "1" : "0";
824 //-----------------------------------------------------------------------------
825 #ifdef TRAFF_STAT_WITH_PORTS
826 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
828 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
831 STG_LOCKER lock(&mutex);
833 if (!connected || tariff == NULL)
839 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
840 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
844 int tt = tariff->GetTraffType();
845 if (tt == TARIFF::TRAFF_UP ||
846 tt == TARIFF::TRAFF_UP_DOWN ||
847 // Check NEW traff data
848 (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
851 if (traff < threshold &&
852 traff + len >= threshold)
854 // cash = partBeforeThreshold * priceBeforeThreshold +
855 // partAfterThreshold * priceAfterThreshold
856 int64_t before = threshold - traff; // Chunk part before threshold
857 int64_t after = len - before; // Chunk part after threshold
858 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
859 down.ConstData()[dir],
862 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
863 down.ConstData()[dir],
869 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
870 down.ConstData()[dir],
875 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
877 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
878 cost = dc - freeMb.ConstData();
880 // Direct access to internal data structures via friend-specifier
881 property.Stat().freeMb -= dc;
882 property.Stat().cash -= cost;
888 sessionUpload[dir] += len;
889 sessionUploadModTime = stgTime;
893 if (!settings->GetWriteFreeMbTraffCost() &&
894 freeMb.ConstData() >= 0)
897 #ifdef TRAFF_STAT_WITH_PORTS
898 IP_DIR_PAIR idp(ip, dir, port);
900 IP_DIR_PAIR idp(ip, dir);
903 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
904 lb = traffStat.lower_bound(idp);
905 if (lb == traffStat.end() || lb->first != idp)
909 STAT_NODE(len, 0, cost)));
913 lb->second.cash += cost;
914 lb->second.up += len;
917 //-----------------------------------------------------------------------------
918 #ifdef TRAFF_STAT_WITH_PORTS
919 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
921 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
924 STG_LOCKER lock(&mutex);
926 if (!connected || tariff == NULL)
932 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
933 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
937 int tt = tariff->GetTraffType();
938 if (tt == TARIFF::TRAFF_DOWN ||
939 tt == TARIFF::TRAFF_UP_DOWN ||
940 // Check NEW traff data
941 (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
944 if (traff < threshold &&
945 traff + len >= threshold)
947 // cash = partBeforeThreshold * priceBeforeThreshold +
948 // partAfterThreshold * priceAfterThreshold
949 int64_t before = threshold - traff; // Chunk part before threshold
950 int64_t after = len - before; // Chunk part after threshold
951 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
952 down.ConstData()[dir], // Traff before chunk
955 tariff->GetPriceWithTraffType(up.ConstData()[dir],
956 dt[dir], // Traff after chunk
962 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
963 down.ConstData()[dir],
968 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
970 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
971 cost = dc - freeMb.ConstData();
973 property.Stat().freeMb -= dc;
974 property.Stat().cash -= cost;
980 sessionDownload[dir] += len;
981 sessionDownloadModTime = stgTime;
985 if (!settings->GetWriteFreeMbTraffCost() &&
986 freeMb.ConstData() >= 0)
989 #ifdef TRAFF_STAT_WITH_PORTS
990 IP_DIR_PAIR idp(ip, dir, port);
992 IP_DIR_PAIR idp(ip, dir);
995 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
996 lb = traffStat.lower_bound(idp);
997 if (lb == traffStat.end() || lb->first != idp)
1001 STAT_NODE(0, len, cost)));
1005 lb->second.cash += cost;
1006 lb->second.down += len;
1009 //-----------------------------------------------------------------------------
1010 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1012 STG_LOCKER lock(&mutex);
1013 currIP.AddBeforeNotifier(notifier);
1015 //-----------------------------------------------------------------------------
1016 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1018 STG_LOCKER lock(&mutex);
1019 currIP.DelBeforeNotifier(notifier);
1021 //-----------------------------------------------------------------------------
1022 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1024 STG_LOCKER lock(&mutex);
1025 currIP.AddAfterNotifier(notifier);
1027 //-----------------------------------------------------------------------------
1028 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1030 STG_LOCKER lock(&mutex);
1031 currIP.DelAfterNotifier(notifier);
1033 //-----------------------------------------------------------------------------
1034 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1036 STG_LOCKER lock(&mutex);
1037 connected.AddBeforeNotifier(notifier);
1039 //-----------------------------------------------------------------------------
1040 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1042 STG_LOCKER lock(&mutex);
1043 connected.DelBeforeNotifier(notifier);
1045 //-----------------------------------------------------------------------------
1046 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1048 STG_LOCKER lock(&mutex);
1049 connected.AddAfterNotifier(notifier);
1051 //-----------------------------------------------------------------------------
1052 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1054 STG_LOCKER lock(&mutex);
1055 connected.DelAfterNotifier(notifier);
1057 //-----------------------------------------------------------------------------
1058 void USER_IMPL::OnAdd()
1060 STG_LOCKER lock(&mutex);
1062 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1064 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1066 std::string scriptOnAddParams;
1067 strprintf(&scriptOnAddParams,
1069 scriptOnAdd.c_str(),
1072 ScriptExec(scriptOnAddParams.c_str());
1076 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1079 //-----------------------------------------------------------------------------
1080 void USER_IMPL::OnDelete()
1082 STG_LOCKER lock(&mutex);
1084 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1086 if (access(scriptOnDel.c_str(), X_OK) == 0)
1088 std::string scriptOnDelParams;
1089 strprintf(&scriptOnDelParams,
1091 scriptOnDel.c_str(),
1094 ScriptExec(scriptOnDelParams.c_str());
1098 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1103 //-----------------------------------------------------------------------------
1104 int USER_IMPL::WriteDetailStat(bool hard)
1106 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1108 if (!traffStatSaved.second.empty())
1110 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1112 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1113 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1114 WriteServLog("%s", store->GetStrError().c_str());
1117 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1123 STG_LOCKER lock(&mutex);
1127 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1129 if (ts.size() && !disabledDetailStat)
1131 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1133 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1134 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1135 WriteServLog("%s", store->GetStrError().c_str());
1138 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1139 STG_LOCKER lock(&mutex);
1140 traffStatSaved.second.swap(ts);
1141 traffStatSaved.first = lastWriteDetailedStat;
1146 lastWriteDetailedStat = stgTime;
1149 //-----------------------------------------------------------------------------
1150 double USER_IMPL::GetPassiveTimePart() const
1152 STG_LOCKER lock(&mutex);
1154 static int daysInMonth[12] =
1155 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1159 localtime_r(&t, &tms);
1161 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1163 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1166 secMonth += 24 * 3600;
1169 time_t dt = secMonth - passiveTime;
1174 return static_cast<double>(dt) / secMonth;
1176 //-----------------------------------------------------------------------------
1177 void USER_IMPL::SetPassiveTimeAsNewUser()
1179 STG_LOCKER lock(&mutex);
1183 localtime_r(&t, &tm);
1184 int daysCurrMon = DaysInCurrentMonth();
1185 double pt = tm.tm_mday - 1;
1188 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1190 //-----------------------------------------------------------------------------
1191 void USER_IMPL::MidnightResetSessionStat()
1193 STG_LOCKER lock(&mutex);
1197 Disconnect(true, "fake");
1201 //-----------------------------------------------------------------------------
1202 void USER_IMPL::ProcessNewMonth()
1204 STG_LOCKER lock(&mutex);
1208 Disconnect(true, "fake");
1210 DIR_TRAFF zeroTarff;
1223 if (nextTariff.ConstData() != "")
1226 nt = tariffs->FindByName(nextTariff);
1229 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1230 login.c_str(), property.tariffName.Get().c_str());
1234 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1241 //-----------------------------------------------------------------------------
1242 void USER_IMPL::ProcessDayFeeSpread()
1244 STG_LOCKER lock(&mutex);
1246 if (passive.ConstData() || tariff == NULL)
1249 if (tariff->GetPeriod() != TARIFF::MONTH)
1252 double fee = tariff->GetFee() / DaysInCurrentMonth();
1254 if (std::fabs(fee) < 1.0e-3)
1258 switch (settings->GetFeeChargeType())
1261 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1264 if (c + credit >= 0)
1265 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1268 if (c + credit >= fee)
1269 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1273 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1278 //-----------------------------------------------------------------------------
1279 void USER_IMPL::ProcessDayFee()
1281 STG_LOCKER lock(&mutex);
1286 if (tariff->GetPeriod() != TARIFF::MONTH)
1289 double passiveTimePart = 1.0;
1290 if (!settings->GetFullFee())
1292 passiveTimePart = GetPassiveTimePart();
1296 if (passive.ConstData())
1298 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1302 double fee = tariff->GetFee() * passiveTimePart;
1306 if (std::fabs(fee) < 1.0e-3)
1313 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1320 switch (settings->GetFeeChargeType())
1323 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1327 if (c + credit >= 0)
1329 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1334 if (c + credit >= fee)
1336 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1343 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1349 //-----------------------------------------------------------------------------
1350 void USER_IMPL::ProcessDailyFee()
1352 STG_LOCKER lock(&mutex);
1354 if (passive.ConstData() || tariff == NULL)
1357 if (tariff->GetPeriod() != TARIFF::DAY)
1360 double fee = tariff->GetFee();
1366 switch (settings->GetFeeChargeType())
1369 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1372 if (c + credit >= 0)
1373 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1376 if (c + credit >= fee)
1377 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1382 //-----------------------------------------------------------------------------
1383 void USER_IMPL::SetPrepaidTraff()
1386 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1388 //-----------------------------------------------------------------------------
1389 int USER_IMPL::AddMessage(STG_MSG * msg)
1391 STG_LOCKER lock(&mutex);
1393 if (SendMessage(*msg))
1395 if (store->AddMessage(msg, login))
1397 errorStr = store->GetStrError();
1398 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1399 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1402 messages.push_back(*msg);
1406 if (msg->header.repeat > 0)
1408 msg->header.repeat--;
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 if (store->AddMessage(msg, login))
1417 errorStr = store->GetStrError();
1418 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1419 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1422 messages.push_back(*msg);
1427 //-----------------------------------------------------------------------------
1428 int USER_IMPL::SendMessage(STG_MSG & msg) const
1430 // No lock `cause we are already locked from caller
1432 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1433 while (it != authorizedBy.end())
1435 if (!(*it++)->SendMessage(msg, currIP))
1441 //TODO: gcc v. 4.x generate ICE on x86_64
1442 msg.header.lastSendTime = static_cast<int>(time(NULL));
1444 msg.header.lastSendTime = static_cast<int>(stgTime);
1446 msg.header.repeat--;
1450 //-----------------------------------------------------------------------------
1451 void USER_IMPL::ScanMessage()
1453 // No lock `cause we are already locked from caller
1454 // We need not check for the authorizedBy `cause it has already checked by caller
1456 std::list<STG_MSG>::iterator it(messages.begin());
1457 while (it != messages.end())
1459 if (settings->GetMessageTimeout() > 0 &&
1460 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1463 if (store->DelMessage(it->header.id, login))
1465 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1466 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1468 messages.erase(it++);
1471 if (it->GetNextSendTime() <= stgTime)
1473 if (SendMessage(*it))
1475 // We need to check all messages in queue for timeout
1479 if (it->header.repeat < 0)
1481 if (store->DelMessage(it->header.id, login))
1483 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1484 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1486 messages.erase(it++);
1490 if (store->EditMessage(*it, login))
1492 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1493 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1504 //-----------------------------------------------------------------------------
1505 std::string USER_IMPL::GetParamValue(const std::string & name) const
1507 std::string lowerName = ToLower(name);
1508 if (lowerName == "id")
1510 std::ostringstream stream;
1512 return stream.str();
1514 if (lowerName == "login") return login;
1515 if (lowerName == "currip") return currIP.ToString();
1516 if (lowerName == "enableddirs") return GetEnabledDirs();
1517 if (lowerName == "tariff") return property.tariffName;
1518 if (property.Exists(lowerName))
1519 return property.GetPropertyValue(lowerName);
1522 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1526 //-----------------------------------------------------------------------------
1527 //-----------------------------------------------------------------------------
1528 //-----------------------------------------------------------------------------
1529 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1531 if (newPassive && !oldPassive && user->tariff != NULL)
1532 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1538 //-----------------------------------------------------------------------------
1539 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1541 if (oldValue && !newValue && user->GetConnected())
1543 user->Disconnect(false, "disabled");
1545 else if (!oldValue && newValue && user->IsInetable())
1547 user->Connect(false);
1551 //-----------------------------------------------------------------------------
1552 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1554 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1555 user->Disconnect(false, "Change tariff");
1556 user->tariff = user->tariffs->FindByName(newTariff);
1557 if (user->settings->GetReconnectOnTariffChange() &&
1558 !user->authorizedBy.empty() &&
1560 user->Connect(false);
1562 //-----------------------------------------------------------------------------
1563 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1565 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1566 user->lastCashAdd = newCash - oldCash;
1568 //-----------------------------------------------------------------------------
1569 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1571 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1572 if (user->connected)
1573 user->Disconnect(false, "Change IP");
1574 if (!user->authorizedBy.empty() && user->IsInetable())
1575 user->Connect(false);
1577 //-----------------------------------------------------------------------------