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
40 #include "user_impl.h"
44 #include "script_executer.h"
49 USER_IMPL::USER_IMPL(const SETTINGS * s,
55 property(s->GetScriptsDir()),
56 WriteServLog(GetStgLogger()),
60 connected(__connected),
64 lastIPForDisconnect(0),
69 tariff(tariffs->GetNoTariff()),
73 lastCashAdd(property.lastCashAdd),
74 passiveTime(property.passiveTime),
75 lastCashAddTime(property.lastCashAddTime),
76 freeMb(property.freeMb),
77 lastActivityTime(property.lastActivityTime),
78 password(property.password),
79 passive(property.passive),
80 disabled(property.disabled),
81 disabledDetailStat(property.disabledDetailStat),
82 alwaysOnline(property.alwaysOnline),
83 tariffName(property.tariffName),
84 nextTariff(property.nextTariff),
85 address(property.address),
87 group(property.group),
88 email(property.email),
89 phone(property.phone),
90 realName(property.realName),
91 credit(property.credit),
92 creditExpire(property.creditExpire),
94 userdata0(property.userdata0),
95 userdata1(property.userdata1),
96 userdata2(property.userdata2),
97 userdata3(property.userdata3),
98 userdata4(property.userdata4),
99 userdata5(property.userdata5),
100 userdata6(property.userdata6),
101 userdata7(property.userdata7),
102 userdata8(property.userdata8),
103 userdata9(property.userdata9),
104 passiveNotifier(this),
105 tariffNotifier(this),
111 password = "*_EMPTY_PASSWORD_*";
112 tariffName = NO_TARIFF_NAME;
114 tariff = tariffs->GetNoTariff();
117 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
118 lastWriteDeatiledStat = stgTime;
120 property.tariffName.AddBeforeNotifier(&tariffNotifier);
121 property.passive.AddBeforeNotifier(&passiveNotifier);
122 property.cash.AddBeforeNotifier(&cashNotifier);
123 currIP.AddAfterNotifier(&ipNotifier);
125 lastScanMessages = 0;
127 pthread_mutexattr_t attr;
128 pthread_mutexattr_init(&attr);
129 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
130 pthread_mutex_init(&mutex, &attr);
132 //-----------------------------------------------------------------------------
133 USER_IMPL::USER_IMPL(const USER_IMPL & u)
135 property(u.settings->GetScriptsDir()),
136 WriteServLog(GetStgLogger()),
139 __connected(u.__connected),
140 connected(__connected),
141 __currIP(u.__currIP),
143 lastIPForDisconnect(0),
144 pingTime(u.pingTime),
145 sysAdmin(u.sysAdmin),
152 lastCashAdd(property.lastCashAdd),
153 passiveTime(property.passiveTime),
154 lastCashAddTime(property.lastCashAddTime),
155 freeMb(property.freeMb),
156 lastActivityTime(property.lastActivityTime),
157 password(property.password),
158 passive(property.passive),
159 disabled(property.disabled),
160 disabledDetailStat(property.disabledDetailStat),
161 alwaysOnline(property.alwaysOnline),
162 tariffName(property.tariffName),
163 nextTariff(property.nextTariff),
164 address(property.address),
166 group(property.group),
167 email(property.email),
168 phone(property.phone),
169 realName(property.realName),
170 credit(property.credit),
171 creditExpire(property.creditExpire),
173 userdata0(property.userdata0),
174 userdata1(property.userdata1),
175 userdata2(property.userdata2),
176 userdata3(property.userdata3),
177 userdata4(property.userdata4),
178 userdata5(property.userdata5),
179 userdata6(property.userdata6),
180 userdata7(property.userdata7),
181 userdata8(property.userdata8),
182 userdata9(property.userdata9),
183 passiveNotifier(this),
184 tariffNotifier(this),
195 lastWriteStat = u.lastWriteStat;
196 lastWriteDeatiledStat = u.lastWriteDeatiledStat;
198 settings = u.settings;
200 property.tariffName.AddBeforeNotifier(&tariffNotifier);
201 property.passive.AddBeforeNotifier(&passiveNotifier);
202 property.cash.AddBeforeNotifier(&cashNotifier);
203 currIP.AddAfterNotifier(&ipNotifier);
205 lastScanMessages = 0;
207 property.SetProperties(u.property);
209 pthread_mutexattr_t attr;
210 pthread_mutexattr_init(&attr);
211 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
212 pthread_mutex_init(&mutex, &attr);
214 //-----------------------------------------------------------------------------
215 USER_IMPL::~USER_IMPL()
217 property.passive.DelBeforeNotifier(&passiveNotifier);
218 property.tariffName.DelBeforeNotifier(&tariffNotifier);
219 pthread_mutex_destroy(&mutex);
221 //-----------------------------------------------------------------------------
222 void USER_IMPL::SetLogin(string const & l)
224 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
225 assert(login.empty() && "Login is already set");
227 id = userIDGenerator.GetNextID();
229 //-----------------------------------------------------------------------------
230 int USER_IMPL::ReadConf()
232 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
235 if (store->RestoreUserConf(&conf, login))
237 WriteServLog("Cannot read conf for user %s.", login.c_str());
238 WriteServLog("%s", store->GetStrError().c_str());
239 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
240 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
244 property.SetConf(conf);
246 tariff = tariffs->FindByName(tariffName);
249 WriteServLog("Cannot read user %s. Tariff %s not exist.",
250 login.c_str(), property.tariffName.Get().c_str());
254 std::vector<STG_MSG_HDR> hdrsList;
256 if (store->GetMessageHdrs(&hdrsList, login))
258 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
262 std::vector<STG_MSG_HDR>::const_iterator it;
263 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
266 if (store->GetMessage(it->id, &msg, login) == 0)
268 messages.push_back(msg);
274 //-----------------------------------------------------------------------------
275 int USER_IMPL::ReadStat()
277 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
280 if (store->RestoreUserStat(&stat, login))
282 WriteServLog("Cannot read stat for user %s.", login.c_str());
283 WriteServLog("%s", store->GetStrError().c_str());
284 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
285 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
289 property.SetStat(stat);
293 //-----------------------------------------------------------------------------
294 int USER_IMPL::WriteConf()
296 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
297 USER_CONF conf(property.GetConf());
299 printfd(__FILE__, "USER::WriteConf()\n");
301 if (store->SaveUserConf(conf, login))
303 WriteServLog("Cannot write conf for user %s.", login.c_str());
304 WriteServLog("%s", store->GetStrError().c_str());
305 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
306 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
312 //-----------------------------------------------------------------------------
313 int USER_IMPL::WriteStat()
315 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
316 USER_STAT stat(property.GetStat());
318 printfd(__FILE__, "USER::WriteStat()\n");
320 if (store->SaveUserStat(stat, login))
322 WriteServLog("Cannot write stat for user %s.", login.c_str());
323 WriteServLog("%s", store->GetStrError().c_str());
324 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
325 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
329 lastWriteStat = stgTime;
333 //-----------------------------------------------------------------------------
334 int USER_IMPL::WriteMonthStat()
336 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
337 time_t tt = stgTime - 3600;
339 localtime_r(&tt, &t1);
341 USER_STAT stat(property.GetStat());
342 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
344 WriteServLog("Cannot write month stat for user %s.", login.c_str());
345 WriteServLog("%s", store->GetStrError().c_str());
346 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
347 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
353 //-----------------------------------------------------------------------------
354 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
356 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
358 * Authorize user. It only means that user will be authorized. Nothing more.
359 * User can be connected or disconnected while authorized.
360 * Example: user is authorized but disconnected due to 0 money or blocking
364 * Prevent double authorization by identical authorizers
366 if (authorizedBy.find(auth) != authorizedBy.end())
372 for (int i = 0; i < DIR_NUM; i++)
374 enabledDirs[i] = dirs & (1 << i);
377 if (authorizedBy.size())
381 // We are already authorized, but with different IP address
382 errorStr = "User " + login + " alredy authorized with IP address " + inet_ntostring(ip);
387 if (!users->FindByIPIdx(ip, &u))
389 // Address is already present in IP-index
390 // If it's not our IP - throw an error
393 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
400 if (users->IsIPInIndex(ip))
402 // Address is already present in IP-index
403 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
407 if (ips.ConstData().IsIPInIPS(ip))
410 lastIPForDisconnect = currIP;
414 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
415 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
420 authorizedBy.insert(auth);
426 //-----------------------------------------------------------------------------
427 void USER_IMPL::Unauthorize(const AUTH * auth)
429 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
431 * Authorizer tries to unauthorize user, that was not authorized by it
433 if (!authorizedBy.erase(auth))
436 if (authorizedBy.empty())
438 lastIPForDisconnect = currIP;
439 currIP = 0; // DelUser in traffcounter
443 //-----------------------------------------------------------------------------
444 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
446 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
447 // Is this user authorized by specified authorizer?
448 return authorizedBy.find(auth) != authorizedBy.end();
450 //-----------------------------------------------------------------------------
451 void USER_IMPL::Connect(bool fakeConnect)
454 * Connect user to Internet. This function is differ from Authorize() !!!
457 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
461 string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
463 if (access(scriptOnConnect.c_str(), X_OK) == 0)
465 char dirsStr[DIR_NUM + 1];
466 dirsStr[DIR_NUM] = 0;
467 for (int i = 0; i < DIR_NUM; i++)
469 dirsStr[i] = enabledDirs[i] ? '1' : '0';
472 string scriptOnConnectParams;
473 strprintf(&scriptOnConnectParams,
474 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
475 scriptOnConnect.c_str(),
477 inet_ntostring(currIP).c_str(),
482 ScriptExec(scriptOnConnectParams);
486 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
492 if (store->WriteUserConnect(login, currIP))
494 WriteServLog("Cannot write connect for user %s.", login.c_str());
495 WriteServLog("%s", store->GetStrError().c_str());
499 lastIPForDisconnect = currIP;
501 //-----------------------------------------------------------------------------
502 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
505 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
508 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
510 if (!lastIPForDisconnect)
512 printfd(__FILE__, "lastIPForDisconnect\n");
518 string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
520 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
522 char dirsStr[DIR_NUM + 1];
523 dirsStr[DIR_NUM] = 0;
524 for (int i = 0; i < DIR_NUM; i++)
526 dirsStr[i] = enabledDirs[i] ? '1' : '0';
529 string scriptOnDisonnectParams;
530 strprintf(&scriptOnDisonnectParams,
531 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
532 scriptOnDisonnect.c_str(),
534 inet_ntostring(lastIPForDisconnect).c_str(),
539 ScriptExec(scriptOnDisonnectParams);
543 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
549 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
551 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
552 WriteServLog("%s", store->GetStrError().c_str());
556 lastIPForDisconnect = 0;
558 DIR_TRAFF zeroSesssion;
560 sessionUpload = zeroSesssion;
561 sessionDownload = zeroSesssion;
563 //-----------------------------------------------------------------------------
564 void USER_IMPL::PrintUser() const
567 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
568 cout << "============================================================" << endl;
569 cout << "id=" << id << endl;
570 cout << "login=" << login << endl;
571 cout << "password=" << password << endl;
572 cout << "passive=" << passive << endl;
573 cout << "disabled=" << disabled << endl;
574 cout << "disabledDetailStat=" << disabledDetailStat << endl;
575 cout << "alwaysOnline=" << alwaysOnline << endl;
576 cout << "tariffName=" << tariffName << endl;
577 cout << "address=" << address << endl;
578 cout << "phone=" << phone << endl;
579 cout << "email=" << email << endl;
580 cout << "note=" << note << endl;
581 cout << "realName=" <<realName << endl;
582 cout << "group=" << group << endl;
583 cout << "credit=" << credit << endl;
584 cout << "nextTariff=" << nextTariff << endl;
585 cout << "userdata0" << userdata0 << endl;
586 cout << "userdata1" << userdata1 << endl;
587 cout << "creditExpire=" << creditExpire << endl;
588 cout << "ips=" << ips << endl;
589 cout << "------------------------" << endl;
590 cout << "up=" << up << endl;
591 cout << "down=" << down << endl;
592 cout << "cash=" << cash << endl;
593 cout << "freeMb=" << freeMb << endl;
594 cout << "lastCashAdd=" << lastCashAdd << endl;
595 cout << "lastCashAddTime=" << lastCashAddTime << endl;
596 cout << "passiveTime=" << passiveTime << endl;
597 cout << "lastActivityTime=" << lastActivityTime << endl;
598 cout << "============================================================" << endl;
600 //-----------------------------------------------------------------------------
601 void USER_IMPL::Run()
603 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
605 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
607 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
610 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
612 WriteServLog("User: %s. Credit expired.", login.c_str());
618 if (passive.ConstData()
619 && (stgTime % 30 == 0)
620 && (passiveTime.ModificationTime() != stgTime))
622 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
623 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
626 if (!authorizedBy.empty())
630 lastActivityTime = *const_cast<time_t *>(&stgTime);
632 if (!connected && IsInetable())
636 if (connected && !IsInetable())
639 Disconnect(false, "disabled");
641 Disconnect(false, "passive");
643 Disconnect(false, "no cash");
646 if (stgTime - lastScanMessages > 10)
649 lastScanMessages = stgTime;
656 Disconnect(false, "not authorized");
661 //-----------------------------------------------------------------------------
662 void USER_IMPL::UpdatePingTime(time_t t)
664 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
665 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
671 //-----------------------------------------------------------------------------
672 bool USER_IMPL::IsInetable()
674 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
676 if (disabled || passive)
679 if (settings->GetFreeMbAllowInet())
685 if (settings->GetShowFeeInCash())
687 return (cash >= -credit);
690 return (cash - tariff->GetFee() >= -credit);
692 //-----------------------------------------------------------------------------
693 string USER_IMPL::GetEnabledDirs()
695 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
698 for(int i = 0; i < DIR_NUM; i++)
699 dirs += enabledDirs[i] ? "1" : "0";
702 //-----------------------------------------------------------------------------
703 #ifdef TRAFF_STAT_WITH_PORTS
704 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
706 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
709 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
717 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
718 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
722 int tt = tariff->GetTraffType();
723 if (tt == TRAFF_UP ||
724 tt == TRAFF_UP_DOWN ||
725 // Check NEW traff data
726 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
729 if (traff < threshold &&
730 traff + len >= threshold)
732 // cash = partBeforeThreshold * priceBeforeThreshold +
733 // partAfterThreshold * priceAfterThreshold
734 int64_t before = threshold - traff; // Chunk part before threshold
735 int64_t after = len - before; // Chunk part after threshold
736 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
737 down.ConstData()[dir],
740 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
741 down.ConstData()[dir],
747 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
748 down.ConstData()[dir],
753 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
755 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
756 cost = dc - freeMb.ConstData();
758 // Direct access to internal data structures via friend-specifier
759 property.Stat().freeMb -= dc;
760 property.Stat().cash -= cost;
766 sessionUpload[dir] += len;
770 if (!settings->GetWriteFreeMbTraffCost() &&
771 freeMb.ConstData() >= 0)
774 #ifdef TRAFF_STAT_WITH_PORTS
775 IP_DIR_PAIR idp(ip, dir, port);
777 IP_DIR_PAIR idp(ip, dir);
780 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
781 lb = traffStat.lower_bound(idp);
782 if (lb == traffStat.end() || lb->first != idp)
785 pair<IP_DIR_PAIR, STAT_NODE>(idp,
786 STAT_NODE(len, 0, cost)));
790 lb->second.cash += cost;
791 lb->second.up += len;
794 //-----------------------------------------------------------------------------
795 #ifdef TRAFF_STAT_WITH_PORTS
796 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
798 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
801 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
809 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
810 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
814 int tt = tariff->GetTraffType();
815 if (tt == TRAFF_DOWN ||
816 tt == TRAFF_UP_DOWN ||
817 // Check NEW traff data
818 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
821 if (traff < threshold &&
822 traff + len >= threshold)
824 // cash = partBeforeThreshold * priceBeforeThreshold +
825 // partAfterThreshold * priceAfterThreshold
826 int64_t before = threshold - traff; // Chunk part before threshold
827 int64_t after = len - before; // Chunk part after threshold
828 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
829 down.ConstData()[dir], // Traff before chunk
832 tariff->GetPriceWithTraffType(up.ConstData()[dir],
833 dt[dir], // Traff after chunk
839 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
840 down.ConstData()[dir],
845 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
847 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
848 cost = dc - freeMb.ConstData();
850 property.Stat().freeMb -= dc;
851 property.Stat().cash -= cost;
857 sessionDownload[dir] += len;
861 if (!settings->GetWriteFreeMbTraffCost() &&
862 freeMb.ConstData() >= 0)
865 #ifdef TRAFF_STAT_WITH_PORTS
866 IP_DIR_PAIR idp(ip, dir, port);
868 IP_DIR_PAIR idp(ip, dir);
871 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
872 lb = traffStat.lower_bound(idp);
873 if (lb == traffStat.end() || lb->first != idp)
876 pair<IP_DIR_PAIR, STAT_NODE>(idp,
877 STAT_NODE(0, len, cost)));
881 lb->second.cash += cost;
882 lb->second.down += len;
885 //-----------------------------------------------------------------------------
886 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
888 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
889 currIP.AddBeforeNotifier(n);
891 //-----------------------------------------------------------------------------
892 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
894 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
895 currIP.DelBeforeNotifier(n);
897 //-----------------------------------------------------------------------------
898 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
900 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
901 currIP.AddAfterNotifier(n);
903 //-----------------------------------------------------------------------------
904 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
906 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
907 currIP.DelAfterNotifier(n);
909 //-----------------------------------------------------------------------------
910 void USER_IMPL::OnAdd()
912 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
914 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
916 if (access(scriptOnAdd.c_str(), X_OK) == 0)
918 string scriptOnAddParams;
919 strprintf(&scriptOnAddParams,
924 ScriptExec(scriptOnAddParams);
928 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
931 //-----------------------------------------------------------------------------
932 void USER_IMPL::OnDelete()
934 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
936 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
938 if (access(scriptOnDel.c_str(), X_OK) == 0)
940 string scriptOnDelParams;
941 strprintf(&scriptOnDelParams,
946 ScriptExec(scriptOnDelParams);
950 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
955 //-----------------------------------------------------------------------------
956 int USER_IMPL::WriteDetailStat(bool hard)
958 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
960 if (!traffStatSaved.second.empty())
962 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
964 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
965 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
966 WriteServLog("%s", store->GetStrError().c_str());
969 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
975 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
979 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
981 if (ts.size() && !disabledDetailStat)
983 if (store->WriteDetailedStat(ts, lastWriteDeatiledStat, login))
985 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
986 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
987 WriteServLog("%s", store->GetStrError().c_str());
990 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
991 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
992 traffStatSaved.second.swap(ts);
993 traffStatSaved.first = lastWriteDeatiledStat;
998 lastWriteDeatiledStat = stgTime;
1001 //-----------------------------------------------------------------------------
1002 double USER_IMPL::GetPassiveTimePart() const
1004 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1006 static int daysInMonth[12] =
1007 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1011 localtime_r(&t, &tms);
1013 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1015 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1018 secMonth += 24 * 3600;
1021 int dt = secMonth - passiveTime;
1026 return double(dt) / (secMonth);
1028 //-----------------------------------------------------------------------------
1029 void USER_IMPL::SetPassiveTimeAsNewUser()
1031 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1035 localtime_r(&t, &tm);
1036 int daysCurrMon = DaysInCurrentMonth();
1037 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
1039 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1041 //-----------------------------------------------------------------------------
1042 void USER_IMPL::MidnightResetSessionStat()
1044 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1048 Disconnect(true, "fake");
1052 //-----------------------------------------------------------------------------
1053 void USER_IMPL::ProcessNewMonth()
1055 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1059 Disconnect(true, "fake");
1061 DIR_TRAFF zeroTarff;
1074 if (nextTariff.ConstData() != "")
1077 nt = tariffs->FindByName(nextTariff);
1080 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1081 login.c_str(), property.tariffName.Get().c_str());
1085 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1092 //-----------------------------------------------------------------------------
1093 void USER_IMPL::ProcessDayFeeSpread()
1095 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1097 if (passive.ConstData())
1100 double f = tariff->GetFee() / DaysInCurrentMonth();
1106 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1109 //-----------------------------------------------------------------------------
1110 void USER_IMPL::ProcessDayFee()
1112 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1114 double passiveTimePart = 1.0;
1115 if (!settings->GetFullFee())
1117 passiveTimePart = GetPassiveTimePart();
1121 if (passive.ConstData())
1123 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1127 double f = tariff->GetFee() * passiveTimePart;
1135 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1140 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1142 //-----------------------------------------------------------------------------
1143 void USER_IMPL::SetPrepaidTraff()
1145 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1147 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1149 //-----------------------------------------------------------------------------
1150 int USER_IMPL::AddMessage(STG_MSG * msg)
1152 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1154 if (SendMessage(*msg))
1156 if (store->AddMessage(msg, login))
1158 errorStr = store->GetStrError();
1159 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1160 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1163 messages.push_back(*msg);
1167 if (msg->header.repeat > 0)
1169 msg->header.repeat--;
1171 //TODO: gcc v. 4.x generate ICE on x86_64
1172 msg->header.lastSendTime = time(NULL);
1174 msg->header.lastSendTime = stgTime;
1176 if (store->AddMessage(msg, login))
1178 errorStr = store->GetStrError();
1179 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1180 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1183 messages.push_back(*msg);
1188 //-----------------------------------------------------------------------------
1189 int USER_IMPL::SendMessage(STG_MSG & msg) const
1191 // No lock `cause we are already locked from caller
1193 set<const AUTH*>::iterator it(authorizedBy.begin());
1194 while (it != authorizedBy.end())
1196 if (!(*it++)->SendMessage(msg, currIP))
1202 //TODO: gcc v. 4.x generate ICE on x86_64
1203 msg.header.lastSendTime = time(NULL);
1205 msg.header.lastSendTime = stgTime;
1207 msg.header.repeat--;
1211 //-----------------------------------------------------------------------------
1212 void USER_IMPL::ScanMessage()
1214 // No lock `cause we are already locked from caller
1215 // We need not check for the authorizedBy `cause it has already checked by caller
1217 std::list<STG_MSG>::iterator it(messages.begin());
1218 while (it != messages.end())
1220 if (settings->GetMessageTimeout() > 0 &&
1221 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1224 if (store->DelMessage(it->header.id, login))
1226 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1227 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1229 messages.erase(it++);
1232 if (it->GetNextSendTime() <= stgTime)
1234 if (SendMessage(*it))
1236 // We need to check all messages in queue for timeout
1240 if (it->header.repeat < 0)
1242 if (store->DelMessage(it->header.id, login))
1244 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1245 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1247 messages.erase(it++);
1251 if (store->EditMessage(*it, login))
1253 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1254 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1261 //-----------------------------------------------------------------------------
1262 //-----------------------------------------------------------------------------
1263 //-----------------------------------------------------------------------------
1264 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1266 if (newPassive && !oldPassive)
1267 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1273 //-----------------------------------------------------------------------------
1274 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1276 user->tariff = user->tariffs->FindByName(newTariff);
1278 //-----------------------------------------------------------------------------
1279 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1281 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1282 user->lastCashAdd = newCash - oldCash;
1284 //-----------------------------------------------------------------------------
1285 void CHG_IP_NOTIFIER::Notify(const uint32_t & from, const uint32_t & to)
1287 printfd(__FILE__, "Change IP from %s to %s\n", inet_ntostring(from).c_str(), inet_ntostring(to).c_str());
1289 if (user->connected)
1290 user->Disconnect(false, "Change IP");
1292 if (user->IsInetable())
1293 user->Connect(false);
1295 //-----------------------------------------------------------------------------