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()) + "\"";
607 ScriptExec(scriptOnConnectParams.c_str());
611 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
617 if (store->WriteUserConnect(login, currIP))
619 WriteServLog("Cannot write connect for user %s.", login.c_str());
620 WriteServLog("%s", store->GetStrError().c_str());
624 lastIPForDisconnect = currIP;
626 //-----------------------------------------------------------------------------
627 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
630 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
633 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
635 if (!lastIPForDisconnect)
637 printfd(__FILE__, "lastIPForDisconnect\n");
643 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
645 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
647 char dirsStr[DIR_NUM + 1];
648 dirsStr[DIR_NUM] = 0;
649 for (int i = 0; i < DIR_NUM; i++)
651 dirsStr[i] = enabledDirs[i] ? '1' : '0';
654 std::string scriptOnDisonnectParams;
655 strprintf(&scriptOnDisonnectParams,
656 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
657 scriptOnDisonnect.c_str(),
659 inet_ntostring(lastIPForDisconnect).c_str(),
664 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
665 while (it != settings->GetScriptParams().end())
667 scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
670 ScriptExec(scriptOnDisonnectParams.c_str());
674 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
680 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
682 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
683 WriteServLog("%s", store->GetStrError().c_str());
687 lastIPForDisconnect = 0;
689 DIR_TRAFF zeroSesssion;
691 sessionUpload = zeroSesssion;
692 sessionDownload = zeroSesssion;
694 //-----------------------------------------------------------------------------
695 void USER_IMPL::PrintUser() const
698 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
699 std::cout << "============================================================" << std::endl;
700 std::cout << "id=" << id << std::endl;
701 std::cout << "login=" << login << std::endl;
702 std::cout << "password=" << password << std::endl;
703 std::cout << "passive=" << passive << std::endl;
704 std::cout << "disabled=" << disabled << std::endl;
705 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
706 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
707 std::cout << "tariffName=" << tariffName << std::endl;
708 std::cout << "address=" << address << std::endl;
709 std::cout << "phone=" << phone << std::endl;
710 std::cout << "email=" << email << std::endl;
711 std::cout << "note=" << note << std::endl;
712 std::cout << "realName=" <<realName << std::endl;
713 std::cout << "group=" << group << std::endl;
714 std::cout << "credit=" << credit << std::endl;
715 std::cout << "nextTariff=" << nextTariff << std::endl;
716 std::cout << "userdata0" << userdata0 << std::endl;
717 std::cout << "userdata1" << userdata1 << std::endl;
718 std::cout << "creditExpire=" << creditExpire << std::endl;
719 std::cout << "ips=" << ips << std::endl;
720 std::cout << "------------------------" << std::endl;
721 std::cout << "up=" << up << std::endl;
722 std::cout << "down=" << down << std::endl;
723 std::cout << "cash=" << cash << std::endl;
724 std::cout << "freeMb=" << freeMb << std::endl;
725 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
726 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
727 std::cout << "passiveTime=" << passiveTime << std::endl;
728 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
729 std::cout << "============================================================" << std::endl;
731 //-----------------------------------------------------------------------------
732 void USER_IMPL::Run()
734 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
736 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
738 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
741 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
743 WriteServLog("User: %s. Credit expired.", login.c_str());
749 if (passive.ConstData()
750 && (stgTime % 30 == 0)
751 && (passiveTime.ModificationTime() != stgTime))
753 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
754 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
757 if (!authorizedBy.empty())
761 property.Stat().lastActivityTime = stgTime;
763 if (!connected && IsInetable())
767 if (connected && !IsInetable())
770 Disconnect(false, "disabled");
772 Disconnect(false, "passive");
774 Disconnect(false, "no cash");
777 if (stgTime - lastScanMessages > 10)
780 lastScanMessages = stgTime;
787 Disconnect(false, "not authorized");
792 //-----------------------------------------------------------------------------
793 void USER_IMPL::UpdatePingTime(time_t t)
795 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
796 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
802 //-----------------------------------------------------------------------------
803 bool USER_IMPL::IsInetable()
805 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
807 if (disabled || passive)
810 if (settings->GetFreeMbAllowInet())
816 if (settings->GetShowFeeInCash() || tariff == NULL)
818 return (cash >= -credit);
821 return (cash - tariff->GetFee() >= -credit);
823 //-----------------------------------------------------------------------------
824 std::string USER_IMPL::GetEnabledDirs()
826 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
828 std::string dirs = "";
829 for(int i = 0; i < DIR_NUM; i++)
830 dirs += enabledDirs[i] ? "1" : "0";
833 //-----------------------------------------------------------------------------
834 #ifdef TRAFF_STAT_WITH_PORTS
835 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
837 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
840 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
842 if (!connected || tariff == NULL)
848 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
849 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
853 int tt = tariff->GetTraffType();
854 if (tt == TRAFF_UP ||
855 tt == TRAFF_UP_DOWN ||
856 // Check NEW traff data
857 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
860 if (traff < threshold &&
861 traff + len >= threshold)
863 // cash = partBeforeThreshold * priceBeforeThreshold +
864 // partAfterThreshold * priceAfterThreshold
865 int64_t before = threshold - traff; // Chunk part before threshold
866 int64_t after = len - before; // Chunk part after threshold
867 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
868 down.ConstData()[dir],
871 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
872 down.ConstData()[dir],
878 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
879 down.ConstData()[dir],
884 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
886 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
887 cost = dc - freeMb.ConstData();
889 // Direct access to internal data structures via friend-specifier
890 property.Stat().freeMb -= dc;
891 property.Stat().cash -= cost;
897 sessionUpload[dir] += len;
901 if (!settings->GetWriteFreeMbTraffCost() &&
902 freeMb.ConstData() >= 0)
905 #ifdef TRAFF_STAT_WITH_PORTS
906 IP_DIR_PAIR idp(ip, dir, port);
908 IP_DIR_PAIR idp(ip, dir);
911 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
912 lb = traffStat.lower_bound(idp);
913 if (lb == traffStat.end() || lb->first != idp)
917 STAT_NODE(len, 0, cost)));
921 lb->second.cash += cost;
922 lb->second.up += len;
925 //-----------------------------------------------------------------------------
926 #ifdef TRAFF_STAT_WITH_PORTS
927 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
929 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
932 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
934 if (!connected || tariff == NULL)
940 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
941 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
945 int tt = tariff->GetTraffType();
946 if (tt == TRAFF_DOWN ||
947 tt == TRAFF_UP_DOWN ||
948 // Check NEW traff data
949 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
952 if (traff < threshold &&
953 traff + len >= threshold)
955 // cash = partBeforeThreshold * priceBeforeThreshold +
956 // partAfterThreshold * priceAfterThreshold
957 int64_t before = threshold - traff; // Chunk part before threshold
958 int64_t after = len - before; // Chunk part after threshold
959 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
960 down.ConstData()[dir], // Traff before chunk
963 tariff->GetPriceWithTraffType(up.ConstData()[dir],
964 dt[dir], // Traff after chunk
970 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
971 down.ConstData()[dir],
976 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
978 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
979 cost = dc - freeMb.ConstData();
981 property.Stat().freeMb -= dc;
982 property.Stat().cash -= cost;
988 sessionDownload[dir] += len;
992 if (!settings->GetWriteFreeMbTraffCost() &&
993 freeMb.ConstData() >= 0)
996 #ifdef TRAFF_STAT_WITH_PORTS
997 IP_DIR_PAIR idp(ip, dir, port);
999 IP_DIR_PAIR idp(ip, dir);
1002 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
1003 lb = traffStat.lower_bound(idp);
1004 if (lb == traffStat.end() || lb->first != idp)
1006 traffStat.insert(lb,
1008 STAT_NODE(0, len, cost)));
1012 lb->second.cash += cost;
1013 lb->second.down += len;
1016 //-----------------------------------------------------------------------------
1017 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1019 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1020 currIP.AddBeforeNotifier(notifier);
1022 //-----------------------------------------------------------------------------
1023 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1025 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1026 currIP.DelBeforeNotifier(notifier);
1028 //-----------------------------------------------------------------------------
1029 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1031 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1032 currIP.AddAfterNotifier(notifier);
1034 //-----------------------------------------------------------------------------
1035 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1037 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1038 currIP.DelAfterNotifier(notifier);
1040 //-----------------------------------------------------------------------------
1041 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1043 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1044 connected.AddBeforeNotifier(notifier);
1046 //-----------------------------------------------------------------------------
1047 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1049 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1050 connected.DelBeforeNotifier(notifier);
1052 //-----------------------------------------------------------------------------
1053 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1055 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1056 connected.AddAfterNotifier(notifier);
1058 //-----------------------------------------------------------------------------
1059 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1061 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1062 connected.DelAfterNotifier(notifier);
1064 //-----------------------------------------------------------------------------
1065 void USER_IMPL::OnAdd()
1067 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1069 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1071 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1073 std::string scriptOnAddParams;
1074 strprintf(&scriptOnAddParams,
1076 scriptOnAdd.c_str(),
1079 ScriptExec(scriptOnAddParams.c_str());
1083 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1086 //-----------------------------------------------------------------------------
1087 void USER_IMPL::OnDelete()
1089 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1091 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1093 if (access(scriptOnDel.c_str(), X_OK) == 0)
1095 std::string scriptOnDelParams;
1096 strprintf(&scriptOnDelParams,
1098 scriptOnDel.c_str(),
1101 ScriptExec(scriptOnDelParams.c_str());
1105 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1110 //-----------------------------------------------------------------------------
1111 int USER_IMPL::WriteDetailStat(bool hard)
1113 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1115 if (!traffStatSaved.second.empty())
1117 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1119 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1120 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1121 WriteServLog("%s", store->GetStrError().c_str());
1124 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1130 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1134 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1136 if (ts.size() && !disabledDetailStat)
1138 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1140 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1141 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1142 WriteServLog("%s", store->GetStrError().c_str());
1145 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1146 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1147 traffStatSaved.second.swap(ts);
1148 traffStatSaved.first = lastWriteDetailedStat;
1153 lastWriteDetailedStat = stgTime;
1156 //-----------------------------------------------------------------------------
1157 double USER_IMPL::GetPassiveTimePart() const
1159 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1161 static int daysInMonth[12] =
1162 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1166 localtime_r(&t, &tms);
1168 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1170 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1173 secMonth += 24 * 3600;
1176 time_t dt = secMonth - passiveTime;
1181 return static_cast<double>(dt) / secMonth;
1183 //-----------------------------------------------------------------------------
1184 void USER_IMPL::SetPassiveTimeAsNewUser()
1186 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1190 localtime_r(&t, &tm);
1191 int daysCurrMon = DaysInCurrentMonth();
1192 double pt = tm.tm_mday - 1;
1195 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1197 //-----------------------------------------------------------------------------
1198 void USER_IMPL::MidnightResetSessionStat()
1200 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1204 Disconnect(true, "fake");
1208 //-----------------------------------------------------------------------------
1209 void USER_IMPL::ProcessNewMonth()
1211 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1215 Disconnect(true, "fake");
1217 DIR_TRAFF zeroTarff;
1230 if (nextTariff.ConstData() != "")
1233 nt = tariffs->FindByName(nextTariff);
1236 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1237 login.c_str(), property.tariffName.Get().c_str());
1241 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1248 //-----------------------------------------------------------------------------
1249 void USER_IMPL::ProcessDayFeeSpread()
1251 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1253 if (passive.ConstData() || tariff == NULL)
1256 double fee = tariff->GetFee() / DaysInCurrentMonth();
1258 if (std::fabs(fee) < 1.0e-3)
1262 switch (settings->GetFeeChargeType())
1265 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1268 if (c + credit >= 0)
1269 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1272 if (c + credit >= fee)
1273 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1277 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1282 //-----------------------------------------------------------------------------
1283 void USER_IMPL::ProcessDayFee()
1285 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1290 double passiveTimePart = 1.0;
1291 if (!settings->GetFullFee())
1293 passiveTimePart = GetPassiveTimePart();
1297 if (passive.ConstData())
1299 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1303 double fee = tariff->GetFee() * passiveTimePart;
1307 if (std::fabs(fee) < 1.0e-3)
1314 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1321 switch (settings->GetFeeChargeType())
1324 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1328 if (c + credit >= 0)
1330 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1335 if (c + credit >= fee)
1337 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1344 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, __FILE__, __LINE__);
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 if (name == "freeMb") return property.freeMb.ToString();
1476 if (name == "passive") return property.passive.ToString();
1477 if (name == "disabled") return property.disabled.ToString();
1478 if (name == "alwaysOnline") return property.alwaysOnline.ToString();
1479 if (name == "tariffName") return property.tariffName;
1480 if (name == "nextTariff") return property.nextTariff;
1481 if (name == "address") return property.address;
1482 if (name == "note") return property.note;
1483 if (name == "group") return property.group;
1484 if (name == "email") return property.email;
1485 if (name == "phone") return property.phone;
1486 if (name == "realName") return property.realName;
1487 if (name == "credit") return property.credit.ToString();
1488 if (name == "userdata0") return property.userdata0;
1489 if (name == "userdata1") return property.userdata1;
1490 if (name == "userdata2") return property.userdata2;
1491 if (name == "userdata3") return property.userdata3;
1492 if (name == "userdata4") return property.userdata4;
1493 if (name == "userdata5") return property.userdata5;
1494 if (name == "userdata6") return property.userdata6;
1495 if (name == "userdata7") return property.userdata7;
1496 if (name == "userdata8") return property.userdata8;
1497 if (name == "userdata9") return property.userdata9;
1498 //if (name == "cash") return property.cash.ToString();
1501 // std::stringstream stream;
1503 // return stream.str();;
1505 //if (name == "login") return login;
1506 //if (name == "ip") return currIP.ToString();
1508 //-----------------------------------------------------------------------------
1509 //-----------------------------------------------------------------------------
1510 //-----------------------------------------------------------------------------
1511 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1513 if (newPassive && !oldPassive && user->tariff != NULL)
1514 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1520 //-----------------------------------------------------------------------------
1521 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1523 if (oldValue && !newValue && user->GetConnected())
1525 user->Disconnect(false, "disabled");
1527 else if (!oldValue && newValue && user->IsInetable())
1529 user->Connect(false);
1533 //-----------------------------------------------------------------------------
1534 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1536 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1537 user->Disconnect(false, "Change tariff");
1538 user->tariff = user->tariffs->FindByName(newTariff);
1539 if (user->settings->GetReconnectOnTariffChange() &&
1540 !user->authorizedBy.empty() &&
1542 user->Connect(false);
1544 //-----------------------------------------------------------------------------
1545 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1547 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1548 user->lastCashAdd = newCash - oldCash;
1550 //-----------------------------------------------------------------------------
1551 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1553 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1554 if (user->connected)
1555 user->Disconnect(false, "Change IP");
1556 if (!user->authorizedBy.empty() && user->IsInetable())
1557 user->Connect(false);
1559 //-----------------------------------------------------------------------------