2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
27 $Date: 2010/11/03 10:50:03 $
36 #include <unistd.h> // access
42 #include "stg/users.h"
43 #include "stg/common.h"
44 #include "stg/scriptexecuter.h"
45 #include "stg/tariff.h"
46 #include "stg/tariffs.h"
47 #include "stg/admin.h"
48 #include "user_impl.h"
49 #include "settings_impl.h"
50 #include "stg_timer.h"
52 #ifdef USE_ABSTRACT_SETTINGS
53 USER_IMPL::USER_IMPL(const SETTINGS * s,
60 property(s->GetScriptsDir()),
61 WriteServLog(GetStgLogger()),
66 connected(__connected),
71 lastIPForDisconnect(0),
84 lastWriteDetailedStat(0),
88 lastCashAdd(property.lastCashAdd),
89 passiveTime(property.passiveTime),
90 lastCashAddTime(property.lastCashAddTime),
91 freeMb(property.freeMb),
92 lastActivityTime(property.lastActivityTime),
93 password(property.password),
94 passive(property.passive),
95 disabled(property.disabled),
96 disabledDetailStat(property.disabledDetailStat),
97 alwaysOnline(property.alwaysOnline),
98 tariffName(property.tariffName),
99 nextTariff(property.nextTariff),
100 address(property.address),
102 group(property.group),
103 email(property.email),
104 phone(property.phone),
105 realName(property.realName),
106 credit(property.credit),
107 creditExpire(property.creditExpire),
109 userdata0(property.userdata0),
110 userdata1(property.userdata1),
111 userdata2(property.userdata2),
112 userdata3(property.userdata3),
113 userdata4(property.userdata4),
114 userdata5(property.userdata5),
115 userdata6(property.userdata6),
116 userdata7(property.userdata7),
117 userdata8(property.userdata8),
118 userdata9(property.userdata9),
121 passiveNotifier(this),
122 tariffNotifier(this),
128 password = "*_EMPTY_PASSWORD_*";
129 tariffName = NO_TARIFF_NAME;
131 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
132 lastWriteDetailedStat = stgTime;
134 property.tariffName.AddBeforeNotifier(&tariffNotifier);
135 property.passive.AddBeforeNotifier(&passiveNotifier);
136 property.disabled.AddAfterNotifier(&disabledNotifier);
137 property.cash.AddBeforeNotifier(&cashNotifier);
138 ips.AddAfterNotifier(&ipNotifier);
140 pthread_mutexattr_t attr;
141 pthread_mutexattr_init(&attr);
142 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
143 pthread_mutex_init(&mutex, &attr);
146 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
153 property(s->GetScriptsDir()),
154 WriteServLog(GetStgLogger()),
159 connected(__connected),
164 lastIPForDisconnect(0),
177 lastWriteDetailedStat(0),
181 lastCashAdd(property.lastCashAdd),
182 passiveTime(property.passiveTime),
183 lastCashAddTime(property.lastCashAddTime),
184 freeMb(property.freeMb),
185 lastActivityTime(property.lastActivityTime),
186 password(property.password),
187 passive(property.passive),
188 disabled(property.disabled),
189 disabledDetailStat(property.disabledDetailStat),
190 alwaysOnline(property.alwaysOnline),
191 tariffName(property.tariffName),
192 nextTariff(property.nextTariff),
193 address(property.address),
195 group(property.group),
196 email(property.email),
197 phone(property.phone),
198 realName(property.realName),
199 credit(property.credit),
200 creditExpire(property.creditExpire),
202 userdata0(property.userdata0),
203 userdata1(property.userdata1),
204 userdata2(property.userdata2),
205 userdata3(property.userdata3),
206 userdata4(property.userdata4),
207 userdata5(property.userdata5),
208 userdata6(property.userdata6),
209 userdata7(property.userdata7),
210 userdata8(property.userdata8),
211 userdata9(property.userdata9),
214 passiveNotifier(this),
215 disabledNotifier(this),
216 tariffNotifier(this),
222 password = "*_EMPTY_PASSWORD_*";
223 tariffName = NO_TARIFF_NAME;
225 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
226 lastWriteDetailedStat = stgTime;
228 property.tariffName.AddBeforeNotifier(&tariffNotifier);
229 property.passive.AddBeforeNotifier(&passiveNotifier);
230 property.disabled.AddAfterNotifier(&disabledNotifier);
231 property.cash.AddBeforeNotifier(&cashNotifier);
232 ips.AddAfterNotifier(&ipNotifier);
234 pthread_mutexattr_t attr;
235 pthread_mutexattr_init(&attr);
236 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
237 pthread_mutex_init(&mutex, &attr);
240 //-----------------------------------------------------------------------------
241 USER_IMPL::USER_IMPL(const USER_IMPL & u)
244 property(u.settings->GetScriptsDir()),
245 WriteServLog(GetStgLogger()),
250 connected(__connected),
252 userIDGenerator(u.userIDGenerator),
253 __currIP(u.__currIP),
255 lastIPForDisconnect(0),
256 pingTime(u.pingTime),
257 sysAdmin(u.sysAdmin),
261 traffStat(u.traffStat),
262 traffStatSaved(u.traffStatSaved),
263 settings(u.settings),
265 messages(u.messages),
267 lastWriteStat(u.lastWriteStat),
268 lastWriteDetailedStat(u.lastWriteDetailedStat),
272 lastCashAdd(property.lastCashAdd),
273 passiveTime(property.passiveTime),
274 lastCashAddTime(property.lastCashAddTime),
275 freeMb(property.freeMb),
276 lastActivityTime(property.lastActivityTime),
277 password(property.password),
278 passive(property.passive),
279 disabled(property.disabled),
280 disabledDetailStat(property.disabledDetailStat),
281 alwaysOnline(property.alwaysOnline),
282 tariffName(property.tariffName),
283 nextTariff(property.nextTariff),
284 address(property.address),
286 group(property.group),
287 email(property.email),
288 phone(property.phone),
289 realName(property.realName),
290 credit(property.credit),
291 creditExpire(property.creditExpire),
293 userdata0(property.userdata0),
294 userdata1(property.userdata1),
295 userdata2(property.userdata2),
296 userdata3(property.userdata3),
297 userdata4(property.userdata4),
298 userdata5(property.userdata5),
299 userdata6(property.userdata6),
300 userdata7(property.userdata7),
301 userdata8(property.userdata8),
302 userdata9(property.userdata9),
305 passiveNotifier(this),
306 disabledNotifier(this),
307 tariffNotifier(this),
316 property.tariffName.AddBeforeNotifier(&tariffNotifier);
317 property.passive.AddBeforeNotifier(&passiveNotifier);
318 property.disabled.AddAfterNotifier(&disabledNotifier);
319 property.cash.AddBeforeNotifier(&cashNotifier);
320 ips.AddAfterNotifier(&ipNotifier);
322 property.SetProperties(u.property);
324 pthread_mutexattr_t attr;
325 pthread_mutexattr_init(&attr);
326 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
327 pthread_mutex_init(&mutex, &attr);
329 //-----------------------------------------------------------------------------
330 USER_IMPL::~USER_IMPL()
332 property.tariffName.DelBeforeNotifier(&tariffNotifier);
333 property.passive.DelBeforeNotifier(&passiveNotifier);
334 property.disabled.DelAfterNotifier(&disabledNotifier);
335 property.cash.DelBeforeNotifier(&cashNotifier);
336 pthread_mutex_destroy(&mutex);
338 //-----------------------------------------------------------------------------
339 void USER_IMPL::SetLogin(const std::string & l)
341 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
342 assert(login.empty() && "Login is already set");
344 id = userIDGenerator.GetNextID();
346 //-----------------------------------------------------------------------------
347 int USER_IMPL::ReadConf()
349 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
352 if (store->RestoreUserConf(&conf, login))
354 WriteServLog("Cannot read conf for user %s.", login.c_str());
355 WriteServLog("%s", store->GetStrError().c_str());
356 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
357 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
361 property.SetConf(conf);
363 tariff = tariffs->FindByName(tariffName);
366 WriteServLog("Cannot read user %s. Tariff %s not exist.",
367 login.c_str(), property.tariffName.Get().c_str());
371 std::vector<STG_MSG_HDR> hdrsList;
373 if (store->GetMessageHdrs(&hdrsList, login))
375 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
376 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
378 store->GetStrError().c_str());
382 std::vector<STG_MSG_HDR>::const_iterator it;
383 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
386 if (store->GetMessage(it->id, &msg, login) == 0)
388 messages.push_back(msg);
394 //-----------------------------------------------------------------------------
395 int USER_IMPL::ReadStat()
397 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
400 if (store->RestoreUserStat(&stat, login))
402 WriteServLog("Cannot read stat for user %s.", login.c_str());
403 WriteServLog("%s", store->GetStrError().c_str());
404 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
405 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
409 property.SetStat(stat);
413 //-----------------------------------------------------------------------------
414 int USER_IMPL::WriteConf()
416 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
417 USER_CONF conf(property.GetConf());
419 printfd(__FILE__, "USER::WriteConf()\n");
421 if (store->SaveUserConf(conf, login))
423 WriteServLog("Cannot write conf for user %s.", login.c_str());
424 WriteServLog("%s", store->GetStrError().c_str());
425 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
426 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
432 //-----------------------------------------------------------------------------
433 int USER_IMPL::WriteStat()
435 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
436 USER_STAT stat(property.GetStat());
438 if (store->SaveUserStat(stat, login))
440 WriteServLog("Cannot write stat for user %s.", login.c_str());
441 WriteServLog("%s", store->GetStrError().c_str());
442 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
443 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
447 lastWriteStat = stgTime;
451 //-----------------------------------------------------------------------------
452 int USER_IMPL::WriteMonthStat()
454 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
455 time_t tt = stgTime - 3600;
457 localtime_r(&tt, &t1);
459 USER_STAT stat(property.GetStat());
460 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
462 WriteServLog("Cannot write month stat for user %s.", login.c_str());
463 WriteServLog("%s", store->GetStrError().c_str());
464 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
465 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
471 //-----------------------------------------------------------------------------
472 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
474 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
476 * Authorize user. It only means that user will be authorized. Nothing more.
477 * User can be connected or disconnected while authorized.
478 * Example: user is authorized but disconnected due to 0 money or blocking
482 * Prevent double authorization by identical authorizers
484 if (authorizedBy.find(auth) != authorizedBy.end())
490 for (int i = 0; i < DIR_NUM; i++)
492 enabledDirs[i] = dirs & (1 << i);
495 if (!authorizedBy.empty())
499 // We are already authorized, but with different IP address
500 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
505 if (!users->FindByIPIdx(ip, &u))
507 // Address is already present in IP-index
508 // If it's not our IP - throw an error
511 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
518 if (users->IsIPInIndex(ip))
520 // Address is already present in IP-index
521 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
525 if (ips.ConstData().IsIPInIPS(ip))
528 lastIPForDisconnect = currIP;
532 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
533 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
538 authorizedBy.insert(auth);
544 //-----------------------------------------------------------------------------
545 void USER_IMPL::Unauthorize(const AUTH * auth)
547 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
549 * Authorizer tries to unauthorize user, that was not authorized by it
551 if (!authorizedBy.erase(auth))
554 if (authorizedBy.empty())
556 lastIPForDisconnect = currIP;
557 currIP = 0; // DelUser in traffcounter
561 //-----------------------------------------------------------------------------
562 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
564 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
565 // Is this user authorized by specified authorizer?
566 return authorizedBy.find(auth) != authorizedBy.end();
568 //-----------------------------------------------------------------------------
569 void USER_IMPL::Connect(bool fakeConnect)
572 * Connect user to Internet. This function is differ from Authorize() !!!
575 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
579 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
581 if (access(scriptOnConnect.c_str(), X_OK) == 0)
583 char dirsStr[DIR_NUM + 1];
584 dirsStr[DIR_NUM] = 0;
585 for (int i = 0; i < DIR_NUM; i++)
587 dirsStr[i] = enabledDirs[i] ? '1' : '0';
590 std::string scriptOnConnectParams;
592 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
593 while (it != settings->GetScriptParams().end())
595 scriptOnConnectParams += GetParamValue(it->c_str());
598 // strprintf(&scriptOnConnectParams,
599 // "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
600 // scriptOnConnect.c_str(),
602 // inet_ntostring(currIP).c_str(),
607 ScriptExec(scriptOnConnectParams.c_str());
611 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
617 if (store->WriteUserConnect(login, currIP))
619 WriteServLog("Cannot write connect for user %s.", login.c_str());
620 WriteServLog("%s", store->GetStrError().c_str());
624 lastIPForDisconnect = currIP;
626 //-----------------------------------------------------------------------------
627 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
630 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
633 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
635 if (!lastIPForDisconnect)
637 printfd(__FILE__, "lastIPForDisconnect\n");
643 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
645 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
647 char dirsStr[DIR_NUM + 1];
648 dirsStr[DIR_NUM] = 0;
649 for (int i = 0; i < DIR_NUM; i++)
651 dirsStr[i] = enabledDirs[i] ? '1' : '0';
654 std::string scriptOnDisonnectParams;
655 strprintf(&scriptOnDisonnectParams,
656 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
657 scriptOnDisonnect.c_str(),
659 inet_ntostring(lastIPForDisconnect).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
1471 return property.cash.ToString();
1473 if (name == "freeMb")
1475 return property.freeMb.ToString();
1477 if (name == "passive")
1479 return property.passive.ToString();
1481 if (name == "disabled")
1483 return property.disabled.ToString();
1485 if (name == "alwaysOnline")
1487 return property.alwaysOnline.ToString();
1489 if (name == "tariffName")
1491 return property.tariffName;
1493 if (name == "nextTariff")
1495 return property.nextTariff;
1497 if (name == "address")
1499 return property.address;
1503 return property.note;
1505 if (name == "group")
1507 return property.group;
1509 if (name == "email")
1511 return property.email;
1513 if (name == "phone")
1515 return property.phone;
1517 if (name == "realName")
1519 return property.realName;
1521 if (name == "credit")
1523 return property.credit.ToString();
1525 if (name == "userdata0")
1527 return property.userdata0;
1529 if (name == "userdata1")
1531 return property.userdata1;
1533 if (name == "userdata2")
1535 return property.userdata2;
1537 if (name == "userdata3")
1539 return property.userdata3;
1541 if (name == "userdata4")
1543 return property.userdata4;
1545 if (name == "userdata5")
1547 return property.userdata5;
1549 if (name == "userdata6")
1551 return property.userdata6;
1553 if (name == "userdata7")
1555 return property.userdata7;
1557 if (name == "userdata8")
1559 return property.userdata8;
1561 if (name == "userdata9")
1563 return property.userdata9;
1567 std::stringstream stream;
1569 return stream.str();;
1571 if (name == "login")
1577 return currIP.ToString();
1580 //-----------------------------------------------------------------------------
1581 //-----------------------------------------------------------------------------
1582 //-----------------------------------------------------------------------------
1583 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1585 if (newPassive && !oldPassive && user->tariff != NULL)
1586 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1592 //-----------------------------------------------------------------------------
1593 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1595 if (oldValue && !newValue && user->GetConnected())
1597 user->Disconnect(false, "disabled");
1599 else if (!oldValue && newValue && user->IsInetable())
1601 user->Connect(false);
1605 //-----------------------------------------------------------------------------
1606 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1608 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1609 user->Disconnect(false, "Change tariff");
1610 user->tariff = user->tariffs->FindByName(newTariff);
1611 if (user->settings->GetReconnectOnTariffChange() &&
1612 !user->authorizedBy.empty() &&
1614 user->Connect(false);
1616 //-----------------------------------------------------------------------------
1617 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1619 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1620 user->lastCashAdd = newCash - oldCash;
1622 //-----------------------------------------------------------------------------
1623 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1625 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1626 if (user->connected)
1627 user->Disconnect(false, "Change IP");
1628 if (!user->authorizedBy.empty() && user->IsInetable())
1629 user->Connect(false);
1631 //-----------------------------------------------------------------------------