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 $
35 #include "user_impl.h"
36 #include "settings_impl.h"
37 #include "stg_timer.h"
39 #include "stg/users.h"
40 #include "stg/common.h"
41 #include "stg/scriptexecuter.h"
42 #include "stg/tariff.h"
43 #include "stg/tariffs.h"
44 #include "stg/services.h"
45 #include "stg/service_conf.h"
46 #include "stg/admin.h"
57 #include <unistd.h> // access
64 std::string dirsToString(const bool * dirs)
67 for (size_t i = 0; i < DIR_NUM; i++)
68 res += dirs[i] ? '1' : '0';
72 void dirsFromBits(bool * dirs, uint32_t bits)
74 for (size_t i = 0; i < DIR_NUM; i++)
75 dirs[i] = bits & (1 << i);
80 UserImpl::UserImpl(const Settings * s,
85 const Services & svcs)
88 WriteServLog(Logger::get()),
92 connected(__connected),
95 lastIPForDisconnect(0),
103 authorizedModificationTime(0),
106 lastWriteDetailedStat(0),
107 cash(properties.cash),
109 down(properties.down),
110 lastCashAdd(properties.lastCashAdd),
111 passiveTime(properties.passiveTime),
112 lastCashAddTime(properties.lastCashAddTime),
113 freeMb(properties.freeMb),
114 lastActivityTime(properties.lastActivityTime),
115 password(properties.password),
116 passive(properties.passive),
117 disabled(properties.disabled),
118 disabledDetailStat(properties.disabledDetailStat),
119 alwaysOnline(properties.alwaysOnline),
120 tariffName(properties.tariffName),
121 nextTariff(properties.nextTariff),
122 address(properties.address),
123 note(properties.note),
124 group(properties.group),
125 email(properties.email),
126 phone(properties.phone),
127 realName(properties.realName),
128 credit(properties.credit),
129 creditExpire(properties.creditExpire),
131 userdata0(properties.userdata0),
132 userdata1(properties.userdata1),
133 userdata2(properties.userdata2),
134 userdata3(properties.userdata3),
135 userdata4(properties.userdata4),
136 userdata5(properties.userdata5),
137 userdata6(properties.userdata6),
138 userdata7(properties.userdata7),
139 userdata8(properties.userdata8),
140 userdata9(properties.userdata9),
141 sessionUploadModTime(stgTime),
142 sessionDownloadModTime(stgTime),
143 passiveNotifier(this),
144 disabledNotifier(this),
145 tariffNotifier(this),
151 //-----------------------------------------------------------------------------
152 void UserImpl::Init()
154 password = "*_EMPTY_PASSWORD_*";
155 tariffName = NO_TARIFF_NAME;
156 tariff = tariffs->FindByName(tariffName);
157 ips = UserIPs::parse("*");
158 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
159 lastWriteDetailedStat = stgTime;
161 properties.tariffName.AddBeforeNotifier(&tariffNotifier);
162 properties.passive.AddBeforeNotifier(&passiveNotifier);
163 properties.disabled.AddAfterNotifier(&disabledNotifier);
164 properties.cash.AddBeforeNotifier(&cashNotifier);
165 ips.AddAfterNotifier(&ipNotifier);
167 pthread_mutexattr_t attr;
168 pthread_mutexattr_init(&attr);
169 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
170 pthread_mutex_init(&mutex, &attr);
172 //-----------------------------------------------------------------------------
173 UserImpl::UserImpl(const UserImpl & u)
175 properties(*u.settings),
176 WriteServLog(Logger::get()),
181 connected(__connected),
182 __currIP(u.__currIP),
184 lastIPForDisconnect(0),
185 pingTime(u.pingTime),
186 sysAdmin(u.sysAdmin),
190 m_services(u.m_services),
191 traffStat(u.traffStat),
192 traffStatSaved(u.traffStatSaved),
193 settings(u.settings),
194 authorizedModificationTime(u.authorizedModificationTime),
195 messages(u.messages),
197 lastWriteStat(u.lastWriteStat),
198 lastWriteDetailedStat(u.lastWriteDetailedStat),
199 cash(properties.cash),
201 down(properties.down),
202 lastCashAdd(properties.lastCashAdd),
203 passiveTime(properties.passiveTime),
204 lastCashAddTime(properties.lastCashAddTime),
205 freeMb(properties.freeMb),
206 lastActivityTime(properties.lastActivityTime),
207 password(properties.password),
208 passive(properties.passive),
209 disabled(properties.disabled),
210 disabledDetailStat(properties.disabledDetailStat),
211 alwaysOnline(properties.alwaysOnline),
212 tariffName(properties.tariffName),
213 nextTariff(properties.nextTariff),
214 address(properties.address),
215 note(properties.note),
216 group(properties.group),
217 email(properties.email),
218 phone(properties.phone),
219 realName(properties.realName),
220 credit(properties.credit),
221 creditExpire(properties.creditExpire),
223 userdata0(properties.userdata0),
224 userdata1(properties.userdata1),
225 userdata2(properties.userdata2),
226 userdata3(properties.userdata3),
227 userdata4(properties.userdata4),
228 userdata5(properties.userdata5),
229 userdata6(properties.userdata6),
230 userdata7(properties.userdata7),
231 userdata8(properties.userdata8),
232 userdata9(properties.userdata9),
235 sessionUploadModTime(stgTime),
236 sessionDownloadModTime(stgTime),
237 passiveNotifier(this),
238 disabledNotifier(this),
239 tariffNotifier(this),
246 properties.tariffName.AddBeforeNotifier(&tariffNotifier);
247 properties.passive.AddBeforeNotifier(&passiveNotifier);
248 properties.disabled.AddAfterNotifier(&disabledNotifier);
249 properties.cash.AddBeforeNotifier(&cashNotifier);
250 ips.AddAfterNotifier(&ipNotifier);
252 properties.SetProperties(u.properties);
254 pthread_mutexattr_t attr;
255 pthread_mutexattr_init(&attr);
256 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
257 pthread_mutex_init(&mutex, &attr);
259 //-----------------------------------------------------------------------------
260 UserImpl::~UserImpl()
262 properties.tariffName.DelBeforeNotifier(&tariffNotifier);
263 properties.passive.DelBeforeNotifier(&passiveNotifier);
264 properties.disabled.DelAfterNotifier(&disabledNotifier);
265 properties.cash.DelBeforeNotifier(&cashNotifier);
266 pthread_mutex_destroy(&mutex);
268 //-----------------------------------------------------------------------------
269 void UserImpl::SetLogin(const std::string & l)
271 STG_LOCKER lock(&mutex);
272 static int idGen = 0;
273 assert(login.empty() && "Login is already set");
277 //-----------------------------------------------------------------------------
278 int UserImpl::ReadConf()
280 STG_LOCKER lock(&mutex);
283 if (store->RestoreUserConf(&conf, login))
285 WriteServLog("Cannot read conf for user %s.", login.c_str());
286 WriteServLog("%s", store->GetStrError().c_str());
287 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
288 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
292 properties.SetConf(conf);
294 tariff = tariffs->FindByName(tariffName);
297 WriteServLog("Cannot read user %s. Tariff %s not exist.",
298 login.c_str(), properties.tariffName.Get().c_str());
302 std::vector<Message::Header> hdrsList;
304 if (store->GetMessageHdrs(&hdrsList, login))
306 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
307 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
309 store->GetStrError().c_str());
313 std::vector<Message::Header>::const_iterator it;
314 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
317 if (store->GetMessage(it->id, &msg, login) == 0)
319 messages.push_back(msg);
325 //-----------------------------------------------------------------------------
326 int UserImpl::ReadStat()
328 STG_LOCKER lock(&mutex);
331 if (store->RestoreUserStat(&stat, login))
333 WriteServLog("Cannot read stat for user %s.", login.c_str());
334 WriteServLog("%s", store->GetStrError().c_str());
335 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
336 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
340 properties.SetStat(stat);
344 //-----------------------------------------------------------------------------
345 int UserImpl::WriteConf()
347 STG_LOCKER lock(&mutex);
348 UserConf conf(properties.GetConf());
350 printfd(__FILE__, "UserImpl::WriteConf()\n");
352 if (store->SaveUserConf(conf, login))
354 WriteServLog("Cannot write conf for user %s.", login.c_str());
355 WriteServLog("%s", store->GetStrError().c_str());
356 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
357 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
363 //-----------------------------------------------------------------------------
364 int UserImpl::WriteStat()
366 STG_LOCKER lock(&mutex);
367 UserStat stat(properties.GetStat());
369 if (store->SaveUserStat(stat, login))
371 WriteServLog("Cannot write stat for user %s.", login.c_str());
372 WriteServLog("%s", store->GetStrError().c_str());
373 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
374 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
378 lastWriteStat = stgTime;
382 //-----------------------------------------------------------------------------
383 int UserImpl::WriteMonthStat()
385 STG_LOCKER lock(&mutex);
386 time_t tt = stgTime - 3600;
388 localtime_r(&tt, &t1);
390 UserStat stat(properties.GetStat());
391 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
393 WriteServLog("Cannot write month stat for user %s.", login.c_str());
394 WriteServLog("%s", store->GetStrError().c_str());
395 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
396 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
402 //-----------------------------------------------------------------------------
403 int UserImpl::Authorize(uint32_t ip, uint32_t dirs, const Auth * auth)
405 STG_LOCKER lock(&mutex);
407 * Authorize user. It only means that user will be authorized. Nothing more.
408 * User can be connected or disconnected while authorized.
409 * Example: user is authorized but disconnected due to 0 money or blocking
413 * TODO: in fact "authorization" means allowing access to a service. What we
414 * call "authorization" here, int STG, is "authentication". So this should be
419 * Prevent double authorization by identical authorizers
421 if (authorizedBy.find(auth) != authorizedBy.end())
427 dirsFromBits(enabledDirs, dirs);
429 if (!authorizedBy.empty())
433 // We are already authorized, but with different IP address
434 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
439 if (!users->FindByIPIdx(ip, &u))
441 // Address presents in IP-index.
442 // If it's not our IP - report it.
445 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
452 if (users->IsIPInIndex(ip))
454 // Address is already present in IP-index.
455 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
459 if (ips.ConstData().find(ip))
462 lastIPForDisconnect = currIP;
466 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().toString().c_str());
467 errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
472 if (authorizedBy.empty())
473 authorizedModificationTime = stgTime;
474 authorizedBy.insert(auth);
480 //-----------------------------------------------------------------------------
481 void UserImpl::Unauthorize(const Auth * auth, const std::string & reason)
483 STG_LOCKER lock(&mutex);
485 * Authorizer tries to unauthorize user, that was not authorized by it
487 if (!authorizedBy.erase(auth))
490 authorizedModificationTime = stgTime;
492 if (authorizedBy.empty())
494 lastDisconnectReason = reason;
495 lastIPForDisconnect = currIP;
496 currIP = 0; // DelUser in traffcounter
498 Disconnect(false, "not authorized");
502 //-----------------------------------------------------------------------------
503 bool UserImpl::IsAuthorizedBy(const Auth * auth) const
505 STG_LOCKER lock(&mutex);
506 // Is this user authorized by specified authorizer?
507 return authorizedBy.find(auth) != authorizedBy.end();
509 //-----------------------------------------------------------------------------
510 std::vector<std::string> UserImpl::GetAuthorizers() const
512 STG_LOCKER lock(&mutex);
513 std::vector<std::string> list;
514 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), [](const auto auth){ return auth->GetVersion(); });
517 //-----------------------------------------------------------------------------
518 void UserImpl::Connect(bool fakeConnect)
521 * Connect user to Internet. This function is differ from Authorize() !!!
524 STG_LOCKER lock(&mutex);
528 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
530 if (access(scriptOnConnect.c_str(), X_OK) == 0)
532 std::string dirs = dirsToString(enabledDirs);
534 std::string scriptOnConnectParams;
535 strprintf(&scriptOnConnectParams,
536 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
537 scriptOnConnect.c_str(),
539 inet_ntostring(currIP).c_str(),
544 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
545 while (it != settings->GetScriptParams().end())
547 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
551 ScriptExec(scriptOnConnectParams.c_str());
555 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
561 if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP))
563 WriteServLog("Cannot write connect for user %s.", login.c_str());
564 WriteServLog("%s", store->GetStrError().c_str());
568 lastIPForDisconnect = currIP;
570 //-----------------------------------------------------------------------------
571 void UserImpl::Disconnect(bool fakeDisconnect, const std::string & reason)
574 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
577 STG_LOCKER lock(&mutex);
579 if (!lastIPForDisconnect)
581 printfd(__FILE__, "lastIPForDisconnect\n");
587 lastDisconnectReason = reason;
588 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
590 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
592 std::string dirs = dirsToString(enabledDirs);
594 std::string scriptOnDisonnectParams;
595 strprintf(&scriptOnDisonnectParams,
596 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
597 scriptOnDisonnect.c_str(),
599 inet_ntostring(lastIPForDisconnect).c_str(),
604 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
605 while (it != settings->GetScriptParams().end())
607 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
611 ScriptExec(scriptOnDisonnectParams.c_str());
615 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
621 std::string reasonMessage(reason);
622 if (!lastDisconnectReason.empty())
623 reasonMessage += ": " + lastDisconnectReason;
625 if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
626 cash, freeMb, reasonMessage))
628 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
629 WriteServLog("%s", store->GetStrError().c_str());
633 lastIPForDisconnect = 0;
635 sessionUpload.reset();
636 sessionDownload.reset();
637 sessionUploadModTime = stgTime;
638 sessionDownloadModTime = stgTime;
640 //-----------------------------------------------------------------------------
643 STG_LOCKER lock(&mutex);
645 if (stgTime > lastWriteStat + settings->GetStatWritePeriod())
647 printfd(__FILE__, "UserImpl::WriteStat user=%s\n", GetLogin().c_str());
650 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
652 WriteServLog("User: %s. Credit expired.", login.c_str());
658 if (passive.ConstData()
659 && (stgTime % 30 == 0)
660 && (passiveTime.ModificationTime() != stgTime))
662 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
663 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
666 if (!authorizedBy.empty())
669 properties.Stat().lastActivityTime = stgTime;
671 if (!connected && IsInetable())
674 if (connected && !IsInetable())
677 Disconnect(false, "disabled");
679 Disconnect(false, "passive");
681 Disconnect(false, "no cash");
684 if (stgTime - lastScanMessages > 10)
687 lastScanMessages = stgTime;
693 Disconnect(false, "not authorized");
697 //-----------------------------------------------------------------------------
698 void UserImpl::UpdatePingTime(time_t t)
700 STG_LOCKER lock(&mutex);
706 //-----------------------------------------------------------------------------
707 bool UserImpl::IsInetable()
709 if (disabled || passive)
712 if (settings->GetFreeMbAllowInet())
718 if (settings->GetShowFeeInCash() || tariff == NULL)
719 return (cash >= -credit);
721 return (cash - tariff->GetFee() >= -credit);
723 //-----------------------------------------------------------------------------
724 std::string UserImpl::GetEnabledDirs() const
726 return dirsToString(enabledDirs);
728 //-----------------------------------------------------------------------------
729 #ifdef TRAFF_STAT_WITH_PORTS
730 void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
732 void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
735 STG_LOCKER lock(&mutex);
737 if (!connected || tariff == NULL)
743 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
744 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
748 int tt = tariff->GetTraffType();
749 if (tt == Tariff::TRAFF_UP ||
750 tt == Tariff::TRAFF_UP_DOWN ||
751 // Check NEW traff data
752 (tt == Tariff::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
755 if (traff < threshold &&
756 traff + len >= threshold)
758 // cash = partBeforeThreshold * priceBeforeThreshold +
759 // partAfterThreshold * priceAfterThreshold
760 int64_t before = threshold - traff; // Chunk part before threshold
761 int64_t after = len - before; // Chunk part after threshold
762 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
763 down.ConstData()[dir],
766 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
767 down.ConstData()[dir],
773 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
774 down.ConstData()[dir],
779 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
781 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
782 cost = dc - freeMb.ConstData();
784 // Direct access to internal data structures via friend-specifier
785 properties.Stat().freeMb -= dc;
786 properties.Stat().cash -= cost;
792 sessionUpload[dir] += len;
793 sessionUploadModTime = stgTime;
797 if (!settings->GetWriteFreeMbTraffCost() &&
798 freeMb.ConstData() >= 0)
801 #ifdef TRAFF_STAT_WITH_PORTS
802 IPDirPair idp(ip, dir, port);
804 IPDirPair idp(ip, dir);
807 std::map<IPDirPair, StatNode>::iterator lb;
808 lb = traffStat.lower_bound(idp);
809 if (lb == traffStat.end() || lb->first != idp)
813 StatNode(len, 0, cost)));
817 lb->second.cash += cost;
818 lb->second.up += len;
821 //-----------------------------------------------------------------------------
822 #ifdef TRAFF_STAT_WITH_PORTS
823 void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
825 void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
828 STG_LOCKER lock(&mutex);
830 if (!connected || tariff == NULL)
836 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
837 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
841 int tt = tariff->GetTraffType();
842 if (tt == Tariff::TRAFF_DOWN ||
843 tt == Tariff::TRAFF_UP_DOWN ||
844 // Check NEW traff data
845 (tt == Tariff::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
848 if (traff < threshold &&
849 traff + len >= threshold)
851 // cash = partBeforeThreshold * priceBeforeThreshold +
852 // partAfterThreshold * priceAfterThreshold
853 int64_t before = threshold - traff; // Chunk part before threshold
854 int64_t after = len - before; // Chunk part after threshold
855 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
856 down.ConstData()[dir], // Traff before chunk
859 tariff->GetPriceWithTraffType(up.ConstData()[dir],
860 dt[dir], // Traff after chunk
866 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
867 down.ConstData()[dir],
872 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
874 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
875 cost = dc - freeMb.ConstData();
877 properties.Stat().freeMb -= dc;
878 properties.Stat().cash -= cost;
884 sessionDownload[dir] += len;
885 sessionDownloadModTime = stgTime;
889 if (!settings->GetWriteFreeMbTraffCost() &&
890 freeMb.ConstData() >= 0)
893 #ifdef TRAFF_STAT_WITH_PORTS
894 IPDirPair idp(ip, dir, port);
896 IPDirPair idp(ip, dir);
899 std::map<IPDirPair, StatNode>::iterator lb;
900 lb = traffStat.lower_bound(idp);
901 if (lb == traffStat.end() || lb->first != idp)
905 StatNode(0, len, cost)));
909 lb->second.cash += cost;
910 lb->second.down += len;
913 //-----------------------------------------------------------------------------
914 void UserImpl::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
916 STG_LOCKER lock(&mutex);
917 currIP.AddBeforeNotifier(notifier);
919 //-----------------------------------------------------------------------------
920 void UserImpl::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
922 STG_LOCKER lock(&mutex);
923 currIP.DelBeforeNotifier(notifier);
925 //-----------------------------------------------------------------------------
926 void UserImpl::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
928 STG_LOCKER lock(&mutex);
929 currIP.AddAfterNotifier(notifier);
931 //-----------------------------------------------------------------------------
932 void UserImpl::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
934 STG_LOCKER lock(&mutex);
935 currIP.DelAfterNotifier(notifier);
937 //-----------------------------------------------------------------------------
938 void UserImpl::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
940 STG_LOCKER lock(&mutex);
941 connected.AddBeforeNotifier(notifier);
943 //-----------------------------------------------------------------------------
944 void UserImpl::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
946 STG_LOCKER lock(&mutex);
947 connected.DelBeforeNotifier(notifier);
949 //-----------------------------------------------------------------------------
950 void UserImpl::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
952 STG_LOCKER lock(&mutex);
953 connected.AddAfterNotifier(notifier);
955 //-----------------------------------------------------------------------------
956 void UserImpl::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
958 STG_LOCKER lock(&mutex);
959 connected.DelAfterNotifier(notifier);
961 //-----------------------------------------------------------------------------
962 void UserImpl::OnAdd()
964 STG_LOCKER lock(&mutex);
966 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
968 if (access(scriptOnAdd.c_str(), X_OK) == 0)
970 std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
972 ScriptExec(scriptOnAddParams.c_str());
976 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
979 //-----------------------------------------------------------------------------
980 void UserImpl::OnDelete()
982 STG_LOCKER lock(&mutex);
984 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
986 if (access(scriptOnDel.c_str(), X_OK) == 0)
988 std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
990 ScriptExec(scriptOnDelParams.c_str());
994 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
999 //-----------------------------------------------------------------------------
1000 int UserImpl::WriteDetailStat(bool hard)
1002 printfd(__FILE__, "UserImpl::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1004 if (!traffStatSaved.second.empty())
1006 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1008 printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write detail stat from queue\n");
1009 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1010 WriteServLog("%s", store->GetStrError().c_str());
1013 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1019 STG_LOCKER lock(&mutex);
1023 printfd(__FILE__, "UserImpl::WriteDetailedStat() - size = %d\n", ts.size());
1025 if (ts.size() && !disabledDetailStat)
1027 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1029 printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write current detail stat\n");
1030 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1031 WriteServLog("%s", store->GetStrError().c_str());
1034 printfd(__FILE__, "UserImpl::WriteDetailStat() - pushing detail stat to queue\n");
1035 STG_LOCKER lock(&mutex);
1036 traffStatSaved.second.swap(ts);
1037 traffStatSaved.first = lastWriteDetailedStat;
1042 lastWriteDetailedStat = stgTime;
1045 //-----------------------------------------------------------------------------
1046 double UserImpl::GetPassiveTimePart() const
1048 STG_LOCKER lock(&mutex);
1050 static const std::array<unsigned, 12> daysInMonth{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1054 localtime_r(&t, &tms);
1056 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1058 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1061 secMonth += 24 * 3600;
1064 time_t dt = secMonth - passiveTime;
1069 return static_cast<double>(dt) / secMonth;
1071 //-----------------------------------------------------------------------------
1072 void UserImpl::SetPassiveTimeAsNewUser()
1074 STG_LOCKER lock(&mutex);
1078 localtime_r(&t, &tm);
1079 int daysCurrMon = DaysInCurrentMonth();
1080 double pt = tm.tm_mday - 1;
1083 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1085 //-----------------------------------------------------------------------------
1086 void UserImpl::MidnightResetSessionStat()
1088 STG_LOCKER lock(&mutex);
1092 Disconnect(true, "fake");
1096 //-----------------------------------------------------------------------------
1097 void UserImpl::ProcessNewMonth()
1099 STG_LOCKER lock(&mutex);
1102 Disconnect(true, "fake");
1106 properties.Stat().monthUp.reset();
1107 properties.Stat().monthDown.reset();
1113 if (nextTariff.ConstData() != "")
1115 const Tariff * nt = tariffs->FindByName(nextTariff);
1118 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1119 login.c_str(), properties.tariffName.Get().c_str());
1123 std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime);
1124 if (message.empty())
1126 properties.tariffName.Set(nextTariff, *sysAdmin, login, *store);
1130 WriteServLog("Tariff change is prohibited for user %s. %s",
1139 //-----------------------------------------------------------------------------
1140 void UserImpl::ProcessDayFeeSpread()
1142 STG_LOCKER lock(&mutex);
1144 if (passive.ConstData() || tariff == NULL)
1147 if (tariff->GetPeriod() != Tariff::MONTH)
1150 double fee = tariff->GetFee() / DaysInCurrentMonth();
1152 if (std::fabs(fee) < 1.0e-3)
1156 switch (settings->GetFeeChargeType())
1159 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1162 if (c + credit >= 0)
1163 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1166 if (c + credit >= fee)
1167 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1171 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1176 //-----------------------------------------------------------------------------
1177 void UserImpl::ProcessDayFee()
1179 STG_LOCKER lock(&mutex);
1184 if (tariff->GetPeriod() != Tariff::MONTH)
1187 double passiveTimePart = 1.0;
1188 if (!settings->GetFullFee())
1190 passiveTimePart = GetPassiveTimePart();
1194 if (passive.ConstData())
1196 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1200 double fee = tariff->GetFee() * passiveTimePart;
1204 if (std::fabs(fee) < 1.0e-3)
1211 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1218 switch (settings->GetFeeChargeType())
1221 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1225 if (c + credit >= 0)
1227 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1232 if (c + credit >= fee)
1234 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1241 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1247 //-----------------------------------------------------------------------------
1248 void UserImpl::ProcessDailyFee()
1250 STG_LOCKER lock(&mutex);
1252 if (passive.ConstData() || tariff == NULL)
1255 if (tariff->GetPeriod() != Tariff::DAY)
1258 double fee = tariff->GetFee();
1264 switch (settings->GetFeeChargeType())
1267 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1270 if (c + credit >= 0)
1271 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1274 if (c + credit >= fee)
1275 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1280 //-----------------------------------------------------------------------------
1281 void UserImpl::ProcessServices()
1285 localtime_r(&t, &tms);
1287 double passiveTimePart = 1.0;
1288 if (!settings->GetFullFee())
1290 passiveTimePart = GetPassiveTimePart();
1294 if (passive.ConstData())
1296 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1301 for (size_t i = 0; i < properties.Conf().services.size(); ++i)
1304 if (m_services.Find(properties.Conf().services[i], &conf))
1306 if (conf.payDay == tms.tm_mday ||
1307 (conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth()))
1310 double fee = conf.cost * passiveTimePart;
1311 printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1318 switch (settings->GetFeeChargeType())
1321 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1325 if (c + credit >= 0)
1327 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1332 if (c + credit >= fee)
1334 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1341 properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
1349 //-----------------------------------------------------------------------------
1350 void UserImpl::SetPrepaidTraff()
1353 properties.freeMb.Set(tariff->GetFree(), *sysAdmin, login, *store, "Prepaid traffic");
1355 //-----------------------------------------------------------------------------
1356 int UserImpl::AddMessage(Message * msg)
1358 STG_LOCKER lock(&mutex);
1360 if (SendMessage(*msg))
1362 if (store->AddMessage(msg, login))
1364 errorStr = store->GetStrError();
1365 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1366 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1369 messages.push_back(*msg);
1373 if (msg->header.repeat > 0)
1375 msg->header.repeat--;
1377 //TODO: gcc v. 4.x generate ICE on x86_64
1378 msg->header.lastSendTime = static_cast<int>(time(NULL));
1380 msg->header.lastSendTime = static_cast<int>(stgTime);
1382 if (store->AddMessage(msg, login))
1384 errorStr = store->GetStrError();
1385 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1386 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1389 messages.push_back(*msg);
1394 //-----------------------------------------------------------------------------
1395 int UserImpl::SendMessage(Message & msg) const
1397 // No lock `cause we are already locked from caller
1399 std::set<const Auth*>::iterator it(authorizedBy.begin());
1400 while (it != authorizedBy.end())
1402 if (!(*it++)->SendMessage(msg, currIP))
1408 //TODO: gcc v. 4.x generate ICE on x86_64
1409 msg.header.lastSendTime = static_cast<int>(time(NULL));
1411 msg.header.lastSendTime = static_cast<int>(stgTime);
1413 msg.header.repeat--;
1417 //-----------------------------------------------------------------------------
1418 void UserImpl::ScanMessage()
1420 // No lock `cause we are already locked from caller
1421 // We need not check for the authorizedBy `cause it has already checked by caller
1423 auto it = messages.begin();
1424 while (it != messages.end())
1426 if (settings->GetMessageTimeout() > 0 &&
1427 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1430 if (store->DelMessage(it->header.id, login))
1432 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1433 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1435 messages.erase(it++);
1438 if (it->GetNextSendTime() <= stgTime)
1440 if (SendMessage(*it))
1442 // We need to check all messages in queue for timeout
1446 if (it->header.repeat < 0)
1448 if (store->DelMessage(it->header.id, login))
1450 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1451 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1453 messages.erase(it++);
1457 if (store->EditMessage(*it, login))
1459 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1460 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1471 //-----------------------------------------------------------------------------
1472 std::string UserImpl::GetParamValue(const std::string & name) const
1474 std::string lowerName = ToLower(name);
1475 if (lowerName == "id")
1477 std::ostringstream stream;
1479 return stream.str();
1481 if (lowerName == "login") return login;
1482 if (lowerName == "currip") return currIP.ToString();
1483 if (lowerName == "enableddirs") return GetEnabledDirs();
1484 if (lowerName == "tariff") return properties.tariffName;
1485 if (properties.Exists(lowerName))
1486 return properties.GetPropertyValue(lowerName);
1489 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1493 //-----------------------------------------------------------------------------
1494 //-----------------------------------------------------------------------------
1495 //-----------------------------------------------------------------------------
1496 void STG::CHG_PASSIVE_NOTIFIER::notify(const int & oldPassive, const int & newPassive)
1498 if (newPassive && !oldPassive && user->tariff != NULL)
1499 user->properties.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1505 //-----------------------------------------------------------------------------
1506 void STG::CHG_DISABLED_NOTIFIER::notify(const int & oldValue, const int & newValue)
1508 if (oldValue && !newValue && user->GetConnected())
1509 user->Disconnect(false, "disabled");
1510 else if (!oldValue && newValue && user->IsInetable())
1511 user->Connect(false);
1513 //-----------------------------------------------------------------------------
1514 void STG::CHG_TARIFF_NOTIFIER::notify(const std::string &, const std::string & newTariff)
1516 STG_LOCKER lock(&user->mutex);
1517 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1518 user->Disconnect(false, "Change tariff");
1519 user->tariff = user->tariffs->FindByName(newTariff);
1520 if (user->settings->GetReconnectOnTariffChange() &&
1521 !user->authorizedBy.empty() &&
1524 // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name.
1525 user->properties.Conf().tariffName = newTariff;
1526 user->Connect(false);
1529 //-----------------------------------------------------------------------------
1530 void STG::CHG_CASH_NOTIFIER::notify(const double & oldCash, const double & newCash)
1532 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1533 user->lastCashAdd = newCash - oldCash;
1535 //-----------------------------------------------------------------------------
1536 void STG::CHG_IPS_NOTIFIER::notify(const UserIPs & from, const UserIPs & to)
1538 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.toString().c_str(), to.toString().c_str());
1539 if (user->connected)
1540 user->Disconnect(false, "Change IP");
1541 if (!user->authorizedBy.empty() && user->IsInetable())
1542 user->Connect(false);