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 pthread_mutexattr_t attr;
127 pthread_mutexattr_init(&attr);
128 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
129 pthread_mutex_init(&mutex, &attr);
131 //-----------------------------------------------------------------------------
132 USER::USER(const USER & u)
133 : property(u.settings),
134 WriteServLog(GetStgLogger()),
137 __connected(u.__connected),
138 connected(__connected),
139 __currIP(u.__currIP),
141 lastIPForDisconnect(0),
142 pingTime(u.pingTime),
143 sysAdmin(u.sysAdmin),
150 lastCashAdd(property.lastCashAdd),
151 passiveTime(property.passiveTime),
152 lastCashAddTime(property.lastCashAddTime),
153 freeMb(property.freeMb),
154 lastActivityTime(property.lastActivityTime),
155 password(property.password),
156 passive(property.passive),
157 disabled(property.disabled),
158 disabledDetailStat(property.disabledDetailStat),
159 alwaysOnline(property.alwaysOnline),
160 tariffName(property.tariffName),
161 nextTariff(property.nextTariff),
162 address(property.address),
164 group(property.group),
165 email(property.email),
166 phone(property.phone),
167 realName(property.realName),
168 credit(property.credit),
169 creditExpire(property.creditExpire),
171 userdata0(property.userdata0),
172 userdata1(property.userdata1),
173 userdata2(property.userdata2),
174 userdata3(property.userdata3),
175 userdata4(property.userdata4),
176 userdata5(property.userdata5),
177 userdata6(property.userdata6),
178 userdata7(property.userdata7),
179 userdata8(property.userdata8),
180 userdata9(property.userdata9),
181 passiveNotifier(this),
182 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 //-----------------------------------------------------------------------------
217 property.passive.DelBeforeNotifier(&passiveNotifier);
218 property.tariffName.DelBeforeNotifier(&tariffNotifier);
219 pthread_mutex_destroy(&mutex);
221 //-----------------------------------------------------------------------------
222 void USER::SetLogin(string const & l)
224 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
225 assert(login.empty() && "Login is already set");
227 id = userIDGenerator.GetNextID();
229 //-----------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------
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::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::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::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::Authorize(uint32_t ip, const string &, uint32_t dirs, const BASE_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);
386 map<uint32_t, user_iter>::const_iterator ci = ipIndex->find(ip);
387 if (ci != ipIndex->end())
389 // Address is already present in IP-index
390 // If it's not our IP - throw an error
391 if (&(*ci->second) != this)
393 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
400 if (ipIndex->find(ip) != ipIndex->end())
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::Unauthorize(const BASE_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::IsAuthorizedBy(const BASE_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::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->GetScriptDir() + "/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::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->GetScriptDir() + "/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::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 //-----------------------------------------------------------------------------
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::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::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::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::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
706 void USER::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::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
798 void USER::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::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
888 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
889 currIP.AddBeforeNotifier(n);
891 //-----------------------------------------------------------------------------
892 void USER::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
894 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
895 currIP.DelBeforeNotifier(n);
897 //-----------------------------------------------------------------------------
898 void USER::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
900 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
901 currIP.AddAfterNotifier(n);
903 //-----------------------------------------------------------------------------
904 void USER::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
906 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
907 currIP.DelAfterNotifier(n);
909 //-----------------------------------------------------------------------------
912 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
914 string scriptOnAdd = settings->GetScriptDir() + "/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::OnDelete()
934 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
936 string scriptOnDel = settings->GetScriptDir() + "/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::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::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::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::MidnightResetSessionStat()
1044 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1048 Disconnect(true, "fake");
1052 //-----------------------------------------------------------------------------
1053 void USER::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::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::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::SetPrepaidTraff()
1145 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1147 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1149 //-----------------------------------------------------------------------------
1150 int USER::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::SendMessage(STG_MSG & msg) const
1191 // No lock `cause we are already locked from caller
1193 set<const BASE_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::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 //-----------------------------------------------------------------------------