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 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
56 property(s->GetScriptsDir()),
57 WriteServLog(GetStgLogger()),
61 connected(__connected),
65 lastIPForDisconnect(0),
70 tariff(tariffs->GetNoTariff()),
74 lastCashAdd(property.lastCashAdd),
75 passiveTime(property.passiveTime),
76 lastCashAddTime(property.lastCashAddTime),
77 freeMb(property.freeMb),
78 lastActivityTime(property.lastActivityTime),
79 password(property.password),
80 passive(property.passive),
81 disabled(property.disabled),
82 disabledDetailStat(property.disabledDetailStat),
83 alwaysOnline(property.alwaysOnline),
84 tariffName(property.tariffName),
85 nextTariff(property.nextTariff),
86 address(property.address),
88 group(property.group),
89 email(property.email),
90 phone(property.phone),
91 realName(property.realName),
92 credit(property.credit),
93 creditExpire(property.creditExpire),
95 userdata0(property.userdata0),
96 userdata1(property.userdata1),
97 userdata2(property.userdata2),
98 userdata3(property.userdata3),
99 userdata4(property.userdata4),
100 userdata5(property.userdata5),
101 userdata6(property.userdata6),
102 userdata7(property.userdata7),
103 userdata8(property.userdata8),
104 userdata9(property.userdata9),
105 passiveNotifier(this),
106 tariffNotifier(this),
112 password = "*_EMPTY_PASSWORD_*";
113 tariffName = NO_TARIFF_NAME;
115 tariff = tariffs->GetNoTariff();
118 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
119 lastWriteDetailedStat = stgTime;
121 property.tariffName.AddBeforeNotifier(&tariffNotifier);
122 property.passive.AddBeforeNotifier(&passiveNotifier);
123 property.cash.AddBeforeNotifier(&cashNotifier);
124 ips.AddAfterNotifier(&ipNotifier);
126 lastScanMessages = 0;
128 pthread_mutexattr_t attr;
129 pthread_mutexattr_init(&attr);
130 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
131 pthread_mutex_init(&mutex, &attr);
133 //-----------------------------------------------------------------------------
134 USER_IMPL::USER_IMPL(const USER_IMPL & u)
136 property(u.settings->GetScriptsDir()),
137 WriteServLog(GetStgLogger()),
140 __connected(u.__connected),
141 connected(__connected),
142 __currIP(u.__currIP),
144 lastIPForDisconnect(0),
145 pingTime(u.pingTime),
146 sysAdmin(u.sysAdmin),
153 lastCashAdd(property.lastCashAdd),
154 passiveTime(property.passiveTime),
155 lastCashAddTime(property.lastCashAddTime),
156 freeMb(property.freeMb),
157 lastActivityTime(property.lastActivityTime),
158 password(property.password),
159 passive(property.passive),
160 disabled(property.disabled),
161 disabledDetailStat(property.disabledDetailStat),
162 alwaysOnline(property.alwaysOnline),
163 tariffName(property.tariffName),
164 nextTariff(property.nextTariff),
165 address(property.address),
167 group(property.group),
168 email(property.email),
169 phone(property.phone),
170 realName(property.realName),
171 credit(property.credit),
172 creditExpire(property.creditExpire),
174 userdata0(property.userdata0),
175 userdata1(property.userdata1),
176 userdata2(property.userdata2),
177 userdata3(property.userdata3),
178 userdata4(property.userdata4),
179 userdata5(property.userdata5),
180 userdata6(property.userdata6),
181 userdata7(property.userdata7),
182 userdata8(property.userdata8),
183 userdata9(property.userdata9),
184 passiveNotifier(this),
185 tariffNotifier(this),
196 lastWriteStat = u.lastWriteStat;
197 lastWriteDetailedStat = u.lastWriteDetailedStat;
199 settings = u.settings;
201 property.tariffName.AddBeforeNotifier(&tariffNotifier);
202 property.passive.AddBeforeNotifier(&passiveNotifier);
203 property.cash.AddBeforeNotifier(&cashNotifier);
204 ips.AddAfterNotifier(&ipNotifier);
206 lastScanMessages = 0;
208 property.SetProperties(u.property);
210 pthread_mutexattr_t attr;
211 pthread_mutexattr_init(&attr);
212 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
213 pthread_mutex_init(&mutex, &attr);
215 //-----------------------------------------------------------------------------
216 USER_IMPL::~USER_IMPL()
218 property.passive.DelBeforeNotifier(&passiveNotifier);
219 property.tariffName.DelBeforeNotifier(&tariffNotifier);
220 pthread_mutex_destroy(&mutex);
222 //-----------------------------------------------------------------------------
223 void USER_IMPL::SetLogin(string const & l)
225 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
226 assert(login.empty() && "Login is already set");
228 id = userIDGenerator.GetNextID();
230 //-----------------------------------------------------------------------------
231 int USER_IMPL::ReadConf()
233 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
236 if (store->RestoreUserConf(&conf, login))
238 WriteServLog("Cannot read conf for user %s.", login.c_str());
239 WriteServLog("%s", store->GetStrError().c_str());
240 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
241 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
245 property.SetConf(conf);
247 tariff = tariffs->FindByName(tariffName);
250 WriteServLog("Cannot read user %s. Tariff %s not exist.",
251 login.c_str(), property.tariffName.Get().c_str());
255 std::vector<STG_MSG_HDR> hdrsList;
257 if (store->GetMessageHdrs(&hdrsList, login))
259 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
263 std::vector<STG_MSG_HDR>::const_iterator it;
264 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
267 if (store->GetMessage(it->id, &msg, login) == 0)
269 messages.push_back(msg);
275 //-----------------------------------------------------------------------------
276 int USER_IMPL::ReadStat()
278 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
281 if (store->RestoreUserStat(&stat, login))
283 WriteServLog("Cannot read stat for user %s.", login.c_str());
284 WriteServLog("%s", store->GetStrError().c_str());
285 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
286 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
290 property.SetStat(stat);
294 //-----------------------------------------------------------------------------
295 int USER_IMPL::WriteConf()
297 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
298 USER_CONF conf(property.GetConf());
300 printfd(__FILE__, "USER::WriteConf()\n");
302 if (store->SaveUserConf(conf, login))
304 WriteServLog("Cannot write conf for user %s.", login.c_str());
305 WriteServLog("%s", store->GetStrError().c_str());
306 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
307 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
313 //-----------------------------------------------------------------------------
314 int USER_IMPL::WriteStat()
316 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
317 USER_STAT stat(property.GetStat());
319 if (store->SaveUserStat(stat, login))
321 WriteServLog("Cannot write stat for user %s.", login.c_str());
322 WriteServLog("%s", store->GetStrError().c_str());
323 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
324 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
328 lastWriteStat = stgTime;
332 //-----------------------------------------------------------------------------
333 int USER_IMPL::WriteMonthStat()
335 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
336 time_t tt = stgTime - 3600;
338 localtime_r(&tt, &t1);
340 USER_STAT stat(property.GetStat());
341 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
343 WriteServLog("Cannot write month stat for user %s.", login.c_str());
344 WriteServLog("%s", store->GetStrError().c_str());
345 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
346 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
352 //-----------------------------------------------------------------------------
353 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
355 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
357 * Authorize user. It only means that user will be authorized. Nothing more.
358 * User can be connected or disconnected while authorized.
359 * Example: user is authorized but disconnected due to 0 money or blocking
363 * Prevent double authorization by identical authorizers
365 if (authorizedBy.find(auth) != authorizedBy.end())
371 for (int i = 0; i < DIR_NUM; i++)
373 enabledDirs[i] = dirs & (1 << i);
376 if (authorizedBy.size())
380 // We are already authorized, but with different IP address
381 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
386 if (!users->FindByIPIdx(ip, &u))
388 // Address is already present in IP-index
389 // If it's not our IP - throw an error
392 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
399 if (users->IsIPInIndex(ip))
401 // Address is already present in IP-index
402 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
406 if (ips.ConstData().IsIPInIPS(ip))
409 lastIPForDisconnect = currIP;
413 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
414 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
419 authorizedBy.insert(auth);
425 //-----------------------------------------------------------------------------
426 void USER_IMPL::Unauthorize(const AUTH * auth)
428 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
430 * Authorizer tries to unauthorize user, that was not authorized by it
432 if (!authorizedBy.erase(auth))
435 if (authorizedBy.empty())
437 lastIPForDisconnect = currIP;
438 currIP = 0; // DelUser in traffcounter
442 //-----------------------------------------------------------------------------
443 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
445 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
446 // Is this user authorized by specified authorizer?
447 return authorizedBy.find(auth) != authorizedBy.end();
449 //-----------------------------------------------------------------------------
450 void USER_IMPL::Connect(bool fakeConnect)
453 * Connect user to Internet. This function is differ from Authorize() !!!
456 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
460 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
462 if (access(scriptOnConnect.c_str(), X_OK) == 0)
464 char dirsStr[DIR_NUM + 1];
465 dirsStr[DIR_NUM] = 0;
466 for (int i = 0; i < DIR_NUM; i++)
468 dirsStr[i] = enabledDirs[i] ? '1' : '0';
471 string scriptOnConnectParams;
472 strprintf(&scriptOnConnectParams,
473 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
474 scriptOnConnect.c_str(),
476 inet_ntostring(currIP).c_str(),
481 ScriptExec(scriptOnConnectParams);
485 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
491 if (store->WriteUserConnect(login, currIP))
493 WriteServLog("Cannot write connect for user %s.", login.c_str());
494 WriteServLog("%s", store->GetStrError().c_str());
498 lastIPForDisconnect = currIP;
500 //-----------------------------------------------------------------------------
501 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
504 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
507 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
509 if (!lastIPForDisconnect)
511 printfd(__FILE__, "lastIPForDisconnect\n");
517 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
519 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
521 char dirsStr[DIR_NUM + 1];
522 dirsStr[DIR_NUM] = 0;
523 for (int i = 0; i < DIR_NUM; i++)
525 dirsStr[i] = enabledDirs[i] ? '1' : '0';
528 string scriptOnDisonnectParams;
529 strprintf(&scriptOnDisonnectParams,
530 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
531 scriptOnDisonnect.c_str(),
533 inet_ntostring(lastIPForDisconnect).c_str(),
538 ScriptExec(scriptOnDisonnectParams);
542 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
548 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
550 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
551 WriteServLog("%s", store->GetStrError().c_str());
555 lastIPForDisconnect = 0;
557 DIR_TRAFF zeroSesssion;
559 sessionUpload = zeroSesssion;
560 sessionDownload = zeroSesssion;
562 //-----------------------------------------------------------------------------
563 void USER_IMPL::PrintUser() const
566 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
567 cout << "============================================================" << endl;
568 cout << "id=" << id << endl;
569 cout << "login=" << login << endl;
570 cout << "password=" << password << endl;
571 cout << "passive=" << passive << endl;
572 cout << "disabled=" << disabled << endl;
573 cout << "disabledDetailStat=" << disabledDetailStat << endl;
574 cout << "alwaysOnline=" << alwaysOnline << endl;
575 cout << "tariffName=" << tariffName << endl;
576 cout << "address=" << address << endl;
577 cout << "phone=" << phone << endl;
578 cout << "email=" << email << endl;
579 cout << "note=" << note << endl;
580 cout << "realName=" <<realName << endl;
581 cout << "group=" << group << endl;
582 cout << "credit=" << credit << endl;
583 cout << "nextTariff=" << nextTariff << endl;
584 cout << "userdata0" << userdata0 << endl;
585 cout << "userdata1" << userdata1 << endl;
586 cout << "creditExpire=" << creditExpire << endl;
587 cout << "ips=" << ips << endl;
588 cout << "------------------------" << endl;
589 cout << "up=" << up << endl;
590 cout << "down=" << down << endl;
591 cout << "cash=" << cash << endl;
592 cout << "freeMb=" << freeMb << endl;
593 cout << "lastCashAdd=" << lastCashAdd << endl;
594 cout << "lastCashAddTime=" << lastCashAddTime << endl;
595 cout << "passiveTime=" << passiveTime << endl;
596 cout << "lastActivityTime=" << lastActivityTime << endl;
597 cout << "============================================================" << endl;
599 //-----------------------------------------------------------------------------
600 void USER_IMPL::Run()
602 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
604 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
606 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
609 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
611 WriteServLog("User: %s. Credit expired.", login.c_str());
617 if (passive.ConstData()
618 && (stgTime % 30 == 0)
619 && (passiveTime.ModificationTime() != stgTime))
621 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
622 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
625 if (!authorizedBy.empty())
629 property.Stat().lastActivityTime = stgTime;
631 if (!connected && IsInetable())
635 if (connected && !IsInetable())
638 Disconnect(false, "disabled");
640 Disconnect(false, "passive");
642 Disconnect(false, "no cash");
645 if (stgTime - lastScanMessages > 10)
648 lastScanMessages = stgTime;
655 Disconnect(false, "not authorized");
660 //-----------------------------------------------------------------------------
661 void USER_IMPL::UpdatePingTime(time_t t)
663 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
664 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
670 //-----------------------------------------------------------------------------
671 bool USER_IMPL::IsInetable()
673 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
675 if (disabled || passive)
678 if (settings->GetFreeMbAllowInet())
684 if (settings->GetShowFeeInCash())
686 return (cash >= -credit);
689 return (cash - tariff->GetFee() >= -credit);
691 //-----------------------------------------------------------------------------
692 string USER_IMPL::GetEnabledDirs()
694 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
697 for(int i = 0; i < DIR_NUM; i++)
698 dirs += enabledDirs[i] ? "1" : "0";
701 //-----------------------------------------------------------------------------
702 #ifdef TRAFF_STAT_WITH_PORTS
703 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
705 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
708 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
716 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
717 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
721 int tt = tariff->GetTraffType();
722 if (tt == TRAFF_UP ||
723 tt == TRAFF_UP_DOWN ||
724 // Check NEW traff data
725 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
728 if (traff < threshold &&
729 traff + len >= threshold)
731 // cash = partBeforeThreshold * priceBeforeThreshold +
732 // partAfterThreshold * priceAfterThreshold
733 int64_t before = threshold - traff; // Chunk part before threshold
734 int64_t after = len - before; // Chunk part after threshold
735 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
736 down.ConstData()[dir],
739 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
740 down.ConstData()[dir],
746 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
747 down.ConstData()[dir],
752 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
754 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
755 cost = dc - freeMb.ConstData();
757 // Direct access to internal data structures via friend-specifier
758 property.Stat().freeMb -= dc;
759 property.Stat().cash -= cost;
765 sessionUpload[dir] += len;
769 if (!settings->GetWriteFreeMbTraffCost() &&
770 freeMb.ConstData() >= 0)
773 #ifdef TRAFF_STAT_WITH_PORTS
774 IP_DIR_PAIR idp(ip, dir, port);
776 IP_DIR_PAIR idp(ip, dir);
779 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
780 lb = traffStat.lower_bound(idp);
781 if (lb == traffStat.end() || lb->first != idp)
784 pair<IP_DIR_PAIR, STAT_NODE>(idp,
785 STAT_NODE(len, 0, cost)));
789 lb->second.cash += cost;
790 lb->second.up += len;
793 //-----------------------------------------------------------------------------
794 #ifdef TRAFF_STAT_WITH_PORTS
795 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
797 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
800 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
808 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
809 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
813 int tt = tariff->GetTraffType();
814 if (tt == TRAFF_DOWN ||
815 tt == TRAFF_UP_DOWN ||
816 // Check NEW traff data
817 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
820 if (traff < threshold &&
821 traff + len >= threshold)
823 // cash = partBeforeThreshold * priceBeforeThreshold +
824 // partAfterThreshold * priceAfterThreshold
825 int64_t before = threshold - traff; // Chunk part before threshold
826 int64_t after = len - before; // Chunk part after threshold
827 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
828 down.ConstData()[dir], // Traff before chunk
831 tariff->GetPriceWithTraffType(up.ConstData()[dir],
832 dt[dir], // Traff after chunk
838 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
839 down.ConstData()[dir],
844 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
846 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
847 cost = dc - freeMb.ConstData();
849 property.Stat().freeMb -= dc;
850 property.Stat().cash -= cost;
856 sessionDownload[dir] += len;
860 if (!settings->GetWriteFreeMbTraffCost() &&
861 freeMb.ConstData() >= 0)
864 #ifdef TRAFF_STAT_WITH_PORTS
865 IP_DIR_PAIR idp(ip, dir, port);
867 IP_DIR_PAIR idp(ip, dir);
870 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
871 lb = traffStat.lower_bound(idp);
872 if (lb == traffStat.end() || lb->first != idp)
875 pair<IP_DIR_PAIR, STAT_NODE>(idp,
876 STAT_NODE(0, len, cost)));
880 lb->second.cash += cost;
881 lb->second.down += len;
884 //-----------------------------------------------------------------------------
885 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
887 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
888 currIP.AddBeforeNotifier(n);
890 //-----------------------------------------------------------------------------
891 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
893 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
894 currIP.DelBeforeNotifier(n);
896 //-----------------------------------------------------------------------------
897 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
899 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
900 currIP.AddAfterNotifier(n);
902 //-----------------------------------------------------------------------------
903 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
905 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
906 currIP.DelAfterNotifier(n);
908 //-----------------------------------------------------------------------------
909 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
911 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
912 connected.AddBeforeNotifier(n);
914 //-----------------------------------------------------------------------------
915 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
917 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
918 connected.DelBeforeNotifier(n);
920 //-----------------------------------------------------------------------------
921 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
923 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
924 connected.AddAfterNotifier(n);
926 //-----------------------------------------------------------------------------
927 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
929 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
930 connected.DelAfterNotifier(n);
932 //-----------------------------------------------------------------------------
933 void USER_IMPL::OnAdd()
935 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
937 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
939 if (access(scriptOnAdd.c_str(), X_OK) == 0)
941 string scriptOnAddParams;
942 strprintf(&scriptOnAddParams,
947 ScriptExec(scriptOnAddParams);
951 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
954 //-----------------------------------------------------------------------------
955 void USER_IMPL::OnDelete()
957 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
959 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
961 if (access(scriptOnDel.c_str(), X_OK) == 0)
963 string scriptOnDelParams;
964 strprintf(&scriptOnDelParams,
969 ScriptExec(scriptOnDelParams);
973 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
978 //-----------------------------------------------------------------------------
979 int USER_IMPL::WriteDetailStat(bool hard)
981 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
983 if (!traffStatSaved.second.empty())
985 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
987 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
988 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
989 WriteServLog("%s", store->GetStrError().c_str());
992 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
998 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1002 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1004 if (ts.size() && !disabledDetailStat)
1006 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1008 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1009 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1010 WriteServLog("%s", store->GetStrError().c_str());
1013 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1014 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1015 traffStatSaved.second.swap(ts);
1016 traffStatSaved.first = lastWriteDetailedStat;
1021 lastWriteDetailedStat = stgTime;
1024 //-----------------------------------------------------------------------------
1025 double USER_IMPL::GetPassiveTimePart() const
1027 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1029 static int daysInMonth[12] =
1030 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1034 localtime_r(&t, &tms);
1036 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1038 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1041 secMonth += 24 * 3600;
1044 int dt = secMonth - passiveTime;
1049 return double(dt) / (secMonth);
1051 //-----------------------------------------------------------------------------
1052 void USER_IMPL::SetPassiveTimeAsNewUser()
1054 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1058 localtime_r(&t, &tm);
1059 int daysCurrMon = DaysInCurrentMonth();
1060 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1062 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1064 //-----------------------------------------------------------------------------
1065 void USER_IMPL::MidnightResetSessionStat()
1067 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1071 Disconnect(true, "fake");
1075 //-----------------------------------------------------------------------------
1076 void USER_IMPL::ProcessNewMonth()
1078 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1082 Disconnect(true, "fake");
1084 DIR_TRAFF zeroTarff;
1097 if (nextTariff.ConstData() != "")
1100 nt = tariffs->FindByName(nextTariff);
1103 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1104 login.c_str(), property.tariffName.Get().c_str());
1108 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1115 //-----------------------------------------------------------------------------
1116 void USER_IMPL::ProcessDayFeeSpread()
1118 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1120 if (passive.ConstData())
1123 double f = tariff->GetFee() / DaysInCurrentMonth();
1129 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1132 //-----------------------------------------------------------------------------
1133 void USER_IMPL::ProcessDayFee()
1135 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1137 double passiveTimePart = 1.0;
1138 if (!settings->GetFullFee())
1140 passiveTimePart = GetPassiveTimePart();
1144 if (passive.ConstData())
1146 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1150 double f = tariff->GetFee() * passiveTimePart;
1158 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1163 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1165 //-----------------------------------------------------------------------------
1166 void USER_IMPL::SetPrepaidTraff()
1168 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1170 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1172 //-----------------------------------------------------------------------------
1173 int USER_IMPL::AddMessage(STG_MSG * msg)
1175 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1177 if (SendMessage(*msg))
1179 if (store->AddMessage(msg, login))
1181 errorStr = store->GetStrError();
1182 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1183 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1186 messages.push_back(*msg);
1190 if (msg->header.repeat > 0)
1192 msg->header.repeat--;
1194 //TODO: gcc v. 4.x generate ICE on x86_64
1195 msg->header.lastSendTime = time(NULL);
1197 msg->header.lastSendTime = stgTime;
1199 if (store->AddMessage(msg, login))
1201 errorStr = store->GetStrError();
1202 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1203 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1206 messages.push_back(*msg);
1211 //-----------------------------------------------------------------------------
1212 int USER_IMPL::SendMessage(STG_MSG & msg) const
1214 // No lock `cause we are already locked from caller
1216 set<const AUTH*>::iterator it(authorizedBy.begin());
1217 while (it != authorizedBy.end())
1219 if (!(*it++)->SendMessage(msg, currIP))
1225 //TODO: gcc v. 4.x generate ICE on x86_64
1226 msg.header.lastSendTime = time(NULL);
1228 msg.header.lastSendTime = stgTime;
1230 msg.header.repeat--;
1234 //-----------------------------------------------------------------------------
1235 void USER_IMPL::ScanMessage()
1237 // No lock `cause we are already locked from caller
1238 // We need not check for the authorizedBy `cause it has already checked by caller
1240 std::list<STG_MSG>::iterator it(messages.begin());
1241 while (it != messages.end())
1243 if (settings->GetMessageTimeout() > 0 &&
1244 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1247 if (store->DelMessage(it->header.id, login))
1249 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1250 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1252 messages.erase(it++);
1255 if (it->GetNextSendTime() <= stgTime)
1257 if (SendMessage(*it))
1259 // We need to check all messages in queue for timeout
1263 if (it->header.repeat < 0)
1265 if (store->DelMessage(it->header.id, login))
1267 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1268 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1270 messages.erase(it++);
1274 if (store->EditMessage(*it, login))
1276 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1277 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1288 //-----------------------------------------------------------------------------
1289 //-----------------------------------------------------------------------------
1290 //-----------------------------------------------------------------------------
1291 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1293 if (newPassive && !oldPassive)
1294 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1300 //-----------------------------------------------------------------------------
1301 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1303 user->tariff = user->tariffs->FindByName(newTariff);
1305 //-----------------------------------------------------------------------------
1306 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1308 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1309 user->lastCashAdd = newCash - oldCash;
1311 //-----------------------------------------------------------------------------
1312 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1314 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1315 if (user->connected)
1316 user->Disconnect(true, "Change IP");
1317 if (user->IsInetable())
1318 user->Connect(true);
1320 //-----------------------------------------------------------------------------