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/admin.h"
54 #include <unistd.h> // access
59 std::string dirsToString(const bool * dirs)
62 for (size_t i = 0; i < DIR_NUM; i++)
63 res += dirs[i] ? '1' : '0';
67 void dirsFromBits(bool * dirs, uint32_t bits)
69 for (size_t i = 0; i < DIR_NUM; i++)
70 dirs[i] = bits & (1 << i);
75 #ifdef USE_ABSTRACT_SETTINGS
76 USER_IMPL::USER_IMPL(const SETTINGS * s,
81 const SERVICES & svcs)
83 property(s->GetScriptsDir()),
84 WriteServLog(GetStgLogger()),
88 connected(__connected),
91 lastIPForDisconnect(0),
99 authorizedModificationTime(0),
102 lastWriteDetailedStat(0),
106 lastCashAdd(property.lastCashAdd),
107 passiveTime(property.passiveTime),
108 lastCashAddTime(property.lastCashAddTime),
109 freeMb(property.freeMb),
110 lastActivityTime(property.lastActivityTime),
111 password(property.password),
112 passive(property.passive),
113 disabled(property.disabled),
114 disabledDetailStat(property.disabledDetailStat),
115 alwaysOnline(property.alwaysOnline),
116 tariffName(property.tariffName),
117 nextTariff(property.nextTariff),
118 address(property.address),
120 group(property.group),
121 email(property.email),
122 phone(property.phone),
123 realName(property.realName),
124 credit(property.credit),
125 creditExpire(property.creditExpire),
127 userdata0(property.userdata0),
128 userdata1(property.userdata1),
129 userdata2(property.userdata2),
130 userdata3(property.userdata3),
131 userdata4(property.userdata4),
132 userdata5(property.userdata5),
133 userdata6(property.userdata6),
134 userdata7(property.userdata7),
135 userdata8(property.userdata8),
136 userdata9(property.userdata9),
137 passiveNotifier(this),
138 disabledNotifier(this),
139 tariffNotifier(this),
146 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
151 const SERVICES & svcs)
153 property(s->GetScriptsDir()),
154 WriteServLog(GetStgLogger()),
158 connected(__connected),
161 lastIPForDisconnect(0),
169 authorizedModificationTime(0),
172 lastWriteDetailedStat(0),
176 lastCashAdd(property.lastCashAdd),
177 passiveTime(property.passiveTime),
178 lastCashAddTime(property.lastCashAddTime),
179 freeMb(property.freeMb),
180 lastActivityTime(property.lastActivityTime),
181 password(property.password),
182 passive(property.passive),
183 disabled(property.disabled),
184 disabledDetailStat(property.disabledDetailStat),
185 alwaysOnline(property.alwaysOnline),
186 tariffName(property.tariffName),
187 nextTariff(property.nextTariff),
188 address(property.address),
190 group(property.group),
191 email(property.email),
192 phone(property.phone),
193 realName(property.realName),
194 credit(property.credit),
195 creditExpire(property.creditExpire),
197 userdata0(property.userdata0),
198 userdata1(property.userdata1),
199 userdata2(property.userdata2),
200 userdata3(property.userdata3),
201 userdata4(property.userdata4),
202 userdata5(property.userdata5),
203 userdata6(property.userdata6),
204 userdata7(property.userdata7),
205 userdata8(property.userdata8),
206 userdata9(property.userdata9),
207 passiveNotifier(this),
208 disabledNotifier(this),
209 tariffNotifier(this),
216 //-----------------------------------------------------------------------------
217 void USER_IMPL::Init()
219 password = "*_EMPTY_PASSWORD_*";
220 tariffName = NO_TARIFF_NAME;
222 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
223 lastWriteDetailedStat = stgTime;
225 property.tariffName.AddBeforeNotifier(&tariffNotifier);
226 property.passive.AddBeforeNotifier(&passiveNotifier);
227 property.disabled.AddAfterNotifier(&disabledNotifier);
228 property.cash.AddBeforeNotifier(&cashNotifier);
229 ips.AddAfterNotifier(&ipNotifier);
231 pthread_mutexattr_t attr;
232 pthread_mutexattr_init(&attr);
233 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
234 pthread_mutex_init(&mutex, &attr);
236 //-----------------------------------------------------------------------------
237 USER_IMPL::USER_IMPL(const USER_IMPL & u)
240 property(u.settings->GetScriptsDir()),
241 WriteServLog(GetStgLogger()),
246 connected(__connected),
247 userIDGenerator(u.userIDGenerator),
248 __currIP(u.__currIP),
250 lastIPForDisconnect(0),
251 pingTime(u.pingTime),
252 sysAdmin(u.sysAdmin),
256 m_services(u.m_services),
257 traffStat(u.traffStat),
258 traffStatSaved(u.traffStatSaved),
259 settings(u.settings),
260 authorizedModificationTime(u.authorizedModificationTime),
261 messages(u.messages),
263 lastWriteStat(u.lastWriteStat),
264 lastWriteDetailedStat(u.lastWriteDetailedStat),
268 lastCashAdd(property.lastCashAdd),
269 passiveTime(property.passiveTime),
270 lastCashAddTime(property.lastCashAddTime),
271 freeMb(property.freeMb),
272 lastActivityTime(property.lastActivityTime),
273 password(property.password),
274 passive(property.passive),
275 disabled(property.disabled),
276 disabledDetailStat(property.disabledDetailStat),
277 alwaysOnline(property.alwaysOnline),
278 tariffName(property.tariffName),
279 nextTariff(property.nextTariff),
280 address(property.address),
282 group(property.group),
283 email(property.email),
284 phone(property.phone),
285 realName(property.realName),
286 credit(property.credit),
287 creditExpire(property.creditExpire),
289 userdata0(property.userdata0),
290 userdata1(property.userdata1),
291 userdata2(property.userdata2),
292 userdata3(property.userdata3),
293 userdata4(property.userdata4),
294 userdata5(property.userdata5),
295 userdata6(property.userdata6),
296 userdata7(property.userdata7),
297 userdata8(property.userdata8),
298 userdata9(property.userdata9),
301 passiveNotifier(this),
302 disabledNotifier(this),
303 tariffNotifier(this),
310 property.tariffName.AddBeforeNotifier(&tariffNotifier);
311 property.passive.AddBeforeNotifier(&passiveNotifier);
312 property.disabled.AddAfterNotifier(&disabledNotifier);
313 property.cash.AddBeforeNotifier(&cashNotifier);
314 ips.AddAfterNotifier(&ipNotifier);
316 property.SetProperties(u.property);
318 pthread_mutexattr_t attr;
319 pthread_mutexattr_init(&attr);
320 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
321 pthread_mutex_init(&mutex, &attr);
323 //-----------------------------------------------------------------------------
324 USER_IMPL::~USER_IMPL()
326 property.tariffName.DelBeforeNotifier(&tariffNotifier);
327 property.passive.DelBeforeNotifier(&passiveNotifier);
328 property.disabled.DelAfterNotifier(&disabledNotifier);
329 property.cash.DelBeforeNotifier(&cashNotifier);
330 pthread_mutex_destroy(&mutex);
332 //-----------------------------------------------------------------------------
333 void USER_IMPL::SetLogin(const std::string & l)
335 STG_LOCKER lock(&mutex);
336 assert(login.empty() && "Login is already set");
338 id = userIDGenerator.GetNextID();
340 //-----------------------------------------------------------------------------
341 int USER_IMPL::ReadConf()
343 STG_LOCKER lock(&mutex);
346 if (store->RestoreUserConf(&conf, login))
348 WriteServLog("Cannot read conf for user %s.", login.c_str());
349 WriteServLog("%s", store->GetStrError().c_str());
350 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
351 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
355 property.SetConf(conf);
357 tariff = tariffs->FindByName(tariffName);
360 WriteServLog("Cannot read user %s. Tariff %s not exist.",
361 login.c_str(), property.tariffName.Get().c_str());
365 std::vector<STG_MSG_HDR> hdrsList;
367 if (store->GetMessageHdrs(&hdrsList, login))
369 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
370 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
372 store->GetStrError().c_str());
376 std::vector<STG_MSG_HDR>::const_iterator it;
377 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
380 if (store->GetMessage(it->id, &msg, login) == 0)
382 messages.push_back(msg);
388 //-----------------------------------------------------------------------------
389 int USER_IMPL::ReadStat()
391 STG_LOCKER lock(&mutex);
394 if (store->RestoreUserStat(&stat, login))
396 WriteServLog("Cannot read stat for user %s.", login.c_str());
397 WriteServLog("%s", store->GetStrError().c_str());
398 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
399 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
403 property.SetStat(stat);
407 //-----------------------------------------------------------------------------
408 int USER_IMPL::WriteConf()
410 STG_LOCKER lock(&mutex);
411 USER_CONF conf(property.GetConf());
413 printfd(__FILE__, "USER::WriteConf()\n");
415 if (store->SaveUserConf(conf, login))
417 WriteServLog("Cannot write conf for user %s.", login.c_str());
418 WriteServLog("%s", store->GetStrError().c_str());
419 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
420 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
426 //-----------------------------------------------------------------------------
427 int USER_IMPL::WriteStat()
429 STG_LOCKER lock(&mutex);
430 USER_STAT stat(property.GetStat());
432 if (store->SaveUserStat(stat, login))
434 WriteServLog("Cannot write stat for user %s.", login.c_str());
435 WriteServLog("%s", store->GetStrError().c_str());
436 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
437 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
441 lastWriteStat = stgTime;
445 //-----------------------------------------------------------------------------
446 int USER_IMPL::WriteMonthStat()
448 STG_LOCKER lock(&mutex);
449 time_t tt = stgTime - 3600;
451 localtime_r(&tt, &t1);
453 USER_STAT stat(property.GetStat());
454 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
456 WriteServLog("Cannot write month stat for user %s.", login.c_str());
457 WriteServLog("%s", store->GetStrError().c_str());
458 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
459 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
465 //-----------------------------------------------------------------------------
466 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
468 STG_LOCKER lock(&mutex);
470 * Authorize user. It only means that user will be authorized. Nothing more.
471 * User can be connected or disconnected while authorized.
472 * Example: user is authorized but disconnected due to 0 money or blocking
476 * TODO: in fact "authorization" means allowing access to a service. What we
477 * call "authorization" here, int STG, is "authentication". So this should be
482 * Prevent double authorization by identical authorizers
484 if (authorizedBy.find(auth) != authorizedBy.end())
490 dirsFromBits(enabledDirs, dirs);
492 if (!authorizedBy.empty())
496 // We are already authorized, but with different IP address
497 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
502 if (!users->FindByIPIdx(ip, &u))
504 // Address presents in IP-index.
505 // If it's not our IP - report it.
508 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
515 if (users->IsIPInIndex(ip))
517 // Address is already present in IP-index.
518 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
522 if (ips.ConstData().IsIPInIPS(ip))
525 lastIPForDisconnect = currIP;
529 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
530 errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
535 if (authorizedBy.empty())
536 authorizedModificationTime = stgTime;
537 authorizedBy.insert(auth);
543 //-----------------------------------------------------------------------------
544 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
546 STG_LOCKER lock(&mutex);
548 * Authorizer tries to unauthorize user, that was not authorized by it
550 if (!authorizedBy.erase(auth))
553 authorizedModificationTime = stgTime;
555 if (authorizedBy.empty())
557 lastDisconnectReason = reason;
558 lastIPForDisconnect = currIP;
559 currIP = 0; // DelUser in traffcounter
563 //-----------------------------------------------------------------------------
564 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
566 STG_LOCKER lock(&mutex);
567 // Is this user authorized by specified authorizer?
568 return authorizedBy.find(auth) != authorizedBy.end();
570 //-----------------------------------------------------------------------------
571 std::vector<std::string> USER_IMPL::GetAuthorizers() const
573 STG_LOCKER lock(&mutex);
574 std::vector<std::string> list;
575 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
578 //-----------------------------------------------------------------------------
579 void USER_IMPL::Connect(bool fakeConnect)
582 * Connect user to Internet. This function is differ from Authorize() !!!
585 STG_LOCKER lock(&mutex);
589 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
591 if (access(scriptOnConnect.c_str(), X_OK) == 0)
593 std::string dirs = dirsToString(enabledDirs);
595 std::string scriptOnConnectParams;
596 strprintf(&scriptOnConnectParams,
597 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
598 scriptOnConnect.c_str(),
600 inet_ntostring(currIP).c_str(),
605 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
606 while (it != settings->GetScriptParams().end())
608 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
612 ScriptExec(scriptOnConnectParams.c_str());
616 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
622 if (store->WriteUserConnect(login, currIP))
624 WriteServLog("Cannot write connect for user %s.", login.c_str());
625 WriteServLog("%s", store->GetStrError().c_str());
629 lastIPForDisconnect = currIP;
631 //-----------------------------------------------------------------------------
632 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
635 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
638 STG_LOCKER lock(&mutex);
640 if (!lastIPForDisconnect)
642 printfd(__FILE__, "lastIPForDisconnect\n");
648 lastDisconnectReason = reason;
649 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
651 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
653 std::string dirs = dirsToString(enabledDirs);
655 std::string scriptOnDisonnectParams;
656 strprintf(&scriptOnDisonnectParams,
657 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
658 scriptOnDisonnect.c_str(),
660 inet_ntostring(lastIPForDisconnect).c_str(),
665 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
666 while (it != settings->GetScriptParams().end())
668 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
672 ScriptExec(scriptOnDisonnectParams.c_str());
676 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
682 std::string reasonMessage(reason);
683 if (!lastDisconnectReason.empty())
684 reasonMessage += ": " + lastDisconnectReason;
686 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
687 cash, freeMb, reasonMessage))
689 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
690 WriteServLog("%s", store->GetStrError().c_str());
694 lastIPForDisconnect = 0;
696 sessionUpload.Reset();
697 sessionDownload.Reset();
698 sessionUploadModTime = stgTime;
699 sessionDownloadModTime = stgTime;
701 //-----------------------------------------------------------------------------
702 void USER_IMPL::Run()
704 STG_LOCKER lock(&mutex);
706 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
708 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
711 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
713 WriteServLog("User: %s. Credit expired.", login.c_str());
719 if (passive.ConstData()
720 && (stgTime % 30 == 0)
721 && (passiveTime.ModificationTime() != stgTime))
723 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
724 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
727 if (!authorizedBy.empty())
730 property.Stat().lastActivityTime = stgTime;
732 if (!connected && IsInetable())
735 if (connected && !IsInetable())
738 Disconnect(false, "disabled");
740 Disconnect(false, "passive");
742 Disconnect(false, "no cash");
745 if (stgTime - lastScanMessages > 10)
748 lastScanMessages = stgTime;
754 Disconnect(false, "not authorized");
758 //-----------------------------------------------------------------------------
759 void USER_IMPL::UpdatePingTime(time_t t)
761 STG_LOCKER lock(&mutex);
767 //-----------------------------------------------------------------------------
768 bool USER_IMPL::IsInetable()
770 if (disabled || passive)
773 if (settings->GetFreeMbAllowInet())
779 if (settings->GetShowFeeInCash() || tariff == NULL)
780 return (cash >= -credit);
782 return (cash - tariff->GetFee() >= -credit);
784 //-----------------------------------------------------------------------------
785 std::string USER_IMPL::GetEnabledDirs() const
787 return dirsToString(enabledDirs);
789 //-----------------------------------------------------------------------------
790 #ifdef TRAFF_STAT_WITH_PORTS
791 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
793 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
796 STG_LOCKER lock(&mutex);
798 if (!connected || tariff == NULL)
804 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
805 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
809 int tt = tariff->GetTraffType();
810 if (tt == TARIFF::TRAFF_UP ||
811 tt == TARIFF::TRAFF_UP_DOWN ||
812 // Check NEW traff data
813 (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
816 if (traff < threshold &&
817 traff + len >= threshold)
819 // cash = partBeforeThreshold * priceBeforeThreshold +
820 // partAfterThreshold * priceAfterThreshold
821 int64_t before = threshold - traff; // Chunk part before threshold
822 int64_t after = len - before; // Chunk part after threshold
823 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
824 down.ConstData()[dir],
827 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
828 down.ConstData()[dir],
834 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
835 down.ConstData()[dir],
840 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
842 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
843 cost = dc - freeMb.ConstData();
845 // Direct access to internal data structures via friend-specifier
846 property.Stat().freeMb -= dc;
847 property.Stat().cash -= cost;
853 sessionUpload[dir] += len;
854 sessionUploadModTime = stgTime;
858 if (!settings->GetWriteFreeMbTraffCost() &&
859 freeMb.ConstData() >= 0)
862 #ifdef TRAFF_STAT_WITH_PORTS
863 IP_DIR_PAIR idp(ip, dir, port);
865 IP_DIR_PAIR idp(ip, dir);
868 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
869 lb = traffStat.lower_bound(idp);
870 if (lb == traffStat.end() || lb->first != idp)
874 STAT_NODE(len, 0, cost)));
878 lb->second.cash += cost;
879 lb->second.up += len;
882 //-----------------------------------------------------------------------------
883 #ifdef TRAFF_STAT_WITH_PORTS
884 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
886 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
889 STG_LOCKER lock(&mutex);
891 if (!connected || tariff == NULL)
897 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
898 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
902 int tt = tariff->GetTraffType();
903 if (tt == TARIFF::TRAFF_DOWN ||
904 tt == TARIFF::TRAFF_UP_DOWN ||
905 // Check NEW traff data
906 (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
909 if (traff < threshold &&
910 traff + len >= threshold)
912 // cash = partBeforeThreshold * priceBeforeThreshold +
913 // partAfterThreshold * priceAfterThreshold
914 int64_t before = threshold - traff; // Chunk part before threshold
915 int64_t after = len - before; // Chunk part after threshold
916 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
917 down.ConstData()[dir], // Traff before chunk
920 tariff->GetPriceWithTraffType(up.ConstData()[dir],
921 dt[dir], // Traff after chunk
927 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
928 down.ConstData()[dir],
933 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
935 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
936 cost = dc - freeMb.ConstData();
938 property.Stat().freeMb -= dc;
939 property.Stat().cash -= cost;
945 sessionDownload[dir] += len;
946 sessionDownloadModTime = stgTime;
950 if (!settings->GetWriteFreeMbTraffCost() &&
951 freeMb.ConstData() >= 0)
954 #ifdef TRAFF_STAT_WITH_PORTS
955 IP_DIR_PAIR idp(ip, dir, port);
957 IP_DIR_PAIR idp(ip, dir);
960 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
961 lb = traffStat.lower_bound(idp);
962 if (lb == traffStat.end() || lb->first != idp)
966 STAT_NODE(0, len, cost)));
970 lb->second.cash += cost;
971 lb->second.down += len;
974 //-----------------------------------------------------------------------------
975 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
977 STG_LOCKER lock(&mutex);
978 currIP.AddBeforeNotifier(notifier);
980 //-----------------------------------------------------------------------------
981 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
983 STG_LOCKER lock(&mutex);
984 currIP.DelBeforeNotifier(notifier);
986 //-----------------------------------------------------------------------------
987 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
989 STG_LOCKER lock(&mutex);
990 currIP.AddAfterNotifier(notifier);
992 //-----------------------------------------------------------------------------
993 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
995 STG_LOCKER lock(&mutex);
996 currIP.DelAfterNotifier(notifier);
998 //-----------------------------------------------------------------------------
999 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1001 STG_LOCKER lock(&mutex);
1002 connected.AddBeforeNotifier(notifier);
1004 //-----------------------------------------------------------------------------
1005 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1007 STG_LOCKER lock(&mutex);
1008 connected.DelBeforeNotifier(notifier);
1010 //-----------------------------------------------------------------------------
1011 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1013 STG_LOCKER lock(&mutex);
1014 connected.AddAfterNotifier(notifier);
1016 //-----------------------------------------------------------------------------
1017 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1019 STG_LOCKER lock(&mutex);
1020 connected.DelAfterNotifier(notifier);
1022 //-----------------------------------------------------------------------------
1023 void USER_IMPL::OnAdd()
1025 STG_LOCKER lock(&mutex);
1027 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1029 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1031 std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
1033 ScriptExec(scriptOnAddParams.c_str());
1037 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1040 //-----------------------------------------------------------------------------
1041 void USER_IMPL::OnDelete()
1043 STG_LOCKER lock(&mutex);
1045 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1047 if (access(scriptOnDel.c_str(), X_OK) == 0)
1049 std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
1051 ScriptExec(scriptOnDelParams.c_str());
1055 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1060 //-----------------------------------------------------------------------------
1061 int USER_IMPL::WriteDetailStat(bool hard)
1063 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1065 if (!traffStatSaved.second.empty())
1067 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1069 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1070 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1071 WriteServLog("%s", store->GetStrError().c_str());
1074 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1080 STG_LOCKER lock(&mutex);
1084 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1086 if (ts.size() && !disabledDetailStat)
1088 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1090 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1091 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1092 WriteServLog("%s", store->GetStrError().c_str());
1095 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1096 STG_LOCKER lock(&mutex);
1097 traffStatSaved.second.swap(ts);
1098 traffStatSaved.first = lastWriteDetailedStat;
1103 lastWriteDetailedStat = stgTime;
1106 //-----------------------------------------------------------------------------
1107 double USER_IMPL::GetPassiveTimePart() const
1109 STG_LOCKER lock(&mutex);
1111 static int daysInMonth[12] =
1112 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1116 localtime_r(&t, &tms);
1118 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1120 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1123 secMonth += 24 * 3600;
1126 time_t dt = secMonth - passiveTime;
1131 return static_cast<double>(dt) / secMonth;
1133 //-----------------------------------------------------------------------------
1134 void USER_IMPL::SetPassiveTimeAsNewUser()
1136 STG_LOCKER lock(&mutex);
1140 localtime_r(&t, &tm);
1141 int daysCurrMon = DaysInCurrentMonth();
1142 double pt = tm.tm_mday - 1;
1145 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1147 //-----------------------------------------------------------------------------
1148 void USER_IMPL::MidnightResetSessionStat()
1150 STG_LOCKER lock(&mutex);
1154 Disconnect(true, "fake");
1158 //-----------------------------------------------------------------------------
1159 void USER_IMPL::ProcessNewMonth()
1161 STG_LOCKER lock(&mutex);
1164 Disconnect(true, "fake");
1168 property.Stat().monthUp.Reset();
1169 property.Stat().monthDown.Reset();
1175 if (nextTariff.ConstData() != "")
1177 const TARIFF * nt = tariffs->FindByName(nextTariff);
1179 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1180 login.c_str(), property.tariffName.Get().c_str());
1182 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1187 //-----------------------------------------------------------------------------
1188 void USER_IMPL::ProcessDayFeeSpread()
1190 STG_LOCKER lock(&mutex);
1192 if (passive.ConstData() || tariff == NULL)
1195 if (tariff->GetPeriod() != TARIFF::MONTH)
1198 double fee = tariff->GetFee() / DaysInCurrentMonth();
1200 if (std::fabs(fee) < 1.0e-3)
1204 switch (settings->GetFeeChargeType())
1207 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1210 if (c + credit >= 0)
1211 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1214 if (c + credit >= fee)
1215 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1219 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1224 //-----------------------------------------------------------------------------
1225 void USER_IMPL::ProcessDayFee()
1227 STG_LOCKER lock(&mutex);
1232 if (tariff->GetPeriod() != TARIFF::MONTH)
1235 double passiveTimePart = 1.0;
1236 if (!settings->GetFullFee())
1238 passiveTimePart = GetPassiveTimePart();
1242 if (passive.ConstData())
1244 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1248 double fee = tariff->GetFee() * passiveTimePart;
1252 if (std::fabs(fee) < 1.0e-3)
1259 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1266 switch (settings->GetFeeChargeType())
1269 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1273 if (c + credit >= 0)
1275 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1280 if (c + credit >= fee)
1282 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1289 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1295 //-----------------------------------------------------------------------------
1296 void USER_IMPL::ProcessDailyFee()
1298 STG_LOCKER lock(&mutex);
1300 if (passive.ConstData() || tariff == NULL)
1303 if (tariff->GetPeriod() != TARIFF::DAY)
1306 double fee = tariff->GetFee();
1312 switch (settings->GetFeeChargeType())
1315 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1318 if (c + credit >= 0)
1319 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1322 if (c + credit >= fee)
1323 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1328 //-----------------------------------------------------------------------------
1329 void USER_IMPL::ProcessServices()
1333 localtime_r(&t, &tms);
1335 double passiveTimePart = 1.0;
1336 if (!settings->GetFullFee())
1338 passiveTimePart = GetPassiveTimePart();
1342 if (passive.ConstData())
1344 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1349 for (size_t i = 0; i < property.Conf().services.size(); ++i)
1352 if (m_services.Find(property.Conf().services[i], &conf))
1354 if (conf.payDay == tms.tm_mday ||
1355 conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth())
1358 double fee = conf.cost * passiveTimePart;
1359 printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1366 switch (settings->GetFeeChargeType())
1369 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1373 if (c + credit >= 0)
1375 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1380 if (c + credit >= fee)
1382 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1389 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1397 //-----------------------------------------------------------------------------
1398 void USER_IMPL::SetPrepaidTraff()
1401 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1403 //-----------------------------------------------------------------------------
1404 int USER_IMPL::AddMessage(STG_MSG * msg)
1406 STG_LOCKER lock(&mutex);
1408 if (SendMessage(*msg))
1410 if (store->AddMessage(msg, login))
1412 errorStr = store->GetStrError();
1413 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1414 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1417 messages.push_back(*msg);
1421 if (msg->header.repeat > 0)
1423 msg->header.repeat--;
1425 //TODO: gcc v. 4.x generate ICE on x86_64
1426 msg->header.lastSendTime = static_cast<int>(time(NULL));
1428 msg->header.lastSendTime = static_cast<int>(stgTime);
1430 if (store->AddMessage(msg, login))
1432 errorStr = store->GetStrError();
1433 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1434 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1437 messages.push_back(*msg);
1442 //-----------------------------------------------------------------------------
1443 int USER_IMPL::SendMessage(STG_MSG & msg) const
1445 // No lock `cause we are already locked from caller
1447 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1448 while (it != authorizedBy.end())
1450 if (!(*it++)->SendMessage(msg, currIP))
1456 //TODO: gcc v. 4.x generate ICE on x86_64
1457 msg.header.lastSendTime = static_cast<int>(time(NULL));
1459 msg.header.lastSendTime = static_cast<int>(stgTime);
1461 msg.header.repeat--;
1465 //-----------------------------------------------------------------------------
1466 void USER_IMPL::ScanMessage()
1468 // No lock `cause we are already locked from caller
1469 // We need not check for the authorizedBy `cause it has already checked by caller
1471 std::list<STG_MSG>::iterator it(messages.begin());
1472 while (it != messages.end())
1474 if (settings->GetMessageTimeout() > 0 &&
1475 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1478 if (store->DelMessage(it->header.id, login))
1480 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1481 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1483 messages.erase(it++);
1486 if (it->GetNextSendTime() <= stgTime)
1488 if (SendMessage(*it))
1490 // We need to check all messages in queue for timeout
1494 if (it->header.repeat < 0)
1496 if (store->DelMessage(it->header.id, login))
1498 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1499 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1501 messages.erase(it++);
1505 if (store->EditMessage(*it, login))
1507 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1508 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1519 //-----------------------------------------------------------------------------
1520 std::string USER_IMPL::GetParamValue(const std::string & name) const
1522 std::string lowerName = ToLower(name);
1523 if (lowerName == "id")
1525 std::ostringstream stream;
1527 return stream.str();
1529 if (lowerName == "login") return login;
1530 if (lowerName == "currip") return currIP.ToString();
1531 if (lowerName == "enableddirs") return GetEnabledDirs();
1532 if (lowerName == "tariff") return property.tariffName;
1533 if (property.Exists(lowerName))
1534 return property.GetPropertyValue(lowerName);
1537 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1541 //-----------------------------------------------------------------------------
1542 //-----------------------------------------------------------------------------
1543 //-----------------------------------------------------------------------------
1544 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1546 if (newPassive && !oldPassive && user->tariff != NULL)
1547 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1553 //-----------------------------------------------------------------------------
1554 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1556 if (oldValue && !newValue && user->GetConnected())
1557 user->Disconnect(false, "disabled");
1558 else if (!oldValue && newValue && user->IsInetable())
1559 user->Connect(false);
1561 //-----------------------------------------------------------------------------
1562 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1564 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1565 user->Disconnect(false, "Change tariff");
1566 user->tariff = user->tariffs->FindByName(newTariff);
1567 if (user->settings->GetReconnectOnTariffChange() &&
1568 !user->authorizedBy.empty() &&
1570 user->Connect(false);
1572 //-----------------------------------------------------------------------------
1573 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1575 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1576 user->lastCashAdd = newCash - oldCash;
1578 //-----------------------------------------------------------------------------
1579 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1581 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1582 if (user->connected)
1583 user->Disconnect(false, "Change IP");
1584 if (!user->authorizedBy.empty() && user->IsInetable())
1585 user->Connect(false);