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)
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)
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),
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 (!settings->GetDisableSessionLog() && 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 (!settings->GetDisableSessionLog() && 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);
1182 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1183 login.c_str(), property.tariffName.Get().c_str());
1187 std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime);
1188 if (message.empty())
1190 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1194 WriteServLog("Tariff change is prohibited for user %s. %s",
1203 //-----------------------------------------------------------------------------
1204 void USER_IMPL::ProcessDayFeeSpread()
1206 STG_LOCKER lock(&mutex);
1208 if (passive.ConstData() || tariff == NULL)
1211 if (tariff->GetPeriod() != TARIFF::MONTH)
1214 double fee = tariff->GetFee() / DaysInCurrentMonth();
1216 if (std::fabs(fee) < 1.0e-3)
1220 switch (settings->GetFeeChargeType())
1223 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1226 if (c + credit >= 0)
1227 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1230 if (c + credit >= fee)
1231 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1235 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1240 //-----------------------------------------------------------------------------
1241 void USER_IMPL::ProcessDayFee()
1243 STG_LOCKER lock(&mutex);
1248 if (tariff->GetPeriod() != TARIFF::MONTH)
1251 double passiveTimePart = 1.0;
1252 if (!settings->GetFullFee())
1254 passiveTimePart = GetPassiveTimePart();
1258 if (passive.ConstData())
1260 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1264 double fee = tariff->GetFee() * passiveTimePart;
1268 if (std::fabs(fee) < 1.0e-3)
1275 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1282 switch (settings->GetFeeChargeType())
1285 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1289 if (c + credit >= 0)
1291 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1296 if (c + credit >= fee)
1298 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1305 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1311 //-----------------------------------------------------------------------------
1312 void USER_IMPL::ProcessDailyFee()
1314 STG_LOCKER lock(&mutex);
1316 if (passive.ConstData() || tariff == NULL)
1319 if (tariff->GetPeriod() != TARIFF::DAY)
1322 double fee = tariff->GetFee();
1328 switch (settings->GetFeeChargeType())
1331 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1334 if (c + credit >= 0)
1335 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1338 if (c + credit >= fee)
1339 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1344 //-----------------------------------------------------------------------------
1345 void USER_IMPL::ProcessServices()
1349 localtime_r(&t, &tms);
1351 double passiveTimePart = 1.0;
1352 if (!settings->GetFullFee())
1354 passiveTimePart = GetPassiveTimePart();
1358 if (passive.ConstData())
1360 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1365 for (size_t i = 0; i < property.Conf().services.size(); ++i)
1368 if (m_services.Find(property.Conf().services[i], &conf))
1370 if (conf.payDay == tms.tm_mday ||
1371 (conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth()))
1374 double fee = conf.cost * passiveTimePart;
1375 printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1382 switch (settings->GetFeeChargeType())
1385 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1389 if (c + credit >= 0)
1391 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1396 if (c + credit >= fee)
1398 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1405 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1413 //-----------------------------------------------------------------------------
1414 void USER_IMPL::SetPrepaidTraff()
1417 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1419 //-----------------------------------------------------------------------------
1420 int USER_IMPL::AddMessage(STG_MSG * msg)
1422 STG_LOCKER lock(&mutex);
1424 if (SendMessage(*msg))
1426 if (store->AddMessage(msg, login))
1428 errorStr = store->GetStrError();
1429 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1430 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1433 messages.push_back(*msg);
1437 if (msg->header.repeat > 0)
1439 msg->header.repeat--;
1441 //TODO: gcc v. 4.x generate ICE on x86_64
1442 msg->header.lastSendTime = static_cast<int>(time(NULL));
1444 msg->header.lastSendTime = static_cast<int>(stgTime);
1446 if (store->AddMessage(msg, login))
1448 errorStr = store->GetStrError();
1449 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1450 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1453 messages.push_back(*msg);
1458 //-----------------------------------------------------------------------------
1459 int USER_IMPL::SendMessage(STG_MSG & msg) const
1461 // No lock `cause we are already locked from caller
1463 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1464 while (it != authorizedBy.end())
1466 if (!(*it++)->SendMessage(msg, currIP))
1472 //TODO: gcc v. 4.x generate ICE on x86_64
1473 msg.header.lastSendTime = static_cast<int>(time(NULL));
1475 msg.header.lastSendTime = static_cast<int>(stgTime);
1477 msg.header.repeat--;
1481 //-----------------------------------------------------------------------------
1482 void USER_IMPL::ScanMessage()
1484 // No lock `cause we are already locked from caller
1485 // We need not check for the authorizedBy `cause it has already checked by caller
1487 std::list<STG_MSG>::iterator it(messages.begin());
1488 while (it != messages.end())
1490 if (settings->GetMessageTimeout() > 0 &&
1491 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1494 if (store->DelMessage(it->header.id, login))
1496 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1497 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1499 messages.erase(it++);
1502 if (it->GetNextSendTime() <= stgTime)
1504 if (SendMessage(*it))
1506 // We need to check all messages in queue for timeout
1510 if (it->header.repeat < 0)
1512 if (store->DelMessage(it->header.id, login))
1514 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1515 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1517 messages.erase(it++);
1521 if (store->EditMessage(*it, login))
1523 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1524 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1535 //-----------------------------------------------------------------------------
1536 std::string USER_IMPL::GetParamValue(const std::string & name) const
1538 std::string lowerName = ToLower(name);
1539 if (lowerName == "id")
1541 std::ostringstream stream;
1543 return stream.str();
1545 if (lowerName == "login") return login;
1546 if (lowerName == "currip") return currIP.ToString();
1547 if (lowerName == "enableddirs") return GetEnabledDirs();
1548 if (lowerName == "tariff") return property.tariffName;
1549 if (property.Exists(lowerName))
1550 return property.GetPropertyValue(lowerName);
1553 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1557 //-----------------------------------------------------------------------------
1558 //-----------------------------------------------------------------------------
1559 //-----------------------------------------------------------------------------
1560 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1562 if (newPassive && !oldPassive && user->tariff != NULL)
1563 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1569 //-----------------------------------------------------------------------------
1570 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1572 if (oldValue && !newValue && user->GetConnected())
1573 user->Disconnect(false, "disabled");
1574 else if (!oldValue && newValue && user->IsInetable())
1575 user->Connect(false);
1577 //-----------------------------------------------------------------------------
1578 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1580 STG_LOCKER lock(&user->mutex);
1581 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1582 user->Disconnect(false, "Change tariff");
1583 user->tariff = user->tariffs->FindByName(newTariff);
1584 if (user->settings->GetReconnectOnTariffChange() &&
1585 !user->authorizedBy.empty() &&
1588 // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name.
1589 user->property.Conf().tariffName = newTariff;
1590 user->Connect(false);
1593 //-----------------------------------------------------------------------------
1594 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1596 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1597 user->lastCashAdd = newCash - oldCash;
1599 //-----------------------------------------------------------------------------
1600 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1602 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1603 if (user->connected)
1604 user->Disconnect(false, "Change IP");
1605 if (!user->authorizedBy.empty() && user->IsInetable())
1606 user->Connect(false);