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
 
  41 #include "stg/users.h"
 
  42 #include "stg/common.h"
 
  43 #include "stg/scriptexecuter.h"
 
  44 #include "stg/tariff.h"
 
  45 #include "stg/tariffs.h"
 
  46 #include "stg/admin.h"
 
  47 #include "user_impl.h"
 
  48 #include "settings_impl.h"
 
  50 #ifdef USE_ABSTRACT_SETTINGS
 
  51 USER_IMPL::USER_IMPL(const SETTINGS * s,
 
  57       property(s->GetScriptsDir()),
 
  58       WriteServLog(GetStgLogger()),
 
  62       connected(__connected),
 
  66       lastIPForDisconnect(0),
 
  71       tariff(tariffs->GetNoTariff()),
 
  75       lastCashAdd(property.lastCashAdd),
 
  76       passiveTime(property.passiveTime),
 
  77       lastCashAddTime(property.lastCashAddTime),
 
  78       freeMb(property.freeMb),
 
  79       lastActivityTime(property.lastActivityTime),
 
  80       password(property.password),
 
  81       passive(property.passive),
 
  82       disabled(property.disabled),
 
  83       disabledDetailStat(property.disabledDetailStat),
 
  84       alwaysOnline(property.alwaysOnline),
 
  85       tariffName(property.tariffName),
 
  86       nextTariff(property.nextTariff),
 
  87       address(property.address),
 
  89       group(property.group),
 
  90       email(property.email),
 
  91       phone(property.phone),
 
  92       realName(property.realName),
 
  93       credit(property.credit),
 
  94       creditExpire(property.creditExpire),
 
  96       userdata0(property.userdata0),
 
  97       userdata1(property.userdata1),
 
  98       userdata2(property.userdata2),
 
  99       userdata3(property.userdata3),
 
 100       userdata4(property.userdata4),
 
 101       userdata5(property.userdata5),
 
 102       userdata6(property.userdata6),
 
 103       userdata7(property.userdata7),
 
 104       userdata8(property.userdata8),
 
 105       userdata9(property.userdata9),
 
 106       passiveNotifier(this),
 
 107       tariffNotifier(this),
 
 113 password = "*_EMPTY_PASSWORD_*";
 
 114 tariffName = NO_TARIFF_NAME;
 
 116 tariff = tariffs->GetNoTariff();
 
 119 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
 
 120 lastWriteDetailedStat = stgTime;
 
 122 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 123 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 124 property.cash.AddBeforeNotifier(&cashNotifier);
 
 125 ips.AddAfterNotifier(&ipNotifier);
 
 127 lastScanMessages = 0;
 
 129 pthread_mutexattr_t attr;
 
 130 pthread_mutexattr_init(&attr);
 
 131 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 132 pthread_mutex_init(&mutex, &attr);
 
 135 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
 
 141       property(s->GetScriptsDir()),
 
 142       WriteServLog(GetStgLogger()),
 
 146       connected(__connected),
 
 150       lastIPForDisconnect(0),
 
 155       tariff(tariffs->GetNoTariff()),
 
 159       lastCashAdd(property.lastCashAdd),
 
 160       passiveTime(property.passiveTime),
 
 161       lastCashAddTime(property.lastCashAddTime),
 
 162       freeMb(property.freeMb),
 
 163       lastActivityTime(property.lastActivityTime),
 
 164       password(property.password),
 
 165       passive(property.passive),
 
 166       disabled(property.disabled),
 
 167       disabledDetailStat(property.disabledDetailStat),
 
 168       alwaysOnline(property.alwaysOnline),
 
 169       tariffName(property.tariffName),
 
 170       nextTariff(property.nextTariff),
 
 171       address(property.address),
 
 173       group(property.group),
 
 174       email(property.email),
 
 175       phone(property.phone),
 
 176       realName(property.realName),
 
 177       credit(property.credit),
 
 178       creditExpire(property.creditExpire),
 
 180       userdata0(property.userdata0),
 
 181       userdata1(property.userdata1),
 
 182       userdata2(property.userdata2),
 
 183       userdata3(property.userdata3),
 
 184       userdata4(property.userdata4),
 
 185       userdata5(property.userdata5),
 
 186       userdata6(property.userdata6),
 
 187       userdata7(property.userdata7),
 
 188       userdata8(property.userdata8),
 
 189       userdata9(property.userdata9),
 
 190       passiveNotifier(this),
 
 191       tariffNotifier(this),
 
 197 password = "*_EMPTY_PASSWORD_*";
 
 198 tariffName = NO_TARIFF_NAME;
 
 200 tariff = tariffs->GetNoTariff();
 
 203 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
 
 204 lastWriteDetailedStat = stgTime;
 
 206 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 207 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 208 property.cash.AddBeforeNotifier(&cashNotifier);
 
 209 ips.AddAfterNotifier(&ipNotifier);
 
 211 lastScanMessages = 0;
 
 213 pthread_mutexattr_t attr;
 
 214 pthread_mutexattr_init(&attr);
 
 215 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 216 pthread_mutex_init(&mutex, &attr);
 
 219 //-----------------------------------------------------------------------------
 
 220 USER_IMPL::USER_IMPL(const USER_IMPL & u)
 
 222       property(u.settings->GetScriptsDir()),
 
 223       WriteServLog(GetStgLogger()),
 
 226       __connected(u.__connected),
 
 227       connected(__connected),
 
 228       __currIP(u.__currIP),
 
 230       lastIPForDisconnect(0),
 
 231       pingTime(u.pingTime),
 
 232       sysAdmin(u.sysAdmin),
 
 239       lastCashAdd(property.lastCashAdd),
 
 240       passiveTime(property.passiveTime),
 
 241       lastCashAddTime(property.lastCashAddTime),
 
 242       freeMb(property.freeMb),
 
 243       lastActivityTime(property.lastActivityTime),
 
 244       password(property.password),
 
 245       passive(property.passive),
 
 246       disabled(property.disabled),
 
 247       disabledDetailStat(property.disabledDetailStat),
 
 248       alwaysOnline(property.alwaysOnline),
 
 249       tariffName(property.tariffName),
 
 250       nextTariff(property.nextTariff),
 
 251       address(property.address),
 
 253       group(property.group),
 
 254       email(property.email),
 
 255       phone(property.phone),
 
 256       realName(property.realName),
 
 257       credit(property.credit),
 
 258       creditExpire(property.creditExpire),
 
 260       userdata0(property.userdata0),
 
 261       userdata1(property.userdata1),
 
 262       userdata2(property.userdata2),
 
 263       userdata3(property.userdata3),
 
 264       userdata4(property.userdata4),
 
 265       userdata5(property.userdata5),
 
 266       userdata6(property.userdata6),
 
 267       userdata7(property.userdata7),
 
 268       userdata8(property.userdata8),
 
 269       userdata9(property.userdata9),
 
 270       passiveNotifier(this),
 
 271       tariffNotifier(this),
 
 282 lastWriteStat = u.lastWriteStat;
 
 283 lastWriteDetailedStat = u.lastWriteDetailedStat;
 
 285 settings = u.settings;
 
 287 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 288 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 289 property.cash.AddBeforeNotifier(&cashNotifier);
 
 290 ips.AddAfterNotifier(&ipNotifier);
 
 292 lastScanMessages = 0;
 
 294 property.SetProperties(u.property);
 
 296 pthread_mutexattr_t attr;
 
 297 pthread_mutexattr_init(&attr);
 
 298 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 299 pthread_mutex_init(&mutex, &attr);
 
 301 //-----------------------------------------------------------------------------
 
 302 USER_IMPL::~USER_IMPL()
 
 304 property.passive.DelBeforeNotifier(&passiveNotifier);
 
 305 property.tariffName.DelBeforeNotifier(&tariffNotifier);
 
 306 pthread_mutex_destroy(&mutex);
 
 308 //-----------------------------------------------------------------------------
 
 309 void USER_IMPL::SetLogin(string const & l)
 
 311 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 312 assert(login.empty() && "Login is already set");
 
 314 id = userIDGenerator.GetNextID();
 
 316 //-----------------------------------------------------------------------------
 
 317 int USER_IMPL::ReadConf()
 
 319 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 322 if (store->RestoreUserConf(&conf, login))
 
 324     WriteServLog("Cannot read conf for user %s.", login.c_str());
 
 325     WriteServLog("%s", store->GetStrError().c_str());
 
 326     printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
 
 327     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 331 property.SetConf(conf);
 
 333 tariff = tariffs->FindByName(tariffName);
 
 336     WriteServLog("Cannot read user %s. Tariff %s not exist.",
 
 337                  login.c_str(), property.tariffName.Get().c_str());
 
 341 std::vector<STG_MSG_HDR> hdrsList;
 
 343 if (store->GetMessageHdrs(&hdrsList, login))
 
 345     printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
 
 349 std::vector<STG_MSG_HDR>::const_iterator it;
 
 350 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
 
 353     if (store->GetMessage(it->id, &msg, login) == 0)
 
 355         messages.push_back(msg);
 
 361 //-----------------------------------------------------------------------------
 
 362 int USER_IMPL::ReadStat()
 
 364 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 367 if (store->RestoreUserStat(&stat, login))
 
 369     WriteServLog("Cannot read stat for user %s.", login.c_str());
 
 370     WriteServLog("%s", store->GetStrError().c_str());
 
 371     printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
 
 372     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 376 property.SetStat(stat);
 
 380 //-----------------------------------------------------------------------------
 
 381 int USER_IMPL::WriteConf()
 
 383 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 384 USER_CONF conf(property.GetConf());
 
 386 printfd(__FILE__, "USER::WriteConf()\n");
 
 388 if (store->SaveUserConf(conf, login))
 
 390     WriteServLog("Cannot write conf for user %s.", login.c_str());
 
 391     WriteServLog("%s", store->GetStrError().c_str());
 
 392     printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
 
 393     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 399 //-----------------------------------------------------------------------------
 
 400 int USER_IMPL::WriteStat()
 
 402 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 403 USER_STAT stat(property.GetStat());
 
 405 if (store->SaveUserStat(stat, login))
 
 407     WriteServLog("Cannot write stat for user %s.", login.c_str());
 
 408     WriteServLog("%s", store->GetStrError().c_str());
 
 409     printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
 
 410     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 414 lastWriteStat = stgTime;
 
 418 //-----------------------------------------------------------------------------
 
 419 int USER_IMPL::WriteMonthStat()
 
 421 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 422 time_t tt = stgTime - 3600;
 
 424 localtime_r(&tt, &t1);
 
 426 USER_STAT stat(property.GetStat());
 
 427 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
 
 429     WriteServLog("Cannot write month stat for user %s.", login.c_str());
 
 430     WriteServLog("%s", store->GetStrError().c_str());
 
 431     printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
 
 432     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 438 //-----------------------------------------------------------------------------
 
 439 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
 
 441 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 443  *  Authorize user. It only means that user will be authorized. Nothing more.
 
 444  *  User can be connected or disconnected while authorized.
 
 445  *  Example: user is authorized but disconnected due to 0 money or blocking
 
 449  * Prevent double authorization by identical authorizers
 
 451 if (authorizedBy.find(auth) != authorizedBy.end())
 
 457 for (int i = 0; i < DIR_NUM; i++)
 
 459     enabledDirs[i] = dirs & (1 << i);
 
 462 if (authorizedBy.size())
 
 466         //  We are already authorized, but with different IP address
 
 467         errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
 
 472     if (!users->FindByIPIdx(ip, &u))
 
 474         //  Address is already present in IP-index
 
 475         //  If it's not our IP - throw an error
 
 478             errorStr = "IP address " + inet_ntostring(ip) + " already in use";
 
 485     if (users->IsIPInIndex(ip))
 
 487         //  Address is already present in IP-index
 
 488         errorStr = "IP address " + inet_ntostring(ip) + " already in use";
 
 492     if (ips.ConstData().IsIPInIPS(ip))
 
 495         lastIPForDisconnect = currIP;
 
 499         printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
 
 500         errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
 
 505 authorizedBy.insert(auth);
 
 511 //-----------------------------------------------------------------------------
 
 512 void USER_IMPL::Unauthorize(const AUTH * auth)
 
 514 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 516  *  Authorizer tries to unauthorize user, that was not authorized by it
 
 518 if (!authorizedBy.erase(auth))
 
 521 if (authorizedBy.empty())
 
 523     lastIPForDisconnect = currIP;
 
 524     currIP = 0; // DelUser in traffcounter
 
 528 //-----------------------------------------------------------------------------
 
 529 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
 
 531 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 532 //  Is this user authorized by specified authorizer?
 
 533 return authorizedBy.find(auth) != authorizedBy.end();
 
 535 //-----------------------------------------------------------------------------
 
 536 void USER_IMPL::Connect(bool fakeConnect)
 
 539  *  Connect user to Internet. This function is differ from Authorize() !!!
 
 542 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 546     string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
 
 548     if (access(scriptOnConnect.c_str(), X_OK) == 0)
 
 550         char dirsStr[DIR_NUM + 1];
 
 551         dirsStr[DIR_NUM] = 0;
 
 552         for (int i = 0; i < DIR_NUM; i++)
 
 554             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 557         string scriptOnConnectParams;
 
 558         strprintf(&scriptOnConnectParams,
 
 559                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 560                 scriptOnConnect.c_str(),
 
 562                 inet_ntostring(currIP).c_str(),
 
 567         ScriptExec(scriptOnConnectParams);
 
 571         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
 
 577 if (store->WriteUserConnect(login, currIP))
 
 579     WriteServLog("Cannot write connect for user %s.", login.c_str());
 
 580     WriteServLog("%s", store->GetStrError().c_str());
 
 584     lastIPForDisconnect = currIP;
 
 586 //-----------------------------------------------------------------------------
 
 587 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
 
 590  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
 
 593 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 595 if (!lastIPForDisconnect)
 
 597     printfd(__FILE__, "lastIPForDisconnect\n");
 
 603     string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
 
 605     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
 
 607         char dirsStr[DIR_NUM + 1];
 
 608         dirsStr[DIR_NUM] = 0;
 
 609         for (int i = 0; i < DIR_NUM; i++)
 
 611             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 614         string scriptOnDisonnectParams;
 
 615         strprintf(&scriptOnDisonnectParams,
 
 616                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 617                 scriptOnDisonnect.c_str(),
 
 619                 inet_ntostring(lastIPForDisconnect).c_str(),
 
 624         ScriptExec(scriptOnDisonnectParams);
 
 628         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
 
 634 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
 
 636     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
 
 637     WriteServLog("%s", store->GetStrError().c_str());
 
 641     lastIPForDisconnect = 0;
 
 643 DIR_TRAFF zeroSesssion;
 
 645 sessionUpload = zeroSesssion;
 
 646 sessionDownload = zeroSesssion;
 
 648 //-----------------------------------------------------------------------------
 
 649 void USER_IMPL::PrintUser() const
 
 652 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 653 cout << "============================================================" << endl;
 
 654 cout << "id=" << id << endl;
 
 655 cout << "login=" << login << endl;
 
 656 cout << "password=" << password << endl;
 
 657 cout << "passive=" << passive << endl;
 
 658 cout << "disabled=" << disabled << endl;
 
 659 cout << "disabledDetailStat=" << disabledDetailStat << endl;
 
 660 cout << "alwaysOnline=" << alwaysOnline << endl;
 
 661 cout << "tariffName=" << tariffName << endl;
 
 662 cout << "address=" << address << endl;
 
 663 cout << "phone=" << phone << endl;
 
 664 cout << "email=" << email << endl;
 
 665 cout << "note=" << note << endl;
 
 666 cout << "realName=" <<realName << endl;
 
 667 cout << "group=" << group << endl;
 
 668 cout << "credit=" << credit << endl;
 
 669 cout << "nextTariff=" << nextTariff << endl;
 
 670 cout << "userdata0" << userdata0 << endl;
 
 671 cout << "userdata1" << userdata1 << endl;
 
 672 cout << "creditExpire=" << creditExpire << endl;
 
 673 cout << "ips=" << ips << endl;
 
 674 cout << "------------------------" << endl;
 
 675 cout << "up=" << up << endl;
 
 676 cout << "down=" << down << endl;
 
 677 cout << "cash=" << cash << endl;
 
 678 cout << "freeMb=" << freeMb << endl;
 
 679 cout << "lastCashAdd=" << lastCashAdd << endl;
 
 680 cout << "lastCashAddTime=" << lastCashAddTime << endl;
 
 681 cout << "passiveTime=" << passiveTime << endl;
 
 682 cout << "lastActivityTime=" << lastActivityTime << endl;
 
 683 cout << "============================================================" << endl;
 
 685 //-----------------------------------------------------------------------------
 
 686 void USER_IMPL::Run()
 
 688 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 690 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
 
 692     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
 
 695 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
 
 697     WriteServLog("User: %s. Credit expired.", login.c_str());
 
 703 if (passive.ConstData()
 
 704     && (stgTime % 30 == 0)
 
 705     && (passiveTime.ModificationTime() != stgTime))
 
 707     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
 
 708     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
 
 711 if (!authorizedBy.empty())
 
 715         property.Stat().lastActivityTime = stgTime;
 
 717     if (!connected && IsInetable())
 
 721     if (connected && !IsInetable())
 
 724             Disconnect(false, "disabled");
 
 726             Disconnect(false, "passive");
 
 728             Disconnect(false, "no cash");
 
 731     if (stgTime - lastScanMessages > 10)
 
 734         lastScanMessages = stgTime;
 
 741         Disconnect(false, "not authorized");
 
 746 //-----------------------------------------------------------------------------
 
 747 void USER_IMPL::UpdatePingTime(time_t t)
 
 749 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 750 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
 
 756 //-----------------------------------------------------------------------------
 
 757 bool USER_IMPL::IsInetable()
 
 759 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 761 if (disabled || passive)
 
 764 if (settings->GetFreeMbAllowInet())
 
 770 if (settings->GetShowFeeInCash())
 
 772     return (cash >= -credit);
 
 775 return (cash - tariff->GetFee() >= -credit);
 
 777 //-----------------------------------------------------------------------------
 
 778 string USER_IMPL::GetEnabledDirs()
 
 780 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 783 for(int i = 0; i < DIR_NUM; i++)
 
 784     dirs += enabledDirs[i] ? "1" : "0";
 
 787 //-----------------------------------------------------------------------------
 
 788 #ifdef TRAFF_STAT_WITH_PORTS
 
 789 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 791 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
 
 794 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 802 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 803 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 807 int tt = tariff->GetTraffType();
 
 808 if (tt == TRAFF_UP ||
 
 809     tt == TRAFF_UP_DOWN ||
 
 810     // Check NEW traff data
 
 811     (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
 
 814     if (traff < threshold &&
 
 815         traff + len >= threshold)
 
 817         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 818         //        partAfterThreshold * priceAfterThreshold
 
 819         int64_t before = threshold - traff; // Chunk part before threshold
 
 820         int64_t after = len - before; // Chunk part after threshold
 
 821         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
 
 822                                            down.ConstData()[dir],
 
 825              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
 
 826                                            down.ConstData()[dir],
 
 832         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 833                                            down.ConstData()[dir],
 
 838     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 840     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 841         cost = dc - freeMb.ConstData();
 
 843     // Direct access to internal data structures via friend-specifier
 
 844     property.Stat().freeMb -= dc;
 
 845     property.Stat().cash -= cost;
 
 851 sessionUpload[dir] += len;
 
 855 if (!settings->GetWriteFreeMbTraffCost() &&
 
 856      freeMb.ConstData() >= 0)
 
 859 #ifdef TRAFF_STAT_WITH_PORTS
 
 860 IP_DIR_PAIR idp(ip, dir, port);
 
 862 IP_DIR_PAIR idp(ip, dir);
 
 865 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
 866 lb = traffStat.lower_bound(idp);
 
 867 if (lb == traffStat.end() || lb->first != idp)
 
 870                      pair<IP_DIR_PAIR, STAT_NODE>(idp,
 
 871                                                   STAT_NODE(len, 0, cost)));
 
 875     lb->second.cash += cost;
 
 876     lb->second.up += len;
 
 879 //-----------------------------------------------------------------------------
 
 880 #ifdef TRAFF_STAT_WITH_PORTS
 
 881 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 883 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
 
 886 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 894 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 895 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 899 int tt = tariff->GetTraffType();
 
 900 if (tt == TRAFF_DOWN ||
 
 901     tt == TRAFF_UP_DOWN ||
 
 902     // Check NEW traff data
 
 903     (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
 
 906     if (traff < threshold &&
 
 907         traff + len >= threshold)
 
 909         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 910         //        partAfterThreshold * priceAfterThreshold
 
 911         int64_t before = threshold - traff; // Chunk part before threshold
 
 912         int64_t after = len - before; // Chunk part after threshold
 
 913         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 914                                            down.ConstData()[dir], // Traff before chunk
 
 917              tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 918                                            dt[dir], // Traff after chunk
 
 924         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 925                                            down.ConstData()[dir],
 
 930     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 932     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 933         cost = dc - freeMb.ConstData();
 
 935     property.Stat().freeMb -= dc;
 
 936     property.Stat().cash -= cost;
 
 942 sessionDownload[dir] += len;
 
 946 if (!settings->GetWriteFreeMbTraffCost() &&
 
 947      freeMb.ConstData() >= 0)
 
 950 #ifdef TRAFF_STAT_WITH_PORTS
 
 951 IP_DIR_PAIR idp(ip, dir, port);
 
 953 IP_DIR_PAIR idp(ip, dir);
 
 956 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
 957 lb = traffStat.lower_bound(idp);
 
 958 if (lb == traffStat.end() || lb->first != idp)
 
 961                      pair<IP_DIR_PAIR, STAT_NODE>(idp,
 
 962                                                   STAT_NODE(0, len, cost)));
 
 966     lb->second.cash += cost;
 
 967     lb->second.down += len;
 
 970 //-----------------------------------------------------------------------------
 
 971 void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
 
 973 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 974 currIP.AddBeforeNotifier(n);
 
 976 //-----------------------------------------------------------------------------
 
 977 void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
 
 979 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 980 currIP.DelBeforeNotifier(n);
 
 982 //-----------------------------------------------------------------------------
 
 983 void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
 
 985 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 986 currIP.AddAfterNotifier(n);
 
 988 //-----------------------------------------------------------------------------
 
 989 void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
 
 991 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 992 currIP.DelAfterNotifier(n);
 
 994 //-----------------------------------------------------------------------------
 
 995 void USER_IMPL::AddConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
 
 997 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 998 connected.AddBeforeNotifier(n);
 
1000 //-----------------------------------------------------------------------------
 
1001 void USER_IMPL::DelConnectedBeforeNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
 
1003 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1004 connected.DelBeforeNotifier(n);
 
1006 //-----------------------------------------------------------------------------
 
1007 void USER_IMPL::AddConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
 
1009 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1010 connected.AddAfterNotifier(n);
 
1012 //-----------------------------------------------------------------------------
 
1013 void USER_IMPL::DelConnectedAfterNotifier(PROPERTY_NOTIFIER_BASE<bool> * n)
 
1015 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1016 connected.DelAfterNotifier(n);
 
1018 //-----------------------------------------------------------------------------
 
1019 void USER_IMPL::OnAdd()
 
1021 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1023 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
 
1025 if (access(scriptOnAdd.c_str(), X_OK) == 0)
 
1027     string scriptOnAddParams;
 
1028     strprintf(&scriptOnAddParams,
 
1030             scriptOnAdd.c_str(),
 
1033     ScriptExec(scriptOnAddParams);
 
1037     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
 
1040 //-----------------------------------------------------------------------------
 
1041 void USER_IMPL::OnDelete()
 
1043 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1045 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
 
1047 if (access(scriptOnDel.c_str(), X_OK) == 0)
 
1049     string scriptOnDelParams;
 
1050     strprintf(&scriptOnDelParams,
 
1052             scriptOnDel.c_str(),
 
1055     ScriptExec(scriptOnDelParams);
 
1059     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
 
1064 //-----------------------------------------------------------------------------
 
1065 int USER_IMPL::WriteDetailStat(bool hard)
 
1067 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
 
1069 if (!traffStatSaved.second.empty())
 
1071     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
 
1073         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
 
1074         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
 
1075         WriteServLog("%s", store->GetStrError().c_str());
 
1078     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
 
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, lastWriteDetailedStat, 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             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1101             traffStatSaved.second.swap(ts);
 
1102             traffStatSaved.first = lastWriteDetailedStat;
 
1107 lastWriteDetailedStat = stgTime;
 
1110 //-----------------------------------------------------------------------------
 
1111 double USER_IMPL::GetPassiveTimePart() const
 
1113 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1115 static int daysInMonth[12] =
 
1116 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
1120 localtime_r(&t, &tms);
 
1122 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
 
1124 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
 
1127     secMonth += 24 * 3600;
 
1130 int dt = secMonth - passiveTime;
 
1135 return double(dt) / (secMonth);
 
1137 //-----------------------------------------------------------------------------
 
1138 void USER_IMPL::SetPassiveTimeAsNewUser()
 
1140 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1144 localtime_r(&t, &tm);
 
1145 int daysCurrMon = DaysInCurrentMonth();
 
1146 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
 
1148 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
 
1150 //-----------------------------------------------------------------------------
 
1151 void USER_IMPL::MidnightResetSessionStat()
 
1153 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1157     Disconnect(true, "fake");
 
1161 //-----------------------------------------------------------------------------
 
1162 void USER_IMPL::ProcessNewMonth()
 
1164 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1168     Disconnect(true, "fake");
 
1170 DIR_TRAFF zeroTarff;
 
1183 if (nextTariff.ConstData() != "")
 
1186     nt = tariffs->FindByName(nextTariff);
 
1189         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
 
1190                      login.c_str(), property.tariffName.Get().c_str());
 
1194         property.tariffName.Set(nextTariff, sysAdmin, login, store);
 
1201 //-----------------------------------------------------------------------------
 
1202 void USER_IMPL::ProcessDayFeeSpread()
 
1204 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1206 if (passive.ConstData())
 
1209 double fee = tariff->GetFee() / DaysInCurrentMonth();
 
1215 switch (settings->GetFeeChargeType())
 
1218         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1222             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1226             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1231 //-----------------------------------------------------------------------------
 
1232 void USER_IMPL::ProcessDayFee()
 
1234 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1236 double passiveTimePart = 1.0;
 
1237 if (!settings->GetFullFee())
 
1239     passiveTimePart = GetPassiveTimePart();
 
1243     if (passive.ConstData())
 
1245         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
 
1249 double fee = tariff->GetFee() * passiveTimePart;
 
1257 printfd(__FILE__, "login: %8s   Fee=%f PassiveTimePart=%f fee=%f\n",
 
1262 switch (settings->GetFeeChargeType())
 
1265         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1269             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1273             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1277 //-----------------------------------------------------------------------------
 
1278 void USER_IMPL::SetPrepaidTraff()
 
1280 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1282 property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
 
1284 //-----------------------------------------------------------------------------
 
1285 int USER_IMPL::AddMessage(STG_MSG * msg)
 
1287 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1289 if (SendMessage(*msg))
 
1291     if (store->AddMessage(msg, login))
 
1293         errorStr = store->GetStrError();
 
1294         WriteServLog("Error adding message: '%s'", errorStr.c_str());
 
1295         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
 
1298     messages.push_back(*msg);
 
1302     if (msg->header.repeat > 0)
 
1304         msg->header.repeat--;
 
1306         //TODO: gcc v. 4.x generate ICE on x86_64
 
1307         msg->header.lastSendTime = time(NULL);
 
1309         msg->header.lastSendTime = stgTime;
 
1311         if (store->AddMessage(msg, login))
 
1313             errorStr = store->GetStrError();
 
1314             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
 
1315             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
 
1318         messages.push_back(*msg);
 
1323 //-----------------------------------------------------------------------------
 
1324 int USER_IMPL::SendMessage(STG_MSG & msg) const
 
1326 // No lock `cause we are already locked from caller
 
1328 set<const AUTH*>::iterator it(authorizedBy.begin());
 
1329 while (it != authorizedBy.end())
 
1331     if (!(*it++)->SendMessage(msg, currIP))
 
1337     //TODO: gcc v. 4.x generate ICE on x86_64
 
1338     msg.header.lastSendTime = time(NULL);
 
1340     msg.header.lastSendTime = stgTime;
 
1342     msg.header.repeat--;
 
1346 //-----------------------------------------------------------------------------
 
1347 void USER_IMPL::ScanMessage()
 
1349 // No lock `cause we are already locked from caller
 
1350 // We need not check for the authorizedBy `cause it has already checked by caller
 
1352 std::list<STG_MSG>::iterator it(messages.begin());
 
1353 while (it != messages.end())
 
1355     if (settings->GetMessageTimeout() > 0 &&
 
1356         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
 
1359         if (store->DelMessage(it->header.id, login))
 
1361             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1362             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1364         messages.erase(it++);
 
1367     if (it->GetNextSendTime() <= stgTime)
 
1369         if (SendMessage(*it))
 
1371             // We need to check all messages in queue for timeout
 
1375         if (it->header.repeat < 0)
 
1377             if (store->DelMessage(it->header.id, login))
 
1379                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1380                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1382             messages.erase(it++);
 
1386             if (store->EditMessage(*it, login))
 
1388                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
 
1389                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
 
1400 //-----------------------------------------------------------------------------
 
1401 //-----------------------------------------------------------------------------
 
1402 //-----------------------------------------------------------------------------
 
1403 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
 
1405 if (newPassive && !oldPassive)
 
1406     user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
 
1412 //-----------------------------------------------------------------------------
 
1413 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
 
1415 user->tariff = user->tariffs->FindByName(newTariff);
 
1417 //-----------------------------------------------------------------------------
 
1418 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
 
1420 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
 
1421 user->lastCashAdd = newCash - oldCash;
 
1423 //-----------------------------------------------------------------------------
 
1424 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
 
1426     printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
 
1427     if (user->connected)
 
1428         user->Disconnect(true, "Change IP");
 
1429     if (user->IsInetable())
 
1430         user->Connect(true);
 
1432 //-----------------------------------------------------------------------------