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
41 #include "stg/users.h"
42 #include "stg/common.h"
43 #include "stg/scriptexecuter.h"
44 #include "stg/tariff.h"
45 #include "stg/tariffs.h"
46 #include "stg/admin.h"
47 #include "user_impl.h"
48 #include "settings_impl.h"
50 #ifdef USE_ABSTRACT_SETTINGS
51 USER_IMPL::USER_IMPL(const SETTINGS * s,
57 property(s->GetScriptsDir()),
58 WriteServLog(GetStgLogger()),
62 connected(__connected),
66 lastIPForDisconnect(0),
71 tariff(tariffs->GetNoTariff()),
75 lastCashAdd(property.lastCashAdd),
76 passiveTime(property.passiveTime),
77 lastCashAddTime(property.lastCashAddTime),
78 freeMb(property.freeMb),
79 lastActivityTime(property.lastActivityTime),
80 password(property.password),
81 passive(property.passive),
82 disabled(property.disabled),
83 disabledDetailStat(property.disabledDetailStat),
84 alwaysOnline(property.alwaysOnline),
85 tariffName(property.tariffName),
86 nextTariff(property.nextTariff),
87 address(property.address),
89 group(property.group),
90 email(property.email),
91 phone(property.phone),
92 realName(property.realName),
93 credit(property.credit),
94 creditExpire(property.creditExpire),
96 userdata0(property.userdata0),
97 userdata1(property.userdata1),
98 userdata2(property.userdata2),
99 userdata3(property.userdata3),
100 userdata4(property.userdata4),
101 userdata5(property.userdata5),
102 userdata6(property.userdata6),
103 userdata7(property.userdata7),
104 userdata8(property.userdata8),
105 userdata9(property.userdata9),
106 passiveNotifier(this),
107 tariffNotifier(this),
113 password = "*_EMPTY_PASSWORD_*";
114 tariffName = NO_TARIFF_NAME;
116 tariff = tariffs->GetNoTariff();
119 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
120 lastWriteDetailedStat = stgTime;
122 property.tariffName.AddBeforeNotifier(&tariffNotifier);
123 property.passive.AddBeforeNotifier(&passiveNotifier);
124 property.cash.AddBeforeNotifier(&cashNotifier);
125 ips.AddAfterNotifier(&ipNotifier);
127 lastScanMessages = 0;
129 pthread_mutexattr_t attr;
130 pthread_mutexattr_init(&attr);
131 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
132 pthread_mutex_init(&mutex, &attr);
135 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
141 property(s->GetScriptsDir()),
142 WriteServLog(GetStgLogger()),
146 connected(__connected),
150 lastIPForDisconnect(0),
155 tariff(tariffs->GetNoTariff()),
159 lastCashAdd(property.lastCashAdd),
160 passiveTime(property.passiveTime),
161 lastCashAddTime(property.lastCashAddTime),
162 freeMb(property.freeMb),
163 lastActivityTime(property.lastActivityTime),
164 password(property.password),
165 passive(property.passive),
166 disabled(property.disabled),
167 disabledDetailStat(property.disabledDetailStat),
168 alwaysOnline(property.alwaysOnline),
169 tariffName(property.tariffName),
170 nextTariff(property.nextTariff),
171 address(property.address),
173 group(property.group),
174 email(property.email),
175 phone(property.phone),
176 realName(property.realName),
177 credit(property.credit),
178 creditExpire(property.creditExpire),
180 userdata0(property.userdata0),
181 userdata1(property.userdata1),
182 userdata2(property.userdata2),
183 userdata3(property.userdata3),
184 userdata4(property.userdata4),
185 userdata5(property.userdata5),
186 userdata6(property.userdata6),
187 userdata7(property.userdata7),
188 userdata8(property.userdata8),
189 userdata9(property.userdata9),
190 passiveNotifier(this),
191 tariffNotifier(this),
197 password = "*_EMPTY_PASSWORD_*";
198 tariffName = NO_TARIFF_NAME;
200 tariff = tariffs->GetNoTariff();
203 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
204 lastWriteDetailedStat = stgTime;
206 property.tariffName.AddBeforeNotifier(&tariffNotifier);
207 property.passive.AddBeforeNotifier(&passiveNotifier);
208 property.cash.AddBeforeNotifier(&cashNotifier);
209 ips.AddAfterNotifier(&ipNotifier);
211 lastScanMessages = 0;
213 pthread_mutexattr_t attr;
214 pthread_mutexattr_init(&attr);
215 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
216 pthread_mutex_init(&mutex, &attr);
219 //-----------------------------------------------------------------------------
220 USER_IMPL::USER_IMPL(const USER_IMPL & u)
222 property(u.settings->GetScriptsDir()),
223 WriteServLog(GetStgLogger()),
226 __connected(u.__connected),
227 connected(__connected),
228 __currIP(u.__currIP),
230 lastIPForDisconnect(0),
231 pingTime(u.pingTime),
232 sysAdmin(u.sysAdmin),
239 lastCashAdd(property.lastCashAdd),
240 passiveTime(property.passiveTime),
241 lastCashAddTime(property.lastCashAddTime),
242 freeMb(property.freeMb),
243 lastActivityTime(property.lastActivityTime),
244 password(property.password),
245 passive(property.passive),
246 disabled(property.disabled),
247 disabledDetailStat(property.disabledDetailStat),
248 alwaysOnline(property.alwaysOnline),
249 tariffName(property.tariffName),
250 nextTariff(property.nextTariff),
251 address(property.address),
253 group(property.group),
254 email(property.email),
255 phone(property.phone),
256 realName(property.realName),
257 credit(property.credit),
258 creditExpire(property.creditExpire),
260 userdata0(property.userdata0),
261 userdata1(property.userdata1),
262 userdata2(property.userdata2),
263 userdata3(property.userdata3),
264 userdata4(property.userdata4),
265 userdata5(property.userdata5),
266 userdata6(property.userdata6),
267 userdata7(property.userdata7),
268 userdata8(property.userdata8),
269 userdata9(property.userdata9),
270 passiveNotifier(this),
271 tariffNotifier(this),
282 lastWriteStat = u.lastWriteStat;
283 lastWriteDetailedStat = u.lastWriteDetailedStat;
285 settings = u.settings;
287 property.tariffName.AddBeforeNotifier(&tariffNotifier);
288 property.passive.AddBeforeNotifier(&passiveNotifier);
289 property.cash.AddBeforeNotifier(&cashNotifier);
290 ips.AddAfterNotifier(&ipNotifier);
292 lastScanMessages = 0;
294 property.SetProperties(u.property);
296 pthread_mutexattr_t attr;
297 pthread_mutexattr_init(&attr);
298 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
299 pthread_mutex_init(&mutex, &attr);
301 //-----------------------------------------------------------------------------
302 USER_IMPL::~USER_IMPL()
304 property.passive.DelBeforeNotifier(&passiveNotifier);
305 property.tariffName.DelBeforeNotifier(&tariffNotifier);
306 pthread_mutex_destroy(&mutex);
308 //-----------------------------------------------------------------------------
309 void USER_IMPL::SetLogin(string const & l)
311 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
312 assert(login.empty() && "Login is already set");
314 id = userIDGenerator.GetNextID();
316 //-----------------------------------------------------------------------------
317 int USER_IMPL::ReadConf()
319 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
322 if (store->RestoreUserConf(&conf, login))
324 WriteServLog("Cannot read conf for user %s.", login.c_str());
325 WriteServLog("%s", store->GetStrError().c_str());
326 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
327 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
331 property.SetConf(conf);
333 tariff = tariffs->FindByName(tariffName);
336 WriteServLog("Cannot read user %s. Tariff %s not exist.",
337 login.c_str(), property.tariffName.Get().c_str());
341 std::vector<STG_MSG_HDR> hdrsList;
343 if (store->GetMessageHdrs(&hdrsList, login))
345 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
349 std::vector<STG_MSG_HDR>::const_iterator it;
350 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
353 if (store->GetMessage(it->id, &msg, login) == 0)
355 messages.push_back(msg);
361 //-----------------------------------------------------------------------------
362 int USER_IMPL::ReadStat()
364 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
367 if (store->RestoreUserStat(&stat, login))
369 WriteServLog("Cannot read stat for user %s.", login.c_str());
370 WriteServLog("%s", store->GetStrError().c_str());
371 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
372 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
376 property.SetStat(stat);
380 //-----------------------------------------------------------------------------
381 int USER_IMPL::WriteConf()
383 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
384 USER_CONF conf(property.GetConf());
386 printfd(__FILE__, "USER::WriteConf()\n");
388 if (store->SaveUserConf(conf, login))
390 WriteServLog("Cannot write conf for user %s.", login.c_str());
391 WriteServLog("%s", store->GetStrError().c_str());
392 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
393 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
399 //-----------------------------------------------------------------------------
400 int USER_IMPL::WriteStat()
402 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
403 USER_STAT stat(property.GetStat());
405 if (store->SaveUserStat(stat, login))
407 WriteServLog("Cannot write stat for user %s.", login.c_str());
408 WriteServLog("%s", store->GetStrError().c_str());
409 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
410 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
414 lastWriteStat = stgTime;
418 //-----------------------------------------------------------------------------
419 int USER_IMPL::WriteMonthStat()
421 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
422 time_t tt = stgTime - 3600;
424 localtime_r(&tt, &t1);
426 USER_STAT stat(property.GetStat());
427 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
429 WriteServLog("Cannot write month stat for user %s.", login.c_str());
430 WriteServLog("%s", store->GetStrError().c_str());
431 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
432 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
438 //-----------------------------------------------------------------------------
439 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
441 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
443 * Authorize user. It only means that user will be authorized. Nothing more.
444 * User can be connected or disconnected while authorized.
445 * Example: user is authorized but disconnected due to 0 money or blocking
449 * Prevent double authorization by identical authorizers
451 if (authorizedBy.find(auth) != authorizedBy.end())
457 for (int i = 0; i < DIR_NUM; i++)
459 enabledDirs[i] = dirs & (1 << i);
462 if (authorizedBy.size())
466 // We are already authorized, but with different IP address
467 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
472 if (!users->FindByIPIdx(ip, &u))
474 // Address is already present in IP-index
475 // If it's not our IP - throw an error
478 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
485 if (users->IsIPInIndex(ip))
487 // Address is already present in IP-index
488 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
492 if (ips.ConstData().IsIPInIPS(ip))
495 lastIPForDisconnect = currIP;
499 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
500 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
505 authorizedBy.insert(auth);
511 //-----------------------------------------------------------------------------
512 void USER_IMPL::Unauthorize(const AUTH * auth)
514 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
516 * Authorizer tries to unauthorize user, that was not authorized by it
518 if (!authorizedBy.erase(auth))
521 if (authorizedBy.empty())
523 lastIPForDisconnect = currIP;
524 currIP = 0; // DelUser in traffcounter
528 //-----------------------------------------------------------------------------
529 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
531 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
532 // Is this user authorized by specified authorizer?
533 return authorizedBy.find(auth) != authorizedBy.end();
535 //-----------------------------------------------------------------------------
536 void USER_IMPL::Connect(bool fakeConnect)
539 * Connect user to Internet. This function is differ from Authorize() !!!
542 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
546 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
548 if (access(scriptOnConnect.c_str(), X_OK) == 0)
550 char dirsStr[DIR_NUM + 1];
551 dirsStr[DIR_NUM] = 0;
552 for (int i = 0; i < DIR_NUM; i++)
554 dirsStr[i] = enabledDirs[i] ? '1' : '0';
557 string scriptOnConnectParams;
558 strprintf(&scriptOnConnectParams,
559 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
560 scriptOnConnect.c_str(),
562 inet_ntostring(currIP).c_str(),
567 ScriptExec(scriptOnConnectParams);
571 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
577 if (store->WriteUserConnect(login, currIP))
579 WriteServLog("Cannot write connect for user %s.", login.c_str());
580 WriteServLog("%s", store->GetStrError().c_str());
584 lastIPForDisconnect = currIP;
586 //-----------------------------------------------------------------------------
587 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
590 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
593 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
595 if (!lastIPForDisconnect)
597 printfd(__FILE__, "lastIPForDisconnect\n");
603 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
605 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
607 char dirsStr[DIR_NUM + 1];
608 dirsStr[DIR_NUM] = 0;
609 for (int i = 0; i < DIR_NUM; i++)
611 dirsStr[i] = enabledDirs[i] ? '1' : '0';
614 string scriptOnDisonnectParams;
615 strprintf(&scriptOnDisonnectParams,
616 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
617 scriptOnDisonnect.c_str(),
619 inet_ntostring(lastIPForDisconnect).c_str(),
624 ScriptExec(scriptOnDisonnectParams);
628 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
634 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
636 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
637 WriteServLog("%s", store->GetStrError().c_str());
641 lastIPForDisconnect = 0;
643 DIR_TRAFF zeroSesssion;
645 sessionUpload = zeroSesssion;
646 sessionDownload = zeroSesssion;
648 //-----------------------------------------------------------------------------
649 void USER_IMPL::PrintUser() const
652 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
653 cout << "============================================================" << endl;
654 cout << "id=" << id << endl;
655 cout << "login=" << login << endl;
656 cout << "password=" << password << endl;
657 cout << "passive=" << passive << endl;
658 cout << "disabled=" << disabled << endl;
659 cout << "disabledDetailStat=" << disabledDetailStat << endl;
660 cout << "alwaysOnline=" << alwaysOnline << endl;
661 cout << "tariffName=" << tariffName << endl;
662 cout << "address=" << address << endl;
663 cout << "phone=" << phone << endl;
664 cout << "email=" << email << endl;
665 cout << "note=" << note << endl;
666 cout << "realName=" <<realName << endl;
667 cout << "group=" << group << endl;
668 cout << "credit=" << credit << endl;
669 cout << "nextTariff=" << nextTariff << endl;
670 cout << "userdata0" << userdata0 << endl;
671 cout << "userdata1" << userdata1 << endl;
672 cout << "creditExpire=" << creditExpire << endl;
673 cout << "ips=" << ips << endl;
674 cout << "------------------------" << endl;
675 cout << "up=" << up << endl;
676 cout << "down=" << down << endl;
677 cout << "cash=" << cash << endl;
678 cout << "freeMb=" << freeMb << endl;
679 cout << "lastCashAdd=" << lastCashAdd << endl;
680 cout << "lastCashAddTime=" << lastCashAddTime << endl;
681 cout << "passiveTime=" << passiveTime << endl;
682 cout << "lastActivityTime=" << lastActivityTime << endl;
683 cout << "============================================================" << endl;
685 //-----------------------------------------------------------------------------
686 void USER_IMPL::Run()
688 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
690 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
692 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
695 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
697 WriteServLog("User: %s. Credit expired.", login.c_str());
703 if (passive.ConstData()
704 && (stgTime % 30 == 0)
705 && (passiveTime.ModificationTime() != stgTime))
707 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
708 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
711 if (!authorizedBy.empty())
715 property.Stat().lastActivityTime = stgTime;
717 if (!connected && IsInetable())
721 if (connected && !IsInetable())
724 Disconnect(false, "disabled");
726 Disconnect(false, "passive");
728 Disconnect(false, "no cash");
731 if (stgTime - lastScanMessages > 10)
734 lastScanMessages = stgTime;
741 Disconnect(false, "not authorized");
746 //-----------------------------------------------------------------------------
747 void USER_IMPL::UpdatePingTime(time_t t)
749 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
750 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
756 //-----------------------------------------------------------------------------
757 bool USER_IMPL::IsInetable()
759 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
761 if (disabled || passive)
764 if (settings->GetFreeMbAllowInet())
770 if (settings->GetShowFeeInCash())
772 return (cash >= -credit);
775 return (cash - tariff->GetFee() >= -credit);
777 //-----------------------------------------------------------------------------
778 string USER_IMPL::GetEnabledDirs()
780 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
783 for(int i = 0; i < DIR_NUM; i++)
784 dirs += enabledDirs[i] ? "1" : "0";
787 //-----------------------------------------------------------------------------
788 #ifdef TRAFF_STAT_WITH_PORTS
789 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
791 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
794 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
802 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
803 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
807 int tt = tariff->GetTraffType();
808 if (tt == TRAFF_UP ||
809 tt == TRAFF_UP_DOWN ||
810 // Check NEW traff data
811 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
814 if (traff < threshold &&
815 traff + len >= threshold)
817 // cash = partBeforeThreshold * priceBeforeThreshold +
818 // partAfterThreshold * priceAfterThreshold
819 int64_t before = threshold - traff; // Chunk part before threshold
820 int64_t after = len - before; // Chunk part after threshold
821 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
822 down.ConstData()[dir],
825 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
826 down.ConstData()[dir],
832 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
833 down.ConstData()[dir],
838 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
840 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
841 cost = dc - freeMb.ConstData();
843 // Direct access to internal data structures via friend-specifier
844 property.Stat().freeMb -= dc;
845 property.Stat().cash -= cost;
851 sessionUpload[dir] += len;
855 if (!settings->GetWriteFreeMbTraffCost() &&
856 freeMb.ConstData() >= 0)
859 #ifdef TRAFF_STAT_WITH_PORTS
860 IP_DIR_PAIR idp(ip, dir, port);
862 IP_DIR_PAIR idp(ip, dir);
865 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
866 lb = traffStat.lower_bound(idp);
867 if (lb == traffStat.end() || lb->first != idp)
870 pair<IP_DIR_PAIR, STAT_NODE>(idp,
871 STAT_NODE(len, 0, cost)));
875 lb->second.cash += cost;
876 lb->second.up += len;
879 //-----------------------------------------------------------------------------
880 #ifdef TRAFF_STAT_WITH_PORTS
881 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
883 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
886 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
894 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
895 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
899 int tt = tariff->GetTraffType();
900 if (tt == TRAFF_DOWN ||
901 tt == TRAFF_UP_DOWN ||
902 // Check NEW traff data
903 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
906 if (traff < threshold &&
907 traff + len >= threshold)
909 // cash = partBeforeThreshold * priceBeforeThreshold +
910 // partAfterThreshold * priceAfterThreshold
911 int64_t before = threshold - traff; // Chunk part before threshold
912 int64_t after = len - before; // Chunk part after threshold
913 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
914 down.ConstData()[dir], // Traff before chunk
917 tariff->GetPriceWithTraffType(up.ConstData()[dir],
918 dt[dir], // Traff after chunk
924 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
925 down.ConstData()[dir],
930 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
932 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
933 cost = dc - freeMb.ConstData();
935 property.Stat().freeMb -= dc;
936 property.Stat().cash -= cost;
942 sessionDownload[dir] += len;
946 if (!settings->GetWriteFreeMbTraffCost() &&
947 freeMb.ConstData() >= 0)
950 #ifdef TRAFF_STAT_WITH_PORTS
951 IP_DIR_PAIR idp(ip, dir, port);
953 IP_DIR_PAIR idp(ip, dir);
956 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
957 lb = traffStat.lower_bound(idp);
958 if (lb == traffStat.end() || lb->first != idp)
961 pair<IP_DIR_PAIR, STAT_NODE>(idp,
962 STAT_NODE(0, len, cost)));
966 lb->second.cash += cost;
967 lb->second.down += len;
970 //-----------------------------------------------------------------------------
971 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
973 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
974 currIP.AddBeforeNotifier(n);
976 //-----------------------------------------------------------------------------
977 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
979 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
980 currIP.DelBeforeNotifier(n);
982 //-----------------------------------------------------------------------------
983 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
985 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
986 currIP.AddAfterNotifier(n);
988 //-----------------------------------------------------------------------------
989 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
991 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
992 currIP.DelAfterNotifier(n);
994 //-----------------------------------------------------------------------------
995 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
997 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
998 connected.AddBeforeNotifier(n);
1000 //-----------------------------------------------------------------------------
1001 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1003 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1004 connected.DelBeforeNotifier(n);
1006 //-----------------------------------------------------------------------------
1007 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1009 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1010 connected.AddAfterNotifier(n);
1012 //-----------------------------------------------------------------------------
1013 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
1015 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1016 connected.DelAfterNotifier(n);
1018 //-----------------------------------------------------------------------------
1019 void USER_IMPL::OnAdd()
1021 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1023 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1025 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1027 string scriptOnAddParams;
1028 strprintf(&scriptOnAddParams,
1030 scriptOnAdd.c_str(),
1033 ScriptExec(scriptOnAddParams);
1037 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1040 //-----------------------------------------------------------------------------
1041 void USER_IMPL::OnDelete()
1043 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1045 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1047 if (access(scriptOnDel.c_str(), X_OK) == 0)
1049 string scriptOnDelParams;
1050 strprintf(&scriptOnDelParams,
1052 scriptOnDel.c_str(),
1055 ScriptExec(scriptOnDelParams);
1059 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1064 //-----------------------------------------------------------------------------
1065 int USER_IMPL::WriteDetailStat(bool hard)
1067 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1069 if (!traffStatSaved.second.empty())
1071 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1073 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1074 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1075 WriteServLog("%s", store->GetStrError().c_str());
1078 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1084 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1088 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1090 if (ts.size() && !disabledDetailStat)
1092 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1094 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1095 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1096 WriteServLog("%s", store->GetStrError().c_str());
1099 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1100 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1101 traffStatSaved.second.swap(ts);
1102 traffStatSaved.first = lastWriteDetailedStat;
1107 lastWriteDetailedStat = stgTime;
1110 //-----------------------------------------------------------------------------
1111 double USER_IMPL::GetPassiveTimePart() const
1113 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1115 static int daysInMonth[12] =
1116 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1120 localtime_r(&t, &tms);
1122 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1124 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1127 secMonth += 24 * 3600;
1130 int dt = secMonth - passiveTime;
1135 return double(dt) / (secMonth);
1137 //-----------------------------------------------------------------------------
1138 void USER_IMPL::SetPassiveTimeAsNewUser()
1140 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1144 localtime_r(&t, &tm);
1145 int daysCurrMon = DaysInCurrentMonth();
1146 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1148 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1150 //-----------------------------------------------------------------------------
1151 void USER_IMPL::MidnightResetSessionStat()
1153 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1157 Disconnect(true, "fake");
1161 //-----------------------------------------------------------------------------
1162 void USER_IMPL::ProcessNewMonth()
1164 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1168 Disconnect(true, "fake");
1170 DIR_TRAFF zeroTarff;
1183 if (nextTariff.ConstData() != "")
1186 nt = tariffs->FindByName(nextTariff);
1189 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1190 login.c_str(), property.tariffName.Get().c_str());
1194 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1201 //-----------------------------------------------------------------------------
1202 void USER_IMPL::ProcessDayFeeSpread()
1204 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1206 if (passive.ConstData())
1209 double fee = tariff->GetFee() / DaysInCurrentMonth();
1215 switch (settings->GetFeeChargeType())
1218 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1222 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1226 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1231 //-----------------------------------------------------------------------------
1232 void USER_IMPL::ProcessDayFee()
1234 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1236 double passiveTimePart = 1.0;
1237 if (!settings->GetFullFee())
1239 passiveTimePart = GetPassiveTimePart();
1243 if (passive.ConstData())
1245 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1249 double fee = tariff->GetFee() * passiveTimePart;
1257 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1262 switch (settings->GetFeeChargeType())
1265 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1269 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1273 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1277 //-----------------------------------------------------------------------------
1278 void USER_IMPL::SetPrepaidTraff()
1280 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1282 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1284 //-----------------------------------------------------------------------------
1285 int USER_IMPL::AddMessage(STG_MSG * msg)
1287 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1289 if (SendMessage(*msg))
1291 if (store->AddMessage(msg, login))
1293 errorStr = store->GetStrError();
1294 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1295 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1298 messages.push_back(*msg);
1302 if (msg->header.repeat > 0)
1304 msg->header.repeat--;
1306 //TODO: gcc v. 4.x generate ICE on x86_64
1307 msg->header.lastSendTime = time(NULL);
1309 msg->header.lastSendTime = stgTime;
1311 if (store->AddMessage(msg, login))
1313 errorStr = store->GetStrError();
1314 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1315 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1318 messages.push_back(*msg);
1323 //-----------------------------------------------------------------------------
1324 int USER_IMPL::SendMessage(STG_MSG & msg) const
1326 // No lock `cause we are already locked from caller
1328 set<const AUTH*>::iterator it(authorizedBy.begin());
1329 while (it != authorizedBy.end())
1331 if (!(*it++)->SendMessage(msg, currIP))
1337 //TODO: gcc v. 4.x generate ICE on x86_64
1338 msg.header.lastSendTime = time(NULL);
1340 msg.header.lastSendTime = stgTime;
1342 msg.header.repeat--;
1346 //-----------------------------------------------------------------------------
1347 void USER_IMPL::ScanMessage()
1349 // No lock `cause we are already locked from caller
1350 // We need not check for the authorizedBy `cause it has already checked by caller
1352 std::list<STG_MSG>::iterator it(messages.begin());
1353 while (it != messages.end())
1355 if (settings->GetMessageTimeout() > 0 &&
1356 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1359 if (store->DelMessage(it->header.id, login))
1361 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1362 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1364 messages.erase(it++);
1367 if (it->GetNextSendTime() <= stgTime)
1369 if (SendMessage(*it))
1371 // We need to check all messages in queue for timeout
1375 if (it->header.repeat < 0)
1377 if (store->DelMessage(it->header.id, login))
1379 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1380 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1382 messages.erase(it++);
1386 if (store->EditMessage(*it, login))
1388 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1389 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1400 //-----------------------------------------------------------------------------
1401 //-----------------------------------------------------------------------------
1402 //-----------------------------------------------------------------------------
1403 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1405 if (newPassive && !oldPassive)
1406 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1412 //-----------------------------------------------------------------------------
1413 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1415 user->tariff = user->tariffs->FindByName(newTariff);
1417 //-----------------------------------------------------------------------------
1418 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1420 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1421 user->lastCashAdd = newCash - oldCash;
1423 //-----------------------------------------------------------------------------
1424 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1426 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1427 if (user->connected)
1428 user->Disconnect(true, "Change IP");
1429 if (user->IsInetable())
1430 user->Connect(true);
1432 //-----------------------------------------------------------------------------