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
43 #include "script_executer.h"
48 USER::USER(const SETTINGS * s,
49 const BASE_STORE * st,
52 const map<uint32_t, user_iter> * ipIdx)
54 WriteServLog(GetStgLogger()),
58 connected(__connected),
62 lastIPForDisconnect(0),
67 tariff(tariffs->GetNoTariff()),
71 lastCashAdd(property.lastCashAdd),
72 passiveTime(property.passiveTime),
73 lastCashAddTime(property.lastCashAddTime),
74 freeMb(property.freeMb),
75 lastActivityTime(property.lastActivityTime),
76 password(property.password),
77 passive(property.passive),
78 disabled(property.disabled),
79 disabledDetailStat(property.disabledDetailStat),
80 alwaysOnline(property.alwaysOnline),
81 tariffName(property.tariffName),
82 nextTariff(property.nextTariff),
83 address(property.address),
85 group(property.group),
86 email(property.email),
87 phone(property.phone),
88 realName(property.realName),
89 credit(property.credit),
90 creditExpire(property.creditExpire),
92 userdata0(property.userdata0),
93 userdata1(property.userdata1),
94 userdata2(property.userdata2),
95 userdata3(property.userdata3),
96 userdata4(property.userdata4),
97 userdata5(property.userdata5),
98 userdata6(property.userdata6),
99 userdata7(property.userdata7),
100 userdata8(property.userdata8),
101 userdata9(property.userdata9),
102 passiveNotifier(this),
103 tariffNotifier(this),
110 password = "*_EMPTY_PASSWORD_*";
111 tariffName = NO_TARIFF_NAME;
113 tariff = tariffs->GetNoTariff();
116 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
117 lastWriteDeatiledStat = stgTime;
119 property.tariffName.AddBeforeNotifier(&tariffNotifier);
120 property.passive.AddBeforeNotifier(&passiveNotifier);
121 property.cash.AddBeforeNotifier(&cashNotifier);
122 currIP.AddAfterNotifier(&ipNotifier);
124 lastScanMessages = 0;
126 writeFreeMbTraffCost = settings->GetWriteFreeMbTraffCost();
128 pthread_mutexattr_t attr;
129 pthread_mutexattr_init(&attr);
130 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
131 pthread_mutex_init(&mutex, &attr);
133 //-----------------------------------------------------------------------------
134 USER::USER(const USER & u)
135 : property(u.settings),
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),
197 lastWriteStat = u.lastWriteStat;
198 lastWriteDeatiledStat = u.lastWriteDeatiledStat;
200 settings = u.settings;
202 property.tariffName.AddBeforeNotifier(&tariffNotifier);
203 property.passive.AddBeforeNotifier(&passiveNotifier);
204 property.cash.AddBeforeNotifier(&cashNotifier);
205 currIP.AddAfterNotifier(&ipNotifier);
207 lastScanMessages = 0;
209 writeFreeMbTraffCost = settings->GetWriteFreeMbTraffCost();
211 property.SetProperties(u.property);
213 pthread_mutexattr_t attr;
214 pthread_mutexattr_init(&attr);
215 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
216 pthread_mutex_init(&mutex, &attr);
218 //-----------------------------------------------------------------------------
221 property.passive.DelBeforeNotifier(&passiveNotifier);
222 property.tariffName.DelBeforeNotifier(&tariffNotifier);
223 pthread_mutex_destroy(&mutex);
225 //-----------------------------------------------------------------------------
226 void USER::SetLogin(string const & l)
228 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
229 assert(login.empty() && "Login is already set");
231 id = userIDGenerator.GetNextID();
233 //-----------------------------------------------------------------------------
236 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
239 if (store->RestoreUserConf(&conf, login))
241 WriteServLog("Cannot read conf for user %s.", login.c_str());
242 WriteServLog("%s", store->GetStrError().c_str());
243 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
244 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
248 property.SetConf(conf);
250 tariff = tariffs->FindByName(tariffName);
253 WriteServLog("Cannot read user %s. Tariff %s not exist.",
254 login.c_str(), property.tariffName.Get().c_str());
258 std::vector<STG_MSG_HDR> hdrsList;
260 if (store->GetMessageHdrs(&hdrsList, login))
262 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
266 std::vector<STG_MSG_HDR>::const_iterator it;
267 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
270 if (store->GetMessage(it->id, &msg, login) == 0)
272 messages.push_back(msg);
278 //-----------------------------------------------------------------------------
281 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
284 if (store->RestoreUserStat(&stat, login))
286 WriteServLog("Cannot read stat for user %s.", login.c_str());
287 WriteServLog("%s", store->GetStrError().c_str());
288 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
289 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
293 property.SetStat(stat);
297 //-----------------------------------------------------------------------------
298 int USER::WriteConf()
300 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
301 USER_CONF conf(property.GetConf());
303 printfd(__FILE__, "USER::WriteConf()\n");
305 if (store->SaveUserConf(conf, login))
307 WriteServLog("Cannot write conf for user %s.", login.c_str());
308 WriteServLog("%s", store->GetStrError().c_str());
309 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
310 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
316 //-----------------------------------------------------------------------------
317 int USER::WriteStat()
319 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
320 USER_STAT stat(property.GetStat());
322 printfd(__FILE__, "USER::WriteStat()\n");
324 if (store->SaveUserStat(stat, login))
326 WriteServLog("Cannot write stat for user %s.", login.c_str());
327 WriteServLog("%s", store->GetStrError().c_str());
328 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
329 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
333 lastWriteStat = stgTime;
337 //-----------------------------------------------------------------------------
338 int USER::WriteMonthStat()
340 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
341 time_t tt = stgTime - 3600;
342 struct tm * t1 = localtime(&tt);
344 USER_STAT stat(property.GetStat());
345 if (store->SaveMonthStat(stat, t1->tm_mon, t1->tm_year, login))
347 WriteServLog("Cannot write month stat for user %s.", login.c_str());
348 WriteServLog("%s", store->GetStrError().c_str());
349 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
350 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
356 //-----------------------------------------------------------------------------
357 int USER::Authorize(uint32_t ip, const string &, uint32_t dirs, const BASE_AUTH * auth)
359 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
361 * Authorize user. It only means that user will be authorized. Nothing more.
362 * User can be connected or disconnected while authorized.
363 * Example: user is authorized but disconnected due to 0 money or blocking
367 * Prevent double authorization by identical authorizers
369 if (authorizedBy.find(auth) != authorizedBy.end())
375 for (int i = 0; i < DIR_NUM; i++)
377 enabledDirs[i] = dirs & (1 << i);
380 if (authorizedBy.size())
384 // We are already authorized, but with different IP address
385 errorStr = "User " + login + " alredy authorized with IP address " + inet_ntostring(ip);
389 map<uint32_t, user_iter>::const_iterator ci = ipIndex->find(ip);
390 if (ci != ipIndex->end())
392 // Address is already present in IP-index
393 // If it's not our IP - throw an error
394 if (&(*ci->second) != this)
396 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
403 if (ipIndex->find(ip) != ipIndex->end())
405 // Address is already present in IP-index
406 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
410 if (ips.ConstData().IsIPInIPS(ip))
413 lastIPForDisconnect = currIP;
417 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
418 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
423 authorizedBy.insert(auth);
429 //-----------------------------------------------------------------------------
430 void USER::Unauthorize(const BASE_AUTH * auth)
432 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
434 * Authorizer tries to unauthorize user, that was not authorized by it
436 if (!authorizedBy.erase(auth))
439 if (authorizedBy.empty())
441 lastIPForDisconnect = currIP;
442 currIP = 0; // DelUser in traffcounter
446 //-----------------------------------------------------------------------------
447 bool USER::IsAuthorizedBy(const BASE_AUTH * auth) const
449 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
450 // Is this user authorized by specified authorizer?
451 return authorizedBy.find(auth) != authorizedBy.end();
453 //-----------------------------------------------------------------------------
454 void USER::Connect(bool fakeConnect)
457 * Connect user to Internet. This function is differ from Authorize() !!!
460 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
464 string scriptOnConnect = settings->GetScriptDir() + "/OnConnect";
466 if (access(scriptOnConnect.c_str(), X_OK) == 0)
468 char dirsStr[DIR_NUM + 1];
469 dirsStr[DIR_NUM] = 0;
470 for (int i = 0; i < DIR_NUM; i++)
472 dirsStr[i] = enabledDirs[i] ? '1' : '0';
475 string scriptOnConnectParams;
476 strprintf(&scriptOnConnectParams,
477 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
478 scriptOnConnect.c_str(),
480 inet_ntostring(currIP).c_str(),
485 ScriptExec(scriptOnConnectParams);
489 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
495 if (store->WriteUserConnect(login, currIP))
497 WriteServLog("Cannot write connect for user %s.", login.c_str());
498 WriteServLog("%s", store->GetStrError().c_str());
502 lastIPForDisconnect = currIP;
504 //-----------------------------------------------------------------------------
505 void USER::Disconnect(bool fakeDisconnect, const std::string & reason)
508 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
511 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
513 if (!lastIPForDisconnect)
515 printfd(__FILE__, "lastIPForDisconnect\n");
521 string scriptOnDisonnect = settings->GetScriptDir() + "/OnDisconnect";
523 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
525 char dirsStr[DIR_NUM + 1];
526 dirsStr[DIR_NUM] = 0;
527 for (int i = 0; i < DIR_NUM; i++)
529 dirsStr[i] = enabledDirs[i] ? '1' : '0';
532 string scriptOnDisonnectParams;
533 strprintf(&scriptOnDisonnectParams,
534 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
535 scriptOnDisonnect.c_str(),
537 inet_ntostring(lastIPForDisconnect).c_str(),
542 ScriptExec(scriptOnDisonnectParams);
546 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
552 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
554 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
555 WriteServLog("%s", store->GetStrError().c_str());
559 lastIPForDisconnect = 0;
561 DIR_TRAFF zeroSesssion;
563 sessionUpload = zeroSesssion;
564 sessionDownload = zeroSesssion;
566 //-----------------------------------------------------------------------------
567 void USER::PrintUser() const
570 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
571 cout << "============================================================" << endl;
572 cout << "id=" << id << endl;
573 cout << "login=" << login << endl;
574 cout << "password=" << password << endl;
575 cout << "passive=" << passive << endl;
576 cout << "disabled=" << disabled << endl;
577 cout << "disabledDetailStat=" << disabledDetailStat << endl;
578 cout << "alwaysOnline=" << alwaysOnline << endl;
579 cout << "tariffName=" << tariffName << endl;
580 cout << "address=" << address << endl;
581 cout << "phone=" << phone << endl;
582 cout << "email=" << email << endl;
583 cout << "note=" << note << endl;
584 cout << "realName=" <<realName << endl;
585 cout << "group=" << group << endl;
586 cout << "credit=" << credit << endl;
587 cout << "nextTariff=" << nextTariff << endl;
588 cout << "userdata0" << userdata0 << endl;
589 cout << "userdata1" << userdata1 << endl;
590 cout << "creditExpire=" << creditExpire << endl;
591 cout << "ips=" << ips << endl;
592 cout << "------------------------" << endl;
593 cout << "up=" << up << endl;
594 cout << "down=" << down << endl;
595 cout << "cash=" << cash << endl;
596 cout << "freeMb=" << freeMb << endl;
597 cout << "lastCashAdd=" << lastCashAdd << endl;
598 cout << "lastCashAddTime=" << lastCashAddTime << endl;
599 cout << "passiveTime=" << passiveTime << endl;
600 cout << "lastActivityTime=" << lastActivityTime << endl;
601 cout << "============================================================" << endl;
603 //-----------------------------------------------------------------------------
606 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
608 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
610 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
613 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
615 WriteServLog("User: %s. Credit expired.", login.c_str());
621 if (passive.ConstData()
622 && (stgTime % 30 == 0)
623 && (passiveTime.ModificationTime() != stgTime))
625 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
626 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
629 if (!authorizedBy.empty())
633 lastActivityTime = *const_cast<time_t *>(&stgTime);
635 if (!connected && IsInetable())
639 if (connected && !IsInetable())
642 Disconnect(false, "disabled");
644 Disconnect(false, "passive");
646 Disconnect(false, "no cash");
649 if (stgTime - lastScanMessages > 10)
652 lastScanMessages = stgTime;
659 Disconnect(false, "not authorized");
664 //-----------------------------------------------------------------------------
665 void USER::UpdatePingTime(time_t t)
667 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
668 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
674 //-----------------------------------------------------------------------------
675 bool USER::IsInetable()
677 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
679 if (disabled || passive)
682 if (settings->GetFreeMbAllowInet())
688 if (settings->GetShowFeeInCash())
690 return (cash >= -credit);
693 return (cash - tariff->GetFee() >= -credit);
695 //-----------------------------------------------------------------------------
696 string USER::GetEnabledDirs()
698 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
701 for(int i = 0; i < DIR_NUM; i++)
702 dirs += enabledDirs[i] ? "1" : "0";
705 //-----------------------------------------------------------------------------
706 #ifdef TRAFF_STAT_WITH_PORTS
707 void USER::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
709 void USER::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
712 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
720 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
721 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
725 int tt = tariff->GetTraffType();
726 if (tt == TRAFF_UP ||
727 tt == TRAFF_UP_DOWN ||
728 // Check NEW traff data
729 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
732 if (traff < threshold &&
733 traff + len >= threshold)
735 // cash = partBeforeThreshold * priceBeforeThreshold +
736 // partAfterThreshold * priceAfterThreshold
737 int64_t before = threshold - traff; // Chunk part before threshold
738 int64_t after = len - before; // Chunk part after threshold
739 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
740 down.ConstData()[dir],
743 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
744 down.ConstData()[dir],
750 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
751 down.ConstData()[dir],
756 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
758 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
759 cost = dc - freeMb.ConstData();
761 // Direct access to internal data structures via friend-specifier
762 property.stat.freeMb -= dc;
763 property.stat.cash -= cost;
769 sessionUpload[dir] += len;
773 if (!writeFreeMbTraffCost && freeMb.ConstData() >= 0)
776 #ifdef TRAFF_STAT_WITH_PORTS
777 IP_DIR_PAIR idp(ip, dir, port);
779 IP_DIR_PAIR idp(ip, dir);
782 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
783 lb = traffStat.lower_bound(idp);
784 if (lb == traffStat.end() || lb->first != idp)
787 pair<IP_DIR_PAIR, STAT_NODE>(idp,
788 STAT_NODE(len, 0, cost)));
792 lb->second.cash += cost;
793 lb->second.up += len;
796 //-----------------------------------------------------------------------------
797 #ifdef TRAFF_STAT_WITH_PORTS
798 void USER::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
800 void USER::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
803 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
811 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
812 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
816 int tt = tariff->GetTraffType();
817 if (tt == TRAFF_DOWN ||
818 tt == TRAFF_UP_DOWN ||
819 // Check NEW traff data
820 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
823 if (traff < threshold &&
824 traff + len >= threshold)
826 // cash = partBeforeThreshold * priceBeforeThreshold +
827 // partAfterThreshold * priceAfterThreshold
828 int64_t before = threshold - traff; // Chunk part before threshold
829 int64_t after = len - before; // Chunk part after threshold
830 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
831 down.ConstData()[dir], // Traff before chunk
834 tariff->GetPriceWithTraffType(up.ConstData()[dir],
835 dt[dir], // Traff after chunk
841 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
842 down.ConstData()[dir],
847 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
849 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
850 cost = dc - freeMb.ConstData();
852 property.stat.freeMb -= dc;
853 property.stat.cash -= cost;
859 sessionDownload[dir] += len;
863 if (!writeFreeMbTraffCost && freeMb.ConstData() >= 0)
866 #ifdef TRAFF_STAT_WITH_PORTS
867 IP_DIR_PAIR idp(ip, dir, port);
869 IP_DIR_PAIR idp(ip, dir);
872 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
873 lb = traffStat.lower_bound(idp);
874 if (lb == traffStat.end() || lb->first != idp)
877 pair<IP_DIR_PAIR, STAT_NODE>(idp,
878 STAT_NODE(0, len, cost)));
882 lb->second.cash += cost;
883 lb->second.down += len;
886 //-----------------------------------------------------------------------------
887 void USER::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
889 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
890 currIP.AddBeforeNotifier(n);
892 //-----------------------------------------------------------------------------
893 void USER::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
895 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
896 currIP.DelBeforeNotifier(n);
898 //-----------------------------------------------------------------------------
899 void USER::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
901 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
902 currIP.AddAfterNotifier(n);
904 //-----------------------------------------------------------------------------
905 void USER::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
907 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
908 currIP.DelAfterNotifier(n);
910 //-----------------------------------------------------------------------------
913 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
915 string scriptOnAdd = settings->GetScriptDir() + "/OnUserAdd";
917 if (access(scriptOnAdd.c_str(), X_OK) == 0)
919 string scriptOnAddParams;
920 strprintf(&scriptOnAddParams,
925 ScriptExec(scriptOnAddParams);
929 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
932 //-----------------------------------------------------------------------------
933 void USER::OnDelete()
935 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
937 string scriptOnDel = settings->GetScriptDir() + "/OnUserDel";
939 if (access(scriptOnDel.c_str(), X_OK) == 0)
941 string scriptOnDelParams;
942 strprintf(&scriptOnDelParams,
947 ScriptExec(scriptOnDelParams);
951 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
956 //-----------------------------------------------------------------------------
957 int USER::WriteDetailStat(bool hard)
959 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
961 if (!traffStatSaved.second.empty())
963 if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
965 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
966 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
967 WriteServLog("%s", store->GetStrError().c_str());
970 traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
976 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
980 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
982 if (ts.size() && !disabledDetailStat)
984 if (store->WriteDetailedStat(ts, lastWriteDeatiledStat, login))
986 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
987 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
988 WriteServLog("%s", store->GetStrError().c_str());
991 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
992 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
993 traffStatSaved.second.swap(ts);
994 traffStatSaved.first = lastWriteDeatiledStat;
999 lastWriteDeatiledStat = stgTime;
1002 //-----------------------------------------------------------------------------
1003 double USER::GetPassiveTimePart() const
1005 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1007 static int daysInMonth[12] =
1008 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1012 tms = localtime(&t);
1014 time_t secMonth = daysInMonth[(tms->tm_mon + 11) % 12] * 24 * 3600; // Previous month
1016 if (tms->tm_year % 4 == 0 && tms->tm_mon == 1)
1019 secMonth += 24 * 3600;
1022 int dt = secMonth - passiveTime;
1027 return double(dt) / (secMonth);
1029 //-----------------------------------------------------------------------------
1030 void USER::SetPassiveTimeAsNewUser()
1032 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1038 int daysCurrMon = DaysInCurrentMonth();
1039 double pt = (tm->tm_mday - 1) / (double)daysCurrMon;
1041 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1043 //-----------------------------------------------------------------------------
1044 void USER::MidnightResetSessionStat()
1046 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1050 Disconnect(true, "fake");
1054 //-----------------------------------------------------------------------------
1055 void USER::ProcessNewMonth()
1057 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1061 Disconnect(true, "fake");
1063 DIR_TRAFF zeroTarff;
1076 if (nextTariff.ConstData() != "")
1079 nt = tariffs->FindByName(nextTariff);
1082 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1083 login.c_str(), property.tariffName.Get().c_str());
1087 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1094 //-----------------------------------------------------------------------------
1095 void USER::ProcessDayFeeSpread()
1097 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1099 if (passive.ConstData())
1102 double f = tariff->GetFee() / DaysInCurrentMonth();
1108 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1111 //-----------------------------------------------------------------------------
1112 void USER::ProcessDayFee()
1114 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1116 double passiveTimePart = 1.0;
1117 if (!settings->GetFullFee())
1119 passiveTimePart = GetPassiveTimePart();
1123 if (passive.ConstData())
1125 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1129 double f = tariff->GetFee() * passiveTimePart;
1137 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1142 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1144 //-----------------------------------------------------------------------------
1145 void USER::SetPrepaidTraff()
1147 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1149 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1151 //-----------------------------------------------------------------------------
1152 int USER::AddMessage(STG_MSG * msg)
1154 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1156 if (SendMessage(*msg))
1158 if (store->AddMessage(msg, login))
1160 errorStr = store->GetStrError();
1161 WriteServLog("Error adding message: '%s'", errorStr.c_str());
1162 printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1165 messages.push_back(*msg);
1169 if (msg->header.repeat > 0)
1171 msg->header.repeat--;
1173 //TODO: gcc v. 4.x generate ICE on x86_64
1174 msg->header.lastSendTime = time(NULL);
1176 msg->header.lastSendTime = stgTime;
1178 if (store->AddMessage(msg, login))
1180 errorStr = store->GetStrError();
1181 WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1182 printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1185 messages.push_back(*msg);
1190 //-----------------------------------------------------------------------------
1191 int USER::SendMessage(STG_MSG & msg) const
1193 // No lock `cause we are already locked from caller
1195 set<const BASE_AUTH*>::iterator it(authorizedBy.begin());
1196 while (it != authorizedBy.end())
1198 if (!(*it++)->SendMessage(msg, currIP))
1204 //TODO: gcc v. 4.x generate ICE on x86_64
1205 msg.header.lastSendTime = time(NULL);
1207 msg.header.lastSendTime = stgTime;
1209 msg.header.repeat--;
1213 //-----------------------------------------------------------------------------
1214 void USER::ScanMessage()
1216 // No lock `cause we are already locked from caller
1217 // We need not check for the authorizedBy `cause it has already checked by caller
1219 std::list<STG_MSG>::iterator it(messages.begin());
1220 while (it != messages.end())
1222 if (settings->GetMessageTimeout() > 0 &&
1223 difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1226 if (store->DelMessage(it->header.id, login))
1228 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1229 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1231 messages.erase(it++);
1234 if (it->GetNextSendTime() <= stgTime)
1236 if (SendMessage(*it))
1238 // We need to check all messages in queue for timeout
1242 if (it->header.repeat < 0)
1244 if (store->DelMessage(it->header.id, login))
1246 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1247 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1249 messages.erase(it++);
1253 if (store->EditMessage(*it, login))
1255 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1256 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1263 //-----------------------------------------------------------------------------
1264 //-----------------------------------------------------------------------------
1265 //-----------------------------------------------------------------------------
1266 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1268 if (newPassive && !oldPassive)
1269 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1275 //-----------------------------------------------------------------------------
1276 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1278 user->tariff = user->tariffs->FindByName(newTariff);
1280 //-----------------------------------------------------------------------------
1281 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1283 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1284 user->lastCashAdd = newCash - oldCash;
1286 //-----------------------------------------------------------------------------
1287 void CHG_IP_NOTIFIER::Notify(const uint32_t & from, const uint32_t & to)
1289 printfd(__FILE__, "Change IP from %s to %s\n", inet_ntostring(from).c_str(), inet_ntostring(to).c_str());
1291 if (user->connected)
1292 user->Disconnect(false, "Change IP");
1294 if (user->IsInetable())
1295 user->Connect(false);
1297 //-----------------------------------------------------------------------------