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 sessionUploadModTime(stgTime),
138 sessionDownloadModTime(stgTime),
139 passiveNotifier(this),
140 disabledNotifier(this),
141 tariffNotifier(this),
148 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
153 const SERVICES & svcs)
156 WriteServLog(GetStgLogger()),
160 connected(__connected),
163 lastIPForDisconnect(0),
171 authorizedModificationTime(0),
174 lastWriteDetailedStat(0),
178 lastCashAdd(property.lastCashAdd),
179 passiveTime(property.passiveTime),
180 lastCashAddTime(property.lastCashAddTime),
181 freeMb(property.freeMb),
182 lastActivityTime(property.lastActivityTime),
183 password(property.password),
184 passive(property.passive),
185 disabled(property.disabled),
186 disabledDetailStat(property.disabledDetailStat),
187 alwaysOnline(property.alwaysOnline),
188 tariffName(property.tariffName),
189 nextTariff(property.nextTariff),
190 address(property.address),
192 group(property.group),
193 email(property.email),
194 phone(property.phone),
195 realName(property.realName),
196 credit(property.credit),
197 creditExpire(property.creditExpire),
199 userdata0(property.userdata0),
200 userdata1(property.userdata1),
201 userdata2(property.userdata2),
202 userdata3(property.userdata3),
203 userdata4(property.userdata4),
204 userdata5(property.userdata5),
205 userdata6(property.userdata6),
206 userdata7(property.userdata7),
207 userdata8(property.userdata8),
208 userdata9(property.userdata9),
209 sessionUploadModTime(stgTime),
210 sessionDownloadModTime(stgTime),
211 passiveNotifier(this),
212 disabledNotifier(this),
213 tariffNotifier(this),
220 //-----------------------------------------------------------------------------
221 void USER_IMPL::Init()
223 password = "*_EMPTY_PASSWORD_*";
224 tariffName = NO_TARIFF_NAME;
226 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
227 lastWriteDetailedStat = stgTime;
229 property.tariffName.AddBeforeNotifier(&tariffNotifier);
230 property.passive.AddBeforeNotifier(&passiveNotifier);
231 property.disabled.AddAfterNotifier(&disabledNotifier);
232 property.cash.AddBeforeNotifier(&cashNotifier);
233 ips.AddAfterNotifier(&ipNotifier);
235 pthread_mutexattr_t attr;
236 pthread_mutexattr_init(&attr);
237 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
238 pthread_mutex_init(&mutex, &attr);
240 //-----------------------------------------------------------------------------
241 USER_IMPL::USER_IMPL(const USER_IMPL & u)
244 property(*u.settings),
245 WriteServLog(GetStgLogger()),
250 connected(__connected),
251 userIDGenerator(u.userIDGenerator),
252 __currIP(u.__currIP),
254 lastIPForDisconnect(0),
255 pingTime(u.pingTime),
256 sysAdmin(u.sysAdmin),
260 m_services(u.m_services),
261 traffStat(u.traffStat),
262 traffStatSaved(u.traffStatSaved),
263 settings(u.settings),
264 authorizedModificationTime(u.authorizedModificationTime),
265 messages(u.messages),
267 lastWriteStat(u.lastWriteStat),
268 lastWriteDetailedStat(u.lastWriteDetailedStat),
272 lastCashAdd(property.lastCashAdd),
273 passiveTime(property.passiveTime),
274 lastCashAddTime(property.lastCashAddTime),
275 freeMb(property.freeMb),
276 lastActivityTime(property.lastActivityTime),
277 password(property.password),
278 passive(property.passive),
279 disabled(property.disabled),
280 disabledDetailStat(property.disabledDetailStat),
281 alwaysOnline(property.alwaysOnline),
282 tariffName(property.tariffName),
283 nextTariff(property.nextTariff),
284 address(property.address),
286 group(property.group),
287 email(property.email),
288 phone(property.phone),
289 realName(property.realName),
290 credit(property.credit),
291 creditExpire(property.creditExpire),
293 userdata0(property.userdata0),
294 userdata1(property.userdata1),
295 userdata2(property.userdata2),
296 userdata3(property.userdata3),
297 userdata4(property.userdata4),
298 userdata5(property.userdata5),
299 userdata6(property.userdata6),
300 userdata7(property.userdata7),
301 userdata8(property.userdata8),
302 userdata9(property.userdata9),
305 sessionUploadModTime(stgTime),
306 sessionDownloadModTime(stgTime),
307 passiveNotifier(this),
308 disabledNotifier(this),
309 tariffNotifier(this),
316 property.tariffName.AddBeforeNotifier(&tariffNotifier);
317 property.passive.AddBeforeNotifier(&passiveNotifier);
318 property.disabled.AddAfterNotifier(&disabledNotifier);
319 property.cash.AddBeforeNotifier(&cashNotifier);
320 ips.AddAfterNotifier(&ipNotifier);
322 property.SetProperties(u.property);
324 pthread_mutexattr_t attr;
325 pthread_mutexattr_init(&attr);
326 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
327 pthread_mutex_init(&mutex, &attr);
329 //-----------------------------------------------------------------------------
330 USER_IMPL::~USER_IMPL()
332 property.tariffName.DelBeforeNotifier(&tariffNotifier);
333 property.passive.DelBeforeNotifier(&passiveNotifier);
334 property.disabled.DelAfterNotifier(&disabledNotifier);
335 property.cash.DelBeforeNotifier(&cashNotifier);
336 pthread_mutex_destroy(&mutex);
338 //-----------------------------------------------------------------------------
339 void USER_IMPL::SetLogin(const std::string & l)
341 STG_LOCKER lock(&mutex);
342 assert(login.empty() && "Login is already set");
344 id = userIDGenerator.GetNextID();
346 //-----------------------------------------------------------------------------
347 int USER_IMPL::ReadConf()
349 STG_LOCKER lock(&mutex);
352 if (store->RestoreUserConf(&conf, login))
354 WriteServLog("Cannot read conf for user %s.", login.c_str());
355 WriteServLog("%s", store->GetStrError().c_str());
356 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
357 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
361 property.SetConf(conf);
363 tariff = tariffs->FindByName(tariffName);
366 WriteServLog("Cannot read user %s. Tariff %s not exist.",
367 login.c_str(), property.tariffName.Get().c_str());
371 std::vector<STG_MSG_HDR> hdrsList;
373 if (store->GetMessageHdrs(&hdrsList, login))
375 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
376 WriteServLog("Cannot read user %s. Error reading message headers: %s.",
378 store->GetStrError().c_str());
382 std::vector<STG_MSG_HDR>::const_iterator it;
383 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
386 if (store->GetMessage(it->id, &msg, login) == 0)
388 messages.push_back(msg);
394 //-----------------------------------------------------------------------------
395 int USER_IMPL::ReadStat()
397 STG_LOCKER lock(&mutex);
400 if (store->RestoreUserStat(&stat, login))
402 WriteServLog("Cannot read stat for user %s.", login.c_str());
403 WriteServLog("%s", store->GetStrError().c_str());
404 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
405 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
409 property.SetStat(stat);
413 //-----------------------------------------------------------------------------
414 int USER_IMPL::WriteConf()
416 STG_LOCKER lock(&mutex);
417 USER_CONF conf(property.GetConf());
419 printfd(__FILE__, "USER::WriteConf()\n");
421 if (store->SaveUserConf(conf, login))
423 WriteServLog("Cannot write conf for user %s.", login.c_str());
424 WriteServLog("%s", store->GetStrError().c_str());
425 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
426 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
432 //-----------------------------------------------------------------------------
433 int USER_IMPL::WriteStat()
435 STG_LOCKER lock(&mutex);
436 USER_STAT stat(property.GetStat());
438 if (store->SaveUserStat(stat, login))
440 WriteServLog("Cannot write stat for user %s.", login.c_str());
441 WriteServLog("%s", store->GetStrError().c_str());
442 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
443 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
447 lastWriteStat = stgTime;
451 //-----------------------------------------------------------------------------
452 int USER_IMPL::WriteMonthStat()
454 STG_LOCKER lock(&mutex);
455 time_t tt = stgTime - 3600;
457 localtime_r(&tt, &t1);
459 USER_STAT stat(property.GetStat());
460 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
462 WriteServLog("Cannot write month stat for user %s.", login.c_str());
463 WriteServLog("%s", store->GetStrError().c_str());
464 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
465 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
471 //-----------------------------------------------------------------------------
472 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
474 STG_LOCKER lock(&mutex);
476 * Authorize user. It only means that user will be authorized. Nothing more.
477 * User can be connected or disconnected while authorized.
478 * Example: user is authorized but disconnected due to 0 money or blocking
482 * TODO: in fact "authorization" means allowing access to a service. What we
483 * call "authorization" here, int STG, is "authentication". So this should be
488 * Prevent double authorization by identical authorizers
490 if (authorizedBy.find(auth) != authorizedBy.end())
496 dirsFromBits(enabledDirs, dirs);
498 if (!authorizedBy.empty())
502 // We are already authorized, but with different IP address
503 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
508 if (!users->FindByIPIdx(ip, &u))
510 // Address presents in IP-index.
511 // If it's not our IP - report it.
514 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
521 if (users->IsIPInIndex(ip))
523 // Address is already present in IP-index.
524 errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
528 if (ips.ConstData().IsIPInIPS(ip))
531 lastIPForDisconnect = currIP;
535 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
536 errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
541 if (authorizedBy.empty())
542 authorizedModificationTime = stgTime;
543 authorizedBy.insert(auth);
549 //-----------------------------------------------------------------------------
550 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
552 STG_LOCKER lock(&mutex);
554 * Authorizer tries to unauthorize user, that was not authorized by it
556 if (!authorizedBy.erase(auth))
559 authorizedModificationTime = stgTime;
561 if (authorizedBy.empty())
563 lastDisconnectReason = reason;
564 lastIPForDisconnect = currIP;
565 currIP = 0; // DelUser in traffcounter
567 Disconnect(false, "not authorized");
571 //-----------------------------------------------------------------------------
572 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
574 STG_LOCKER lock(&mutex);
575 // Is this user authorized by specified authorizer?
576 return authorizedBy.find(auth) != authorizedBy.end();
578 //-----------------------------------------------------------------------------
579 std::vector<std::string> USER_IMPL::GetAuthorizers() const
581 STG_LOCKER lock(&mutex);
582 std::vector<std::string> list;
583 std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
586 //-----------------------------------------------------------------------------
587 void USER_IMPL::Connect(bool fakeConnect)
590 * Connect user to Internet. This function is differ from Authorize() !!!
593 STG_LOCKER lock(&mutex);
597 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
599 if (access(scriptOnConnect.c_str(), X_OK) == 0)
601 std::string dirs = dirsToString(enabledDirs);
603 std::string scriptOnConnectParams;
604 strprintf(&scriptOnConnectParams,
605 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
606 scriptOnConnect.c_str(),
608 inet_ntostring(currIP).c_str(),
613 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
614 while (it != settings->GetScriptParams().end())
616 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
620 ScriptExec(scriptOnConnectParams.c_str());
624 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
630 if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP))
632 WriteServLog("Cannot write connect for user %s.", login.c_str());
633 WriteServLog("%s", store->GetStrError().c_str());
637 lastIPForDisconnect = currIP;
639 //-----------------------------------------------------------------------------
640 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
643 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
646 STG_LOCKER lock(&mutex);
648 if (!lastIPForDisconnect)
650 printfd(__FILE__, "lastIPForDisconnect\n");
656 lastDisconnectReason = reason;
657 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
659 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
661 std::string dirs = dirsToString(enabledDirs);
663 std::string scriptOnDisonnectParams;
664 strprintf(&scriptOnDisonnectParams,
665 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
666 scriptOnDisonnect.c_str(),
668 inet_ntostring(lastIPForDisconnect).c_str(),
673 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
674 while (it != settings->GetScriptParams().end())
676 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
680 ScriptExec(scriptOnDisonnectParams.c_str());
684 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
690 std::string reasonMessage(reason);
691 if (!lastDisconnectReason.empty())
692 reasonMessage += ": " + lastDisconnectReason;
694 if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
695 cash, freeMb, reasonMessage))
697 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
698 WriteServLog("%s", store->GetStrError().c_str());
702 lastIPForDisconnect = 0;
704 sessionUpload.Reset();
705 sessionDownload.Reset();
706 sessionUploadModTime = stgTime;
707 sessionDownloadModTime = stgTime;
709 //-----------------------------------------------------------------------------
710 void USER_IMPL::Run()
712 STG_LOCKER lock(&mutex);
714 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
716 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
719 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
721 WriteServLog("User: %s. Credit expired.", login.c_str());
727 if (passive.ConstData()
728 && (stgTime % 30 == 0)
729 && (passiveTime.ModificationTime() != stgTime))
731 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
732 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
735 if (!authorizedBy.empty())
738 property.Stat().lastActivityTime = stgTime;
740 if (!connected && IsInetable())
743 if (connected && !IsInetable())
746 Disconnect(false, "disabled");
748 Disconnect(false, "passive");
750 Disconnect(false, "no cash");
753 if (stgTime - lastScanMessages > 10)
756 lastScanMessages = stgTime;
762 Disconnect(false, "not authorized");
766 //-----------------------------------------------------------------------------
767 void USER_IMPL::UpdatePingTime(time_t t)
769 STG_LOCKER lock(&mutex);
775 //-----------------------------------------------------------------------------
776 bool USER_IMPL::IsInetable()
778 if (disabled || passive)
781 if (settings->GetFreeMbAllowInet())
787 if (settings->GetShowFeeInCash() || tariff == NULL)
788 return (cash >= -credit);
790 return (cash - tariff->GetFee() >= -credit);
792 //-----------------------------------------------------------------------------
793 std::string USER_IMPL::GetEnabledDirs() const
795 return dirsToString(enabledDirs);
797 //-----------------------------------------------------------------------------
798 #ifdef TRAFF_STAT_WITH_PORTS
799 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
801 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
804 STG_LOCKER lock(&mutex);
806 if (!connected || tariff == NULL)
812 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
813 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
817 int tt = tariff->GetTraffType();
818 if (tt == TARIFF::TRAFF_UP ||
819 tt == TARIFF::TRAFF_UP_DOWN ||
820 // Check NEW traff data
821 (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
824 if (traff < threshold &&
825 traff + len >= threshold)
827 // cash = partBeforeThreshold * priceBeforeThreshold +
828 // partAfterThreshold * priceAfterThreshold
829 int64_t before = threshold - traff; // Chunk part before threshold
830 int64_t after = len - before; // Chunk part after threshold
831 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
832 down.ConstData()[dir],
835 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
836 down.ConstData()[dir],
842 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
843 down.ConstData()[dir],
848 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
850 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
851 cost = dc - freeMb.ConstData();
853 // Direct access to internal data structures via friend-specifier
854 property.Stat().freeMb -= dc;
855 property.Stat().cash -= cost;
861 sessionUpload[dir] += len;
862 sessionUploadModTime = stgTime;
866 if (!settings->GetWriteFreeMbTraffCost() &&
867 freeMb.ConstData() >= 0)
870 #ifdef TRAFF_STAT_WITH_PORTS
871 IP_DIR_PAIR idp(ip, dir, port);
873 IP_DIR_PAIR idp(ip, dir);
876 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
877 lb = traffStat.lower_bound(idp);
878 if (lb == traffStat.end() || lb->first != idp)
882 STAT_NODE(len, 0, cost)));
886 lb->second.cash += cost;
887 lb->second.up += len;
890 //-----------------------------------------------------------------------------
891 #ifdef TRAFF_STAT_WITH_PORTS
892 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
894 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
897 STG_LOCKER lock(&mutex);
899 if (!connected || tariff == NULL)
905 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
906 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
910 int tt = tariff->GetTraffType();
911 if (tt == TARIFF::TRAFF_DOWN ||
912 tt == TARIFF::TRAFF_UP_DOWN ||
913 // Check NEW traff data
914 (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
917 if (traff < threshold &&
918 traff + len >= threshold)
920 // cash = partBeforeThreshold * priceBeforeThreshold +
921 // partAfterThreshold * priceAfterThreshold
922 int64_t before = threshold - traff; // Chunk part before threshold
923 int64_t after = len - before; // Chunk part after threshold
924 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
925 down.ConstData()[dir], // Traff before chunk
928 tariff->GetPriceWithTraffType(up.ConstData()[dir],
929 dt[dir], // Traff after chunk
935 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
936 down.ConstData()[dir],
941 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
943 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
944 cost = dc - freeMb.ConstData();
946 property.Stat().freeMb -= dc;
947 property.Stat().cash -= cost;
953 sessionDownload[dir] += len;
954 sessionDownloadModTime = stgTime;
958 if (!settings->GetWriteFreeMbTraffCost() &&
959 freeMb.ConstData() >= 0)
962 #ifdef TRAFF_STAT_WITH_PORTS
963 IP_DIR_PAIR idp(ip, dir, port);
965 IP_DIR_PAIR idp(ip, dir);
968 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
969 lb = traffStat.lower_bound(idp);
970 if (lb == traffStat.end() || lb->first != idp)
974 STAT_NODE(0, len, cost)));
978 lb->second.cash += cost;
979 lb->second.down += len;
982 //-----------------------------------------------------------------------------
983 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
985 STG_LOCKER lock(&mutex);
986 currIP.AddBeforeNotifier(notifier);
988 //-----------------------------------------------------------------------------
989 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
991 STG_LOCKER lock(&mutex);
992 currIP.DelBeforeNotifier(notifier);
994 //-----------------------------------------------------------------------------
995 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
997 STG_LOCKER lock(&mutex);
998 currIP.AddAfterNotifier(notifier);
1000 //-----------------------------------------------------------------------------
1001 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1003 STG_LOCKER lock(&mutex);
1004 currIP.DelAfterNotifier(notifier);
1006 //-----------------------------------------------------------------------------
1007 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1009 STG_LOCKER lock(&mutex);
1010 connected.AddBeforeNotifier(notifier);
1012 //-----------------------------------------------------------------------------
1013 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1015 STG_LOCKER lock(&mutex);
1016 connected.DelBeforeNotifier(notifier);
1018 //-----------------------------------------------------------------------------
1019 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1021 STG_LOCKER lock(&mutex);
1022 connected.AddAfterNotifier(notifier);
1024 //-----------------------------------------------------------------------------
1025 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1027 STG_LOCKER lock(&mutex);
1028 connected.DelAfterNotifier(notifier);
1030 //-----------------------------------------------------------------------------
1031 void USER_IMPL::OnAdd()
1033 STG_LOCKER lock(&mutex);
1035 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1037 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1039 std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
1041 ScriptExec(scriptOnAddParams.c_str());
1045 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1048 //-----------------------------------------------------------------------------
1049 void USER_IMPL::OnDelete()
1051 STG_LOCKER lock(&mutex);
1053 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1055 if (access(scriptOnDel.c_str(), X_OK) == 0)
1057 std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
1059 ScriptExec(scriptOnDelParams.c_str());
1063 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1068 //-----------------------------------------------------------------------------
1069 int USER_IMPL::WriteDetailStat(bool hard)
1071 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1073 if (!traffStatSaved.second.empty())
1075 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1077 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1078 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1079 WriteServLog("%s", store->GetStrError().c_str());
1082 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1088 STG_LOCKER lock(&mutex);
1092 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1094 if (ts.size() && !disabledDetailStat)
1096 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1098 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1099 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1100 WriteServLog("%s", store->GetStrError().c_str());
1103 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1104 STG_LOCKER lock(&mutex);
1105 traffStatSaved.second.swap(ts);
1106 traffStatSaved.first = lastWriteDetailedStat;
1111 lastWriteDetailedStat = stgTime;
1114 //-----------------------------------------------------------------------------
1115 double USER_IMPL::GetPassiveTimePart() const
1117 STG_LOCKER lock(&mutex);
1119 static int daysInMonth[12] =
1120 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1124 localtime_r(&t, &tms);
1126 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1128 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1131 secMonth += 24 * 3600;
1134 time_t dt = secMonth - passiveTime;
1139 return static_cast<double>(dt) / secMonth;
1141 //-----------------------------------------------------------------------------
1142 void USER_IMPL::SetPassiveTimeAsNewUser()
1144 STG_LOCKER lock(&mutex);
1148 localtime_r(&t, &tm);
1149 int daysCurrMon = DaysInCurrentMonth();
1150 double pt = tm.tm_mday - 1;
1153 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1155 //-----------------------------------------------------------------------------
1156 void USER_IMPL::MidnightResetSessionStat()
1158 STG_LOCKER lock(&mutex);
1162 Disconnect(true, "fake");
1166 //-----------------------------------------------------------------------------
1167 void USER_IMPL::ProcessNewMonth()
1169 STG_LOCKER lock(&mutex);
1172 Disconnect(true, "fake");
1176 property.Stat().monthUp.Reset();
1177 property.Stat().monthDown.Reset();
1183 if (nextTariff.ConstData() != "")
1185 const TARIFF * nt = tariffs->FindByName(nextTariff);
1188 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1189 login.c_str(), property.tariffName.Get().c_str());
1193 std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime);
1194 if (message.empty())
1196 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1200 WriteServLog("Tariff change is prohibited for user %s. %s",
1209 //-----------------------------------------------------------------------------
1210 void USER_IMPL::ProcessDayFeeSpread()
1212 STG_LOCKER lock(&mutex);
1214 if (passive.ConstData() || tariff == NULL)
1217 if (tariff->GetPeriod() != TARIFF::MONTH)
1220 double fee = tariff->GetFee() / DaysInCurrentMonth();
1222 if (std::fabs(fee) < 1.0e-3)
1226 switch (settings->GetFeeChargeType())
1229 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1232 if (c + credit >= 0)
1233 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1236 if (c + credit >= fee)
1237 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1241 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1246 //-----------------------------------------------------------------------------
1247 void USER_IMPL::ProcessDayFee()
1249 STG_LOCKER lock(&mutex);
1254 if (tariff->GetPeriod() != TARIFF::MONTH)
1257 double passiveTimePart = 1.0;
1258 if (!settings->GetFullFee())
1260 passiveTimePart = GetPassiveTimePart();
1264 if (passive.ConstData())
1266 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1270 double fee = tariff->GetFee() * passiveTimePart;
1274 if (std::fabs(fee) < 1.0e-3)
1281 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1288 switch (settings->GetFeeChargeType())
1291 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1295 if (c + credit >= 0)
1297 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1302 if (c + credit >= fee)
1304 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1311 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1317 //-----------------------------------------------------------------------------
1318 void USER_IMPL::ProcessDailyFee()
1320 STG_LOCKER lock(&mutex);
1322 if (passive.ConstData() || tariff == NULL)
1325 if (tariff->GetPeriod() != TARIFF::DAY)
1328 double fee = tariff->GetFee();
1334 switch (settings->GetFeeChargeType())
1337 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1340 if (c + credit >= 0)
1341 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1344 if (c + credit >= fee)
1345 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1350 //-----------------------------------------------------------------------------
1351 void USER_IMPL::SetPrepaidTraff()
1354 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1356 //-----------------------------------------------------------------------------
1357 int USER_IMPL::AddMessage(STG_MSG * msg)
1359 STG_LOCKER lock(&mutex);
1361 if (SendMessage(*msg))
1363 if (store->AddMessage(msg, login))
1365 errorStr = store->GetStrError();
1366 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1367 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1370 messages.push_back(*msg);
1374 if (msg->header.repeat > 0)
1376 msg->header.repeat--;
1378 //TODO: gcc v. 4.x generate ICE on x86_64
1379 msg->header.lastSendTime = static_cast<int>(time(NULL));
1381 msg->header.lastSendTime = static_cast<int>(stgTime);
1383 if (store->AddMessage(msg, login))
1385 errorStr = store->GetStrError();
1386 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1387 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1390 messages.push_back(*msg);
1395 //-----------------------------------------------------------------------------
1396 int USER_IMPL::SendMessage(STG_MSG & msg) const
1398 // No lock `cause we are already locked from caller
1400 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1401 while (it != authorizedBy.end())
1403 if (!(*it++)->SendMessage(msg, currIP))
1409 //TODO: gcc v. 4.x generate ICE on x86_64
1410 msg.header.lastSendTime = static_cast<int>(time(NULL));
1412 msg.header.lastSendTime = static_cast<int>(stgTime);
1414 msg.header.repeat--;
1418 //-----------------------------------------------------------------------------
1419 void USER_IMPL::ScanMessage()
1421 // No lock `cause we are already locked from caller
1422 // We need not check for the authorizedBy `cause it has already checked by caller
1424 std::list<STG_MSG>::iterator it(messages.begin());
1425 while (it != messages.end())
1427 if (settings->GetMessageTimeout() > 0 &&
1428 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1431 if (store->DelMessage(it->header.id, login))
1433 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1434 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1436 messages.erase(it++);
1439 if (it->GetNextSendTime() <= stgTime)
1441 if (SendMessage(*it))
1443 // We need to check all messages in queue for timeout
1447 if (it->header.repeat < 0)
1449 if (store->DelMessage(it->header.id, login))
1451 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1452 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1454 messages.erase(it++);
1458 if (store->EditMessage(*it, login))
1460 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1461 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1472 //-----------------------------------------------------------------------------
1473 std::string USER_IMPL::GetParamValue(const std::string & name) const
1475 std::string lowerName = ToLower(name);
1476 if (lowerName == "id")
1478 std::ostringstream stream;
1480 return stream.str();
1482 if (lowerName == "login") return login;
1483 if (lowerName == "currip") return currIP.ToString();
1484 if (lowerName == "enableddirs") return GetEnabledDirs();
1485 if (lowerName == "tariff") return property.tariffName;
1486 if (property.Exists(lowerName))
1487 return property.GetPropertyValue(lowerName);
1490 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1494 //-----------------------------------------------------------------------------
1495 //-----------------------------------------------------------------------------
1496 //-----------------------------------------------------------------------------
1497 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1499 if (newPassive && !oldPassive && user->tariff != NULL)
1500 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1506 //-----------------------------------------------------------------------------
1507 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1509 if (oldValue && !newValue && user->GetConnected())
1510 user->Disconnect(false, "disabled");
1511 else if (!oldValue && newValue && user->IsInetable())
1512 user->Connect(false);
1514 //-----------------------------------------------------------------------------
1515 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1517 STG_LOCKER lock(&user->mutex);
1518 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1519 user->Disconnect(false, "Change tariff");
1520 user->tariff = user->tariffs->FindByName(newTariff);
1521 if (user->settings->GetReconnectOnTariffChange() &&
1522 !user->authorizedBy.empty() &&
1525 // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name.
1526 user->property.Conf().tariffName = newTariff;
1527 user->Connect(false);
1530 //-----------------------------------------------------------------------------
1531 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1533 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1534 user->lastCashAdd = newCash - oldCash;
1536 //-----------------------------------------------------------------------------
1537 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1539 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1540 if (user->connected)
1541 user->Disconnect(false, "Change IP");
1542 if (!user->authorizedBy.empty() && user->IsInetable())
1543 user->Connect(false);