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 += " \"";
 
 605             scriptOnConnectParams += GetParamValue(it->c_str());
 
 606             scriptOnConnectParams += "\"";
 
 609         ScriptExec(scriptOnConnectParams.c_str());
 
 613         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
 
 619 if (store->WriteUserConnect(login, currIP))
 
 621     WriteServLog("Cannot write connect for user %s.", login.c_str());
 
 622     WriteServLog("%s", store->GetStrError().c_str());
 
 626     lastIPForDisconnect = currIP;
 
 628 //-----------------------------------------------------------------------------
 
 629 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
 
 632  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
 
 635 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 637 if (!lastIPForDisconnect)
 
 639     printfd(__FILE__, "lastIPForDisconnect\n");
 
 645     std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
 
 647     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
 
 649         char dirsStr[DIR_NUM + 1];
 
 650         dirsStr[DIR_NUM] = 0;
 
 651         for (int i = 0; i < DIR_NUM; i++)
 
 653             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 656         std::string scriptOnDisonnectParams;
 
 657         strprintf(&scriptOnDisonnectParams,
 
 658                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 659                 scriptOnDisonnect.c_str(),
 
 661                 inet_ntostring(lastIPForDisconnect).c_str(),
 
 666         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
 
 667         while (it != settings->GetScriptParams().end())
 
 669             scriptOnDisonnectParams += " \"";
 
 670             scriptOnDisonnectParams += GetParamValue(it->c_str());
 
 671             scriptOnDisonnectParams += "\"";
 
 674         ScriptExec(scriptOnDisonnectParams.c_str());
 
 678         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
 
 684 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
 
 686     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
 
 687     WriteServLog("%s", store->GetStrError().c_str());
 
 691     lastIPForDisconnect = 0;
 
 693 DIR_TRAFF zeroSesssion;
 
 695 sessionUpload = zeroSesssion;
 
 696 sessionDownload = zeroSesssion;
 
 698 //-----------------------------------------------------------------------------
 
 699 void USER_IMPL::PrintUser() const
 
 702 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 703 std::cout << "============================================================" << std::endl;
 
 704 std::cout << "id=" << id << std::endl;
 
 705 std::cout << "login=" << login << std::endl;
 
 706 std::cout << "password=" << password << std::endl;
 
 707 std::cout << "passive=" << passive << std::endl;
 
 708 std::cout << "disabled=" << disabled << std::endl;
 
 709 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
 
 710 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
 
 711 std::cout << "tariffName=" << tariffName << std::endl;
 
 712 std::cout << "address=" << address << std::endl;
 
 713 std::cout << "phone=" << phone << std::endl;
 
 714 std::cout << "email=" << email << std::endl;
 
 715 std::cout << "note=" << note << std::endl;
 
 716 std::cout << "realName=" <<realName << std::endl;
 
 717 std::cout << "group=" << group << std::endl;
 
 718 std::cout << "credit=" << credit << std::endl;
 
 719 std::cout << "nextTariff=" << nextTariff << std::endl;
 
 720 std::cout << "userdata0" << userdata0 << std::endl;
 
 721 std::cout << "userdata1" << userdata1 << std::endl;
 
 722 std::cout << "creditExpire=" << creditExpire << std::endl;
 
 723 std::cout << "ips=" << ips << std::endl;
 
 724 std::cout << "------------------------" << std::endl;
 
 725 std::cout << "up=" << up << std::endl;
 
 726 std::cout << "down=" << down << std::endl;
 
 727 std::cout << "cash=" << cash << std::endl;
 
 728 std::cout << "freeMb=" << freeMb << std::endl;
 
 729 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
 
 730 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
 
 731 std::cout << "passiveTime=" << passiveTime << std::endl;
 
 732 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
 
 733 std::cout << "============================================================" << std::endl;
 
 735 //-----------------------------------------------------------------------------
 
 736 void USER_IMPL::Run()
 
 738 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 740 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
 
 742     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
 
 745 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
 
 747     WriteServLog("User: %s. Credit expired.", login.c_str());
 
 753 if (passive.ConstData()
 
 754     && (stgTime % 30 == 0)
 
 755     && (passiveTime.ModificationTime() != stgTime))
 
 757     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
 
 758     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
 
 761 if (!authorizedBy.empty())
 
 765         property.Stat().lastActivityTime = stgTime;
 
 767     if (!connected && IsInetable())
 
 771     if (connected && !IsInetable())
 
 774             Disconnect(false, "disabled");
 
 776             Disconnect(false, "passive");
 
 778             Disconnect(false, "no cash");
 
 781     if (stgTime - lastScanMessages > 10)
 
 784         lastScanMessages = stgTime;
 
 791         Disconnect(false, "not authorized");
 
 796 //-----------------------------------------------------------------------------
 
 797 void USER_IMPL::UpdatePingTime(time_t t)
 
 799 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 800 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
 
 806 //-----------------------------------------------------------------------------
 
 807 bool USER_IMPL::IsInetable()
 
 809 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 811 if (disabled || passive)
 
 814 if (settings->GetFreeMbAllowInet())
 
 820 if (settings->GetShowFeeInCash() || tariff == NULL)
 
 822     return (cash >= -credit);
 
 825 return (cash - tariff->GetFee() >= -credit);
 
 827 //-----------------------------------------------------------------------------
 
 828 std::string USER_IMPL::GetEnabledDirs()
 
 830 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 832 std::string dirs = "";
 
 833 for(int i = 0; i < DIR_NUM; i++)
 
 834     dirs += enabledDirs[i] ? "1" : "0";
 
 837 //-----------------------------------------------------------------------------
 
 838 #ifdef TRAFF_STAT_WITH_PORTS
 
 839 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 841 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
 
 844 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 846 if (!connected || tariff == NULL)
 
 852 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 853 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 857 int tt = tariff->GetTraffType();
 
 858 if (tt == TRAFF_UP ||
 
 859     tt == TRAFF_UP_DOWN ||
 
 860     // Check NEW traff data
 
 861     (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
 
 864     if (traff < threshold &&
 
 865         traff + len >= threshold)
 
 867         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 868         //        partAfterThreshold * priceAfterThreshold
 
 869         int64_t before = threshold - traff; // Chunk part before threshold
 
 870         int64_t after = len - before; // Chunk part after threshold
 
 871         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
 
 872                                            down.ConstData()[dir],
 
 875              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
 
 876                                            down.ConstData()[dir],
 
 882         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 883                                            down.ConstData()[dir],
 
 888     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 890     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 891         cost = dc - freeMb.ConstData();
 
 893     // Direct access to internal data structures via friend-specifier
 
 894     property.Stat().freeMb -= dc;
 
 895     property.Stat().cash -= cost;
 
 901 sessionUpload[dir] += len;
 
 905 if (!settings->GetWriteFreeMbTraffCost() &&
 
 906      freeMb.ConstData() >= 0)
 
 909 #ifdef TRAFF_STAT_WITH_PORTS
 
 910 IP_DIR_PAIR idp(ip, dir, port);
 
 912 IP_DIR_PAIR idp(ip, dir);
 
 915 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
 916 lb = traffStat.lower_bound(idp);
 
 917 if (lb == traffStat.end() || lb->first != idp)
 
 921                                     STAT_NODE(len, 0, cost)));
 
 925     lb->second.cash += cost;
 
 926     lb->second.up += len;
 
 929 //-----------------------------------------------------------------------------
 
 930 #ifdef TRAFF_STAT_WITH_PORTS
 
 931 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 933 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
 
 936 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 938 if (!connected || tariff == NULL)
 
 944 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 945 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 949 int tt = tariff->GetTraffType();
 
 950 if (tt == TRAFF_DOWN ||
 
 951     tt == TRAFF_UP_DOWN ||
 
 952     // Check NEW traff data
 
 953     (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
 
 956     if (traff < threshold &&
 
 957         traff + len >= threshold)
 
 959         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 960         //        partAfterThreshold * priceAfterThreshold
 
 961         int64_t before = threshold - traff; // Chunk part before threshold
 
 962         int64_t after = len - before; // Chunk part after threshold
 
 963         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 964                                            down.ConstData()[dir], // Traff before chunk
 
 967              tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 968                                            dt[dir], // Traff after chunk
 
 974         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 975                                            down.ConstData()[dir],
 
 980     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 982     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 983         cost = dc - freeMb.ConstData();
 
 985     property.Stat().freeMb -= dc;
 
 986     property.Stat().cash -= cost;
 
 992 sessionDownload[dir] += len;
 
 996 if (!settings->GetWriteFreeMbTraffCost() &&
 
 997      freeMb.ConstData() >= 0)
 
1000 #ifdef TRAFF_STAT_WITH_PORTS
 
1001 IP_DIR_PAIR idp(ip, dir, port);
 
1003 IP_DIR_PAIR idp(ip, dir);
 
1006 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
1007 lb = traffStat.lower_bound(idp);
 
1008 if (lb == traffStat.end() || lb->first != idp)
 
1010     traffStat.insert(lb,
 
1012                                     STAT_NODE(0, len, cost)));
 
1016     lb->second.cash += cost;
 
1017     lb->second.down += len;
 
1020 //-----------------------------------------------------------------------------
 
1021 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
 
1023 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1024 currIP.AddBeforeNotifier(notifier);
 
1026 //-----------------------------------------------------------------------------
 
1027 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
 
1029 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1030 currIP.DelBeforeNotifier(notifier);
 
1032 //-----------------------------------------------------------------------------
 
1033 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
 
1035 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1036 currIP.AddAfterNotifier(notifier);
 
1038 //-----------------------------------------------------------------------------
 
1039 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
 
1041 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1042 currIP.DelAfterNotifier(notifier);
 
1044 //-----------------------------------------------------------------------------
 
1045 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
 
1047 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1048 connected.AddBeforeNotifier(notifier);
 
1050 //-----------------------------------------------------------------------------
 
1051 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
 
1053 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1054 connected.DelBeforeNotifier(notifier);
 
1056 //-----------------------------------------------------------------------------
 
1057 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
 
1059 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1060 connected.AddAfterNotifier(notifier);
 
1062 //-----------------------------------------------------------------------------
 
1063 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
 
1065 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1066 connected.DelAfterNotifier(notifier);
 
1068 //-----------------------------------------------------------------------------
 
1069 void USER_IMPL::OnAdd()
 
1071 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1073 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
 
1075 if (access(scriptOnAdd.c_str(), X_OK) == 0)
 
1077     std::string scriptOnAddParams;
 
1078     strprintf(&scriptOnAddParams,
 
1080             scriptOnAdd.c_str(),
 
1083     ScriptExec(scriptOnAddParams.c_str());
 
1087     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
 
1090 //-----------------------------------------------------------------------------
 
1091 void USER_IMPL::OnDelete()
 
1093 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1095 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
 
1097 if (access(scriptOnDel.c_str(), X_OK) == 0)
 
1099     std::string scriptOnDelParams;
 
1100     strprintf(&scriptOnDelParams,
 
1102             scriptOnDel.c_str(),
 
1105     ScriptExec(scriptOnDelParams.c_str());
 
1109     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
 
1114 //-----------------------------------------------------------------------------
 
1115 int USER_IMPL::WriteDetailStat(bool hard)
 
1117 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
 
1119 if (!traffStatSaved.second.empty())
 
1121     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
 
1123         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
 
1124         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
 
1125         WriteServLog("%s", store->GetStrError().c_str());
 
1128     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
 
1134     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1138 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
 
1140 if (ts.size() && !disabledDetailStat)
 
1142     if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
 
1144         printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
 
1145         WriteServLog("Cannot write detail stat for user %s.", login.c_str());
 
1146         WriteServLog("%s", store->GetStrError().c_str());
 
1149             printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
 
1150             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1151             traffStatSaved.second.swap(ts);
 
1152             traffStatSaved.first = lastWriteDetailedStat;
 
1157 lastWriteDetailedStat = stgTime;
 
1160 //-----------------------------------------------------------------------------
 
1161 double USER_IMPL::GetPassiveTimePart() const
 
1163 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1165 static int daysInMonth[12] =
 
1166 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
1170 localtime_r(&t, &tms);
 
1172 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
 
1174 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
 
1177     secMonth += 24 * 3600;
 
1180 time_t dt = secMonth - passiveTime;
 
1185 return static_cast<double>(dt) / secMonth;
 
1187 //-----------------------------------------------------------------------------
 
1188 void USER_IMPL::SetPassiveTimeAsNewUser()
 
1190 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1194 localtime_r(&t, &tm);
 
1195 int daysCurrMon = DaysInCurrentMonth();
 
1196 double pt = tm.tm_mday - 1;
 
1199 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
 
1201 //-----------------------------------------------------------------------------
 
1202 void USER_IMPL::MidnightResetSessionStat()
 
1204 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1208     Disconnect(true, "fake");
 
1212 //-----------------------------------------------------------------------------
 
1213 void USER_IMPL::ProcessNewMonth()
 
1215 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1219     Disconnect(true, "fake");
 
1221 DIR_TRAFF zeroTarff;
 
1234 if (nextTariff.ConstData() != "")
 
1237     nt = tariffs->FindByName(nextTariff);
 
1240         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
 
1241                      login.c_str(), property.tariffName.Get().c_str());
 
1245         property.tariffName.Set(nextTariff, sysAdmin, login, store);
 
1252 //-----------------------------------------------------------------------------
 
1253 void USER_IMPL::ProcessDayFeeSpread()
 
1255 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1257 if (passive.ConstData() || tariff == NULL)
 
1260 double fee = tariff->GetFee() / DaysInCurrentMonth();
 
1262 if (std::fabs(fee) < 1.0e-3)
 
1266 switch (settings->GetFeeChargeType())
 
1269         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1272         if (c + credit >= 0)
 
1273             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1276         if (c + credit >= fee)
 
1277             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1281             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1286 //-----------------------------------------------------------------------------
 
1287 void USER_IMPL::ProcessDayFee()
 
1289 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1294 double passiveTimePart = 1.0;
 
1295 if (!settings->GetFullFee())
 
1297     passiveTimePart = GetPassiveTimePart();
 
1301     if (passive.ConstData())
 
1303         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
 
1307 double fee = tariff->GetFee() * passiveTimePart;
 
1311 if (std::fabs(fee) < 1.0e-3)
 
1318 printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
 
1325 switch (settings->GetFeeChargeType())
 
1328         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1332         if (c + credit >= 0)
 
1334             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1339         if (c + credit >= fee)
 
1341             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1348             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1354 //-----------------------------------------------------------------------------
 
1355 void USER_IMPL::SetPrepaidTraff()
 
1358     property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
 
1360 //-----------------------------------------------------------------------------
 
1361 int USER_IMPL::AddMessage(STG_MSG * msg)
 
1363 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1365 if (SendMessage(*msg))
 
1367     if (store->AddMessage(msg, login))
 
1369         errorStr = store->GetStrError();
 
1370         WriteServLog("Error adding message: '%s'", errorStr.c_str());
 
1371         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
 
1374     messages.push_back(*msg);
 
1378     if (msg->header.repeat > 0)
 
1380         msg->header.repeat--;
 
1382         //TODO: gcc v. 4.x generate ICE on x86_64
 
1383         msg->header.lastSendTime = static_cast<int>(time(NULL));
 
1385         msg->header.lastSendTime = static_cast<int>(stgTime);
 
1387         if (store->AddMessage(msg, login))
 
1389             errorStr = store->GetStrError();
 
1390             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
 
1391             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
 
1394         messages.push_back(*msg);
 
1399 //-----------------------------------------------------------------------------
 
1400 int USER_IMPL::SendMessage(STG_MSG & msg) const
 
1402 // No lock `cause we are already locked from caller
 
1404 std::set<const AUTH*>::iterator it(authorizedBy.begin());
 
1405 while (it != authorizedBy.end())
 
1407     if (!(*it++)->SendMessage(msg, currIP))
 
1413     //TODO: gcc v. 4.x generate ICE on x86_64
 
1414     msg.header.lastSendTime = static_cast<int>(time(NULL));
 
1416     msg.header.lastSendTime = static_cast<int>(stgTime);
 
1418     msg.header.repeat--;
 
1422 //-----------------------------------------------------------------------------
 
1423 void USER_IMPL::ScanMessage()
 
1425 // No lock `cause we are already locked from caller
 
1426 // We need not check for the authorizedBy `cause it has already checked by caller
 
1428 std::list<STG_MSG>::iterator it(messages.begin());
 
1429 while (it != messages.end())
 
1431     if (settings->GetMessageTimeout() > 0 &&
 
1432         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
 
1435         if (store->DelMessage(it->header.id, login))
 
1437             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1438             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1440         messages.erase(it++);
 
1443     if (it->GetNextSendTime() <= stgTime)
 
1445         if (SendMessage(*it))
 
1447             // We need to check all messages in queue for timeout
 
1451         if (it->header.repeat < 0)
 
1453             if (store->DelMessage(it->header.id, login))
 
1455                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1456                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1458             messages.erase(it++);
 
1462             if (store->EditMessage(*it, login))
 
1464                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
 
1465                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
 
1476 //-----------------------------------------------------------------------------
 
1477 std::string USER_IMPL::GetParamValue(const std::string & name) const
 
1479 if (name == "freeMb")       return property.freeMb.ToString();
 
1480 if (name == "passive")      return property.passive.ToString();
 
1481 if (name == "disabled")     return property.disabled.ToString();
 
1482 if (name == "alwaysOnline") return property.alwaysOnline.ToString();
 
1483 if (name == "tariffName")   return property.tariffName;
 
1484 if (name == "nextTariff")   return property.nextTariff;
 
1485 if (name == "address")      return property.address;
 
1486 if (name == "note")         return property.note;
 
1487 if (name == "group")        return property.group;
 
1488 if (name == "email")        return property.email;
 
1489 if (name == "phone")        return property.phone;
 
1490 if (name == "realName")     return property.realName;
 
1491 if (name == "credit")       return property.credit.ToString();
 
1492 if (name == "userdata0")    return property.userdata0;
 
1493 if (name == "userdata1")    return property.userdata1;
 
1494 if (name == "userdata2")    return property.userdata2;
 
1495 if (name == "userdata3")    return property.userdata3;
 
1496 if (name == "userdata4")    return property.userdata4;
 
1497 if (name == "userdata5")    return property.userdata5;
 
1498 if (name == "userdata6")    return property.userdata6;
 
1499 if (name == "userdata7")    return property.userdata7;
 
1500 if (name == "userdata8")    return property.userdata8;
 
1501 if (name == "userdata9")    return property.userdata9;
 
1502 //if (name == "cash")         return property.cash.ToString();
 
1505 //    std::stringstream stream;
 
1507 //    return stream.str();;
 
1509 //if (name == "login")        return login;
 
1510 //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 //-----------------------------------------------------------------------------