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 "user_impl.h"
45 #include "script_executer.h"
50 USER_IMPL::USER_IMPL(const SETTINGS * 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 lastWriteDeatiledStat = 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 lastWriteDeatiledStat = u.lastWriteDeatiledStat;
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 lastActivityTime = *const_cast<time_t *>(&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 || passive)
680 if (settings->GetFreeMbAllowInet())
686 if (settings->GetShowFeeInCash())
688 return (cash >= -credit);
691 return (cash - tariff->GetFee() >= -credit);
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::OnAdd()
913 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
915 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
917 if (access(scriptOnAdd.c_str(), X_OK) == 0)
919 string scriptOnAddParams;
920 strprintf(&scriptOnAddParams,
925 ScriptExec(scriptOnAddParams);
929 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
932 //-----------------------------------------------------------------------------
933 void USER_IMPL::OnDelete()
935 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
937 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
939 if (access(scriptOnDel.c_str(), X_OK) == 0)
941 string scriptOnDelParams;
942 strprintf(&scriptOnDelParams,
947 ScriptExec(scriptOnDelParams);
951 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
956 //-----------------------------------------------------------------------------
957 int USER_IMPL::WriteDetailStat(bool hard)
959 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
961 if (!traffStatSaved.second.empty())
963 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
965 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
966 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
967 WriteServLog("%s", store->GetStrError().c_str());
970 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
976 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
980 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
982 if (ts.size() && !disabledDetailStat)
984 if (store->WriteDetailedStat(ts, lastWriteDeatiledStat, login))
986 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
987 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
988 WriteServLog("%s", store->GetStrError().c_str());
991 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
992 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
993 traffStatSaved.second.swap(ts);
994 traffStatSaved.first = lastWriteDeatiledStat;
999 lastWriteDeatiledStat = stgTime;
1002 //-----------------------------------------------------------------------------
1003 double USER_IMPL::GetPassiveTimePart() const
1005 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1007 static int daysInMonth[12] =
1008 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1012 localtime_r(&t, &tms);
1014 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1016 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1019 secMonth += 24 * 3600;
1022 int dt = secMonth - passiveTime;
1027 return double(dt) / (secMonth);
1029 //-----------------------------------------------------------------------------
1030 void USER_IMPL::SetPassiveTimeAsNewUser()
1032 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1036 localtime_r(&t, &tm);
1037 int daysCurrMon = DaysInCurrentMonth();
1038 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1040 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1042 //-----------------------------------------------------------------------------
1043 void USER_IMPL::MidnightResetSessionStat()
1045 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1049 Disconnect(true, "fake");
1053 //-----------------------------------------------------------------------------
1054 void USER_IMPL::ProcessNewMonth()
1056 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1060 Disconnect(true, "fake");
1062 DIR_TRAFF zeroTarff;
1075 if (nextTariff.ConstData() != "")
1078 nt = tariffs->FindByName(nextTariff);
1081 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1082 login.c_str(), property.tariffName.Get().c_str());
1086 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1093 //-----------------------------------------------------------------------------
1094 void USER_IMPL::ProcessDayFeeSpread()
1096 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1098 if (passive.ConstData())
1101 double f = tariff->GetFee() / DaysInCurrentMonth();
1107 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1110 //-----------------------------------------------------------------------------
1111 void USER_IMPL::ProcessDayFee()
1113 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1115 double passiveTimePart = 1.0;
1116 if (!settings->GetFullFee())
1118 passiveTimePart = GetPassiveTimePart();
1122 if (passive.ConstData())
1124 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1128 double f = tariff->GetFee() * passiveTimePart;
1136 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1141 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1143 //-----------------------------------------------------------------------------
1144 void USER_IMPL::SetPrepaidTraff()
1146 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1148 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1150 //-----------------------------------------------------------------------------
1151 int USER_IMPL::AddMessage(STG_MSG * msg)
1153 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1155 if (SendMessage(*msg))
1157 if (store->AddMessage(msg, login))
1159 errorStr = store->GetStrError();
1160 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1161 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1164 messages.push_back(*msg);
1168 if (msg->header.repeat > 0)
1170 msg->header.repeat--;
1172 //TODO: gcc v. 4.x generate ICE on x86_64
1173 msg->header.lastSendTime = time(NULL);
1175 msg->header.lastSendTime = stgTime;
1177 if (store->AddMessage(msg, login))
1179 errorStr = store->GetStrError();
1180 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1181 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1184 messages.push_back(*msg);
1189 //-----------------------------------------------------------------------------
1190 int USER_IMPL::SendMessage(STG_MSG & msg) const
1192 // No lock `cause we are already locked from caller
1194 set<const AUTH*>::iterator it(authorizedBy.begin());
1195 while (it != authorizedBy.end())
1197 if (!(*it++)->SendMessage(msg, currIP))
1203 //TODO: gcc v. 4.x generate ICE on x86_64
1204 msg.header.lastSendTime = time(NULL);
1206 msg.header.lastSendTime = stgTime;
1208 msg.header.repeat--;
1212 //-----------------------------------------------------------------------------
1213 void USER_IMPL::ScanMessage()
1215 // No lock `cause we are already locked from caller
1216 // We need not check for the authorizedBy `cause it has already checked by caller
1218 std::list<STG_MSG>::iterator it(messages.begin());
1219 while (it != messages.end())
1221 if (settings->GetMessageTimeout() > 0 &&
1222 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1225 if (store->DelMessage(it->header.id, login))
1227 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1228 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1230 messages.erase(it++);
1233 if (it->GetNextSendTime() <= stgTime)
1235 if (SendMessage(*it))
1237 // We need to check all messages in queue for timeout
1241 if (it->header.repeat < 0)
1243 if (store->DelMessage(it->header.id, login))
1245 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1246 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1248 messages.erase(it++);
1252 if (store->EditMessage(*it, login))
1254 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1255 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1262 //-----------------------------------------------------------------------------
1263 //-----------------------------------------------------------------------------
1264 //-----------------------------------------------------------------------------
1265 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1267 if (newPassive && !oldPassive)
1268 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1274 //-----------------------------------------------------------------------------
1275 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1277 user->tariff = user->tariffs->FindByName(newTariff);
1279 //-----------------------------------------------------------------------------
1280 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1282 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1283 user->lastCashAdd = newCash - oldCash;
1285 //-----------------------------------------------------------------------------
1286 void CHG_IP_NOTIFIER::Notify(const uint32_t & from, const uint32_t & to)
1288 printfd(__FILE__, "Change IP from %s to %s\n", inet_ntostring(from).c_str(), inet_ntostring(to).c_str());
1290 if (user->connected)
1291 user->Disconnect(false, "Change IP");
1293 if (user->IsInetable())
1294 user->Connect(false);
1296 //-----------------------------------------------------------------------------