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 /*traffStatInUse = 0;
114 traffStat = &traffStatInternal[0];*/
115 tariff = tariffs->GetNoTariff();
118 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
119 lastWriteDeatiledStat = stgTime;
120 lastSwapDeatiledStat = stgTime;
122 property.tariffName.AddBeforeNotifier(&tariffNotifier);
123 property.passive.AddBeforeNotifier(&passiveNotifier);
124 property.cash.AddBeforeNotifier(&cashNotifier);
125 currIP.AddAfterNotifier(&ipNotifier);
127 lastScanMessages = 0;
129 writeFreeMbTraffCost = settings->GetWriteFreeMbTraffCost();
131 pthread_mutexattr_t attr;
132 pthread_mutexattr_init(&attr);
133 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
134 pthread_mutex_init(&mutex, &attr);
136 //-----------------------------------------------------------------------------
137 USER::USER(const USER & u)
138 : property(u.settings),
139 WriteServLog(GetStgLogger()),
142 __connected(u.__connected),
143 connected(__connected),
144 __currIP(u.__currIP),
146 lastIPForDisconnect(0),
147 pingTime(u.pingTime),
148 sysAdmin(u.sysAdmin),
155 lastCashAdd(property.lastCashAdd),
156 passiveTime(property.passiveTime),
157 lastCashAddTime(property.lastCashAddTime),
158 freeMb(property.freeMb),
159 lastActivityTime(property.lastActivityTime),
160 password(property.password),
161 passive(property.passive),
162 disabled(property.disabled),
163 disabledDetailStat(property.disabledDetailStat),
164 alwaysOnline(property.alwaysOnline),
165 tariffName(property.tariffName),
166 nextTariff(property.nextTariff),
167 address(property.address),
169 group(property.group),
170 email(property.email),
171 phone(property.phone),
172 realName(property.realName),
173 credit(property.credit),
174 creditExpire(property.creditExpire),
176 userdata0(property.userdata0),
177 userdata1(property.userdata1),
178 userdata2(property.userdata2),
179 userdata3(property.userdata3),
180 userdata4(property.userdata4),
181 userdata5(property.userdata5),
182 userdata6(property.userdata6),
183 userdata7(property.userdata7),
184 userdata8(property.userdata8),
185 userdata9(property.userdata9),
186 passiveNotifier(this),
187 tariffNotifier(this),
200 lastWriteStat = u.lastWriteStat;
201 lastWriteDeatiledStat = u.lastWriteDeatiledStat;
202 lastSwapDeatiledStat = u.lastSwapDeatiledStat;
204 settings = u.settings;
206 property.tariffName.AddBeforeNotifier(&tariffNotifier);
207 property.passive.AddBeforeNotifier(&passiveNotifier);
208 property.cash.AddBeforeNotifier(&cashNotifier);
209 currIP.AddAfterNotifier(&ipNotifier);
211 lastScanMessages = 0;
213 writeFreeMbTraffCost = settings->GetWriteFreeMbTraffCost();
216 password = u.password.ConstData();
217 passive = u.passive.ConstData();
218 disabled = u.disabled.ConstData();
219 disabledDetailStat = u.disabledDetailStat.ConstData();
220 alwaysOnline = u.alwaysOnline.ConstData();
221 tariffName = u.tariffName.ConstData();
222 nextTariff = u.nextTariff.ConstData();
223 address = u.address.ConstData();
224 phone = u.phone.ConstData();
225 email = u.email.ConstData();
226 note = u.note.ConstData();
227 realName = u.realName.ConstData();
228 group = u.group.ConstData();
229 credit = u.credit.ConstData();
230 nextTariff = u.nextTariff.ConstData();
231 userdata0 = u.userdata0.ConstData();
232 userdata1 = u.userdata1.ConstData();
233 userdata2 = u.userdata2.ConstData();
234 userdata3 = u.userdata3.ConstData();
235 userdata4 = u.userdata4.ConstData();
236 userdata5 = u.userdata5.ConstData();
237 userdata6 = u.userdata6.ConstData();
238 userdata7 = u.userdata7.ConstData();
239 userdata8 = u.userdata8.ConstData();
240 userdata9 = u.userdata9.ConstData();
242 creditExpire = u.creditExpire.ConstData();
243 ips = u.ips.ConstData();
246 up = u.up.ConstData();
247 down = u.down.ConstData();
248 cash = u.cash.ConstData();
249 freeMb = u.freeMb.ConstData();
250 lastCashAdd = u.lastCashAdd.ConstData();
251 lastCashAddTime = u.lastCashAddTime.ConstData();
252 passiveTime = u.passiveTime.ConstData();
253 lastActivityTime = u.lastActivityTime.ConstData();
255 pthread_mutexattr_t attr;
256 pthread_mutexattr_init(&attr);
257 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
258 pthread_mutex_init(&mutex, &attr);
260 //-----------------------------------------------------------------------------
263 property.passive.DelBeforeNotifier(&passiveNotifier);
264 property.tariffName.DelBeforeNotifier(&tariffNotifier);
265 pthread_mutex_destroy(&mutex);
267 //-----------------------------------------------------------------------------
268 void USER::SetLogin(string const & l)
270 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
271 assert(login.empty() && "Login is already set");
273 id = userIDGenerator.GetNextID();
275 //-----------------------------------------------------------------------------
278 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
281 if (store->RestoreUserConf(&uc, login))
283 WriteServLog("Cannot read conf for user %s.", login.c_str());
284 WriteServLog("%s", store->GetStrError().c_str());
285 printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
286 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
290 password = uc.password;
291 passive = uc.passive;
292 disabled = uc.disabled;
293 disabledDetailStat = uc.disabledDetailStat;
294 alwaysOnline = uc.alwaysOnline;
295 tariffName = uc.tariffName;
296 address = uc.address;
300 realName = uc.realName;
303 nextTariff = uc.nextTariff;
304 userdata0 = uc.userdata[0];
305 userdata1 = uc.userdata[1];
306 userdata2 = uc.userdata[2];
307 userdata3 = uc.userdata[3];
308 userdata4 = uc.userdata[4];
309 userdata5 = uc.userdata[5];
310 userdata6 = uc.userdata[6];
311 userdata7 = uc.userdata[7];
312 userdata8 = uc.userdata[8];
313 userdata9 = uc.userdata[9];
315 creditExpire = uc.creditExpire;
318 tariff = tariffs->FindByName(tariffName);
321 WriteServLog("Cannot read user %s. Tariff %s not exist.",
322 login.c_str(), property.tariffName.Get().c_str());
328 //-----------------------------------------------------------------------------
331 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
334 if (store->RestoreUserStat(&us, login))
336 WriteServLog("Cannot read stat for user %s.", login.c_str());
337 WriteServLog("%s", store->GetStrError().c_str());
338 printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
339 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
347 lastCashAdd = us.lastCashAdd;
348 lastCashAddTime = us.lastCashAddTime;
349 passiveTime = us.passiveTime;
350 lastActivityTime = us.lastActivityTime;
354 //-----------------------------------------------------------------------------
355 int USER::WriteConf()
357 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
360 uc.password = password;
361 uc.passive = passive;
362 uc.disabled = disabled;
363 uc.disabledDetailStat = disabledDetailStat;
364 uc.alwaysOnline = alwaysOnline;
365 uc.tariffName = tariffName;
366 uc.address = address;
370 uc.realName = realName;
373 uc.nextTariff = nextTariff;
374 uc.userdata[0] = userdata0;
375 uc.userdata[1] = userdata1;
376 uc.userdata[2] = userdata2;
377 uc.userdata[3] = userdata3;
378 uc.userdata[4] = userdata4;
379 uc.userdata[5] = userdata5;
380 uc.userdata[6] = userdata6;
381 uc.userdata[7] = userdata7;
382 uc.userdata[8] = userdata8;
383 uc.userdata[9] = userdata9;
385 uc.creditExpire = creditExpire;
388 printfd(__FILE__, "USER::WriteConf()\n");
390 if (store->SaveUserConf(uc, login))
392 WriteServLog("Cannot write conf for user %s.", login.c_str());
393 WriteServLog("%s", store->GetStrError().c_str());
394 printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
395 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
401 //-----------------------------------------------------------------------------
402 int USER::WriteStat()
404 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
411 us.lastCashAdd = lastCashAdd;
412 us.lastCashAddTime = lastCashAddTime;
413 us.passiveTime = passiveTime;
414 us.lastActivityTime = lastActivityTime;
416 printfd(__FILE__, "USER::WriteStat()\n");
418 if (store->SaveUserStat(us, login))
420 WriteServLog("Cannot write stat for user %s.", login.c_str());
421 WriteServLog("%s", store->GetStrError().c_str());
422 printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
423 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
427 lastWriteStat = stgTime;
431 //-----------------------------------------------------------------------------
432 int USER::WriteMonthStat()
434 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
437 time_t tt = stgTime - 3600;
444 us.lastCashAdd = lastCashAdd;
445 us.lastCashAddTime = lastCashAddTime;
446 us.passiveTime = passiveTime;
447 us.lastActivityTime = lastActivityTime;
449 if (store->SaveMonthStat(us, t1->tm_mon, t1->tm_year, login))
451 WriteServLog("Cannot write month stat for user %s.", login.c_str());
452 WriteServLog("%s", store->GetStrError().c_str());
453 printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
454 printfd(__FILE__, "%s\n", store->GetStrError().c_str());
460 //-----------------------------------------------------------------------------
461 int USER::Authorize(uint32_t ip, const string &, uint32_t dirs, const BASE_AUTH * auth)
463 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
465 * Authorize user. It only means that user will be authorized. Nothing more.
466 * User can be connected or disconnected while authorized.
467 * Example: user is authorized but disconnected due to 0 money or blocking
471 * Prevent double authorization by identical authorizers
473 if (authorizedBy.find(auth) != authorizedBy.end())
479 for (int i = 0; i < DIR_NUM; i++)
481 enabledDirs[i] = dirs & (1 << i);
484 if (authorizedBy.size())
488 // We are already authorized, but with different IP address
489 errorStr = "User " + login + " alredy authorized with IP address " + inet_ntostring(ip);
493 map<uint32_t, user_iter>::const_iterator ci = ipIndex->find(ip);
494 if (ci != ipIndex->end())
496 // Address is already present in IP-index
497 // If it's not our IP - throw an error
498 if (&(*ci->second) != this)
500 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
507 if (ipIndex->find(ip) != ipIndex->end())
509 // Address is already present in IP-index
510 errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
514 if (ips.ConstData().IsIPInIPS(ip))
517 lastIPForDisconnect = currIP;
521 printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
522 errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
527 authorizedBy.insert(auth);
533 //-----------------------------------------------------------------------------
534 void USER::Unauthorize(const BASE_AUTH * auth)
536 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
538 * Authorizer tries to unauthorize user, that was not authorized by it
540 if (!authorizedBy.erase(auth))
543 if (authorizedBy.empty())
545 lastIPForDisconnect = currIP;
546 currIP = 0; // DelUser in traffcounter
550 //-----------------------------------------------------------------------------
551 bool USER::IsAuthorizedBy(const BASE_AUTH * auth) const
553 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
554 // Is this user authorized by specified authorizer?
555 return authorizedBy.find(auth) != authorizedBy.end();
557 //-----------------------------------------------------------------------------
558 void USER::Connect(bool fakeConnect)
561 * Connect user to Internet. This function is differ from Authorize() !!!
564 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
568 string scriptOnConnect = settings->GetScriptDir() + "/OnConnect";
570 if (access(scriptOnConnect.c_str(), X_OK) == 0)
572 char dirsStr[DIR_NUM + 1];
573 dirsStr[DIR_NUM] = 0;
574 for (int i = 0; i < DIR_NUM; i++)
576 dirsStr[i] = enabledDirs[i] ? '1' : '0';
579 string scriptOnConnectParams;
580 strprintf(&scriptOnConnectParams,
581 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
582 scriptOnConnect.c_str(),
584 inet_ntostring(currIP).c_str(),
589 ScriptExec(scriptOnConnectParams);
593 WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
599 if (store->WriteUserConnect(login, currIP))
601 WriteServLog("Cannot write connect for user %s.", login.c_str());
602 WriteServLog("%s", store->GetStrError().c_str());
606 lastIPForDisconnect = currIP;
608 //-----------------------------------------------------------------------------
609 void USER::Disconnect(bool fakeDisconnect, const std::string & reason)
612 * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
615 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
617 if (!lastIPForDisconnect)
619 printfd(__FILE__, "lastIPForDisconnect\n");
625 string scriptOnDisonnect = settings->GetScriptDir() + "/OnDisconnect";
627 if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
629 char dirsStr[DIR_NUM + 1];
630 dirsStr[DIR_NUM] = 0;
631 for (int i = 0; i < DIR_NUM; i++)
633 dirsStr[i] = enabledDirs[i] ? '1' : '0';
636 string scriptOnDisonnectParams;
637 strprintf(&scriptOnDisonnectParams,
638 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
639 scriptOnDisonnect.c_str(),
641 inet_ntostring(lastIPForDisconnect).c_str(),
646 ScriptExec(scriptOnDisonnectParams);
650 WriteServLog("Script OnDisconnect cannot be executed. File not found.");
656 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
658 WriteServLog("Cannot write disconnect for user %s.", login.c_str());
659 WriteServLog("%s", store->GetStrError().c_str());
663 lastIPForDisconnect = 0;
665 DIR_TRAFF zeroSesssion;
667 sessionUpload = zeroSesssion;
668 sessionDownload = zeroSesssion;
670 //-----------------------------------------------------------------------------
671 void USER::PrintUser() const
674 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
675 cout << "============================================================" << endl;
676 cout << "id=" << id << endl;
677 cout << "login=" << login << endl;
678 cout << "password=" << password << endl;
679 cout << "passive=" << passive << endl;
680 cout << "disabled=" << disabled << endl;
681 cout << "disabledDetailStat=" << disabledDetailStat << endl;
682 cout << "alwaysOnline=" << alwaysOnline << endl;
683 cout << "tariffName=" << tariffName << endl;
684 cout << "address=" << address << endl;
685 cout << "phone=" << phone << endl;
686 cout << "email=" << email << endl;
687 cout << "note=" << note << endl;
688 cout << "realName=" <<realName << endl;
689 cout << "group=" << group << endl;
690 cout << "credit=" << credit << endl;
691 cout << "nextTariff=" << nextTariff << endl;
692 cout << "userdata0" << userdata0 << endl;
693 cout << "userdata1" << userdata1 << endl;
694 cout << "creditExpire=" << creditExpire << endl;
695 cout << "ips=" << ips << endl;
696 cout << "------------------------" << endl;
697 cout << "up=" << up << endl;
698 cout << "down=" << down << endl;
699 cout << "cash=" << cash << endl;
700 cout << "freeMb=" << freeMb << endl;
701 cout << "lastCashAdd=" << lastCashAdd << endl;
702 cout << "lastCashAddTime=" << lastCashAddTime << endl;
703 cout << "passiveTime=" << passiveTime << endl;
704 cout << "lastActivityTime=" << lastActivityTime << endl;
705 cout << "============================================================" << endl;
707 //-----------------------------------------------------------------------------
710 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
712 if (stgTime - lastWriteStat > settings->GetStatWritePeriod())
714 printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
717 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
719 WriteServLog("User: %s. Credit expired.", login.c_str());
725 if (passive.ConstData()
726 && (stgTime % 30 == 0)
727 && (passiveTime.ModificationTime() != stgTime))
729 passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
730 printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
733 if (!authorizedBy.empty())
737 lastActivityTime = *const_cast<time_t *>(&stgTime);
739 if (!connected && IsInetable())
743 if (connected && !IsInetable())
746 Disconnect(false, "disabled");
748 Disconnect(false, "passive");
750 Disconnect(false, "no cash");
753 if (stgTime - lastScanMessages > 10)
756 lastScanMessages = stgTime;
763 Disconnect(false, "not authorized");
768 //-----------------------------------------------------------------------------
769 void USER::UpdatePingTime(time_t t)
771 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
772 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
778 //-----------------------------------------------------------------------------
779 bool USER::IsInetable()
781 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
783 if (disabled || passive)
786 if (settings->GetFreeMbAllowInet())
792 if (settings->GetShowFeeInCash())
794 return (cash >= -credit);
797 return (cash - tariff->GetFee() >= -credit);
799 //-----------------------------------------------------------------------------
800 string USER::GetEnabledDirs()
802 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
805 for(int i = 0; i < DIR_NUM; i++)
806 dirs += enabledDirs[i] ? "1" : "0";
809 //-----------------------------------------------------------------------------
810 #ifdef TRAFF_STAT_WITH_PORTS
811 void USER::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
813 void USER::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
816 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
824 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
825 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
829 int tt = tariff->GetTraffType();
830 if (tt == TRAFF_UP ||
831 tt == TRAFF_UP_DOWN ||
832 // Check NEW traff data
833 (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
836 if (traff < threshold &&
837 traff + len >= threshold)
839 // cash = partBeforeThreshold * priceBeforeThreshold +
840 // partAfterThreshold * priceAfterThreshold
841 int64_t before = threshold - traff; // Chunk part before threshold
842 int64_t after = len - before; // Chunk part after threshold
843 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
844 down.ConstData()[dir],
847 tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
848 down.ConstData()[dir],
854 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
855 down.ConstData()[dir],
860 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
862 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
863 cost = dc - freeMb.ConstData();
865 // Direct access to internal data structures via friend-specifier
866 property.stat.freeMb -= dc;
867 property.stat.cash -= cost;
873 sessionUpload[dir] += len;
877 if (!writeFreeMbTraffCost && freeMb.ConstData() >= 0)
880 #ifdef TRAFF_STAT_WITH_PORTS
881 IP_DIR_PAIR idp(ip, dir, port);
883 IP_DIR_PAIR idp(ip, dir);
886 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
887 lb = traffStat.lower_bound(idp);
888 if (lb == traffStat.end() || lb->first != idp)
891 pair<IP_DIR_PAIR, STAT_NODE>(idp,
892 STAT_NODE(len, 0, cost)));
896 lb->second.cash += cost;
897 lb->second.up += len;
900 //-----------------------------------------------------------------------------
901 #ifdef TRAFF_STAT_WITH_PORTS
902 void USER::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
904 void USER::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
907 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
915 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
916 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
920 int tt = tariff->GetTraffType();
921 if (tt == TRAFF_DOWN ||
922 tt == TRAFF_UP_DOWN ||
923 // Check NEW traff data
924 (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
927 if (traff < threshold &&
928 traff + len >= threshold)
930 // cash = partBeforeThreshold * priceBeforeThreshold +
931 // partAfterThreshold * priceAfterThreshold
932 int64_t before = threshold - traff; // Chunk part before threshold
933 int64_t after = len - before; // Chunk part after threshold
934 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
935 down.ConstData()[dir], // Traff before chunk
938 tariff->GetPriceWithTraffType(up.ConstData()[dir],
939 dt[dir], // Traff after chunk
945 dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
946 down.ConstData()[dir],
951 if (freeMb.ConstData() <= 0) // FreeMb is exhausted
953 else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
954 cost = dc - freeMb.ConstData();
956 property.stat.freeMb -= dc;
957 property.stat.cash -= cost;
963 sessionDownload[dir] += len;
967 if (!writeFreeMbTraffCost && freeMb.ConstData() >= 0)
970 #ifdef TRAFF_STAT_WITH_PORTS
971 IP_DIR_PAIR idp(ip, dir, port);
973 IP_DIR_PAIR idp(ip, dir);
976 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
977 lb = traffStat.lower_bound(idp);
978 if (lb == traffStat.end() || lb->first != idp)
981 pair<IP_DIR_PAIR, STAT_NODE>(idp,
982 STAT_NODE(0, len, cost)));
986 lb->second.cash += cost;
987 lb->second.down += len;
990 //-----------------------------------------------------------------------------
991 void USER::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
993 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
994 currIP.AddBeforeNotifier(n);
996 //-----------------------------------------------------------------------------
997 void USER::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
999 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1000 currIP.DelBeforeNotifier(n);
1002 //-----------------------------------------------------------------------------
1003 void USER::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
1005 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1006 currIP.AddAfterNotifier(n);
1008 //-----------------------------------------------------------------------------
1009 void USER::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
1011 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1012 currIP.DelAfterNotifier(n);
1014 //-----------------------------------------------------------------------------
1017 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1019 string scriptOnAdd = settings->GetScriptDir() + "/OnUserAdd";
1021 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1023 string scriptOnAddParams;
1024 strprintf(&scriptOnAddParams,
1026 scriptOnAdd.c_str(),
1029 ScriptExec(scriptOnAddParams);
1033 WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1036 //-----------------------------------------------------------------------------
1037 void USER::OnDelete()
1039 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1041 string scriptOnDel = settings->GetScriptDir() + "/OnUserDel";
1043 if (access(scriptOnDel.c_str(), X_OK) == 0)
1045 string scriptOnDelParams;
1046 strprintf(&scriptOnDelParams,
1048 scriptOnDel.c_str(),
1051 ScriptExec(scriptOnDelParams);
1055 WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1060 //-----------------------------------------------------------------------------
1061 int USER::WriteDetailStat(bool hard)
1063 printfd(__FILE__, "USER::WriteDetailedStat() - queue size = %d\n", traffStatQueue.size());
1065 if (!traffStatQueue.empty())
1067 std::list<std::pair<time_t, TRAFF_STAT> >::iterator it;
1068 for (it = traffStatQueue.begin(); it != traffStatQueue.end(); ++it)
1070 if (store->WriteDetailedStat(it->second, it->first, login))
1072 printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1073 WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatQueue.size(), login.c_str());
1074 WriteServLog("%s", store->GetStrError().c_str());
1077 traffStatQueue.erase(it++);
1084 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1088 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1090 if (ts.size() && !disabledDetailStat)
1092 if (store->WriteDetailedStat(ts, lastWriteDeatiledStat, login))
1094 printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1095 WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1096 WriteServLog("%s", store->GetStrError().c_str());
1099 printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1100 traffStatQueue.push_back(std::make_pair(lastWriteDeatiledStat, ts));
1104 lastWriteDeatiledStat = stgTime;
1107 //-----------------------------------------------------------------------------
1108 double USER::GetPassiveTimePart() const
1110 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1112 static int daysInMonth[12] =
1113 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1117 tms = localtime(&t);
1119 time_t secMonth = daysInMonth[(tms->tm_mon + 11) % 12] * 24 * 3600; // Previous month
1121 if (tms->tm_year % 4 == 0 && tms->tm_mon == 1)
1124 secMonth += 24 * 3600;
1127 int dt = secMonth - passiveTime;
1132 return double(dt) / (secMonth);
1134 //-----------------------------------------------------------------------------
1135 void USER::SetPassiveTimeAsNewUser()
1137 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1143 int daysCurrMon = DaysInCurrentMonth();
1144 double pt = (tm->tm_mday - 1) / (double)daysCurrMon;
1146 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
1148 //-----------------------------------------------------------------------------
1149 void USER::MidnightResetSessionStat()
1151 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1155 Disconnect(true, "fake");
1159 //-----------------------------------------------------------------------------
1160 void USER::ProcessNewMonth()
1162 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1166 Disconnect(true, "fake");
1168 DIR_TRAFF zeroTarff;
1181 if (nextTariff.ConstData() != "")
1184 nt = tariffs->FindByName(nextTariff);
1187 WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1188 login.c_str(), property.tariffName.Get().c_str());
1192 property.tariffName.Set(nextTariff, sysAdmin, login, store);
1199 //-----------------------------------------------------------------------------
1200 void USER::ProcessDayFeeSpread()
1202 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1204 if (passive.ConstData())
1207 double f = tariff->GetFee() / DaysInCurrentMonth();
1213 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1216 //-----------------------------------------------------------------------------
1217 void USER::ProcessDayFee()
1219 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1221 double passiveTimePart = 1.0;
1222 if (!settings->GetFullFee())
1224 passiveTimePart = GetPassiveTimePart();
1228 if (passive.ConstData())
1230 printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1234 double f = tariff->GetFee() * passiveTimePart;
1242 printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
1247 property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
1249 //-----------------------------------------------------------------------------
1250 void USER::SetPrepaidTraff()
1252 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1254 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1256 //-----------------------------------------------------------------------------
1257 int USER::AddMessage(STG_MSG * msg)
1259 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1261 if (SendMessage(*msg) == 0)
1263 if (msg->header.repeat > 0)
1265 msg->header.repeat--;
1267 //TODO: gcc v. 4.x generate ICE on x86_64
1268 msg->header.lastSendTime = time(NULL);
1270 msg->header.lastSendTime = stgTime;
1272 if (store->AddMessage(msg, login))
1274 errorStr = store->GetStrError();
1275 STG_LOGGER & WriteServLog = GetStgLogger();
1276 WriteServLog("Error adding message %s", errorStr.c_str());
1277 WriteServLog("%s", store->GetStrError().c_str());
1284 if (store->AddMessage(msg, login))
1286 errorStr = store->GetStrError();
1287 STG_LOGGER & WriteServLog = GetStgLogger();
1288 WriteServLog("Error adding message %s", errorStr.c_str());
1289 WriteServLog("%s", store->GetStrError().c_str());
1295 //-----------------------------------------------------------------------------
1296 int USER::SendMessage(const STG_MSG & msg)
1298 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1300 if (authorizedBy.empty())
1306 set<const BASE_AUTH*>::iterator it;
1308 it = authorizedBy.begin();
1309 while (it != authorizedBy.end())
1311 if ((*it)->SendMessage(msg, currIP) == 0)
1317 //-----------------------------------------------------------------------------
1318 int USER::ScanMessage()
1320 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1322 vector<STG_MSG_HDR> hdrsList;
1324 if (store->GetMessageHdrs(&hdrsList, login))
1326 printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
1330 for (unsigned i = 0; i < hdrsList.size(); i++)
1333 if (hdrsList[i].lastSendTime + hdrsList[i].repeatPeriod * 60 < (unsigned)stgTime)
1336 if (store->GetMessage(hdrsList[i].id, &msg, login) == 0)
1338 if (SendMessage(msg) == 0)
1340 msg.header.repeat--;
1341 if (msg.header.repeat < 0)
1343 printfd(__FILE__, "DelMessage\n");
1344 store->DelMessage(hdrsList[i].id, login);
1349 //TODO: gcc v. 4.x generate ICE on x86_64
1350 msg.header.lastSendTime = time(NULL);
1352 msg.header.lastSendTime = stgTime;
1354 if (store->EditMessage(msg, login))
1356 printfd(__FILE__, "EditMessage Error %s\n", store->GetStrError().c_str());
1363 WriteServLog("Cannot get message for user %s.", login.c_str());
1364 WriteServLog("%s", store->GetStrError().c_str());
1370 //-----------------------------------------------------------------------------
1371 //-----------------------------------------------------------------------------
1372 //-----------------------------------------------------------------------------
1373 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1375 if (newPassive && !oldPassive)
1376 user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1382 //-----------------------------------------------------------------------------
1383 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
1385 user->tariff = user->tariffs->FindByName(newTariff);
1387 //-----------------------------------------------------------------------------
1388 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1390 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1391 user->lastCashAdd = newCash - oldCash;
1393 //-----------------------------------------------------------------------------
1394 void CHG_IP_NOTIFIER::Notify(const uint32_t & from, const uint32_t & to)
1396 printfd(__FILE__, "Change IP from %s to %s\n", inet_ntostring(from).c_str(), inet_ntostring(to).c_str());
1398 if (user->connected)
1399 user->Disconnect(false, "Change IP");
1401 if (user->IsInetable())
1402 user->Connect(false);
1404 //-----------------------------------------------------------------------------