X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/6f7160dd027c8ce7e2760aa369768ba39ab80181..73bee151e048054bde9a39c5ad2efec25af9c77b:/projects/stargazer/user_impl.cpp diff --git a/projects/stargazer/user_impl.cpp b/projects/stargazer/user_impl.cpp index f18dd76e..7116a11e 100644 --- a/projects/stargazer/user_impl.cpp +++ b/projects/stargazer/user_impl.cpp @@ -32,97 +32,128 @@ #define _GNU_SOURCE #endif +#include "user_impl.h" +#include "settings_impl.h" +#include "stg_timer.h" + +#include "stg/users.h" +#include "stg/common.h" +#include "stg/scriptexecuter.h" +#include "stg/tariff.h" +#include "stg/tariffs.h" +#include "stg/services.h" +#include "stg/service_conf.h" +#include "stg/admin.h" + +#include +#include +#include + +#include +#include +#include + #include #include // access -#include +using STG::UserImpl; -#include "user_impl.h" -#include "users.h" -#include "common.h" -#include "settings.h" -#include "script_executer.h" -#include "tariff.h" -#include "tariffs.h" -#include "admin.h" - -USER_IMPL::USER_IMPL(const SETTINGS * s, - const BASE_STORE * st, - const TARIFFS * t, - const ADMIN & a, - const USERS * u) +namespace +{ + +std::string dirsToString(const bool * dirs) +{ +std::string res; +for (size_t i = 0; i < DIR_NUM; i++) + res += dirs[i] ? '1' : '0'; +return res; +} + +void dirsFromBits(bool * dirs, uint32_t bits) +{ +for (size_t i = 0; i < DIR_NUM; i++) + dirs[i] = bits & (1 << i); +} + +} + +UserImpl::UserImpl(const Settings * s, + const Store * st, + const Tariffs * t, + const Admin * a, + const Users * u, + const Services & svcs) : users(u), - property(s), - WriteServLog(GetStgLogger()), - login(), + properties(*s), + WriteServLog(Logger::get()), + lastScanMessages(0), id(0), - __connected(0), - connected(__connected), - userIDGenerator(), - __currIP(0), - currIP(__currIP), lastIPForDisconnect(0), pingTime(0), sysAdmin(a), store(st), tariffs(t), - tariff(tariffs->GetNoTariff()), - cash(property.cash), - up(property.up), - down(property.down), - lastCashAdd(property.lastCashAdd), - passiveTime(property.passiveTime), - lastCashAddTime(property.lastCashAddTime), - freeMb(property.freeMb), - lastActivityTime(property.lastActivityTime), - password(property.password), - passive(property.passive), - disabled(property.disabled), - disabledDetailStat(property.disabledDetailStat), - alwaysOnline(property.alwaysOnline), - tariffName(property.tariffName), - nextTariff(property.nextTariff), - address(property.address), - note(property.note), - group(property.group), - email(property.email), - phone(property.phone), - realName(property.realName), - credit(property.credit), - creditExpire(property.creditExpire), - ips(property.ips), - userdata0(property.userdata0), - userdata1(property.userdata1), - userdata2(property.userdata2), - userdata3(property.userdata3), - userdata4(property.userdata4), - userdata5(property.userdata5), - userdata6(property.userdata6), - userdata7(property.userdata7), - userdata8(property.userdata8), - userdata9(property.userdata9), - passiveNotifier(this), - tariffNotifier(this), - cashNotifier(this), - ipNotifier(this) + tariff(NULL), + m_services(svcs), + settings(s), + authorizedModificationTime(0), + deleted(false), + lastWriteStat(0), + lastWriteDetailedStat(0), + cash(properties.cash), + up(properties.up), + down(properties.down), + lastCashAdd(properties.lastCashAdd), + passiveTime(properties.passiveTime), + lastCashAddTime(properties.lastCashAddTime), + freeMb(properties.freeMb), + lastActivityTime(properties.lastActivityTime), + password(properties.password), + passive(properties.passive), + disabled(properties.disabled), + disabledDetailStat(properties.disabledDetailStat), + alwaysOnline(properties.alwaysOnline), + tariffName(properties.tariffName), + nextTariff(properties.nextTariff), + address(properties.address), + note(properties.note), + group(properties.group), + email(properties.email), + phone(properties.phone), + realName(properties.realName), + credit(properties.credit), + creditExpire(properties.creditExpire), + ips(properties.ips), + userdata0(properties.userdata0), + userdata1(properties.userdata1), + userdata2(properties.userdata2), + userdata3(properties.userdata3), + userdata4(properties.userdata4), + userdata5(properties.userdata5), + userdata6(properties.userdata6), + userdata7(properties.userdata7), + userdata8(properties.userdata8), + userdata9(properties.userdata9), + sessionUploadModTime(stgTime), + sessionDownloadModTime(stgTime) +{ + Init(); +} +//----------------------------------------------------------------------------- +void UserImpl::Init() { -settings = s; - password = "*_EMPTY_PASSWORD_*"; tariffName = NO_TARIFF_NAME; -connected = 0; -tariff = tariffs->GetNoTariff(); -ips = StrToIPS("*"); -deleted = false; +tariff = tariffs->FindByName(tariffName); +ips = UserIPs::parse("*"); lastWriteStat = stgTime + random() % settings->GetStatWritePeriod(); -lastWriteDeatiledStat = stgTime; - -property.tariffName.AddBeforeNotifier(&tariffNotifier); -property.passive.AddBeforeNotifier(&passiveNotifier); -property.cash.AddBeforeNotifier(&cashNotifier); -currIP.AddAfterNotifier(&ipNotifier); +lastWriteDetailedStat = stgTime; -lastScanMessages = 0; +m_beforePassiveConn = properties.passive.beforeChange([this](auto oldVal, auto newVal){ onPassiveChange(oldVal, newVal); }); +m_afterDisabledConn = properties.disabled.afterChange([this](auto oldVal, auto newVal){ onDisabledChange(oldVal, newVal); }); +m_beforeTariffConn = properties.tariffName.beforeChange([this](const auto& oldVal, const auto& newVal){ onTariffChange(oldVal, newVal); }); +m_beforeCashConn = properties.cash.beforeChange([this](auto oldVal, auto newVal){ onCashChange(oldVal, newVal); }); +m_afterIPConn = ips.afterChange([this](const auto& oldVal, const auto& newVal){ onIPChange(oldVal, newVal); }); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -130,107 +161,102 @@ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&mutex, &attr); } //----------------------------------------------------------------------------- -USER_IMPL::USER_IMPL(const USER_IMPL & u) +UserImpl::UserImpl(const UserImpl & u) : users(u.users), - property(u.settings), - WriteServLog(GetStgLogger()), + properties(*u.settings), + WriteServLog(Logger::get()), + lastScanMessages(0), login(u.login), id(u.id), - __connected(u.__connected), - connected(__connected), - __currIP(u.__currIP), - currIP(__currIP), lastIPForDisconnect(0), pingTime(u.pingTime), sysAdmin(u.sysAdmin), store(u.store), tariffs(u.tariffs), tariff(u.tariff), - cash(property.cash), - up(property.up), - down(property.down), - lastCashAdd(property.lastCashAdd), - passiveTime(property.passiveTime), - lastCashAddTime(property.lastCashAddTime), - freeMb(property.freeMb), - lastActivityTime(property.lastActivityTime), - password(property.password), - passive(property.passive), - disabled(property.disabled), - disabledDetailStat(property.disabledDetailStat), - alwaysOnline(property.alwaysOnline), - tariffName(property.tariffName), - nextTariff(property.nextTariff), - address(property.address), - note(property.note), - group(property.group), - email(property.email), - phone(property.phone), - realName(property.realName), - credit(property.credit), - creditExpire(property.creditExpire), - ips(property.ips), - userdata0(property.userdata0), - userdata1(property.userdata1), - userdata2(property.userdata2), - userdata3(property.userdata3), - userdata4(property.userdata4), - userdata5(property.userdata5), - userdata6(property.userdata6), - userdata7(property.userdata7), - userdata8(property.userdata8), - userdata9(property.userdata9), - passiveNotifier(this), - tariffNotifier(this), - cashNotifier(this), - ipNotifier(this) + m_services(u.m_services), + traffStat(u.traffStat), + traffStatSaved(u.traffStatSaved), + settings(u.settings), + authorizedModificationTime(u.authorizedModificationTime), + messages(u.messages), + deleted(u.deleted), + lastWriteStat(u.lastWriteStat), + lastWriteDetailedStat(u.lastWriteDetailedStat), + cash(properties.cash), + up(properties.up), + down(properties.down), + lastCashAdd(properties.lastCashAdd), + passiveTime(properties.passiveTime), + lastCashAddTime(properties.lastCashAddTime), + freeMb(properties.freeMb), + lastActivityTime(properties.lastActivityTime), + password(properties.password), + passive(properties.passive), + disabled(properties.disabled), + disabledDetailStat(properties.disabledDetailStat), + alwaysOnline(properties.alwaysOnline), + tariffName(properties.tariffName), + nextTariff(properties.nextTariff), + address(properties.address), + note(properties.note), + group(properties.group), + email(properties.email), + phone(properties.phone), + realName(properties.realName), + credit(properties.credit), + creditExpire(properties.creditExpire), + ips(properties.ips), + userdata0(properties.userdata0), + userdata1(properties.userdata1), + userdata2(properties.userdata2), + userdata3(properties.userdata3), + userdata4(properties.userdata4), + userdata5(properties.userdata5), + userdata6(properties.userdata6), + userdata7(properties.userdata7), + userdata8(properties.userdata8), + userdata9(properties.userdata9), + sessionUpload(), + sessionDownload(), + sessionUploadModTime(stgTime), + sessionDownloadModTime(stgTime) { -if (&u == this) - return; - -connected = 0; - -deleted = u.deleted; - -lastWriteStat = u.lastWriteStat; -lastWriteDeatiledStat = u.lastWriteDeatiledStat; - -settings = u.settings; - -property.tariffName.AddBeforeNotifier(&tariffNotifier); -property.passive.AddBeforeNotifier(&passiveNotifier); -property.cash.AddBeforeNotifier(&cashNotifier); -currIP.AddAfterNotifier(&ipNotifier); + if (&u == this) + return; -lastScanMessages = 0; + m_beforePassiveConn = properties.passive.beforeChange([this](auto oldVal, auto newVal){ onPassiveChange(oldVal, newVal); }); + m_afterDisabledConn = properties.disabled.afterChange([this](auto oldVal, auto newVal){ onDisabledChange(oldVal, newVal); }); + m_beforeTariffConn = properties.tariffName.beforeChange([this](const auto& oldVal, const auto& newVal){ onTariffChange(oldVal, newVal); }); + m_beforeCashConn = properties.cash.beforeChange([this](auto oldVal, auto newVal){ onCashChange(oldVal, newVal); }); + m_afterIPConn = ips.afterChange([this](const auto& oldVal, const auto& newVal){ onIPChange(oldVal, newVal); }); -property.SetProperties(u.property); + properties.SetProperties(u.properties); -pthread_mutexattr_t attr; -pthread_mutexattr_init(&attr); -pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); -pthread_mutex_init(&mutex, &attr); + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex, &attr); } //----------------------------------------------------------------------------- -USER_IMPL::~USER_IMPL() +UserImpl::~UserImpl() { -property.passive.DelBeforeNotifier(&passiveNotifier); -property.tariffName.DelBeforeNotifier(&tariffNotifier); pthread_mutex_destroy(&mutex); } //----------------------------------------------------------------------------- -void USER_IMPL::SetLogin(string const & l) +void UserImpl::SetLogin(const std::string & l) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); +static int idGen = 0; assert(login.empty() && "Login is already set"); login = l; -id = userIDGenerator.GetNextID(); +id = idGen++; } //----------------------------------------------------------------------------- -int USER_IMPL::ReadConf() +int UserImpl::ReadConf() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_CONF conf; +STG_LOCKER lock(&mutex); +UserConf conf; if (store->RestoreUserConf(&conf, login)) { @@ -241,28 +267,31 @@ if (store->RestoreUserConf(&conf, login)) return -1; } -property.SetConf(conf); +properties.SetConf(conf); tariff = tariffs->FindByName(tariffName); if (tariff == NULL) { WriteServLog("Cannot read user %s. Tariff %s not exist.", - login.c_str(), property.tariffName.Get().c_str()); + login.c_str(), properties.tariffName.Get().c_str()); return -1; } -std::vector hdrsList; +std::vector hdrsList; if (store->GetMessageHdrs(&hdrsList, login)) { printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str()); + WriteServLog("Cannot read user %s. Error reading message headers: %s.", + login.c_str(), + store->GetStrError().c_str()); return -1; } -std::vector::const_iterator it; +std::vector::const_iterator it; for (it = hdrsList.begin(); it != hdrsList.end(); ++it) { - STG_MSG msg; + Message msg; if (store->GetMessage(it->id, &msg, login) == 0) { messages.push_back(msg); @@ -272,10 +301,10 @@ for (it = hdrsList.begin(); it != hdrsList.end(); ++it) return 0; } //----------------------------------------------------------------------------- -int USER_IMPL::ReadStat() +int UserImpl::ReadStat() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_STAT stat; +STG_LOCKER lock(&mutex); +UserStat stat; if (store->RestoreUserStat(&stat, login)) { @@ -286,17 +315,17 @@ if (store->RestoreUserStat(&stat, login)) return -1; } -property.SetStat(stat); +properties.SetStat(stat); return 0; } //----------------------------------------------------------------------------- -int USER_IMPL::WriteConf() +int UserImpl::WriteConf() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_CONF conf(property.GetConf()); +STG_LOCKER lock(&mutex); +UserConf conf(properties.GetConf()); -printfd(__FILE__, "USER::WriteConf()\n"); +printfd(__FILE__, "UserImpl::WriteConf()\n"); if (store->SaveUserConf(conf, login)) { @@ -310,12 +339,10 @@ if (store->SaveUserConf(conf, login)) return 0; } //----------------------------------------------------------------------------- -int USER_IMPL::WriteStat() +int UserImpl::WriteStat() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_STAT stat(property.GetStat()); - -printfd(__FILE__, "USER::WriteStat()\n"); +STG_LOCKER lock(&mutex); +UserStat stat(properties.GetStat()); if (store->SaveUserStat(stat, login)) { @@ -331,14 +358,14 @@ lastWriteStat = stgTime; return 0; } //----------------------------------------------------------------------------- -int USER_IMPL::WriteMonthStat() +int UserImpl::WriteMonthStat() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); time_t tt = stgTime - 3600; struct tm t1; localtime_r(&tt, &t1); -USER_STAT stat(property.GetStat()); +UserStat stat(properties.GetStat()); if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login)) { WriteServLog("Cannot write month stat for user %s.", login.c_str()); @@ -351,15 +378,21 @@ if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login)) return 0; } //----------------------------------------------------------------------------- -int USER_IMPL::Authorize(uint32_t ip, const string &, uint32_t dirs, const BASE_AUTH * auth) +int UserImpl::Authorize(uint32_t ip, uint32_t dirs, const Auth * auth) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); /* * Authorize user. It only means that user will be authorized. Nothing more. * User can be connected or disconnected while authorized. * Example: user is authorized but disconnected due to 0 money or blocking */ +/* + * TODO: in fact "authorization" means allowing access to a service. What we + * call "authorization" here, int STG, is "authentication". So this should be + * fixed in future. + */ + /* * Prevent double authorization by identical authorizers */ @@ -369,28 +402,25 @@ if (authorizedBy.find(auth) != authorizedBy.end()) if (!ip) return -1; -for (int i = 0; i < DIR_NUM; i++) - { - enabledDirs[i] = dirs & (1 << i); - } +dirsFromBits(enabledDirs, dirs); -if (authorizedBy.size()) +if (!authorizedBy.empty()) { - if (currIP != ip) + if (m_currIP != ip) { - // We are already authorized, but with different IP address - errorStr = "User " + login + " alredy authorized with IP address " + inet_ntostring(ip); + // We are already authorized, but with different IP address + errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip); return -1; } - USER * u = NULL; + User * u = NULL; if (!users->FindByIPIdx(ip, &u)) { - // Address is already present in IP-index - // If it's not our IP - throw an error + // Address presents in IP-index. + // If it's not our IP - report it. if (u != this) { - errorStr = "IP address " + inet_ntostring(ip) + " alredy in use"; + errorStr = "IP address " + inet_ntostring(ip) + " is already in use"; return -1; } } @@ -399,24 +429,26 @@ else { if (users->IsIPInIndex(ip)) { - // Address is already present in IP-index - errorStr = "IP address " + inet_ntostring(ip) + " alredy in use"; + // Address is already present in IP-index. + errorStr = "IP address " + inet_ntostring(ip) + " is already in use"; return -1; } - if (ips.ConstData().IsIPInIPS(ip)) + if (ips.ConstData().find(ip)) { - currIP = ip; - lastIPForDisconnect = currIP; + m_currIP = ip; + lastIPForDisconnect = m_currIP; } else { - printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str()); - errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login; + printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().toString().c_str()); + errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login; return -1; } } +if (authorizedBy.empty()) + authorizedModificationTime = stgTime; authorizedBy.insert(auth); ScanMessage(); @@ -424,88 +456,103 @@ ScanMessage(); return 0; } //----------------------------------------------------------------------------- -void USER_IMPL::Unauthorize(const BASE_AUTH * auth) +void UserImpl::Unauthorize(const Auth * auth, const std::string & reason) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); /* * Authorizer tries to unauthorize user, that was not authorized by it */ if (!authorizedBy.erase(auth)) return; +authorizedModificationTime = stgTime; + if (authorizedBy.empty()) { - lastIPForDisconnect = currIP; - currIP = 0; // DelUser in traffcounter + lastDisconnectReason = reason; + lastIPForDisconnect = m_currIP; + m_currIP = 0; // DelUser in traffcounter + if (m_connected) + Disconnect(false, "not authorized"); return; } } //----------------------------------------------------------------------------- -bool USER_IMPL::IsAuthorizedBy(const BASE_AUTH * auth) const +bool UserImpl::IsAuthorizedBy(const Auth * auth) const { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -// Is this user authorized by specified authorizer? +STG_LOCKER lock(&mutex); +// Is this user authorized by specified authorizer? return authorizedBy.find(auth) != authorizedBy.end(); } //----------------------------------------------------------------------------- -void USER_IMPL::Connect(bool fakeConnect) +std::vector UserImpl::GetAuthorizers() const +{ + STG_LOCKER lock(&mutex); + std::vector list; + std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), [](const auto auth){ return auth->GetVersion(); }); + return list; +} +//----------------------------------------------------------------------------- +void UserImpl::Connect(bool fakeConnect) { /* - * Connect user to Internet. This function is differ from Authorize() !!! + * Connect user to Internet. This function is differ from Authorize() !!! */ -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); if (!fakeConnect) { - string scriptOnConnect = settings->GetScriptDir() + "/OnConnect"; + std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect"; if (access(scriptOnConnect.c_str(), X_OK) == 0) { - char dirsStr[DIR_NUM + 1]; - dirsStr[DIR_NUM] = 0; - for (int i = 0; i < DIR_NUM; i++) - { - dirsStr[i] = enabledDirs[i] ? '1' : '0'; - } + std::string dirs = dirsToString(enabledDirs); - string scriptOnConnectParams; + std::string scriptOnConnectParams; strprintf(&scriptOnConnectParams, - "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"", - scriptOnConnect.c_str(), - login.c_str(), - inet_ntostring(currIP).c_str(), - (double)cash, - id, - dirsStr); + "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"", + scriptOnConnect.c_str(), + login.c_str(), + inet_ntostring(m_currIP).c_str(), + cash.ConstData(), + id, + dirs.c_str()); + + std::vector::const_iterator it(settings->GetScriptParams().begin()); + while (it != settings->GetScriptParams().end()) + { + scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\""; + ++it; + } - ScriptExec(scriptOnConnectParams); + ScriptExec(scriptOnConnectParams.c_str()); } else { WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str()); } - connected = true; + m_connected = true; } -if (store->WriteUserConnect(login, currIP)) +if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, m_currIP)) { WriteServLog("Cannot write connect for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); } if (!fakeConnect) - lastIPForDisconnect = currIP; + lastIPForDisconnect = m_currIP; } //----------------------------------------------------------------------------- -void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason) +void UserImpl::Disconnect(bool fakeDisconnect, const std::string & reason) { /* * Disconnect user from Internet. This function is differ from UnAuthorize() !!! */ -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); if (!lastIPForDisconnect) { @@ -515,38 +562,46 @@ if (!lastIPForDisconnect) if (!fakeDisconnect) { - string scriptOnDisonnect = settings->GetScriptDir() + "/OnDisconnect"; + lastDisconnectReason = reason; + std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect"; if (access(scriptOnDisonnect.c_str(), X_OK) == 0) { - char dirsStr[DIR_NUM + 1]; - dirsStr[DIR_NUM] = 0; - for (int i = 0; i < DIR_NUM; i++) - { - dirsStr[i] = enabledDirs[i] ? '1' : '0'; - } + std::string dirs = dirsToString(enabledDirs); - string scriptOnDisonnectParams; + std::string scriptOnDisonnectParams; strprintf(&scriptOnDisonnectParams, "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"", scriptOnDisonnect.c_str(), login.c_str(), inet_ntostring(lastIPForDisconnect).c_str(), - (double)cash, + cash.ConstData(), id, - dirsStr); + dirs.c_str()); + + std::vector::const_iterator it(settings->GetScriptParams().begin()); + while (it != settings->GetScriptParams().end()) + { + scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\""; + ++it; + } - ScriptExec(scriptOnDisonnectParams); + ScriptExec(scriptOnDisonnectParams.c_str()); } else { WriteServLog("Script OnDisconnect cannot be executed. File not found."); } - connected = false; + m_connected = false; } -if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason)) +std::string reasonMessage(reason); +if (!lastDisconnectReason.empty()) + reasonMessage += ": " + lastDisconnectReason; + +if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, + cash, freeMb, reasonMessage)) { WriteServLog("Cannot write disconnect for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); @@ -555,56 +610,19 @@ if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, if (!fakeDisconnect) lastIPForDisconnect = 0; -DIR_TRAFF zeroSesssion; - -sessionUpload = zeroSesssion; -sessionDownload = zeroSesssion; +sessionUpload.reset(); +sessionDownload.reset(); +sessionUploadModTime = stgTime; +sessionDownloadModTime = stgTime; } //----------------------------------------------------------------------------- -void USER_IMPL::PrintUser() const +void UserImpl::Run() { -//return; -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -cout << "============================================================" << endl; -cout << "id=" << id << endl; -cout << "login=" << login << endl; -cout << "password=" << password << endl; -cout << "passive=" << passive << endl; -cout << "disabled=" << disabled << endl; -cout << "disabledDetailStat=" << disabledDetailStat << endl; -cout << "alwaysOnline=" << alwaysOnline << endl; -cout << "tariffName=" << tariffName << endl; -cout << "address=" << address << endl; -cout << "phone=" << phone << endl; -cout << "email=" << email << endl; -cout << "note=" << note << endl; -cout << "realName=" < static_cast(lastWriteStat + settings->GetStatWritePeriod())) +if (stgTime > lastWriteStat + settings->GetStatWritePeriod()) { - printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str()); + printfd(__FILE__, "UserImpl::WriteStat user=%s\n", GetLogin().c_str()); WriteStat(); } if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime) @@ -625,15 +643,13 @@ if (passive.ConstData() if (!authorizedBy.empty()) { - if (connected) - { - lastActivityTime = *const_cast(&stgTime); - } - if (!connected && IsInetable()) - { + if (m_connected) + properties.Stat().lastActivityTime = stgTime; + + if (!m_connected && IsInetable()) Connect(); - } - if (connected && !IsInetable()) + + if (m_connected && !IsInetable()) { if (disabled) Disconnect(false, "disabled"); @@ -651,28 +667,23 @@ if (!authorizedBy.empty()) } else { - if (connected) - { + if (m_connected) Disconnect(false, "not authorized"); - } } } //----------------------------------------------------------------------------- -void USER_IMPL::UpdatePingTime(time_t t) +void UserImpl::UpdatePingTime(time_t t) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -//printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str()); +STG_LOCKER lock(&mutex); if (t) pingTime = t; else pingTime = stgTime; } //----------------------------------------------------------------------------- -bool USER_IMPL::IsInetable() +bool UserImpl::IsInetable() { -//STG_LOCKER lock(&mutex, __FILE__, __LINE__); - if (disabled || passive) return false; @@ -682,37 +693,30 @@ if (settings->GetFreeMbAllowInet()) return true; } -if (settings->GetShowFeeInCash()) - { +if (settings->GetShowFeeInCash() || tariff == NULL) return (cash >= -credit); - } return (cash - tariff->GetFee() >= -credit); } //----------------------------------------------------------------------------- -string USER_IMPL::GetEnabledDirs() +std::string UserImpl::GetEnabledDirs() const { -//STG_LOCKER lock(&mutex, __FILE__, __LINE__); - -string dirs = ""; -for(int i = 0; i < DIR_NUM; i++) - dirs += enabledDirs[i] ? "1" : "0"; -return dirs; +return dirsToString(enabledDirs); } //----------------------------------------------------------------------------- #ifdef TRAFF_STAT_WITH_PORTS -void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len) +void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len) #else -void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len) +void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint32_t len) #endif { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); -if (!connected) +if (!m_connected || tariff == NULL) return; double cost = 0; -DIR_TRAFF dt(up); +DirTraff dt(up); int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]); int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024; @@ -720,10 +724,10 @@ int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024; dt[dir] += len; int tt = tariff->GetTraffType(); -if (tt == TRAFF_UP || - tt == TRAFF_UP_DOWN || +if (tt == Tariff::TRAFF_UP || + tt == Tariff::TRAFF_UP_DOWN || // Check NEW traff data - (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir])) + (tt == Tariff::TRAFF_MAX && dt[dir] > down.ConstData()[dir])) { double dc = 0; if (traff < threshold && @@ -756,14 +760,15 @@ if (tt == TRAFF_UP || cost = dc - freeMb.ConstData(); // Direct access to internal data structures via friend-specifier - property.Stat().freeMb -= dc; - property.Stat().cash -= cost; + properties.Stat().freeMb -= dc; + properties.Stat().cash -= cost; cash.ModifyTime(); freeMb.ModifyTime(); } up = dt; sessionUpload[dir] += len; +sessionUploadModTime = stgTime; //Add detailed stat @@ -772,18 +777,18 @@ if (!settings->GetWriteFreeMbTraffCost() && cost = 0; #ifdef TRAFF_STAT_WITH_PORTS -IP_DIR_PAIR idp(ip, dir, port); +IPDirPair idp(ip, dir, port); #else -IP_DIR_PAIR idp(ip, dir); +IPDirPair idp(ip, dir); #endif -map::iterator lb; +std::map::iterator lb; lb = traffStat.lower_bound(idp); if (lb == traffStat.end() || lb->first != idp) { traffStat.insert(lb, - pair(idp, - STAT_NODE(len, 0, cost))); + std::make_pair(idp, + StatNode(len, 0, cost))); } else { @@ -793,18 +798,18 @@ else } //----------------------------------------------------------------------------- #ifdef TRAFF_STAT_WITH_PORTS -void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len) +void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len) #else -void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len) +void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint32_t len) #endif { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); -if (!connected) +if (!m_connected || tariff == NULL) return; double cost = 0; -DIR_TRAFF dt(down); +DirTraff dt(down); int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]); int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024; @@ -812,10 +817,10 @@ int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024; dt[dir] += len; int tt = tariff->GetTraffType(); -if (tt == TRAFF_DOWN || - tt == TRAFF_UP_DOWN || +if (tt == Tariff::TRAFF_DOWN || + tt == Tariff::TRAFF_UP_DOWN || // Check NEW traff data - (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir])) + (tt == Tariff::TRAFF_MAX && up.ConstData()[dir] <= dt[dir])) { double dc = 0; if (traff < threshold && @@ -847,14 +852,15 @@ if (tt == TRAFF_DOWN || else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted cost = dc - freeMb.ConstData(); - property.Stat().freeMb -= dc; - property.Stat().cash -= cost; + properties.Stat().freeMb -= dc; + properties.Stat().cash -= cost; cash.ModifyTime(); freeMb.ModifyTime(); } down = dt; sessionDownload[dir] += len; +sessionDownloadModTime = stgTime; //Add detailed stat @@ -863,18 +869,18 @@ if (!settings->GetWriteFreeMbTraffCost() && cost = 0; #ifdef TRAFF_STAT_WITH_PORTS -IP_DIR_PAIR idp(ip, dir, port); +IPDirPair idp(ip, dir, port); #else -IP_DIR_PAIR idp(ip, dir); +IPDirPair idp(ip, dir); #endif -map::iterator lb; +std::map::iterator lb; lb = traffStat.lower_bound(idp); if (lb == traffStat.end() || lb->first != idp) { traffStat.insert(lb, - pair(idp, - STAT_NODE(0, len, cost))); + std::make_pair(idp, + StatNode(0, len, cost))); } else { @@ -883,45 +889,17 @@ else } } //----------------------------------------------------------------------------- -void USER_IMPL::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE * n) +void UserImpl::OnAdd() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -currIP.AddBeforeNotifier(n); -} -//----------------------------------------------------------------------------- -void USER_IMPL::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE * n) -{ -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -currIP.DelBeforeNotifier(n); -} -//----------------------------------------------------------------------------- -void USER_IMPL::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE * n) -{ -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -currIP.AddAfterNotifier(n); -} -//----------------------------------------------------------------------------- -void USER_IMPL::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE * n) -{ -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -currIP.DelAfterNotifier(n); -} -//----------------------------------------------------------------------------- -void USER_IMPL::OnAdd() -{ -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); -string scriptOnAdd = settings->GetScriptDir() + "/OnUserAdd"; +std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd"; if (access(scriptOnAdd.c_str(), X_OK) == 0) { - string scriptOnAddParams; - strprintf(&scriptOnAddParams, - "%s \"%s\"", - scriptOnAdd.c_str(), - login.c_str()); + std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\""; - ScriptExec(scriptOnAddParams); + ScriptExec(scriptOnAddParams.c_str()); } else { @@ -929,21 +907,17 @@ else } } //----------------------------------------------------------------------------- -void USER_IMPL::OnDelete() +void UserImpl::OnDelete() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); -string scriptOnDel = settings->GetScriptDir() + "/OnUserDel"; +std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel"; if (access(scriptOnDel.c_str(), X_OK) == 0) { - string scriptOnDelParams; - strprintf(&scriptOnDelParams, - "%s \"%s\"", - scriptOnDel.c_str(), - login.c_str()); + std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\""; - ScriptExec(scriptOnDelParams); + ScriptExec(scriptOnDelParams.c_str()); } else { @@ -953,15 +927,15 @@ else Run(); } //----------------------------------------------------------------------------- -int USER_IMPL::WriteDetailStat(bool hard) +int UserImpl::WriteDetailStat(bool hard) { -printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size()); +printfd(__FILE__, "UserImpl::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size()); if (!traffStatSaved.second.empty()) { if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login)) { - printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n"); + printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write detail stat from queue\n"); WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); return -1; @@ -969,42 +943,41 @@ if (!traffStatSaved.second.empty()) traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end()); } -TRAFF_STAT ts; +TraffStat ts; { - STG_LOCKER lock(&mutex, __FILE__, __LINE__); + STG_LOCKER lock(&mutex); ts.swap(traffStat); } -printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size()); +printfd(__FILE__, "UserImpl::WriteDetailedStat() - size = %d\n", ts.size()); if (ts.size() && !disabledDetailStat) { - if (store->WriteDetailedStat(ts, lastWriteDeatiledStat, login)) + if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login)) { - printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n"); + printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write current detail stat\n"); WriteServLog("Cannot write detail stat for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); if (!hard) { - printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n"); - STG_LOCKER lock(&mutex, __FILE__, __LINE__); + printfd(__FILE__, "UserImpl::WriteDetailStat() - pushing detail stat to queue\n"); + STG_LOCKER lock(&mutex); traffStatSaved.second.swap(ts); - traffStatSaved.first = lastWriteDeatiledStat; + traffStatSaved.first = lastWriteDetailedStat; } return -1; } } -lastWriteDeatiledStat = stgTime; +lastWriteDetailedStat = stgTime; return 0; } //----------------------------------------------------------------------------- -double USER_IMPL::GetPassiveTimePart() const +double UserImpl::GetPassiveTimePart() const { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); -static int daysInMonth[12] = -{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +static const std::array daysInMonth{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; struct tm tms; time_t t = stgTime; @@ -1018,98 +991,128 @@ if (tms.tm_year % 4 == 0 && tms.tm_mon == 1) secMonth += 24 * 3600; } -int dt = secMonth - passiveTime; +time_t dt = secMonth - passiveTime; if (dt < 0) dt = 0; -return double(dt) / (secMonth); +return static_cast(dt) / secMonth; } //----------------------------------------------------------------------------- -void USER_IMPL::SetPassiveTimeAsNewUser() +void UserImpl::SetPassiveTimeAsNewUser() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); time_t t = stgTime; struct tm tm; localtime_r(&t, &tm); int daysCurrMon = DaysInCurrentMonth(); -double pt = (tm.tm_mday - 1) / (double)daysCurrMon; +double pt = tm.tm_mday - 1; +pt /= daysCurrMon; -passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon); +passiveTime = static_cast(pt * 24 * 3600 * daysCurrMon); } //----------------------------------------------------------------------------- -void USER_IMPL::MidnightResetSessionStat() +void UserImpl::MidnightResetSessionStat() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); -if (connected) +if (m_connected) { Disconnect(true, "fake"); Connect(true); } } //----------------------------------------------------------------------------- -void USER_IMPL::ProcessNewMonth() +void UserImpl::ProcessNewMonth() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); // Reset traff -if (connected) - { +if (m_connected) Disconnect(true, "fake"); - } -DIR_TRAFF zeroTarff; WriteMonthStat(); -up = zeroTarff; -down = zeroTarff; +properties.Stat().monthUp.reset(); +properties.Stat().monthDown.reset(); -if (connected) - { +if (m_connected) Connect(true); - } // Set new tariff if (nextTariff.ConstData() != "") { - const TARIFF * nt; - nt = tariffs->FindByName(nextTariff); + const Tariff * nt = tariffs->FindByName(nextTariff); if (nt == NULL) { WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.", - login.c_str(), property.tariffName.Get().c_str()); + login.c_str(), properties.tariffName.Get().c_str()); } else { - property.tariffName.Set(nextTariff, sysAdmin, login, store); - tariff = nt; + std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime); + if (message.empty()) + { + properties.tariffName.Set(nextTariff, *sysAdmin, login, *store); + } + else + { + WriteServLog("Tariff change is prohibited for user %s. %s", + login.c_str(), + message.c_str()); + } } ResetNextTariff(); WriteConf(); } } //----------------------------------------------------------------------------- -void USER_IMPL::ProcessDayFeeSpread() +void UserImpl::ProcessDayFeeSpread() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); + +if (passive.ConstData() || tariff == NULL) + return; -if (passive.ConstData()) +if (tariff->GetPeriod() != Tariff::MONTH) return; -double f = tariff->GetFee() / DaysInCurrentMonth(); +double fee = tariff->GetFee() / DaysInCurrentMonth(); -if (f == 0.0) +if (std::fabs(fee) < 1.0e-3) return; double c = cash; -property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge"); +switch (settings->GetFeeChargeType()) + { + case 0: + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + break; + case 1: + if (c + credit >= 0) + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + break; + case 2: + if (c + credit >= fee) + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + break; + case 3: + if (c >= 0) + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + break; + } ResetPassiveTime(); } //----------------------------------------------------------------------------- -void USER_IMPL::ProcessDayFee() +void UserImpl::ProcessDayFee() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); + +if (tariff == NULL) + return; + +if (tariff->GetPeriod() != Tariff::MONTH) + return; double passiveTimePart = 1.0; if (!settings->GetFullFee()) @@ -1124,32 +1127,165 @@ else return; } } -double f = tariff->GetFee() * passiveTimePart; +double fee = tariff->GetFee() * passiveTimePart; ResetPassiveTime(); -if (f == 0.0) +if (std::fabs(fee) < 1.0e-3) + { + SetPrepaidTraff(); return; + } double c = cash; -printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n", +printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n", login.c_str(), + cash.ConstData(), + credit.ConstData(), tariff->GetFee(), passiveTimePart, - f); -property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge"); + fee); +switch (settings->GetFeeChargeType()) + { + case 0: + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + SetPrepaidTraff(); + break; + case 1: + if (c + credit >= 0) + { + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + case 2: + if (c + credit >= fee) + { + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + case 3: + if (c >= 0) + { + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + } } //----------------------------------------------------------------------------- -void USER_IMPL::SetPrepaidTraff() +void UserImpl::ProcessDailyFee() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); + +if (passive.ConstData() || tariff == NULL) + return; + +if (tariff->GetPeriod() != Tariff::DAY) + return; -property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic"); +double fee = tariff->GetFee(); + +if (fee == 0.0) + return; + +double c = cash; +switch (settings->GetFeeChargeType()) + { + case 0: + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + break; + case 1: + if (c + credit >= 0) + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + break; + case 2: + if (c + credit >= fee) + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + break; + } +ResetPassiveTime(); } //----------------------------------------------------------------------------- -int USER_IMPL::AddMessage(STG_MSG * msg) +void UserImpl::ProcessServices() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +struct tm tms; +time_t t = stgTime; +localtime_r(&t, &tms); + +double passiveTimePart = 1.0; +if (!settings->GetFullFee()) + { + passiveTimePart = GetPassiveTimePart(); + } +else + { + if (passive.ConstData()) + { + printfd(__FILE__, "Don't charge fee `cause we are passive\n"); + return; + } + } + +for (size_t i = 0; i < properties.Conf().services.size(); ++i) + { + ServiceConf conf; + if (m_services.Find(properties.Conf().services[i], &conf)) + continue; + if (conf.payDay == tms.tm_mday || + (conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth())) + { + double c = cash; + double fee = conf.cost * passiveTimePart; + printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n", + login.c_str(), + cash.ConstData(), + credit.ConstData(), + tariff->GetFee(), + passiveTimePart, + fee); + switch (settings->GetFeeChargeType()) + { + case 0: + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + SetPrepaidTraff(); + break; + case 1: + if (c + credit >= 0) + { + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + case 2: + if (c + credit >= fee) + { + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + case 3: + if (c >= 0) + { + properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + } + } + } +} +//----------------------------------------------------------------------------- +void UserImpl::SetPrepaidTraff() +{ +if (tariff != NULL) + properties.freeMb.Set(tariff->GetFree(), *sysAdmin, login, *store, "Prepaid traffic"); +} +//----------------------------------------------------------------------------- +int UserImpl::AddMessage(Message * msg) +{ +STG_LOCKER lock(&mutex); if (SendMessage(*msg)) { @@ -1169,9 +1305,9 @@ else msg->header.repeat--; #ifndef DEBUG //TODO: gcc v. 4.x generate ICE on x86_64 - msg->header.lastSendTime = time(NULL); + msg->header.lastSendTime = static_cast(time(NULL)); #else - msg->header.lastSendTime = stgTime; + msg->header.lastSendTime = static_cast(stgTime); #endif if (store->AddMessage(msg, login)) { @@ -1186,35 +1322,35 @@ else return 0; } //----------------------------------------------------------------------------- -int USER_IMPL::SendMessage(STG_MSG & msg) const +int UserImpl::SendMessage(Message & msg) const { // No lock `cause we are already locked from caller int ret = -1; -set::iterator it(authorizedBy.begin()); +std::set::iterator it(authorizedBy.begin()); while (it != authorizedBy.end()) { - if (!(*it++)->SendMessage(msg, currIP)) + if (!(*it++)->SendMessage(msg, m_currIP)) ret = 0; } if (!ret) { #ifndef DEBUG //TODO: gcc v. 4.x generate ICE on x86_64 - msg.header.lastSendTime = time(NULL); + msg.header.lastSendTime = static_cast(time(NULL)); #else - msg.header.lastSendTime = stgTime; + msg.header.lastSendTime = static_cast(stgTime); #endif msg.header.repeat--; } return ret; } //----------------------------------------------------------------------------- -void USER_IMPL::ScanMessage() +void UserImpl::ScanMessage() { // No lock `cause we are already locked from caller // We need not check for the authorizedBy `cause it has already checked by caller -std::list::iterator it(messages.begin()); +auto it = messages.begin(); while (it != messages.end()) { if (settings->GetMessageTimeout() > 0 && @@ -1256,40 +1392,83 @@ while (it != messages.end()) ++it; } } + else + { + ++it; + } } } //----------------------------------------------------------------------------- +std::string UserImpl::GetParamValue(const std::string & name) const +{ + std::string lowerName = ToLower(name); + if (lowerName == "id") + { + std::ostringstream stream; + stream << id; + return stream.str(); + } + if (lowerName == "login") return login; + if (lowerName == "currip") return m_currIP.ToString(); + if (lowerName == "enableddirs") return GetEnabledDirs(); + if (lowerName == "tariff") return properties.tariffName; + if (properties.Exists(lowerName)) + return properties.GetPropertyValue(lowerName); + else + { + WriteServLog("User’s parameter '%s' does not exist.", name.c_str()); + return ""; + } +} //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive) +//----------------------------------------------------------------------------- +void UserImpl::onPassiveChange(int oldVal, int newVal) { -if (newPassive && !oldPassive) - user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(), - user->sysAdmin, - user->login, - user->store, + if (newVal && !oldVal && tariff != NULL) + properties.cash.Set(cash - tariff->GetPassiveCost(), + *sysAdmin, + login, + *store, "Freeze"); } //----------------------------------------------------------------------------- -void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff) +void UserImpl::onDisabledChange(int oldVal, int newVal) { -user->tariff = user->tariffs->FindByName(newTariff); + if (oldVal && !newVal && GetConnected()) + Disconnect(false, "disabled"); + else if (!oldVal && newVal && IsInetable()) + Connect(false); } //----------------------------------------------------------------------------- -void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash) +void UserImpl::onTariffChange(const std::string& /*oldVal*/, const std::string& newVal) { -user->lastCashAddTime = *const_cast(&stgTime); -user->lastCashAdd = newCash - oldCash; + STG_LOCKER lock(&mutex); + if (settings->GetReconnectOnTariffChange() && m_connected) + Disconnect(false, "Change tariff"); + tariff = tariffs->FindByName(newVal); + if (settings->GetReconnectOnTariffChange() && + !authorizedBy.empty() && + IsInetable()) + { + // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name. + properties.Conf().tariffName = newVal; + Connect(false); + } } //----------------------------------------------------------------------------- -void CHG_IP_NOTIFIER::Notify(const uint32_t & from, const uint32_t & to) +void UserImpl::onCashChange(double oldVal, double newVal) { - printfd(__FILE__, "Change IP from %s to %s\n", inet_ntostring(from).c_str(), inet_ntostring(to).c_str()); - if (from != 0) - if (user->connected) - user->Disconnect(false, "Change IP"); - if (to != 0) - if (user->IsInetable()) - user->Connect(false); + time_t now = stgTime; + lastCashAddTime = now; + lastCashAdd = newVal - oldVal; } //----------------------------------------------------------------------------- +void UserImpl::onIPChange(const UserIPs& oldVal, const UserIPs& newVal) +{ + printfd(__FILE__, "Change IP from '%s' to '%s'\n", oldVal.toString().c_str(), newVal.toString().c_str()); + if (m_connected) + Disconnect(false, "Change IP"); + if (!authorizedBy.empty() && IsInetable()) + Connect(false); +}