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 $
36 #include <unistd.h> // access
42 #include "stg/users.h"
43 #include "stg/common.h"
44 #include "stg/scriptexecuter.h"
45 #include "stg/tariff.h"
46 #include "stg/tariffs.h"
47 #include "stg/admin.h"
48 #include "user_impl.h"
49 #include "settings_impl.h"
50 #include "stg_timer.h"
52 #ifdef USE_ABSTRACT_SETTINGS
53 USER_IMPL::USER_IMPL(const SETTINGS * s,
60 property(s->GetScriptsDir()),
61 WriteServLog(GetStgLogger()),
66 connected(__connected),
71 lastIPForDisconnect(0),
84 lastWriteDetailedStat(0),
88 lastCashAdd(property.lastCashAdd),
89 passiveTime(property.passiveTime),
90 lastCashAddTime(property.lastCashAddTime),
91 freeMb(property.freeMb),
92 lastActivityTime(property.lastActivityTime),
93 password(property.password),
94 passive(property.passive),
95 disabled(property.disabled),
96 disabledDetailStat(property.disabledDetailStat),
97 alwaysOnline(property.alwaysOnline),
98 tariffName(property.tariffName),
99 nextTariff(property.nextTariff),
100 address(property.address),
102 group(property.group),
103 email(property.email),
104 phone(property.phone),
105 realName(property.realName),
106 credit(property.credit),
107 creditExpire(property.creditExpire),
109 userdata0(property.userdata0),
110 userdata1(property.userdata1),
111 userdata2(property.userdata2),
112 userdata3(property.userdata3),
113 userdata4(property.userdata4),
114 userdata5(property.userdata5),
115 userdata6(property.userdata6),
116 userdata7(property.userdata7),
117 userdata8(property.userdata8),
118 userdata9(property.userdata9),
121 passiveNotifier(this),
122 tariffNotifier(this),
128 password = "*_EMPTY_PASSWORD_*";
129 tariffName = NO_TARIFF_NAME;
131 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
132 lastWriteDetailedStat = stgTime;
134 property.tariffName.AddBeforeNotifier(&tariffNotifier);
135 property.passive.AddBeforeNotifier(&passiveNotifier);
136 property.disabled.AddAfterNotifier(&disabledNotifier);
137 property.cash.AddBeforeNotifier(&cashNotifier);
138 ips.AddAfterNotifier(&ipNotifier);
140 pthread_mutexattr_t attr;
141 pthread_mutexattr_init(&attr);
142 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
143 pthread_mutex_init(&mutex, &attr);
146 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
153 property(s->GetScriptsDir()),
154 WriteServLog(GetStgLogger()),
159 connected(__connected),
164 lastIPForDisconnect(0),
177 lastWriteDetailedStat(0),
181 lastCashAdd(property.lastCashAdd),
182 passiveTime(property.passiveTime),
183 lastCashAddTime(property.lastCashAddTime),
184 freeMb(property.freeMb),
185 lastActivityTime(property.lastActivityTime),
186 password(property.password),
187 passive(property.passive),
188 disabled(property.disabled),
189 disabledDetailStat(property.disabledDetailStat),
190 alwaysOnline(property.alwaysOnline),
191 tariffName(property.tariffName),
192 nextTariff(property.nextTariff),
193 address(property.address),
195 group(property.group),
196 email(property.email),
197 phone(property.phone),
198 realName(property.realName),
199 credit(property.credit),
200 creditExpire(property.creditExpire),
202 userdata0(property.userdata0),
203 userdata1(property.userdata1),
204 userdata2(property.userdata2),
205 userdata3(property.userdata3),
206 userdata4(property.userdata4),
207 userdata5(property.userdata5),
208 userdata6(property.userdata6),
209 userdata7(property.userdata7),
210 userdata8(property.userdata8),
211 userdata9(property.userdata9),
214 passiveNotifier(this),
215 disabledNotifier(this),
216 tariffNotifier(this),
222 password = "*_EMPTY_PASSWORD_*";
223 tariffName = NO_TARIFF_NAME;
225 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
226 lastWriteDetailedStat = stgTime;
228 property.tariffName.AddBeforeNotifier(&tariffNotifier);
229 property.passive.AddBeforeNotifier(&passiveNotifier);
230 property.disabled.AddAfterNotifier(&disabledNotifier);
231 property.cash.AddBeforeNotifier(&cashNotifier);
232 ips.AddAfterNotifier(&ipNotifier);
234 pthread_mutexattr_t attr;
235 pthread_mutexattr_init(&attr);
236 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
237 pthread_mutex_init(&mutex, &attr);
240 //-----------------------------------------------------------------------------
241 USER_IMPL::USER_IMPL(const USER_IMPL & u)
244 property(u.settings->GetScriptsDir()),
245 WriteServLog(GetStgLogger()),
250 connected(__connected),
252 userIDGenerator(u.userIDGenerator),
253 __currIP(u.__currIP),
255 lastIPForDisconnect(0),
256 pingTime(u.pingTime),
257 sysAdmin(u.sysAdmin),
261 traffStat(u.traffStat),
262 traffStatSaved(u.traffStatSaved),
263 settings(u.settings),
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 passiveNotifier(this),
306 disabledNotifier(this),
307 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, __FILE__, __LINE__);
342 assert(login.empty() && "Login is already set");
344 id = userIDGenerator.GetNextID();
346 //-----------------------------------------------------------------------------
347 int USER_IMPL::ReadConf()
349 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
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, __FILE__, __LINE__);
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, __FILE__, __LINE__);
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, __FILE__, __LINE__);
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, __FILE__, __LINE__);
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, __FILE__, __LINE__);
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 * Prevent double authorization by identical authorizers
484 if (authorizedBy.find(auth) != authorizedBy.end())
490 for (int i = 0; i < DIR_NUM; i++)
492 enabledDirs[i] = dirs & (1 << i);
495 if (!authorizedBy.empty())
499 // We are already authorized, but with different IP address
500 errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
505 if (!users->FindByIPIdx(ip, &u))
507 // Address is already present in IP-index
508 // If it's not our IP - throw an error
511 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
518 if (users->IsIPInIndex(ip))
520 // Address is already present in IP-index
521 errorStr = "IP address " + inet_ntostring(ip) + " already in use";
525 if (ips.ConstData().IsIPInIPS(ip))
528 lastIPForDisconnect = currIP;
532 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
533 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
538 authorizedBy.insert(auth);
544 //-----------------------------------------------------------------------------
545 void USER_IMPL::Unauthorize(const AUTH * auth)
547 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
549 * Authorizer tries to unauthorize user, that was not authorized by it
551 if (!authorizedBy.erase(auth))
554 if (authorizedBy.empty())
556 lastIPForDisconnect = currIP;
557 currIP = 0; // DelUser in traffcounter
561 //-----------------------------------------------------------------------------
562 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
564 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
565 // Is this user authorized by specified authorizer?
566 return authorizedBy.find(auth) != authorizedBy.end();
568 //-----------------------------------------------------------------------------
569 void USER_IMPL::Connect(bool fakeConnect)
572 * Connect user to Internet. This function is differ from Authorize() !!!
575 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
579 std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
581 if (access(scriptOnConnect.c_str(), X_OK) == 0)
583 char dirsStr[DIR_NUM + 1];
584 dirsStr[DIR_NUM] = 0;
585 for (int i = 0; i < DIR_NUM; i++)
587 dirsStr[i] = enabledDirs[i] ? '1' : '0';
590 std::string scriptOnConnectParams;
592 strprintf(&scriptOnConnectParams,
593 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
594 scriptOnConnect.c_str(),
596 inet_ntostring(currIP).c_str(),
601 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
602 while (it != settings->GetScriptParams().end())
604 scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
608 ScriptExec(scriptOnConnectParams.c_str());
612 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
618 if (store->WriteUserConnect(login, currIP))
620 WriteServLog("Cannot write connect for user %s.", login.c_str());
621 WriteServLog("%s", store->GetStrError().c_str());
625 lastIPForDisconnect = currIP;
627 //-----------------------------------------------------------------------------
628 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
631 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
634 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
636 if (!lastIPForDisconnect)
638 printfd(__FILE__, "lastIPForDisconnect\n");
644 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
646 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
648 char dirsStr[DIR_NUM + 1];
649 dirsStr[DIR_NUM] = 0;
650 for (int i = 0; i < DIR_NUM; i++)
652 dirsStr[i] = enabledDirs[i] ? '1' : '0';
655 std::string scriptOnDisonnectParams;
656 strprintf(&scriptOnDisonnectParams,
657 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
658 scriptOnDisonnect.c_str(),
660 inet_ntostring(lastIPForDisconnect).c_str(),
665 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
666 while (it != settings->GetScriptParams().end())
668 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
672 ScriptExec(scriptOnDisonnectParams.c_str());
676 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
682 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
684 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
685 WriteServLog("%s", store->GetStrError().c_str());
689 lastIPForDisconnect = 0;
691 DIR_TRAFF zeroSesssion;
693 sessionUpload = zeroSesssion;
694 sessionDownload = zeroSesssion;
696 //-----------------------------------------------------------------------------
697 void USER_IMPL::PrintUser() const
700 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
701 std::cout << "============================================================" << std::endl;
702 std::cout << "id=" << id << std::endl;
703 std::cout << "login=" << login << std::endl;
704 std::cout << "password=" << password << std::endl;
705 std::cout << "passive=" << passive << std::endl;
706 std::cout << "disabled=" << disabled << std::endl;
707 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
708 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
709 std::cout << "tariffName=" << tariffName << std::endl;
710 std::cout << "address=" << address << std::endl;
711 std::cout << "phone=" << phone << std::endl;
712 std::cout << "email=" << email << std::endl;
713 std::cout << "note=" << note << std::endl;
714 std::cout << "realName=" <<realName << std::endl;
715 std::cout << "group=" << group << std::endl;
716 std::cout << "credit=" << credit << std::endl;
717 std::cout << "nextTariff=" << nextTariff << std::endl;
718 std::cout << "userdata0" << userdata0 << std::endl;
719 std::cout << "userdata1" << userdata1 << std::endl;
720 std::cout << "creditExpire=" << creditExpire << std::endl;
721 std::cout << "ips=" << ips << std::endl;
722 std::cout << "------------------------" << std::endl;
723 std::cout << "up=" << up << std::endl;
724 std::cout << "down=" << down << std::endl;
725 std::cout << "cash=" << cash << std::endl;
726 std::cout << "freeMb=" << freeMb << std::endl;
727 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
728 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
729 std::cout << "passiveTime=" << passiveTime << std::endl;
730 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
731 std::cout << "============================================================" << std::endl;
733 //-----------------------------------------------------------------------------
734 void USER_IMPL::Run()
736 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
738 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
740 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
743 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
745 WriteServLog("User: %s. Credit expired.", login.c_str());
751 if (passive.ConstData()
752 && (stgTime % 30 == 0)
753 && (passiveTime.ModificationTime() != stgTime))
755 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
756 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
759 if (!authorizedBy.empty())
763 property.Stat().lastActivityTime = stgTime;
765 if (!connected && IsInetable())
769 if (connected && !IsInetable())
772 Disconnect(false, "disabled");
774 Disconnect(false, "passive");
776 Disconnect(false, "no cash");
779 if (stgTime - lastScanMessages > 10)
782 lastScanMessages = stgTime;
789 Disconnect(false, "not authorized");
794 //-----------------------------------------------------------------------------
795 void USER_IMPL::UpdatePingTime(time_t t)
797 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
798 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
804 //-----------------------------------------------------------------------------
805 bool USER_IMPL::IsInetable()
807 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
809 if (disabled || passive)
812 if (settings->GetFreeMbAllowInet())
818 if (settings->GetShowFeeInCash() || tariff == NULL)
820 return (cash >= -credit);
823 return (cash - tariff->GetFee() >= -credit);
825 //-----------------------------------------------------------------------------
826 std::string USER_IMPL::GetEnabledDirs() const
828 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
830 std::string dirs = "";
831 for(int i = 0; i < DIR_NUM; i++)
832 dirs += enabledDirs[i] ? "1" : "0";
835 //-----------------------------------------------------------------------------
836 #ifdef TRAFF_STAT_WITH_PORTS
837 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
839 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
842 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
844 if (!connected || tariff == NULL)
850 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
851 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
855 int tt = tariff->GetTraffType();
856 if (tt == TRAFF_UP ||
857 tt == TRAFF_UP_DOWN ||
858 // Check NEW traff data
859 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
862 if (traff < threshold &&
863 traff + len >= threshold)
865 // cash = partBeforeThreshold * priceBeforeThreshold +
866 // partAfterThreshold * priceAfterThreshold
867 int64_t before = threshold - traff; // Chunk part before threshold
868 int64_t after = len - before; // Chunk part after threshold
869 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
870 down.ConstData()[dir],
873 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
874 down.ConstData()[dir],
880 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
881 down.ConstData()[dir],
886 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
888 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
889 cost = dc - freeMb.ConstData();
891 // Direct access to internal data structures via friend-specifier
892 property.Stat().freeMb -= dc;
893 property.Stat().cash -= cost;
899 sessionUpload[dir] += len;
903 if (!settings->GetWriteFreeMbTraffCost() &&
904 freeMb.ConstData() >= 0)
907 #ifdef TRAFF_STAT_WITH_PORTS
908 IP_DIR_PAIR idp(ip, dir, port);
910 IP_DIR_PAIR idp(ip, dir);
913 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
914 lb = traffStat.lower_bound(idp);
915 if (lb == traffStat.end() || lb->first != idp)
919 STAT_NODE(len, 0, cost)));
923 lb->second.cash += cost;
924 lb->second.up += len;
927 //-----------------------------------------------------------------------------
928 #ifdef TRAFF_STAT_WITH_PORTS
929 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
931 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
934 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
936 if (!connected || tariff == NULL)
942 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
943 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
947 int tt = tariff->GetTraffType();
948 if (tt == TRAFF_DOWN ||
949 tt == TRAFF_UP_DOWN ||
950 // Check NEW traff data
951 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
954 if (traff < threshold &&
955 traff + len >= threshold)
957 // cash = partBeforeThreshold * priceBeforeThreshold +
958 // partAfterThreshold * priceAfterThreshold
959 int64_t before = threshold - traff; // Chunk part before threshold
960 int64_t after = len - before; // Chunk part after threshold
961 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
962 down.ConstData()[dir], // Traff before chunk
965 tariff->GetPriceWithTraffType(up.ConstData()[dir],
966 dt[dir], // Traff after chunk
972 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
973 down.ConstData()[dir],
978 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
980 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
981 cost = dc - freeMb.ConstData();
983 property.Stat().freeMb -= dc;
984 property.Stat().cash -= cost;
990 sessionDownload[dir] += len;
994 if (!settings->GetWriteFreeMbTraffCost() &&
995 freeMb.ConstData() >= 0)
998 #ifdef TRAFF_STAT_WITH_PORTS
999 IP_DIR_PAIR idp(ip, dir, port);
1001 IP_DIR_PAIR idp(ip, dir);
1004 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
1005 lb = traffStat.lower_bound(idp);
1006 if (lb == traffStat.end() || lb->first != idp)
1008 traffStat.insert(lb,
1010 STAT_NODE(0, len, cost)));
1014 lb->second.cash += cost;
1015 lb->second.down += len;
1018 //-----------------------------------------------------------------------------
1019 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1021 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1022 currIP.AddBeforeNotifier(notifier);
1024 //-----------------------------------------------------------------------------
1025 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1027 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1028 currIP.DelBeforeNotifier(notifier);
1030 //-----------------------------------------------------------------------------
1031 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1033 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1034 currIP.AddAfterNotifier(notifier);
1036 //-----------------------------------------------------------------------------
1037 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1039 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1040 currIP.DelAfterNotifier(notifier);
1042 //-----------------------------------------------------------------------------
1043 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1045 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1046 connected.AddBeforeNotifier(notifier);
1048 //-----------------------------------------------------------------------------
1049 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1051 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1052 connected.DelBeforeNotifier(notifier);
1054 //-----------------------------------------------------------------------------
1055 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1057 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1058 connected.AddAfterNotifier(notifier);
1060 //-----------------------------------------------------------------------------
1061 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1063 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1064 connected.DelAfterNotifier(notifier);
1066 //-----------------------------------------------------------------------------
1067 void USER_IMPL::OnAdd()
1069 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1071 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1073 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1075 std::string scriptOnAddParams;
1076 strprintf(&scriptOnAddParams,
1078 scriptOnAdd.c_str(),
1081 ScriptExec(scriptOnAddParams.c_str());
1085 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1088 //-----------------------------------------------------------------------------
1089 void USER_IMPL::OnDelete()
1091 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1093 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1095 if (access(scriptOnDel.c_str(), X_OK) == 0)
1097 std::string scriptOnDelParams;
1098 strprintf(&scriptOnDelParams,
1100 scriptOnDel.c_str(),
1103 ScriptExec(scriptOnDelParams.c_str());
1107 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1112 //-----------------------------------------------------------------------------
1113 int USER_IMPL::WriteDetailStat(bool hard)
1115 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1117 if (!traffStatSaved.second.empty())
1119 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1121 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1122 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1123 WriteServLog("%s", store->GetStrError().c_str());
1126 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1132 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1136 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1138 if (ts.size() && !disabledDetailStat)
1140 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1142 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1143 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1144 WriteServLog("%s", store->GetStrError().c_str());
1147 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1148 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1149 traffStatSaved.second.swap(ts);
1150 traffStatSaved.first = lastWriteDetailedStat;
1155 lastWriteDetailedStat = stgTime;
1158 //-----------------------------------------------------------------------------
1159 double USER_IMPL::GetPassiveTimePart() const
1161 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1163 static int daysInMonth[12] =
1164 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1168 localtime_r(&t, &tms);
1170 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1172 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1175 secMonth += 24 * 3600;
1178 time_t dt = secMonth - passiveTime;
1183 return static_cast<double>(dt) / secMonth;
1185 //-----------------------------------------------------------------------------
1186 void USER_IMPL::SetPassiveTimeAsNewUser()
1188 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1192 localtime_r(&t, &tm);
1193 int daysCurrMon = DaysInCurrentMonth();
1194 double pt = tm.tm_mday - 1;
1197 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1199 //-----------------------------------------------------------------------------
1200 void USER_IMPL::MidnightResetSessionStat()
1202 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1206 Disconnect(true, "fake");
1210 //-----------------------------------------------------------------------------
1211 void USER_IMPL::ProcessNewMonth()
1213 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1217 Disconnect(true, "fake");
1219 DIR_TRAFF zeroTarff;
1232 if (nextTariff.ConstData() != "")
1235 nt = tariffs->FindByName(nextTariff);
1238 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1239 login.c_str(), property.tariffName.Get().c_str());
1243 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1250 //-----------------------------------------------------------------------------
1251 void USER_IMPL::ProcessDayFeeSpread()
1253 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1255 if (passive.ConstData() || tariff == NULL)
1258 double fee = tariff->GetFee() / DaysInCurrentMonth();
1260 if (std::fabs(fee) < 1.0e-3)
1264 switch (settings->GetFeeChargeType())
1267 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1270 if (c + credit >= 0)
1271 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1274 if (c + credit >= fee)
1275 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1279 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1284 //-----------------------------------------------------------------------------
1285 void USER_IMPL::ProcessDayFee()
1287 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1292 double passiveTimePart = 1.0;
1293 if (!settings->GetFullFee())
1295 passiveTimePart = GetPassiveTimePart();
1299 if (passive.ConstData())
1301 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1305 double fee = tariff->GetFee() * passiveTimePart;
1309 if (std::fabs(fee) < 1.0e-3)
1316 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1323 switch (settings->GetFeeChargeType())
1326 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1330 if (c + credit >= 0)
1332 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1337 if (c + credit >= fee)
1339 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1346 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1352 //-----------------------------------------------------------------------------
1353 void USER_IMPL::SetPrepaidTraff()
1356 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1358 //-----------------------------------------------------------------------------
1359 int USER_IMPL::AddMessage(STG_MSG * msg)
1361 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1363 if (SendMessage(*msg))
1365 if (store->AddMessage(msg, login))
1367 errorStr = store->GetStrError();
1368 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1369 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1372 messages.push_back(*msg);
1376 if (msg->header.repeat > 0)
1378 msg->header.repeat--;
1380 //TODO: gcc v. 4.x generate ICE on x86_64
1381 msg->header.lastSendTime = static_cast<int>(time(NULL));
1383 msg->header.lastSendTime = static_cast<int>(stgTime);
1385 if (store->AddMessage(msg, login))
1387 errorStr = store->GetStrError();
1388 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1389 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1392 messages.push_back(*msg);
1397 //-----------------------------------------------------------------------------
1398 int USER_IMPL::SendMessage(STG_MSG & msg) const
1400 // No lock `cause we are already locked from caller
1402 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1403 while (it != authorizedBy.end())
1405 if (!(*it++)->SendMessage(msg, currIP))
1411 //TODO: gcc v. 4.x generate ICE on x86_64
1412 msg.header.lastSendTime = static_cast<int>(time(NULL));
1414 msg.header.lastSendTime = static_cast<int>(stgTime);
1416 msg.header.repeat--;
1420 //-----------------------------------------------------------------------------
1421 void USER_IMPL::ScanMessage()
1423 // No lock `cause we are already locked from caller
1424 // We need not check for the authorizedBy `cause it has already checked by caller
1426 std::list<STG_MSG>::iterator it(messages.begin());
1427 while (it != messages.end())
1429 if (settings->GetMessageTimeout() > 0 &&
1430 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1433 if (store->DelMessage(it->header.id, login))
1435 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1436 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1438 messages.erase(it++);
1441 if (it->GetNextSendTime() <= stgTime)
1443 if (SendMessage(*it))
1445 // We need to check all messages in queue for timeout
1449 if (it->header.repeat < 0)
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++);
1460 if (store->EditMessage(*it, login))
1462 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1463 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1474 //-----------------------------------------------------------------------------
1475 std::string USER_IMPL::GetParamValue(const std::string & name) const
1479 std::ostringstream stream;
1481 return stream.str();
1483 if (name == "login") return login;
1484 if (name == "ip") return currIP.ToString();
1485 if (name == "enabledDirs") return GetEnabledDirs();
1486 if (property.Exists(name)) return property.GetPropertyValue(name);
1489 WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1493 //-----------------------------------------------------------------------------
1494 //-----------------------------------------------------------------------------
1495 //-----------------------------------------------------------------------------
1496 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1498 if (newPassive && !oldPassive && user->tariff != NULL)
1499 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1505 //-----------------------------------------------------------------------------
1506 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1508 if (oldValue && !newValue && user->GetConnected())
1510 user->Disconnect(false, "disabled");
1512 else if (!oldValue && newValue && user->IsInetable())
1514 user->Connect(false);
1518 //-----------------------------------------------------------------------------
1519 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1521 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1522 user->Disconnect(false, "Change tariff");
1523 user->tariff = user->tariffs->FindByName(newTariff);
1524 if (user->settings->GetReconnectOnTariffChange() &&
1525 !user->authorizedBy.empty() &&
1527 user->Connect(false);
1529 //-----------------------------------------------------------------------------
1530 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1532 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1533 user->lastCashAdd = newCash - oldCash;
1535 //-----------------------------------------------------------------------------
1536 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1538 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1539 if (user->connected)
1540 user->Disconnect(false, "Change IP");
1541 if (!user->authorizedBy.empty() && user->IsInetable())
1542 user->Connect(false);
1544 //-----------------------------------------------------------------------------