2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
27 $Date: 2010/11/03 10:50:03 $
36 #include <unistd.h> // access
44 #include "stg/users.h"
45 #include "stg/common.h"
46 #include "stg/scriptexecuter.h"
47 #include "stg/tariff.h"
48 #include "stg/tariffs.h"
49 #include "stg/admin.h"
50 #include "user_impl.h"
51 #include "settings_impl.h"
52 #include "stg_timer.h"
54 #ifdef USE_ABSTRACT_SETTINGS
55 USER_IMPL::USER_IMPL(const SETTINGS * s,
62 property(s->GetScriptsDir()),
63 WriteServLog(GetStgLogger()),
68 connected(__connected),
73 lastIPForDisconnect(0),
86 lastWriteDetailedStat(0),
90 lastCashAdd(property.lastCashAdd),
91 passiveTime(property.passiveTime),
92 lastCashAddTime(property.lastCashAddTime),
93 freeMb(property.freeMb),
94 lastActivityTime(property.lastActivityTime),
95 password(property.password),
96 passive(property.passive),
97 disabled(property.disabled),
98 disabledDetailStat(property.disabledDetailStat),
99 alwaysOnline(property.alwaysOnline),
100 tariffName(property.tariffName),
101 nextTariff(property.nextTariff),
102 address(property.address),
104 group(property.group),
105 email(property.email),
106 phone(property.phone),
107 realName(property.realName),
108 credit(property.credit),
109 creditExpire(property.creditExpire),
111 userdata0(property.userdata0),
112 userdata1(property.userdata1),
113 userdata2(property.userdata2),
114 userdata3(property.userdata3),
115 userdata4(property.userdata4),
116 userdata5(property.userdata5),
117 userdata6(property.userdata6),
118 userdata7(property.userdata7),
119 userdata8(property.userdata8),
120 userdata9(property.userdata9),
123 passiveNotifier(this),
124 tariffNotifier(this),
130 password = "*_EMPTY_PASSWORD_*";
131 tariffName = NO_TARIFF_NAME;
133 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
134 lastWriteDetailedStat = stgTime;
136 property.tariffName.AddBeforeNotifier(&tariffNotifier);
137 property.passive.AddBeforeNotifier(&passiveNotifier);
138 property.disabled.AddAfterNotifier(&disabledNotifier);
139 property.cash.AddBeforeNotifier(&cashNotifier);
140 ips.AddAfterNotifier(&ipNotifier);
142 pthread_mutexattr_t attr;
143 pthread_mutexattr_init(&attr);
144 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
145 pthread_mutex_init(&mutex, &attr);
148 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
155 property(s->GetScriptsDir()),
156 WriteServLog(GetStgLogger()),
161 connected(__connected),
166 lastIPForDisconnect(0),
179 lastWriteDetailedStat(0),
183 lastCashAdd(property.lastCashAdd),
184 passiveTime(property.passiveTime),
185 lastCashAddTime(property.lastCashAddTime),
186 freeMb(property.freeMb),
187 lastActivityTime(property.lastActivityTime),
188 password(property.password),
189 passive(property.passive),
190 disabled(property.disabled),
191 disabledDetailStat(property.disabledDetailStat),
192 alwaysOnline(property.alwaysOnline),
193 tariffName(property.tariffName),
194 nextTariff(property.nextTariff),
195 address(property.address),
197 group(property.group),
198 email(property.email),
199 phone(property.phone),
200 realName(property.realName),
201 credit(property.credit),
202 creditExpire(property.creditExpire),
204 userdata0(property.userdata0),
205 userdata1(property.userdata1),
206 userdata2(property.userdata2),
207 userdata3(property.userdata3),
208 userdata4(property.userdata4),
209 userdata5(property.userdata5),
210 userdata6(property.userdata6),
211 userdata7(property.userdata7),
212 userdata8(property.userdata8),
213 userdata9(property.userdata9),
216 passiveNotifier(this),
217 disabledNotifier(this),
218 tariffNotifier(this),
224 password = "*_EMPTY_PASSWORD_*";
225 tariffName = NO_TARIFF_NAME;
227 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
228 lastWriteDetailedStat = stgTime;
230 property.tariffName.AddBeforeNotifier(&tariffNotifier);
231 property.passive.AddBeforeNotifier(&passiveNotifier);
232 property.disabled.AddAfterNotifier(&disabledNotifier);
233 property.cash.AddBeforeNotifier(&cashNotifier);
234 ips.AddAfterNotifier(&ipNotifier);
236 pthread_mutexattr_t attr;
237 pthread_mutexattr_init(&attr);
238 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
239 pthread_mutex_init(&mutex, &attr);
242 //-----------------------------------------------------------------------------
243 USER_IMPL::USER_IMPL(const USER_IMPL & u)
246 property(u.settings->GetScriptsDir()),
247 WriteServLog(GetStgLogger()),
252 connected(__connected),
254 userIDGenerator(u.userIDGenerator),
255 __currIP(u.__currIP),
257 lastIPForDisconnect(0),
258 pingTime(u.pingTime),
259 sysAdmin(u.sysAdmin),
263 traffStat(u.traffStat),
264 traffStatSaved(u.traffStatSaved),
265 settings(u.settings),
267 messages(u.messages),
269 lastWriteStat(u.lastWriteStat),
270 lastWriteDetailedStat(u.lastWriteDetailedStat),
274 lastCashAdd(property.lastCashAdd),
275 passiveTime(property.passiveTime),
276 lastCashAddTime(property.lastCashAddTime),
277 freeMb(property.freeMb),
278 lastActivityTime(property.lastActivityTime),
279 password(property.password),
280 passive(property.passive),
281 disabled(property.disabled),
282 disabledDetailStat(property.disabledDetailStat),
283 alwaysOnline(property.alwaysOnline),
284 tariffName(property.tariffName),
285 nextTariff(property.nextTariff),
286 address(property.address),
288 group(property.group),
289 email(property.email),
290 phone(property.phone),
291 realName(property.realName),
292 credit(property.credit),
293 creditExpire(property.creditExpire),
295 userdata0(property.userdata0),
296 userdata1(property.userdata1),
297 userdata2(property.userdata2),
298 userdata3(property.userdata3),
299 userdata4(property.userdata4),
300 userdata5(property.userdata5),
301 userdata6(property.userdata6),
302 userdata7(property.userdata7),
303 userdata8(property.userdata8),
304 userdata9(property.userdata9),
307 passiveNotifier(this),
308 disabledNotifier(this),
309 tariffNotifier(this),
318 property.tariffName.AddBeforeNotifier(&tariffNotifier);
319 property.passive.AddBeforeNotifier(&passiveNotifier);
320 property.disabled.AddAfterNotifier(&disabledNotifier);
321 property.cash.AddBeforeNotifier(&cashNotifier);
322 ips.AddAfterNotifier(&ipNotifier);
324 property.SetProperties(u.property);
326 pthread_mutexattr_t attr;
327 pthread_mutexattr_init(&attr);
328 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
329 pthread_mutex_init(&mutex, &attr);
331 //-----------------------------------------------------------------------------
332 USER_IMPL::~USER_IMPL()
334 property.tariffName.DelBeforeNotifier(&tariffNotifier);
335 property.passive.DelBeforeNotifier(&passiveNotifier);
336 property.disabled.DelAfterNotifier(&disabledNotifier);
337 property.cash.DelBeforeNotifier(&cashNotifier);
338 pthread_mutex_destroy(&mutex);
340 //-----------------------------------------------------------------------------
341 void USER_IMPL::SetLogin(const std::string & l)
343 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
344 assert(login.empty() && "Login is already set");
346 id = userIDGenerator.GetNextID();
348 //-----------------------------------------------------------------------------
349 int USER_IMPL::ReadConf()
351 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
354 if (store->RestoreUserConf(&conf, login))
356 WriteServLog("Cannot read conf for user %s.", login.c_str());
357 WriteServLog("%s", store->GetStrError().c_str());
358 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
359 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
363 property.SetConf(conf);
365 tariff = tariffs->FindByName(tariffName);
368 WriteServLog("Cannot read user %s. Tariff %s not exist.",
369 login.c_str(), property.tariffName.Get().c_str());
373 std::vector<STG_MSG_HDR> hdrsList;
375 if (store->GetMessageHdrs(&hdrsList, login))
377 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
378 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
380 store->GetStrError().c_str());
384 std::vector<STG_MSG_HDR>::const_iterator it;
385 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
388 if (store->GetMessage(it->id, &msg, login) == 0)
390 messages.push_back(msg);
396 //-----------------------------------------------------------------------------
397 int USER_IMPL::ReadStat()
399 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
402 if (store->RestoreUserStat(&stat, login))
404 WriteServLog("Cannot read stat for user %s.", login.c_str());
405 WriteServLog("%s", store->GetStrError().c_str());
406 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
407 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
411 property.SetStat(stat);
415 //-----------------------------------------------------------------------------
416 int USER_IMPL::WriteConf()
418 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
419 USER_CONF conf(property.GetConf());
421 printfd(__FILE__, "USER::WriteConf()\n");
423 if (store->SaveUserConf(conf, login))
425 WriteServLog("Cannot write conf for user %s.", login.c_str());
426 WriteServLog("%s", store->GetStrError().c_str());
427 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
428 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
434 //-----------------------------------------------------------------------------
435 int USER_IMPL::WriteStat()
437 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
438 USER_STAT stat(property.GetStat());
440 if (store->SaveUserStat(stat, login))
442 WriteServLog("Cannot write stat for user %s.", login.c_str());
443 WriteServLog("%s", store->GetStrError().c_str());
444 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
445 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
449 lastWriteStat = stgTime;
453 //-----------------------------------------------------------------------------
454 int USER_IMPL::WriteMonthStat()
456 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
457 time_t tt = stgTime - 3600;
459 localtime_r(&tt, &t1);
461 USER_STAT stat(property.GetStat());
462 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
464 WriteServLog("Cannot write month stat for user %s.", login.c_str());
465 WriteServLog("%s", store->GetStrError().c_str());
466 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
467 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
473 //-----------------------------------------------------------------------------
474 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
476 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
478 * Authorize user. It only means that user will be authorized. Nothing more.
479 * User can be connected or disconnected while authorized.
480 * Example: user is authorized but disconnected due to 0 money or blocking
484 * Prevent double authorization by identical authorizers
486 if (authorizedBy.find(auth) != authorizedBy.end())
492 for (int i = 0; i < DIR_NUM; i++)
494 enabledDirs[i] = dirs & (1 << i);
497 if (!authorizedBy.empty())
501 // We are already authorized, but with different IP address
502 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
507 if (!users->FindByIPIdx(ip, &u))
509 // Address is already present in IP-index
510 // If it's not our IP - throw an error
513 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
520 if (users->IsIPInIndex(ip))
522 // Address is already present in IP-index
523 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
527 if (ips.ConstData().IsIPInIPS(ip))
530 lastIPForDisconnect = currIP;
534 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
535 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
540 authorizedBy.insert(auth);
546 //-----------------------------------------------------------------------------
547 void USER_IMPL::Unauthorize(const AUTH * auth)
549 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
551 * Authorizer tries to unauthorize user, that was not authorized by it
553 if (!authorizedBy.erase(auth))
556 if (authorizedBy.empty())
558 lastIPForDisconnect = currIP;
559 currIP = 0; // DelUser in traffcounter
563 //-----------------------------------------------------------------------------
564 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
566 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
567 // Is this user authorized by specified authorizer?
568 return authorizedBy.find(auth) != authorizedBy.end();
570 //-----------------------------------------------------------------------------
571 std::vector<std::string> USER_IMPL::GetAuthorizers() const
573 std::vector<std::string> list;
574 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
577 //-----------------------------------------------------------------------------
578 void USER_IMPL::Connect(bool fakeConnect)
581 * Connect user to Internet. This function is differ from Authorize() !!!
584 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
588 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
590 if (access(scriptOnConnect.c_str(), X_OK) == 0)
592 char dirsStr[DIR_NUM + 1];
593 dirsStr[DIR_NUM] = 0;
594 for (int i = 0; i < DIR_NUM; i++)
596 dirsStr[i] = enabledDirs[i] ? '1' : '0';
599 std::string scriptOnConnectParams;
600 strprintf(&scriptOnConnectParams,
601 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
602 scriptOnConnect.c_str(),
604 inet_ntostring(currIP).c_str(),
609 ScriptExec(scriptOnConnectParams.c_str());
613 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
619 if (store->WriteUserConnect(login, currIP))
621 WriteServLog("Cannot write connect for user %s.", login.c_str());
622 WriteServLog("%s", store->GetStrError().c_str());
626 lastIPForDisconnect = currIP;
628 //-----------------------------------------------------------------------------
629 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
632 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
635 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
637 if (!lastIPForDisconnect)
639 printfd(__FILE__, "lastIPForDisconnect\n");
645 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
647 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
649 char dirsStr[DIR_NUM + 1];
650 dirsStr[DIR_NUM] = 0;
651 for (int i = 0; i < DIR_NUM; i++)
653 dirsStr[i] = enabledDirs[i] ? '1' : '0';
656 std::string scriptOnDisonnectParams;
657 strprintf(&scriptOnDisonnectParams,
658 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
659 scriptOnDisonnect.c_str(),
661 inet_ntostring(lastIPForDisconnect).c_str(),
666 ScriptExec(scriptOnDisonnectParams.c_str());
670 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
676 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
678 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
679 WriteServLog("%s", store->GetStrError().c_str());
683 lastIPForDisconnect = 0;
685 DIR_TRAFF zeroSesssion;
687 sessionUpload = zeroSesssion;
688 sessionDownload = zeroSesssion;
690 //-----------------------------------------------------------------------------
691 void USER_IMPL::PrintUser() const
694 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
695 std::cout << "============================================================" << std::endl;
696 std::cout << "id=" << id << std::endl;
697 std::cout << "login=" << login << std::endl;
698 std::cout << "password=" << password << std::endl;
699 std::cout << "passive=" << passive << std::endl;
700 std::cout << "disabled=" << disabled << std::endl;
701 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
702 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
703 std::cout << "tariffName=" << tariffName << std::endl;
704 std::cout << "address=" << address << std::endl;
705 std::cout << "phone=" << phone << std::endl;
706 std::cout << "email=" << email << std::endl;
707 std::cout << "note=" << note << std::endl;
708 std::cout << "realName=" <<realName << std::endl;
709 std::cout << "group=" << group << std::endl;
710 std::cout << "credit=" << credit << std::endl;
711 std::cout << "nextTariff=" << nextTariff << std::endl;
712 std::cout << "userdata0" << userdata0 << std::endl;
713 std::cout << "userdata1" << userdata1 << std::endl;
714 std::cout << "creditExpire=" << creditExpire << std::endl;
715 std::cout << "ips=" << ips << std::endl;
716 std::cout << "------------------------" << std::endl;
717 std::cout << "up=" << up << std::endl;
718 std::cout << "down=" << down << std::endl;
719 std::cout << "cash=" << cash << std::endl;
720 std::cout << "freeMb=" << freeMb << std::endl;
721 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
722 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
723 std::cout << "passiveTime=" << passiveTime << std::endl;
724 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
725 std::cout << "============================================================" << std::endl;
727 //-----------------------------------------------------------------------------
728 void USER_IMPL::Run()
730 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
732 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
734 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
737 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
739 WriteServLog("User: %s. Credit expired.", login.c_str());
745 if (passive.ConstData()
746 && (stgTime % 30 == 0)
747 && (passiveTime.ModificationTime() != stgTime))
749 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
750 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
753 if (!authorizedBy.empty())
757 property.Stat().lastActivityTime = stgTime;
759 if (!connected && IsInetable())
763 if (connected && !IsInetable())
766 Disconnect(false, "disabled");
768 Disconnect(false, "passive");
770 Disconnect(false, "no cash");
773 if (stgTime - lastScanMessages > 10)
776 lastScanMessages = stgTime;
783 Disconnect(false, "not authorized");
788 //-----------------------------------------------------------------------------
789 void USER_IMPL::UpdatePingTime(time_t t)
791 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
792 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
798 //-----------------------------------------------------------------------------
799 bool USER_IMPL::IsInetable()
801 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
803 if (disabled || passive)
806 if (settings->GetFreeMbAllowInet())
812 if (settings->GetShowFeeInCash() || tariff == NULL)
814 return (cash >= -credit);
817 return (cash - tariff->GetFee() >= -credit);
819 //-----------------------------------------------------------------------------
820 std::string USER_IMPL::GetEnabledDirs()
822 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
824 std::string dirs = "";
825 for(int i = 0; i < DIR_NUM; i++)
826 dirs += enabledDirs[i] ? "1" : "0";
829 //-----------------------------------------------------------------------------
830 #ifdef TRAFF_STAT_WITH_PORTS
831 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
833 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
836 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
838 if (!connected || tariff == NULL)
844 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
845 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
849 int tt = tariff->GetTraffType();
850 if (tt == TRAFF_UP ||
851 tt == TRAFF_UP_DOWN ||
852 // Check NEW traff data
853 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
856 if (traff < threshold &&
857 traff + len >= threshold)
859 // cash = partBeforeThreshold * priceBeforeThreshold +
860 // partAfterThreshold * priceAfterThreshold
861 int64_t before = threshold - traff; // Chunk part before threshold
862 int64_t after = len - before; // Chunk part after threshold
863 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
864 down.ConstData()[dir],
867 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
868 down.ConstData()[dir],
874 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
875 down.ConstData()[dir],
880 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
882 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
883 cost = dc - freeMb.ConstData();
885 // Direct access to internal data structures via friend-specifier
886 property.Stat().freeMb -= dc;
887 property.Stat().cash -= cost;
893 sessionUpload[dir] += len;
897 if (!settings->GetWriteFreeMbTraffCost() &&
898 freeMb.ConstData() >= 0)
901 #ifdef TRAFF_STAT_WITH_PORTS
902 IP_DIR_PAIR idp(ip, dir, port);
904 IP_DIR_PAIR idp(ip, dir);
907 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
908 lb = traffStat.lower_bound(idp);
909 if (lb == traffStat.end() || lb->first != idp)
913 STAT_NODE(len, 0, cost)));
917 lb->second.cash += cost;
918 lb->second.up += len;
921 //-----------------------------------------------------------------------------
922 #ifdef TRAFF_STAT_WITH_PORTS
923 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
925 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
928 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
930 if (!connected || tariff == NULL)
936 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
937 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
941 int tt = tariff->GetTraffType();
942 if (tt == TRAFF_DOWN ||
943 tt == TRAFF_UP_DOWN ||
944 // Check NEW traff data
945 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
948 if (traff < threshold &&
949 traff + len >= threshold)
951 // cash = partBeforeThreshold * priceBeforeThreshold +
952 // partAfterThreshold * priceAfterThreshold
953 int64_t before = threshold - traff; // Chunk part before threshold
954 int64_t after = len - before; // Chunk part after threshold
955 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
956 down.ConstData()[dir], // Traff before chunk
959 tariff->GetPriceWithTraffType(up.ConstData()[dir],
960 dt[dir], // Traff after chunk
966 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
967 down.ConstData()[dir],
972 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
974 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
975 cost = dc - freeMb.ConstData();
977 property.Stat().freeMb -= dc;
978 property.Stat().cash -= cost;
984 sessionDownload[dir] += len;
988 if (!settings->GetWriteFreeMbTraffCost() &&
989 freeMb.ConstData() >= 0)
992 #ifdef TRAFF_STAT_WITH_PORTS
993 IP_DIR_PAIR idp(ip, dir, port);
995 IP_DIR_PAIR idp(ip, dir);
998 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
999 lb = traffStat.lower_bound(idp);
1000 if (lb == traffStat.end() || lb->first != idp)
1002 traffStat.insert(lb,
1004 STAT_NODE(0, len, cost)));
1008 lb->second.cash += cost;
1009 lb->second.down += len;
1012 //-----------------------------------------------------------------------------
1013 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1015 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1016 currIP.AddBeforeNotifier(notifier);
1018 //-----------------------------------------------------------------------------
1019 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1021 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1022 currIP.DelBeforeNotifier(notifier);
1024 //-----------------------------------------------------------------------------
1025 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1027 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1028 currIP.AddAfterNotifier(notifier);
1030 //-----------------------------------------------------------------------------
1031 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1033 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1034 currIP.DelAfterNotifier(notifier);
1036 //-----------------------------------------------------------------------------
1037 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1039 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1040 connected.AddBeforeNotifier(notifier);
1042 //-----------------------------------------------------------------------------
1043 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1045 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1046 connected.DelBeforeNotifier(notifier);
1048 //-----------------------------------------------------------------------------
1049 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1051 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1052 connected.AddAfterNotifier(notifier);
1054 //-----------------------------------------------------------------------------
1055 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1057 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1058 connected.DelAfterNotifier(notifier);
1060 //-----------------------------------------------------------------------------
1061 void USER_IMPL::OnAdd()
1063 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1065 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1067 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1069 std::string scriptOnAddParams;
1070 strprintf(&scriptOnAddParams,
1072 scriptOnAdd.c_str(),
1075 ScriptExec(scriptOnAddParams.c_str());
1079 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1082 //-----------------------------------------------------------------------------
1083 void USER_IMPL::OnDelete()
1085 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1087 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1089 if (access(scriptOnDel.c_str(), X_OK) == 0)
1091 std::string scriptOnDelParams;
1092 strprintf(&scriptOnDelParams,
1094 scriptOnDel.c_str(),
1097 ScriptExec(scriptOnDelParams.c_str());
1101 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1106 //-----------------------------------------------------------------------------
1107 int USER_IMPL::WriteDetailStat(bool hard)
1109 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1111 if (!traffStatSaved.second.empty())
1113 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1115 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1116 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1117 WriteServLog("%s", store->GetStrError().c_str());
1120 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1126 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1130 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1132 if (ts.size() && !disabledDetailStat)
1134 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1136 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1137 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1138 WriteServLog("%s", store->GetStrError().c_str());
1141 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1142 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1143 traffStatSaved.second.swap(ts);
1144 traffStatSaved.first = lastWriteDetailedStat;
1149 lastWriteDetailedStat = stgTime;
1152 //-----------------------------------------------------------------------------
1153 double USER_IMPL::GetPassiveTimePart() const
1155 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1157 static int daysInMonth[12] =
1158 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1162 localtime_r(&t, &tms);
1164 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1166 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1169 secMonth += 24 * 3600;
1172 time_t dt = secMonth - passiveTime;
1177 return static_cast<double>(dt) / secMonth;
1179 //-----------------------------------------------------------------------------
1180 void USER_IMPL::SetPassiveTimeAsNewUser()
1182 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1186 localtime_r(&t, &tm);
1187 int daysCurrMon = DaysInCurrentMonth();
1188 double pt = tm.tm_mday - 1;
1191 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1193 //-----------------------------------------------------------------------------
1194 void USER_IMPL::MidnightResetSessionStat()
1196 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1200 Disconnect(true, "fake");
1204 //-----------------------------------------------------------------------------
1205 void USER_IMPL::ProcessNewMonth()
1207 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1211 Disconnect(true, "fake");
1213 DIR_TRAFF zeroTarff;
1226 if (nextTariff.ConstData() != "")
1229 nt = tariffs->FindByName(nextTariff);
1232 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1233 login.c_str(), property.tariffName.Get().c_str());
1237 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1244 //-----------------------------------------------------------------------------
1245 void USER_IMPL::ProcessDayFeeSpread()
1247 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1249 if (passive.ConstData() || tariff == NULL)
1252 double fee = tariff->GetFee() / DaysInCurrentMonth();
1254 if (std::fabs(fee) < 1.0e-3)
1258 switch (settings->GetFeeChargeType())
1261 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1264 if (c + credit >= 0)
1265 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1268 if (c + credit >= fee)
1269 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1273 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1278 //-----------------------------------------------------------------------------
1279 void USER_IMPL::ProcessDayFee()
1281 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1286 double passiveTimePart = 1.0;
1287 if (!settings->GetFullFee())
1289 passiveTimePart = GetPassiveTimePart();
1293 if (passive.ConstData())
1295 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1299 double fee = tariff->GetFee() * passiveTimePart;
1303 if (std::fabs(fee) < 1.0e-3)
1310 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1317 switch (settings->GetFeeChargeType())
1320 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1324 if (c + credit >= 0)
1326 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1331 if (c + credit >= fee)
1333 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1340 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1346 //-----------------------------------------------------------------------------
1347 void USER_IMPL::SetPrepaidTraff()
1350 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1352 //-----------------------------------------------------------------------------
1353 int USER_IMPL::AddMessage(STG_MSG * msg)
1355 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1357 if (SendMessage(*msg))
1359 if (store->AddMessage(msg, login))
1361 errorStr = store->GetStrError();
1362 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1363 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1366 messages.push_back(*msg);
1370 if (msg->header.repeat > 0)
1372 msg->header.repeat--;
1374 //TODO: gcc v. 4.x generate ICE on x86_64
1375 msg->header.lastSendTime = static_cast<int>(time(NULL));
1377 msg->header.lastSendTime = static_cast<int>(stgTime);
1379 if (store->AddMessage(msg, login))
1381 errorStr = store->GetStrError();
1382 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1383 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1386 messages.push_back(*msg);
1391 //-----------------------------------------------------------------------------
1392 int USER_IMPL::SendMessage(STG_MSG & msg) const
1394 // No lock `cause we are already locked from caller
1396 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1397 while (it != authorizedBy.end())
1399 if (!(*it++)->SendMessage(msg, currIP))
1405 //TODO: gcc v. 4.x generate ICE on x86_64
1406 msg.header.lastSendTime = static_cast<int>(time(NULL));
1408 msg.header.lastSendTime = static_cast<int>(stgTime);
1410 msg.header.repeat--;
1414 //-----------------------------------------------------------------------------
1415 void USER_IMPL::ScanMessage()
1417 // No lock `cause we are already locked from caller
1418 // We need not check for the authorizedBy `cause it has already checked by caller
1420 std::list<STG_MSG>::iterator it(messages.begin());
1421 while (it != messages.end())
1423 if (settings->GetMessageTimeout() > 0 &&
1424 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1427 if (store->DelMessage(it->header.id, login))
1429 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1430 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1432 messages.erase(it++);
1435 if (it->GetNextSendTime() <= stgTime)
1437 if (SendMessage(*it))
1439 // We need to check all messages in queue for timeout
1443 if (it->header.repeat < 0)
1445 if (store->DelMessage(it->header.id, login))
1447 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1448 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1450 messages.erase(it++);
1454 if (store->EditMessage(*it, login))
1456 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1457 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1468 //-----------------------------------------------------------------------------
1469 //-----------------------------------------------------------------------------
1470 //-----------------------------------------------------------------------------
1471 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1473 if (newPassive && !oldPassive && user->tariff != NULL)
1474 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1480 //-----------------------------------------------------------------------------
1481 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1483 if (oldValue && !newValue && user->GetConnected())
1485 user->Disconnect(false, "disabled");
1487 else if (!oldValue && newValue && user->IsInetable())
1489 user->Connect(false);
1493 //-----------------------------------------------------------------------------
1494 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1496 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1497 user->Disconnect(false, "Change tariff");
1498 user->tariff = user->tariffs->FindByName(newTariff);
1499 if (user->settings->GetReconnectOnTariffChange() &&
1500 !user->authorizedBy.empty() &&
1502 user->Connect(false);
1504 //-----------------------------------------------------------------------------
1505 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1507 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1508 user->lastCashAdd = newCash - oldCash;
1510 //-----------------------------------------------------------------------------
1511 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1513 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1514 if (user->connected)
1515 user->Disconnect(false, "Change IP");
1516 if (!user->authorizedBy.empty() && user->IsInetable())
1517 user->Connect(false);
1519 //-----------------------------------------------------------------------------