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
 
  42 #include "stg/users.h"
 
  43 #include "stg/common.h"
 
  44 #include "stg/scriptexecuter.h"
 
  45 #include "stg/tariff.h"
 
  46 #include "stg/tariffs.h"
 
  47 #include "stg/admin.h"
 
  48 #include "user_impl.h"
 
  49 #include "settings_impl.h"
 
  50 #include "stg_timer.h"
 
  52 #ifdef USE_ABSTRACT_SETTINGS
 
  53 USER_IMPL::USER_IMPL(const SETTINGS * s,
 
  60       property(s->GetScriptsDir()),
 
  61       WriteServLog(GetStgLogger()),
 
  66       connected(__connected),
 
  71       lastIPForDisconnect(0),
 
  84       lastWriteDetailedStat(0),
 
  88       lastCashAdd(property.lastCashAdd),
 
  89       passiveTime(property.passiveTime),
 
  90       lastCashAddTime(property.lastCashAddTime),
 
  91       freeMb(property.freeMb),
 
  92       lastActivityTime(property.lastActivityTime),
 
  93       password(property.password),
 
  94       passive(property.passive),
 
  95       disabled(property.disabled),
 
  96       disabledDetailStat(property.disabledDetailStat),
 
  97       alwaysOnline(property.alwaysOnline),
 
  98       tariffName(property.tariffName),
 
  99       nextTariff(property.nextTariff),
 
 100       address(property.address),
 
 102       group(property.group),
 
 103       email(property.email),
 
 104       phone(property.phone),
 
 105       realName(property.realName),
 
 106       credit(property.credit),
 
 107       creditExpire(property.creditExpire),
 
 109       userdata0(property.userdata0),
 
 110       userdata1(property.userdata1),
 
 111       userdata2(property.userdata2),
 
 112       userdata3(property.userdata3),
 
 113       userdata4(property.userdata4),
 
 114       userdata5(property.userdata5),
 
 115       userdata6(property.userdata6),
 
 116       userdata7(property.userdata7),
 
 117       userdata8(property.userdata8),
 
 118       userdata9(property.userdata9),
 
 121       passiveNotifier(this),
 
 122       tariffNotifier(this),
 
 128 password = "*_EMPTY_PASSWORD_*";
 
 129 tariffName = NO_TARIFF_NAME;
 
 131 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
 
 132 lastWriteDetailedStat = stgTime;
 
 134 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 135 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 136 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 137 property.cash.AddBeforeNotifier(&cashNotifier);
 
 138 ips.AddAfterNotifier(&ipNotifier);
 
 140 pthread_mutexattr_t attr;
 
 141 pthread_mutexattr_init(&attr);
 
 142 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 143 pthread_mutex_init(&mutex, &attr);
 
 146 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
 
 153       property(s->GetScriptsDir()),
 
 154       WriteServLog(GetStgLogger()),
 
 159       connected(__connected),
 
 164       lastIPForDisconnect(0),
 
 177       lastWriteDetailedStat(0),
 
 181       lastCashAdd(property.lastCashAdd),
 
 182       passiveTime(property.passiveTime),
 
 183       lastCashAddTime(property.lastCashAddTime),
 
 184       freeMb(property.freeMb),
 
 185       lastActivityTime(property.lastActivityTime),
 
 186       password(property.password),
 
 187       passive(property.passive),
 
 188       disabled(property.disabled),
 
 189       disabledDetailStat(property.disabledDetailStat),
 
 190       alwaysOnline(property.alwaysOnline),
 
 191       tariffName(property.tariffName),
 
 192       nextTariff(property.nextTariff),
 
 193       address(property.address),
 
 195       group(property.group),
 
 196       email(property.email),
 
 197       phone(property.phone),
 
 198       realName(property.realName),
 
 199       credit(property.credit),
 
 200       creditExpire(property.creditExpire),
 
 202       userdata0(property.userdata0),
 
 203       userdata1(property.userdata1),
 
 204       userdata2(property.userdata2),
 
 205       userdata3(property.userdata3),
 
 206       userdata4(property.userdata4),
 
 207       userdata5(property.userdata5),
 
 208       userdata6(property.userdata6),
 
 209       userdata7(property.userdata7),
 
 210       userdata8(property.userdata8),
 
 211       userdata9(property.userdata9),
 
 214       passiveNotifier(this),
 
 215       disabledNotifier(this),
 
 216       tariffNotifier(this),
 
 222 password = "*_EMPTY_PASSWORD_*";
 
 223 tariffName = NO_TARIFF_NAME;
 
 225 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
 
 226 lastWriteDetailedStat = stgTime;
 
 228 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 229 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 230 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 231 property.cash.AddBeforeNotifier(&cashNotifier);
 
 232 ips.AddAfterNotifier(&ipNotifier);
 
 234 pthread_mutexattr_t attr;
 
 235 pthread_mutexattr_init(&attr);
 
 236 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 237 pthread_mutex_init(&mutex, &attr);
 
 240 //-----------------------------------------------------------------------------
 
 241 USER_IMPL::USER_IMPL(const USER_IMPL & u)
 
 244       property(u.settings->GetScriptsDir()),
 
 245       WriteServLog(GetStgLogger()),
 
 250       connected(__connected),
 
 252       userIDGenerator(u.userIDGenerator),
 
 253       __currIP(u.__currIP),
 
 255       lastIPForDisconnect(0),
 
 256       pingTime(u.pingTime),
 
 257       sysAdmin(u.sysAdmin),
 
 261       traffStat(u.traffStat),
 
 262       traffStatSaved(u.traffStatSaved),
 
 263       settings(u.settings),
 
 265       messages(u.messages),
 
 267       lastWriteStat(u.lastWriteStat),
 
 268       lastWriteDetailedStat(u.lastWriteDetailedStat),
 
 272       lastCashAdd(property.lastCashAdd),
 
 273       passiveTime(property.passiveTime),
 
 274       lastCashAddTime(property.lastCashAddTime),
 
 275       freeMb(property.freeMb),
 
 276       lastActivityTime(property.lastActivityTime),
 
 277       password(property.password),
 
 278       passive(property.passive),
 
 279       disabled(property.disabled),
 
 280       disabledDetailStat(property.disabledDetailStat),
 
 281       alwaysOnline(property.alwaysOnline),
 
 282       tariffName(property.tariffName),
 
 283       nextTariff(property.nextTariff),
 
 284       address(property.address),
 
 286       group(property.group),
 
 287       email(property.email),
 
 288       phone(property.phone),
 
 289       realName(property.realName),
 
 290       credit(property.credit),
 
 291       creditExpire(property.creditExpire),
 
 293       userdata0(property.userdata0),
 
 294       userdata1(property.userdata1),
 
 295       userdata2(property.userdata2),
 
 296       userdata3(property.userdata3),
 
 297       userdata4(property.userdata4),
 
 298       userdata5(property.userdata5),
 
 299       userdata6(property.userdata6),
 
 300       userdata7(property.userdata7),
 
 301       userdata8(property.userdata8),
 
 302       userdata9(property.userdata9),
 
 305       passiveNotifier(this),
 
 306       disabledNotifier(this),
 
 307       tariffNotifier(this),
 
 316 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 317 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 318 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 319 property.cash.AddBeforeNotifier(&cashNotifier);
 
 320 ips.AddAfterNotifier(&ipNotifier);
 
 322 property.SetProperties(u.property);
 
 324 pthread_mutexattr_t attr;
 
 325 pthread_mutexattr_init(&attr);
 
 326 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 327 pthread_mutex_init(&mutex, &attr);
 
 329 //-----------------------------------------------------------------------------
 
 330 USER_IMPL::~USER_IMPL()
 
 332 property.tariffName.DelBeforeNotifier(&tariffNotifier);
 
 333 property.passive.DelBeforeNotifier(&passiveNotifier);
 
 334 property.disabled.DelAfterNotifier(&disabledNotifier);
 
 335 property.cash.DelBeforeNotifier(&cashNotifier);
 
 336 pthread_mutex_destroy(&mutex);
 
 338 //-----------------------------------------------------------------------------
 
 339 void USER_IMPL::SetLogin(const std::string & l)
 
 341 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 342 assert(login.empty() && "Login is already set");
 
 344 id = userIDGenerator.GetNextID();
 
 346 //-----------------------------------------------------------------------------
 
 347 int USER_IMPL::ReadConf()
 
 349 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 352 if (store->RestoreUserConf(&conf, login))
 
 354     WriteServLog("Cannot read conf for user %s.", login.c_str());
 
 355     WriteServLog("%s", store->GetStrError().c_str());
 
 356     printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
 
 357     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 361 property.SetConf(conf);
 
 363 tariff = tariffs->FindByName(tariffName);
 
 366     WriteServLog("Cannot read user %s. Tariff %s not exist.",
 
 367                  login.c_str(), property.tariffName.Get().c_str());
 
 371 std::vector<STG_MSG_HDR> hdrsList;
 
 373 if (store->GetMessageHdrs(&hdrsList, login))
 
 375     printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
 
 376     WriteServLog("Cannot read user %s. Error reading message headers: %s.",
 
 378                  store->GetStrError().c_str());
 
 382 std::vector<STG_MSG_HDR>::const_iterator it;
 
 383 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
 
 386     if (store->GetMessage(it->id, &msg, login) == 0)
 
 388         messages.push_back(msg);
 
 394 //-----------------------------------------------------------------------------
 
 395 int USER_IMPL::ReadStat()
 
 397 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 400 if (store->RestoreUserStat(&stat, login))
 
 402     WriteServLog("Cannot read stat for user %s.", login.c_str());
 
 403     WriteServLog("%s", store->GetStrError().c_str());
 
 404     printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
 
 405     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 409 property.SetStat(stat);
 
 413 //-----------------------------------------------------------------------------
 
 414 int USER_IMPL::WriteConf()
 
 416 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 417 USER_CONF conf(property.GetConf());
 
 419 printfd(__FILE__, "USER::WriteConf()\n");
 
 421 if (store->SaveUserConf(conf, login))
 
 423     WriteServLog("Cannot write conf for user %s.", login.c_str());
 
 424     WriteServLog("%s", store->GetStrError().c_str());
 
 425     printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
 
 426     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 432 //-----------------------------------------------------------------------------
 
 433 int USER_IMPL::WriteStat()
 
 435 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 436 USER_STAT stat(property.GetStat());
 
 438 if (store->SaveUserStat(stat, login))
 
 440     WriteServLog("Cannot write stat for user %s.", login.c_str());
 
 441     WriteServLog("%s", store->GetStrError().c_str());
 
 442     printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
 
 443     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 447 lastWriteStat = stgTime;
 
 451 //-----------------------------------------------------------------------------
 
 452 int USER_IMPL::WriteMonthStat()
 
 454 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 455 time_t tt = stgTime - 3600;
 
 457 localtime_r(&tt, &t1);
 
 459 USER_STAT stat(property.GetStat());
 
 460 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
 
 462     WriteServLog("Cannot write month stat for user %s.", login.c_str());
 
 463     WriteServLog("%s", store->GetStrError().c_str());
 
 464     printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
 
 465     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 471 //-----------------------------------------------------------------------------
 
 472 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
 
 474 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 476  *  Authorize user. It only means that user will be authorized. Nothing more.
 
 477  *  User can be connected or disconnected while authorized.
 
 478  *  Example: user is authorized but disconnected due to 0 money or blocking
 
 482  * Prevent double authorization by identical authorizers
 
 484 if (authorizedBy.find(auth) != authorizedBy.end())
 
 490 for (int i = 0; i < DIR_NUM; i++)
 
 492     enabledDirs[i] = dirs & (1 << i);
 
 495 if (!authorizedBy.empty())
 
 499         //  We are already authorized, but with different IP address
 
 500         errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
 
 505     if (!users->FindByIPIdx(ip, &u))
 
 507         //  Address is already present in IP-index
 
 508         //  If it's not our IP - throw an error
 
 511             errorStr = "IP address " + inet_ntostring(ip) + " already in use";
 
 518     if (users->IsIPInIndex(ip))
 
 520         //  Address is already present in IP-index
 
 521         errorStr = "IP address " + inet_ntostring(ip) + " already in use";
 
 525     if (ips.ConstData().IsIPInIPS(ip))
 
 528         lastIPForDisconnect = currIP;
 
 532         printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
 
 533         errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
 
 538 authorizedBy.insert(auth);
 
 544 //-----------------------------------------------------------------------------
 
 545 void USER_IMPL::Unauthorize(const AUTH * auth)
 
 547 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 549  *  Authorizer tries to unauthorize user, that was not authorized by it
 
 551 if (!authorizedBy.erase(auth))
 
 554 if (authorizedBy.empty())
 
 556     lastIPForDisconnect = currIP;
 
 557     currIP = 0; // DelUser in traffcounter
 
 561 //-----------------------------------------------------------------------------
 
 562 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
 
 564 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 565 //  Is this user authorized by specified authorizer?
 
 566 return authorizedBy.find(auth) != authorizedBy.end();
 
 568 //-----------------------------------------------------------------------------
 
 569 void USER_IMPL::Connect(bool fakeConnect)
 
 572  *  Connect user to Internet. This function is differ from Authorize() !!!
 
 575 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 579     std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
 
 581     if (access(scriptOnConnect.c_str(), X_OK) == 0)
 
 583         char dirsStr[DIR_NUM + 1];
 
 584         dirsStr[DIR_NUM] = 0;
 
 585         for (int i = 0; i < DIR_NUM; i++)
 
 587             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 590         std::string scriptOnConnectParams;
 
 592         strprintf(&scriptOnConnectParams,
 
 593                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 594                 scriptOnConnect.c_str(),
 
 596                 inet_ntostring(currIP).c_str(),
 
 601         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
 
 602         while (it != settings->GetScriptParams().end())
 
 604             scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
 
 608         ScriptExec(scriptOnConnectParams.c_str());
 
 612         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
 
 618 if (store->WriteUserConnect(login, currIP))
 
 620     WriteServLog("Cannot write connect for user %s.", login.c_str());
 
 621     WriteServLog("%s", store->GetStrError().c_str());
 
 625     lastIPForDisconnect = currIP;
 
 627 //-----------------------------------------------------------------------------
 
 628 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
 
 631  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
 
 634 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 636 if (!lastIPForDisconnect)
 
 638     printfd(__FILE__, "lastIPForDisconnect\n");
 
 644     std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
 
 646     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
 
 648         char dirsStr[DIR_NUM + 1];
 
 649         dirsStr[DIR_NUM] = 0;
 
 650         for (int i = 0; i < DIR_NUM; i++)
 
 652             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 655         std::string scriptOnDisonnectParams;
 
 656         strprintf(&scriptOnDisonnectParams,
 
 657                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 658                 scriptOnDisonnect.c_str(),
 
 660                 inet_ntostring(lastIPForDisconnect).c_str(),
 
 665         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
 
 666         while (it != settings->GetScriptParams().end())
 
 668             scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
 
 672         ScriptExec(scriptOnDisonnectParams.c_str());
 
 676         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
 
 682 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
 
 684     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
 
 685     WriteServLog("%s", store->GetStrError().c_str());
 
 689     lastIPForDisconnect = 0;
 
 691 DIR_TRAFF zeroSesssion;
 
 693 sessionUpload = zeroSesssion;
 
 694 sessionDownload = zeroSesssion;
 
 696 //-----------------------------------------------------------------------------
 
 697 void USER_IMPL::PrintUser() const
 
 700 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 701 std::cout << "============================================================" << std::endl;
 
 702 std::cout << "id=" << id << std::endl;
 
 703 std::cout << "login=" << login << std::endl;
 
 704 std::cout << "password=" << password << std::endl;
 
 705 std::cout << "passive=" << passive << std::endl;
 
 706 std::cout << "disabled=" << disabled << std::endl;
 
 707 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
 
 708 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
 
 709 std::cout << "tariffName=" << tariffName << std::endl;
 
 710 std::cout << "address=" << address << std::endl;
 
 711 std::cout << "phone=" << phone << std::endl;
 
 712 std::cout << "email=" << email << std::endl;
 
 713 std::cout << "note=" << note << std::endl;
 
 714 std::cout << "realName=" <<realName << std::endl;
 
 715 std::cout << "group=" << group << std::endl;
 
 716 std::cout << "credit=" << credit << std::endl;
 
 717 std::cout << "nextTariff=" << nextTariff << std::endl;
 
 718 std::cout << "userdata0" << userdata0 << std::endl;
 
 719 std::cout << "userdata1" << userdata1 << std::endl;
 
 720 std::cout << "creditExpire=" << creditExpire << std::endl;
 
 721 std::cout << "ips=" << ips << std::endl;
 
 722 std::cout << "------------------------" << std::endl;
 
 723 std::cout << "up=" << up << std::endl;
 
 724 std::cout << "down=" << down << std::endl;
 
 725 std::cout << "cash=" << cash << std::endl;
 
 726 std::cout << "freeMb=" << freeMb << std::endl;
 
 727 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
 
 728 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
 
 729 std::cout << "passiveTime=" << passiveTime << std::endl;
 
 730 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
 
 731 std::cout << "============================================================" << std::endl;
 
 733 //-----------------------------------------------------------------------------
 
 734 void USER_IMPL::Run()
 
 736 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 738 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
 
 740     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
 
 743 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
 
 745     WriteServLog("User: %s. Credit expired.", login.c_str());
 
 751 if (passive.ConstData()
 
 752     && (stgTime % 30 == 0)
 
 753     && (passiveTime.ModificationTime() != stgTime))
 
 755     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
 
 756     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
 
 759 if (!authorizedBy.empty())
 
 763         property.Stat().lastActivityTime = stgTime;
 
 765     if (!connected && IsInetable())
 
 769     if (connected && !IsInetable())
 
 772             Disconnect(false, "disabled");
 
 774             Disconnect(false, "passive");
 
 776             Disconnect(false, "no cash");
 
 779     if (stgTime - lastScanMessages > 10)
 
 782         lastScanMessages = stgTime;
 
 789         Disconnect(false, "not authorized");
 
 794 //-----------------------------------------------------------------------------
 
 795 void USER_IMPL::UpdatePingTime(time_t t)
 
 797 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 798 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
 
 804 //-----------------------------------------------------------------------------
 
 805 bool USER_IMPL::IsInetable()
 
 807 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 809 if (disabled || passive)
 
 812 if (settings->GetFreeMbAllowInet())
 
 818 if (settings->GetShowFeeInCash() || tariff == NULL)
 
 820     return (cash >= -credit);
 
 823 return (cash - tariff->GetFee() >= -credit);
 
 825 //-----------------------------------------------------------------------------
 
 826 std::string USER_IMPL::GetEnabledDirs()
 
 828 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 830 std::string dirs = "";
 
 831 for(int i = 0; i < DIR_NUM; i++)
 
 832     dirs += enabledDirs[i] ? "1" : "0";
 
 835 //-----------------------------------------------------------------------------
 
 836 #ifdef TRAFF_STAT_WITH_PORTS
 
 837 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 839 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
 
 842 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 844 if (!connected || tariff == NULL)
 
 850 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 851 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 855 int tt = tariff->GetTraffType();
 
 856 if (tt == TRAFF_UP ||
 
 857     tt == TRAFF_UP_DOWN ||
 
 858     // Check NEW traff data
 
 859     (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
 
 862     if (traff < threshold &&
 
 863         traff + len >= threshold)
 
 865         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 866         //        partAfterThreshold * priceAfterThreshold
 
 867         int64_t before = threshold - traff; // Chunk part before threshold
 
 868         int64_t after = len - before; // Chunk part after threshold
 
 869         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
 
 870                                            down.ConstData()[dir],
 
 873              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
 
 874                                            down.ConstData()[dir],
 
 880         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 881                                            down.ConstData()[dir],
 
 886     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 888     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 889         cost = dc - freeMb.ConstData();
 
 891     // Direct access to internal data structures via friend-specifier
 
 892     property.Stat().freeMb -= dc;
 
 893     property.Stat().cash -= cost;
 
 899 sessionUpload[dir] += len;
 
 903 if (!settings->GetWriteFreeMbTraffCost() &&
 
 904      freeMb.ConstData() >= 0)
 
 907 #ifdef TRAFF_STAT_WITH_PORTS
 
 908 IP_DIR_PAIR idp(ip, dir, port);
 
 910 IP_DIR_PAIR idp(ip, dir);
 
 913 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
 914 lb = traffStat.lower_bound(idp);
 
 915 if (lb == traffStat.end() || lb->first != idp)
 
 919                                     STAT_NODE(len, 0, cost)));
 
 923     lb->second.cash += cost;
 
 924     lb->second.up += len;
 
 927 //-----------------------------------------------------------------------------
 
 928 #ifdef TRAFF_STAT_WITH_PORTS
 
 929 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 931 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
 
 934 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 936 if (!connected || tariff == NULL)
 
 942 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 943 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 947 int tt = tariff->GetTraffType();
 
 948 if (tt == TRAFF_DOWN ||
 
 949     tt == TRAFF_UP_DOWN ||
 
 950     // Check NEW traff data
 
 951     (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
 
 954     if (traff < threshold &&
 
 955         traff + len >= threshold)
 
 957         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 958         //        partAfterThreshold * priceAfterThreshold
 
 959         int64_t before = threshold - traff; // Chunk part before threshold
 
 960         int64_t after = len - before; // Chunk part after threshold
 
 961         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 962                                            down.ConstData()[dir], // Traff before chunk
 
 965              tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 966                                            dt[dir], // Traff after chunk
 
 972         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 973                                            down.ConstData()[dir],
 
 978     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 980     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 981         cost = dc - freeMb.ConstData();
 
 983     property.Stat().freeMb -= dc;
 
 984     property.Stat().cash -= cost;
 
 990 sessionDownload[dir] += len;
 
 994 if (!settings->GetWriteFreeMbTraffCost() &&
 
 995      freeMb.ConstData() >= 0)
 
 998 #ifdef TRAFF_STAT_WITH_PORTS
 
 999 IP_DIR_PAIR idp(ip, dir, port);
 
1001 IP_DIR_PAIR idp(ip, dir);
 
1004 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
1005 lb = traffStat.lower_bound(idp);
 
1006 if (lb == traffStat.end() || lb->first != idp)
 
1008     traffStat.insert(lb,
 
1010                                     STAT_NODE(0, len, cost)));
 
1014     lb->second.cash += cost;
 
1015     lb->second.down += len;
 
1018 //-----------------------------------------------------------------------------
 
1019 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
 
1021 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1022 currIP.AddBeforeNotifier(notifier);
 
1024 //-----------------------------------------------------------------------------
 
1025 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
 
1027 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1028 currIP.DelBeforeNotifier(notifier);
 
1030 //-----------------------------------------------------------------------------
 
1031 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
 
1033 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1034 currIP.AddAfterNotifier(notifier);
 
1036 //-----------------------------------------------------------------------------
 
1037 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
 
1039 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1040 currIP.DelAfterNotifier(notifier);
 
1042 //-----------------------------------------------------------------------------
 
1043 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
 
1045 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1046 connected.AddBeforeNotifier(notifier);
 
1048 //-----------------------------------------------------------------------------
 
1049 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
 
1051 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1052 connected.DelBeforeNotifier(notifier);
 
1054 //-----------------------------------------------------------------------------
 
1055 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
 
1057 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1058 connected.AddAfterNotifier(notifier);
 
1060 //-----------------------------------------------------------------------------
 
1061 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
 
1063 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1064 connected.DelAfterNotifier(notifier);
 
1066 //-----------------------------------------------------------------------------
 
1067 void USER_IMPL::OnAdd()
 
1069 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1071 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
 
1073 if (access(scriptOnAdd.c_str(), X_OK) == 0)
 
1075     std::string scriptOnAddParams;
 
1076     strprintf(&scriptOnAddParams,
 
1078             scriptOnAdd.c_str(),
 
1081     ScriptExec(scriptOnAddParams.c_str());
 
1085     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
 
1088 //-----------------------------------------------------------------------------
 
1089 void USER_IMPL::OnDelete()
 
1091 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1093 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
 
1095 if (access(scriptOnDel.c_str(), X_OK) == 0)
 
1097     std::string scriptOnDelParams;
 
1098     strprintf(&scriptOnDelParams,
 
1100             scriptOnDel.c_str(),
 
1103     ScriptExec(scriptOnDelParams.c_str());
 
1107     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
 
1112 //-----------------------------------------------------------------------------
 
1113 int USER_IMPL::WriteDetailStat(bool hard)
 
1115 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
 
1117 if (!traffStatSaved.second.empty())
 
1119     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
 
1121         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
 
1122         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
 
1123         WriteServLog("%s", store->GetStrError().c_str());
 
1126     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
 
1132     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1136 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
 
1138 if (ts.size() && !disabledDetailStat)
 
1140     if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
 
1142         printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
 
1143         WriteServLog("Cannot write detail stat for user %s.", login.c_str());
 
1144         WriteServLog("%s", store->GetStrError().c_str());
 
1147             printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
 
1148             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1149             traffStatSaved.second.swap(ts);
 
1150             traffStatSaved.first = lastWriteDetailedStat;
 
1155 lastWriteDetailedStat = stgTime;
 
1158 //-----------------------------------------------------------------------------
 
1159 double USER_IMPL::GetPassiveTimePart() const
 
1161 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1163 static int daysInMonth[12] =
 
1164 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
1168 localtime_r(&t, &tms);
 
1170 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
 
1172 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
 
1175     secMonth += 24 * 3600;
 
1178 time_t dt = secMonth - passiveTime;
 
1183 return static_cast<double>(dt) / secMonth;
 
1185 //-----------------------------------------------------------------------------
 
1186 void USER_IMPL::SetPassiveTimeAsNewUser()
 
1188 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1192 localtime_r(&t, &tm);
 
1193 int daysCurrMon = DaysInCurrentMonth();
 
1194 double pt = tm.tm_mday - 1;
 
1197 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
 
1199 //-----------------------------------------------------------------------------
 
1200 void USER_IMPL::MidnightResetSessionStat()
 
1202 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1206     Disconnect(true, "fake");
 
1210 //-----------------------------------------------------------------------------
 
1211 void USER_IMPL::ProcessNewMonth()
 
1213 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1217     Disconnect(true, "fake");
 
1219 DIR_TRAFF zeroTarff;
 
1232 if (nextTariff.ConstData() != "")
 
1235     nt = tariffs->FindByName(nextTariff);
 
1238         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
 
1239                      login.c_str(), property.tariffName.Get().c_str());
 
1243         property.tariffName.Set(nextTariff, sysAdmin, login, store);
 
1250 //-----------------------------------------------------------------------------
 
1251 void USER_IMPL::ProcessDayFeeSpread()
 
1253 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1255 if (passive.ConstData() || tariff == NULL)
 
1258 double fee = tariff->GetFee() / DaysInCurrentMonth();
 
1260 if (std::fabs(fee) < 1.0e-3)
 
1264 switch (settings->GetFeeChargeType())
 
1267         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1270         if (c + credit >= 0)
 
1271             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1274         if (c + credit >= fee)
 
1275             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1279             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1284 //-----------------------------------------------------------------------------
 
1285 void USER_IMPL::ProcessDayFee()
 
1287 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1292 double passiveTimePart = 1.0;
 
1293 if (!settings->GetFullFee())
 
1295     passiveTimePart = GetPassiveTimePart();
 
1299     if (passive.ConstData())
 
1301         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
 
1305 double fee = tariff->GetFee() * passiveTimePart;
 
1309 if (std::fabs(fee) < 1.0e-3)
 
1316 printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
 
1323 switch (settings->GetFeeChargeType())
 
1326         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1330         if (c + credit >= 0)
 
1332             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1337         if (c + credit >= fee)
 
1339             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1346             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1352 //-----------------------------------------------------------------------------
 
1353 void USER_IMPL::SetPrepaidTraff()
 
1356     property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
 
1358 //-----------------------------------------------------------------------------
 
1359 int USER_IMPL::AddMessage(STG_MSG * msg)
 
1361 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1363 if (SendMessage(*msg))
 
1365     if (store->AddMessage(msg, login))
 
1367         errorStr = store->GetStrError();
 
1368         WriteServLog("Error adding message: '%s'", errorStr.c_str());
 
1369         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
 
1372     messages.push_back(*msg);
 
1376     if (msg->header.repeat > 0)
 
1378         msg->header.repeat--;
 
1380         //TODO: gcc v. 4.x generate ICE on x86_64
 
1381         msg->header.lastSendTime = static_cast<int>(time(NULL));
 
1383         msg->header.lastSendTime = static_cast<int>(stgTime);
 
1385         if (store->AddMessage(msg, login))
 
1387             errorStr = store->GetStrError();
 
1388             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
 
1389             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
 
1392         messages.push_back(*msg);
 
1397 //-----------------------------------------------------------------------------
 
1398 int USER_IMPL::SendMessage(STG_MSG & msg) const
 
1400 // No lock `cause we are already locked from caller
 
1402 std::set<const AUTH*>::iterator it(authorizedBy.begin());
 
1403 while (it != authorizedBy.end())
 
1405     if (!(*it++)->SendMessage(msg, currIP))
 
1411     //TODO: gcc v. 4.x generate ICE on x86_64
 
1412     msg.header.lastSendTime = static_cast<int>(time(NULL));
 
1414     msg.header.lastSendTime = static_cast<int>(stgTime);
 
1416     msg.header.repeat--;
 
1420 //-----------------------------------------------------------------------------
 
1421 void USER_IMPL::ScanMessage()
 
1423 // No lock `cause we are already locked from caller
 
1424 // We need not check for the authorizedBy `cause it has already checked by caller
 
1426 std::list<STG_MSG>::iterator it(messages.begin());
 
1427 while (it != messages.end())
 
1429     if (settings->GetMessageTimeout() > 0 &&
 
1430         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
 
1433         if (store->DelMessage(it->header.id, login))
 
1435             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1436             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1438         messages.erase(it++);
 
1441     if (it->GetNextSendTime() <= stgTime)
 
1443         if (SendMessage(*it))
 
1445             // We need to check all messages in queue for timeout
 
1449         if (it->header.repeat < 0)
 
1451             if (store->DelMessage(it->header.id, login))
 
1453                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1454                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1456             messages.erase(it++);
 
1460             if (store->EditMessage(*it, login))
 
1462                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
 
1463                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
 
1474 //-----------------------------------------------------------------------------
 
1475 std::string USER_IMPL::GetParamValue(const std::string & name) const
 
1477     return properties.GetPropertyValue(&name);
 
1478 //if (name == "freeMb")       return property.freeMb.ToString();
 
1479 //if (name == "passive")      return property.passive.ToString();
 
1480 //if (name == "disabled")     return property.disabled.ToString();
 
1481 //if (name == "alwaysOnline") return property.alwaysOnline.ToString();
 
1482 //if (name == "tariffName")   return property.tariffName;
 
1483 //if (name == "nextTariff")   return property.nextTariff;
 
1484 //if (name == "address")      return property.address;
 
1485 //if (name == "note")         return property.note;
 
1486 //if (name == "group")        return property.group;
 
1487 //if (name == "email")        return property.email;
 
1488 //if (name == "phone")        return property.phone;
 
1489 //if (name == "realName")     return property.realName;
 
1490 //if (name == "credit")       return property.credit.ToString();
 
1491 //if (name == "userdata0")    return property.userdata0;
 
1492 //if (name == "userdata1")    return property.userdata1;
 
1493 //if (name == "userdata2")    return property.userdata2;
 
1494 //if (name == "userdata3")    return property.userdata3;
 
1495 //if (name == "userdata4")    return property.userdata4;
 
1496 //if (name == "userdata5")    return property.userdata5;
 
1497 //if (name == "userdata6")    return property.userdata6;
 
1498 //if (name == "userdata7")    return property.userdata7;
 
1499 //if (name == "userdata8")    return property.userdata8;
 
1500 //if (name == "userdata9")    return property.userdata9;
 
1501 //if (name == "cash")         return property.cash.ToString();
 
1504 //    std::stringstream stream;
 
1506 //    return stream.str();;
 
1508 //if (name == "login")        return login;
 
1509 //if (name == "ip")           return currIP.ToString();
 
1512 //-----------------------------------------------------------------------------
 
1513 //-----------------------------------------------------------------------------
 
1514 //-----------------------------------------------------------------------------
 
1515 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
 
1517 if (newPassive && !oldPassive && user->tariff != NULL)
 
1518     user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
 
1524 //-----------------------------------------------------------------------------
 
1525 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
 
1527 if (oldValue && !newValue && user->GetConnected())
 
1529     user->Disconnect(false, "disabled");
 
1531 else if (!oldValue && newValue && user->IsInetable())
 
1533     user->Connect(false);
 
1537 //-----------------------------------------------------------------------------
 
1538 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
 
1540 if (user->settings->GetReconnectOnTariffChange() && user->connected)
 
1541     user->Disconnect(false, "Change tariff");
 
1542 user->tariff = user->tariffs->FindByName(newTariff);
 
1543 if (user->settings->GetReconnectOnTariffChange() &&
 
1544     !user->authorizedBy.empty() &&
 
1546     user->Connect(false);
 
1548 //-----------------------------------------------------------------------------
 
1549 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
 
1551 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
 
1552 user->lastCashAdd = newCash - oldCash;
 
1554 //-----------------------------------------------------------------------------
 
1555 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
 
1557     printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
 
1558     if (user->connected)
 
1559         user->Disconnect(false, "Change IP");
 
1560     if (!user->authorizedBy.empty() && user->IsInetable())
 
1561         user->Connect(false);
 
1563 //-----------------------------------------------------------------------------