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 $
 
  35 #include "user_impl.h"
 
  36 #include "settings_impl.h"
 
  37 #include "stg_timer.h"
 
  39 #include "stg/users.h"
 
  40 #include "stg/common.h"
 
  41 #include "stg/scriptexecuter.h"
 
  42 #include "stg/tariff.h"
 
  43 #include "stg/tariffs.h"
 
  44 #include "stg/admin.h"
 
  54 #include <unistd.h> // access
 
  56 #ifdef USE_ABSTRACT_SETTINGS
 
  57 USER_IMPL::USER_IMPL(const SETTINGS * s,
 
  64       property(s->GetScriptsDir()),
 
  65       WriteServLog(GetStgLogger()),
 
  69       connected(__connected),
 
  72       lastIPForDisconnect(0),
 
  79       authorizedModificationTime(0),
 
  82       lastWriteDetailedStat(0),
 
  86       lastCashAdd(property.lastCashAdd),
 
  87       passiveTime(property.passiveTime),
 
  88       lastCashAddTime(property.lastCashAddTime),
 
  89       freeMb(property.freeMb),
 
  90       lastActivityTime(property.lastActivityTime),
 
  91       password(property.password),
 
  92       passive(property.passive),
 
  93       disabled(property.disabled),
 
  94       disabledDetailStat(property.disabledDetailStat),
 
  95       alwaysOnline(property.alwaysOnline),
 
  96       tariffName(property.tariffName),
 
  97       nextTariff(property.nextTariff),
 
  98       address(property.address),
 
 100       group(property.group),
 
 101       email(property.email),
 
 102       phone(property.phone),
 
 103       realName(property.realName),
 
 104       credit(property.credit),
 
 105       creditExpire(property.creditExpire),
 
 107       userdata0(property.userdata0),
 
 108       userdata1(property.userdata1),
 
 109       userdata2(property.userdata2),
 
 110       userdata3(property.userdata3),
 
 111       userdata4(property.userdata4),
 
 112       userdata5(property.userdata5),
 
 113       userdata6(property.userdata6),
 
 114       userdata7(property.userdata7),
 
 115       userdata8(property.userdata8),
 
 116       userdata9(property.userdata9),
 
 117       passiveNotifier(this),
 
 118       tariffNotifier(this),
 
 122 password = "*_EMPTY_PASSWORD_*";
 
 123 tariffName = NO_TARIFF_NAME;
 
 125 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
 
 126 lastWriteDetailedStat = stgTime;
 
 128 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 129 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 130 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 131 property.cash.AddBeforeNotifier(&cashNotifier);
 
 132 ips.AddAfterNotifier(&ipNotifier);
 
 134 pthread_mutexattr_t attr;
 
 135 pthread_mutexattr_init(&attr);
 
 136 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 137 pthread_mutex_init(&mutex, &attr);
 
 140 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
 
 147       property(s->GetScriptsDir()),
 
 148       WriteServLog(GetStgLogger()),
 
 152       connected(__connected),
 
 155       lastIPForDisconnect(0),
 
 162       authorizedModificationTime(0),
 
 165       lastWriteDetailedStat(0),
 
 169       lastCashAdd(property.lastCashAdd),
 
 170       passiveTime(property.passiveTime),
 
 171       lastCashAddTime(property.lastCashAddTime),
 
 172       freeMb(property.freeMb),
 
 173       lastActivityTime(property.lastActivityTime),
 
 174       password(property.password),
 
 175       passive(property.passive),
 
 176       disabled(property.disabled),
 
 177       disabledDetailStat(property.disabledDetailStat),
 
 178       alwaysOnline(property.alwaysOnline),
 
 179       tariffName(property.tariffName),
 
 180       nextTariff(property.nextTariff),
 
 181       address(property.address),
 
 183       group(property.group),
 
 184       email(property.email),
 
 185       phone(property.phone),
 
 186       realName(property.realName),
 
 187       credit(property.credit),
 
 188       creditExpire(property.creditExpire),
 
 190       userdata0(property.userdata0),
 
 191       userdata1(property.userdata1),
 
 192       userdata2(property.userdata2),
 
 193       userdata3(property.userdata3),
 
 194       userdata4(property.userdata4),
 
 195       userdata5(property.userdata5),
 
 196       userdata6(property.userdata6),
 
 197       userdata7(property.userdata7),
 
 198       userdata8(property.userdata8),
 
 199       userdata9(property.userdata9),
 
 200       passiveNotifier(this),
 
 201       disabledNotifier(this),
 
 202       tariffNotifier(this),
 
 206 password = "*_EMPTY_PASSWORD_*";
 
 207 tariffName = NO_TARIFF_NAME;
 
 209 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
 
 210 lastWriteDetailedStat = stgTime;
 
 212 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 213 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 214 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 215 property.cash.AddBeforeNotifier(&cashNotifier);
 
 216 ips.AddAfterNotifier(&ipNotifier);
 
 218 pthread_mutexattr_t attr;
 
 219 pthread_mutexattr_init(&attr);
 
 220 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 221 pthread_mutex_init(&mutex, &attr);
 
 224 //-----------------------------------------------------------------------------
 
 225 USER_IMPL::USER_IMPL(const USER_IMPL & u)
 
 228       property(u.settings->GetScriptsDir()),
 
 229       WriteServLog(GetStgLogger()),
 
 234       connected(__connected),
 
 235       userIDGenerator(u.userIDGenerator),
 
 236       __currIP(u.__currIP),
 
 238       lastIPForDisconnect(0),
 
 239       pingTime(u.pingTime),
 
 240       sysAdmin(u.sysAdmin),
 
 244       traffStat(u.traffStat),
 
 245       traffStatSaved(u.traffStatSaved),
 
 246       settings(u.settings),
 
 247       authorizedModificationTime(u.authorizedModificationTime),
 
 248       messages(u.messages),
 
 250       lastWriteStat(u.lastWriteStat),
 
 251       lastWriteDetailedStat(u.lastWriteDetailedStat),
 
 255       lastCashAdd(property.lastCashAdd),
 
 256       passiveTime(property.passiveTime),
 
 257       lastCashAddTime(property.lastCashAddTime),
 
 258       freeMb(property.freeMb),
 
 259       lastActivityTime(property.lastActivityTime),
 
 260       password(property.password),
 
 261       passive(property.passive),
 
 262       disabled(property.disabled),
 
 263       disabledDetailStat(property.disabledDetailStat),
 
 264       alwaysOnline(property.alwaysOnline),
 
 265       tariffName(property.tariffName),
 
 266       nextTariff(property.nextTariff),
 
 267       address(property.address),
 
 269       group(property.group),
 
 270       email(property.email),
 
 271       phone(property.phone),
 
 272       realName(property.realName),
 
 273       credit(property.credit),
 
 274       creditExpire(property.creditExpire),
 
 276       userdata0(property.userdata0),
 
 277       userdata1(property.userdata1),
 
 278       userdata2(property.userdata2),
 
 279       userdata3(property.userdata3),
 
 280       userdata4(property.userdata4),
 
 281       userdata5(property.userdata5),
 
 282       userdata6(property.userdata6),
 
 283       userdata7(property.userdata7),
 
 284       userdata8(property.userdata8),
 
 285       userdata9(property.userdata9),
 
 288       passiveNotifier(this),
 
 289       disabledNotifier(this),
 
 290       tariffNotifier(this),
 
 297 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 298 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 299 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 300 property.cash.AddBeforeNotifier(&cashNotifier);
 
 301 ips.AddAfterNotifier(&ipNotifier);
 
 303 property.SetProperties(u.property);
 
 305 pthread_mutexattr_t attr;
 
 306 pthread_mutexattr_init(&attr);
 
 307 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 308 pthread_mutex_init(&mutex, &attr);
 
 310 //-----------------------------------------------------------------------------
 
 311 USER_IMPL::~USER_IMPL()
 
 313 property.tariffName.DelBeforeNotifier(&tariffNotifier);
 
 314 property.passive.DelBeforeNotifier(&passiveNotifier);
 
 315 property.disabled.DelAfterNotifier(&disabledNotifier);
 
 316 property.cash.DelBeforeNotifier(&cashNotifier);
 
 317 pthread_mutex_destroy(&mutex);
 
 319 //-----------------------------------------------------------------------------
 
 320 void USER_IMPL::SetLogin(const std::string & l)
 
 322 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 323 assert(login.empty() && "Login is already set");
 
 325 id = userIDGenerator.GetNextID();
 
 327 //-----------------------------------------------------------------------------
 
 328 int USER_IMPL::ReadConf()
 
 330 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 333 if (store->RestoreUserConf(&conf, login))
 
 335     WriteServLog("Cannot read conf for user %s.", login.c_str());
 
 336     WriteServLog("%s", store->GetStrError().c_str());
 
 337     printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
 
 338     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 342 property.SetConf(conf);
 
 344 tariff = tariffs->FindByName(tariffName);
 
 347     WriteServLog("Cannot read user %s. Tariff %s not exist.",
 
 348                  login.c_str(), property.tariffName.Get().c_str());
 
 352 std::vector<STG_MSG_HDR> hdrsList;
 
 354 if (store->GetMessageHdrs(&hdrsList, login))
 
 356     printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
 
 357     WriteServLog("Cannot read user %s. Error reading message headers: %s.",
 
 359                  store->GetStrError().c_str());
 
 363 std::vector<STG_MSG_HDR>::const_iterator it;
 
 364 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
 
 367     if (store->GetMessage(it->id, &msg, login) == 0)
 
 369         messages.push_back(msg);
 
 375 //-----------------------------------------------------------------------------
 
 376 int USER_IMPL::ReadStat()
 
 378 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 381 if (store->RestoreUserStat(&stat, login))
 
 383     WriteServLog("Cannot read stat for user %s.", login.c_str());
 
 384     WriteServLog("%s", store->GetStrError().c_str());
 
 385     printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
 
 386     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 390 property.SetStat(stat);
 
 394 //-----------------------------------------------------------------------------
 
 395 int USER_IMPL::WriteConf()
 
 397 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 398 USER_CONF conf(property.GetConf());
 
 400 printfd(__FILE__, "USER::WriteConf()\n");
 
 402 if (store->SaveUserConf(conf, login))
 
 404     WriteServLog("Cannot write conf for user %s.", login.c_str());
 
 405     WriteServLog("%s", store->GetStrError().c_str());
 
 406     printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
 
 407     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 413 //-----------------------------------------------------------------------------
 
 414 int USER_IMPL::WriteStat()
 
 416 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 417 USER_STAT stat(property.GetStat());
 
 419 if (store->SaveUserStat(stat, login))
 
 421     WriteServLog("Cannot write stat for user %s.", login.c_str());
 
 422     WriteServLog("%s", store->GetStrError().c_str());
 
 423     printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
 
 424     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 428 lastWriteStat = stgTime;
 
 432 //-----------------------------------------------------------------------------
 
 433 int USER_IMPL::WriteMonthStat()
 
 435 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 436 time_t tt = stgTime - 3600;
 
 438 localtime_r(&tt, &t1);
 
 440 USER_STAT stat(property.GetStat());
 
 441 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
 
 443     WriteServLog("Cannot write month stat for user %s.", login.c_str());
 
 444     WriteServLog("%s", store->GetStrError().c_str());
 
 445     printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
 
 446     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 452 //-----------------------------------------------------------------------------
 
 453 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
 
 455 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 457  *  Authorize user. It only means that user will be authorized. Nothing more.
 
 458  *  User can be connected or disconnected while authorized.
 
 459  *  Example: user is authorized but disconnected due to 0 money or blocking
 
 463  * Prevent double authorization by identical authorizers
 
 465 if (authorizedBy.find(auth) != authorizedBy.end())
 
 471 for (int i = 0; i < DIR_NUM; i++)
 
 473     enabledDirs[i] = dirs & (1 << i);
 
 476 if (!authorizedBy.empty())
 
 480         //  We are already authorized, but with different IP address
 
 481         errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
 
 486     if (!users->FindByIPIdx(ip, &u))
 
 488         //  Address is already present in IP-index
 
 489         //  If it's not our IP - throw an error
 
 492             errorStr = "IP address " + inet_ntostring(ip) + " already in use";
 
 499     if (users->IsIPInIndex(ip))
 
 501         //  Address is already present in IP-index
 
 502         errorStr = "IP address " + inet_ntostring(ip) + " already in use";
 
 506     if (ips.ConstData().IsIPInIPS(ip))
 
 509         lastIPForDisconnect = currIP;
 
 513         printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
 
 514         errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
 
 519 if (authorizedBy.empty())
 
 520     authorizedModificationTime = stgTime;
 
 521 authorizedBy.insert(auth);
 
 527 //-----------------------------------------------------------------------------
 
 528 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
 
 530 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 532  *  Authorizer tries to unauthorize user, that was not authorized by it
 
 534 if (!authorizedBy.erase(auth))
 
 537 if (authorizedBy.empty())
 
 539     authorizedModificationTime = stgTime;
 
 540     lastDisconnectReason = reason;
 
 541     lastIPForDisconnect = currIP;
 
 542     currIP = 0; // DelUser in traffcounter
 
 546 //-----------------------------------------------------------------------------
 
 547 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
 
 549 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 550 //  Is this user authorized by specified authorizer?
 
 551 return authorizedBy.find(auth) != authorizedBy.end();
 
 553 //-----------------------------------------------------------------------------
 
 554 std::vector<std::string> USER_IMPL::GetAuthorizers() const
 
 556     std::vector<std::string> list;
 
 557     std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
 
 560 //-----------------------------------------------------------------------------
 
 561 void USER_IMPL::Connect(bool fakeConnect)
 
 564  *  Connect user to Internet. This function is differ from Authorize() !!!
 
 567 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 571     std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
 
 573     if (access(scriptOnConnect.c_str(), X_OK) == 0)
 
 575         char dirsStr[DIR_NUM + 1];
 
 576         dirsStr[DIR_NUM] = 0;
 
 577         for (int i = 0; i < DIR_NUM; i++)
 
 579             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 582         std::string scriptOnConnectParams;
 
 584         strprintf(&scriptOnConnectParams,
 
 585                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 586                 scriptOnConnect.c_str(),
 
 588                 inet_ntostring(currIP).c_str(),
 
 593         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
 
 594         while (it != settings->GetScriptParams().end())
 
 596             scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
 
 600         ScriptExec(scriptOnConnectParams.c_str());
 
 604         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
 
 610 if (store->WriteUserConnect(login, currIP))
 
 612     WriteServLog("Cannot write connect for user %s.", login.c_str());
 
 613     WriteServLog("%s", store->GetStrError().c_str());
 
 617     lastIPForDisconnect = currIP;
 
 619 //-----------------------------------------------------------------------------
 
 620 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
 
 623  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
 
 626 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 628 if (!lastIPForDisconnect)
 
 630     printfd(__FILE__, "lastIPForDisconnect\n");
 
 636     lastDisconnectReason = reason;
 
 637     std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
 
 639     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
 
 641         char dirsStr[DIR_NUM + 1];
 
 642         dirsStr[DIR_NUM] = 0;
 
 643         for (int i = 0; i < DIR_NUM; i++)
 
 645             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 648         std::string scriptOnDisonnectParams;
 
 649         strprintf(&scriptOnDisonnectParams,
 
 650                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 651                 scriptOnDisonnect.c_str(),
 
 653                 inet_ntostring(lastIPForDisconnect).c_str(),
 
 658         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
 
 659         while (it != settings->GetScriptParams().end())
 
 661             scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
 
 665         ScriptExec(scriptOnDisonnectParams.c_str());
 
 669         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
 
 675 std::string reasonMessage(reason);
 
 676 if (!lastDisconnectReason.empty())
 
 677     reasonMessage += ": " + lastDisconnectReason;
 
 679 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
 
 680                                cash, freeMb, reasonMessage))
 
 682     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
 
 683     WriteServLog("%s", store->GetStrError().c_str());
 
 687     lastIPForDisconnect = 0;
 
 689 DIR_TRAFF zeroSesssion;
 
 691 sessionUpload = zeroSesssion;
 
 692 sessionDownload = zeroSesssion;
 
 694 //-----------------------------------------------------------------------------
 
 695 void USER_IMPL::PrintUser() const
 
 698 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 699 std::cout << "============================================================" << std::endl;
 
 700 std::cout << "id=" << id << std::endl;
 
 701 std::cout << "login=" << login << std::endl;
 
 702 std::cout << "password=" << password << std::endl;
 
 703 std::cout << "passive=" << passive << std::endl;
 
 704 std::cout << "disabled=" << disabled << std::endl;
 
 705 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
 
 706 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
 
 707 std::cout << "tariffName=" << tariffName << std::endl;
 
 708 std::cout << "address=" << address << std::endl;
 
 709 std::cout << "phone=" << phone << std::endl;
 
 710 std::cout << "email=" << email << std::endl;
 
 711 std::cout << "note=" << note << std::endl;
 
 712 std::cout << "realName=" <<realName << std::endl;
 
 713 std::cout << "group=" << group << std::endl;
 
 714 std::cout << "credit=" << credit << std::endl;
 
 715 std::cout << "nextTariff=" << nextTariff << std::endl;
 
 716 std::cout << "userdata0" << userdata0 << std::endl;
 
 717 std::cout << "userdata1" << userdata1 << std::endl;
 
 718 std::cout << "creditExpire=" << creditExpire << std::endl;
 
 719 std::cout << "ips=" << ips << std::endl;
 
 720 std::cout << "------------------------" << std::endl;
 
 721 std::cout << "up=" << up << std::endl;
 
 722 std::cout << "down=" << down << std::endl;
 
 723 std::cout << "cash=" << cash << std::endl;
 
 724 std::cout << "freeMb=" << freeMb << std::endl;
 
 725 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
 
 726 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
 
 727 std::cout << "passiveTime=" << passiveTime << std::endl;
 
 728 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
 
 729 std::cout << "============================================================" << std::endl;
 
 731 //-----------------------------------------------------------------------------
 
 732 void USER_IMPL::Run()
 
 734 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 736 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
 
 738     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
 
 741 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
 
 743     WriteServLog("User: %s. Credit expired.", login.c_str());
 
 749 if (passive.ConstData()
 
 750     && (stgTime % 30 == 0)
 
 751     && (passiveTime.ModificationTime() != stgTime))
 
 753     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
 
 754     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
 
 757 if (!authorizedBy.empty())
 
 761         property.Stat().lastActivityTime = stgTime;
 
 763     if (!connected && IsInetable())
 
 767     if (connected && !IsInetable())
 
 770             Disconnect(false, "disabled");
 
 772             Disconnect(false, "passive");
 
 774             Disconnect(false, "no cash");
 
 777     if (stgTime - lastScanMessages > 10)
 
 780         lastScanMessages = stgTime;
 
 787         Disconnect(false, "not authorized");
 
 792 //-----------------------------------------------------------------------------
 
 793 void USER_IMPL::UpdatePingTime(time_t t)
 
 795 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 796 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
 
 802 //-----------------------------------------------------------------------------
 
 803 bool USER_IMPL::IsInetable()
 
 805 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 807 if (disabled || passive)
 
 810 if (settings->GetFreeMbAllowInet())
 
 816 if (settings->GetShowFeeInCash() || tariff == NULL)
 
 818     return (cash >= -credit);
 
 821 return (cash - tariff->GetFee() >= -credit);
 
 823 //-----------------------------------------------------------------------------
 
 824 std::string USER_IMPL::GetEnabledDirs() const
 
 826 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 828 std::string dirs = "";
 
 829 for(int i = 0; i < DIR_NUM; i++)
 
 830     dirs += enabledDirs[i] ? "1" : "0";
 
 833 //-----------------------------------------------------------------------------
 
 834 #ifdef TRAFF_STAT_WITH_PORTS
 
 835 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 837 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
 
 840 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 842 if (!connected || tariff == NULL)
 
 848 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 849 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 853 int tt = tariff->GetTraffType();
 
 854 if (tt == TRAFF_UP ||
 
 855     tt == TRAFF_UP_DOWN ||
 
 856     // Check NEW traff data
 
 857     (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
 
 860     if (traff < threshold &&
 
 861         traff + len >= threshold)
 
 863         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 864         //        partAfterThreshold * priceAfterThreshold
 
 865         int64_t before = threshold - traff; // Chunk part before threshold
 
 866         int64_t after = len - before; // Chunk part after threshold
 
 867         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
 
 868                                            down.ConstData()[dir],
 
 871              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
 
 872                                            down.ConstData()[dir],
 
 878         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 879                                            down.ConstData()[dir],
 
 884     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 886     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 887         cost = dc - freeMb.ConstData();
 
 889     // Direct access to internal data structures via friend-specifier
 
 890     property.Stat().freeMb -= dc;
 
 891     property.Stat().cash -= cost;
 
 897 sessionUpload[dir] += len;
 
 901 if (!settings->GetWriteFreeMbTraffCost() &&
 
 902      freeMb.ConstData() >= 0)
 
 905 #ifdef TRAFF_STAT_WITH_PORTS
 
 906 IP_DIR_PAIR idp(ip, dir, port);
 
 908 IP_DIR_PAIR idp(ip, dir);
 
 911 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
 912 lb = traffStat.lower_bound(idp);
 
 913 if (lb == traffStat.end() || lb->first != idp)
 
 917                                     STAT_NODE(len, 0, cost)));
 
 921     lb->second.cash += cost;
 
 922     lb->second.up += len;
 
 925 //-----------------------------------------------------------------------------
 
 926 #ifdef TRAFF_STAT_WITH_PORTS
 
 927 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 929 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
 
 932 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 934 if (!connected || tariff == NULL)
 
 940 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 941 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 945 int tt = tariff->GetTraffType();
 
 946 if (tt == TRAFF_DOWN ||
 
 947     tt == TRAFF_UP_DOWN ||
 
 948     // Check NEW traff data
 
 949     (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
 
 952     if (traff < threshold &&
 
 953         traff + len >= threshold)
 
 955         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 956         //        partAfterThreshold * priceAfterThreshold
 
 957         int64_t before = threshold - traff; // Chunk part before threshold
 
 958         int64_t after = len - before; // Chunk part after threshold
 
 959         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 960                                            down.ConstData()[dir], // Traff before chunk
 
 963              tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 964                                            dt[dir], // Traff after chunk
 
 970         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 971                                            down.ConstData()[dir],
 
 976     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 978     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 979         cost = dc - freeMb.ConstData();
 
 981     property.Stat().freeMb -= dc;
 
 982     property.Stat().cash -= cost;
 
 988 sessionDownload[dir] += len;
 
 992 if (!settings->GetWriteFreeMbTraffCost() &&
 
 993      freeMb.ConstData() >= 0)
 
 996 #ifdef TRAFF_STAT_WITH_PORTS
 
 997 IP_DIR_PAIR idp(ip, dir, port);
 
 999 IP_DIR_PAIR idp(ip, dir);
 
1002 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
1003 lb = traffStat.lower_bound(idp);
 
1004 if (lb == traffStat.end() || lb->first != idp)
 
1006     traffStat.insert(lb,
 
1008                                     STAT_NODE(0, len, cost)));
 
1012     lb->second.cash += cost;
 
1013     lb->second.down += len;
 
1016 //-----------------------------------------------------------------------------
 
1017 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
 
1019 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1020 currIP.AddBeforeNotifier(notifier);
 
1022 //-----------------------------------------------------------------------------
 
1023 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
 
1025 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1026 currIP.DelBeforeNotifier(notifier);
 
1028 //-----------------------------------------------------------------------------
 
1029 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
 
1031 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1032 currIP.AddAfterNotifier(notifier);
 
1034 //-----------------------------------------------------------------------------
 
1035 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
 
1037 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1038 currIP.DelAfterNotifier(notifier);
 
1040 //-----------------------------------------------------------------------------
 
1041 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
 
1043 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1044 connected.AddBeforeNotifier(notifier);
 
1046 //-----------------------------------------------------------------------------
 
1047 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
 
1049 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1050 connected.DelBeforeNotifier(notifier);
 
1052 //-----------------------------------------------------------------------------
 
1053 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
 
1055 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1056 connected.AddAfterNotifier(notifier);
 
1058 //-----------------------------------------------------------------------------
 
1059 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
 
1061 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1062 connected.DelAfterNotifier(notifier);
 
1064 //-----------------------------------------------------------------------------
 
1065 void USER_IMPL::OnAdd()
 
1067 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1069 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
 
1071 if (access(scriptOnAdd.c_str(), X_OK) == 0)
 
1073     std::string scriptOnAddParams;
 
1074     strprintf(&scriptOnAddParams,
 
1076             scriptOnAdd.c_str(),
 
1079     ScriptExec(scriptOnAddParams.c_str());
 
1083     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
 
1086 //-----------------------------------------------------------------------------
 
1087 void USER_IMPL::OnDelete()
 
1089 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1091 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
 
1093 if (access(scriptOnDel.c_str(), X_OK) == 0)
 
1095     std::string scriptOnDelParams;
 
1096     strprintf(&scriptOnDelParams,
 
1098             scriptOnDel.c_str(),
 
1101     ScriptExec(scriptOnDelParams.c_str());
 
1105     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
 
1110 //-----------------------------------------------------------------------------
 
1111 int USER_IMPL::WriteDetailStat(bool hard)
 
1113 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
 
1115 if (!traffStatSaved.second.empty())
 
1117     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
 
1119         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
 
1120         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
 
1121         WriteServLog("%s", store->GetStrError().c_str());
 
1124     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
 
1130     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1134 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
 
1136 if (ts.size() && !disabledDetailStat)
 
1138     if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
 
1140         printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
 
1141         WriteServLog("Cannot write detail stat for user %s.", login.c_str());
 
1142         WriteServLog("%s", store->GetStrError().c_str());
 
1145             printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
 
1146             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1147             traffStatSaved.second.swap(ts);
 
1148             traffStatSaved.first = lastWriteDetailedStat;
 
1153 lastWriteDetailedStat = stgTime;
 
1156 //-----------------------------------------------------------------------------
 
1157 double USER_IMPL::GetPassiveTimePart() const
 
1159 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1161 static int daysInMonth[12] =
 
1162 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
1166 localtime_r(&t, &tms);
 
1168 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
 
1170 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
 
1173     secMonth += 24 * 3600;
 
1176 time_t dt = secMonth - passiveTime;
 
1181 return static_cast<double>(dt) / secMonth;
 
1183 //-----------------------------------------------------------------------------
 
1184 void USER_IMPL::SetPassiveTimeAsNewUser()
 
1186 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1190 localtime_r(&t, &tm);
 
1191 int daysCurrMon = DaysInCurrentMonth();
 
1192 double pt = tm.tm_mday - 1;
 
1195 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
 
1197 //-----------------------------------------------------------------------------
 
1198 void USER_IMPL::MidnightResetSessionStat()
 
1200 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1204     Disconnect(true, "fake");
 
1208 //-----------------------------------------------------------------------------
 
1209 void USER_IMPL::ProcessNewMonth()
 
1211 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1215     Disconnect(true, "fake");
 
1217 DIR_TRAFF zeroTarff;
 
1230 if (nextTariff.ConstData() != "")
 
1233     nt = tariffs->FindByName(nextTariff);
 
1236         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
 
1237                      login.c_str(), property.tariffName.Get().c_str());
 
1241         property.tariffName.Set(nextTariff, sysAdmin, login, store);
 
1248 //-----------------------------------------------------------------------------
 
1249 void USER_IMPL::ProcessDayFeeSpread()
 
1251 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1253 if (passive.ConstData() || tariff == NULL)
 
1256 if (tariff->GetPeriod() != TARIFF::MONTH)
 
1259 double fee = tariff->GetFee() / DaysInCurrentMonth();
 
1261 if (std::fabs(fee) < 1.0e-3)
 
1265 switch (settings->GetFeeChargeType())
 
1268         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1271         if (c + credit >= 0)
 
1272             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1275         if (c + credit >= fee)
 
1276             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1280             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1285 //-----------------------------------------------------------------------------
 
1286 void USER_IMPL::ProcessDayFee()
 
1288 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1293 if (tariff->GetPeriod() != TARIFF::MONTH)
 
1296 double passiveTimePart = 1.0;
 
1297 if (!settings->GetFullFee())
 
1299     passiveTimePart = GetPassiveTimePart();
 
1303     if (passive.ConstData())
 
1305         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
 
1309 double fee = tariff->GetFee() * passiveTimePart;
 
1313 if (std::fabs(fee) < 1.0e-3)
 
1320 printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
 
1327 switch (settings->GetFeeChargeType())
 
1330         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1334         if (c + credit >= 0)
 
1336             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1341         if (c + credit >= fee)
 
1343             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1350             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1356 //-----------------------------------------------------------------------------
 
1357 void USER_IMPL::ProcessDailyFee()
 
1359 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1361 if (passive.ConstData() || tariff == NULL)
 
1364 if (tariff->GetPeriod() != TARIFF::DAY)
 
1367 double fee = tariff->GetFee();
 
1373 switch (settings->GetFeeChargeType())
 
1376         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1379         if (c + credit >= 0)
 
1380             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1383         if (c + credit >= fee)
 
1384             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1389 //-----------------------------------------------------------------------------
 
1390 void USER_IMPL::SetPrepaidTraff()
 
1393     property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
 
1395 //-----------------------------------------------------------------------------
 
1396 int USER_IMPL::AddMessage(STG_MSG * msg)
 
1398 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1400 if (SendMessage(*msg))
 
1402     if (store->AddMessage(msg, login))
 
1404         errorStr = store->GetStrError();
 
1405         WriteServLog("Error adding message: '%s'", errorStr.c_str());
 
1406         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
 
1409     messages.push_back(*msg);
 
1413     if (msg->header.repeat > 0)
 
1415         msg->header.repeat--;
 
1417         //TODO: gcc v. 4.x generate ICE on x86_64
 
1418         msg->header.lastSendTime = static_cast<int>(time(NULL));
 
1420         msg->header.lastSendTime = static_cast<int>(stgTime);
 
1422         if (store->AddMessage(msg, login))
 
1424             errorStr = store->GetStrError();
 
1425             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
 
1426             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
 
1429         messages.push_back(*msg);
 
1434 //-----------------------------------------------------------------------------
 
1435 int USER_IMPL::SendMessage(STG_MSG & msg) const
 
1437 // No lock `cause we are already locked from caller
 
1439 std::set<const AUTH*>::iterator it(authorizedBy.begin());
 
1440 while (it != authorizedBy.end())
 
1442     if (!(*it++)->SendMessage(msg, currIP))
 
1448     //TODO: gcc v. 4.x generate ICE on x86_64
 
1449     msg.header.lastSendTime = static_cast<int>(time(NULL));
 
1451     msg.header.lastSendTime = static_cast<int>(stgTime);
 
1453     msg.header.repeat--;
 
1457 //-----------------------------------------------------------------------------
 
1458 void USER_IMPL::ScanMessage()
 
1460 // No lock `cause we are already locked from caller
 
1461 // We need not check for the authorizedBy `cause it has already checked by caller
 
1463 std::list<STG_MSG>::iterator it(messages.begin());
 
1464 while (it != messages.end())
 
1466     if (settings->GetMessageTimeout() > 0 &&
 
1467         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
 
1470         if (store->DelMessage(it->header.id, login))
 
1472             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1473             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1475         messages.erase(it++);
 
1478     if (it->GetNextSendTime() <= stgTime)
 
1480         if (SendMessage(*it))
 
1482             // We need to check all messages in queue for timeout
 
1486         if (it->header.repeat < 0)
 
1488             if (store->DelMessage(it->header.id, login))
 
1490                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1491                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1493             messages.erase(it++);
 
1497             if (store->EditMessage(*it, login))
 
1499                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
 
1500                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
 
1511 //-----------------------------------------------------------------------------
 
1512 std::string USER_IMPL::GetParamValue(const std::string & name) const
 
1514     std::string lowerName = ToLower(name);
 
1515     if (lowerName == "id")
 
1517         std::ostringstream stream;
 
1519         return stream.str();
 
1521     if (lowerName == "login")       return login;
 
1522     if (lowerName == "currip")      return currIP.ToString();
 
1523     if (lowerName == "enableddirs") return GetEnabledDirs();
 
1524     if (lowerName == "tariff")      return property.tariffName;
 
1525     if (property.Exists(lowerName))
 
1526         return property.GetPropertyValue(lowerName);
 
1529         WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
 
1533 //-----------------------------------------------------------------------------
 
1534 //-----------------------------------------------------------------------------
 
1535 //-----------------------------------------------------------------------------
 
1536 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
 
1538 if (newPassive && !oldPassive && user->tariff != NULL)
 
1539     user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
 
1545 //-----------------------------------------------------------------------------
 
1546 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
 
1548 if (oldValue && !newValue && user->GetConnected())
 
1550     user->Disconnect(false, "disabled");
 
1552 else if (!oldValue && newValue && user->IsInetable())
 
1554     user->Connect(false);
 
1558 //-----------------------------------------------------------------------------
 
1559 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
 
1561 if (user->settings->GetReconnectOnTariffChange() && user->connected)
 
1562     user->Disconnect(false, "Change tariff");
 
1563 user->tariff = user->tariffs->FindByName(newTariff);
 
1564 if (user->settings->GetReconnectOnTariffChange() &&
 
1565     !user->authorizedBy.empty() &&
 
1567     user->Connect(false);
 
1569 //-----------------------------------------------------------------------------
 
1570 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
 
1572 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
 
1573 user->lastCashAdd = newCash - oldCash;
 
1575 //-----------------------------------------------------------------------------
 
1576 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
 
1578     printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
 
1579     if (user->connected)
 
1580         user->Disconnect(false, "Change IP");
 
1581     if (!user->authorizedBy.empty() && user->IsInetable())
 
1582         user->Connect(false);
 
1584 //-----------------------------------------------------------------------------