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;
583 strprintf(&scriptOnConnectParams,
584 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
585 scriptOnConnect.c_str(),
587 inet_ntostring(currIP).c_str(),
592 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
593 while (it != settings->GetScriptParams().end())
595 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
599 ScriptExec(scriptOnConnectParams.c_str());
603 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
609 if (store->WriteUserConnect(login, currIP))
611 WriteServLog("Cannot write connect for user %s.", login.c_str());
612 WriteServLog("%s", store->GetStrError().c_str());
616 lastIPForDisconnect = currIP;
618 //-----------------------------------------------------------------------------
619 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
622 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
625 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
627 if (!lastIPForDisconnect)
629 printfd(__FILE__, "lastIPForDisconnect\n");
635 lastDisconnectReason = reason;
636 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
638 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
640 char dirsStr[DIR_NUM + 1];
641 dirsStr[DIR_NUM] = 0;
642 for (int i = 0; i < DIR_NUM; i++)
644 dirsStr[i] = enabledDirs[i] ? '1' : '0';
647 std::string scriptOnDisonnectParams;
648 strprintf(&scriptOnDisonnectParams,
649 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
650 scriptOnDisonnect.c_str(),
652 inet_ntostring(lastIPForDisconnect).c_str(),
657 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
658 while (it != settings->GetScriptParams().end())
660 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
664 ScriptExec(scriptOnDisonnectParams.c_str());
668 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
674 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
676 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
677 WriteServLog("%s", store->GetStrError().c_str());
681 lastIPForDisconnect = 0;
683 DIR_TRAFF zeroSesssion;
685 sessionUpload = zeroSesssion;
686 sessionDownload = zeroSesssion;
688 //-----------------------------------------------------------------------------
689 void USER_IMPL::PrintUser() const
692 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
693 std::cout << "============================================================" << std::endl;
694 std::cout << "id=" << id << std::endl;
695 std::cout << "login=" << login << std::endl;
696 std::cout << "password=" << password << std::endl;
697 std::cout << "passive=" << passive << std::endl;
698 std::cout << "disabled=" << disabled << std::endl;
699 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
700 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
701 std::cout << "tariffName=" << tariffName << std::endl;
702 std::cout << "address=" << address << std::endl;
703 std::cout << "phone=" << phone << std::endl;
704 std::cout << "email=" << email << std::endl;
705 std::cout << "note=" << note << std::endl;
706 std::cout << "realName=" <<realName << std::endl;
707 std::cout << "group=" << group << std::endl;
708 std::cout << "credit=" << credit << std::endl;
709 std::cout << "nextTariff=" << nextTariff << std::endl;
710 std::cout << "userdata0" << userdata0 << std::endl;
711 std::cout << "userdata1" << userdata1 << std::endl;
712 std::cout << "creditExpire=" << creditExpire << std::endl;
713 std::cout << "ips=" << ips << std::endl;
714 std::cout << "------------------------" << std::endl;
715 std::cout << "up=" << up << std::endl;
716 std::cout << "down=" << down << std::endl;
717 std::cout << "cash=" << cash << std::endl;
718 std::cout << "freeMb=" << freeMb << std::endl;
719 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
720 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
721 std::cout << "passiveTime=" << passiveTime << std::endl;
722 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
723 std::cout << "============================================================" << std::endl;
725 //-----------------------------------------------------------------------------
726 void USER_IMPL::Run()
728 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
730 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
732 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
735 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
737 WriteServLog("User: %s. Credit expired.", login.c_str());
743 if (passive.ConstData()
744 && (stgTime % 30 == 0)
745 && (passiveTime.ModificationTime() != stgTime))
747 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
748 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
751 if (!authorizedBy.empty())
755 property.Stat().lastActivityTime = stgTime;
757 if (!connected && IsInetable())
761 if (connected && !IsInetable())
764 Disconnect(false, "disabled");
766 Disconnect(false, "passive");
768 Disconnect(false, "no cash");
771 if (stgTime - lastScanMessages > 10)
774 lastScanMessages = stgTime;
781 Disconnect(false, "not authorized");
786 //-----------------------------------------------------------------------------
787 void USER_IMPL::UpdatePingTime(time_t t)
789 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
790 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
796 //-----------------------------------------------------------------------------
797 bool USER_IMPL::IsInetable()
799 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
801 if (disabled || passive)
804 if (settings->GetFreeMbAllowInet())
810 if (settings->GetShowFeeInCash() || tariff == NULL)
812 return (cash >= -credit);
815 return (cash - tariff->GetFee() >= -credit);
817 //-----------------------------------------------------------------------------
818 std::string USER_IMPL::GetEnabledDirs()
820 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
822 std::string dirs = "";
823 for(int i = 0; i < DIR_NUM; i++)
824 dirs += enabledDirs[i] ? "1" : "0";
827 //-----------------------------------------------------------------------------
828 #ifdef TRAFF_STAT_WITH_PORTS
829 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
831 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
834 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
836 if (!connected || tariff == NULL)
842 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
843 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
847 int tt = tariff->GetTraffType();
848 if (tt == TRAFF_UP ||
849 tt == TRAFF_UP_DOWN ||
850 // Check NEW traff data
851 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
854 if (traff < threshold &&
855 traff + len >= threshold)
857 // cash = partBeforeThreshold * priceBeforeThreshold +
858 // partAfterThreshold * priceAfterThreshold
859 int64_t before = threshold - traff; // Chunk part before threshold
860 int64_t after = len - before; // Chunk part after threshold
861 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
862 down.ConstData()[dir],
865 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
866 down.ConstData()[dir],
872 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
873 down.ConstData()[dir],
878 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
880 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
881 cost = dc - freeMb.ConstData();
883 // Direct access to internal data structures via friend-specifier
884 property.Stat().freeMb -= dc;
885 property.Stat().cash -= cost;
891 sessionUpload[dir] += len;
895 if (!settings->GetWriteFreeMbTraffCost() &&
896 freeMb.ConstData() >= 0)
899 #ifdef TRAFF_STAT_WITH_PORTS
900 IP_DIR_PAIR idp(ip, dir, port);
902 IP_DIR_PAIR idp(ip, dir);
905 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
906 lb = traffStat.lower_bound(idp);
907 if (lb == traffStat.end() || lb->first != idp)
911 STAT_NODE(len, 0, cost)));
915 lb->second.cash += cost;
916 lb->second.up += len;
919 //-----------------------------------------------------------------------------
920 #ifdef TRAFF_STAT_WITH_PORTS
921 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
923 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
926 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
928 if (!connected || tariff == NULL)
934 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
935 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
939 int tt = tariff->GetTraffType();
940 if (tt == TRAFF_DOWN ||
941 tt == TRAFF_UP_DOWN ||
942 // Check NEW traff data
943 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
946 if (traff < threshold &&
947 traff + len >= threshold)
949 // cash = partBeforeThreshold * priceBeforeThreshold +
950 // partAfterThreshold * priceAfterThreshold
951 int64_t before = threshold - traff; // Chunk part before threshold
952 int64_t after = len - before; // Chunk part after threshold
953 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
954 down.ConstData()[dir], // Traff before chunk
957 tariff->GetPriceWithTraffType(up.ConstData()[dir],
958 dt[dir], // Traff after chunk
964 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
965 down.ConstData()[dir],
970 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
972 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
973 cost = dc - freeMb.ConstData();
975 property.Stat().freeMb -= dc;
976 property.Stat().cash -= cost;
982 sessionDownload[dir] += len;
986 if (!settings->GetWriteFreeMbTraffCost() &&
987 freeMb.ConstData() >= 0)
990 #ifdef TRAFF_STAT_WITH_PORTS
991 IP_DIR_PAIR idp(ip, dir, port);
993 IP_DIR_PAIR idp(ip, dir);
996 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
997 lb = traffStat.lower_bound(idp);
998 if (lb == traffStat.end() || lb->first != idp)
1000 traffStat.insert(lb,
1002 STAT_NODE(0, len, cost)));
1006 lb->second.cash += cost;
1007 lb->second.down += len;
1010 //-----------------------------------------------------------------------------
1011 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1013 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1014 currIP.AddBeforeNotifier(notifier);
1016 //-----------------------------------------------------------------------------
1017 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1019 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1020 currIP.DelBeforeNotifier(notifier);
1022 //-----------------------------------------------------------------------------
1023 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1025 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1026 currIP.AddAfterNotifier(notifier);
1028 //-----------------------------------------------------------------------------
1029 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1031 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1032 currIP.DelAfterNotifier(notifier);
1034 //-----------------------------------------------------------------------------
1035 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1037 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1038 connected.AddBeforeNotifier(notifier);
1040 //-----------------------------------------------------------------------------
1041 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1043 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1044 connected.DelBeforeNotifier(notifier);
1046 //-----------------------------------------------------------------------------
1047 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1049 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1050 connected.AddAfterNotifier(notifier);
1052 //-----------------------------------------------------------------------------
1053 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1055 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1056 connected.DelAfterNotifier(notifier);
1058 //-----------------------------------------------------------------------------
1059 void USER_IMPL::OnAdd()
1061 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1063 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1065 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1067 std::string scriptOnAddParams;
1068 strprintf(&scriptOnAddParams,
1070 scriptOnAdd.c_str(),
1073 ScriptExec(scriptOnAddParams.c_str());
1077 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1080 //-----------------------------------------------------------------------------
1081 void USER_IMPL::OnDelete()
1083 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1085 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1087 if (access(scriptOnDel.c_str(), X_OK) == 0)
1089 std::string scriptOnDelParams;
1090 strprintf(&scriptOnDelParams,
1092 scriptOnDel.c_str(),
1095 ScriptExec(scriptOnDelParams.c_str());
1099 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1104 //-----------------------------------------------------------------------------
1105 int USER_IMPL::WriteDetailStat(bool hard)
1107 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1109 if (!traffStatSaved.second.empty())
1111 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1113 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1114 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1115 WriteServLog("%s", store->GetStrError().c_str());
1118 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1124 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1128 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1130 if (ts.size() && !disabledDetailStat)
1132 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1134 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1135 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1136 WriteServLog("%s", store->GetStrError().c_str());
1139 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1140 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1141 traffStatSaved.second.swap(ts);
1142 traffStatSaved.first = lastWriteDetailedStat;
1147 lastWriteDetailedStat = stgTime;
1150 //-----------------------------------------------------------------------------
1151 double USER_IMPL::GetPassiveTimePart() const
1153 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1155 static int daysInMonth[12] =
1156 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1160 localtime_r(&t, &tms);
1162 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1164 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1167 secMonth += 24 * 3600;
1170 time_t dt = secMonth - passiveTime;
1175 return static_cast<double>(dt) / secMonth;
1177 //-----------------------------------------------------------------------------
1178 void USER_IMPL::SetPassiveTimeAsNewUser()
1180 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1184 localtime_r(&t, &tm);
1185 int daysCurrMon = DaysInCurrentMonth();
1186 double pt = tm.tm_mday - 1;
1189 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1191 //-----------------------------------------------------------------------------
1192 void USER_IMPL::MidnightResetSessionStat()
1194 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1198 Disconnect(true, "fake");
1202 //-----------------------------------------------------------------------------
1203 void USER_IMPL::ProcessNewMonth()
1205 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1209 Disconnect(true, "fake");
1211 DIR_TRAFF zeroTarff;
1224 if (nextTariff.ConstData() != "")
1227 nt = tariffs->FindByName(nextTariff);
1230 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1231 login.c_str(), property.tariffName.Get().c_str());
1235 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1242 //-----------------------------------------------------------------------------
1243 void USER_IMPL::ProcessDayFeeSpread()
1245 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1247 if (passive.ConstData() || tariff == NULL)
1250 double fee = tariff->GetFee() / DaysInCurrentMonth();
1252 if (std::fabs(fee) < 1.0e-3)
1256 switch (settings->GetFeeChargeType())
1259 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1262 if (c + credit >= 0)
1263 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1266 if (c + credit >= fee)
1267 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1271 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1276 //-----------------------------------------------------------------------------
1277 void USER_IMPL::ProcessDayFee()
1279 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1284 double passiveTimePart = 1.0;
1285 if (!settings->GetFullFee())
1287 passiveTimePart = GetPassiveTimePart();
1291 if (passive.ConstData())
1293 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1297 double fee = tariff->GetFee() * passiveTimePart;
1301 if (std::fabs(fee) < 1.0e-3)
1308 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1315 switch (settings->GetFeeChargeType())
1318 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1322 if (c + credit >= 0)
1324 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1329 if (c + credit >= fee)
1331 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1338 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1344 //-----------------------------------------------------------------------------
1345 void USER_IMPL::SetPrepaidTraff()
1348 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1350 //-----------------------------------------------------------------------------
1351 int USER_IMPL::AddMessage(STG_MSG * msg)
1353 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1355 if (SendMessage(*msg))
1357 if (store->AddMessage(msg, login))
1359 errorStr = store->GetStrError();
1360 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1361 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1364 messages.push_back(*msg);
1368 if (msg->header.repeat > 0)
1370 msg->header.repeat--;
1372 //TODO: gcc v. 4.x generate ICE on x86_64
1373 msg->header.lastSendTime = static_cast<int>(time(NULL));
1375 msg->header.lastSendTime = static_cast<int>(stgTime);
1377 if (store->AddMessage(msg, login))
1379 errorStr = store->GetStrError();
1380 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1381 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1384 messages.push_back(*msg);
1389 //-----------------------------------------------------------------------------
1390 int USER_IMPL::SendMessage(STG_MSG & msg) const
1392 // No lock `cause we are already locked from caller
1394 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1395 while (it != authorizedBy.end())
1397 if (!(*it++)->SendMessage(msg, currIP))
1403 //TODO: gcc v. 4.x generate ICE on x86_64
1404 msg.header.lastSendTime = static_cast<int>(time(NULL));
1406 msg.header.lastSendTime = static_cast<int>(stgTime);
1408 msg.header.repeat--;
1412 //-----------------------------------------------------------------------------
1413 void USER_IMPL::ScanMessage()
1415 // No lock `cause we are already locked from caller
1416 // We need not check for the authorizedBy `cause it has already checked by caller
1418 std::list<STG_MSG>::iterator it(messages.begin());
1419 while (it != messages.end())
1421 if (settings->GetMessageTimeout() > 0 &&
1422 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1425 if (store->DelMessage(it->header.id, login))
1427 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1428 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1430 messages.erase(it++);
1433 if (it->GetNextSendTime() <= stgTime)
1435 if (SendMessage(*it))
1437 // We need to check all messages in queue for timeout
1441 if (it->header.repeat < 0)
1443 if (store->DelMessage(it->header.id, login))
1445 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1446 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1448 messages.erase(it++);
1452 if (store->EditMessage(*it, login))
1454 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1455 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1466 //-----------------------------------------------------------------------------
1467 std::string USER_IMPL::GetParamValue(const std::string & name) const
1469 if (name == "freeMb") return property.freeMb.ToString();
1470 if (name == "passive") return property.passive.ToString();
1471 if (name == "disabled") return property.disabled.ToString();
1472 if (name == "alwaysOnline") return property.alwaysOnline.ToString();
1473 if (name == "tariffName") return property.tariffName;
1474 if (name == "nextTariff") return property.nextTariff;
1475 if (name == "address") return property.address;
1476 if (name == "note") return property.note;
1477 if (name == "group") return property.group;
1478 if (name == "email") return property.email;
1479 if (name == "phone") return property.phone;
1480 if (name == "realName") return property.realName;
1481 if (name == "credit") return property.credit.ToString();
1482 if (name == "userdata0") return property.userdata0;
1483 if (name == "userdata1") return property.userdata1;
1484 if (name == "userdata2") return property.userdata2;
1485 if (name == "userdata3") return property.userdata3;
1486 if (name == "userdata4") return property.userdata4;
1487 if (name == "userdata5") return property.userdata5;
1488 if (name == "userdata6") return property.userdata6;
1489 if (name == "userdata7") return property.userdata7;
1490 if (name == "userdata8") return property.userdata8;
1491 if (name == "userdata9") return property.userdata9;
1492 if (name == "cash") return property.cash.ToString();
1495 std::stringstream stream;
1497 return stream.str();;
1499 if (name == "login") return login;
1500 if (name == "ip") return currIP.ToString();
1503 //-----------------------------------------------------------------------------
1504 //-----------------------------------------------------------------------------
1505 //-----------------------------------------------------------------------------
1506 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1508 if (newPassive && !oldPassive && user->tariff != NULL)
1509 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1515 //-----------------------------------------------------------------------------
1516 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1518 if (oldValue && !newValue && user->GetConnected())
1520 user->Disconnect(false, "disabled");
1522 else if (!oldValue && newValue && user->IsInetable())
1524 user->Connect(false);
1528 //-----------------------------------------------------------------------------
1529 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1531 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1532 user->Disconnect(false, "Change tariff");
1533 user->tariff = user->tariffs->FindByName(newTariff);
1534 if (user->settings->GetReconnectOnTariffChange() &&
1535 !user->authorizedBy.empty() &&
1537 user->Connect(false);
1539 //-----------------------------------------------------------------------------
1540 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1542 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1543 user->lastCashAdd = newCash - oldCash;
1545 //-----------------------------------------------------------------------------
1546 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1548 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1549 if (user->connected)
1550 user->Disconnect(false, "Change IP");
1551 if (!user->authorizedBy.empty() && user->IsInetable())
1552 user->Connect(false);
1554 //-----------------------------------------------------------------------------