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 currIP.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 currIP.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 printfd(__FILE__, "USER::WriteStat()\n");
321 if (store->SaveUserStat(stat, login))
323 WriteServLog("Cannot write stat for user %s.", login.c_str());
324 WriteServLog("%s", store->GetStrError().c_str());
325 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
326 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
330 lastWriteStat = stgTime;
334 //-----------------------------------------------------------------------------
335 int USER_IMPL::WriteMonthStat()
337 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
338 time_t tt = stgTime - 3600;
340 localtime_r(&tt, &t1);
342 USER_STAT stat(property.GetStat());
343 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
345 WriteServLog("Cannot write month stat for user %s.", login.c_str());
346 WriteServLog("%s", store->GetStrError().c_str());
347 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
348 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
354 //-----------------------------------------------------------------------------
355 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
357 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
359 * Authorize user. It only means that user will be authorized. Nothing more.
360 * User can be connected or disconnected while authorized.
361 * Example: user is authorized but disconnected due to 0 money or blocking
365 * Prevent double authorization by identical authorizers
367 if (authorizedBy.find(auth) != authorizedBy.end())
373 for (int i = 0; i < DIR_NUM; i++)
375 enabledDirs[i] = dirs & (1 << i);
378 if (authorizedBy.size())
382 // We are already authorized, but with different IP address
383 errorStr = "User " + login + " alredy authorized with IP address " + inet_ntostring(ip);
388 if (!users->FindByIPIdx(ip, &u))
390 // Address is already present in IP-index
391 // If it's not our IP - throw an error
394 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
401 if (users->IsIPInIndex(ip))
403 // Address is already present in IP-index
404 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
408 if (ips.ConstData().IsIPInIPS(ip))
411 lastIPForDisconnect = currIP;
415 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
416 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
421 authorizedBy.insert(auth);
427 //-----------------------------------------------------------------------------
428 void USER_IMPL::Unauthorize(const AUTH * auth)
430 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
432 * Authorizer tries to unauthorize user, that was not authorized by it
434 if (!authorizedBy.erase(auth))
437 if (authorizedBy.empty())
439 lastIPForDisconnect = currIP;
440 currIP = 0; // DelUser in traffcounter
444 //-----------------------------------------------------------------------------
445 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
447 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
448 // Is this user authorized by specified authorizer?
449 return authorizedBy.find(auth) != authorizedBy.end();
451 //-----------------------------------------------------------------------------
452 void USER_IMPL::Connect(bool fakeConnect)
455 * Connect user to Internet. This function is differ from Authorize() !!!
458 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
462 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
464 if (access(scriptOnConnect.c_str(), X_OK) == 0)
466 char dirsStr[DIR_NUM + 1];
467 dirsStr[DIR_NUM] = 0;
468 for (int i = 0; i < DIR_NUM; i++)
470 dirsStr[i] = enabledDirs[i] ? '1' : '0';
473 string scriptOnConnectParams;
474 strprintf(&scriptOnConnectParams,
475 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
476 scriptOnConnect.c_str(),
478 inet_ntostring(currIP).c_str(),
483 ScriptExec(scriptOnConnectParams);
487 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
493 if (store->WriteUserConnect(login, currIP))
495 WriteServLog("Cannot write connect for user %s.", login.c_str());
496 WriteServLog("%s", store->GetStrError().c_str());
500 lastIPForDisconnect = currIP;
502 //-----------------------------------------------------------------------------
503 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
506 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
509 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
511 if (!lastIPForDisconnect)
513 printfd(__FILE__, "lastIPForDisconnect\n");
519 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
521 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
523 char dirsStr[DIR_NUM + 1];
524 dirsStr[DIR_NUM] = 0;
525 for (int i = 0; i < DIR_NUM; i++)
527 dirsStr[i] = enabledDirs[i] ? '1' : '0';
530 string scriptOnDisonnectParams;
531 strprintf(&scriptOnDisonnectParams,
532 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
533 scriptOnDisonnect.c_str(),
535 inet_ntostring(lastIPForDisconnect).c_str(),
540 ScriptExec(scriptOnDisonnectParams);
544 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
550 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
552 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
553 WriteServLog("%s", store->GetStrError().c_str());
557 lastIPForDisconnect = 0;
559 DIR_TRAFF zeroSesssion;
561 sessionUpload = zeroSesssion;
562 sessionDownload = zeroSesssion;
564 //-----------------------------------------------------------------------------
565 void USER_IMPL::PrintUser() const
568 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
569 cout << "============================================================" << endl;
570 cout << "id=" << id << endl;
571 cout << "login=" << login << endl;
572 cout << "password=" << password << endl;
573 cout << "passive=" << passive << endl;
574 cout << "disabled=" << disabled << endl;
575 cout << "disabledDetailStat=" << disabledDetailStat << endl;
576 cout << "alwaysOnline=" << alwaysOnline << endl;
577 cout << "tariffName=" << tariffName << endl;
578 cout << "address=" << address << endl;
579 cout << "phone=" << phone << endl;
580 cout << "email=" << email << endl;
581 cout << "note=" << note << endl;
582 cout << "realName=" <<realName << endl;
583 cout << "group=" << group << endl;
584 cout << "credit=" << credit << endl;
585 cout << "nextTariff=" << nextTariff << endl;
586 cout << "userdata0" << userdata0 << endl;
587 cout << "userdata1" << userdata1 << endl;
588 cout << "creditExpire=" << creditExpire << endl;
589 cout << "ips=" << ips << endl;
590 cout << "------------------------" << endl;
591 cout << "up=" << up << endl;
592 cout << "down=" << down << endl;
593 cout << "cash=" << cash << endl;
594 cout << "freeMb=" << freeMb << endl;
595 cout << "lastCashAdd=" << lastCashAdd << endl;
596 cout << "lastCashAddTime=" << lastCashAddTime << endl;
597 cout << "passiveTime=" << passiveTime << endl;
598 cout << "lastActivityTime=" << lastActivityTime << endl;
599 cout << "============================================================" << endl;
601 //-----------------------------------------------------------------------------
602 void USER_IMPL::Run()
604 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
606 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
608 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
611 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
613 WriteServLog("User: %s. Credit expired.", login.c_str());
619 if (passive.ConstData()
620 && (stgTime % 30 == 0)
621 && (passiveTime.ModificationTime() != stgTime))
623 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
624 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
627 if (!authorizedBy.empty())
631 property.Stat().lastActivityTime = stgTime;
633 if (!connected && IsInetable())
637 if (connected && !IsInetable())
640 Disconnect(false, "disabled");
642 Disconnect(false, "passive");
644 Disconnect(false, "no cash");
647 if (stgTime - lastScanMessages > 10)
650 lastScanMessages = stgTime;
657 Disconnect(false, "not authorized");
662 //-----------------------------------------------------------------------------
663 void USER_IMPL::UpdatePingTime(time_t t)
665 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
666 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
672 //-----------------------------------------------------------------------------
673 bool USER_IMPL::IsInetable()
675 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
677 if (disabled.ConstData() || passive.ConstData())
680 if (settings->GetFreeMbAllowInet())
682 if (freeMb.ConstData() >= 0)
686 if (settings->GetShowFeeInCash())
688 return (cash.ConstData() >= -credit.ConstData());
691 return (cash.ConstData() - tariff->GetFee() >= -credit.ConstData());
693 //-----------------------------------------------------------------------------
694 string USER_IMPL::GetEnabledDirs()
696 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
699 for(int i = 0; i < DIR_NUM; i++)
700 dirs += enabledDirs[i] ? "1" : "0";
703 //-----------------------------------------------------------------------------
704 #ifdef TRAFF_STAT_WITH_PORTS
705 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
707 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
710 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
718 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
719 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
723 int tt = tariff->GetTraffType();
724 if (tt == TRAFF_UP ||
725 tt == TRAFF_UP_DOWN ||
726 // Check NEW traff data
727 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
730 if (traff < threshold &&
731 traff + len >= threshold)
733 // cash = partBeforeThreshold * priceBeforeThreshold +
734 // partAfterThreshold * priceAfterThreshold
735 int64_t before = threshold - traff; // Chunk part before threshold
736 int64_t after = len - before; // Chunk part after threshold
737 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
738 down.ConstData()[dir],
741 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
742 down.ConstData()[dir],
748 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
749 down.ConstData()[dir],
754 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
756 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
757 cost = dc - freeMb.ConstData();
759 // Direct access to internal data structures via friend-specifier
760 property.Stat().freeMb -= dc;
761 property.Stat().cash -= cost;
767 sessionUpload[dir] += len;
771 if (!settings->GetWriteFreeMbTraffCost() &&
772 freeMb.ConstData() >= 0)
775 #ifdef TRAFF_STAT_WITH_PORTS
776 IP_DIR_PAIR idp(ip, dir, port);
778 IP_DIR_PAIR idp(ip, dir);
781 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
782 lb = traffStat.lower_bound(idp);
783 if (lb == traffStat.end() || lb->first != idp)
786 pair<IP_DIR_PAIR, STAT_NODE>(idp,
787 STAT_NODE(len, 0, cost)));
791 lb->second.cash += cost;
792 lb->second.up += len;
795 //-----------------------------------------------------------------------------
796 #ifdef TRAFF_STAT_WITH_PORTS
797 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
799 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
802 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
810 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
811 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
815 int tt = tariff->GetTraffType();
816 if (tt == TRAFF_DOWN ||
817 tt == TRAFF_UP_DOWN ||
818 // Check NEW traff data
819 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
822 if (traff < threshold &&
823 traff + len >= threshold)
825 // cash = partBeforeThreshold * priceBeforeThreshold +
826 // partAfterThreshold * priceAfterThreshold
827 int64_t before = threshold - traff; // Chunk part before threshold
828 int64_t after = len - before; // Chunk part after threshold
829 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
830 down.ConstData()[dir], // Traff before chunk
833 tariff->GetPriceWithTraffType(up.ConstData()[dir],
834 dt[dir], // Traff after chunk
840 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
841 down.ConstData()[dir],
846 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
848 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
849 cost = dc - freeMb.ConstData();
851 property.Stat().freeMb -= dc;
852 property.Stat().cash -= cost;
858 sessionDownload[dir] += len;
862 if (!settings->GetWriteFreeMbTraffCost() &&
863 freeMb.ConstData() >= 0)
866 #ifdef TRAFF_STAT_WITH_PORTS
867 IP_DIR_PAIR idp(ip, dir, port);
869 IP_DIR_PAIR idp(ip, dir);
872 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
873 lb = traffStat.lower_bound(idp);
874 if (lb == traffStat.end() || lb->first != idp)
877 pair<IP_DIR_PAIR, STAT_NODE>(idp,
878 STAT_NODE(0, len, cost)));
882 lb->second.cash += cost;
883 lb->second.down += len;
886 //-----------------------------------------------------------------------------
887 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
889 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
890 currIP.AddBeforeNotifier(n);
892 //-----------------------------------------------------------------------------
893 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
895 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
896 currIP.DelBeforeNotifier(n);
898 //-----------------------------------------------------------------------------
899 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
901 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
902 currIP.AddAfterNotifier(n);
904 //-----------------------------------------------------------------------------
905 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
907 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
908 currIP.DelAfterNotifier(n);
910 //-----------------------------------------------------------------------------
911 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
913 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
914 connected.AddBeforeNotifier(n);
916 //-----------------------------------------------------------------------------
917 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
919 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
920 connected.DelBeforeNotifier(n);
922 //-----------------------------------------------------------------------------
923 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
925 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
926 connected.AddAfterNotifier(n);
928 //-----------------------------------------------------------------------------
929 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
931 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
932 connected.DelAfterNotifier(n);
934 //-----------------------------------------------------------------------------
935 void USER_IMPL::OnAdd()
937 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
939 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
941 if (access(scriptOnAdd.c_str(), X_OK) == 0)
943 string scriptOnAddParams;
944 strprintf(&scriptOnAddParams,
949 ScriptExec(scriptOnAddParams);
953 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
956 //-----------------------------------------------------------------------------
957 void USER_IMPL::OnDelete()
959 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
961 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
963 if (access(scriptOnDel.c_str(), X_OK) == 0)
965 string scriptOnDelParams;
966 strprintf(&scriptOnDelParams,
971 ScriptExec(scriptOnDelParams);
975 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
980 //-----------------------------------------------------------------------------
981 int USER_IMPL::WriteDetailStat(bool hard)
983 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
985 if (!traffStatSaved.second.empty())
987 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
989 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
990 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
991 WriteServLog("%s", store->GetStrError().c_str());
994 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1000 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1004 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1006 if (ts.size() && !disabledDetailStat)
1008 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1010 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1011 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1012 WriteServLog("%s", store->GetStrError().c_str());
1015 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1016 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1017 traffStatSaved.second.swap(ts);
1018 traffStatSaved.first = lastWriteDetailedStat;
1023 lastWriteDetailedStat = stgTime;
1026 //-----------------------------------------------------------------------------
1027 double USER_IMPL::GetPassiveTimePart() const
1029 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1031 static int daysInMonth[12] =
1032 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1036 localtime_r(&t, &tms);
1038 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1040 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1043 secMonth += 24 * 3600;
1046 int dt = secMonth - passiveTime;
1051 return double(dt) / (secMonth);
1053 //-----------------------------------------------------------------------------
1054 void USER_IMPL::SetPassiveTimeAsNewUser()
1056 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1060 localtime_r(&t, &tm);
1061 int daysCurrMon = DaysInCurrentMonth();
1062 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1064 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1066 //-----------------------------------------------------------------------------
1067 void USER_IMPL::MidnightResetSessionStat()
1069 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1073 Disconnect(true, "fake");
1077 //-----------------------------------------------------------------------------
1078 void USER_IMPL::ProcessNewMonth()
1080 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1084 Disconnect(true, "fake");
1086 DIR_TRAFF zeroTarff;
1099 if (nextTariff.ConstData() != "")
1102 nt = tariffs->FindByName(nextTariff);
1105 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1106 login.c_str(), property.tariffName.Get().c_str());
1110 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1117 //-----------------------------------------------------------------------------
1118 void USER_IMPL::ProcessDayFeeSpread()
1120 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1122 if (passive.ConstData())
1125 double f = tariff->GetFee() / DaysInCurrentMonth();
1131 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1134 //-----------------------------------------------------------------------------
1135 void USER_IMPL::ProcessDayFee()
1137 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1139 double passiveTimePart = 1.0;
1140 if (!settings->GetFullFee())
1142 passiveTimePart = GetPassiveTimePart();
1146 if (passive.ConstData())
1148 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1152 double f = tariff->GetFee() * passiveTimePart;
1160 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1165 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1167 //-----------------------------------------------------------------------------
1168 void USER_IMPL::SetPrepaidTraff()
1170 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1172 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1174 //-----------------------------------------------------------------------------
1175 int USER_IMPL::AddMessage(STG_MSG * msg)
1177 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1179 if (SendMessage(*msg))
1181 if (store->AddMessage(msg, login))
1183 errorStr = store->GetStrError();
1184 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1185 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1188 messages.push_back(*msg);
1192 if (msg->header.repeat > 0)
1194 msg->header.repeat--;
1196 //TODO: gcc v. 4.x generate ICE on x86_64
1197 msg->header.lastSendTime = time(NULL);
1199 msg->header.lastSendTime = stgTime;
1201 if (store->AddMessage(msg, login))
1203 errorStr = store->GetStrError();
1204 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1205 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1208 messages.push_back(*msg);
1213 //-----------------------------------------------------------------------------
1214 int USER_IMPL::SendMessage(STG_MSG & msg) const
1216 // No lock `cause we are already locked from caller
1218 set<const AUTH*>::iterator it(authorizedBy.begin());
1219 while (it != authorizedBy.end())
1221 if (!(*it++)->SendMessage(msg, currIP))
1227 //TODO: gcc v. 4.x generate ICE on x86_64
1228 msg.header.lastSendTime = time(NULL);
1230 msg.header.lastSendTime = stgTime;
1232 msg.header.repeat--;
1236 //-----------------------------------------------------------------------------
1237 void USER_IMPL::ScanMessage()
1239 // No lock `cause we are already locked from caller
1240 // We need not check for the authorizedBy `cause it has already checked by caller
1242 std::list<STG_MSG>::iterator it(messages.begin());
1243 while (it != messages.end())
1245 if (settings->GetMessageTimeout() > 0 &&
1246 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1249 if (store->DelMessage(it->header.id, login))
1251 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1252 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1254 messages.erase(it++);
1257 if (it->GetNextSendTime() <= stgTime)
1259 if (SendMessage(*it))
1261 // We need to check all messages in queue for timeout
1265 if (it->header.repeat < 0)
1267 if (store->DelMessage(it->header.id, login))
1269 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1270 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1272 messages.erase(it++);
1276 if (store->EditMessage(*it, login))
1278 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1279 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1286 //-----------------------------------------------------------------------------
1287 //-----------------------------------------------------------------------------
1288 //-----------------------------------------------------------------------------
1289 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1291 if (newPassive && !oldPassive)
1292 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1298 //-----------------------------------------------------------------------------
1299 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1301 user->tariff = user->tariffs->FindByName(newTariff);
1303 //-----------------------------------------------------------------------------
1304 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1306 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1307 user->lastCashAdd = newCash - oldCash;
1309 //-----------------------------------------------------------------------------
1310 void CHG_IP_NOTIFIER::Notify(const uint32_t & from, const uint32_t & to)
1312 printfd(__FILE__, "Change IP from %s to %s\n", inet_ntostring(from).c_str(), inet_ntostring(to).c_str());
1314 if (user->connected)
1315 user->Disconnect(false, "Change IP");
1317 if (user->IsInetable())
1318 user->Connect(false);
1320 //-----------------------------------------------------------------------------