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 disabledNotifier(this),
119 tariffNotifier(this),
123 password = "*_EMPTY_PASSWORD_*";
124 tariffName = NO_TARIFF_NAME;
126 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
127 lastWriteDetailedStat = stgTime;
129 property.tariffName.AddBeforeNotifier(&tariffNotifier);
130 property.passive.AddBeforeNotifier(&passiveNotifier);
131 property.disabled.AddAfterNotifier(&disabledNotifier);
132 property.cash.AddBeforeNotifier(&cashNotifier);
133 ips.AddAfterNotifier(&ipNotifier);
135 pthread_mutexattr_t attr;
136 pthread_mutexattr_init(&attr);
137 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
138 pthread_mutex_init(&mutex, &attr);
141 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
148 property(s->GetScriptsDir()),
149 WriteServLog(GetStgLogger()),
153 connected(__connected),
156 lastIPForDisconnect(0),
163 authorizedModificationTime(0),
166 lastWriteDetailedStat(0),
170 lastCashAdd(property.lastCashAdd),
171 passiveTime(property.passiveTime),
172 lastCashAddTime(property.lastCashAddTime),
173 freeMb(property.freeMb),
174 lastActivityTime(property.lastActivityTime),
175 password(property.password),
176 passive(property.passive),
177 disabled(property.disabled),
178 disabledDetailStat(property.disabledDetailStat),
179 alwaysOnline(property.alwaysOnline),
180 tariffName(property.tariffName),
181 nextTariff(property.nextTariff),
182 address(property.address),
184 group(property.group),
185 email(property.email),
186 phone(property.phone),
187 realName(property.realName),
188 credit(property.credit),
189 creditExpire(property.creditExpire),
191 userdata0(property.userdata0),
192 userdata1(property.userdata1),
193 userdata2(property.userdata2),
194 userdata3(property.userdata3),
195 userdata4(property.userdata4),
196 userdata5(property.userdata5),
197 userdata6(property.userdata6),
198 userdata7(property.userdata7),
199 userdata8(property.userdata8),
200 userdata9(property.userdata9),
201 passiveNotifier(this),
202 disabledNotifier(this),
203 tariffNotifier(this),
207 password = "*_EMPTY_PASSWORD_*";
208 tariffName = NO_TARIFF_NAME;
210 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
211 lastWriteDetailedStat = stgTime;
213 property.tariffName.AddBeforeNotifier(&tariffNotifier);
214 property.passive.AddBeforeNotifier(&passiveNotifier);
215 property.disabled.AddAfterNotifier(&disabledNotifier);
216 property.cash.AddBeforeNotifier(&cashNotifier);
217 ips.AddAfterNotifier(&ipNotifier);
219 pthread_mutexattr_t attr;
220 pthread_mutexattr_init(&attr);
221 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
222 pthread_mutex_init(&mutex, &attr);
225 //-----------------------------------------------------------------------------
226 USER_IMPL::USER_IMPL(const USER_IMPL & u)
229 property(u.settings->GetScriptsDir()),
230 WriteServLog(GetStgLogger()),
235 connected(__connected),
236 userIDGenerator(u.userIDGenerator),
237 __currIP(u.__currIP),
239 lastIPForDisconnect(0),
240 pingTime(u.pingTime),
241 sysAdmin(u.sysAdmin),
245 traffStat(u.traffStat),
246 traffStatSaved(u.traffStatSaved),
247 settings(u.settings),
248 authorizedModificationTime(u.authorizedModificationTime),
249 messages(u.messages),
251 lastWriteStat(u.lastWriteStat),
252 lastWriteDetailedStat(u.lastWriteDetailedStat),
256 lastCashAdd(property.lastCashAdd),
257 passiveTime(property.passiveTime),
258 lastCashAddTime(property.lastCashAddTime),
259 freeMb(property.freeMb),
260 lastActivityTime(property.lastActivityTime),
261 password(property.password),
262 passive(property.passive),
263 disabled(property.disabled),
264 disabledDetailStat(property.disabledDetailStat),
265 alwaysOnline(property.alwaysOnline),
266 tariffName(property.tariffName),
267 nextTariff(property.nextTariff),
268 address(property.address),
270 group(property.group),
271 email(property.email),
272 phone(property.phone),
273 realName(property.realName),
274 credit(property.credit),
275 creditExpire(property.creditExpire),
277 userdata0(property.userdata0),
278 userdata1(property.userdata1),
279 userdata2(property.userdata2),
280 userdata3(property.userdata3),
281 userdata4(property.userdata4),
282 userdata5(property.userdata5),
283 userdata6(property.userdata6),
284 userdata7(property.userdata7),
285 userdata8(property.userdata8),
286 userdata9(property.userdata9),
289 passiveNotifier(this),
290 disabledNotifier(this),
291 tariffNotifier(this),
298 property.tariffName.AddBeforeNotifier(&tariffNotifier);
299 property.passive.AddBeforeNotifier(&passiveNotifier);
300 property.disabled.AddAfterNotifier(&disabledNotifier);
301 property.cash.AddBeforeNotifier(&cashNotifier);
302 ips.AddAfterNotifier(&ipNotifier);
304 property.SetProperties(u.property);
306 pthread_mutexattr_t attr;
307 pthread_mutexattr_init(&attr);
308 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
309 pthread_mutex_init(&mutex, &attr);
311 //-----------------------------------------------------------------------------
312 USER_IMPL::~USER_IMPL()
314 property.tariffName.DelBeforeNotifier(&tariffNotifier);
315 property.passive.DelBeforeNotifier(&passiveNotifier);
316 property.disabled.DelAfterNotifier(&disabledNotifier);
317 property.cash.DelBeforeNotifier(&cashNotifier);
318 pthread_mutex_destroy(&mutex);
320 //-----------------------------------------------------------------------------
321 void USER_IMPL::SetLogin(const std::string & l)
323 STG_LOCKER lock(&mutex);
324 assert(login.empty() && "Login is already set");
326 id = userIDGenerator.GetNextID();
328 //-----------------------------------------------------------------------------
329 int USER_IMPL::ReadConf()
331 STG_LOCKER lock(&mutex);
334 if (store->RestoreUserConf(&conf, login))
336 WriteServLog("Cannot read conf for user %s.", login.c_str());
337 WriteServLog("%s", store->GetStrError().c_str());
338 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
339 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
343 property.SetConf(conf);
345 tariff = tariffs->FindByName(tariffName);
348 WriteServLog("Cannot read user %s. Tariff %s not exist.",
349 login.c_str(), property.tariffName.Get().c_str());
353 std::vector<STG_MSG_HDR> hdrsList;
355 if (store->GetMessageHdrs(&hdrsList, login))
357 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
358 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
360 store->GetStrError().c_str());
364 std::vector<STG_MSG_HDR>::const_iterator it;
365 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
368 if (store->GetMessage(it->id, &msg, login) == 0)
370 messages.push_back(msg);
376 //-----------------------------------------------------------------------------
377 int USER_IMPL::ReadStat()
379 STG_LOCKER lock(&mutex);
382 if (store->RestoreUserStat(&stat, login))
384 WriteServLog("Cannot read stat for user %s.", login.c_str());
385 WriteServLog("%s", store->GetStrError().c_str());
386 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
387 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
391 property.SetStat(stat);
395 //-----------------------------------------------------------------------------
396 int USER_IMPL::WriteConf()
398 STG_LOCKER lock(&mutex);
399 USER_CONF conf(property.GetConf());
401 printfd(__FILE__, "USER::WriteConf()\n");
403 if (store->SaveUserConf(conf, login))
405 WriteServLog("Cannot write conf for user %s.", login.c_str());
406 WriteServLog("%s", store->GetStrError().c_str());
407 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
408 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
414 //-----------------------------------------------------------------------------
415 int USER_IMPL::WriteStat()
417 STG_LOCKER lock(&mutex);
418 USER_STAT stat(property.GetStat());
420 if (store->SaveUserStat(stat, login))
422 WriteServLog("Cannot write stat for user %s.", login.c_str());
423 WriteServLog("%s", store->GetStrError().c_str());
424 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
425 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
429 lastWriteStat = stgTime;
433 //-----------------------------------------------------------------------------
434 int USER_IMPL::WriteMonthStat()
436 STG_LOCKER lock(&mutex);
437 time_t tt = stgTime - 3600;
439 localtime_r(&tt, &t1);
441 USER_STAT stat(property.GetStat());
442 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
444 WriteServLog("Cannot write month stat for user %s.", login.c_str());
445 WriteServLog("%s", store->GetStrError().c_str());
446 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
447 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
453 //-----------------------------------------------------------------------------
454 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
456 STG_LOCKER lock(&mutex);
458 * Authorize user. It only means that user will be authorized. Nothing more.
459 * User can be connected or disconnected while authorized.
460 * Example: user is authorized but disconnected due to 0 money or blocking
464 * Prevent double authorization by identical authorizers
466 if (authorizedBy.find(auth) != authorizedBy.end())
472 for (int i = 0; i < DIR_NUM; i++)
474 enabledDirs[i] = dirs & (1 << i);
477 if (!authorizedBy.empty())
481 // We are already authorized, but with different IP address
482 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
487 if (!users->FindByIPIdx(ip, &u))
489 // Address is already present in IP-index
490 // If it's not our IP - throw an error
493 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
500 if (users->IsIPInIndex(ip))
502 // Address is already present in IP-index
503 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
507 if (ips.ConstData().IsIPInIPS(ip))
510 lastIPForDisconnect = currIP;
514 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
515 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
520 if (authorizedBy.empty())
521 authorizedModificationTime = stgTime;
522 authorizedBy.insert(auth);
528 //-----------------------------------------------------------------------------
529 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
531 STG_LOCKER lock(&mutex);
533 * Authorizer tries to unauthorize user, that was not authorized by it
535 if (!authorizedBy.erase(auth))
538 if (authorizedBy.empty())
540 authorizedModificationTime = stgTime;
541 lastDisconnectReason = reason;
542 lastIPForDisconnect = currIP;
543 currIP = 0; // DelUser in traffcounter
547 //-----------------------------------------------------------------------------
548 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
550 STG_LOCKER lock(&mutex);
551 // Is this user authorized by specified authorizer?
552 return authorizedBy.find(auth) != authorizedBy.end();
554 //-----------------------------------------------------------------------------
555 std::vector<std::string> USER_IMPL::GetAuthorizers() const
557 std::vector<std::string> list;
558 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
561 //-----------------------------------------------------------------------------
562 void USER_IMPL::Connect(bool fakeConnect)
565 * Connect user to Internet. This function is differ from Authorize() !!!
568 STG_LOCKER lock(&mutex);
572 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
574 if (access(scriptOnConnect.c_str(), X_OK) == 0)
576 char dirsStr[DIR_NUM + 1];
577 dirsStr[DIR_NUM] = 0;
578 for (int i = 0; i < DIR_NUM; i++)
580 dirsStr[i] = enabledDirs[i] ? '1' : '0';
583 std::string scriptOnConnectParams;
585 strprintf(&scriptOnConnectParams,
586 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
587 scriptOnConnect.c_str(),
589 inet_ntostring(currIP).c_str(),
594 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
595 while (it != settings->GetScriptParams().end())
597 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
601 ScriptExec(scriptOnConnectParams.c_str());
605 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
611 if (store->WriteUserConnect(login, currIP))
613 WriteServLog("Cannot write connect for user %s.", login.c_str());
614 WriteServLog("%s", store->GetStrError().c_str());
618 lastIPForDisconnect = currIP;
620 //-----------------------------------------------------------------------------
621 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
624 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
627 STG_LOCKER lock(&mutex);
629 if (!lastIPForDisconnect)
631 printfd(__FILE__, "lastIPForDisconnect\n");
637 lastDisconnectReason = reason;
638 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
640 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
642 char dirsStr[DIR_NUM + 1];
643 dirsStr[DIR_NUM] = 0;
644 for (int i = 0; i < DIR_NUM; i++)
646 dirsStr[i] = enabledDirs[i] ? '1' : '0';
649 std::string scriptOnDisonnectParams;
650 strprintf(&scriptOnDisonnectParams,
651 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
652 scriptOnDisonnect.c_str(),
654 inet_ntostring(lastIPForDisconnect).c_str(),
659 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
660 while (it != settings->GetScriptParams().end())
662 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
666 ScriptExec(scriptOnDisonnectParams.c_str());
670 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
676 std::string reasonMessage(reason);
677 if (!lastDisconnectReason.empty())
678 reasonMessage += ": " + lastDisconnectReason;
680 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
681 cash, freeMb, reasonMessage))
683 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
684 WriteServLog("%s", store->GetStrError().c_str());
688 lastIPForDisconnect = 0;
690 DIR_TRAFF zeroSesssion;
692 sessionUpload = zeroSesssion;
693 sessionDownload = zeroSesssion;
694 sessionUploadModTime = stgTime;
695 sessionDownloadModTime = stgTime;
697 //-----------------------------------------------------------------------------
698 void USER_IMPL::PrintUser() const
701 STG_LOCKER lock(&mutex);
702 std::cout << "============================================================" << std::endl;
703 std::cout << "id=" << id << std::endl;
704 std::cout << "login=" << login << std::endl;
705 std::cout << "password=" << password << std::endl;
706 std::cout << "passive=" << passive << std::endl;
707 std::cout << "disabled=" << disabled << std::endl;
708 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
709 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
710 std::cout << "tariffName=" << tariffName << std::endl;
711 std::cout << "address=" << address << std::endl;
712 std::cout << "phone=" << phone << std::endl;
713 std::cout << "email=" << email << std::endl;
714 std::cout << "note=" << note << std::endl;
715 std::cout << "realName=" <<realName << std::endl;
716 std::cout << "group=" << group << std::endl;
717 std::cout << "credit=" << credit << std::endl;
718 std::cout << "nextTariff=" << nextTariff << std::endl;
719 std::cout << "userdata0" << userdata0 << std::endl;
720 std::cout << "userdata1" << userdata1 << std::endl;
721 std::cout << "creditExpire=" << creditExpire << std::endl;
722 std::cout << "ips=" << ips << std::endl;
723 std::cout << "------------------------" << std::endl;
724 std::cout << "up=" << up << std::endl;
725 std::cout << "down=" << down << std::endl;
726 std::cout << "cash=" << cash << std::endl;
727 std::cout << "freeMb=" << freeMb << std::endl;
728 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
729 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
730 std::cout << "passiveTime=" << passiveTime << std::endl;
731 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
732 std::cout << "============================================================" << std::endl;
734 //-----------------------------------------------------------------------------
735 void USER_IMPL::Run()
737 STG_LOCKER lock(&mutex);
739 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
741 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
744 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
746 WriteServLog("User: %s. Credit expired.", login.c_str());
752 if (passive.ConstData()
753 && (stgTime % 30 == 0)
754 && (passiveTime.ModificationTime() != stgTime))
756 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
757 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
760 if (!authorizedBy.empty())
764 property.Stat().lastActivityTime = stgTime;
766 if (!connected && IsInetable())
770 if (connected && !IsInetable())
773 Disconnect(false, "disabled");
775 Disconnect(false, "passive");
777 Disconnect(false, "no cash");
780 if (stgTime - lastScanMessages > 10)
783 lastScanMessages = stgTime;
790 Disconnect(false, "not authorized");
795 //-----------------------------------------------------------------------------
796 void USER_IMPL::UpdatePingTime(time_t t)
798 STG_LOCKER lock(&mutex);
799 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
805 //-----------------------------------------------------------------------------
806 bool USER_IMPL::IsInetable()
808 //STG_LOCKER lock(&mutex);
810 if (disabled || passive)
813 if (settings->GetFreeMbAllowInet())
819 if (settings->GetShowFeeInCash() || tariff == NULL)
821 return (cash >= -credit);
824 return (cash - tariff->GetFee() >= -credit);
826 //-----------------------------------------------------------------------------
827 std::string USER_IMPL::GetEnabledDirs() const
829 //STG_LOCKER lock(&mutex);
831 std::string dirs = "";
832 for(int i = 0; i < DIR_NUM; i++)
833 dirs += enabledDirs[i] ? "1" : "0";
836 //-----------------------------------------------------------------------------
837 #ifdef TRAFF_STAT_WITH_PORTS
838 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
840 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
843 STG_LOCKER lock(&mutex);
845 if (!connected || tariff == NULL)
851 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
852 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
856 int tt = tariff->GetTraffType();
857 if (tt == TARIFF::TRAFF_UP ||
858 tt == TARIFF::TRAFF_UP_DOWN ||
859 // Check NEW traff data
860 (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
863 if (traff < threshold &&
864 traff + len >= threshold)
866 // cash = partBeforeThreshold * priceBeforeThreshold +
867 // partAfterThreshold * priceAfterThreshold
868 int64_t before = threshold - traff; // Chunk part before threshold
869 int64_t after = len - before; // Chunk part after threshold
870 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
871 down.ConstData()[dir],
874 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
875 down.ConstData()[dir],
881 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
882 down.ConstData()[dir],
887 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
889 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
890 cost = dc - freeMb.ConstData();
892 // Direct access to internal data structures via friend-specifier
893 property.Stat().freeMb -= dc;
894 property.Stat().cash -= cost;
900 sessionUpload[dir] += len;
901 sessionUploadModTime = stgTime;
905 if (!settings->GetWriteFreeMbTraffCost() &&
906 freeMb.ConstData() >= 0)
909 #ifdef TRAFF_STAT_WITH_PORTS
910 IP_DIR_PAIR idp(ip, dir, port);
912 IP_DIR_PAIR idp(ip, dir);
915 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
916 lb = traffStat.lower_bound(idp);
917 if (lb == traffStat.end() || lb->first != idp)
921 STAT_NODE(len, 0, cost)));
925 lb->second.cash += cost;
926 lb->second.up += len;
929 //-----------------------------------------------------------------------------
930 #ifdef TRAFF_STAT_WITH_PORTS
931 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
933 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
936 STG_LOCKER lock(&mutex);
938 if (!connected || tariff == NULL)
944 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
945 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
949 int tt = tariff->GetTraffType();
950 if (tt == TARIFF::TRAFF_DOWN ||
951 tt == TARIFF::TRAFF_UP_DOWN ||
952 // Check NEW traff data
953 (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
956 if (traff < threshold &&
957 traff + len >= threshold)
959 // cash = partBeforeThreshold * priceBeforeThreshold +
960 // partAfterThreshold * priceAfterThreshold
961 int64_t before = threshold - traff; // Chunk part before threshold
962 int64_t after = len - before; // Chunk part after threshold
963 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
964 down.ConstData()[dir], // Traff before chunk
967 tariff->GetPriceWithTraffType(up.ConstData()[dir],
968 dt[dir], // Traff after chunk
974 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
975 down.ConstData()[dir],
980 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
982 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
983 cost = dc - freeMb.ConstData();
985 property.Stat().freeMb -= dc;
986 property.Stat().cash -= cost;
992 sessionDownload[dir] += len;
993 sessionDownloadModTime = stgTime;
997 if (!settings->GetWriteFreeMbTraffCost() &&
998 freeMb.ConstData() >= 0)
1001 #ifdef TRAFF_STAT_WITH_PORTS
1002 IP_DIR_PAIR idp(ip, dir, port);
1004 IP_DIR_PAIR idp(ip, dir);
1007 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
1008 lb = traffStat.lower_bound(idp);
1009 if (lb == traffStat.end() || lb->first != idp)
1011 traffStat.insert(lb,
1013 STAT_NODE(0, len, cost)));
1017 lb->second.cash += cost;
1018 lb->second.down += len;
1021 //-----------------------------------------------------------------------------
1022 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1024 STG_LOCKER lock(&mutex);
1025 currIP.AddBeforeNotifier(notifier);
1027 //-----------------------------------------------------------------------------
1028 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1030 STG_LOCKER lock(&mutex);
1031 currIP.DelBeforeNotifier(notifier);
1033 //-----------------------------------------------------------------------------
1034 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1036 STG_LOCKER lock(&mutex);
1037 currIP.AddAfterNotifier(notifier);
1039 //-----------------------------------------------------------------------------
1040 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1042 STG_LOCKER lock(&mutex);
1043 currIP.DelAfterNotifier(notifier);
1045 //-----------------------------------------------------------------------------
1046 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1048 STG_LOCKER lock(&mutex);
1049 connected.AddBeforeNotifier(notifier);
1051 //-----------------------------------------------------------------------------
1052 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1054 STG_LOCKER lock(&mutex);
1055 connected.DelBeforeNotifier(notifier);
1057 //-----------------------------------------------------------------------------
1058 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1060 STG_LOCKER lock(&mutex);
1061 connected.AddAfterNotifier(notifier);
1063 //-----------------------------------------------------------------------------
1064 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1066 STG_LOCKER lock(&mutex);
1067 connected.DelAfterNotifier(notifier);
1069 //-----------------------------------------------------------------------------
1070 void USER_IMPL::OnAdd()
1072 STG_LOCKER lock(&mutex);
1074 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1076 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1078 std::string scriptOnAddParams;
1079 strprintf(&scriptOnAddParams,
1081 scriptOnAdd.c_str(),
1084 ScriptExec(scriptOnAddParams.c_str());
1088 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1091 //-----------------------------------------------------------------------------
1092 void USER_IMPL::OnDelete()
1094 STG_LOCKER lock(&mutex);
1096 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1098 if (access(scriptOnDel.c_str(), X_OK) == 0)
1100 std::string scriptOnDelParams;
1101 strprintf(&scriptOnDelParams,
1103 scriptOnDel.c_str(),
1106 ScriptExec(scriptOnDelParams.c_str());
1110 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1115 //-----------------------------------------------------------------------------
1116 int USER_IMPL::WriteDetailStat(bool hard)
1118 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1120 if (!traffStatSaved.second.empty())
1122 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1124 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1125 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1126 WriteServLog("%s", store->GetStrError().c_str());
1129 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1135 STG_LOCKER lock(&mutex);
1139 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1141 if (ts.size() && !disabledDetailStat)
1143 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1145 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1146 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1147 WriteServLog("%s", store->GetStrError().c_str());
1150 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1151 STG_LOCKER lock(&mutex);
1152 traffStatSaved.second.swap(ts);
1153 traffStatSaved.first = lastWriteDetailedStat;
1158 lastWriteDetailedStat = stgTime;
1161 //-----------------------------------------------------------------------------
1162 double USER_IMPL::GetPassiveTimePart() const
1164 STG_LOCKER lock(&mutex);
1166 static int daysInMonth[12] =
1167 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1171 localtime_r(&t, &tms);
1173 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1175 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1178 secMonth += 24 * 3600;
1181 time_t dt = secMonth - passiveTime;
1186 return static_cast<double>(dt) / secMonth;
1188 //-----------------------------------------------------------------------------
1189 void USER_IMPL::SetPassiveTimeAsNewUser()
1191 STG_LOCKER lock(&mutex);
1195 localtime_r(&t, &tm);
1196 int daysCurrMon = DaysInCurrentMonth();
1197 double pt = tm.tm_mday - 1;
1200 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1202 //-----------------------------------------------------------------------------
1203 void USER_IMPL::MidnightResetSessionStat()
1205 STG_LOCKER lock(&mutex);
1209 Disconnect(true, "fake");
1213 //-----------------------------------------------------------------------------
1214 void USER_IMPL::ProcessNewMonth()
1216 STG_LOCKER lock(&mutex);
1220 Disconnect(true, "fake");
1222 DIR_TRAFF zeroTarff;
1235 if (nextTariff.ConstData() != "")
1238 nt = tariffs->FindByName(nextTariff);
1241 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1242 login.c_str(), property.tariffName.Get().c_str());
1246 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1253 //-----------------------------------------------------------------------------
1254 void USER_IMPL::ProcessDayFeeSpread()
1256 STG_LOCKER lock(&mutex);
1258 if (passive.ConstData() || tariff == NULL)
1261 if (tariff->GetPeriod() != TARIFF::MONTH)
1264 double fee = tariff->GetFee() / DaysInCurrentMonth();
1266 if (std::fabs(fee) < 1.0e-3)
1270 switch (settings->GetFeeChargeType())
1273 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1276 if (c + credit >= 0)
1277 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1280 if (c + credit >= fee)
1281 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1285 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1290 //-----------------------------------------------------------------------------
1291 void USER_IMPL::ProcessDayFee()
1293 STG_LOCKER lock(&mutex);
1298 if (tariff->GetPeriod() != TARIFF::MONTH)
1301 double passiveTimePart = 1.0;
1302 if (!settings->GetFullFee())
1304 passiveTimePart = GetPassiveTimePart();
1308 if (passive.ConstData())
1310 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1314 double fee = tariff->GetFee() * passiveTimePart;
1318 if (std::fabs(fee) < 1.0e-3)
1325 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1332 switch (settings->GetFeeChargeType())
1335 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1339 if (c + credit >= 0)
1341 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1346 if (c + credit >= fee)
1348 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1355 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1361 //-----------------------------------------------------------------------------
1362 void USER_IMPL::ProcessDailyFee()
1364 STG_LOCKER lock(&mutex);
1366 if (passive.ConstData() || tariff == NULL)
1369 if (tariff->GetPeriod() != TARIFF::DAY)
1372 double fee = tariff->GetFee();
1378 switch (settings->GetFeeChargeType())
1381 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1384 if (c + credit >= 0)
1385 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1388 if (c + credit >= fee)
1389 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1394 //-----------------------------------------------------------------------------
1395 void USER_IMPL::SetPrepaidTraff()
1398 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1400 //-----------------------------------------------------------------------------
1401 int USER_IMPL::AddMessage(STG_MSG * msg)
1403 STG_LOCKER lock(&mutex);
1405 if (SendMessage(*msg))
1407 if (store->AddMessage(msg, login))
1409 errorStr = store->GetStrError();
1410 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1411 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1414 messages.push_back(*msg);
1418 if (msg->header.repeat > 0)
1420 msg->header.repeat--;
1422 //TODO: gcc v. 4.x generate ICE on x86_64
1423 msg->header.lastSendTime = static_cast<int>(time(NULL));
1425 msg->header.lastSendTime = static_cast<int>(stgTime);
1427 if (store->AddMessage(msg, login))
1429 errorStr = store->GetStrError();
1430 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1431 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1434 messages.push_back(*msg);
1439 //-----------------------------------------------------------------------------
1440 int USER_IMPL::SendMessage(STG_MSG & msg) const
1442 // No lock `cause we are already locked from caller
1444 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1445 while (it != authorizedBy.end())
1447 if (!(*it++)->SendMessage(msg, currIP))
1453 //TODO: gcc v. 4.x generate ICE on x86_64
1454 msg.header.lastSendTime = static_cast<int>(time(NULL));
1456 msg.header.lastSendTime = static_cast<int>(stgTime);
1458 msg.header.repeat--;
1462 //-----------------------------------------------------------------------------
1463 void USER_IMPL::ScanMessage()
1465 // No lock `cause we are already locked from caller
1466 // We need not check for the authorizedBy `cause it has already checked by caller
1468 std::list<STG_MSG>::iterator it(messages.begin());
1469 while (it != messages.end())
1471 if (settings->GetMessageTimeout() > 0 &&
1472 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1475 if (store->DelMessage(it->header.id, login))
1477 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1478 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1480 messages.erase(it++);
1483 if (it->GetNextSendTime() <= stgTime)
1485 if (SendMessage(*it))
1487 // We need to check all messages in queue for timeout
1491 if (it->header.repeat < 0)
1493 if (store->DelMessage(it->header.id, login))
1495 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1496 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1498 messages.erase(it++);
1502 if (store->EditMessage(*it, login))
1504 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1505 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1516 //-----------------------------------------------------------------------------
1517 std::string USER_IMPL::GetParamValue(const std::string & name) const
1519 std::string lowerName = ToLower(name);
1520 if (lowerName == "id")
1522 std::ostringstream stream;
1524 return stream.str();
1526 if (lowerName == "login") return login;
1527 if (lowerName == "currip") return currIP.ToString();
1528 if (lowerName == "enableddirs") return GetEnabledDirs();
1529 if (lowerName == "tariff") return property.tariffName;
1530 if (property.Exists(lowerName))
1531 return property.GetPropertyValue(lowerName);
1534 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1538 //-----------------------------------------------------------------------------
1539 //-----------------------------------------------------------------------------
1540 //-----------------------------------------------------------------------------
1541 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1543 if (newPassive && !oldPassive && user->tariff != NULL)
1544 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1550 //-----------------------------------------------------------------------------
1551 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1553 if (oldValue && !newValue && user->GetConnected())
1555 user->Disconnect(false, "disabled");
1557 else if (!oldValue && newValue && user->IsInetable())
1559 user->Connect(false);
1563 //-----------------------------------------------------------------------------
1564 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1566 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1567 user->Disconnect(false, "Change tariff");
1568 user->tariff = user->tariffs->FindByName(newTariff);
1569 if (user->settings->GetReconnectOnTariffChange() &&
1570 !user->authorizedBy.empty() &&
1572 user->Connect(false);
1574 //-----------------------------------------------------------------------------
1575 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1577 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1578 user->lastCashAdd = newCash - oldCash;
1580 //-----------------------------------------------------------------------------
1581 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1583 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1584 if (user->connected)
1585 user->Disconnect(false, "Change IP");
1586 if (!user->authorizedBy.empty() && user->IsInetable())
1587 user->Connect(false);
1589 //-----------------------------------------------------------------------------