X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/102a98fb1218ebee228837b895d7132e7d2628ec..26b7dcb329abea46e11695c4df61e54c9cf9fd6c:/projects/stargazer/user_impl.cpp diff --git a/projects/stargazer/user_impl.cpp b/projects/stargazer/user_impl.cpp index 35ec6efb..f3410368 100644 --- a/projects/stargazer/user_impl.cpp +++ b/projects/stargazer/user_impl.cpp @@ -32,12 +32,9 @@ #define _GNU_SOURCE #endif -#include -#include // access - -#include -#include -#include +#include "user_impl.h" +#include "settings_impl.h" +#include "stg_timer.h" #include "stg/users.h" #include "stg/common.h" @@ -45,27 +42,50 @@ #include "stg/tariff.h" #include "stg/tariffs.h" #include "stg/admin.h" -#include "user_impl.h" -#include "settings_impl.h" -#include "stg_timer.h" + +#include +#include + +#include +#include +#include + +#include +#include // access + +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); +} + +} #ifdef USE_ABSTRACT_SETTINGS USER_IMPL::USER_IMPL(const SETTINGS * s, const STORE * st, const TARIFFS * t, const ADMIN * a, - const USERS * u) - : USER(), - users(u), - property(s->GetScriptsDir()), + const USERS * u, + const SERVICES & svcs) + : users(u), + property(*s), WriteServLog(GetStgLogger()), lastScanMessages(0), - login(), id(0), __connected(0), connected(__connected), - enabledDirs(), - userIDGenerator(), __currIP(0), currIP(__currIP), lastIPForDisconnect(0), @@ -74,11 +94,9 @@ USER_IMPL::USER_IMPL(const SETTINGS * s, store(st), tariffs(t), tariff(NULL), - traffStat(), - traffStatSaved(), + m_services(svcs), settings(s), - authorizedBy(), - messages(), + authorizedModificationTime(0), deleted(false), lastWriteStat(0), lastWriteDetailedStat(0), @@ -116,49 +134,28 @@ USER_IMPL::USER_IMPL(const SETTINGS * s, userdata7(property.userdata7), userdata8(property.userdata8), userdata9(property.userdata9), - sessionUpload(), - sessionDownload(), passiveNotifier(this), + disabledNotifier(this), tariffNotifier(this), cashNotifier(this), - ipNotifier(this), - mutex(), - errorStr() + ipNotifier(this) { -password = "*_EMPTY_PASSWORD_*"; -tariffName = NO_TARIFF_NAME; -ips = StrToIPS("*"); -lastWriteStat = stgTime + random() % settings->GetStatWritePeriod(); -lastWriteDetailedStat = stgTime; - -property.tariffName.AddBeforeNotifier(&tariffNotifier); -property.passive.AddBeforeNotifier(&passiveNotifier); -property.disabled.AddAfterNotifier(&disabledNotifier); -property.cash.AddBeforeNotifier(&cashNotifier); -ips.AddAfterNotifier(&ipNotifier); - -pthread_mutexattr_t attr; -pthread_mutexattr_init(&attr); -pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); -pthread_mutex_init(&mutex, &attr); +Init(); } #else USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s, const STORE * st, const TARIFFS * t, const ADMIN * a, - const USERS * u) - : USER(), - users(u), - property(s->GetScriptsDir()), + const USERS * u, + const SERVICES & svcs) + : users(u), + property(*s), WriteServLog(GetStgLogger()), lastScanMessages(0), - login(), id(0), __connected(0), connected(__connected), - enabledDirs(), - userIDGenerator(), __currIP(0), currIP(__currIP), lastIPForDisconnect(0), @@ -167,11 +164,9 @@ USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s, store(st), tariffs(t), tariff(NULL), - traffStat(), - traffStatSaved(), + m_services(svcs), settings(s), - authorizedBy(), - messages(), + authorizedModificationTime(0), deleted(false), lastWriteStat(0), lastWriteDetailedStat(0), @@ -209,15 +204,17 @@ USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s, userdata7(property.userdata7), userdata8(property.userdata8), userdata9(property.userdata9), - sessionUpload(), - sessionDownload(), passiveNotifier(this), disabledNotifier(this), tariffNotifier(this), cashNotifier(this), - ipNotifier(this), - mutex(), - errorStr() + ipNotifier(this) +{ +Init(); +} +#endif +//----------------------------------------------------------------------------- +void USER_IMPL::Init() { password = "*_EMPTY_PASSWORD_*"; tariffName = NO_TARIFF_NAME; @@ -236,19 +233,17 @@ pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&mutex, &attr); } -#endif //----------------------------------------------------------------------------- USER_IMPL::USER_IMPL(const USER_IMPL & u) : USER(), users(u.users), - property(u.settings->GetScriptsDir()), + property(*u.settings), WriteServLog(GetStgLogger()), lastScanMessages(0), login(u.login), id(u.id), __connected(0), connected(__connected), - enabledDirs(), userIDGenerator(u.userIDGenerator), __currIP(u.__currIP), currIP(__currIP), @@ -258,10 +253,11 @@ USER_IMPL::USER_IMPL(const USER_IMPL & u) store(u.store), tariffs(u.tariffs), tariff(u.tariff), + m_services(u.m_services), traffStat(u.traffStat), traffStatSaved(u.traffStatSaved), settings(u.settings), - authorizedBy(), + authorizedModificationTime(u.authorizedModificationTime), messages(u.messages), deleted(u.deleted), lastWriteStat(u.lastWriteStat), @@ -306,9 +302,7 @@ USER_IMPL::USER_IMPL(const USER_IMPL & u) disabledNotifier(this), tariffNotifier(this), cashNotifier(this), - ipNotifier(this), - mutex(), - errorStr() + ipNotifier(this) { if (&u == this) return; @@ -338,7 +332,7 @@ pthread_mutex_destroy(&mutex); //----------------------------------------------------------------------------- void USER_IMPL::SetLogin(const std::string & l) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); assert(login.empty() && "Login is already set"); login = l; id = userIDGenerator.GetNextID(); @@ -346,7 +340,7 @@ id = userIDGenerator.GetNextID(); //----------------------------------------------------------------------------- int USER_IMPL::ReadConf() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); USER_CONF conf; if (store->RestoreUserConf(&conf, login)) @@ -394,7 +388,7 @@ return 0; //----------------------------------------------------------------------------- int USER_IMPL::ReadStat() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); USER_STAT stat; if (store->RestoreUserStat(&stat, login)) @@ -413,7 +407,7 @@ return 0; //----------------------------------------------------------------------------- int USER_IMPL::WriteConf() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); USER_CONF conf(property.GetConf()); printfd(__FILE__, "USER::WriteConf()\n"); @@ -432,7 +426,7 @@ return 0; //----------------------------------------------------------------------------- int USER_IMPL::WriteStat() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); USER_STAT stat(property.GetStat()); if (store->SaveUserStat(stat, login)) @@ -451,7 +445,7 @@ return 0; //----------------------------------------------------------------------------- int USER_IMPL::WriteMonthStat() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); time_t tt = stgTime - 3600; struct tm t1; localtime_r(&tt, &t1); @@ -471,13 +465,19 @@ return 0; //----------------------------------------------------------------------------- int USER_IMPL::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 */ @@ -487,16 +487,13 @@ 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.empty()) { if (currIP != ip) { - // We are already authorized, but with different IP address + // We are already authorized, but with different IP address errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip); return -1; } @@ -504,11 +501,11 @@ if (!authorizedBy.empty()) 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) + " already in use"; + errorStr = "IP address " + inet_ntostring(ip) + " is already in use"; return -1; } } @@ -517,8 +514,8 @@ else { if (users->IsIPInIndex(ip)) { - // Address is already present in IP-index - errorStr = "IP address " + inet_ntostring(ip) + " already in use"; + // Address is already present in IP-index. + errorStr = "IP address " + inet_ntostring(ip) + " is already in use"; return -1; } @@ -530,11 +527,13 @@ else 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; + errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login; return -1; } } +if (authorizedBy.empty()) + authorizedModificationTime = stgTime; authorizedBy.insert(auth); ScanMessage(); @@ -542,37 +541,50 @@ ScanMessage(); return 0; } //----------------------------------------------------------------------------- -void USER_IMPL::Unauthorize(const AUTH * auth) +void USER_IMPL::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()) { + lastDisconnectReason = reason; lastIPForDisconnect = currIP; currIP = 0; // DelUser in traffcounter + if (connected) + Disconnect(false, "not authorized"); return; } } //----------------------------------------------------------------------------- bool USER_IMPL::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(); } //----------------------------------------------------------------------------- +std::vector USER_IMPL::GetAuthorizers() const +{ + STG_LOCKER lock(&mutex); + std::vector list; + std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion)); + return list; +} +//----------------------------------------------------------------------------- void USER_IMPL::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) { @@ -580,23 +592,17 @@ if (!fakeConnect) 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); std::string scriptOnConnectParams; - strprintf(&scriptOnConnectParams, - "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"", - scriptOnConnect.c_str(), - login.c_str(), - inet_ntostring(currIP).c_str(), - cash.ConstData(), - id, - dirsStr); + "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"", + scriptOnConnect.c_str(), + login.c_str(), + inet_ntostring(currIP).c_str(), + cash.ConstData(), + id, + dirs.c_str()); std::vector::const_iterator it(settings->GetScriptParams().begin()); while (it != settings->GetScriptParams().end()) @@ -615,7 +621,7 @@ if (!fakeConnect) connected = true; } -if (store->WriteUserConnect(login, currIP)) +if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP)) { WriteServLog("Cannot write connect for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); @@ -631,7 +637,7 @@ void USER_IMPL::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) { @@ -641,16 +647,12 @@ if (!lastIPForDisconnect) if (!fakeDisconnect) { + 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); std::string scriptOnDisonnectParams; strprintf(&scriptOnDisonnectParams, @@ -660,7 +662,7 @@ if (!fakeDisconnect) inet_ntostring(lastIPForDisconnect).c_str(), cash.ConstData(), id, - dirsStr); + dirs.c_str()); std::vector::const_iterator it(settings->GetScriptParams().begin()); while (it != settings->GetScriptParams().end()) @@ -679,7 +681,12 @@ if (!fakeDisconnect) 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()); @@ -688,52 +695,15 @@ if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, if (!fakeDisconnect) lastIPForDisconnect = 0; -DIR_TRAFF zeroSesssion; - -sessionUpload = zeroSesssion; -sessionDownload = zeroSesssion; -} -//----------------------------------------------------------------------------- -void USER_IMPL::PrintUser() const -{ -//return; -STG_LOCKER lock(&mutex, __FILE__, __LINE__); -std::cout << "============================================================" << std::endl; -std::cout << "id=" << id << std::endl; -std::cout << "login=" << login << std::endl; -std::cout << "password=" << password << std::endl; -std::cout << "passive=" << passive << std::endl; -std::cout << "disabled=" << disabled << std::endl; -std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl; -std::cout << "alwaysOnline=" << alwaysOnline << std::endl; -std::cout << "tariffName=" << tariffName << std::endl; -std::cout << "address=" << address << std::endl; -std::cout << "phone=" << phone << std::endl; -std::cout << "email=" << email << std::endl; -std::cout << "note=" << note << std::endl; -std::cout << "realName=" < static_cast(lastWriteStat + settings->GetStatWritePeriod())) { @@ -759,13 +729,11 @@ if (passive.ConstData() if (!authorizedBy.empty()) { if (connected) - { property.Stat().lastActivityTime = stgTime; - } + if (!connected && IsInetable()) - { Connect(); - } + if (connected && !IsInetable()) { if (disabled) @@ -785,17 +753,14 @@ if (!authorizedBy.empty()) else { if (connected) - { Disconnect(false, "not authorized"); - } } } //----------------------------------------------------------------------------- void USER_IMPL::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 @@ -804,8 +769,6 @@ else //----------------------------------------------------------------------------- bool USER_IMPL::IsInetable() { -//STG_LOCKER lock(&mutex, __FILE__, __LINE__); - if (disabled || passive) return false; @@ -816,21 +779,14 @@ if (settings->GetFreeMbAllowInet()) } if (settings->GetShowFeeInCash() || tariff == NULL) - { return (cash >= -credit); - } return (cash - tariff->GetFee() >= -credit); } //----------------------------------------------------------------------------- -std::string USER_IMPL::GetEnabledDirs() +std::string USER_IMPL::GetEnabledDirs() const { -//STG_LOCKER lock(&mutex, __FILE__, __LINE__); - -std::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 @@ -839,7 +795,7 @@ void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len) void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len) #endif { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); if (!connected || tariff == NULL) return; @@ -853,10 +809,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 && @@ -897,6 +853,7 @@ if (tt == TRAFF_UP || up = dt; sessionUpload[dir] += len; +sessionUploadModTime = stgTime; //Add detailed stat @@ -931,7 +888,7 @@ void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len) void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len) #endif { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); if (!connected || tariff == NULL) return; @@ -945,10 +902,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 && @@ -988,6 +945,7 @@ if (tt == TRAFF_DOWN || down = dt; sessionDownload[dir] += len; +sessionDownloadModTime = stgTime; //Add detailed stat @@ -1018,65 +976,61 @@ else //----------------------------------------------------------------------------- void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); currIP.AddBeforeNotifier(notifier); } //----------------------------------------------------------------------------- void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); currIP.DelBeforeNotifier(notifier); } //----------------------------------------------------------------------------- void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); currIP.AddAfterNotifier(notifier); } //----------------------------------------------------------------------------- void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); currIP.DelAfterNotifier(notifier); } //----------------------------------------------------------------------------- void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); connected.AddBeforeNotifier(notifier); } //----------------------------------------------------------------------------- void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); connected.DelBeforeNotifier(notifier); } //----------------------------------------------------------------------------- void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); connected.AddAfterNotifier(notifier); } //----------------------------------------------------------------------------- void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); connected.DelAfterNotifier(notifier); } //----------------------------------------------------------------------------- void USER_IMPL::OnAdd() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd"; if (access(scriptOnAdd.c_str(), X_OK) == 0) { - std::string scriptOnAddParams; - strprintf(&scriptOnAddParams, - "%s \"%s\"", - scriptOnAdd.c_str(), - login.c_str()); + std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\""; ScriptExec(scriptOnAddParams.c_str()); } @@ -1088,17 +1042,13 @@ else //----------------------------------------------------------------------------- void USER_IMPL::OnDelete() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel"; if (access(scriptOnDel.c_str(), X_OK) == 0) { - std::string scriptOnDelParams; - strprintf(&scriptOnDelParams, - "%s \"%s\"", - scriptOnDel.c_str(), - login.c_str()); + std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\""; ScriptExec(scriptOnDelParams.c_str()); } @@ -1129,7 +1079,7 @@ if (!traffStatSaved.second.empty()) TRAFF_STAT ts; { - STG_LOCKER lock(&mutex, __FILE__, __LINE__); + STG_LOCKER lock(&mutex); ts.swap(traffStat); } @@ -1145,7 +1095,7 @@ if (ts.size() && !disabledDetailStat) if (!hard) { printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n"); - STG_LOCKER lock(&mutex, __FILE__, __LINE__); + STG_LOCKER lock(&mutex); traffStatSaved.second.swap(ts); traffStatSaved.first = lastWriteDetailedStat; } @@ -1158,7 +1108,7 @@ return 0; //----------------------------------------------------------------------------- double USER_IMPL::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}; @@ -1185,7 +1135,7 @@ return static_cast(dt) / secMonth; //----------------------------------------------------------------------------- void USER_IMPL::SetPassiveTimeAsNewUser() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); time_t t = stgTime; struct tm tm; @@ -1199,7 +1149,7 @@ passiveTime = static_cast(pt * 24 * 3600 * daysCurrMon); //----------------------------------------------------------------------------- void USER_IMPL::MidnightResetSessionStat() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); if (connected) { @@ -1210,29 +1160,23 @@ if (connected) //----------------------------------------------------------------------------- void USER_IMPL::ProcessNewMonth() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); // Reset traff if (connected) - { Disconnect(true, "fake"); - } -DIR_TRAFF zeroTarff; WriteMonthStat(); -up = zeroTarff; -down = zeroTarff; +property.Stat().monthUp.Reset(); +property.Stat().monthDown.Reset(); if (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.", @@ -1240,8 +1184,17 @@ if (nextTariff.ConstData() != "") } else { - property.tariffName.Set(nextTariff, sysAdmin, login, store); - //tariff = nt; + std::string message = tariff->TariffChangeIsAllowed(*nt); + if (message.empty()) + { + property.tariffName.Set(nextTariff, sysAdmin, login, store); + } + else + { + WriteServLog("Tariff change is prohibited for user %s. %s", + login.c_str(), + message.c_str()); + } } ResetNextTariff(); WriteConf(); @@ -1250,11 +1203,14 @@ if (nextTariff.ConstData() != "") //----------------------------------------------------------------------------- void USER_IMPL::ProcessDayFeeSpread() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); if (passive.ConstData() || tariff == NULL) return; +if (tariff->GetPeriod() != TARIFF::MONTH) + return; + double fee = tariff->GetFee() / DaysInCurrentMonth(); if (std::fabs(fee) < 1.0e-3) @@ -1284,11 +1240,14 @@ ResetPassiveTime(); //----------------------------------------------------------------------------- void USER_IMPL::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()) { @@ -1350,6 +1309,108 @@ switch (settings->GetFeeChargeType()) } } //----------------------------------------------------------------------------- +void USER_IMPL::ProcessDailyFee() +{ +STG_LOCKER lock(&mutex); + +if (passive.ConstData() || tariff == NULL) + return; + +if (tariff->GetPeriod() != TARIFF::DAY) + return; + +double fee = tariff->GetFee(); + +if (fee == 0.0) + return; + +double c = cash; +switch (settings->GetFeeChargeType()) + { + case 0: + property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge"); + break; + case 1: + if (c + credit >= 0) + property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge"); + break; + case 2: + if (c + credit >= fee) + property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge"); + break; + } +ResetPassiveTime(); +} +//----------------------------------------------------------------------------- +void USER_IMPL::ProcessServices() +{ +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 < property.Conf().services.size(); ++i) + { + SERVICE_CONF conf; + if (m_services.Find(property.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: + property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge"); + SetPrepaidTraff(); + break; + case 1: + if (c + credit >= 0) + { + property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + case 2: + if (c + credit >= fee) + { + property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + case 3: + if (c >= 0) + { + property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge"); + SetPrepaidTraff(); + } + break; + } + } + } +} +//----------------------------------------------------------------------------- void USER_IMPL::SetPrepaidTraff() { if (tariff != NULL) @@ -1358,7 +1419,7 @@ if (tariff != NULL) //----------------------------------------------------------------------------- int USER_IMPL::AddMessage(STG_MSG * msg) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +STG_LOCKER lock(&mutex); if (SendMessage(*msg)) { @@ -1474,40 +1535,24 @@ while (it != messages.end()) //----------------------------------------------------------------------------- std::string USER_IMPL::GetParamValue(const std::string & name) const { -if (name == "id") - { - std::stringstream stream; - stream << id; - return stream.str();; - } -if (name == "login") return login; -if (name == "ip") return currIP.ToString(); -return property.GetPropertyValue(&name); -//if (name == "freeMb") return property.freeMb.ToString(); -//if (name == "passive") return property.passive.ToString(); -//if (name == "disabled") return property.disabled.ToString(); -//if (name == "alwaysOnline") return property.alwaysOnline.ToString(); -//if (name == "tariffName") return property.tariffName; -//if (name == "nextTariff") return property.nextTariff; -//if (name == "address") return property.address; -//if (name == "note") return property.note; -//if (name == "group") return property.group; -//if (name == "email") return property.email; -//if (name == "phone") return property.phone; -//if (name == "realName") return property.realName; -//if (name == "credit") return property.credit.ToString(); -//if (name == "userdata0") return property.userdata0; -//if (name == "userdata1") return property.userdata1; -//if (name == "userdata2") return property.userdata2; -//if (name == "userdata3") return property.userdata3; -//if (name == "userdata4") return property.userdata4; -//if (name == "userdata5") return property.userdata5; -//if (name == "userdata6") return property.userdata6; -//if (name == "userdata7") return property.userdata7; -//if (name == "userdata8") return property.userdata8; -//if (name == "userdata9") return property.userdata9; -//if (name == "cash") return property.cash.ToString(); -//return ""; + 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 currIP.ToString(); + if (lowerName == "enableddirs") return GetEnabledDirs(); + if (lowerName == "tariff") return property.tariffName; + if (property.Exists(lowerName)) + return property.GetPropertyValue(lowerName); + else + { + WriteServLog("User’s parameter '%s' does not exist.", name.c_str()); + return ""; + } } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -1525,25 +1570,25 @@ if (newPassive && !oldPassive && user->tariff != NULL) void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue) { if (oldValue && !newValue && user->GetConnected()) - { user->Disconnect(false, "disabled"); - } else if (!oldValue && newValue && user->IsInetable()) - { user->Connect(false); - } - } //----------------------------------------------------------------------------- void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff) { +STG_LOCKER lock(&user->mutex); if (user->settings->GetReconnectOnTariffChange() && user->connected) user->Disconnect(false, "Change tariff"); user->tariff = user->tariffs->FindByName(newTariff); if (user->settings->GetReconnectOnTariffChange() && !user->authorizedBy.empty() && user->IsInetable()) + { + // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name. + user->property.Conf().tariffName = newTariff; user->Connect(false); + } } //----------------------------------------------------------------------------- void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash) @@ -1554,10 +1599,9 @@ user->lastCashAdd = newCash - oldCash; //----------------------------------------------------------------------------- void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to) { - printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str()); - if (user->connected) - user->Disconnect(false, "Change IP"); - if (!user->authorizedBy.empty() && user->IsInetable()) - user->Connect(false); +printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str()); +if (user->connected) + user->Disconnect(false, "Change IP"); +if (!user->authorizedBy.empty() && user->IsInetable()) + user->Connect(false); } -//-----------------------------------------------------------------------------