X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/641204dfbdb9fc870cdd2e7f9e3169a44693e7bf..e507bc9f35fcf9ce0ea09f03b0187cab73519b07:/projects/stargazer/user.cpp diff --git a/projects/stargazer/user.cpp b/projects/stargazer/user.cpp index 6c328602..d8368c4d 100644 --- a/projects/stargazer/user.cpp +++ b/projects/stargazer/user.cpp @@ -110,14 +110,11 @@ ipIndex = ipIdx; password = "*_EMPTY_PASSWORD_*"; tariffName = NO_TARIFF_NAME; connected = 0; -traffStatInUse = 0; -traffStat = &traffStatInternal[0]; tariff = tariffs->GetNoTariff(); ips = StrToIPS("*"); deleted = false; lastWriteStat = stgTime + random() % settings->GetStatWritePeriod(); lastWriteDeatiledStat = stgTime; -lastSwapDeatiledStat = stgTime; property.tariffName.AddBeforeNotifier(&tariffNotifier); property.passive.AddBeforeNotifier(&passiveNotifier); @@ -126,8 +123,6 @@ currIP.AddAfterNotifier(&ipNotifier); lastScanMessages = 0; -writeFreeMbTraffCost = settings->GetWriteFreeMbTraffCost(); - pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); @@ -192,17 +187,13 @@ if (&u == this) return; connected = 0; -traffStatInUse = 0; ipIndex = u.ipIndex; deleted = u.deleted; -traffStat = &traffStatInternal[traffStatInUse % 2]; -traffStatToWrite = &traffStatInternal[(traffStatInUse +1) % 2]; lastWriteStat = u.lastWriteStat; lastWriteDeatiledStat = u.lastWriteDeatiledStat; -lastSwapDeatiledStat = u.lastSwapDeatiledStat; settings = u.settings; @@ -213,7 +204,7 @@ currIP.AddAfterNotifier(&ipNotifier); lastScanMessages = 0; -writeFreeMbTraffCost = settings->GetWriteFreeMbTraffCost(); +property.SetProperties(u.property); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -239,9 +230,9 @@ id = userIDGenerator.GetNextID(); int USER::ReadConf() { STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_CONF uc; +USER_CONF conf; -if (store->RestoreUserConf(&uc, login)) +if (store->RestoreUserConf(&conf, login)) { WriteServLog("Cannot read conf for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); @@ -250,33 +241,7 @@ if (store->RestoreUserConf(&uc, login)) return -1; } -password = uc.password; -passive = uc.passive; -disabled = uc.disabled; -disabledDetailStat = uc.disabledDetailStat; -alwaysOnline = uc.alwaysOnline; -tariffName = uc.tariffName; -address = uc.address; -phone = uc.phone; -email = uc.email; -note = uc.note; -realName = uc.realName; -group = uc.group; -credit = uc.credit; -nextTariff = uc.nextTariff; -userdata0 = uc.userdata[0]; -userdata1 = uc.userdata[1]; -userdata2 = uc.userdata[2]; -userdata3 = uc.userdata[3]; -userdata4 = uc.userdata[4]; -userdata5 = uc.userdata[5]; -userdata6 = uc.userdata[6]; -userdata7 = uc.userdata[7]; -userdata8 = uc.userdata[8]; -userdata9 = uc.userdata[9]; - -creditExpire = uc.creditExpire; -ips = uc.ips; +property.SetConf(conf); tariff = tariffs->FindByName(tariffName); if (tariff == NULL) @@ -286,15 +251,33 @@ if (tariff == NULL) return -1; } +std::vector hdrsList; + +if (store->GetMessageHdrs(&hdrsList, login)) + { + printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str()); + return -1; + } + +std::vector::const_iterator it; +for (it = hdrsList.begin(); it != hdrsList.end(); ++it) + { + STG_MSG msg; + if (store->GetMessage(it->id, &msg, login) == 0) + { + messages.push_back(msg); + } + } + return 0; } //----------------------------------------------------------------------------- int USER::ReadStat() { STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_STAT us; +USER_STAT stat; -if (store->RestoreUserStat(&us, login)) +if (store->RestoreUserStat(&stat, login)) { WriteServLog("Cannot read stat for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); @@ -303,14 +286,7 @@ if (store->RestoreUserStat(&us, login)) return -1; } -up = us.up; -down = us.down; -cash = us.cash; -freeMb = us.freeMb; -lastCashAdd = us.lastCashAdd; -lastCashAddTime = us.lastCashAddTime; -passiveTime = us.passiveTime; -lastActivityTime = us.lastActivityTime; +property.SetStat(stat); return 0; } @@ -318,39 +294,11 @@ return 0; int USER::WriteConf() { STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_CONF uc; - -uc.password = password; -uc.passive = passive; -uc.disabled = disabled; -uc.disabledDetailStat = disabledDetailStat; -uc.alwaysOnline = alwaysOnline; -uc.tariffName = tariffName; -uc.address = address; -uc.phone = phone; -uc.email = email; -uc.note = note; -uc.realName = realName; -uc.group = group; -uc.credit = credit; -uc.nextTariff = nextTariff; -uc.userdata[0] = userdata0; -uc.userdata[1] = userdata1; -uc.userdata[2] = userdata2; -uc.userdata[3] = userdata3; -uc.userdata[4] = userdata4; -uc.userdata[5] = userdata5; -uc.userdata[6] = userdata6; -uc.userdata[7] = userdata7; -uc.userdata[8] = userdata8; -uc.userdata[9] = userdata9; - -uc.creditExpire = creditExpire; -uc.ips = ips; +USER_CONF conf(property.GetConf()); printfd(__FILE__, "USER::WriteConf()\n"); -if (store->SaveUserConf(uc, login)) +if (store->SaveUserConf(conf, login)) { WriteServLog("Cannot write conf for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); @@ -365,20 +313,11 @@ return 0; int USER::WriteStat() { STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_STAT us; - -us.up = up; -us.down = down; -us.cash = cash; -us.freeMb = freeMb; -us.lastCashAdd = lastCashAdd; -us.lastCashAddTime = lastCashAddTime; -us.passiveTime = passiveTime; -us.lastActivityTime = lastActivityTime; +USER_STAT stat(property.GetStat()); printfd(__FILE__, "USER::WriteStat()\n"); -if (store->SaveUserStat(us, login)) +if (store->SaveUserStat(stat, login)) { WriteServLog("Cannot write stat for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); @@ -395,21 +334,12 @@ return 0; int USER::WriteMonthStat() { STG_LOCKER lock(&mutex, __FILE__, __LINE__); -USER_STAT us; -struct tm * t1; time_t tt = stgTime - 3600; -t1 = localtime(&tt); - -us.up = up; -us.down = down; -us.cash = cash; -us.freeMb = freeMb; -us.lastCashAdd = lastCashAdd; -us.lastCashAddTime = lastCashAddTime; -us.passiveTime = passiveTime; -us.lastActivityTime = lastActivityTime; - -if (store->SaveMonthStat(us, t1->tm_mon, t1->tm_year, login)) +struct tm t1; +localtime_r(&tt, &t1); + +USER_STAT stat(property.GetStat()); +if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login)) { WriteServLog("Cannot write month stat for user %s.", login.c_str()); WriteServLog("%s", store->GetStrError().c_str()); @@ -567,10 +497,6 @@ if (store->WriteUserConnect(login, currIP)) if (!fakeConnect) lastIPForDisconnect = currIP; - -//printfd(__FILE__, "Connect. user name \'%s\' ip=%s\n", login.c_str(), inet_ntostring(currIP).c_str()); -/*if (settings->GetLogUserConnectDisconnect()) - WriteServLog("User \'%s\', %s: Connect.", login.c_str(), inet_ntostring(currIP).c_str());*/ } //----------------------------------------------------------------------------- void USER::Disconnect(bool fakeDisconnect, const std::string & reason) @@ -626,10 +552,6 @@ if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, WriteServLog("%s", store->GetStrError().c_str()); } -//printfd(__FILE__, "Disconnect. User name \'%s\' ip=%s reason: '%s'\n", login.c_str(), inet_ntostring(lastIPForDisconnect).c_str(), reason.c_str()); -/*if (settings->GetLogUserConnectDisconnect()) - WriteServLog("User \'%s\', %s: Disconnect.", login.c_str(), inet_ntostring(lastIPForDisconnect).c_str());*/ - if (!fakeDisconnect) lastIPForDisconnect = 0; @@ -680,7 +602,7 @@ void USER::Run() { STG_LOCKER lock(&mutex, __FILE__, __LINE__); -if (stgTime - lastWriteStat > settings->GetStatWritePeriod()) +if (stgTime > static_cast(lastWriteStat + settings->GetStatWritePeriod())) { printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str()); WriteStat(); @@ -845,7 +767,8 @@ sessionUpload[dir] += len; //Add detailed stat -if (!writeFreeMbTraffCost && freeMb.ConstData() >= 0) +if (!settings->GetWriteFreeMbTraffCost() && + freeMb.ConstData() >= 0) cost = 0; #ifdef TRAFF_STAT_WITH_PORTS @@ -855,25 +778,18 @@ IP_DIR_PAIR idp(ip, dir); #endif map::iterator lb; -lb = traffStat->lower_bound(idp); -if (lb == traffStat->end()) +lb = traffStat.lower_bound(idp); +if (lb == traffStat.end() || lb->first != idp) { - traffStat->insert(lb, - pair(idp, - STAT_NODE(len, 0, cost))); + traffStat.insert(lb, + pair(idp, + STAT_NODE(len, 0, cost))); } else - if (lb->first.dir == dir && lb->first.ip == ip) - { - lb->second.cash += cost; - lb->second.up += len; - } - else - { - traffStat->insert(lb, - pair(idp, - STAT_NODE(len, 0, cost))); - } + { + lb->second.cash += cost; + lb->second.up += len; + } } //----------------------------------------------------------------------------- #ifdef TRAFF_STAT_WITH_PORTS @@ -942,7 +858,8 @@ sessionDownload[dir] += len; //Add detailed stat -if (!writeFreeMbTraffCost && freeMb.ConstData() >= 0) +if (!settings->GetWriteFreeMbTraffCost() && + freeMb.ConstData() >= 0) cost = 0; #ifdef TRAFF_STAT_WITH_PORTS @@ -952,25 +869,18 @@ IP_DIR_PAIR idp(ip, dir); #endif map::iterator lb; -lb = traffStat->lower_bound(idp); -if (lb == traffStat->end()) +lb = traffStat.lower_bound(idp); +if (lb == traffStat.end() || lb->first != idp) { - traffStat->insert(lb, - pair(idp, - STAT_NODE(0, len, cost))); + traffStat.insert(lb, + pair(idp, + STAT_NODE(0, len, cost))); } else - if (lb->first.dir == dir && lb->first.ip == ip) - { - lb->second.cash += cost; - lb->second.down += len; - } - else - { - traffStat->insert(lb, - pair(idp, - STAT_NODE(0, len, cost))); - } + { + lb->second.cash += cost; + lb->second.down += len; + } } //----------------------------------------------------------------------------- void USER::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE * n) @@ -1043,39 +953,49 @@ else Run(); } //----------------------------------------------------------------------------- -void USER::ResetDetailStat() +int USER::WriteDetailStat(bool hard) { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size()); -traffStatToWrite->erase(traffStatToWrite->begin(), traffStatToWrite->end()); -} -//----------------------------------------------------------------------------- -int USER::WriteDetailStat() -{ -STG_LOCKER lock(&mutex, __FILE__, __LINE__); +if (!traffStatSaved.second.empty()) + { + if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login)) + { + printfd(__FILE__, "USER::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; + } + traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end()); + } -printfd(__FILE__, "USER::WriteDetailedStat(): size = %d\n", traffStatToWrite->size()); +TRAFF_STAT ts; -if (traffStatToWrite->size() && !disabledDetailStat) { - if (store->WriteDetailedStat(traffStatToWrite, lastWriteDeatiledStat, login)) + STG_LOCKER lock(&mutex, __FILE__, __LINE__); + ts.swap(traffStat); + } + +printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size()); + +if (ts.size() && !disabledDetailStat) + { + if (store->WriteDetailedStat(ts, lastWriteDeatiledStat, login)) { + printfd(__FILE__, "USER::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__); + traffStatSaved.second.swap(ts); + traffStatSaved.first = lastWriteDeatiledStat; + } + return -1; } } -lastWriteDeatiledStat = lastSwapDeatiledStat; -return 0; -} -//----------------------------------------------------------------------------- -int USER::SwapDetailStat() -{ -STG_LOCKER lock(&mutex, __FILE__, __LINE__); - -lastSwapDeatiledStat = stgTime; -traffStatToWrite = &traffStatInternal[traffStatInUse % 2]; -traffStat = &traffStatInternal[++traffStatInUse % 2]; - +lastWriteDeatiledStat = stgTime; return 0; } //----------------------------------------------------------------------------- @@ -1086,13 +1006,13 @@ STG_LOCKER lock(&mutex, __FILE__, __LINE__); static int daysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -struct tm * tms; +struct tm tms; time_t t = stgTime; -tms = localtime(&t); +localtime_r(&t, &tms); -time_t secMonth = daysInMonth[(tms->tm_mon + 11) % 12] * 24 * 3600; // Previous month +time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month -if (tms->tm_year % 4 == 0 && tms->tm_mon == 1) +if (tms.tm_year % 4 == 0 && tms.tm_mon == 1) { // Leap year secMonth += 24 * 3600; @@ -1110,12 +1030,11 @@ void USER::SetPassiveTimeAsNewUser() { STG_LOCKER lock(&mutex, __FILE__, __LINE__); -time_t t; -struct tm * tm; -t = stgTime; -tm = localtime(&t); +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) / (double)daysCurrMon; passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon); } @@ -1232,7 +1151,18 @@ int USER::AddMessage(STG_MSG * msg) { STG_LOCKER lock(&mutex, __FILE__, __LINE__); -if (SendMessage(*msg) == 0) +if (SendMessage(*msg)) + { + if (store->AddMessage(msg, login)) + { + errorStr = store->GetStrError(); + WriteServLog("Error adding message: '%s'", errorStr.c_str()); + printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str()); + return -1; + } + messages.push_back(*msg); + } +else { if (msg->header.repeat > 0) { @@ -1246,100 +1176,87 @@ if (SendMessage(*msg) == 0) if (store->AddMessage(msg, login)) { errorStr = store->GetStrError(); - STG_LOGGER & WriteServLog = GetStgLogger(); - WriteServLog("Error adding message %s", errorStr.c_str()); - WriteServLog("%s", store->GetStrError().c_str()); + WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str()); + printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str()); return -1; } - } - } -else - { - if (store->AddMessage(msg, login)) - { - errorStr = store->GetStrError(); - STG_LOGGER & WriteServLog = GetStgLogger(); - WriteServLog("Error adding message %s", errorStr.c_str()); - WriteServLog("%s", store->GetStrError().c_str()); - return -1; + messages.push_back(*msg); } } return 0; } //----------------------------------------------------------------------------- -int USER::SendMessage(const STG_MSG & msg) +int USER::SendMessage(STG_MSG & msg) const { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); - -if (authorizedBy.empty()) - { - return -1; - } - +// No lock `cause we are already locked from caller int ret = -1; -set::iterator it; - -it = authorizedBy.begin(); +set::iterator it(authorizedBy.begin()); while (it != authorizedBy.end()) { - if ((*it)->SendMessage(msg, currIP) == 0) + if (!(*it++)->SendMessage(msg, currIP)) ret = 0; - ++it; + } +if (!ret) + { +#ifndef DEBUG + //TODO: gcc v. 4.x generate ICE on x86_64 + msg.header.lastSendTime = time(NULL); +#else + msg.header.lastSendTime = stgTime; +#endif + msg.header.repeat--; } return ret; } //----------------------------------------------------------------------------- -int USER::ScanMessage() +void USER::ScanMessage() { -STG_LOCKER lock(&mutex, __FILE__, __LINE__); - -vector hdrsList; - -if (store->GetMessageHdrs(&hdrsList, login)) - { - printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str()); - return -1; - } +// No lock `cause we are already locked from caller +// We need not check for the authorizedBy `cause it has already checked by caller -for (unsigned i = 0; i < hdrsList.size(); i++) +std::list::iterator it(messages.begin()); +while (it != messages.end()) { - - if (hdrsList[i].lastSendTime + hdrsList[i].repeatPeriod * 60 < (unsigned)stgTime) + if (settings->GetMessageTimeout() > 0 && + difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout()) { - STG_MSG msg; - if (store->GetMessage(hdrsList[i].id, &msg, login) == 0) + // Timeout exceeded + if (store->DelMessage(it->header.id, login)) { - if (SendMessage(msg) == 0) + WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str()); + printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str()); + } + messages.erase(it++); + continue; + } + if (it->GetNextSendTime() <= stgTime) + { + if (SendMessage(*it)) + { + // We need to check all messages in queue for timeout + ++it; + continue; + } + if (it->header.repeat < 0) + { + if (store->DelMessage(it->header.id, login)) { - msg.header.repeat--; - if (msg.header.repeat < 0) - { - printfd(__FILE__, "DelMessage\n"); - store->DelMessage(hdrsList[i].id, login); - } - else - { - #ifndef DEBUG - //TODO: gcc v. 4.x generate ICE on x86_64 - msg.header.lastSendTime = time(NULL); - #else - msg.header.lastSendTime = stgTime; - #endif - if (store->EditMessage(msg, login)) - { - printfd(__FILE__, "EditMessage Error %s\n", store->GetStrError().c_str()); - } - } + WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str()); + printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str()); } + messages.erase(it++); } else { - WriteServLog("Cannot get message for user %s.", login.c_str()); - WriteServLog("%s", store->GetStrError().c_str()); + if (store->EditMessage(*it, login)) + { + WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str()); + printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str()); + } + ++it; } } } -return 0; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -1369,8 +1286,10 @@ void CHG_IP_NOTIFIER::Notify(const uint32_t & from, const uint32_t & to) { printfd(__FILE__, "Change IP from %s to %s\n", inet_ntostring(from).c_str(), inet_ntostring(to).c_str()); if (from != 0) - user->Disconnect(false, "Change IP"); + if (user->connected) + user->Disconnect(false, "Change IP"); if (to != 0) - user->Connect(false); + if (user->IsInetable()) + user->Connect(false); } //-----------------------------------------------------------------------------