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
561 Disconnect(false, "not authorized");
565 //-----------------------------------------------------------------------------
566 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
568 STG_LOCKER lock(&mutex);
569 // Is this user authorized by specified authorizer?
570 return authorizedBy.find(auth) != authorizedBy.end();
572 //-----------------------------------------------------------------------------
573 std::vector<std::string> USER_IMPL::GetAuthorizers() const
575 STG_LOCKER lock(&mutex);
576 std::vector<std::string> list;
577 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
580 //-----------------------------------------------------------------------------
581 void USER_IMPL::Connect(bool fakeConnect)
584 * Connect user to Internet. This function is differ from Authorize() !!!
587 STG_LOCKER lock(&mutex);
591 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
593 if (access(scriptOnConnect.c_str(), X_OK) == 0)
595 std::string dirs = dirsToString(enabledDirs);
597 std::string scriptOnConnectParams;
598 strprintf(&scriptOnConnectParams,
599 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
600 scriptOnConnect.c_str(),
602 inet_ntostring(currIP).c_str(),
607 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
608 while (it != settings->GetScriptParams().end())
610 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
614 ScriptExec(scriptOnConnectParams.c_str());
618 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
624 if (store->WriteUserConnect(login, currIP))
626 WriteServLog("Cannot write connect for user %s.", login.c_str());
627 WriteServLog("%s", store->GetStrError().c_str());
631 lastIPForDisconnect = currIP;
633 //-----------------------------------------------------------------------------
634 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
637 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
640 STG_LOCKER lock(&mutex);
642 if (!lastIPForDisconnect)
644 printfd(__FILE__, "lastIPForDisconnect\n");
650 lastDisconnectReason = reason;
651 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
653 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
655 std::string dirs = dirsToString(enabledDirs);
657 std::string scriptOnDisonnectParams;
658 strprintf(&scriptOnDisonnectParams,
659 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
660 scriptOnDisonnect.c_str(),
662 inet_ntostring(lastIPForDisconnect).c_str(),
667 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
668 while (it != settings->GetScriptParams().end())
670 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
674 ScriptExec(scriptOnDisonnectParams.c_str());
678 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
684 std::string reasonMessage(reason);
685 if (!lastDisconnectReason.empty())
686 reasonMessage += ": " + lastDisconnectReason;
688 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
689 cash, freeMb, reasonMessage))
691 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
692 WriteServLog("%s", store->GetStrError().c_str());
696 lastIPForDisconnect = 0;
698 sessionUpload.Reset();
699 sessionDownload.Reset();
700 sessionUploadModTime = stgTime;
701 sessionDownloadModTime = stgTime;
703 //-----------------------------------------------------------------------------
704 void USER_IMPL::Run()
706 STG_LOCKER lock(&mutex);
708 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
710 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
713 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
715 WriteServLog("User: %s. Credit expired.", login.c_str());
721 if (passive.ConstData()
722 && (stgTime % 30 == 0)
723 && (passiveTime.ModificationTime() != stgTime))
725 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
726 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
729 if (!authorizedBy.empty())
732 property.Stat().lastActivityTime = stgTime;
734 if (!connected && IsInetable())
737 if (connected && !IsInetable())
740 Disconnect(false, "disabled");
742 Disconnect(false, "passive");
744 Disconnect(false, "no cash");
747 if (stgTime - lastScanMessages > 10)
750 lastScanMessages = stgTime;
756 Disconnect(false, "not authorized");
760 //-----------------------------------------------------------------------------
761 void USER_IMPL::UpdatePingTime(time_t t)
763 STG_LOCKER lock(&mutex);
769 //-----------------------------------------------------------------------------
770 bool USER_IMPL::IsInetable()
772 if (disabled || passive)
775 if (settings->GetFreeMbAllowInet())
781 if (settings->GetShowFeeInCash() || tariff == NULL)
782 return (cash >= -credit);
784 return (cash - tariff->GetFee() >= -credit);
786 //-----------------------------------------------------------------------------
787 std::string USER_IMPL::GetEnabledDirs() const
789 return dirsToString(enabledDirs);
791 //-----------------------------------------------------------------------------
792 #ifdef TRAFF_STAT_WITH_PORTS
793 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
795 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
798 STG_LOCKER lock(&mutex);
800 if (!connected || tariff == NULL)
806 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
807 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
811 int tt = tariff->GetTraffType();
812 if (tt == TARIFF::TRAFF_UP ||
813 tt == TARIFF::TRAFF_UP_DOWN ||
814 // Check NEW traff data
815 (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
818 if (traff < threshold &&
819 traff + len >= threshold)
821 // cash = partBeforeThreshold * priceBeforeThreshold +
822 // partAfterThreshold * priceAfterThreshold
823 int64_t before = threshold - traff; // Chunk part before threshold
824 int64_t after = len - before; // Chunk part after threshold
825 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
826 down.ConstData()[dir],
829 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
830 down.ConstData()[dir],
836 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
837 down.ConstData()[dir],
842 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
844 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
845 cost = dc - freeMb.ConstData();
847 // Direct access to internal data structures via friend-specifier
848 property.Stat().freeMb -= dc;
849 property.Stat().cash -= cost;
855 sessionUpload[dir] += len;
856 sessionUploadModTime = stgTime;
860 if (!settings->GetWriteFreeMbTraffCost() &&
861 freeMb.ConstData() >= 0)
864 #ifdef TRAFF_STAT_WITH_PORTS
865 IP_DIR_PAIR idp(ip, dir, port);
867 IP_DIR_PAIR idp(ip, dir);
870 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
871 lb = traffStat.lower_bound(idp);
872 if (lb == traffStat.end() || lb->first != idp)
876 STAT_NODE(len, 0, cost)));
880 lb->second.cash += cost;
881 lb->second.up += len;
884 //-----------------------------------------------------------------------------
885 #ifdef TRAFF_STAT_WITH_PORTS
886 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
888 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
891 STG_LOCKER lock(&mutex);
893 if (!connected || tariff == NULL)
899 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
900 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
904 int tt = tariff->GetTraffType();
905 if (tt == TARIFF::TRAFF_DOWN ||
906 tt == TARIFF::TRAFF_UP_DOWN ||
907 // Check NEW traff data
908 (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
911 if (traff < threshold &&
912 traff + len >= threshold)
914 // cash = partBeforeThreshold * priceBeforeThreshold +
915 // partAfterThreshold * priceAfterThreshold
916 int64_t before = threshold - traff; // Chunk part before threshold
917 int64_t after = len - before; // Chunk part after threshold
918 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
919 down.ConstData()[dir], // Traff before chunk
922 tariff->GetPriceWithTraffType(up.ConstData()[dir],
923 dt[dir], // Traff after chunk
929 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
930 down.ConstData()[dir],
935 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
937 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
938 cost = dc - freeMb.ConstData();
940 property.Stat().freeMb -= dc;
941 property.Stat().cash -= cost;
947 sessionDownload[dir] += len;
948 sessionDownloadModTime = stgTime;
952 if (!settings->GetWriteFreeMbTraffCost() &&
953 freeMb.ConstData() >= 0)
956 #ifdef TRAFF_STAT_WITH_PORTS
957 IP_DIR_PAIR idp(ip, dir, port);
959 IP_DIR_PAIR idp(ip, dir);
962 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
963 lb = traffStat.lower_bound(idp);
964 if (lb == traffStat.end() || lb->first != idp)
968 STAT_NODE(0, len, cost)));
972 lb->second.cash += cost;
973 lb->second.down += len;
976 //-----------------------------------------------------------------------------
977 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
979 STG_LOCKER lock(&mutex);
980 currIP.AddBeforeNotifier(notifier);
982 //-----------------------------------------------------------------------------
983 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
985 STG_LOCKER lock(&mutex);
986 currIP.DelBeforeNotifier(notifier);
988 //-----------------------------------------------------------------------------
989 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
991 STG_LOCKER lock(&mutex);
992 currIP.AddAfterNotifier(notifier);
994 //-----------------------------------------------------------------------------
995 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
997 STG_LOCKER lock(&mutex);
998 currIP.DelAfterNotifier(notifier);
1000 //-----------------------------------------------------------------------------
1001 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1003 STG_LOCKER lock(&mutex);
1004 connected.AddBeforeNotifier(notifier);
1006 //-----------------------------------------------------------------------------
1007 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1009 STG_LOCKER lock(&mutex);
1010 connected.DelBeforeNotifier(notifier);
1012 //-----------------------------------------------------------------------------
1013 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1015 STG_LOCKER lock(&mutex);
1016 connected.AddAfterNotifier(notifier);
1018 //-----------------------------------------------------------------------------
1019 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1021 STG_LOCKER lock(&mutex);
1022 connected.DelAfterNotifier(notifier);
1024 //-----------------------------------------------------------------------------
1025 void USER_IMPL::OnAdd()
1027 STG_LOCKER lock(&mutex);
1029 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1031 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1033 std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
1035 ScriptExec(scriptOnAddParams.c_str());
1039 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1042 //-----------------------------------------------------------------------------
1043 void USER_IMPL::OnDelete()
1045 STG_LOCKER lock(&mutex);
1047 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1049 if (access(scriptOnDel.c_str(), X_OK) == 0)
1051 std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
1053 ScriptExec(scriptOnDelParams.c_str());
1057 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1062 //-----------------------------------------------------------------------------
1063 int USER_IMPL::WriteDetailStat(bool hard)
1065 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1067 if (!traffStatSaved.second.empty())
1069 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1071 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1072 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1073 WriteServLog("%s", store->GetStrError().c_str());
1076 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1082 STG_LOCKER lock(&mutex);
1086 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1088 if (ts.size() && !disabledDetailStat)
1090 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1092 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1093 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1094 WriteServLog("%s", store->GetStrError().c_str());
1097 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1098 STG_LOCKER lock(&mutex);
1099 traffStatSaved.second.swap(ts);
1100 traffStatSaved.first = lastWriteDetailedStat;
1105 lastWriteDetailedStat = stgTime;
1108 //-----------------------------------------------------------------------------
1109 double USER_IMPL::GetPassiveTimePart() const
1111 STG_LOCKER lock(&mutex);
1113 static int daysInMonth[12] =
1114 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1118 localtime_r(&t, &tms);
1120 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1122 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1125 secMonth += 24 * 3600;
1128 time_t dt = secMonth - passiveTime;
1133 return static_cast<double>(dt) / secMonth;
1135 //-----------------------------------------------------------------------------
1136 void USER_IMPL::SetPassiveTimeAsNewUser()
1138 STG_LOCKER lock(&mutex);
1142 localtime_r(&t, &tm);
1143 int daysCurrMon = DaysInCurrentMonth();
1144 double pt = tm.tm_mday - 1;
1147 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1149 //-----------------------------------------------------------------------------
1150 void USER_IMPL::MidnightResetSessionStat()
1152 STG_LOCKER lock(&mutex);
1156 Disconnect(true, "fake");
1160 //-----------------------------------------------------------------------------
1161 void USER_IMPL::ProcessNewMonth()
1163 STG_LOCKER lock(&mutex);
1166 Disconnect(true, "fake");
1170 property.Stat().monthUp.Reset();
1171 property.Stat().monthDown.Reset();
1177 if (nextTariff.ConstData() != "")
1179 const TARIFF * nt = tariffs->FindByName(nextTariff);
1181 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1182 login.c_str(), property.tariffName.Get().c_str());
1184 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1189 //-----------------------------------------------------------------------------
1190 void USER_IMPL::ProcessDayFeeSpread()
1192 STG_LOCKER lock(&mutex);
1194 if (passive.ConstData() || tariff == NULL)
1197 if (tariff->GetPeriod() != TARIFF::MONTH)
1200 double fee = tariff->GetFee() / DaysInCurrentMonth();
1202 if (std::fabs(fee) < 1.0e-3)
1206 switch (settings->GetFeeChargeType())
1209 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1212 if (c + credit >= 0)
1213 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1216 if (c + credit >= fee)
1217 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1221 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1226 //-----------------------------------------------------------------------------
1227 void USER_IMPL::ProcessDayFee()
1229 STG_LOCKER lock(&mutex);
1234 if (tariff->GetPeriod() != TARIFF::MONTH)
1237 double passiveTimePart = 1.0;
1238 if (!settings->GetFullFee())
1240 passiveTimePart = GetPassiveTimePart();
1244 if (passive.ConstData())
1246 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1250 double fee = tariff->GetFee() * passiveTimePart;
1254 if (std::fabs(fee) < 1.0e-3)
1261 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1268 switch (settings->GetFeeChargeType())
1271 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1275 if (c + credit >= 0)
1277 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1282 if (c + credit >= fee)
1284 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1291 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1297 //-----------------------------------------------------------------------------
1298 void USER_IMPL::ProcessDailyFee()
1300 STG_LOCKER lock(&mutex);
1302 if (passive.ConstData() || tariff == NULL)
1305 if (tariff->GetPeriod() != TARIFF::DAY)
1308 double fee = tariff->GetFee();
1314 switch (settings->GetFeeChargeType())
1317 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1320 if (c + credit >= 0)
1321 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1324 if (c + credit >= fee)
1325 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1330 //-----------------------------------------------------------------------------
1331 void USER_IMPL::ProcessServices()
1335 localtime_r(&t, &tms);
1337 double passiveTimePart = 1.0;
1338 if (!settings->GetFullFee())
1340 passiveTimePart = GetPassiveTimePart();
1344 if (passive.ConstData())
1346 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1351 for (size_t i = 0; i < property.Conf().services.size(); ++i)
1354 if (m_services.Find(property.Conf().services[i], &conf))
1356 if (conf.payDay == tms.tm_mday ||
1357 (conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth()))
1360 double fee = conf.cost * passiveTimePart;
1361 printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1368 switch (settings->GetFeeChargeType())
1371 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1375 if (c + credit >= 0)
1377 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1382 if (c + credit >= fee)
1384 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1391 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1399 //-----------------------------------------------------------------------------
1400 void USER_IMPL::SetPrepaidTraff()
1403 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1405 //-----------------------------------------------------------------------------
1406 int USER_IMPL::AddMessage(STG_MSG * msg)
1408 STG_LOCKER lock(&mutex);
1410 if (SendMessage(*msg))
1412 if (store->AddMessage(msg, login))
1414 errorStr = store->GetStrError();
1415 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1416 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1419 messages.push_back(*msg);
1423 if (msg->header.repeat > 0)
1425 msg->header.repeat--;
1427 //TODO: gcc v. 4.x generate ICE on x86_64
1428 msg->header.lastSendTime = static_cast<int>(time(NULL));
1430 msg->header.lastSendTime = static_cast<int>(stgTime);
1432 if (store->AddMessage(msg, login))
1434 errorStr = store->GetStrError();
1435 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1436 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1439 messages.push_back(*msg);
1444 //-----------------------------------------------------------------------------
1445 int USER_IMPL::SendMessage(STG_MSG & msg) const
1447 // No lock `cause we are already locked from caller
1449 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1450 while (it != authorizedBy.end())
1452 if (!(*it++)->SendMessage(msg, currIP))
1458 //TODO: gcc v. 4.x generate ICE on x86_64
1459 msg.header.lastSendTime = static_cast<int>(time(NULL));
1461 msg.header.lastSendTime = static_cast<int>(stgTime);
1463 msg.header.repeat--;
1467 //-----------------------------------------------------------------------------
1468 void USER_IMPL::ScanMessage()
1470 // No lock `cause we are already locked from caller
1471 // We need not check for the authorizedBy `cause it has already checked by caller
1473 std::list<STG_MSG>::iterator it(messages.begin());
1474 while (it != messages.end())
1476 if (settings->GetMessageTimeout() > 0 &&
1477 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1480 if (store->DelMessage(it->header.id, login))
1482 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1483 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1485 messages.erase(it++);
1488 if (it->GetNextSendTime() <= stgTime)
1490 if (SendMessage(*it))
1492 // We need to check all messages in queue for timeout
1496 if (it->header.repeat < 0)
1498 if (store->DelMessage(it->header.id, login))
1500 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1501 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1503 messages.erase(it++);
1507 if (store->EditMessage(*it, login))
1509 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1510 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1521 //-----------------------------------------------------------------------------
1522 std::string USER_IMPL::GetParamValue(const std::string & name) const
1524 std::string lowerName = ToLower(name);
1525 if (lowerName == "id")
1527 std::ostringstream stream;
1529 return stream.str();
1531 if (lowerName == "login") return login;
1532 if (lowerName == "currip") return currIP.ToString();
1533 if (lowerName == "enableddirs") return GetEnabledDirs();
1534 if (lowerName == "tariff") return property.tariffName;
1535 if (property.Exists(lowerName))
1536 return property.GetPropertyValue(lowerName);
1539 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1543 //-----------------------------------------------------------------------------
1544 //-----------------------------------------------------------------------------
1545 //-----------------------------------------------------------------------------
1546 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1548 if (newPassive && !oldPassive && user->tariff != NULL)
1549 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1555 //-----------------------------------------------------------------------------
1556 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1558 if (oldValue && !newValue && user->GetConnected())
1559 user->Disconnect(false, "disabled");
1560 else if (!oldValue && newValue && user->IsInetable())
1561 user->Connect(false);
1563 //-----------------------------------------------------------------------------
1564 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1566 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1567 user->Disconnect(false, "Change tariff");
1568 user->tariff = user->tariffs->FindByName(newTariff);
1569 if (user->settings->GetReconnectOnTariffChange() &&
1570 !user->authorizedBy.empty() &&
1572 user->Connect(false);
1574 //-----------------------------------------------------------------------------
1575 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1577 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1578 user->lastCashAdd = newCash - oldCash;
1580 //-----------------------------------------------------------------------------
1581 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1583 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1584 if (user->connected)
1585 user->Disconnect(false, "Change IP");
1586 if (!user->authorizedBy.empty() && user->IsInetable())
1587 user->Connect(false);