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