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(string const & 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 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 string scriptOnConnectParams;
591 strprintf(&scriptOnConnectParams,
592 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
593 scriptOnConnect.c_str(),
595 inet_ntostring(currIP).c_str(),
600 ScriptExec(scriptOnConnectParams.c_str());
604 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
610 if (store->WriteUserConnect(login, currIP))
612 WriteServLog("Cannot write connect for user %s.", login.c_str());
613 WriteServLog("%s", store->GetStrError().c_str());
617 lastIPForDisconnect = currIP;
619 //-----------------------------------------------------------------------------
620 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
623 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
626 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
628 if (!lastIPForDisconnect)
630 printfd(__FILE__, "lastIPForDisconnect\n");
636 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 string scriptOnDisonnectParams;
648 strprintf(&scriptOnDisonnectParams,
649 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
650 scriptOnDisonnect.c_str(),
652 inet_ntostring(lastIPForDisconnect).c_str(),
657 ScriptExec(scriptOnDisonnectParams.c_str());
661 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
667 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
669 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
670 WriteServLog("%s", store->GetStrError().c_str());
674 lastIPForDisconnect = 0;
676 DIR_TRAFF zeroSesssion;
678 sessionUpload = zeroSesssion;
679 sessionDownload = zeroSesssion;
681 //-----------------------------------------------------------------------------
682 void USER_IMPL::PrintUser() const
685 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
686 cout << "============================================================" << endl;
687 cout << "id=" << id << endl;
688 cout << "login=" << login << endl;
689 cout << "password=" << password << endl;
690 cout << "passive=" << passive << endl;
691 cout << "disabled=" << disabled << endl;
692 cout << "disabledDetailStat=" << disabledDetailStat << endl;
693 cout << "alwaysOnline=" << alwaysOnline << endl;
694 cout << "tariffName=" << tariffName << endl;
695 cout << "address=" << address << endl;
696 cout << "phone=" << phone << endl;
697 cout << "email=" << email << endl;
698 cout << "note=" << note << endl;
699 cout << "realName=" <<realName << endl;
700 cout << "group=" << group << endl;
701 cout << "credit=" << credit << endl;
702 cout << "nextTariff=" << nextTariff << endl;
703 cout << "userdata0" << userdata0 << endl;
704 cout << "userdata1" << userdata1 << endl;
705 cout << "creditExpire=" << creditExpire << endl;
706 cout << "ips=" << ips << endl;
707 cout << "------------------------" << endl;
708 cout << "up=" << up << endl;
709 cout << "down=" << down << endl;
710 cout << "cash=" << cash << endl;
711 cout << "freeMb=" << freeMb << endl;
712 cout << "lastCashAdd=" << lastCashAdd << endl;
713 cout << "lastCashAddTime=" << lastCashAddTime << endl;
714 cout << "passiveTime=" << passiveTime << endl;
715 cout << "lastActivityTime=" << lastActivityTime << endl;
716 cout << "============================================================" << endl;
718 //-----------------------------------------------------------------------------
719 void USER_IMPL::Run()
721 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
723 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
725 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
728 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
730 WriteServLog("User: %s. Credit expired.", login.c_str());
736 if (passive.ConstData()
737 && (stgTime % 30 == 0)
738 && (passiveTime.ModificationTime() != stgTime))
740 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
741 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
744 if (!authorizedBy.empty())
748 property.Stat().lastActivityTime = stgTime;
750 if (!connected && IsInetable())
754 if (connected && !IsInetable())
757 Disconnect(false, "disabled");
759 Disconnect(false, "passive");
761 Disconnect(false, "no cash");
764 if (stgTime - lastScanMessages > 10)
767 lastScanMessages = stgTime;
774 Disconnect(false, "not authorized");
779 //-----------------------------------------------------------------------------
780 void USER_IMPL::UpdatePingTime(time_t t)
782 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
783 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
789 //-----------------------------------------------------------------------------
790 bool USER_IMPL::IsInetable()
792 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
794 if (disabled || passive)
797 if (settings->GetFreeMbAllowInet())
803 if (settings->GetShowFeeInCash() || tariff == NULL)
805 return (cash >= -credit);
808 return (cash - tariff->GetFee() >= -credit);
810 //-----------------------------------------------------------------------------
811 string USER_IMPL::GetEnabledDirs()
813 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
816 for(int i = 0; i < DIR_NUM; i++)
817 dirs += enabledDirs[i] ? "1" : "0";
820 //-----------------------------------------------------------------------------
821 #ifdef TRAFF_STAT_WITH_PORTS
822 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
824 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
827 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
829 if (!connected || tariff == NULL)
835 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
836 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
840 int tt = tariff->GetTraffType();
841 if (tt == TRAFF_UP ||
842 tt == TRAFF_UP_DOWN ||
843 // Check NEW traff data
844 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
847 if (traff < threshold &&
848 traff + len >= threshold)
850 // cash = partBeforeThreshold * priceBeforeThreshold +
851 // partAfterThreshold * priceAfterThreshold
852 int64_t before = threshold - traff; // Chunk part before threshold
853 int64_t after = len - before; // Chunk part after threshold
854 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
855 down.ConstData()[dir],
858 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
859 down.ConstData()[dir],
865 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
866 down.ConstData()[dir],
871 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
873 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
874 cost = dc - freeMb.ConstData();
876 // Direct access to internal data structures via friend-specifier
877 property.Stat().freeMb -= dc;
878 property.Stat().cash -= cost;
884 sessionUpload[dir] += len;
888 if (!settings->GetWriteFreeMbTraffCost() &&
889 freeMb.ConstData() >= 0)
892 #ifdef TRAFF_STAT_WITH_PORTS
893 IP_DIR_PAIR idp(ip, dir, port);
895 IP_DIR_PAIR idp(ip, dir);
898 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
899 lb = traffStat.lower_bound(idp);
900 if (lb == traffStat.end() || lb->first != idp)
903 pair<IP_DIR_PAIR, STAT_NODE>(idp,
904 STAT_NODE(len, 0, cost)));
908 lb->second.cash += cost;
909 lb->second.up += len;
912 //-----------------------------------------------------------------------------
913 #ifdef TRAFF_STAT_WITH_PORTS
914 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
916 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
919 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
921 if (!connected || tariff == NULL)
927 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
928 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
932 int tt = tariff->GetTraffType();
933 if (tt == TRAFF_DOWN ||
934 tt == TRAFF_UP_DOWN ||
935 // Check NEW traff data
936 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
939 if (traff < threshold &&
940 traff + len >= threshold)
942 // cash = partBeforeThreshold * priceBeforeThreshold +
943 // partAfterThreshold * priceAfterThreshold
944 int64_t before = threshold - traff; // Chunk part before threshold
945 int64_t after = len - before; // Chunk part after threshold
946 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
947 down.ConstData()[dir], // Traff before chunk
950 tariff->GetPriceWithTraffType(up.ConstData()[dir],
951 dt[dir], // Traff after chunk
957 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
958 down.ConstData()[dir],
963 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
965 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
966 cost = dc - freeMb.ConstData();
968 property.Stat().freeMb -= dc;
969 property.Stat().cash -= cost;
975 sessionDownload[dir] += len;
979 if (!settings->GetWriteFreeMbTraffCost() &&
980 freeMb.ConstData() >= 0)
983 #ifdef TRAFF_STAT_WITH_PORTS
984 IP_DIR_PAIR idp(ip, dir, port);
986 IP_DIR_PAIR idp(ip, dir);
989 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
990 lb = traffStat.lower_bound(idp);
991 if (lb == traffStat.end() || lb->first != idp)
994 pair<IP_DIR_PAIR, STAT_NODE>(idp,
995 STAT_NODE(0, len, cost)));
999 lb->second.cash += cost;
1000 lb->second.down += len;
1003 //-----------------------------------------------------------------------------
1004 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1006 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1007 currIP.AddBeforeNotifier(notifier);
1009 //-----------------------------------------------------------------------------
1010 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1012 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1013 currIP.DelBeforeNotifier(notifier);
1015 //-----------------------------------------------------------------------------
1016 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1018 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1019 currIP.AddAfterNotifier(notifier);
1021 //-----------------------------------------------------------------------------
1022 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1024 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1025 currIP.DelAfterNotifier(notifier);
1027 //-----------------------------------------------------------------------------
1028 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1030 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1031 connected.AddBeforeNotifier(notifier);
1033 //-----------------------------------------------------------------------------
1034 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1036 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1037 connected.DelBeforeNotifier(notifier);
1039 //-----------------------------------------------------------------------------
1040 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1042 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1043 connected.AddAfterNotifier(notifier);
1045 //-----------------------------------------------------------------------------
1046 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1048 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1049 connected.DelAfterNotifier(notifier);
1051 //-----------------------------------------------------------------------------
1052 void USER_IMPL::OnAdd()
1054 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1056 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1058 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1060 string scriptOnAddParams;
1061 strprintf(&scriptOnAddParams,
1063 scriptOnAdd.c_str(),
1066 ScriptExec(scriptOnAddParams.c_str());
1070 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1073 //-----------------------------------------------------------------------------
1074 void USER_IMPL::OnDelete()
1076 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1078 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1080 if (access(scriptOnDel.c_str(), X_OK) == 0)
1082 string scriptOnDelParams;
1083 strprintf(&scriptOnDelParams,
1085 scriptOnDel.c_str(),
1088 ScriptExec(scriptOnDelParams.c_str());
1092 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1097 //-----------------------------------------------------------------------------
1098 int USER_IMPL::WriteDetailStat(bool hard)
1100 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1102 if (!traffStatSaved.second.empty())
1104 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1106 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1107 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1108 WriteServLog("%s", store->GetStrError().c_str());
1111 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1117 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1121 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1123 if (ts.size() && !disabledDetailStat)
1125 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1127 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1128 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1129 WriteServLog("%s", store->GetStrError().c_str());
1132 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1133 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1134 traffStatSaved.second.swap(ts);
1135 traffStatSaved.first = lastWriteDetailedStat;
1140 lastWriteDetailedStat = stgTime;
1143 //-----------------------------------------------------------------------------
1144 double USER_IMPL::GetPassiveTimePart() const
1146 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1148 static int daysInMonth[12] =
1149 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1153 localtime_r(&t, &tms);
1155 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1157 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1160 secMonth += 24 * 3600;
1163 int dt = secMonth - passiveTime;
1168 return double(dt) / (secMonth);
1170 //-----------------------------------------------------------------------------
1171 void USER_IMPL::SetPassiveTimeAsNewUser()
1173 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1177 localtime_r(&t, &tm);
1178 int daysCurrMon = DaysInCurrentMonth();
1179 double pt = tm.tm_mday - 1;
1182 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1184 //-----------------------------------------------------------------------------
1185 void USER_IMPL::MidnightResetSessionStat()
1187 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1191 Disconnect(true, "fake");
1195 //-----------------------------------------------------------------------------
1196 void USER_IMPL::ProcessNewMonth()
1198 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1202 Disconnect(true, "fake");
1204 DIR_TRAFF zeroTarff;
1217 if (nextTariff.ConstData() != "")
1220 nt = tariffs->FindByName(nextTariff);
1223 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1224 login.c_str(), property.tariffName.Get().c_str());
1228 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1235 //-----------------------------------------------------------------------------
1236 void USER_IMPL::ProcessDayFeeSpread()
1238 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1240 if (passive.ConstData() || tariff == NULL)
1243 double fee = tariff->GetFee() / DaysInCurrentMonth();
1245 if (std::fabs(fee) < 1.0e-3)
1249 switch (settings->GetFeeChargeType())
1252 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1255 if (c + credit >= 0)
1256 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1259 if (c + credit >= fee)
1260 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1264 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1269 //-----------------------------------------------------------------------------
1270 void USER_IMPL::ProcessDayFee()
1272 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1277 double passiveTimePart = 1.0;
1278 if (!settings->GetFullFee())
1280 passiveTimePart = GetPassiveTimePart();
1284 if (passive.ConstData())
1286 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1290 double fee = tariff->GetFee() * passiveTimePart;
1294 if (std::fabs(fee) < 1.0e-3)
1301 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1308 switch (settings->GetFeeChargeType())
1311 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1315 if (c + credit >= 0)
1317 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1322 if (c + credit >= fee)
1324 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1331 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1337 //-----------------------------------------------------------------------------
1338 void USER_IMPL::SetPrepaidTraff()
1341 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1343 //-----------------------------------------------------------------------------
1344 int USER_IMPL::AddMessage(STG_MSG * msg)
1346 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1348 if (SendMessage(*msg))
1350 if (store->AddMessage(msg, login))
1352 errorStr = store->GetStrError();
1353 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1354 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1357 messages.push_back(*msg);
1361 if (msg->header.repeat > 0)
1363 msg->header.repeat--;
1365 //TODO: gcc v. 4.x generate ICE on x86_64
1366 msg->header.lastSendTime = time(NULL);
1368 msg->header.lastSendTime = stgTime;
1370 if (store->AddMessage(msg, login))
1372 errorStr = store->GetStrError();
1373 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1374 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1377 messages.push_back(*msg);
1382 //-----------------------------------------------------------------------------
1383 int USER_IMPL::SendMessage(STG_MSG & msg) const
1385 // No lock `cause we are already locked from caller
1387 set<const AUTH*>::iterator it(authorizedBy.begin());
1388 while (it != authorizedBy.end())
1390 if (!(*it++)->SendMessage(msg, currIP))
1396 //TODO: gcc v. 4.x generate ICE on x86_64
1397 msg.header.lastSendTime = time(NULL);
1399 msg.header.lastSendTime = stgTime;
1401 msg.header.repeat--;
1405 //-----------------------------------------------------------------------------
1406 void USER_IMPL::ScanMessage()
1408 // No lock `cause we are already locked from caller
1409 // We need not check for the authorizedBy `cause it has already checked by caller
1411 std::list<STG_MSG>::iterator it(messages.begin());
1412 while (it != messages.end())
1414 if (settings->GetMessageTimeout() > 0 &&
1415 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1418 if (store->DelMessage(it->header.id, login))
1420 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1421 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1423 messages.erase(it++);
1426 if (it->GetNextSendTime() <= stgTime)
1428 if (SendMessage(*it))
1430 // We need to check all messages in queue for timeout
1434 if (it->header.repeat < 0)
1436 if (store->DelMessage(it->header.id, login))
1438 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1439 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1441 messages.erase(it++);
1445 if (store->EditMessage(*it, login))
1447 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1448 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1459 //-----------------------------------------------------------------------------
1460 //-----------------------------------------------------------------------------
1461 //-----------------------------------------------------------------------------
1462 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1464 if (newPassive && !oldPassive && user->tariff != NULL)
1465 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1471 //-----------------------------------------------------------------------------
1472 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1474 if (oldValue && !newValue && user->GetConnected())
1476 user->Disconnect(false, "disabled");
1478 else if (!oldValue && newValue && user->IsInetable())
1480 user->Connect(false);
1484 //-----------------------------------------------------------------------------
1485 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1487 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1488 user->Disconnect(false, "Change tariff");
1489 user->tariff = user->tariffs->FindByName(newTariff);
1490 if (user->settings->GetReconnectOnTariffChange() &&
1491 !user->authorizedBy.empty() &&
1493 user->Connect(false);
1495 //-----------------------------------------------------------------------------
1496 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1498 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1499 user->lastCashAdd = newCash - oldCash;
1501 //-----------------------------------------------------------------------------
1502 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1504 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1505 if (user->connected)
1506 user->Disconnect(false, "Change IP");
1507 if (!user->authorizedBy.empty() && user->IsInetable())
1508 user->Connect(false);
1510 //-----------------------------------------------------------------------------