2  *    This program is free software; you can redistribute it and/or modify
 
   3  *    it under the terms of the GNU General Public License as published by
 
   4  *    the Free Software Foundation; either version 2 of the License, or
 
   5  *    (at your option) any later version.
 
   7  *    This program is distributed in the hope that it will be useful,
 
   8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  10  *    GNU General Public License for more details.
 
  12  *    You should have received a copy of the GNU General Public License
 
  13  *    along with this program; if not, write to the Free Software
 
  14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
  22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
 
  27  $Date: 2010/11/03 10:50:03 $
 
  36 #include <unistd.h> // access
 
  41 #include "stg/users.h"
 
  42 #include "stg/common.h"
 
  43 #include "stg/scriptexecuter.h"
 
  44 #include "stg/tariff.h"
 
  45 #include "stg/tariffs.h"
 
  46 #include "stg/admin.h"
 
  47 #include "user_impl.h"
 
  48 #include "settings_impl.h"
 
  49 #include "stg_timer.h"
 
  51 #ifdef USE_ABSTRACT_SETTINGS
 
  52 USER_IMPL::USER_IMPL(const SETTINGS * s,
 
  59       property(s->GetScriptsDir()),
 
  60       WriteServLog(GetStgLogger()),
 
  65       connected(__connected),
 
  70       lastIPForDisconnect(0),
 
  83       lastWriteDetailedStat(0),
 
  87       lastCashAdd(property.lastCashAdd),
 
  88       passiveTime(property.passiveTime),
 
  89       lastCashAddTime(property.lastCashAddTime),
 
  90       freeMb(property.freeMb),
 
  91       lastActivityTime(property.lastActivityTime),
 
  92       password(property.password),
 
  93       passive(property.passive),
 
  94       disabled(property.disabled),
 
  95       disabledDetailStat(property.disabledDetailStat),
 
  96       alwaysOnline(property.alwaysOnline),
 
  97       tariffName(property.tariffName),
 
  98       nextTariff(property.nextTariff),
 
  99       address(property.address),
 
 101       group(property.group),
 
 102       email(property.email),
 
 103       phone(property.phone),
 
 104       realName(property.realName),
 
 105       credit(property.credit),
 
 106       creditExpire(property.creditExpire),
 
 108       userdata0(property.userdata0),
 
 109       userdata1(property.userdata1),
 
 110       userdata2(property.userdata2),
 
 111       userdata3(property.userdata3),
 
 112       userdata4(property.userdata4),
 
 113       userdata5(property.userdata5),
 
 114       userdata6(property.userdata6),
 
 115       userdata7(property.userdata7),
 
 116       userdata8(property.userdata8),
 
 117       userdata9(property.userdata9),
 
 120       passiveNotifier(this),
 
 121       tariffNotifier(this),
 
 127 password = "*_EMPTY_PASSWORD_*";
 
 128 tariffName = NO_TARIFF_NAME;
 
 130 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
 
 131 lastWriteDetailedStat = stgTime;
 
 133 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 134 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 135 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 136 property.cash.AddBeforeNotifier(&cashNotifier);
 
 137 ips.AddAfterNotifier(&ipNotifier);
 
 139 pthread_mutexattr_t attr;
 
 140 pthread_mutexattr_init(&attr);
 
 141 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 142 pthread_mutex_init(&mutex, &attr);
 
 145 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
 
 152       property(s->GetScriptsDir()),
 
 153       WriteServLog(GetStgLogger()),
 
 158       connected(__connected),
 
 163       lastIPForDisconnect(0),
 
 176       lastWriteDetailedStat(0),
 
 180       lastCashAdd(property.lastCashAdd),
 
 181       passiveTime(property.passiveTime),
 
 182       lastCashAddTime(property.lastCashAddTime),
 
 183       freeMb(property.freeMb),
 
 184       lastActivityTime(property.lastActivityTime),
 
 185       password(property.password),
 
 186       passive(property.passive),
 
 187       disabled(property.disabled),
 
 188       disabledDetailStat(property.disabledDetailStat),
 
 189       alwaysOnline(property.alwaysOnline),
 
 190       tariffName(property.tariffName),
 
 191       nextTariff(property.nextTariff),
 
 192       address(property.address),
 
 194       group(property.group),
 
 195       email(property.email),
 
 196       phone(property.phone),
 
 197       realName(property.realName),
 
 198       credit(property.credit),
 
 199       creditExpire(property.creditExpire),
 
 201       userdata0(property.userdata0),
 
 202       userdata1(property.userdata1),
 
 203       userdata2(property.userdata2),
 
 204       userdata3(property.userdata3),
 
 205       userdata4(property.userdata4),
 
 206       userdata5(property.userdata5),
 
 207       userdata6(property.userdata6),
 
 208       userdata7(property.userdata7),
 
 209       userdata8(property.userdata8),
 
 210       userdata9(property.userdata9),
 
 213       passiveNotifier(this),
 
 214       disabledNotifier(this),
 
 215       tariffNotifier(this),
 
 221 password = "*_EMPTY_PASSWORD_*";
 
 222 tariffName = NO_TARIFF_NAME;
 
 224 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
 
 225 lastWriteDetailedStat = stgTime;
 
 227 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 228 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 229 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 230 property.cash.AddBeforeNotifier(&cashNotifier);
 
 231 ips.AddAfterNotifier(&ipNotifier);
 
 233 pthread_mutexattr_t attr;
 
 234 pthread_mutexattr_init(&attr);
 
 235 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 236 pthread_mutex_init(&mutex, &attr);
 
 239 //-----------------------------------------------------------------------------
 
 240 USER_IMPL::USER_IMPL(const USER_IMPL & u)
 
 243       property(u.settings->GetScriptsDir()),
 
 244       WriteServLog(GetStgLogger()),
 
 249       connected(__connected),
 
 251       userIDGenerator(u.userIDGenerator),
 
 252       __currIP(u.__currIP),
 
 254       lastIPForDisconnect(0),
 
 255       pingTime(u.pingTime),
 
 256       sysAdmin(u.sysAdmin),
 
 260       traffStat(u.traffStat),
 
 261       traffStatSaved(u.traffStatSaved),
 
 262       settings(u.settings),
 
 264       messages(u.messages),
 
 266       lastWriteStat(u.lastWriteStat),
 
 267       lastWriteDetailedStat(u.lastWriteDetailedStat),
 
 271       lastCashAdd(property.lastCashAdd),
 
 272       passiveTime(property.passiveTime),
 
 273       lastCashAddTime(property.lastCashAddTime),
 
 274       freeMb(property.freeMb),
 
 275       lastActivityTime(property.lastActivityTime),
 
 276       password(property.password),
 
 277       passive(property.passive),
 
 278       disabled(property.disabled),
 
 279       disabledDetailStat(property.disabledDetailStat),
 
 280       alwaysOnline(property.alwaysOnline),
 
 281       tariffName(property.tariffName),
 
 282       nextTariff(property.nextTariff),
 
 283       address(property.address),
 
 285       group(property.group),
 
 286       email(property.email),
 
 287       phone(property.phone),
 
 288       realName(property.realName),
 
 289       credit(property.credit),
 
 290       creditExpire(property.creditExpire),
 
 292       userdata0(property.userdata0),
 
 293       userdata1(property.userdata1),
 
 294       userdata2(property.userdata2),
 
 295       userdata3(property.userdata3),
 
 296       userdata4(property.userdata4),
 
 297       userdata5(property.userdata5),
 
 298       userdata6(property.userdata6),
 
 299       userdata7(property.userdata7),
 
 300       userdata8(property.userdata8),
 
 301       userdata9(property.userdata9),
 
 304       passiveNotifier(this),
 
 305       disabledNotifier(this),
 
 306       tariffNotifier(this),
 
 315 property.tariffName.AddBeforeNotifier(&tariffNotifier);
 
 316 property.passive.AddBeforeNotifier(&passiveNotifier);
 
 317 property.disabled.AddAfterNotifier(&disabledNotifier);
 
 318 property.cash.AddBeforeNotifier(&cashNotifier);
 
 319 ips.AddAfterNotifier(&ipNotifier);
 
 321 property.SetProperties(u.property);
 
 323 pthread_mutexattr_t attr;
 
 324 pthread_mutexattr_init(&attr);
 
 325 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
 326 pthread_mutex_init(&mutex, &attr);
 
 328 //-----------------------------------------------------------------------------
 
 329 USER_IMPL::~USER_IMPL()
 
 331 property.tariffName.DelBeforeNotifier(&tariffNotifier);
 
 332 property.passive.DelBeforeNotifier(&passiveNotifier);
 
 333 property.disabled.DelAfterNotifier(&disabledNotifier);
 
 334 property.cash.DelBeforeNotifier(&cashNotifier);
 
 335 pthread_mutex_destroy(&mutex);
 
 337 //-----------------------------------------------------------------------------
 
 338 void USER_IMPL::SetLogin(string const & l)
 
 340 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 341 assert(login.empty() && "Login is already set");
 
 343 id = userIDGenerator.GetNextID();
 
 345 //-----------------------------------------------------------------------------
 
 346 int USER_IMPL::ReadConf()
 
 348 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 351 if (store->RestoreUserConf(&conf, login))
 
 353     WriteServLog("Cannot read conf for user %s.", login.c_str());
 
 354     WriteServLog("%s", store->GetStrError().c_str());
 
 355     printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
 
 356     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 360 property.SetConf(conf);
 
 362 tariff = tariffs->FindByName(tariffName);
 
 365     WriteServLog("Cannot read user %s. Tariff %s not exist.",
 
 366                  login.c_str(), property.tariffName.Get().c_str());
 
 370 std::vector<STG_MSG_HDR> hdrsList;
 
 372 if (store->GetMessageHdrs(&hdrsList, login))
 
 374     printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
 
 375     WriteServLog("Cannot read user %s. Error reading message headers: %s.",
 
 377                  store->GetStrError().c_str());
 
 381 std::vector<STG_MSG_HDR>::const_iterator it;
 
 382 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
 
 385     if (store->GetMessage(it->id, &msg, login) == 0)
 
 387         messages.push_back(msg);
 
 393 //-----------------------------------------------------------------------------
 
 394 int USER_IMPL::ReadStat()
 
 396 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 399 if (store->RestoreUserStat(&stat, login))
 
 401     WriteServLog("Cannot read stat for user %s.", login.c_str());
 
 402     WriteServLog("%s", store->GetStrError().c_str());
 
 403     printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
 
 404     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 408 property.SetStat(stat);
 
 412 //-----------------------------------------------------------------------------
 
 413 int USER_IMPL::WriteConf()
 
 415 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 416 USER_CONF conf(property.GetConf());
 
 418 printfd(__FILE__, "USER::WriteConf()\n");
 
 420 if (store->SaveUserConf(conf, login))
 
 422     WriteServLog("Cannot write conf for user %s.", login.c_str());
 
 423     WriteServLog("%s", store->GetStrError().c_str());
 
 424     printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
 
 425     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 431 //-----------------------------------------------------------------------------
 
 432 int USER_IMPL::WriteStat()
 
 434 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 435 USER_STAT stat(property.GetStat());
 
 437 if (store->SaveUserStat(stat, login))
 
 439     WriteServLog("Cannot write stat for user %s.", login.c_str());
 
 440     WriteServLog("%s", store->GetStrError().c_str());
 
 441     printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
 
 442     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 446 lastWriteStat = stgTime;
 
 450 //-----------------------------------------------------------------------------
 
 451 int USER_IMPL::WriteMonthStat()
 
 453 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 454 time_t tt = stgTime - 3600;
 
 456 localtime_r(&tt, &t1);
 
 458 USER_STAT stat(property.GetStat());
 
 459 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
 
 461     WriteServLog("Cannot write month stat for user %s.", login.c_str());
 
 462     WriteServLog("%s", store->GetStrError().c_str());
 
 463     printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
 
 464     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
 
 470 //-----------------------------------------------------------------------------
 
 471 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
 
 473 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 475  *  Authorize user. It only means that user will be authorized. Nothing more.
 
 476  *  User can be connected or disconnected while authorized.
 
 477  *  Example: user is authorized but disconnected due to 0 money or blocking
 
 481  * Prevent double authorization by identical authorizers
 
 483 if (authorizedBy.find(auth) != authorizedBy.end())
 
 489 for (int i = 0; i < DIR_NUM; i++)
 
 491     enabledDirs[i] = dirs & (1 << i);
 
 494 if (!authorizedBy.empty())
 
 498         //  We are already authorized, but with different IP address
 
 499         errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
 
 504     if (!users->FindByIPIdx(ip, &u))
 
 506         //  Address is already present in IP-index
 
 507         //  If it's not our IP - throw an error
 
 510             errorStr = "IP address " + inet_ntostring(ip) + " already in use";
 
 517     if (users->IsIPInIndex(ip))
 
 519         //  Address is already present in IP-index
 
 520         errorStr = "IP address " + inet_ntostring(ip) + " already in use";
 
 524     if (ips.ConstData().IsIPInIPS(ip))
 
 527         lastIPForDisconnect = currIP;
 
 531         printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
 
 532         errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
 
 537 authorizedBy.insert(auth);
 
 543 //-----------------------------------------------------------------------------
 
 544 void USER_IMPL::Unauthorize(const AUTH * auth)
 
 546 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 548  *  Authorizer tries to unauthorize user, that was not authorized by it
 
 550 if (!authorizedBy.erase(auth))
 
 553 if (authorizedBy.empty())
 
 555     lastIPForDisconnect = currIP;
 
 556     currIP = 0; // DelUser in traffcounter
 
 560 //-----------------------------------------------------------------------------
 
 561 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
 
 563 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 564 //  Is this user authorized by specified authorizer?
 
 565 return authorizedBy.find(auth) != authorizedBy.end();
 
 567 //-----------------------------------------------------------------------------
 
 568 void USER_IMPL::Connect(bool fakeConnect)
 
 571  *  Connect user to Internet. This function is differ from Authorize() !!!
 
 574 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 578     string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
 
 580     if (access(scriptOnConnect.c_str(), X_OK) == 0)
 
 582         char dirsStr[DIR_NUM + 1];
 
 583         dirsStr[DIR_NUM] = 0;
 
 584         for (int i = 0; i < DIR_NUM; i++)
 
 586             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 589         string scriptOnConnectParams;
 
 590         strprintf(&scriptOnConnectParams,
 
 591                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 592                 scriptOnConnect.c_str(),
 
 594                 inet_ntostring(currIP).c_str(),
 
 599         ScriptExec(scriptOnConnectParams.c_str());
 
 603         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
 
 609 if (store->WriteUserConnect(login, currIP))
 
 611     WriteServLog("Cannot write connect for user %s.", login.c_str());
 
 612     WriteServLog("%s", store->GetStrError().c_str());
 
 616     lastIPForDisconnect = currIP;
 
 618 //-----------------------------------------------------------------------------
 
 619 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
 
 622  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
 
 625 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 627 if (!lastIPForDisconnect)
 
 629     printfd(__FILE__, "lastIPForDisconnect\n");
 
 635     string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
 
 637     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
 
 639         char dirsStr[DIR_NUM + 1];
 
 640         dirsStr[DIR_NUM] = 0;
 
 641         for (int i = 0; i < DIR_NUM; i++)
 
 643             dirsStr[i] = enabledDirs[i] ? '1' : '0';
 
 646         string scriptOnDisonnectParams;
 
 647         strprintf(&scriptOnDisonnectParams,
 
 648                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
 
 649                 scriptOnDisonnect.c_str(),
 
 651                 inet_ntostring(lastIPForDisconnect).c_str(),
 
 656         ScriptExec(scriptOnDisonnectParams.c_str());
 
 660         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
 
 666 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
 
 668     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
 
 669     WriteServLog("%s", store->GetStrError().c_str());
 
 673     lastIPForDisconnect = 0;
 
 675 DIR_TRAFF zeroSesssion;
 
 677 sessionUpload = zeroSesssion;
 
 678 sessionDownload = zeroSesssion;
 
 680 //-----------------------------------------------------------------------------
 
 681 void USER_IMPL::PrintUser() const
 
 684 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 685 cout << "============================================================" << endl;
 
 686 cout << "id=" << id << endl;
 
 687 cout << "login=" << login << endl;
 
 688 cout << "password=" << password << endl;
 
 689 cout << "passive=" << passive << endl;
 
 690 cout << "disabled=" << disabled << endl;
 
 691 cout << "disabledDetailStat=" << disabledDetailStat << endl;
 
 692 cout << "alwaysOnline=" << alwaysOnline << endl;
 
 693 cout << "tariffName=" << tariffName << endl;
 
 694 cout << "address=" << address << endl;
 
 695 cout << "phone=" << phone << endl;
 
 696 cout << "email=" << email << endl;
 
 697 cout << "note=" << note << endl;
 
 698 cout << "realName=" <<realName << endl;
 
 699 cout << "group=" << group << endl;
 
 700 cout << "credit=" << credit << endl;
 
 701 cout << "nextTariff=" << nextTariff << endl;
 
 702 cout << "userdata0" << userdata0 << endl;
 
 703 cout << "userdata1" << userdata1 << endl;
 
 704 cout << "creditExpire=" << creditExpire << endl;
 
 705 cout << "ips=" << ips << endl;
 
 706 cout << "------------------------" << endl;
 
 707 cout << "up=" << up << endl;
 
 708 cout << "down=" << down << endl;
 
 709 cout << "cash=" << cash << endl;
 
 710 cout << "freeMb=" << freeMb << endl;
 
 711 cout << "lastCashAdd=" << lastCashAdd << endl;
 
 712 cout << "lastCashAddTime=" << lastCashAddTime << endl;
 
 713 cout << "passiveTime=" << passiveTime << endl;
 
 714 cout << "lastActivityTime=" << lastActivityTime << endl;
 
 715 cout << "============================================================" << endl;
 
 717 //-----------------------------------------------------------------------------
 
 718 void USER_IMPL::Run()
 
 720 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 722 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
 
 724     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
 
 727 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
 
 729     WriteServLog("User: %s. Credit expired.", login.c_str());
 
 735 if (passive.ConstData()
 
 736     && (stgTime % 30 == 0)
 
 737     && (passiveTime.ModificationTime() != stgTime))
 
 739     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
 
 740     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
 
 743 if (!authorizedBy.empty())
 
 747         property.Stat().lastActivityTime = stgTime;
 
 749     if (!connected && IsInetable())
 
 753     if (connected && !IsInetable())
 
 756             Disconnect(false, "disabled");
 
 758             Disconnect(false, "passive");
 
 760             Disconnect(false, "no cash");
 
 763     if (stgTime - lastScanMessages > 10)
 
 766         lastScanMessages = stgTime;
 
 773         Disconnect(false, "not authorized");
 
 778 //-----------------------------------------------------------------------------
 
 779 void USER_IMPL::UpdatePingTime(time_t t)
 
 781 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 782 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
 
 788 //-----------------------------------------------------------------------------
 
 789 bool USER_IMPL::IsInetable()
 
 791 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 793 if (disabled || passive)
 
 796 if (settings->GetFreeMbAllowInet())
 
 802 if (settings->GetShowFeeInCash() || tariff == NULL)
 
 804     return (cash >= -credit);
 
 807 return (cash - tariff->GetFee() >= -credit);
 
 809 //-----------------------------------------------------------------------------
 
 810 string USER_IMPL::GetEnabledDirs()
 
 812 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 815 for(int i = 0; i < DIR_NUM; i++)
 
 816     dirs += enabledDirs[i] ? "1" : "0";
 
 819 //-----------------------------------------------------------------------------
 
 820 #ifdef TRAFF_STAT_WITH_PORTS
 
 821 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 823 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
 
 826 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 828 if (!connected || tariff == NULL)
 
 834 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 835 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 839 int tt = tariff->GetTraffType();
 
 840 if (tt == TRAFF_UP ||
 
 841     tt == TRAFF_UP_DOWN ||
 
 842     // Check NEW traff data
 
 843     (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
 
 846     if (traff < threshold &&
 
 847         traff + len >= threshold)
 
 849         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 850         //        partAfterThreshold * priceAfterThreshold
 
 851         int64_t before = threshold - traff; // Chunk part before threshold
 
 852         int64_t after = len - before; // Chunk part after threshold
 
 853         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
 
 854                                            down.ConstData()[dir],
 
 857              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
 
 858                                            down.ConstData()[dir],
 
 864         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 865                                            down.ConstData()[dir],
 
 870     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 872     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 873         cost = dc - freeMb.ConstData();
 
 875     // Direct access to internal data structures via friend-specifier
 
 876     property.Stat().freeMb -= dc;
 
 877     property.Stat().cash -= cost;
 
 883 sessionUpload[dir] += len;
 
 887 if (!settings->GetWriteFreeMbTraffCost() &&
 
 888      freeMb.ConstData() >= 0)
 
 891 #ifdef TRAFF_STAT_WITH_PORTS
 
 892 IP_DIR_PAIR idp(ip, dir, port);
 
 894 IP_DIR_PAIR idp(ip, dir);
 
 897 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
 898 lb = traffStat.lower_bound(idp);
 
 899 if (lb == traffStat.end() || lb->first != idp)
 
 902                      pair<IP_DIR_PAIR, STAT_NODE>(idp,
 
 903                                                   STAT_NODE(len, 0, cost)));
 
 907     lb->second.cash += cost;
 
 908     lb->second.up += len;
 
 911 //-----------------------------------------------------------------------------
 
 912 #ifdef TRAFF_STAT_WITH_PORTS
 
 913 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
 
 915 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
 
 918 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 920 if (!connected || tariff == NULL)
 
 926 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
 
 927 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
 
 931 int tt = tariff->GetTraffType();
 
 932 if (tt == TRAFF_DOWN ||
 
 933     tt == TRAFF_UP_DOWN ||
 
 934     // Check NEW traff data
 
 935     (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
 
 938     if (traff < threshold &&
 
 939         traff + len >= threshold)
 
 941         // cash = partBeforeThreshold * priceBeforeThreshold +
 
 942         //        partAfterThreshold * priceAfterThreshold
 
 943         int64_t before = threshold - traff; // Chunk part before threshold
 
 944         int64_t after = len - before; // Chunk part after threshold
 
 945         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 946                                            down.ConstData()[dir], // Traff before chunk
 
 949              tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 950                                            dt[dir], // Traff after chunk
 
 956         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
 
 957                                            down.ConstData()[dir],
 
 962     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
 
 964     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
 
 965         cost = dc - freeMb.ConstData();
 
 967     property.Stat().freeMb -= dc;
 
 968     property.Stat().cash -= cost;
 
 974 sessionDownload[dir] += len;
 
 978 if (!settings->GetWriteFreeMbTraffCost() &&
 
 979      freeMb.ConstData() >= 0)
 
 982 #ifdef TRAFF_STAT_WITH_PORTS
 
 983 IP_DIR_PAIR idp(ip, dir, port);
 
 985 IP_DIR_PAIR idp(ip, dir);
 
 988 map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
 
 989 lb = traffStat.lower_bound(idp);
 
 990 if (lb == traffStat.end() || lb->first != idp)
 
 993                      pair<IP_DIR_PAIR, STAT_NODE>(idp,
 
 994                                                   STAT_NODE(0, len, cost)));
 
 998     lb->second.cash += cost;
 
 999     lb->second.down += len;
 
1002 //-----------------------------------------------------------------------------
 
1003 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
 
1005 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1006 currIP.AddBeforeNotifier(notifier);
 
1008 //-----------------------------------------------------------------------------
 
1009 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
 
1011 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1012 currIP.DelBeforeNotifier(notifier);
 
1014 //-----------------------------------------------------------------------------
 
1015 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
 
1017 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1018 currIP.AddAfterNotifier(notifier);
 
1020 //-----------------------------------------------------------------------------
 
1021 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
 
1023 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1024 currIP.DelAfterNotifier(notifier);
 
1026 //-----------------------------------------------------------------------------
 
1027 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
 
1029 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1030 connected.AddBeforeNotifier(notifier);
 
1032 //-----------------------------------------------------------------------------
 
1033 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
 
1035 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1036 connected.DelBeforeNotifier(notifier);
 
1038 //-----------------------------------------------------------------------------
 
1039 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
 
1041 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1042 connected.AddAfterNotifier(notifier);
 
1044 //-----------------------------------------------------------------------------
 
1045 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
 
1047 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1048 connected.DelAfterNotifier(notifier);
 
1050 //-----------------------------------------------------------------------------
 
1051 void USER_IMPL::OnAdd()
 
1053 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1055 string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
 
1057 if (access(scriptOnAdd.c_str(), X_OK) == 0)
 
1059     string scriptOnAddParams;
 
1060     strprintf(&scriptOnAddParams,
 
1062             scriptOnAdd.c_str(),
 
1065     ScriptExec(scriptOnAddParams.c_str());
 
1069     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
 
1072 //-----------------------------------------------------------------------------
 
1073 void USER_IMPL::OnDelete()
 
1075 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1077 string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
 
1079 if (access(scriptOnDel.c_str(), X_OK) == 0)
 
1081     string scriptOnDelParams;
 
1082     strprintf(&scriptOnDelParams,
 
1084             scriptOnDel.c_str(),
 
1087     ScriptExec(scriptOnDelParams.c_str());
 
1091     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
 
1096 //-----------------------------------------------------------------------------
 
1097 int USER_IMPL::WriteDetailStat(bool hard)
 
1099 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
 
1101 if (!traffStatSaved.second.empty())
 
1103     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
 
1105         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
 
1106         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
 
1107         WriteServLog("%s", store->GetStrError().c_str());
 
1110     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
 
1116     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1120 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
 
1122 if (ts.size() && !disabledDetailStat)
 
1124     if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
 
1126         printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
 
1127         WriteServLog("Cannot write detail stat for user %s.", login.c_str());
 
1128         WriteServLog("%s", store->GetStrError().c_str());
 
1131             printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
 
1132             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1133             traffStatSaved.second.swap(ts);
 
1134             traffStatSaved.first = lastWriteDetailedStat;
 
1139 lastWriteDetailedStat = stgTime;
 
1142 //-----------------------------------------------------------------------------
 
1143 double USER_IMPL::GetPassiveTimePart() const
 
1145 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1147 static int daysInMonth[12] =
 
1148 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
1152 localtime_r(&t, &tms);
 
1154 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
 
1156 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
 
1159     secMonth += 24 * 3600;
 
1162 int dt = secMonth - passiveTime;
 
1167 return double(dt) / (secMonth);
 
1169 //-----------------------------------------------------------------------------
 
1170 void USER_IMPL::SetPassiveTimeAsNewUser()
 
1172 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1176 localtime_r(&t, &tm);
 
1177 int daysCurrMon = DaysInCurrentMonth();
 
1178 double pt = (tm.tm_mday - 1) / (double)daysCurrMon;
 
1180 passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
 
1182 //-----------------------------------------------------------------------------
 
1183 void USER_IMPL::MidnightResetSessionStat()
 
1185 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1189     Disconnect(true, "fake");
 
1193 //-----------------------------------------------------------------------------
 
1194 void USER_IMPL::ProcessNewMonth()
 
1196 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1200     Disconnect(true, "fake");
 
1202 DIR_TRAFF zeroTarff;
 
1215 if (nextTariff.ConstData() != "")
 
1218     nt = tariffs->FindByName(nextTariff);
 
1221         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
 
1222                      login.c_str(), property.tariffName.Get().c_str());
 
1226         property.tariffName.Set(nextTariff, sysAdmin, login, store);
 
1233 //-----------------------------------------------------------------------------
 
1234 void USER_IMPL::ProcessDayFeeSpread()
 
1236 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1238 if (passive.ConstData() || tariff == NULL)
 
1241 double fee = tariff->GetFee() / DaysInCurrentMonth();
 
1247 switch (settings->GetFeeChargeType())
 
1250         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1253         if (c + credit >= 0)
 
1254             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1257         if (c + credit >= fee)
 
1258             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1262             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1267 //-----------------------------------------------------------------------------
 
1268 void USER_IMPL::ProcessDayFee()
 
1270 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1275 double passiveTimePart = 1.0;
 
1276 if (!settings->GetFullFee())
 
1278     passiveTimePart = GetPassiveTimePart();
 
1282     if (passive.ConstData())
 
1284         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
 
1288 double fee = tariff->GetFee() * passiveTimePart;
 
1299 printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
 
1306 switch (settings->GetFeeChargeType())
 
1309         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1313         if (c + credit >= 0)
 
1315             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1320         if (c + credit >= fee)
 
1322             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1329             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
 
1335 //-----------------------------------------------------------------------------
 
1336 void USER_IMPL::SetPrepaidTraff()
 
1339     property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
 
1341 //-----------------------------------------------------------------------------
 
1342 int USER_IMPL::AddMessage(STG_MSG * msg)
 
1344 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
1346 if (SendMessage(*msg))
 
1348     if (store->AddMessage(msg, login))
 
1350         errorStr = store->GetStrError();
 
1351         WriteServLog("Error adding message: '%s'", errorStr.c_str());
 
1352         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
 
1355     messages.push_back(*msg);
 
1359     if (msg->header.repeat > 0)
 
1361         msg->header.repeat--;
 
1363         //TODO: gcc v. 4.x generate ICE on x86_64
 
1364         msg->header.lastSendTime = time(NULL);
 
1366         msg->header.lastSendTime = stgTime;
 
1368         if (store->AddMessage(msg, login))
 
1370             errorStr = store->GetStrError();
 
1371             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
 
1372             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
 
1375         messages.push_back(*msg);
 
1380 //-----------------------------------------------------------------------------
 
1381 int USER_IMPL::SendMessage(STG_MSG & msg) const
 
1383 // No lock `cause we are already locked from caller
 
1385 set<const AUTH*>::iterator it(authorizedBy.begin());
 
1386 while (it != authorizedBy.end())
 
1388     if (!(*it++)->SendMessage(msg, currIP))
 
1394     //TODO: gcc v. 4.x generate ICE on x86_64
 
1395     msg.header.lastSendTime = time(NULL);
 
1397     msg.header.lastSendTime = stgTime;
 
1399     msg.header.repeat--;
 
1403 //-----------------------------------------------------------------------------
 
1404 void USER_IMPL::ScanMessage()
 
1406 // No lock `cause we are already locked from caller
 
1407 // We need not check for the authorizedBy `cause it has already checked by caller
 
1409 std::list<STG_MSG>::iterator it(messages.begin());
 
1410 while (it != messages.end())
 
1412     if (settings->GetMessageTimeout() > 0 &&
 
1413         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
 
1416         if (store->DelMessage(it->header.id, login))
 
1418             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1419             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1421         messages.erase(it++);
 
1424     if (it->GetNextSendTime() <= stgTime)
 
1426         if (SendMessage(*it))
 
1428             // We need to check all messages in queue for timeout
 
1432         if (it->header.repeat < 0)
 
1434             if (store->DelMessage(it->header.id, login))
 
1436                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
 
1437                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
 
1439             messages.erase(it++);
 
1443             if (store->EditMessage(*it, login))
 
1445                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
 
1446                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
 
1457 //-----------------------------------------------------------------------------
 
1458 //-----------------------------------------------------------------------------
 
1459 //-----------------------------------------------------------------------------
 
1460 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
 
1462 if (newPassive && !oldPassive && user->tariff != NULL)
 
1463     user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
 
1469 //-----------------------------------------------------------------------------
 
1470 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
 
1472 if (oldValue && !newValue && user->GetConnected())
 
1474     user->Disconnect(false, "disabled");
 
1476 else if (!oldValue && newValue && user->IsInetable())
 
1478     user->Connect(false);
 
1482 //-----------------------------------------------------------------------------
 
1483 void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
 
1485 if (user->settings->GetReconnectOnTariffChange() && user->connected)
 
1486     user->Disconnect(false, "Change tariff");
 
1487 user->tariff = user->tariffs->FindByName(newTariff);
 
1488 if (user->settings->GetReconnectOnTariffChange() &&
 
1489     !user->authorizedBy.empty() &&
 
1491     user->Connect(false);
 
1493 //-----------------------------------------------------------------------------
 
1494 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
 
1496 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
 
1497 user->lastCashAdd = newCash - oldCash;
 
1499 //-----------------------------------------------------------------------------
 
1500 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
 
1502     printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
 
1503     if (user->connected)
 
1504         user->Disconnect(false, "Change IP");
 
1505     if (!user->authorizedBy.empty() && user->IsInetable())
 
1506         user->Connect(false);
 
1508 //-----------------------------------------------------------------------------