2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
27 $Date: 2010/11/03 10:50:03 $
36 #include <unistd.h> // access
44 #include "stg/users.h"
45 #include "stg/common.h"
46 #include "stg/scriptexecuter.h"
47 #include "stg/tariff.h"
48 #include "stg/tariffs.h"
49 #include "stg/admin.h"
50 #include "user_impl.h"
51 #include "settings_impl.h"
52 #include "stg_timer.h"
54 #ifdef USE_ABSTRACT_SETTINGS
55 USER_IMPL::USER_IMPL(const SETTINGS * s,
62 property(s->GetScriptsDir()),
63 WriteServLog(GetStgLogger()),
67 connected(__connected),
70 lastIPForDisconnect(0),
77 authorizedModificationTime(0),
80 lastWriteDetailedStat(0),
84 lastCashAdd(property.lastCashAdd),
85 passiveTime(property.passiveTime),
86 lastCashAddTime(property.lastCashAddTime),
87 freeMb(property.freeMb),
88 lastActivityTime(property.lastActivityTime),
89 password(property.password),
90 passive(property.passive),
91 disabled(property.disabled),
92 disabledDetailStat(property.disabledDetailStat),
93 alwaysOnline(property.alwaysOnline),
94 tariffName(property.tariffName),
95 nextTariff(property.nextTariff),
96 address(property.address),
98 group(property.group),
99 email(property.email),
100 phone(property.phone),
101 realName(property.realName),
102 credit(property.credit),
103 creditExpire(property.creditExpire),
105 userdata0(property.userdata0),
106 userdata1(property.userdata1),
107 userdata2(property.userdata2),
108 userdata3(property.userdata3),
109 userdata4(property.userdata4),
110 userdata5(property.userdata5),
111 userdata6(property.userdata6),
112 userdata7(property.userdata7),
113 userdata8(property.userdata8),
114 userdata9(property.userdata9),
115 passiveNotifier(this),
116 tariffNotifier(this),
120 password = "*_EMPTY_PASSWORD_*";
121 tariffName = NO_TARIFF_NAME;
123 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
124 lastWriteDetailedStat = stgTime;
126 property.tariffName.AddBeforeNotifier(&tariffNotifier);
127 property.passive.AddBeforeNotifier(&passiveNotifier);
128 property.disabled.AddAfterNotifier(&disabledNotifier);
129 property.cash.AddBeforeNotifier(&cashNotifier);
130 ips.AddAfterNotifier(&ipNotifier);
132 pthread_mutexattr_t attr;
133 pthread_mutexattr_init(&attr);
134 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
135 pthread_mutex_init(&mutex, &attr);
138 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
145 property(s->GetScriptsDir()),
146 WriteServLog(GetStgLogger()),
150 connected(__connected),
153 lastIPForDisconnect(0),
160 authorizedModificationTime(0),
163 lastWriteDetailedStat(0),
167 lastCashAdd(property.lastCashAdd),
168 passiveTime(property.passiveTime),
169 lastCashAddTime(property.lastCashAddTime),
170 freeMb(property.freeMb),
171 lastActivityTime(property.lastActivityTime),
172 password(property.password),
173 passive(property.passive),
174 disabled(property.disabled),
175 disabledDetailStat(property.disabledDetailStat),
176 alwaysOnline(property.alwaysOnline),
177 tariffName(property.tariffName),
178 nextTariff(property.nextTariff),
179 address(property.address),
181 group(property.group),
182 email(property.email),
183 phone(property.phone),
184 realName(property.realName),
185 credit(property.credit),
186 creditExpire(property.creditExpire),
188 userdata0(property.userdata0),
189 userdata1(property.userdata1),
190 userdata2(property.userdata2),
191 userdata3(property.userdata3),
192 userdata4(property.userdata4),
193 userdata5(property.userdata5),
194 userdata6(property.userdata6),
195 userdata7(property.userdata7),
196 userdata8(property.userdata8),
197 userdata9(property.userdata9),
198 passiveNotifier(this),
199 disabledNotifier(this),
200 tariffNotifier(this),
204 password = "*_EMPTY_PASSWORD_*";
205 tariffName = NO_TARIFF_NAME;
207 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
208 lastWriteDetailedStat = stgTime;
210 property.tariffName.AddBeforeNotifier(&tariffNotifier);
211 property.passive.AddBeforeNotifier(&passiveNotifier);
212 property.disabled.AddAfterNotifier(&disabledNotifier);
213 property.cash.AddBeforeNotifier(&cashNotifier);
214 ips.AddAfterNotifier(&ipNotifier);
216 pthread_mutexattr_t attr;
217 pthread_mutexattr_init(&attr);
218 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
219 pthread_mutex_init(&mutex, &attr);
222 //-----------------------------------------------------------------------------
223 USER_IMPL::USER_IMPL(const USER_IMPL & u)
226 property(u.settings->GetScriptsDir()),
227 WriteServLog(GetStgLogger()),
232 connected(__connected),
233 userIDGenerator(u.userIDGenerator),
234 __currIP(u.__currIP),
236 lastIPForDisconnect(0),
237 pingTime(u.pingTime),
238 sysAdmin(u.sysAdmin),
242 traffStat(u.traffStat),
243 traffStatSaved(u.traffStatSaved),
244 settings(u.settings),
245 authorizedModificationTime(u.authorizedModificationTime),
246 messages(u.messages),
248 lastWriteStat(u.lastWriteStat),
249 lastWriteDetailedStat(u.lastWriteDetailedStat),
253 lastCashAdd(property.lastCashAdd),
254 passiveTime(property.passiveTime),
255 lastCashAddTime(property.lastCashAddTime),
256 freeMb(property.freeMb),
257 lastActivityTime(property.lastActivityTime),
258 password(property.password),
259 passive(property.passive),
260 disabled(property.disabled),
261 disabledDetailStat(property.disabledDetailStat),
262 alwaysOnline(property.alwaysOnline),
263 tariffName(property.tariffName),
264 nextTariff(property.nextTariff),
265 address(property.address),
267 group(property.group),
268 email(property.email),
269 phone(property.phone),
270 realName(property.realName),
271 credit(property.credit),
272 creditExpire(property.creditExpire),
274 userdata0(property.userdata0),
275 userdata1(property.userdata1),
276 userdata2(property.userdata2),
277 userdata3(property.userdata3),
278 userdata4(property.userdata4),
279 userdata5(property.userdata5),
280 userdata6(property.userdata6),
281 userdata7(property.userdata7),
282 userdata8(property.userdata8),
283 userdata9(property.userdata9),
286 passiveNotifier(this),
287 disabledNotifier(this),
288 tariffNotifier(this),
295 property.tariffName.AddBeforeNotifier(&tariffNotifier);
296 property.passive.AddBeforeNotifier(&passiveNotifier);
297 property.disabled.AddAfterNotifier(&disabledNotifier);
298 property.cash.AddBeforeNotifier(&cashNotifier);
299 ips.AddAfterNotifier(&ipNotifier);
301 property.SetProperties(u.property);
303 pthread_mutexattr_t attr;
304 pthread_mutexattr_init(&attr);
305 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
306 pthread_mutex_init(&mutex, &attr);
308 //-----------------------------------------------------------------------------
309 USER_IMPL::~USER_IMPL()
311 property.tariffName.DelBeforeNotifier(&tariffNotifier);
312 property.passive.DelBeforeNotifier(&passiveNotifier);
313 property.disabled.DelAfterNotifier(&disabledNotifier);
314 property.cash.DelBeforeNotifier(&cashNotifier);
315 pthread_mutex_destroy(&mutex);
317 //-----------------------------------------------------------------------------
318 void USER_IMPL::SetLogin(const std::string & l)
320 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
321 assert(login.empty() && "Login is already set");
323 id = userIDGenerator.GetNextID();
325 //-----------------------------------------------------------------------------
326 int USER_IMPL::ReadConf()
328 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
331 if (store->RestoreUserConf(&conf, login))
333 WriteServLog("Cannot read conf for user %s.", login.c_str());
334 WriteServLog("%s", store->GetStrError().c_str());
335 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
336 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
340 property.SetConf(conf);
342 tariff = tariffs->FindByName(tariffName);
345 WriteServLog("Cannot read user %s. Tariff %s not exist.",
346 login.c_str(), property.tariffName.Get().c_str());
350 std::vector<STG_MSG_HDR> hdrsList;
352 if (store->GetMessageHdrs(&hdrsList, login))
354 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
355 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
357 store->GetStrError().c_str());
361 std::vector<STG_MSG_HDR>::const_iterator it;
362 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
365 if (store->GetMessage(it->id, &msg, login) == 0)
367 messages.push_back(msg);
373 //-----------------------------------------------------------------------------
374 int USER_IMPL::ReadStat()
376 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
379 if (store->RestoreUserStat(&stat, login))
381 WriteServLog("Cannot read stat for user %s.", login.c_str());
382 WriteServLog("%s", store->GetStrError().c_str());
383 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
384 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
388 property.SetStat(stat);
392 //-----------------------------------------------------------------------------
393 int USER_IMPL::WriteConf()
395 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
396 USER_CONF conf(property.GetConf());
398 printfd(__FILE__, "USER::WriteConf()\n");
400 if (store->SaveUserConf(conf, login))
402 WriteServLog("Cannot write conf for user %s.", login.c_str());
403 WriteServLog("%s", store->GetStrError().c_str());
404 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
405 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
411 //-----------------------------------------------------------------------------
412 int USER_IMPL::WriteStat()
414 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
415 USER_STAT stat(property.GetStat());
417 if (store->SaveUserStat(stat, login))
419 WriteServLog("Cannot write stat for user %s.", login.c_str());
420 WriteServLog("%s", store->GetStrError().c_str());
421 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
422 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
426 lastWriteStat = stgTime;
430 //-----------------------------------------------------------------------------
431 int USER_IMPL::WriteMonthStat()
433 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
434 time_t tt = stgTime - 3600;
436 localtime_r(&tt, &t1);
438 USER_STAT stat(property.GetStat());
439 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
441 WriteServLog("Cannot write month stat for user %s.", login.c_str());
442 WriteServLog("%s", store->GetStrError().c_str());
443 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
444 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
450 //-----------------------------------------------------------------------------
451 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
453 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
455 * Authorize user. It only means that user will be authorized. Nothing more.
456 * User can be connected or disconnected while authorized.
457 * Example: user is authorized but disconnected due to 0 money or blocking
461 * Prevent double authorization by identical authorizers
463 if (authorizedBy.find(auth) != authorizedBy.end())
469 for (int i = 0; i < DIR_NUM; i++)
471 enabledDirs[i] = dirs & (1 << i);
474 if (!authorizedBy.empty())
478 // We are already authorized, but with different IP address
479 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
484 if (!users->FindByIPIdx(ip, &u))
486 // Address is already present in IP-index
487 // If it's not our IP - throw an error
490 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
497 if (users->IsIPInIndex(ip))
499 // Address is already present in IP-index
500 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
504 if (ips.ConstData().IsIPInIPS(ip))
507 lastIPForDisconnect = currIP;
511 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
512 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
517 if (authorizedBy.empty())
518 authorizedModificationTime = stgTime;
519 authorizedBy.insert(auth);
525 //-----------------------------------------------------------------------------
526 void USER_IMPL::Unauthorize(const AUTH * auth)
528 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
530 * Authorizer tries to unauthorize user, that was not authorized by it
532 if (!authorizedBy.erase(auth))
535 if (authorizedBy.empty())
537 authorizedModificationTime = stgTime;
538 lastIPForDisconnect = currIP;
539 currIP = 0; // DelUser in traffcounter
543 //-----------------------------------------------------------------------------
544 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
546 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
547 // Is this user authorized by specified authorizer?
548 return authorizedBy.find(auth) != authorizedBy.end();
550 //-----------------------------------------------------------------------------
551 std::vector<std::string> USER_IMPL::GetAuthorizers() const
553 std::vector<std::string> list;
554 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
557 //-----------------------------------------------------------------------------
558 void USER_IMPL::Connect(bool fakeConnect)
561 * Connect user to Internet. This function is differ from Authorize() !!!
564 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
568 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
570 if (access(scriptOnConnect.c_str(), X_OK) == 0)
572 char dirsStr[DIR_NUM + 1];
573 dirsStr[DIR_NUM] = 0;
574 for (int i = 0; i < DIR_NUM; i++)
576 dirsStr[i] = enabledDirs[i] ? '1' : '0';
579 std::string scriptOnConnectParams;
580 strprintf(&scriptOnConnectParams,
581 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
582 scriptOnConnect.c_str(),
584 inet_ntostring(currIP).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, __FILE__, __LINE__);
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 ScriptExec(scriptOnDisonnectParams.c_str());
651 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
657 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
659 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
660 WriteServLog("%s", store->GetStrError().c_str());
664 lastIPForDisconnect = 0;
666 DIR_TRAFF zeroSesssion;
668 sessionUpload = zeroSesssion;
669 sessionDownload = zeroSesssion;
671 //-----------------------------------------------------------------------------
672 void USER_IMPL::PrintUser() const
675 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
676 std::cout << "============================================================" << std::endl;
677 std::cout << "id=" << id << std::endl;
678 std::cout << "login=" << login << std::endl;
679 std::cout << "password=" << password << std::endl;
680 std::cout << "passive=" << passive << std::endl;
681 std::cout << "disabled=" << disabled << std::endl;
682 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
683 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
684 std::cout << "tariffName=" << tariffName << std::endl;
685 std::cout << "address=" << address << std::endl;
686 std::cout << "phone=" << phone << std::endl;
687 std::cout << "email=" << email << std::endl;
688 std::cout << "note=" << note << std::endl;
689 std::cout << "realName=" <<realName << std::endl;
690 std::cout << "group=" << group << std::endl;
691 std::cout << "credit=" << credit << std::endl;
692 std::cout << "nextTariff=" << nextTariff << std::endl;
693 std::cout << "userdata0" << userdata0 << std::endl;
694 std::cout << "userdata1" << userdata1 << std::endl;
695 std::cout << "creditExpire=" << creditExpire << std::endl;
696 std::cout << "ips=" << ips << std::endl;
697 std::cout << "------------------------" << std::endl;
698 std::cout << "up=" << up << std::endl;
699 std::cout << "down=" << down << std::endl;
700 std::cout << "cash=" << cash << std::endl;
701 std::cout << "freeMb=" << freeMb << std::endl;
702 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
703 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
704 std::cout << "passiveTime=" << passiveTime << std::endl;
705 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
706 std::cout << "============================================================" << std::endl;
708 //-----------------------------------------------------------------------------
709 void USER_IMPL::Run()
711 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
713 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
715 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
718 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
720 WriteServLog("User: %s. Credit expired.", login.c_str());
726 if (passive.ConstData()
727 && (stgTime % 30 == 0)
728 && (passiveTime.ModificationTime() != stgTime))
730 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
731 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
734 if (!authorizedBy.empty())
738 property.Stat().lastActivityTime = stgTime;
740 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;
764 Disconnect(false, "not authorized");
769 //-----------------------------------------------------------------------------
770 void USER_IMPL::UpdatePingTime(time_t t)
772 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
773 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
779 //-----------------------------------------------------------------------------
780 bool USER_IMPL::IsInetable()
782 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
784 if (disabled || passive)
787 if (settings->GetFreeMbAllowInet())
793 if (settings->GetShowFeeInCash() || tariff == NULL)
795 return (cash >= -credit);
798 return (cash - tariff->GetFee() >= -credit);
800 //-----------------------------------------------------------------------------
801 std::string USER_IMPL::GetEnabledDirs()
803 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
805 std::string dirs = "";
806 for(int i = 0; i < DIR_NUM; i++)
807 dirs += enabledDirs[i] ? "1" : "0";
810 //-----------------------------------------------------------------------------
811 #ifdef TRAFF_STAT_WITH_PORTS
812 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
814 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
817 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
819 if (!connected || tariff == NULL)
825 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
826 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
830 int tt = tariff->GetTraffType();
831 if (tt == TRAFF_UP ||
832 tt == TRAFF_UP_DOWN ||
833 // Check NEW traff data
834 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
837 if (traff < threshold &&
838 traff + len >= threshold)
840 // cash = partBeforeThreshold * priceBeforeThreshold +
841 // partAfterThreshold * priceAfterThreshold
842 int64_t before = threshold - traff; // Chunk part before threshold
843 int64_t after = len - before; // Chunk part after threshold
844 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
845 down.ConstData()[dir],
848 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
849 down.ConstData()[dir],
855 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
856 down.ConstData()[dir],
861 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
863 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
864 cost = dc - freeMb.ConstData();
866 // Direct access to internal data structures via friend-specifier
867 property.Stat().freeMb -= dc;
868 property.Stat().cash -= cost;
874 sessionUpload[dir] += len;
878 if (!settings->GetWriteFreeMbTraffCost() &&
879 freeMb.ConstData() >= 0)
882 #ifdef TRAFF_STAT_WITH_PORTS
883 IP_DIR_PAIR idp(ip, dir, port);
885 IP_DIR_PAIR idp(ip, dir);
888 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
889 lb = traffStat.lower_bound(idp);
890 if (lb == traffStat.end() || lb->first != idp)
894 STAT_NODE(len, 0, cost)));
898 lb->second.cash += cost;
899 lb->second.up += len;
902 //-----------------------------------------------------------------------------
903 #ifdef TRAFF_STAT_WITH_PORTS
904 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
906 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
909 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
911 if (!connected || tariff == NULL)
917 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
918 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
922 int tt = tariff->GetTraffType();
923 if (tt == TRAFF_DOWN ||
924 tt == TRAFF_UP_DOWN ||
925 // Check NEW traff data
926 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
929 if (traff < threshold &&
930 traff + len >= threshold)
932 // cash = partBeforeThreshold * priceBeforeThreshold +
933 // partAfterThreshold * priceAfterThreshold
934 int64_t before = threshold - traff; // Chunk part before threshold
935 int64_t after = len - before; // Chunk part after threshold
936 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
937 down.ConstData()[dir], // Traff before chunk
940 tariff->GetPriceWithTraffType(up.ConstData()[dir],
941 dt[dir], // Traff after chunk
947 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
948 down.ConstData()[dir],
953 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
955 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
956 cost = dc - freeMb.ConstData();
958 property.Stat().freeMb -= dc;
959 property.Stat().cash -= cost;
965 sessionDownload[dir] += len;
969 if (!settings->GetWriteFreeMbTraffCost() &&
970 freeMb.ConstData() >= 0)
973 #ifdef TRAFF_STAT_WITH_PORTS
974 IP_DIR_PAIR idp(ip, dir, port);
976 IP_DIR_PAIR idp(ip, dir);
979 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
980 lb = traffStat.lower_bound(idp);
981 if (lb == traffStat.end() || lb->first != idp)
985 STAT_NODE(0, len, cost)));
989 lb->second.cash += cost;
990 lb->second.down += len;
993 //-----------------------------------------------------------------------------
994 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
996 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
997 currIP.AddBeforeNotifier(notifier);
999 //-----------------------------------------------------------------------------
1000 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1002 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1003 currIP.DelBeforeNotifier(notifier);
1005 //-----------------------------------------------------------------------------
1006 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1008 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1009 currIP.AddAfterNotifier(notifier);
1011 //-----------------------------------------------------------------------------
1012 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1014 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1015 currIP.DelAfterNotifier(notifier);
1017 //-----------------------------------------------------------------------------
1018 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1020 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1021 connected.AddBeforeNotifier(notifier);
1023 //-----------------------------------------------------------------------------
1024 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1026 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1027 connected.DelBeforeNotifier(notifier);
1029 //-----------------------------------------------------------------------------
1030 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1032 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1033 connected.AddAfterNotifier(notifier);
1035 //-----------------------------------------------------------------------------
1036 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1038 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1039 connected.DelAfterNotifier(notifier);
1041 //-----------------------------------------------------------------------------
1042 void USER_IMPL::OnAdd()
1044 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1046 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1048 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1050 std::string scriptOnAddParams;
1051 strprintf(&scriptOnAddParams,
1053 scriptOnAdd.c_str(),
1056 ScriptExec(scriptOnAddParams.c_str());
1060 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1063 //-----------------------------------------------------------------------------
1064 void USER_IMPL::OnDelete()
1066 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1068 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1070 if (access(scriptOnDel.c_str(), X_OK) == 0)
1072 std::string scriptOnDelParams;
1073 strprintf(&scriptOnDelParams,
1075 scriptOnDel.c_str(),
1078 ScriptExec(scriptOnDelParams.c_str());
1082 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1087 //-----------------------------------------------------------------------------
1088 int USER_IMPL::WriteDetailStat(bool hard)
1090 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1092 if (!traffStatSaved.second.empty())
1094 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1096 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1097 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1098 WriteServLog("%s", store->GetStrError().c_str());
1101 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1107 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1111 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1113 if (ts.size() && !disabledDetailStat)
1115 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1117 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1118 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1119 WriteServLog("%s", store->GetStrError().c_str());
1122 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1123 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1124 traffStatSaved.second.swap(ts);
1125 traffStatSaved.first = lastWriteDetailedStat;
1130 lastWriteDetailedStat = stgTime;
1133 //-----------------------------------------------------------------------------
1134 double USER_IMPL::GetPassiveTimePart() const
1136 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1138 static int daysInMonth[12] =
1139 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1143 localtime_r(&t, &tms);
1145 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1147 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1150 secMonth += 24 * 3600;
1153 time_t dt = secMonth - passiveTime;
1158 return static_cast<double>(dt) / secMonth;
1160 //-----------------------------------------------------------------------------
1161 void USER_IMPL::SetPassiveTimeAsNewUser()
1163 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1167 localtime_r(&t, &tm);
1168 int daysCurrMon = DaysInCurrentMonth();
1169 double pt = tm.tm_mday - 1;
1172 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1174 //-----------------------------------------------------------------------------
1175 void USER_IMPL::MidnightResetSessionStat()
1177 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1181 Disconnect(true, "fake");
1185 //-----------------------------------------------------------------------------
1186 void USER_IMPL::ProcessNewMonth()
1188 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1192 Disconnect(true, "fake");
1194 DIR_TRAFF zeroTarff;
1207 if (nextTariff.ConstData() != "")
1210 nt = tariffs->FindByName(nextTariff);
1213 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1214 login.c_str(), property.tariffName.Get().c_str());
1218 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1225 //-----------------------------------------------------------------------------
1226 void USER_IMPL::ProcessDayFeeSpread()
1228 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1230 if (passive.ConstData() || tariff == NULL)
1233 double fee = tariff->GetFee() / DaysInCurrentMonth();
1235 if (std::fabs(fee) < 1.0e-3)
1239 switch (settings->GetFeeChargeType())
1242 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1245 if (c + credit >= 0)
1246 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1249 if (c + credit >= fee)
1250 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1254 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1259 //-----------------------------------------------------------------------------
1260 void USER_IMPL::ProcessDayFee()
1262 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1267 double passiveTimePart = 1.0;
1268 if (!settings->GetFullFee())
1270 passiveTimePart = GetPassiveTimePart();
1274 if (passive.ConstData())
1276 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1280 double fee = tariff->GetFee() * passiveTimePart;
1284 if (std::fabs(fee) < 1.0e-3)
1291 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1298 switch (settings->GetFeeChargeType())
1301 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1305 if (c + credit >= 0)
1307 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1312 if (c + credit >= fee)
1314 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1321 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1327 //-----------------------------------------------------------------------------
1328 void USER_IMPL::SetPrepaidTraff()
1331 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1333 //-----------------------------------------------------------------------------
1334 int USER_IMPL::AddMessage(STG_MSG * msg)
1336 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1338 if (SendMessage(*msg))
1340 if (store->AddMessage(msg, login))
1342 errorStr = store->GetStrError();
1343 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1344 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1347 messages.push_back(*msg);
1351 if (msg->header.repeat > 0)
1353 msg->header.repeat--;
1355 //TODO: gcc v. 4.x generate ICE on x86_64
1356 msg->header.lastSendTime = static_cast<int>(time(NULL));
1358 msg->header.lastSendTime = static_cast<int>(stgTime);
1360 if (store->AddMessage(msg, login))
1362 errorStr = store->GetStrError();
1363 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1364 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1367 messages.push_back(*msg);
1372 //-----------------------------------------------------------------------------
1373 int USER_IMPL::SendMessage(STG_MSG & msg) const
1375 // No lock `cause we are already locked from caller
1377 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1378 while (it != authorizedBy.end())
1380 if (!(*it++)->SendMessage(msg, currIP))
1386 //TODO: gcc v. 4.x generate ICE on x86_64
1387 msg.header.lastSendTime = static_cast<int>(time(NULL));
1389 msg.header.lastSendTime = static_cast<int>(stgTime);
1391 msg.header.repeat--;
1395 //-----------------------------------------------------------------------------
1396 void USER_IMPL::ScanMessage()
1398 // No lock `cause we are already locked from caller
1399 // We need not check for the authorizedBy `cause it has already checked by caller
1401 std::list<STG_MSG>::iterator it(messages.begin());
1402 while (it != messages.end())
1404 if (settings->GetMessageTimeout() > 0 &&
1405 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1408 if (store->DelMessage(it->header.id, login))
1410 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1411 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1413 messages.erase(it++);
1416 if (it->GetNextSendTime() <= stgTime)
1418 if (SendMessage(*it))
1420 // We need to check all messages in queue for timeout
1424 if (it->header.repeat < 0)
1426 if (store->DelMessage(it->header.id, login))
1428 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1429 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1431 messages.erase(it++);
1435 if (store->EditMessage(*it, login))
1437 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1438 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1449 //-----------------------------------------------------------------------------
1450 //-----------------------------------------------------------------------------
1451 //-----------------------------------------------------------------------------
1452 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1454 if (newPassive && !oldPassive && user->tariff != NULL)
1455 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1461 //-----------------------------------------------------------------------------
1462 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1464 if (oldValue && !newValue && user->GetConnected())
1466 user->Disconnect(false, "disabled");
1468 else if (!oldValue && newValue && user->IsInetable())
1470 user->Connect(false);
1474 //-----------------------------------------------------------------------------
1475 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1477 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1478 user->Disconnect(false, "Change tariff");
1479 user->tariff = user->tariffs->FindByName(newTariff);
1480 if (user->settings->GetReconnectOnTariffChange() &&
1481 !user->authorizedBy.empty() &&
1483 user->Connect(false);
1485 //-----------------------------------------------------------------------------
1486 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1488 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1489 user->lastCashAdd = newCash - oldCash;
1491 //-----------------------------------------------------------------------------
1492 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1494 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1495 if (user->connected)
1496 user->Disconnect(false, "Change IP");
1497 if (!user->authorizedBy.empty() && user->IsInetable())
1498 user->Connect(false);
1500 //-----------------------------------------------------------------------------