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());
1185 switch (tariff->GetChangePolicy())
1189 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1192 case TARIFF::TO_CHEAP:
1194 if (nt->GetFee() < tariff->GetFee())
1195 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1197 WriteServLog("Tariff change is prohibited for user %s due to the policy %s. Current tariff %s is more cheap than new tariff %s.",
1199 TARIFF::ChangePolicyToString(tariff->GetChangePolicy()).c_str(),
1200 property.tariffName.Get().c_str(),
1201 property.nextTariff.Get().c_str());
1204 case TARIFF::TO_EXPENSIVE:
1206 if (nt->GetFee() > tariff->GetFee())
1207 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1209 WriteServLog("Tariff change is prohibited for user %s due to the policy %s. Current tariff %s is more expensive than new tariff %s.",
1211 TARIFF::ChangePolicyToString(tariff->GetChangePolicy()).c_str(),
1212 property.tariffName.Get().c_str(),
1213 property.nextTariff.Get().c_str());
1218 WriteServLog("Tariff change is prohibited for user %s. Tariff %s.",
1220 property.tariffName.Get().c_str());
1229 //-----------------------------------------------------------------------------
1230 void USER_IMPL::ProcessDayFeeSpread()
1232 STG_LOCKER lock(&mutex);
1234 if (passive.ConstData() || tariff == NULL)
1237 if (tariff->GetPeriod() != TARIFF::MONTH)
1240 double fee = tariff->GetFee() / DaysInCurrentMonth();
1242 if (std::fabs(fee) < 1.0e-3)
1246 switch (settings->GetFeeChargeType())
1249 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1252 if (c + credit >= 0)
1253 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1256 if (c + credit >= fee)
1257 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1261 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1266 //-----------------------------------------------------------------------------
1267 void USER_IMPL::ProcessDayFee()
1269 STG_LOCKER lock(&mutex);
1274 if (tariff->GetPeriod() != TARIFF::MONTH)
1277 double passiveTimePart = 1.0;
1278 if (!settings->GetFullFee())
1280 passiveTimePart = GetPassiveTimePart();
1284 if (passive.ConstData())
1286 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1290 double fee = tariff->GetFee() * passiveTimePart;
1294 if (std::fabs(fee) < 1.0e-3)
1301 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1308 switch (settings->GetFeeChargeType())
1311 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1315 if (c + credit >= 0)
1317 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1322 if (c + credit >= fee)
1324 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1331 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1337 //-----------------------------------------------------------------------------
1338 void USER_IMPL::ProcessDailyFee()
1340 STG_LOCKER lock(&mutex);
1342 if (passive.ConstData() || tariff == NULL)
1345 if (tariff->GetPeriod() != TARIFF::DAY)
1348 double fee = tariff->GetFee();
1354 switch (settings->GetFeeChargeType())
1357 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1360 if (c + credit >= 0)
1361 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1364 if (c + credit >= fee)
1365 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1370 //-----------------------------------------------------------------------------
1371 void USER_IMPL::SetPrepaidTraff()
1374 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1376 //-----------------------------------------------------------------------------
1377 int USER_IMPL::AddMessage(STG_MSG * msg)
1379 STG_LOCKER lock(&mutex);
1381 if (SendMessage(*msg))
1383 if (store->AddMessage(msg, login))
1385 errorStr = store->GetStrError();
1386 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1387 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1390 messages.push_back(*msg);
1394 if (msg->header.repeat > 0)
1396 msg->header.repeat--;
1398 //TODO: gcc v. 4.x generate ICE on x86_64
1399 msg->header.lastSendTime = static_cast<int>(time(NULL));
1401 msg->header.lastSendTime = static_cast<int>(stgTime);
1403 if (store->AddMessage(msg, login))
1405 errorStr = store->GetStrError();
1406 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1407 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1410 messages.push_back(*msg);
1415 //-----------------------------------------------------------------------------
1416 int USER_IMPL::SendMessage(STG_MSG & msg) const
1418 // No lock `cause we are already locked from caller
1420 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1421 while (it != authorizedBy.end())
1423 if (!(*it++)->SendMessage(msg, currIP))
1429 //TODO: gcc v. 4.x generate ICE on x86_64
1430 msg.header.lastSendTime = static_cast<int>(time(NULL));
1432 msg.header.lastSendTime = static_cast<int>(stgTime);
1434 msg.header.repeat--;
1438 //-----------------------------------------------------------------------------
1439 void USER_IMPL::ScanMessage()
1441 // No lock `cause we are already locked from caller
1442 // We need not check for the authorizedBy `cause it has already checked by caller
1444 std::list<STG_MSG>::iterator it(messages.begin());
1445 while (it != messages.end())
1447 if (settings->GetMessageTimeout() > 0 &&
1448 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1451 if (store->DelMessage(it->header.id, login))
1453 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1454 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1456 messages.erase(it++);
1459 if (it->GetNextSendTime() <= stgTime)
1461 if (SendMessage(*it))
1463 // We need to check all messages in queue for timeout
1467 if (it->header.repeat < 0)
1469 if (store->DelMessage(it->header.id, login))
1471 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1472 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1474 messages.erase(it++);
1478 if (store->EditMessage(*it, login))
1480 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1481 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1492 //-----------------------------------------------------------------------------
1493 std::string USER_IMPL::GetParamValue(const std::string & name) const
1495 std::string lowerName = ToLower(name);
1496 if (lowerName == "id")
1498 std::ostringstream stream;
1500 return stream.str();
1502 if (lowerName == "login") return login;
1503 if (lowerName == "currip") return currIP.ToString();
1504 if (lowerName == "enableddirs") return GetEnabledDirs();
1505 if (lowerName == "tariff") return property.tariffName;
1506 if (property.Exists(lowerName))
1507 return property.GetPropertyValue(lowerName);
1510 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1514 //-----------------------------------------------------------------------------
1515 //-----------------------------------------------------------------------------
1516 //-----------------------------------------------------------------------------
1517 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1519 if (newPassive && !oldPassive && user->tariff != NULL)
1520 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1526 //-----------------------------------------------------------------------------
1527 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1529 if (oldValue && !newValue && user->GetConnected())
1530 user->Disconnect(false, "disabled");
1531 else if (!oldValue && newValue && user->IsInetable())
1532 user->Connect(false);
1534 //-----------------------------------------------------------------------------
1535 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1537 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1538 user->Disconnect(false, "Change tariff");
1539 user->tariff = user->tariffs->FindByName(newTariff);
1540 if (user->settings->GetReconnectOnTariffChange() &&
1541 !user->authorizedBy.empty() &&
1543 user->Connect(false);
1545 //-----------------------------------------------------------------------------
1546 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1548 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1549 user->lastCashAdd = newCash - oldCash;
1551 //-----------------------------------------------------------------------------
1552 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1554 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1555 if (user->connected)
1556 user->Disconnect(false, "Change IP");
1557 if (!user->authorizedBy.empty() && user->IsInetable())
1558 user->Connect(false);