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"
56 #include <unistd.h> // access
63 std::string dirsToString(const bool * dirs)
66 for (size_t i = 0; i < DIR_NUM; i++)
67 res += dirs[i] ? '1' : '0';
71 void dirsFromBits(bool * dirs, uint32_t bits)
73 for (size_t i = 0; i < DIR_NUM; i++)
74 dirs[i] = bits & (1 << i);
79 UserImpl::UserImpl(const Settings * s,
84 const Services & svcs)
87 WriteServLog(Logger::get()),
91 connected(__connected),
94 lastIPForDisconnect(0),
102 authorizedModificationTime(0),
105 lastWriteDetailedStat(0),
106 cash(properties.cash),
108 down(properties.down),
109 lastCashAdd(properties.lastCashAdd),
110 passiveTime(properties.passiveTime),
111 lastCashAddTime(properties.lastCashAddTime),
112 freeMb(properties.freeMb),
113 lastActivityTime(properties.lastActivityTime),
114 password(properties.password),
115 passive(properties.passive),
116 disabled(properties.disabled),
117 disabledDetailStat(properties.disabledDetailStat),
118 alwaysOnline(properties.alwaysOnline),
119 tariffName(properties.tariffName),
120 nextTariff(properties.nextTariff),
121 address(properties.address),
122 note(properties.note),
123 group(properties.group),
124 email(properties.email),
125 phone(properties.phone),
126 realName(properties.realName),
127 credit(properties.credit),
128 creditExpire(properties.creditExpire),
130 userdata0(properties.userdata0),
131 userdata1(properties.userdata1),
132 userdata2(properties.userdata2),
133 userdata3(properties.userdata3),
134 userdata4(properties.userdata4),
135 userdata5(properties.userdata5),
136 userdata6(properties.userdata6),
137 userdata7(properties.userdata7),
138 userdata8(properties.userdata8),
139 userdata9(properties.userdata9),
140 sessionUploadModTime(stgTime),
141 sessionDownloadModTime(stgTime),
142 passiveNotifier(this),
143 disabledNotifier(this),
144 tariffNotifier(this),
150 //-----------------------------------------------------------------------------
151 void UserImpl::Init()
153 password = "*_EMPTY_PASSWORD_*";
154 tariffName = NO_TARIFF_NAME;
155 tariff = tariffs->FindByName(tariffName);
156 ips = UserIPs::parse("*");
157 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
158 lastWriteDetailedStat = stgTime;
160 properties.tariffName.AddBeforeNotifier(&tariffNotifier);
161 properties.passive.AddBeforeNotifier(&passiveNotifier);
162 properties.disabled.AddAfterNotifier(&disabledNotifier);
163 properties.cash.AddBeforeNotifier(&cashNotifier);
164 ips.AddAfterNotifier(&ipNotifier);
166 pthread_mutexattr_t attr;
167 pthread_mutexattr_init(&attr);
168 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
169 pthread_mutex_init(&mutex, &attr);
171 //-----------------------------------------------------------------------------
172 UserImpl::UserImpl(const UserImpl & u)
174 properties(*u.settings),
175 WriteServLog(Logger::get()),
180 connected(__connected),
181 __currIP(u.__currIP),
183 lastIPForDisconnect(0),
184 pingTime(u.pingTime),
185 sysAdmin(u.sysAdmin),
189 m_services(u.m_services),
190 traffStat(u.traffStat),
191 traffStatSaved(u.traffStatSaved),
192 settings(u.settings),
193 authorizedModificationTime(u.authorizedModificationTime),
194 messages(u.messages),
196 lastWriteStat(u.lastWriteStat),
197 lastWriteDetailedStat(u.lastWriteDetailedStat),
198 cash(properties.cash),
200 down(properties.down),
201 lastCashAdd(properties.lastCashAdd),
202 passiveTime(properties.passiveTime),
203 lastCashAddTime(properties.lastCashAddTime),
204 freeMb(properties.freeMb),
205 lastActivityTime(properties.lastActivityTime),
206 password(properties.password),
207 passive(properties.passive),
208 disabled(properties.disabled),
209 disabledDetailStat(properties.disabledDetailStat),
210 alwaysOnline(properties.alwaysOnline),
211 tariffName(properties.tariffName),
212 nextTariff(properties.nextTariff),
213 address(properties.address),
214 note(properties.note),
215 group(properties.group),
216 email(properties.email),
217 phone(properties.phone),
218 realName(properties.realName),
219 credit(properties.credit),
220 creditExpire(properties.creditExpire),
222 userdata0(properties.userdata0),
223 userdata1(properties.userdata1),
224 userdata2(properties.userdata2),
225 userdata3(properties.userdata3),
226 userdata4(properties.userdata4),
227 userdata5(properties.userdata5),
228 userdata6(properties.userdata6),
229 userdata7(properties.userdata7),
230 userdata8(properties.userdata8),
231 userdata9(properties.userdata9),
234 sessionUploadModTime(stgTime),
235 sessionDownloadModTime(stgTime),
236 passiveNotifier(this),
237 disabledNotifier(this),
238 tariffNotifier(this),
245 properties.tariffName.AddBeforeNotifier(&tariffNotifier);
246 properties.passive.AddBeforeNotifier(&passiveNotifier);
247 properties.disabled.AddAfterNotifier(&disabledNotifier);
248 properties.cash.AddBeforeNotifier(&cashNotifier);
249 ips.AddAfterNotifier(&ipNotifier);
251 properties.SetProperties(u.properties);
253 pthread_mutexattr_t attr;
254 pthread_mutexattr_init(&attr);
255 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
256 pthread_mutex_init(&mutex, &attr);
258 //-----------------------------------------------------------------------------
259 UserImpl::~UserImpl()
261 properties.tariffName.DelBeforeNotifier(&tariffNotifier);
262 properties.passive.DelBeforeNotifier(&passiveNotifier);
263 properties.disabled.DelAfterNotifier(&disabledNotifier);
264 properties.cash.DelBeforeNotifier(&cashNotifier);
265 pthread_mutex_destroy(&mutex);
267 //-----------------------------------------------------------------------------
268 void UserImpl::SetLogin(const std::string & l)
270 STG_LOCKER lock(&mutex);
271 static int idGen = 0;
272 assert(login.empty() && "Login is already set");
276 //-----------------------------------------------------------------------------
277 int UserImpl::ReadConf()
279 STG_LOCKER lock(&mutex);
282 if (store->RestoreUserConf(&conf, login))
284 WriteServLog("Cannot read conf for user %s.", login.c_str());
285 WriteServLog("%s", store->GetStrError().c_str());
286 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
287 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
291 properties.SetConf(conf);
293 tariff = tariffs->FindByName(tariffName);
296 WriteServLog("Cannot read user %s. Tariff %s not exist.",
297 login.c_str(), properties.tariffName.Get().c_str());
301 std::vector<Message::Header> hdrsList;
303 if (store->GetMessageHdrs(&hdrsList, login))
305 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
306 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
308 store->GetStrError().c_str());
312 std::vector<Message::Header>::const_iterator it;
313 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
316 if (store->GetMessage(it->id, &msg, login) == 0)
318 messages.push_back(msg);
324 //-----------------------------------------------------------------------------
325 int UserImpl::ReadStat()
327 STG_LOCKER lock(&mutex);
330 if (store->RestoreUserStat(&stat, login))
332 WriteServLog("Cannot read stat for user %s.", login.c_str());
333 WriteServLog("%s", store->GetStrError().c_str());
334 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
335 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
339 properties.SetStat(stat);
343 //-----------------------------------------------------------------------------
344 int UserImpl::WriteConf()
346 STG_LOCKER lock(&mutex);
347 UserConf conf(properties.GetConf());
349 printfd(__FILE__, "UserImpl::WriteConf()\n");
351 if (store->SaveUserConf(conf, login))
353 WriteServLog("Cannot write conf for user %s.", login.c_str());
354 WriteServLog("%s", store->GetStrError().c_str());
355 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
356 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
362 //-----------------------------------------------------------------------------
363 int UserImpl::WriteStat()
365 STG_LOCKER lock(&mutex);
366 UserStat stat(properties.GetStat());
368 if (store->SaveUserStat(stat, login))
370 WriteServLog("Cannot write stat for user %s.", login.c_str());
371 WriteServLog("%s", store->GetStrError().c_str());
372 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
373 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
377 lastWriteStat = stgTime;
381 //-----------------------------------------------------------------------------
382 int UserImpl::WriteMonthStat()
384 STG_LOCKER lock(&mutex);
385 time_t tt = stgTime - 3600;
387 localtime_r(&tt, &t1);
389 UserStat stat(properties.GetStat());
390 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
392 WriteServLog("Cannot write month stat for user %s.", login.c_str());
393 WriteServLog("%s", store->GetStrError().c_str());
394 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
395 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
401 //-----------------------------------------------------------------------------
402 int UserImpl::Authorize(uint32_t ip, uint32_t dirs, const Auth * auth)
404 STG_LOCKER lock(&mutex);
406 * Authorize user. It only means that user will be authorized. Nothing more.
407 * User can be connected or disconnected while authorized.
408 * Example: user is authorized but disconnected due to 0 money or blocking
412 * TODO: in fact "authorization" means allowing access to a service. What we
413 * call "authorization" here, int STG, is "authentication". So this should be
418 * Prevent double authorization by identical authorizers
420 if (authorizedBy.find(auth) != authorizedBy.end())
426 dirsFromBits(enabledDirs, dirs);
428 if (!authorizedBy.empty())
432 // We are already authorized, but with different IP address
433 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
438 if (!users->FindByIPIdx(ip, &u))
440 // Address presents in IP-index.
441 // If it's not our IP - report it.
444 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
451 if (users->IsIPInIndex(ip))
453 // Address is already present in IP-index.
454 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
458 if (ips.ConstData().find(ip))
461 lastIPForDisconnect = currIP;
465 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().toString().c_str());
466 errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
471 if (authorizedBy.empty())
472 authorizedModificationTime = stgTime;
473 authorizedBy.insert(auth);
479 //-----------------------------------------------------------------------------
480 void UserImpl::Unauthorize(const Auth * auth, const std::string & reason)
482 STG_LOCKER lock(&mutex);
484 * Authorizer tries to unauthorize user, that was not authorized by it
486 if (!authorizedBy.erase(auth))
489 authorizedModificationTime = stgTime;
491 if (authorizedBy.empty())
493 lastDisconnectReason = reason;
494 lastIPForDisconnect = currIP;
495 currIP = 0; // DelUser in traffcounter
497 Disconnect(false, "not authorized");
501 //-----------------------------------------------------------------------------
502 bool UserImpl::IsAuthorizedBy(const Auth * auth) const
504 STG_LOCKER lock(&mutex);
505 // Is this user authorized by specified authorizer?
506 return authorizedBy.find(auth) != authorizedBy.end();
508 //-----------------------------------------------------------------------------
509 std::vector<std::string> UserImpl::GetAuthorizers() const
511 STG_LOCKER lock(&mutex);
512 std::vector<std::string> list;
513 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), [](const auto auth){ return auth->GetVersion(); });
516 //-----------------------------------------------------------------------------
517 void UserImpl::Connect(bool fakeConnect)
520 * Connect user to Internet. This function is differ from Authorize() !!!
523 STG_LOCKER lock(&mutex);
527 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
529 if (access(scriptOnConnect.c_str(), X_OK) == 0)
531 std::string dirs = dirsToString(enabledDirs);
533 std::string scriptOnConnectParams;
534 strprintf(&scriptOnConnectParams,
535 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
536 scriptOnConnect.c_str(),
538 inet_ntostring(currIP).c_str(),
543 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
544 while (it != settings->GetScriptParams().end())
546 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
550 ScriptExec(scriptOnConnectParams.c_str());
554 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
560 if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP))
562 WriteServLog("Cannot write connect for user %s.", login.c_str());
563 WriteServLog("%s", store->GetStrError().c_str());
567 lastIPForDisconnect = currIP;
569 //-----------------------------------------------------------------------------
570 void UserImpl::Disconnect(bool fakeDisconnect, const std::string & reason)
573 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
576 STG_LOCKER lock(&mutex);
578 if (!lastIPForDisconnect)
580 printfd(__FILE__, "lastIPForDisconnect\n");
586 lastDisconnectReason = reason;
587 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
589 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
591 std::string dirs = dirsToString(enabledDirs);
593 std::string scriptOnDisonnectParams;
594 strprintf(&scriptOnDisonnectParams,
595 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
596 scriptOnDisonnect.c_str(),
598 inet_ntostring(lastIPForDisconnect).c_str(),
603 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
604 while (it != settings->GetScriptParams().end())
606 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
610 ScriptExec(scriptOnDisonnectParams.c_str());
614 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
620 std::string reasonMessage(reason);
621 if (!lastDisconnectReason.empty())
622 reasonMessage += ": " + lastDisconnectReason;
624 if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
625 cash, freeMb, reasonMessage))
627 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
628 WriteServLog("%s", store->GetStrError().c_str());
632 lastIPForDisconnect = 0;
634 sessionUpload.reset();
635 sessionDownload.reset();
636 sessionUploadModTime = stgTime;
637 sessionDownloadModTime = stgTime;
639 //-----------------------------------------------------------------------------
642 STG_LOCKER lock(&mutex);
644 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
646 printfd(__FILE__, "UserImpl::WriteStat user=%s\n", GetLogin().c_str());
649 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
651 WriteServLog("User: %s. Credit expired.", login.c_str());
657 if (passive.ConstData()
658 && (stgTime % 30 == 0)
659 && (passiveTime.ModificationTime() != stgTime))
661 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
662 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
665 if (!authorizedBy.empty())
668 properties.Stat().lastActivityTime = stgTime;
670 if (!connected && IsInetable())
673 if (connected && !IsInetable())
676 Disconnect(false, "disabled");
678 Disconnect(false, "passive");
680 Disconnect(false, "no cash");
683 if (stgTime - lastScanMessages > 10)
686 lastScanMessages = stgTime;
692 Disconnect(false, "not authorized");
696 //-----------------------------------------------------------------------------
697 void UserImpl::UpdatePingTime(time_t t)
699 STG_LOCKER lock(&mutex);
705 //-----------------------------------------------------------------------------
706 bool UserImpl::IsInetable()
708 if (disabled || passive)
711 if (settings->GetFreeMbAllowInet())
717 if (settings->GetShowFeeInCash() || tariff == NULL)
718 return (cash >= -credit);
720 return (cash - tariff->GetFee() >= -credit);
722 //-----------------------------------------------------------------------------
723 std::string UserImpl::GetEnabledDirs() const
725 return dirsToString(enabledDirs);
727 //-----------------------------------------------------------------------------
728 #ifdef TRAFF_STAT_WITH_PORTS
729 void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
731 void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
734 STG_LOCKER lock(&mutex);
736 if (!connected || tariff == NULL)
742 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
743 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
747 int tt = tariff->GetTraffType();
748 if (tt == Tariff::TRAFF_UP ||
749 tt == Tariff::TRAFF_UP_DOWN ||
750 // Check NEW traff data
751 (tt == Tariff::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
754 if (traff < threshold &&
755 traff + len >= threshold)
757 // cash = partBeforeThreshold * priceBeforeThreshold +
758 // partAfterThreshold * priceAfterThreshold
759 int64_t before = threshold - traff; // Chunk part before threshold
760 int64_t after = len - before; // Chunk part after threshold
761 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
762 down.ConstData()[dir],
765 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
766 down.ConstData()[dir],
772 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
773 down.ConstData()[dir],
778 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
780 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
781 cost = dc - freeMb.ConstData();
783 // Direct access to internal data structures via friend-specifier
784 properties.Stat().freeMb -= dc;
785 properties.Stat().cash -= cost;
791 sessionUpload[dir] += len;
792 sessionUploadModTime = stgTime;
796 if (!settings->GetWriteFreeMbTraffCost() &&
797 freeMb.ConstData() >= 0)
800 #ifdef TRAFF_STAT_WITH_PORTS
801 IPDirPair idp(ip, dir, port);
803 IPDirPair idp(ip, dir);
806 std::map<IPDirPair, StatNode>::iterator lb;
807 lb = traffStat.lower_bound(idp);
808 if (lb == traffStat.end() || lb->first != idp)
812 StatNode(len, 0, cost)));
816 lb->second.cash += cost;
817 lb->second.up += len;
820 //-----------------------------------------------------------------------------
821 #ifdef TRAFF_STAT_WITH_PORTS
822 void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
824 void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
827 STG_LOCKER lock(&mutex);
829 if (!connected || tariff == NULL)
835 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
836 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
840 int tt = tariff->GetTraffType();
841 if (tt == Tariff::TRAFF_DOWN ||
842 tt == Tariff::TRAFF_UP_DOWN ||
843 // Check NEW traff data
844 (tt == Tariff::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
847 if (traff < threshold &&
848 traff + len >= threshold)
850 // cash = partBeforeThreshold * priceBeforeThreshold +
851 // partAfterThreshold * priceAfterThreshold
852 int64_t before = threshold - traff; // Chunk part before threshold
853 int64_t after = len - before; // Chunk part after threshold
854 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
855 down.ConstData()[dir], // Traff before chunk
858 tariff->GetPriceWithTraffType(up.ConstData()[dir],
859 dt[dir], // Traff after chunk
865 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
866 down.ConstData()[dir],
871 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
873 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
874 cost = dc - freeMb.ConstData();
876 properties.Stat().freeMb -= dc;
877 properties.Stat().cash -= cost;
883 sessionDownload[dir] += len;
884 sessionDownloadModTime = stgTime;
888 if (!settings->GetWriteFreeMbTraffCost() &&
889 freeMb.ConstData() >= 0)
892 #ifdef TRAFF_STAT_WITH_PORTS
893 IPDirPair idp(ip, dir, port);
895 IPDirPair idp(ip, dir);
898 std::map<IPDirPair, StatNode>::iterator lb;
899 lb = traffStat.lower_bound(idp);
900 if (lb == traffStat.end() || lb->first != idp)
904 StatNode(0, len, cost)));
908 lb->second.cash += cost;
909 lb->second.down += len;
912 //-----------------------------------------------------------------------------
913 void UserImpl::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
915 STG_LOCKER lock(&mutex);
916 currIP.AddBeforeNotifier(notifier);
918 //-----------------------------------------------------------------------------
919 void UserImpl::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
921 STG_LOCKER lock(&mutex);
922 currIP.DelBeforeNotifier(notifier);
924 //-----------------------------------------------------------------------------
925 void UserImpl::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
927 STG_LOCKER lock(&mutex);
928 currIP.AddAfterNotifier(notifier);
930 //-----------------------------------------------------------------------------
931 void UserImpl::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
933 STG_LOCKER lock(&mutex);
934 currIP.DelAfterNotifier(notifier);
936 //-----------------------------------------------------------------------------
937 void UserImpl::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
939 STG_LOCKER lock(&mutex);
940 connected.AddBeforeNotifier(notifier);
942 //-----------------------------------------------------------------------------
943 void UserImpl::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
945 STG_LOCKER lock(&mutex);
946 connected.DelBeforeNotifier(notifier);
948 //-----------------------------------------------------------------------------
949 void UserImpl::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
951 STG_LOCKER lock(&mutex);
952 connected.AddAfterNotifier(notifier);
954 //-----------------------------------------------------------------------------
955 void UserImpl::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
957 STG_LOCKER lock(&mutex);
958 connected.DelAfterNotifier(notifier);
960 //-----------------------------------------------------------------------------
961 void UserImpl::OnAdd()
963 STG_LOCKER lock(&mutex);
965 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
967 if (access(scriptOnAdd.c_str(), X_OK) == 0)
969 std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
971 ScriptExec(scriptOnAddParams.c_str());
975 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
978 //-----------------------------------------------------------------------------
979 void UserImpl::OnDelete()
981 STG_LOCKER lock(&mutex);
983 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
985 if (access(scriptOnDel.c_str(), X_OK) == 0)
987 std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
989 ScriptExec(scriptOnDelParams.c_str());
993 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
998 //-----------------------------------------------------------------------------
999 int UserImpl::WriteDetailStat(bool hard)
1001 printfd(__FILE__, "UserImpl::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1003 if (!traffStatSaved.second.empty())
1005 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1007 printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write detail stat from queue\n");
1008 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1009 WriteServLog("%s", store->GetStrError().c_str());
1012 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1018 STG_LOCKER lock(&mutex);
1022 printfd(__FILE__, "UserImpl::WriteDetailedStat() - size = %d\n", ts.size());
1024 if (ts.size() && !disabledDetailStat)
1026 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1028 printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write current detail stat\n");
1029 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1030 WriteServLog("%s", store->GetStrError().c_str());
1033 printfd(__FILE__, "UserImpl::WriteDetailStat() - pushing detail stat to queue\n");
1034 STG_LOCKER lock(&mutex);
1035 traffStatSaved.second.swap(ts);
1036 traffStatSaved.first = lastWriteDetailedStat;
1041 lastWriteDetailedStat = stgTime;
1044 //-----------------------------------------------------------------------------
1045 double UserImpl::GetPassiveTimePart() const
1047 STG_LOCKER lock(&mutex);
1049 static int daysInMonth[12] =
1050 {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);