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 fee = tariff->GetFee() / DaysInCurrentMonth();
1129 switch (settings->GetFeeChargeType())
1132 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1136 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1140 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1145 //-----------------------------------------------------------------------------
1146 void USER_IMPL::ProcessDayFee()
1148 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1150 double passiveTimePart = 1.0;
1151 if (!settings->GetFullFee())
1153 passiveTimePart = GetPassiveTimePart();
1157 if (passive.ConstData())
1159 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1163 double fee = tariff->GetFee() * passiveTimePart;
1171 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1176 switch (settings->GetFeeChargeType())
1179 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1183 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1187 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1191 //-----------------------------------------------------------------------------
1192 void USER_IMPL::SetPrepaidTraff()
1194 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1196 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1198 //-----------------------------------------------------------------------------
1199 int USER_IMPL::AddMessage(STG_MSG * msg)
1201 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1203 if (SendMessage(*msg))
1205 if (store->AddMessage(msg, login))
1207 errorStr = store->GetStrError();
1208 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1209 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1212 messages.push_back(*msg);
1216 if (msg->header.repeat > 0)
1218 msg->header.repeat--;
1220 //TODO: gcc v. 4.x generate ICE on x86_64
1221 msg->header.lastSendTime = time(NULL);
1223 msg->header.lastSendTime = stgTime;
1225 if (store->AddMessage(msg, login))
1227 errorStr = store->GetStrError();
1228 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1229 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1232 messages.push_back(*msg);
1237 //-----------------------------------------------------------------------------
1238 int USER_IMPL::SendMessage(STG_MSG & msg) const
1240 // No lock `cause we are already locked from caller
1242 set<const AUTH*>::iterator it(authorizedBy.begin());
1243 while (it != authorizedBy.end())
1245 if (!(*it++)->SendMessage(msg, currIP))
1251 //TODO: gcc v. 4.x generate ICE on x86_64
1252 msg.header.lastSendTime = time(NULL);
1254 msg.header.lastSendTime = stgTime;
1256 msg.header.repeat--;
1260 //-----------------------------------------------------------------------------
1261 void USER_IMPL::ScanMessage()
1263 // No lock `cause we are already locked from caller
1264 // We need not check for the authorizedBy `cause it has already checked by caller
1266 std::list<STG_MSG>::iterator it(messages.begin());
1267 while (it != messages.end())
1269 if (settings->GetMessageTimeout() > 0 &&
1270 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1273 if (store->DelMessage(it->header.id, login))
1275 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1276 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1278 messages.erase(it++);
1281 if (it->GetNextSendTime() <= stgTime)
1283 if (SendMessage(*it))
1285 // We need to check all messages in queue for timeout
1289 if (it->header.repeat < 0)
1291 if (store->DelMessage(it->header.id, login))
1293 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1294 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1296 messages.erase(it++);
1300 if (store->EditMessage(*it, login))
1302 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1303 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1314 //-----------------------------------------------------------------------------
1315 //-----------------------------------------------------------------------------
1316 //-----------------------------------------------------------------------------
1317 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1319 if (newPassive && !oldPassive)
1320 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1326 //-----------------------------------------------------------------------------
1327 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1329 user->tariff = user->tariffs->FindByName(newTariff);
1331 //-----------------------------------------------------------------------------
1332 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1334 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1335 user->lastCashAdd = newCash - oldCash;
1337 //-----------------------------------------------------------------------------
1338 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1340 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1341 if (user->connected)
1342 user->Disconnect(true, "Change IP");
1343 if (user->IsInetable())
1344 user->Connect(true);
1346 //-----------------------------------------------------------------------------