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 += " \"";
605 scriptOnConnectParams += GetParamValue(it->c_str());
606 scriptOnConnectParams += "\"";
609 ScriptExec(scriptOnConnectParams.c_str());
613 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
619 if (store->WriteUserConnect(login, currIP))
621 WriteServLog("Cannot write connect for user %s.", login.c_str());
622 WriteServLog("%s", store->GetStrError().c_str());
626 lastIPForDisconnect = currIP;
628 //-----------------------------------------------------------------------------
629 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
632 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
635 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
637 if (!lastIPForDisconnect)
639 printfd(__FILE__, "lastIPForDisconnect\n");
645 std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
647 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
649 char dirsStr[DIR_NUM + 1];
650 dirsStr[DIR_NUM] = 0;
651 for (int i = 0; i < DIR_NUM; i++)
653 dirsStr[i] = enabledDirs[i] ? '1' : '0';
656 std::string scriptOnDisonnectParams;
657 strprintf(&scriptOnDisonnectParams,
658 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
659 scriptOnDisonnect.c_str(),
661 inet_ntostring(lastIPForDisconnect).c_str(),
666 std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
667 while (it != settings->GetScriptParams().end())
669 scriptOnDisonnectParams += " \"";
670 scriptOnDisonnectParams += GetParamValue(it->c_str());
671 scriptOnDisonnectParams += "\"";
674 ScriptExec(scriptOnDisonnectParams.c_str());
678 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
684 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
686 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
687 WriteServLog("%s", store->GetStrError().c_str());
691 lastIPForDisconnect = 0;
693 DIR_TRAFF zeroSesssion;
695 sessionUpload = zeroSesssion;
696 sessionDownload = zeroSesssion;
698 //-----------------------------------------------------------------------------
699 void USER_IMPL::PrintUser() const
702 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
703 std::cout << "============================================================" << std::endl;
704 std::cout << "id=" << id << std::endl;
705 std::cout << "login=" << login << std::endl;
706 std::cout << "password=" << password << std::endl;
707 std::cout << "passive=" << passive << std::endl;
708 std::cout << "disabled=" << disabled << std::endl;
709 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
710 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
711 std::cout << "tariffName=" << tariffName << std::endl;
712 std::cout << "address=" << address << std::endl;
713 std::cout << "phone=" << phone << std::endl;
714 std::cout << "email=" << email << std::endl;
715 std::cout << "note=" << note << std::endl;
716 std::cout << "realName=" <<realName << std::endl;
717 std::cout << "group=" << group << std::endl;
718 std::cout << "credit=" << credit << std::endl;
719 std::cout << "nextTariff=" << nextTariff << std::endl;
720 std::cout << "userdata0" << userdata0 << std::endl;
721 std::cout << "userdata1" << userdata1 << std::endl;
722 std::cout << "creditExpire=" << creditExpire << std::endl;
723 std::cout << "ips=" << ips << std::endl;
724 std::cout << "------------------------" << std::endl;
725 std::cout << "up=" << up << std::endl;
726 std::cout << "down=" << down << std::endl;
727 std::cout << "cash=" << cash << std::endl;
728 std::cout << "freeMb=" << freeMb << std::endl;
729 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
730 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
731 std::cout << "passiveTime=" << passiveTime << std::endl;
732 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
733 std::cout << "============================================================" << std::endl;
735 //-----------------------------------------------------------------------------
736 void USER_IMPL::Run()
738 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
740 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
742 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
745 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
747 WriteServLog("User: %s. Credit expired.", login.c_str());
753 if (passive.ConstData()
754 && (stgTime % 30 == 0)
755 && (passiveTime.ModificationTime() != stgTime))
757 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
758 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
761 if (!authorizedBy.empty())
765 property.Stat().lastActivityTime = stgTime;
767 if (!connected && IsInetable())
771 if (connected && !IsInetable())
774 Disconnect(false, "disabled");
776 Disconnect(false, "passive");
778 Disconnect(false, "no cash");
781 if (stgTime - lastScanMessages > 10)
784 lastScanMessages = stgTime;
791 Disconnect(false, "not authorized");
796 //-----------------------------------------------------------------------------
797 void USER_IMPL::UpdatePingTime(time_t t)
799 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
800 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
806 //-----------------------------------------------------------------------------
807 bool USER_IMPL::IsInetable()
809 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
811 if (disabled || passive)
814 if (settings->GetFreeMbAllowInet())
820 if (settings->GetShowFeeInCash() || tariff == NULL)
822 return (cash >= -credit);
825 return (cash - tariff->GetFee() >= -credit);
827 //-----------------------------------------------------------------------------
828 std::string USER_IMPL::GetEnabledDirs()
830 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
832 std::string dirs = "";
833 for(int i = 0; i < DIR_NUM; i++)
834 dirs += enabledDirs[i] ? "1" : "0";
837 //-----------------------------------------------------------------------------
838 #ifdef TRAFF_STAT_WITH_PORTS
839 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
841 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
844 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
846 if (!connected || tariff == NULL)
852 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
853 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
857 int tt = tariff->GetTraffType();
858 if (tt == TRAFF_UP ||
859 tt == TRAFF_UP_DOWN ||
860 // Check NEW traff data
861 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
864 if (traff < threshold &&
865 traff + len >= threshold)
867 // cash = partBeforeThreshold * priceBeforeThreshold +
868 // partAfterThreshold * priceAfterThreshold
869 int64_t before = threshold - traff; // Chunk part before threshold
870 int64_t after = len - before; // Chunk part after threshold
871 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
872 down.ConstData()[dir],
875 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
876 down.ConstData()[dir],
882 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
883 down.ConstData()[dir],
888 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
890 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
891 cost = dc - freeMb.ConstData();
893 // Direct access to internal data structures via friend-specifier
894 property.Stat().freeMb -= dc;
895 property.Stat().cash -= cost;
901 sessionUpload[dir] += len;
905 if (!settings->GetWriteFreeMbTraffCost() &&
906 freeMb.ConstData() >= 0)
909 #ifdef TRAFF_STAT_WITH_PORTS
910 IP_DIR_PAIR idp(ip, dir, port);
912 IP_DIR_PAIR idp(ip, dir);
915 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
916 lb = traffStat.lower_bound(idp);
917 if (lb == traffStat.end() || lb->first != idp)
921 STAT_NODE(len, 0, cost)));
925 lb->second.cash += cost;
926 lb->second.up += len;
929 //-----------------------------------------------------------------------------
930 #ifdef TRAFF_STAT_WITH_PORTS
931 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
933 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
936 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
938 if (!connected || tariff == NULL)
944 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
945 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
949 int tt = tariff->GetTraffType();
950 if (tt == TRAFF_DOWN ||
951 tt == TRAFF_UP_DOWN ||
952 // Check NEW traff data
953 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
956 if (traff < threshold &&
957 traff + len >= threshold)
959 // cash = partBeforeThreshold * priceBeforeThreshold +
960 // partAfterThreshold * priceAfterThreshold
961 int64_t before = threshold - traff; // Chunk part before threshold
962 int64_t after = len - before; // Chunk part after threshold
963 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
964 down.ConstData()[dir], // Traff before chunk
967 tariff->GetPriceWithTraffType(up.ConstData()[dir],
968 dt[dir], // Traff after chunk
974 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
975 down.ConstData()[dir],
980 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
982 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
983 cost = dc - freeMb.ConstData();
985 property.Stat().freeMb -= dc;
986 property.Stat().cash -= cost;
992 sessionDownload[dir] += len;
996 if (!settings->GetWriteFreeMbTraffCost() &&
997 freeMb.ConstData() >= 0)
1000 #ifdef TRAFF_STAT_WITH_PORTS
1001 IP_DIR_PAIR idp(ip, dir, port);
1003 IP_DIR_PAIR idp(ip, dir);
1006 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
1007 lb = traffStat.lower_bound(idp);
1008 if (lb == traffStat.end() || lb->first != idp)
1010 traffStat.insert(lb,
1012 STAT_NODE(0, len, cost)));
1016 lb->second.cash += cost;
1017 lb->second.down += len;
1020 //-----------------------------------------------------------------------------
1021 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1023 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1024 currIP.AddBeforeNotifier(notifier);
1026 //-----------------------------------------------------------------------------
1027 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1029 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1030 currIP.DelBeforeNotifier(notifier);
1032 //-----------------------------------------------------------------------------
1033 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1035 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1036 currIP.AddAfterNotifier(notifier);
1038 //-----------------------------------------------------------------------------
1039 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1041 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1042 currIP.DelAfterNotifier(notifier);
1044 //-----------------------------------------------------------------------------
1045 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1047 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1048 connected.AddBeforeNotifier(notifier);
1050 //-----------------------------------------------------------------------------
1051 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1053 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1054 connected.DelBeforeNotifier(notifier);
1056 //-----------------------------------------------------------------------------
1057 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1059 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1060 connected.AddAfterNotifier(notifier);
1062 //-----------------------------------------------------------------------------
1063 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1065 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1066 connected.DelAfterNotifier(notifier);
1068 //-----------------------------------------------------------------------------
1069 void USER_IMPL::OnAdd()
1071 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1073 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1075 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1077 std::string scriptOnAddParams;
1078 strprintf(&scriptOnAddParams,
1080 scriptOnAdd.c_str(),
1083 ScriptExec(scriptOnAddParams.c_str());
1087 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1090 //-----------------------------------------------------------------------------
1091 void USER_IMPL::OnDelete()
1093 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1095 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1097 if (access(scriptOnDel.c_str(), X_OK) == 0)
1099 std::string scriptOnDelParams;
1100 strprintf(&scriptOnDelParams,
1102 scriptOnDel.c_str(),
1105 ScriptExec(scriptOnDelParams.c_str());
1109 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1114 //-----------------------------------------------------------------------------
1115 int USER_IMPL::WriteDetailStat(bool hard)
1117 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1119 if (!traffStatSaved.second.empty())
1121 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1123 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1124 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1125 WriteServLog("%s", store->GetStrError().c_str());
1128 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1134 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1138 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1140 if (ts.size() && !disabledDetailStat)
1142 if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1144 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1145 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1146 WriteServLog("%s", store->GetStrError().c_str());
1149 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1150 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1151 traffStatSaved.second.swap(ts);
1152 traffStatSaved.first = lastWriteDetailedStat;
1157 lastWriteDetailedStat = stgTime;
1160 //-----------------------------------------------------------------------------
1161 double USER_IMPL::GetPassiveTimePart() const
1163 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1165 static int daysInMonth[12] =
1166 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1170 localtime_r(&t, &tms);
1172 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1174 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1177 secMonth += 24 * 3600;
1180 time_t dt = secMonth - passiveTime;
1185 return static_cast<double>(dt) / secMonth;
1187 //-----------------------------------------------------------------------------
1188 void USER_IMPL::SetPassiveTimeAsNewUser()
1190 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1194 localtime_r(&t, &tm);
1195 int daysCurrMon = DaysInCurrentMonth();
1196 double pt = tm.tm_mday - 1;
1199 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1201 //-----------------------------------------------------------------------------
1202 void USER_IMPL::MidnightResetSessionStat()
1204 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1208 Disconnect(true, "fake");
1212 //-----------------------------------------------------------------------------
1213 void USER_IMPL::ProcessNewMonth()
1215 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1219 Disconnect(true, "fake");
1221 DIR_TRAFF zeroTarff;
1234 if (nextTariff.ConstData() != "")
1237 nt = tariffs->FindByName(nextTariff);
1240 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1241 login.c_str(), property.tariffName.Get().c_str());
1245 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1252 //-----------------------------------------------------------------------------
1253 void USER_IMPL::ProcessDayFeeSpread()
1255 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1257 if (passive.ConstData() || tariff == NULL)
1260 double fee = tariff->GetFee() / DaysInCurrentMonth();
1262 if (std::fabs(fee) < 1.0e-3)
1266 switch (settings->GetFeeChargeType())
1269 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1272 if (c + credit >= 0)
1273 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1276 if (c + credit >= fee)
1277 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1281 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1286 //-----------------------------------------------------------------------------
1287 void USER_IMPL::ProcessDayFee()
1289 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1294 double passiveTimePart = 1.0;
1295 if (!settings->GetFullFee())
1297 passiveTimePart = GetPassiveTimePart();
1301 if (passive.ConstData())
1303 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1307 double fee = tariff->GetFee() * passiveTimePart;
1311 if (std::fabs(fee) < 1.0e-3)
1318 printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
1325 switch (settings->GetFeeChargeType())
1328 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1332 if (c + credit >= 0)
1334 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1339 if (c + credit >= fee)
1341 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1348 property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1354 //-----------------------------------------------------------------------------
1355 void USER_IMPL::SetPrepaidTraff()
1358 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1360 //-----------------------------------------------------------------------------
1361 int USER_IMPL::AddMessage(STG_MSG * msg)
1363 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1365 if (SendMessage(*msg))
1367 if (store->AddMessage(msg, login))
1369 errorStr = store->GetStrError();
1370 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1371 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1374 messages.push_back(*msg);
1378 if (msg->header.repeat > 0)
1380 msg->header.repeat--;
1382 //TODO: gcc v. 4.x generate ICE on x86_64
1383 msg->header.lastSendTime = static_cast<int>(time(NULL));
1385 msg->header.lastSendTime = static_cast<int>(stgTime);
1387 if (store->AddMessage(msg, login))
1389 errorStr = store->GetStrError();
1390 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1391 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1394 messages.push_back(*msg);
1399 //-----------------------------------------------------------------------------
1400 int USER_IMPL::SendMessage(STG_MSG & msg) const
1402 // No lock `cause we are already locked from caller
1404 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1405 while (it != authorizedBy.end())
1407 if (!(*it++)->SendMessage(msg, currIP))
1413 //TODO: gcc v. 4.x generate ICE on x86_64
1414 msg.header.lastSendTime = static_cast<int>(time(NULL));
1416 msg.header.lastSendTime = static_cast<int>(stgTime);
1418 msg.header.repeat--;
1422 //-----------------------------------------------------------------------------
1423 void USER_IMPL::ScanMessage()
1425 // No lock `cause we are already locked from caller
1426 // We need not check for the authorizedBy `cause it has already checked by caller
1428 std::list<STG_MSG>::iterator it(messages.begin());
1429 while (it != messages.end())
1431 if (settings->GetMessageTimeout() > 0 &&
1432 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1435 if (store->DelMessage(it->header.id, login))
1437 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1438 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1440 messages.erase(it++);
1443 if (it->GetNextSendTime() <= stgTime)
1445 if (SendMessage(*it))
1447 // We need to check all messages in queue for timeout
1451 if (it->header.repeat < 0)
1453 if (store->DelMessage(it->header.id, login))
1455 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1456 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1458 messages.erase(it++);
1462 if (store->EditMessage(*it, login))
1464 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1465 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1476 //-----------------------------------------------------------------------------
1477 std::string USER_IMPL::GetParamValue(const std::string & name) const
1479 if (name == "freeMb") return property.freeMb.ToString();
1480 if (name == "passive") return property.passive.ToString();
1481 if (name == "disabled") return property.disabled.ToString();
1482 if (name == "alwaysOnline") return property.alwaysOnline.ToString();
1483 if (name == "tariffName") return property.tariffName;
1484 if (name == "nextTariff") return property.nextTariff;
1485 if (name == "address") return property.address;
1486 if (name == "note") return property.note;
1487 if (name == "group") return property.group;
1488 if (name == "email") return property.email;
1489 if (name == "phone") return property.phone;
1490 if (name == "realName") return property.realName;
1491 if (name == "credit") return property.credit.ToString();
1492 if (name == "userdata0") return property.userdata0;
1493 if (name == "userdata1") return property.userdata1;
1494 if (name == "userdata2") return property.userdata2;
1495 if (name == "userdata3") return property.userdata3;
1496 if (name == "userdata4") return property.userdata4;
1497 if (name == "userdata5") return property.userdata5;
1498 if (name == "userdata6") return property.userdata6;
1499 if (name == "userdata7") return property.userdata7;
1500 if (name == "userdata8") return property.userdata8;
1501 if (name == "userdata9") return property.userdata9;
1502 //if (name == "cash") return property.cash.ToString();
1505 // std::stringstream stream;
1507 // return stream.str();;
1509 //if (name == "login") return login;
1510 //if (name == "ip") return currIP.ToString();
1512 //-----------------------------------------------------------------------------
1513 //-----------------------------------------------------------------------------
1514 //-----------------------------------------------------------------------------
1515 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1517 if (newPassive && !oldPassive && user->tariff != NULL)
1518 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1524 //-----------------------------------------------------------------------------
1525 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1527 if (oldValue && !newValue && user->GetConnected())
1529 user->Disconnect(false, "disabled");
1531 else if (!oldValue && newValue && user->IsInetable())
1533 user->Connect(false);
1537 //-----------------------------------------------------------------------------
1538 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1540 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1541 user->Disconnect(false, "Change tariff");
1542 user->tariff = user->tariffs->FindByName(newTariff);
1543 if (user->settings->GetReconnectOnTariffChange() &&
1544 !user->authorizedBy.empty() &&
1546 user->Connect(false);
1548 //-----------------------------------------------------------------------------
1549 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1551 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1552 user->lastCashAdd = newCash - oldCash;
1554 //-----------------------------------------------------------------------------
1555 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1557 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1558 if (user->connected)
1559 user->Disconnect(false, "Change IP");
1560 if (!user->authorizedBy.empty() && user->IsInetable())
1561 user->Connect(false);
1563 //-----------------------------------------------------------------------------