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,
64 property(s->GetScriptsDir()),
65 WriteServLog(GetStgLogger()),
69 connected(__connected),
72 lastIPForDisconnect(0),
79 authorizedModificationTime(0),
82 lastWriteDetailedStat(0),
86 lastCashAdd(property.lastCashAdd),
87 passiveTime(property.passiveTime),
88 lastCashAddTime(property.lastCashAddTime),
89 freeMb(property.freeMb),
90 lastActivityTime(property.lastActivityTime),
91 password(property.password),
92 passive(property.passive),
93 disabled(property.disabled),
94 disabledDetailStat(property.disabledDetailStat),
95 alwaysOnline(property.alwaysOnline),
96 tariffName(property.tariffName),
97 nextTariff(property.nextTariff),
98 address(property.address),
100 group(property.group),
101 email(property.email),
102 phone(property.phone),
103 realName(property.realName),
104 credit(property.credit),
105 creditExpire(property.creditExpire),
107 userdata0(property.userdata0),
108 userdata1(property.userdata1),
109 userdata2(property.userdata2),
110 userdata3(property.userdata3),
111 userdata4(property.userdata4),
112 userdata5(property.userdata5),
113 userdata6(property.userdata6),
114 userdata7(property.userdata7),
115 userdata8(property.userdata8),
116 userdata9(property.userdata9),
117 passiveNotifier(this),
118 tariffNotifier(this),
122 password = "*_EMPTY_PASSWORD_*";
123 tariffName = NO_TARIFF_NAME;
125 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
126 lastWriteDetailedStat = stgTime;
128 property.tariffName.AddBeforeNotifier(&tariffNotifier);
129 property.passive.AddBeforeNotifier(&passiveNotifier);
130 property.disabled.AddAfterNotifier(&disabledNotifier);
131 property.cash.AddBeforeNotifier(&cashNotifier);
132 ips.AddAfterNotifier(&ipNotifier);
134 pthread_mutexattr_t attr;
135 pthread_mutexattr_init(&attr);
136 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
137 pthread_mutex_init(&mutex, &attr);
140 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
147 property(s->GetScriptsDir()),
148 WriteServLog(GetStgLogger()),
152 connected(__connected),
155 lastIPForDisconnect(0),
162 authorizedModificationTime(0),
165 lastWriteDetailedStat(0),
169 lastCashAdd(property.lastCashAdd),
170 passiveTime(property.passiveTime),
171 lastCashAddTime(property.lastCashAddTime),
172 freeMb(property.freeMb),
173 lastActivityTime(property.lastActivityTime),
174 password(property.password),
175 passive(property.passive),
176 disabled(property.disabled),
177 disabledDetailStat(property.disabledDetailStat),
178 alwaysOnline(property.alwaysOnline),
179 tariffName(property.tariffName),
180 nextTariff(property.nextTariff),
181 address(property.address),
183 group(property.group),
184 email(property.email),
185 phone(property.phone),
186 realName(property.realName),
187 credit(property.credit),
188 creditExpire(property.creditExpire),
190 userdata0(property.userdata0),
191 userdata1(property.userdata1),
192 userdata2(property.userdata2),
193 userdata3(property.userdata3),
194 userdata4(property.userdata4),
195 userdata5(property.userdata5),
196 userdata6(property.userdata6),
197 userdata7(property.userdata7),
198 userdata8(property.userdata8),
199 userdata9(property.userdata9),
200 passiveNotifier(this),
201 disabledNotifier(this),
202 tariffNotifier(this),
206 password = "*_EMPTY_PASSWORD_*";
207 tariffName = NO_TARIFF_NAME;
209 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
210 lastWriteDetailedStat = stgTime;
212 property.tariffName.AddBeforeNotifier(&tariffNotifier);
213 property.passive.AddBeforeNotifier(&passiveNotifier);
214 property.disabled.AddAfterNotifier(&disabledNotifier);
215 property.cash.AddBeforeNotifier(&cashNotifier);
216 ips.AddAfterNotifier(&ipNotifier);
218 pthread_mutexattr_t attr;
219 pthread_mutexattr_init(&attr);
220 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
221 pthread_mutex_init(&mutex, &attr);
224 //-----------------------------------------------------------------------------
225 USER_IMPL::USER_IMPL(const USER_IMPL & u)
228 property(u.settings->GetScriptsDir()),
229 WriteServLog(GetStgLogger()),
234 connected(__connected),
235 userIDGenerator(u.userIDGenerator),
236 __currIP(u.__currIP),
238 lastIPForDisconnect(0),
239 pingTime(u.pingTime),
240 sysAdmin(u.sysAdmin),
244 traffStat(u.traffStat),
245 traffStatSaved(u.traffStatSaved),
246 settings(u.settings),
247 authorizedModificationTime(u.authorizedModificationTime),
248 messages(u.messages),
250 lastWriteStat(u.lastWriteStat),
251 lastWriteDetailedStat(u.lastWriteDetailedStat),
255 lastCashAdd(property.lastCashAdd),
256 passiveTime(property.passiveTime),
257 lastCashAddTime(property.lastCashAddTime),
258 freeMb(property.freeMb),
259 lastActivityTime(property.lastActivityTime),
260 password(property.password),
261 passive(property.passive),
262 disabled(property.disabled),
263 disabledDetailStat(property.disabledDetailStat),
264 alwaysOnline(property.alwaysOnline),
265 tariffName(property.tariffName),
266 nextTariff(property.nextTariff),
267 address(property.address),
269 group(property.group),
270 email(property.email),
271 phone(property.phone),
272 realName(property.realName),
273 credit(property.credit),
274 creditExpire(property.creditExpire),
276 userdata0(property.userdata0),
277 userdata1(property.userdata1),
278 userdata2(property.userdata2),
279 userdata3(property.userdata3),
280 userdata4(property.userdata4),
281 userdata5(property.userdata5),
282 userdata6(property.userdata6),
283 userdata7(property.userdata7),
284 userdata8(property.userdata8),
285 userdata9(property.userdata9),
288 passiveNotifier(this),
289 disabledNotifier(this),
290 tariffNotifier(this),
297 property.tariffName.AddBeforeNotifier(&tariffNotifier);
298 property.passive.AddBeforeNotifier(&passiveNotifier);
299 property.disabled.AddAfterNotifier(&disabledNotifier);
300 property.cash.AddBeforeNotifier(&cashNotifier);
301 ips.AddAfterNotifier(&ipNotifier);
303 property.SetProperties(u.property);
305 pthread_mutexattr_t attr;
306 pthread_mutexattr_init(&attr);
307 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
308 pthread_mutex_init(&mutex, &attr);
310 //-----------------------------------------------------------------------------
311 USER_IMPL::~USER_IMPL()
313 property.tariffName.DelBeforeNotifier(&tariffNotifier);
314 property.passive.DelBeforeNotifier(&passiveNotifier);
315 property.disabled.DelAfterNotifier(&disabledNotifier);
316 property.cash.DelBeforeNotifier(&cashNotifier);
317 pthread_mutex_destroy(&mutex);
319 //-----------------------------------------------------------------------------
320 void USER_IMPL::SetLogin(const std::string & l)
322 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
323 assert(login.empty() && "Login is already set");
325 id = userIDGenerator.GetNextID();
327 //-----------------------------------------------------------------------------
328 int USER_IMPL::ReadConf()
330 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
333 if (store->RestoreUserConf(&conf, login))
335 WriteServLog("Cannot read conf for user %s.", login.c_str());
336 WriteServLog("%s", store->GetStrError().c_str());
337 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
338 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
342 property.SetConf(conf);
344 tariff = tariffs->FindByName(tariffName);
347 WriteServLog("Cannot read user %s. Tariff %s not exist.",
348 login.c_str(), property.tariffName.Get().c_str());
352 std::vector<STG_MSG_HDR> hdrsList;
354 if (store->GetMessageHdrs(&hdrsList, login))
356 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
357 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
359 store->GetStrError().c_str());
363 std::vector<STG_MSG_HDR>::const_iterator it;
364 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
367 if (store->GetMessage(it->id, &msg, login) == 0)
369 messages.push_back(msg);
375 //-----------------------------------------------------------------------------
376 int USER_IMPL::ReadStat()
378 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
381 if (store->RestoreUserStat(&stat, login))
383 WriteServLog("Cannot read stat for user %s.", login.c_str());
384 WriteServLog("%s", store->GetStrError().c_str());
385 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
386 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
390 property.SetStat(stat);
394 //-----------------------------------------------------------------------------
395 int USER_IMPL::WriteConf()
397 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
398 USER_CONF conf(property.GetConf());
400 printfd(__FILE__, "USER::WriteConf()\n");
402 if (store->SaveUserConf(conf, login))
404 WriteServLog("Cannot write conf for user %s.", login.c_str());
405 WriteServLog("%s", store->GetStrError().c_str());
406 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
407 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
413 //-----------------------------------------------------------------------------
414 int USER_IMPL::WriteStat()
416 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
417 USER_STAT stat(property.GetStat());
419 if (store->SaveUserStat(stat, login))
421 WriteServLog("Cannot write stat for user %s.", login.c_str());
422 WriteServLog("%s", store->GetStrError().c_str());
423 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
424 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
428 lastWriteStat = stgTime;
432 //-----------------------------------------------------------------------------
433 int USER_IMPL::WriteMonthStat()
435 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
436 time_t tt = stgTime - 3600;
438 localtime_r(&tt, &t1);
440 USER_STAT stat(property.GetStat());
441 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
443 WriteServLog("Cannot write month stat for user %s.", login.c_str());
444 WriteServLog("%s", store->GetStrError().c_str());
445 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
446 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
452 //-----------------------------------------------------------------------------
453 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
455 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
457 * Authorize user. It only means that user will be authorized. Nothing more.
458 * User can be connected or disconnected while authorized.
459 * Example: user is authorized but disconnected due to 0 money or blocking
463 * Prevent double authorization by identical authorizers
465 if (authorizedBy.find(auth) != authorizedBy.end())
471 for (int i = 0; i < DIR_NUM; i++)
473 enabledDirs[i] = dirs & (1 << i);
476 if (!authorizedBy.empty())
480 // We are already authorized, but with different IP address
481 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
486 if (!users->FindByIPIdx(ip, &u))
488 // Address is already present in IP-index
489 // If it's not our IP - throw an error
492 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
499 if (users->IsIPInIndex(ip))
501 // Address is already present in IP-index
502 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
506 if (ips.ConstData().IsIPInIPS(ip))
509 lastIPForDisconnect = currIP;
513 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
514 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
519 if (authorizedBy.empty())
520 authorizedModificationTime = stgTime;
521 authorizedBy.insert(auth);
527 //-----------------------------------------------------------------------------
528 void USER_IMPL::Unauthorize(const AUTH * auth)
530 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
532 * Authorizer tries to unauthorize user, that was not authorized by it
534 if (!authorizedBy.erase(auth))
537 if (authorizedBy.empty())
539 authorizedModificationTime = stgTime;
540 lastIPForDisconnect = currIP;
541 currIP = 0; // DelUser in traffcounter
545 //-----------------------------------------------------------------------------
546 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
548 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
549 // Is this user authorized by specified authorizer?
550 return authorizedBy.find(auth) != authorizedBy.end();
552 //-----------------------------------------------------------------------------
553 std::vector<std::string> USER_IMPL::GetAuthorizers() const
555 std::vector<std::string> list;
556 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
559 //-----------------------------------------------------------------------------
560 void USER_IMPL::Connect(bool fakeConnect)
563 * Connect user to Internet. This function is differ from Authorize() !!!
566 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
570 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
572 if (access(scriptOnConnect.c_str(), X_OK) == 0)
574 char dirsStr[DIR_NUM + 1];
575 dirsStr[DIR_NUM] = 0;
576 for (int i = 0; i < DIR_NUM; i++)
578 dirsStr[i] = enabledDirs[i] ? '1' : '0';
581 std::string scriptOnConnectParams;
582 strprintf(&scriptOnConnectParams,
583 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
584 scriptOnConnect.c_str(),
586 inet_ntostring(currIP).c_str(),
591 ScriptExec(scriptOnConnectParams.c_str());
595 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
601 if (store->WriteUserConnect(login, currIP))
603 WriteServLog("Cannot write connect for user %s.", login.c_str());
604 WriteServLog("%s", store->GetStrError().c_str());
608 lastIPForDisconnect = currIP;
610 //-----------------------------------------------------------------------------
611 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
614 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
617 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
619 if (!lastIPForDisconnect)
621 printfd(__FILE__, "lastIPForDisconnect\n");
627 lastDisconnectReason = reason;
628 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
630 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
632 char dirsStr[DIR_NUM + 1];
633 dirsStr[DIR_NUM] = 0;
634 for (int i = 0; i < DIR_NUM; i++)
636 dirsStr[i] = enabledDirs[i] ? '1' : '0';
639 std::string scriptOnDisonnectParams;
640 strprintf(&scriptOnDisonnectParams,
641 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
642 scriptOnDisonnect.c_str(),
644 inet_ntostring(lastIPForDisconnect).c_str(),
649 ScriptExec(scriptOnDisonnectParams.c_str());
653 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
659 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
661 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
662 WriteServLog("%s", store->GetStrError().c_str());
666 lastIPForDisconnect = 0;
668 DIR_TRAFF zeroSesssion;
670 sessionUpload = zeroSesssion;
671 sessionDownload = zeroSesssion;
673 //-----------------------------------------------------------------------------
674 void USER_IMPL::PrintUser() const
677 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
678 std::cout << "============================================================" << std::endl;
679 std::cout << "id=" << id << std::endl;
680 std::cout << "login=" << login << std::endl;
681 std::cout << "password=" << password << std::endl;
682 std::cout << "passive=" << passive << std::endl;
683 std::cout << "disabled=" << disabled << std::endl;
684 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
685 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
686 std::cout << "tariffName=" << tariffName << std::endl;
687 std::cout << "address=" << address << std::endl;
688 std::cout << "phone=" << phone << std::endl;
689 std::cout << "email=" << email << std::endl;
690 std::cout << "note=" << note << std::endl;
691 std::cout << "realName=" <<realName << std::endl;
692 std::cout << "group=" << group << std::endl;
693 std::cout << "credit=" << credit << std::endl;
694 std::cout << "nextTariff=" << nextTariff << std::endl;
695 std::cout << "userdata0" << userdata0 << std::endl;
696 std::cout << "userdata1" << userdata1 << std::endl;
697 std::cout << "creditExpire=" << creditExpire << std::endl;
698 std::cout << "ips=" << ips << std::endl;
699 std::cout << "------------------------" << std::endl;
700 std::cout << "up=" << up << std::endl;
701 std::cout << "down=" << down << std::endl;
702 std::cout << "cash=" << cash << std::endl;
703 std::cout << "freeMb=" << freeMb << std::endl;
704 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
705 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
706 std::cout << "passiveTime=" << passiveTime << std::endl;
707 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
708 std::cout << "============================================================" << std::endl;
710 //-----------------------------------------------------------------------------
711 void USER_IMPL::Run()
713 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
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())
740 property.Stat().lastActivityTime = stgTime;
742 if (!connected && IsInetable())
746 if (connected && !IsInetable())
749 Disconnect(false, "disabled");
751 Disconnect(false, "passive");
753 Disconnect(false, "no cash");
756 if (stgTime - lastScanMessages > 10)
759 lastScanMessages = stgTime;
766 Disconnect(false, "not authorized");
771 //-----------------------------------------------------------------------------
772 void USER_IMPL::UpdatePingTime(time_t t)
774 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
775 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
781 //-----------------------------------------------------------------------------
782 bool USER_IMPL::IsInetable()
784 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
786 if (disabled || passive)
789 if (settings->GetFreeMbAllowInet())
795 if (settings->GetShowFeeInCash() || tariff == NULL)
797 return (cash >= -credit);
800 return (cash - tariff->GetFee() >= -credit);
802 //-----------------------------------------------------------------------------
803 std::string USER_IMPL::GetEnabledDirs()
805 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
807 std::string dirs = "";
808 for(int i = 0; i < DIR_NUM; i++)
809 dirs += enabledDirs[i] ? "1" : "0";
812 //-----------------------------------------------------------------------------
813 #ifdef TRAFF_STAT_WITH_PORTS
814 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
816 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
819 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
821 if (!connected || tariff == NULL)
827 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
828 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
832 int tt = tariff->GetTraffType();
833 if (tt == TRAFF_UP ||
834 tt == TRAFF_UP_DOWN ||
835 // Check NEW traff data
836 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
839 if (traff < threshold &&
840 traff + len >= threshold)
842 // cash = partBeforeThreshold * priceBeforeThreshold +
843 // partAfterThreshold * priceAfterThreshold
844 int64_t before = threshold - traff; // Chunk part before threshold
845 int64_t after = len - before; // Chunk part after threshold
846 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
847 down.ConstData()[dir],
850 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
851 down.ConstData()[dir],
857 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
858 down.ConstData()[dir],
863 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
865 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
866 cost = dc - freeMb.ConstData();
868 // Direct access to internal data structures via friend-specifier
869 property.Stat().freeMb -= dc;
870 property.Stat().cash -= cost;
876 sessionUpload[dir] += len;
880 if (!settings->GetWriteFreeMbTraffCost() &&
881 freeMb.ConstData() >= 0)
884 #ifdef TRAFF_STAT_WITH_PORTS
885 IP_DIR_PAIR idp(ip, dir, port);
887 IP_DIR_PAIR idp(ip, dir);
890 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
891 lb = traffStat.lower_bound(idp);
892 if (lb == traffStat.end() || lb->first != idp)
896 STAT_NODE(len, 0, cost)));
900 lb->second.cash += cost;
901 lb->second.up += len;
904 //-----------------------------------------------------------------------------
905 #ifdef TRAFF_STAT_WITH_PORTS
906 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
908 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
911 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
913 if (!connected || tariff == NULL)
919 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
920 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
924 int tt = tariff->GetTraffType();
925 if (tt == TRAFF_DOWN ||
926 tt == TRAFF_UP_DOWN ||
927 // Check NEW traff data
928 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
931 if (traff < threshold &&
932 traff + len >= threshold)
934 // cash = partBeforeThreshold * priceBeforeThreshold +
935 // partAfterThreshold * priceAfterThreshold
936 int64_t before = threshold - traff; // Chunk part before threshold
937 int64_t after = len - before; // Chunk part after threshold
938 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
939 down.ConstData()[dir], // Traff before chunk
942 tariff->GetPriceWithTraffType(up.ConstData()[dir],
943 dt[dir], // Traff after chunk
949 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
950 down.ConstData()[dir],
955 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
957 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
958 cost = dc - freeMb.ConstData();
960 property.Stat().freeMb -= dc;
961 property.Stat().cash -= cost;
967 sessionDownload[dir] += len;
971 if (!settings->GetWriteFreeMbTraffCost() &&
972 freeMb.ConstData() >= 0)
975 #ifdef TRAFF_STAT_WITH_PORTS
976 IP_DIR_PAIR idp(ip, dir, port);
978 IP_DIR_PAIR idp(ip, dir);
981 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
982 lb = traffStat.lower_bound(idp);
983 if (lb == traffStat.end() || lb->first != idp)
987 STAT_NODE(0, len, cost)));
991 lb->second.cash += cost;
992 lb->second.down += len;
995 //-----------------------------------------------------------------------------
996 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
998 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
999 currIP.AddBeforeNotifier(notifier);
1001 //-----------------------------------------------------------------------------
1002 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1004 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1005 currIP.DelBeforeNotifier(notifier);
1007 //-----------------------------------------------------------------------------
1008 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1010 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1011 currIP.AddAfterNotifier(notifier);
1013 //-----------------------------------------------------------------------------
1014 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1016 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1017 currIP.DelAfterNotifier(notifier);
1019 //-----------------------------------------------------------------------------
1020 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1022 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1023 connected.AddBeforeNotifier(notifier);
1025 //-----------------------------------------------------------------------------
1026 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1028 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1029 connected.DelBeforeNotifier(notifier);
1031 //-----------------------------------------------------------------------------
1032 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1034 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1035 connected.AddAfterNotifier(notifier);
1037 //-----------------------------------------------------------------------------
1038 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1040 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1041 connected.DelAfterNotifier(notifier);
1043 //-----------------------------------------------------------------------------
1044 void USER_IMPL::OnAdd()
1046 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1048 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1050 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1052 std::string scriptOnAddParams;
1053 strprintf(&scriptOnAddParams,
1055 scriptOnAdd.c_str(),
1058 ScriptExec(scriptOnAddParams.c_str());
1062 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1065 //-----------------------------------------------------------------------------
1066 void USER_IMPL::OnDelete()
1068 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1070 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1072 if (access(scriptOnDel.c_str(), X_OK) == 0)
1074 std::string scriptOnDelParams;
1075 strprintf(&scriptOnDelParams,
1077 scriptOnDel.c_str(),
1080 ScriptExec(scriptOnDelParams.c_str());
1084 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1089 //-----------------------------------------------------------------------------
1090 int USER_IMPL::WriteDetailStat(bool hard)
1092 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1094 if (!traffStatSaved.second.empty())
1096 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1098 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1099 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1100 WriteServLog("%s", store->GetStrError().c_str());
1103 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1109 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1113 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1115 if (ts.size() && !disabledDetailStat)
1117 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1119 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1120 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1121 WriteServLog("%s", store->GetStrError().c_str());
1124 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1125 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1126 traffStatSaved.second.swap(ts);
1127 traffStatSaved.first = lastWriteDetailedStat;
1132 lastWriteDetailedStat = stgTime;
1135 //-----------------------------------------------------------------------------
1136 double USER_IMPL::GetPassiveTimePart() const
1138 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1140 static int daysInMonth[12] =
1141 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1145 localtime_r(&t, &tms);
1147 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1149 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1152 secMonth += 24 * 3600;
1155 time_t dt = secMonth - passiveTime;
1160 return static_cast<double>(dt) / secMonth;
1162 //-----------------------------------------------------------------------------
1163 void USER_IMPL::SetPassiveTimeAsNewUser()
1165 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1169 localtime_r(&t, &tm);
1170 int daysCurrMon = DaysInCurrentMonth();
1171 double pt = tm.tm_mday - 1;
1174 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1176 //-----------------------------------------------------------------------------
1177 void USER_IMPL::MidnightResetSessionStat()
1179 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1183 Disconnect(true, "fake");
1187 //-----------------------------------------------------------------------------
1188 void USER_IMPL::ProcessNewMonth()
1190 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1194 Disconnect(true, "fake");
1196 DIR_TRAFF zeroTarff;
1209 if (nextTariff.ConstData() != "")
1212 nt = tariffs->FindByName(nextTariff);
1215 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1216 login.c_str(), property.tariffName.Get().c_str());
1220 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1227 //-----------------------------------------------------------------------------
1228 void USER_IMPL::ProcessDayFeeSpread()
1230 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1232 if (passive.ConstData() || tariff == NULL)
1235 double fee = tariff->GetFee() / DaysInCurrentMonth();
1237 if (std::fabs(fee) < 1.0e-3)
1241 switch (settings->GetFeeChargeType())
1244 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1247 if (c + credit >= 0)
1248 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1251 if (c + credit >= fee)
1252 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1256 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1261 //-----------------------------------------------------------------------------
1262 void USER_IMPL::ProcessDayFee()
1264 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1269 double passiveTimePart = 1.0;
1270 if (!settings->GetFullFee())
1272 passiveTimePart = GetPassiveTimePart();
1276 if (passive.ConstData())
1278 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1282 double fee = tariff->GetFee() * passiveTimePart;
1286 if (std::fabs(fee) < 1.0e-3)
1293 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1300 switch (settings->GetFeeChargeType())
1303 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1307 if (c + credit >= 0)
1309 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1314 if (c + credit >= fee)
1316 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1323 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1329 //-----------------------------------------------------------------------------
1330 void USER_IMPL::SetPrepaidTraff()
1333 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1335 //-----------------------------------------------------------------------------
1336 int USER_IMPL::AddMessage(STG_MSG * msg)
1338 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1340 if (SendMessage(*msg))
1342 if (store->AddMessage(msg, login))
1344 errorStr = store->GetStrError();
1345 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1346 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1349 messages.push_back(*msg);
1353 if (msg->header.repeat > 0)
1355 msg->header.repeat--;
1357 //TODO: gcc v. 4.x generate ICE on x86_64
1358 msg->header.lastSendTime = static_cast<int>(time(NULL));
1360 msg->header.lastSendTime = static_cast<int>(stgTime);
1362 if (store->AddMessage(msg, login))
1364 errorStr = store->GetStrError();
1365 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1366 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1369 messages.push_back(*msg);
1374 //-----------------------------------------------------------------------------
1375 int USER_IMPL::SendMessage(STG_MSG & msg) const
1377 // No lock `cause we are already locked from caller
1379 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1380 while (it != authorizedBy.end())
1382 if (!(*it++)->SendMessage(msg, currIP))
1388 //TODO: gcc v. 4.x generate ICE on x86_64
1389 msg.header.lastSendTime = static_cast<int>(time(NULL));
1391 msg.header.lastSendTime = static_cast<int>(stgTime);
1393 msg.header.repeat--;
1397 //-----------------------------------------------------------------------------
1398 void USER_IMPL::ScanMessage()
1400 // No lock `cause we are already locked from caller
1401 // We need not check for the authorizedBy `cause it has already checked by caller
1403 std::list<STG_MSG>::iterator it(messages.begin());
1404 while (it != messages.end())
1406 if (settings->GetMessageTimeout() > 0 &&
1407 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1410 if (store->DelMessage(it->header.id, login))
1412 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1413 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1415 messages.erase(it++);
1418 if (it->GetNextSendTime() <= stgTime)
1420 if (SendMessage(*it))
1422 // We need to check all messages in queue for timeout
1426 if (it->header.repeat < 0)
1428 if (store->DelMessage(it->header.id, login))
1430 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1431 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1433 messages.erase(it++);
1437 if (store->EditMessage(*it, login))
1439 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1440 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1451 //-----------------------------------------------------------------------------
1452 //-----------------------------------------------------------------------------
1453 //-----------------------------------------------------------------------------
1454 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1456 if (newPassive && !oldPassive && user->tariff != NULL)
1457 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1463 //-----------------------------------------------------------------------------
1464 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1466 if (oldValue && !newValue && user->GetConnected())
1468 user->Disconnect(false, "disabled");
1470 else if (!oldValue && newValue && user->IsInetable())
1472 user->Connect(false);
1476 //-----------------------------------------------------------------------------
1477 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1479 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1480 user->Disconnect(false, "Change tariff");
1481 user->tariff = user->tariffs->FindByName(newTariff);
1482 if (user->settings->GetReconnectOnTariffChange() &&
1483 !user->authorizedBy.empty() &&
1485 user->Connect(false);
1487 //-----------------------------------------------------------------------------
1488 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1490 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1491 user->lastCashAdd = newCash - oldCash;
1493 //-----------------------------------------------------------------------------
1494 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1496 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1497 if (user->connected)
1498 user->Disconnect(false, "Change IP");
1499 if (!user->authorizedBy.empty() && user->IsInetable())
1500 user->Connect(false);
1502 //-----------------------------------------------------------------------------