wesnothd: use std::chrono instead of the C time API
This commit is contained in:
parent
c2b2664eb2
commit
79120f1e31
20 changed files with 288 additions and 234 deletions
65
src/log.cpp
65
src/log.cpp
|
@ -23,6 +23,8 @@
|
|||
#include "log.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "mt_rng.hpp"
|
||||
#include "serialization/chrono.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "utils/general.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -399,41 +401,28 @@ bool broke_strict() {
|
|||
return strict_threw_;
|
||||
}
|
||||
|
||||
std::string get_timestamp(const std::time_t& t, const std::string& format) {
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << std::put_time(std::localtime(&t), format.c_str());
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
std::string get_timespan(const std::time_t& t) {
|
||||
std::ostringstream sout;
|
||||
// There doesn't seem to be any library function for this
|
||||
const std::time_t minutes = t / 60;
|
||||
const std::time_t days = minutes / 60 / 24;
|
||||
if(t <= 0) {
|
||||
sout << "expired";
|
||||
} else if(minutes == 0) {
|
||||
sout << t << " seconds";
|
||||
} else if(days == 0) {
|
||||
sout << minutes / 60 << " hours, " << minutes % 60 << " minutes";
|
||||
} else {
|
||||
sout << days << " days, " << (minutes / 60) % 24 << " hours, " << minutes % 60 << " minutes";
|
||||
}
|
||||
return sout.str();
|
||||
}
|
||||
|
||||
static void print_precise_timestamp(std::ostream& out) noexcept
|
||||
std::string format_timespan(const std::chrono::seconds& span)
|
||||
{
|
||||
try {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||
auto fractional = std::chrono::duration_cast<std::chrono::microseconds>(now - seconds);
|
||||
std::time_t tm = std::chrono::system_clock::to_time_t(seconds);
|
||||
char c = out.fill('0');
|
||||
out << std::put_time(std::localtime(&tm), "%Y%m%d %H:%M:%S") << "." << std::setw(6) << fractional.count() << ' ';
|
||||
out.fill(c);
|
||||
} catch(...) {}
|
||||
if(span <= std::chrono::seconds{0}) {
|
||||
return "expired";
|
||||
}
|
||||
|
||||
auto [days, hours, minutes, seconds] = chrono::deconstruct_duration(span);
|
||||
std::vector<std::string> formatted_values;
|
||||
|
||||
// TODO C++20: see if we can use the duration stream operators
|
||||
const auto format_time = [&formatted_values](const auto& val, const std::string& suffix) {
|
||||
if(val > std::decay_t<decltype(val)>{0}) {
|
||||
formatted_values.push_back(formatter{} << val.count() << " " << suffix);
|
||||
}
|
||||
};
|
||||
|
||||
format_time(days, "days");
|
||||
format_time(hours, "hours");
|
||||
format_time(minutes, "minutes");
|
||||
format_time(seconds, "seconds");
|
||||
|
||||
return utils::join(formatted_values, ", ");
|
||||
}
|
||||
|
||||
void set_log_sanitize(bool sanitize) {
|
||||
|
@ -502,10 +491,12 @@ void log_in_progress::operator|(formatter&& message)
|
|||
for(int i = 0; i < indent; ++i)
|
||||
stream_ << " ";
|
||||
if(timestamp_) {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
stream_ << chrono::format_local_timestamp(now); // Truncates precision to seconds
|
||||
if(precise_timestamp) {
|
||||
print_precise_timestamp(stream_);
|
||||
} else {
|
||||
stream_ << get_timestamp(std::time(nullptr));
|
||||
auto as_seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||
auto fractional = std::chrono::duration_cast<std::chrono::microseconds>(now - as_seconds);
|
||||
stream_ << "." << std::setw(6) << fractional.count();
|
||||
}
|
||||
}
|
||||
stream_ << prefix_ << sanitize_log(message.str());
|
||||
|
|
|
@ -230,8 +230,8 @@ public:
|
|||
|
||||
void timestamps(bool);
|
||||
void precise_timestamps(bool);
|
||||
std::string get_timestamp(const std::time_t& t, const std::string& format="%Y%m%d %H:%M:%S ");
|
||||
std::string get_timespan(const std::time_t& t);
|
||||
/** TODO: we also have utils::format_timespan, which does something very similar... */
|
||||
std::string format_timespan(const std::chrono::seconds& span);
|
||||
std::string sanitize_log(const std::string& logstr);
|
||||
std::string get_log_file_path();
|
||||
|
||||
|
|
|
@ -1755,10 +1755,11 @@ compression::format prefs::save_compression_format()
|
|||
std::string prefs::get_chat_timestamp(const std::time_t& t)
|
||||
{
|
||||
if(chat_timestamp()) {
|
||||
auto temp = std::chrono::system_clock::from_time_t(t); // FIXME: remove
|
||||
if(use_twelve_hour_clock_format() == false) {
|
||||
return lg::get_timestamp(t, _("[%H:%M]")) + " ";
|
||||
return chrono::format_local_timestamp(temp, _("[%H:%M]")) + " ";
|
||||
} else {
|
||||
return lg::get_timestamp(t, _("[%I:%M %p]")) + " ";
|
||||
return chrono::format_local_timestamp(temp, _("[%I:%M %p]")) + " ";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,37 @@
|
|||
#include "config_attribute_value.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
|
||||
#if __cpp_lib_chrono >= 201907L
|
||||
#define CPP20_CHRONO_SUPPORT
|
||||
#endif
|
||||
|
||||
namespace chrono
|
||||
{
|
||||
#ifdef CPP20_CHRONO_SUPPORT
|
||||
|
||||
using std::chrono::days;
|
||||
using std::chrono::weeks;
|
||||
using std::chrono::months;
|
||||
using std::chrono::years;
|
||||
|
||||
#else
|
||||
|
||||
using days = std::chrono::duration<int, std::ratio<86400>>;
|
||||
using weeks = std::chrono::duration<int, std::ratio<604800>>;
|
||||
using months = std::chrono::duration<int, std::ratio<2629746>>;
|
||||
using years = std::chrono::duration<int, std::ratio<31556952>>;
|
||||
|
||||
#endif
|
||||
|
||||
inline auto parse_timestamp(long long val)
|
||||
{
|
||||
return std::chrono::system_clock::from_time_t(val);
|
||||
}
|
||||
|
||||
inline auto parse_timestamp(const config_attribute_value& val)
|
||||
{
|
||||
return std::chrono::system_clock::from_time_t(val.to_long_long());
|
||||
|
@ -30,10 +58,29 @@ inline auto serialize_timestamp(const std::chrono::system_clock::time_point& tim
|
|||
return std::chrono::system_clock::to_time_t(time);
|
||||
}
|
||||
|
||||
inline auto format_local_timestamp(const std::chrono::system_clock::time_point& time, std::string_view format = "%F %T")
|
||||
{
|
||||
std::ostringstream ss;
|
||||
auto as_time_t = std::chrono::system_clock::to_time_t(time);
|
||||
ss << std::put_time(std::localtime(&as_time_t), format.data());
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
inline auto parse_duration(const config_attribute_value& val, const Duration& def = Duration{0})
|
||||
{
|
||||
return Duration{val.to_long_long(def.count())};
|
||||
}
|
||||
|
||||
template<typename Rep, typename Period>
|
||||
constexpr auto deconstruct_duration(const std::chrono::duration<Rep, Period>& span)
|
||||
{
|
||||
auto days = std::chrono::duration_cast<chrono::days>(span);
|
||||
auto hours = std::chrono::duration_cast<std::chrono::hours>(span - days);
|
||||
auto minutes = std::chrono::duration_cast<std::chrono::minutes>(span - days - hours);
|
||||
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(span - days - hours - minutes);
|
||||
|
||||
return std::tuple{ days, hours, minutes, seconds };
|
||||
}
|
||||
|
||||
} // namespace chrono
|
||||
|
|
|
@ -313,7 +313,7 @@ ban_check dbconn::get_ban_info(const std::string& name, const std::string& ip)
|
|||
// selected ban_type value must be part of user_handler::BAN_TYPE
|
||||
ban_check b;
|
||||
get_complex_results(connection_, b, "select ban_userid, ban_email, case when ban_ip != '' then 1 when ban_userid != 0 then 2 when ban_email != '' then 3 end as ban_type, ban_end from `"+db_banlist_table_+"` where (ban_ip = ? or ban_userid = (select user_id from `"+db_users_table_+"` where UPPER(username) = UPPER(?)) or UPPER(ban_email) = (select UPPER(user_email) from `"+db_users_table_+"` where UPPER(username) = UPPER(?))) AND ban_exclude = 0 AND (ban_end = 0 OR ban_end >= ?)",
|
||||
{ ip, name, name, std::time(nullptr) });
|
||||
{ ip, name, name, std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) });
|
||||
return b;
|
||||
}
|
||||
catch(const mariadb::exception::base& e)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "server/common/forum_user_handler.hpp"
|
||||
#include "server/wesnothd/server.hpp"
|
||||
#include "serialization/chrono.hpp"
|
||||
#include "hash.hpp"
|
||||
#include "log.hpp"
|
||||
#include "config.hpp"
|
||||
|
@ -99,7 +100,8 @@ std::string fuh::extract_salt(const std::string& name) {
|
|||
}
|
||||
|
||||
void fuh::user_logged_in(const std::string& name) {
|
||||
conn_.write_user_int("user_lastvisit", name, static_cast<int>(std::time(nullptr)));
|
||||
auto now = chrono::serialize_timestamp(std::chrono::system_clock::now());
|
||||
conn_.write_user_int("user_lastvisit", name, static_cast<int>(now));
|
||||
}
|
||||
|
||||
bool fuh::user_exists(const std::string& name) {
|
||||
|
@ -156,14 +158,15 @@ std::string fuh::user_info(const std::string& name) {
|
|||
throw error("No user with the name '" + name + "' exists.");
|
||||
}
|
||||
|
||||
std::time_t reg_date = get_registrationdate(name);
|
||||
std::time_t ll_date = get_lastlogin(name);
|
||||
auto reg_date = get_registrationdate(name);
|
||||
auto ll_date = get_lastlogin(name);
|
||||
|
||||
std::string reg_string = ctime(®_date);
|
||||
static constexpr std::string_view format = "%a %b %d %T %Y"; // equivalent to std::ctime
|
||||
std::string reg_string = chrono::format_local_timestamp(reg_date, format);
|
||||
std::string ll_string;
|
||||
|
||||
if(ll_date) {
|
||||
ll_string = ctime(&ll_date);
|
||||
if(ll_date > decltype(ll_date){}) {
|
||||
ll_string = chrono::format_local_timestamp(ll_date, format);
|
||||
} else {
|
||||
ll_string = "Never\n";
|
||||
}
|
||||
|
@ -191,12 +194,12 @@ void fuh::db_update_addon_download_count(const std::string& instance_version, co
|
|||
return conn_.update_addon_download_count(instance_version, id, version);
|
||||
}
|
||||
|
||||
std::time_t fuh::get_lastlogin(const std::string& user) {
|
||||
return std::time_t(conn_.get_user_int(db_extra_table_, "user_lastvisit", user));
|
||||
std::chrono::system_clock::time_point fuh::get_lastlogin(const std::string& user) {
|
||||
return chrono::parse_timestamp(conn_.get_user_int(db_extra_table_, "user_lastvisit", user));
|
||||
}
|
||||
|
||||
std::time_t fuh::get_registrationdate(const std::string& user) {
|
||||
return std::time_t(conn_.get_user_int(db_users_table_, "user_regdate", user));
|
||||
std::chrono::system_clock::time_point fuh::get_registrationdate(const std::string& user) {
|
||||
return chrono::parse_timestamp(conn_.get_user_int(db_users_table_, "user_regdate", user));
|
||||
}
|
||||
|
||||
std::string fuh::get_uuid(){
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
#include "server/common/user_handler.hpp"
|
||||
#include "server/common/dbconn.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <ctime>
|
||||
|
||||
/**
|
||||
* A class to handle the non-SQL logic for connecting to the phpbb forum database.
|
||||
|
@ -344,11 +344,11 @@ private:
|
|||
* @param user The player's username.
|
||||
* @return The player's last login time.
|
||||
*/
|
||||
std::time_t get_lastlogin(const std::string& user);
|
||||
std::chrono::system_clock::time_point get_lastlogin(const std::string& user);
|
||||
|
||||
/**
|
||||
* @param user The player's username.
|
||||
* @return The player's forum registration date.
|
||||
*/
|
||||
std::time_t get_registrationdate(const std::string& user);
|
||||
std::chrono::system_clock::time_point get_registrationdate(const std::string& user);
|
||||
};
|
||||
|
|
|
@ -14,28 +14,34 @@
|
|||
|
||||
#ifdef HAVE_MYSQLPP
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "server/common/resultsets/ban_check.hpp"
|
||||
#include "server/common/user_handler.hpp"
|
||||
#include "serialization/chrono.hpp"
|
||||
|
||||
ban_check::ban_check()
|
||||
: ban_type(user_handler::BAN_TYPE::BAN_NONE)
|
||||
, ban_duration(0)
|
||||
, user_id(0)
|
||||
, email()
|
||||
{
|
||||
ban_type = user_handler::BAN_TYPE::BAN_NONE;
|
||||
ban_duration = 0;
|
||||
user_id = 0;
|
||||
email = "";
|
||||
}
|
||||
|
||||
ban_check::ban_check(const mariadb::result_set& rslt)
|
||||
: ban_type(rslt.get_signed32("ban_type"))
|
||||
, ban_duration(0)
|
||||
, user_id(rslt.get_signed32("ban_userid"))
|
||||
, email(rslt.get_string("ban_email"))
|
||||
{
|
||||
auto ban_end = rslt.get_signed32("ban_end");
|
||||
if(ban_end == 0) return;
|
||||
|
||||
auto time_remaining = chrono::parse_timestamp(ban_end) - std::chrono::system_clock::now();
|
||||
ban_duration = std::chrono::duration_cast<std::chrono::seconds>(time_remaining);
|
||||
}
|
||||
|
||||
void ban_check::read(mariadb::result_set_ref rslt)
|
||||
{
|
||||
if(rslt->next())
|
||||
{
|
||||
ban_type = rslt->get_signed32("ban_type");
|
||||
ban_duration = rslt->get_signed32("ban_end") != 0 ? rslt->get_signed32("ban_end") - std::time(nullptr) : 0;
|
||||
user_id = rslt->get_signed32("ban_userid");
|
||||
email = rslt->get_string("ban_email");
|
||||
}
|
||||
if(rslt->next()) { *this = ban_check{*rslt}; }
|
||||
}
|
||||
|
||||
long ban_check::get_ban_type()
|
||||
|
@ -43,7 +49,7 @@ long ban_check::get_ban_type()
|
|||
return ban_type;
|
||||
}
|
||||
|
||||
int ban_check::get_ban_duration()
|
||||
std::chrono::seconds ban_check::get_ban_duration()
|
||||
{
|
||||
return ban_duration;
|
||||
}
|
||||
|
|
|
@ -18,19 +18,22 @@
|
|||
|
||||
#include "server/common/resultsets/rs_base.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
class ban_check : public rs_base
|
||||
{
|
||||
public:
|
||||
ban_check();
|
||||
void read(mariadb::result_set_ref rslt);
|
||||
explicit ban_check(const mariadb::result_set& rslt);
|
||||
void read(mariadb::result_set_ref rslt) override;
|
||||
long get_ban_type();
|
||||
int get_ban_duration();
|
||||
std::chrono::seconds get_ban_duration();
|
||||
int get_user_id();
|
||||
std::string get_email();
|
||||
|
||||
private:
|
||||
long ban_type;
|
||||
int ban_duration;
|
||||
std::chrono::seconds ban_duration;
|
||||
int user_id;
|
||||
std::string email;
|
||||
};
|
||||
|
|
|
@ -19,7 +19,6 @@ class config;
|
|||
|
||||
#include "exceptions.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
@ -103,20 +102,8 @@ public:
|
|||
/** Ban status description */
|
||||
struct ban_info
|
||||
{
|
||||
BAN_TYPE type; /**< Ban type */
|
||||
std::time_t duration; /**< Ban duration (0 if permanent) */
|
||||
|
||||
ban_info()
|
||||
: type(BAN_NONE)
|
||||
, duration(0)
|
||||
{
|
||||
}
|
||||
|
||||
ban_info(BAN_TYPE ptype, std::time_t pduration)
|
||||
: type(ptype)
|
||||
, duration(pduration)
|
||||
{
|
||||
}
|
||||
BAN_TYPE type = BAN_NONE; /**< Ban type */
|
||||
std::chrono::seconds duration{0}; /**< Ban duration (0 if permanent) */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "lexical_cast.hpp"
|
||||
#include "log.hpp"
|
||||
#include "serialization/binary_or_text.hpp"
|
||||
#include "serialization/chrono.hpp"
|
||||
#include "serialization/parser.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "serialization/unicode.hpp"
|
||||
|
@ -67,8 +68,8 @@ banned::banned(const std::string& ip)
|
|||
: ip_(0)
|
||||
, mask_(0)
|
||||
, ip_text_()
|
||||
, end_time_(0)
|
||||
, start_time_(0)
|
||||
, end_time_()
|
||||
, start_time_()
|
||||
, reason_()
|
||||
, who_banned_(who_banned_default_)
|
||||
, group_()
|
||||
|
@ -80,7 +81,7 @@ banned::banned(const std::string& ip)
|
|||
}
|
||||
|
||||
banned::banned(const std::string& ip,
|
||||
const std::time_t end_time,
|
||||
const utils::optional<std::chrono::system_clock::time_point>& end_time,
|
||||
const std::string& reason,
|
||||
const std::string& who_banned,
|
||||
const std::string& group,
|
||||
|
@ -89,7 +90,7 @@ banned::banned(const std::string& ip,
|
|||
, mask_(0)
|
||||
, ip_text_(ip)
|
||||
, end_time_(end_time)
|
||||
, start_time_(std::time(0))
|
||||
, start_time_(std::chrono::system_clock::now())
|
||||
, reason_(reason)
|
||||
, who_banned_(who_banned)
|
||||
, group_(group)
|
||||
|
@ -104,8 +105,8 @@ banned::banned(const config& cfg)
|
|||
: ip_(0)
|
||||
, mask_(0)
|
||||
, ip_text_()
|
||||
, end_time_(0)
|
||||
, start_time_(0)
|
||||
, end_time_()
|
||||
, start_time_()
|
||||
, reason_()
|
||||
, who_banned_(who_banned_default_)
|
||||
, group_()
|
||||
|
@ -172,11 +173,11 @@ void banned::read(const config& cfg)
|
|||
nick_ = cfg["nick"].str();
|
||||
|
||||
if(cfg.has_attribute("end_time")) {
|
||||
end_time_ = cfg["end_time"].to_time_t(0);
|
||||
end_time_ = chrono::parse_timestamp(cfg["end_time"]);
|
||||
}
|
||||
|
||||
if(cfg.has_attribute("start_time")) {
|
||||
start_time_ = cfg["start_time"].to_time_t(0);
|
||||
start_time_ = chrono::parse_timestamp(cfg["start_time"]);
|
||||
}
|
||||
|
||||
reason_ = cfg["reason"].str();
|
||||
|
@ -196,16 +197,12 @@ void banned::write(config& cfg) const
|
|||
cfg["ip"] = get_ip();
|
||||
cfg["nick"] = get_nick();
|
||||
|
||||
if(end_time_ > 0) {
|
||||
std::stringstream ss;
|
||||
ss << end_time_;
|
||||
cfg["end_time"] = ss.str();
|
||||
if(end_time_) {
|
||||
cfg["end_time"] = chrono::serialize_timestamp(*end_time_);
|
||||
}
|
||||
|
||||
if(start_time_ > 0) {
|
||||
std::stringstream ss;
|
||||
ss << start_time_;
|
||||
cfg["start_time"] = ss.str();
|
||||
if(start_time_) {
|
||||
cfg["start_time"] = chrono::serialize_timestamp(*start_time_);
|
||||
}
|
||||
|
||||
cfg["reason"] = reason_;
|
||||
|
@ -221,34 +218,36 @@ void banned::write(config& cfg) const
|
|||
|
||||
std::string banned::get_human_start_time() const
|
||||
{
|
||||
if(start_time_ == 0) {
|
||||
if(start_time_) {
|
||||
return chrono::format_local_timestamp(*start_time_);
|
||||
} else {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
return lg::get_timestamp(start_time_);
|
||||
}
|
||||
|
||||
std::string banned::get_human_end_time() const
|
||||
{
|
||||
if(end_time_ == 0) {
|
||||
if(end_time_) {
|
||||
return chrono::format_local_timestamp(*end_time_);
|
||||
} else {
|
||||
return "permanent";
|
||||
}
|
||||
|
||||
return lg::get_timestamp(end_time_);
|
||||
}
|
||||
|
||||
std::string banned::get_human_time_span() const
|
||||
{
|
||||
if(end_time_ == 0) {
|
||||
if(!end_time_) {
|
||||
return "permanent";
|
||||
}
|
||||
|
||||
return lg::get_timespan(end_time_ - std::time(nullptr));
|
||||
auto remaining = *end_time_ - std::chrono::system_clock::now();
|
||||
return lg::format_timespan(std::chrono::duration_cast<std::chrono::seconds>(remaining));
|
||||
}
|
||||
|
||||
bool banned::operator>(const banned& b) const
|
||||
{
|
||||
return end_time_ > b.get_end_time();
|
||||
static constexpr std::chrono::system_clock::time_point epoch;
|
||||
return end_time_.value_or(epoch) > b.get_end_time().value_or(epoch);
|
||||
}
|
||||
|
||||
unsigned int banned::get_mask_ip(unsigned int mask) const
|
||||
|
@ -284,7 +283,7 @@ void ban_manager::read()
|
|||
auto new_ban = std::make_shared<banned>(b);
|
||||
assert(bans_.insert(new_ban).second);
|
||||
|
||||
if (new_ban->get_end_time() != 0)
|
||||
if (new_ban->get_end_time())
|
||||
time_queue_.push(new_ban);
|
||||
} catch(const banned::error& e) {
|
||||
ERR_SERVER << e.message << " while reading bans";
|
||||
|
@ -330,13 +329,12 @@ void ban_manager::write()
|
|||
writer.write(cfg);
|
||||
}
|
||||
|
||||
bool ban_manager::parse_time(const std::string& duration, std::time_t* time) const
|
||||
std::pair<bool, utils::optional<std::chrono::system_clock::time_point>> ban_manager::parse_time(
|
||||
const std::string& duration, std::chrono::system_clock::time_point start_time) const
|
||||
{
|
||||
if (!time) return false;
|
||||
|
||||
if(duration.substr(0, 4) == "TIME") {
|
||||
std::tm* loc;
|
||||
loc = std::localtime(time);
|
||||
auto as_time_t = std::chrono::system_clock::to_time_t(start_time);
|
||||
std::tm* loc = std::localtime(&as_time_t);
|
||||
|
||||
std::size_t number = 0;
|
||||
for(auto i = duration.begin() + 4; i != duration.end(); ++i) {
|
||||
|
@ -369,24 +367,21 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
number = 0;
|
||||
}
|
||||
}
|
||||
*time = mktime(loc);
|
||||
return true;
|
||||
return { true, std::chrono::system_clock::from_time_t(std::mktime(loc)) };
|
||||
}
|
||||
|
||||
const auto time_itor = ban_times_.find(duration);
|
||||
|
||||
std::string dur_lower;
|
||||
try {
|
||||
dur_lower = utf8::lowercase(duration);
|
||||
} catch(const utf8::invalid_utf8_exception& e) {
|
||||
ERR_SERVER << "While parsing ban command duration string, caught an invalid utf8 exception: " << e.what();
|
||||
return false;
|
||||
return { false, utils::nullopt };
|
||||
}
|
||||
|
||||
if(dur_lower == "permanent" || duration == "0") {
|
||||
*time = 0;
|
||||
} else if(ban_times_.find(duration) != ban_times_.end()) {
|
||||
*time += time_itor->second;
|
||||
return { true, utils::nullopt };
|
||||
} else if(const auto time_itor = ban_times_.find(duration); time_itor != ban_times_.end()) {
|
||||
return { true, start_time + time_itor->second };
|
||||
} else {
|
||||
std::string::const_iterator i = duration.begin();
|
||||
int number = -1;
|
||||
|
@ -406,7 +401,7 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
&& ++i != d_end && tolower(*i) == 'r'
|
||||
&& ++i != d_end && tolower(*i) == 's') {
|
||||
} else --i;
|
||||
*time += number * 365*24*60*60; // a year;
|
||||
start_time += chrono::years{number};
|
||||
break;
|
||||
case 'M':
|
||||
if (++i != d_end && tolower(*i) == 'i') {
|
||||
|
@ -416,7 +411,7 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
&& ++i != d_end && tolower(*i) == 'e'
|
||||
&& ++i != d_end && tolower(*i) == 's') {
|
||||
} else --i;
|
||||
*time += number * 60;
|
||||
start_time += std::chrono::minutes{number};
|
||||
break;
|
||||
}
|
||||
--i;
|
||||
|
@ -426,7 +421,7 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
&& ++i != d_end && tolower(*i) == 'h'
|
||||
&& ++i != d_end && tolower(*i) == 's') {
|
||||
} else --i;
|
||||
*time += number * 30*24*60*60; // 30 days
|
||||
start_time += chrono::months{number};
|
||||
break;
|
||||
case 'D':
|
||||
case 'd':
|
||||
|
@ -434,7 +429,7 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
&& ++i != d_end && tolower(*i) == 'y'
|
||||
&& ++i != d_end && tolower(*i) == 's') {
|
||||
} else --i;
|
||||
*time += number * 24*60*60;
|
||||
start_time += chrono::days{number};
|
||||
break;
|
||||
case 'H':
|
||||
case 'h':
|
||||
|
@ -443,7 +438,7 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
&& ++i != d_end && tolower(*i) == 'r'
|
||||
&& ++i != d_end && tolower(*i) == 's') {
|
||||
} else --i;
|
||||
*time += number * 60*60;
|
||||
start_time += std::chrono::hours{number};
|
||||
break;
|
||||
case 'm':
|
||||
if (++i != d_end && tolower(*i) == 'o') {
|
||||
|
@ -452,7 +447,7 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
&& ++i != d_end && tolower(*i) == 'h'
|
||||
&& ++i != d_end && tolower(*i) == 's') {
|
||||
} else --i;
|
||||
*time += number * 30*24*60*60; // 30 days
|
||||
start_time += chrono::months{number};
|
||||
break;
|
||||
}
|
||||
--i;
|
||||
|
@ -463,7 +458,7 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
&& ++i != d_end && tolower(*i) == 'e'
|
||||
&& ++i != d_end && tolower(*i) == 's') {
|
||||
} else --i;
|
||||
*time += number * 60;
|
||||
start_time += std::chrono::minutes{number};
|
||||
break;
|
||||
case 'S':
|
||||
case 's':
|
||||
|
@ -474,10 +469,10 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
&& ++i != d_end && tolower(*i) == 'd'
|
||||
&& ++i != d_end && tolower(*i) == 's') {
|
||||
} else --i;
|
||||
*time += number;
|
||||
start_time += std::chrono::seconds{number};
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
return { false, utils::nullopt };
|
||||
break;
|
||||
}
|
||||
number = -1;
|
||||
|
@ -485,15 +480,15 @@ bool ban_manager::parse_time(const std::string& duration, std::time_t* time) con
|
|||
}
|
||||
|
||||
if(is_digit(*--i)) {
|
||||
*time += number * 60; // default to minutes
|
||||
start_time += std::chrono::minutes{number}; // default to minutes
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return { true, start_time };
|
||||
}
|
||||
}
|
||||
|
||||
std::string ban_manager::ban(const std::string& ip,
|
||||
const std::time_t& end_time,
|
||||
const utils::optional<std::chrono::system_clock::time_point>& end_time,
|
||||
const std::string& reason,
|
||||
const std::string& who_banned,
|
||||
const std::string& group,
|
||||
|
@ -515,7 +510,7 @@ std::string ban_manager::ban(const std::string& ip,
|
|||
try {
|
||||
auto new_ban = std::make_shared<banned>(ip, end_time, reason, who_banned, group, nick);
|
||||
bans_.insert(new_ban);
|
||||
if(end_time != 0) {
|
||||
if(end_time) {
|
||||
time_queue_.push(new_ban);
|
||||
}
|
||||
ret << *new_ban;
|
||||
|
@ -568,20 +563,26 @@ void ban_manager::unban_group(std::ostringstream& os, const std::string& group)
|
|||
write();
|
||||
}
|
||||
|
||||
void ban_manager::check_ban_times(std::time_t time_now)
|
||||
void ban_manager::check_ban_times(const std::chrono::system_clock::time_point& time_now)
|
||||
{
|
||||
while(!time_queue_.empty()) {
|
||||
banned_ptr ban = time_queue_.top();
|
||||
const auto& end_time = ban->get_end_time();
|
||||
|
||||
if(ban->get_end_time() > time_now) {
|
||||
if(!end_time || *end_time > time_now) {
|
||||
// No bans going to expire
|
||||
DBG_SERVER << "ban " << ban->get_ip() << " not removed. time: " << time_now << " end_time "
|
||||
<< ban->get_end_time();
|
||||
DBG_SERVER
|
||||
<< "Ban on " << ban->get_ip() << " not removed."
|
||||
<< " time: " << chrono::format_local_timestamp(time_now)
|
||||
<< " end_time: " << (end_time ? chrono::format_local_timestamp(*end_time) : "none");
|
||||
break;
|
||||
}
|
||||
|
||||
// This ban is going to expire so delete it.
|
||||
LOG_SERVER << "Remove a ban " << ban->get_ip() << ". time: " << time_now << " end_time " << ban->get_end_time();
|
||||
LOG_SERVER
|
||||
<< "Removing ban on " << ban->get_ip() << "."
|
||||
<< " time: " << chrono::format_local_timestamp(time_now)
|
||||
<< " end_time: " << chrono::format_local_timestamp(*end_time);
|
||||
std::ostringstream os;
|
||||
unban(os, ban->get_ip(), false);
|
||||
time_queue_.pop();
|
||||
|
@ -698,9 +699,12 @@ void ban_manager::load_config(const config& cfg)
|
|||
{
|
||||
ban_times_.clear();
|
||||
for(const config& bt : cfg.child_range("ban_time")) {
|
||||
std::time_t duration = 0;
|
||||
if(parse_time(bt["time"], &duration)) {
|
||||
ban_times_.emplace(bt["name"], duration);
|
||||
// Use the zero time point so we can easily convert the end time point to a duration
|
||||
auto [success, end_time] = parse_time(bt["time"], {});
|
||||
|
||||
if(success) {
|
||||
auto duration = end_time.value_or(decltype(end_time)::value_type{}).time_since_epoch();
|
||||
ban_times_.emplace(bt["name"], std::chrono::duration_cast<std::chrono::seconds>(duration));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "exceptions.hpp"
|
||||
#include "utils/optional_fwd.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
@ -52,7 +52,7 @@ private:
|
|||
typedef std::set<banned_ptr, banned_compare_subnet> ban_set;
|
||||
typedef std::list<banned_ptr> deleted_ban_list;
|
||||
typedef std::priority_queue<banned_ptr, std::vector<banned_ptr>, banned_compare> ban_time_queue;
|
||||
typedef std::map<std::string, std::size_t> default_ban_times;
|
||||
typedef std::map<std::string, std::chrono::seconds> default_ban_times;
|
||||
typedef std::pair<unsigned int, unsigned int> ip_mask;
|
||||
|
||||
ip_mask parse_ip(const std::string&);
|
||||
|
@ -61,8 +61,8 @@ class banned {
|
|||
unsigned int ip_;
|
||||
unsigned int mask_;
|
||||
std::string ip_text_;
|
||||
std::time_t end_time_;
|
||||
std::time_t start_time_;
|
||||
utils::optional<std::chrono::system_clock::time_point> end_time_;
|
||||
utils::optional<std::chrono::system_clock::time_point> start_time_;
|
||||
std::string reason_;
|
||||
std::string who_banned_;
|
||||
std::string group_;
|
||||
|
@ -70,7 +70,13 @@ class banned {
|
|||
static const std::string who_banned_default_;
|
||||
|
||||
public:
|
||||
banned(const std::string& ip, const std::time_t end_time, const std::string& reason, const std::string& who_banned=who_banned_default_, const std::string& group="", const std::string& nick="");
|
||||
banned(const std::string& ip,
|
||||
const utils::optional<std::chrono::system_clock::time_point>& end_time,
|
||||
const std::string& reason,
|
||||
const std::string& who_banned = who_banned_default_,
|
||||
const std::string& group = "",
|
||||
const std::string& nick = "");
|
||||
|
||||
banned(const config&);
|
||||
|
||||
banned(const std::string& ip);
|
||||
|
@ -78,13 +84,12 @@ public:
|
|||
void read(const config&);
|
||||
void write(config&) const;
|
||||
|
||||
std::time_t get_end_time() const
|
||||
const auto& get_end_time() const
|
||||
{ return end_time_; }
|
||||
|
||||
std::string get_human_end_time() const;
|
||||
std::string get_human_start_time() const;
|
||||
std::string get_human_time_span() const;
|
||||
static std::string get_human_time(const std::time_t&);
|
||||
|
||||
std::string get_reason() const
|
||||
{ return reason_; }
|
||||
|
@ -141,10 +146,10 @@ class ban_manager
|
|||
}
|
||||
|
||||
void init_ban_help();
|
||||
void check_ban_times(std::time_t time_now);
|
||||
void check_ban_times(const std::chrono::system_clock::time_point& time_now);
|
||||
inline void expire_bans()
|
||||
{
|
||||
check_ban_times(std::time(nullptr));
|
||||
check_ban_times(std::chrono::system_clock::now());
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -160,9 +165,16 @@ public:
|
|||
* @returns false if an invalid time modifier is encountered.
|
||||
* *time is undefined in that case.
|
||||
*/
|
||||
bool parse_time(const std::string& duration, std::time_t* time) const;
|
||||
std::pair<bool, utils::optional<std::chrono::system_clock::time_point>> parse_time(
|
||||
const std::string& duration, std::chrono::system_clock::time_point start_time) const;
|
||||
|
||||
std::string ban(const std::string& ip,
|
||||
const utils::optional<std::chrono::system_clock::time_point>& end_time,
|
||||
const std::string& reason,
|
||||
const std::string& who_banned,
|
||||
const std::string& group,
|
||||
const std::string& nick = "");
|
||||
|
||||
std::string ban(const std::string&, const std::time_t&, const std::string&, const std::string&, const std::string&, const std::string& = "");
|
||||
void unban(std::ostringstream& os, const std::string& ip, bool immediate_write=true);
|
||||
void unban_group(std::ostringstream& os, const std::string& group);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "filesystem.hpp"
|
||||
#include "lexical_cast.hpp"
|
||||
#include "log.hpp"
|
||||
#include "serialization/chrono.hpp"
|
||||
#include "server/wesnothd/player_network.hpp"
|
||||
#include "server/wesnothd/server.hpp"
|
||||
|
||||
|
@ -1975,7 +1976,7 @@ void game::send_server_message(const char* message, utils::optional<player_itera
|
|||
msg.set_attr("id", "server");
|
||||
msg.set_attr_dup("message", message);
|
||||
std::stringstream ss;
|
||||
ss << ::std::time(nullptr);
|
||||
ss << chrono::serialize_timestamp(std::chrono::system_clock::now());
|
||||
msg.set_attr_dup("time", ss.str().c_str());
|
||||
} else {
|
||||
simple_wml::node& msg = doc.root().add_child("message");
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "server/wesnothd/metrics.hpp"
|
||||
|
||||
#include "serialization/chrono.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
|
||||
|
@ -42,7 +44,7 @@ metrics::metrics()
|
|||
, current_requests_(0)
|
||||
, nrequests_(0)
|
||||
, nrequests_waited_(0)
|
||||
, started_at_(std::time(nullptr))
|
||||
, started_at_(std::chrono::steady_clock::now())
|
||||
, terminations_()
|
||||
{
|
||||
}
|
||||
|
@ -74,7 +76,9 @@ void metrics::no_requests()
|
|||
current_requests_ = 0;
|
||||
}
|
||||
|
||||
void metrics::record_sample(const simple_wml::string_span& name, clock_t parsing_time, clock_t processing_time)
|
||||
void metrics::record_sample(const simple_wml::string_span& name,
|
||||
const std::chrono::steady_clock::duration& parsing_time,
|
||||
const std::chrono::steady_clock::duration& processing_time)
|
||||
{
|
||||
auto isample = std::lower_bound(samples_.begin(), samples_.end(), name,compare_samples_to_stringspan());
|
||||
if(isample == samples_.end() || isample->name != name) {
|
||||
|
@ -128,34 +132,32 @@ std::ostream& metrics::requests(std::ostream& out) const
|
|||
out << "\nSampled request types:\n";
|
||||
|
||||
std::size_t n = 0;
|
||||
std::size_t pa = 0;
|
||||
std::size_t pr = 0;
|
||||
std::chrono::steady_clock::duration pa{0};
|
||||
std::chrono::steady_clock::duration pr{0};
|
||||
for(const auto& s : ordered_samples) {
|
||||
out << "'" << s.name << "' called " << s.nsamples << " times "
|
||||
<< s.parsing_time << "("<< s.max_parsing_time <<") parsing time, "
|
||||
<< s.processing_time << "("<<s.max_processing_time<<") processing time\n";
|
||||
<< s.parsing_time.count() << "(" << s.max_parsing_time.count() << ") parsing time, "
|
||||
<< s.processing_time.count() << "(" << s.max_processing_time.count() << ") processing time\n";
|
||||
n += s.nsamples;
|
||||
pa += s.parsing_time;
|
||||
pr += s.processing_time;
|
||||
}
|
||||
out << "Total number of request samples = " << n << "\n"
|
||||
<< "Total parsing time = " << pa << "\n"
|
||||
<< "Total processing time = " << pr;
|
||||
<< "Total parsing time = " << pa.count() << "\n"
|
||||
<< "Total processing time = " << pr.count();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, metrics& met)
|
||||
{
|
||||
const std::time_t time_up = std::time(nullptr) - met.started_at_;
|
||||
const int seconds = time_up%60;
|
||||
const int minutes = (time_up/60)%60;
|
||||
const int hours = (time_up/(60*60))%24;
|
||||
const int days = time_up/(60*60*24);
|
||||
const auto time_up = std::chrono::steady_clock::now() - met.started_at_;
|
||||
auto [days, hours, minutes, seconds] = chrono::deconstruct_duration(time_up);
|
||||
|
||||
const int requests_immediate = met.nrequests_ - met.nrequests_waited_;
|
||||
const int percent_immediate = (requests_immediate*100)/(met.nrequests_ > 0 ? met.nrequests_ : 1);
|
||||
out << "METRICS\nUp " << days << " days, " << hours << " hours, "
|
||||
<< minutes << " minutes, " << seconds << " seconds\n"
|
||||
out << "METRICS\nUp " << days.count() << " days, " << hours.count() << " hours, "
|
||||
<< minutes.count() << " minutes, " << seconds.count() << " seconds\n"
|
||||
<< met.nrequests_ << " requests serviced. " << requests_immediate
|
||||
<< " (" << percent_immediate << "%) "
|
||||
<< "requests were serviced immediately.\n"
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "server/common/simple_wml.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
@ -31,7 +31,10 @@ public:
|
|||
void service_request();
|
||||
void no_requests();
|
||||
|
||||
void record_sample(const simple_wml::string_span& name, clock_t parsing_time, clock_t processing_time);
|
||||
/** @todo: Currently unused. Use for something? */
|
||||
void record_sample(const simple_wml::string_span& name,
|
||||
const std::chrono::steady_clock::duration& parsing_time,
|
||||
const std::chrono::steady_clock::duration& processing_time);
|
||||
|
||||
void game_terminated(const std::string& reason);
|
||||
|
||||
|
@ -41,20 +44,12 @@ public:
|
|||
|
||||
struct sample
|
||||
{
|
||||
sample()
|
||||
: name()
|
||||
, nsamples(0)
|
||||
, parsing_time(0)
|
||||
, processing_time(0)
|
||||
, max_parsing_time(0)
|
||||
, max_processing_time(0)
|
||||
{
|
||||
}
|
||||
|
||||
simple_wml::string_span name;
|
||||
int nsamples;
|
||||
clock_t parsing_time, processing_time;
|
||||
clock_t max_parsing_time, max_processing_time;
|
||||
simple_wml::string_span name{};
|
||||
int nsamples = 0;
|
||||
std::chrono::steady_clock::duration parsing_time{0};
|
||||
std::chrono::steady_clock::duration processing_time{0};
|
||||
std::chrono::steady_clock::duration max_parsing_time{0};
|
||||
std::chrono::steady_clock::duration max_processing_time{0};
|
||||
|
||||
operator const simple_wml::string_span&()
|
||||
{
|
||||
|
@ -69,7 +64,7 @@ private:
|
|||
int current_requests_;
|
||||
int nrequests_;
|
||||
int nrequests_waited_;
|
||||
const std::time_t started_at_;
|
||||
const std::chrono::steady_clock::time_point started_at_;
|
||||
std::map<std::string, int> terminations_;
|
||||
};
|
||||
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
|
||||
wesnothd::player::player(const std::string& n, simple_wml::node& cfg, long id,
|
||||
bool registered, const std::string& version, const std::string& source, unsigned long long login_id, const std::size_t max_messages,
|
||||
const std::size_t time_period,
|
||||
const std::chrono::seconds& time_period,
|
||||
const bool moderator)
|
||||
: name_(n)
|
||||
, version_(version)
|
||||
, source_(source)
|
||||
, cfg_(cfg)
|
||||
, registered_(registered)
|
||||
, flood_start_(0)
|
||||
, flood_start_()
|
||||
, messages_since_flood_start_(0)
|
||||
, MaxMessages(max_messages)
|
||||
, TimePeriod(time_period)
|
||||
|
@ -80,8 +80,8 @@ void wesnothd::player::mark_registered(bool registered)
|
|||
|
||||
bool wesnothd::player::is_message_flooding()
|
||||
{
|
||||
const std::time_t now = std::time(nullptr);
|
||||
if (flood_start_ == 0) {
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
if (flood_start_ == std::chrono::system_clock::time_point{}) {
|
||||
flood_start_ = now;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "server/common/simple_wml.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <set>
|
||||
|
||||
namespace wesnothd {
|
||||
|
@ -32,7 +32,7 @@ public:
|
|||
};
|
||||
|
||||
player(const std::string& n, simple_wml::node& cfg, long id, bool registered, const std::string& version, const std::string& source,
|
||||
unsigned long long login_id, const std::size_t max_messages=4, const std::size_t time_period=10,
|
||||
unsigned long long login_id, const std::size_t max_messages=4, const std::chrono::seconds& time_period=std::chrono::seconds{10},
|
||||
const bool moderator=false);
|
||||
|
||||
void set_status(STATUS status);
|
||||
|
@ -65,10 +65,10 @@ private:
|
|||
|
||||
bool registered_;
|
||||
|
||||
std::time_t flood_start_;
|
||||
std::chrono::system_clock::time_point flood_start_;
|
||||
unsigned int messages_since_flood_start_;
|
||||
const std::size_t MaxMessages;
|
||||
const std::time_t TimePeriod;
|
||||
const std::chrono::seconds TimePeriod;
|
||||
STATUS status_;
|
||||
bool moderator_;
|
||||
unsigned long long login_id_;
|
||||
|
|
|
@ -70,7 +70,7 @@ public:
|
|||
|
||||
void enter_lobby();
|
||||
|
||||
const std::chrono::time_point<std::chrono::steady_clock> login_time;
|
||||
const std::chrono::steady_clock::time_point login_time;
|
||||
|
||||
private:
|
||||
const any_socket_ptr socket_;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "filesystem.hpp"
|
||||
#include "log.hpp"
|
||||
#include "multiplayer_error_codes.hpp"
|
||||
#include "serialization/chrono.hpp"
|
||||
#include "serialization/parser.hpp"
|
||||
#include "serialization/preprocessor.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
|
@ -75,6 +76,8 @@ static lg::log_domain log_config("config");
|
|||
#define ERR_CONFIG LOG_STREAM(err, log_config)
|
||||
#define WRN_CONFIG LOG_STREAM(warn, log_config)
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace wesnothd
|
||||
{
|
||||
// we take profiling info on every n requests
|
||||
|
@ -187,7 +190,7 @@ static std::string player_status(const wesnothd::player_record& player)
|
|||
{
|
||||
std::ostringstream out;
|
||||
out << "'" << player.name() << "' @ " << player.client_ip()
|
||||
<< " logged on for " << lg::get_timespan(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - player.login_time).count());
|
||||
<< " logged on for " << lg::format_timespan(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - player.login_time));
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
@ -232,8 +235,7 @@ server::server(int port,
|
|||
, default_time_period_(0)
|
||||
, concurrent_connections_(0)
|
||||
, graceful_restart(false)
|
||||
, lan_server_(std::time(nullptr))
|
||||
, last_user_seen_time_(std::time(nullptr))
|
||||
, lan_server_(0)
|
||||
, restart_command()
|
||||
, max_ip_log_size_(0)
|
||||
, deny_unregistered_login_(false)
|
||||
|
@ -289,14 +291,14 @@ void server::handle_graceful_timeout(const boost::system::error_code& error)
|
|||
process_command("msg All games ended. Shutting down now. Reconnect to the new server instance.", "system");
|
||||
BOOST_THROW_EXCEPTION(server_shutdown("graceful shutdown timeout"));
|
||||
} else {
|
||||
timer_.expires_from_now(std::chrono::seconds(1));
|
||||
timer_.expires_from_now(1s);
|
||||
timer_.async_wait(std::bind(&server::handle_graceful_timeout, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
||||
void server::start_lan_server_timer()
|
||||
{
|
||||
lan_server_timer_.expires_from_now(std::chrono::seconds(lan_server_));
|
||||
lan_server_timer_.expires_from_now(lan_server_);
|
||||
lan_server_timer_.async_wait([this](const boost::system::error_code& ec) { handle_lan_server_shutdown(ec); });
|
||||
}
|
||||
|
||||
|
@ -452,7 +454,7 @@ void server::load_config()
|
|||
information_ = cfg_["information"].str();
|
||||
announcements_ = cfg_["announcements"].str();
|
||||
server_id_ = cfg_["id"].str();
|
||||
lan_server_ = cfg_["lan_server"].to_time_t(0);
|
||||
lan_server_ = chrono::parse_duration(cfg_["lan_server"], 0s);
|
||||
|
||||
deny_unregistered_login_ = cfg_["deny_unregistered_login"].to_bool();
|
||||
|
||||
|
@ -479,12 +481,12 @@ void server::load_config()
|
|||
}
|
||||
|
||||
default_max_messages_ = cfg_["max_messages"].to_int(4);
|
||||
default_time_period_ = cfg_["messages_time_period"].to_int(10);
|
||||
default_time_period_ = chrono::parse_duration(cfg_["messages_time_period"], 10s);
|
||||
concurrent_connections_ = cfg_["connections_allowed"].to_int(5);
|
||||
max_ip_log_size_ = cfg_["max_ip_log_size"].to_int(500);
|
||||
|
||||
failed_login_limit_ = cfg_["failed_logins_limit"].to_int(10);
|
||||
failed_login_ban_ = cfg_["failed_logins_ban"].to_int(3600);
|
||||
failed_login_ban_ = chrono::parse_duration(cfg_["failed_logins_ban"], 3600s);
|
||||
failed_login_buffer_size_ = cfg_["failed_logins_buffer_size"].to_int(500);
|
||||
|
||||
// Example config line:
|
||||
|
@ -587,7 +589,7 @@ std::string server::is_ip_banned(const std::string& ip)
|
|||
|
||||
void server::start_dump_stats()
|
||||
{
|
||||
dump_stats_timer_.expires_after(std::chrono::minutes(5));
|
||||
dump_stats_timer_.expires_after(5min);
|
||||
dump_stats_timer_.async_wait([this](const boost::system::error_code& ec) { dump_stats(ec); });
|
||||
}
|
||||
|
||||
|
@ -648,7 +650,7 @@ void server::dummy_player_updates(const boost::system::error_code& ec)
|
|||
|
||||
void server::start_tournaments_timer()
|
||||
{
|
||||
tournaments_timer_.expires_after(std::chrono::minutes(60));
|
||||
tournaments_timer_.expires_after(60min);
|
||||
tournaments_timer_.async_wait([this](const boost::system::error_code& ec) { refresh_tournaments(ec); });
|
||||
}
|
||||
|
||||
|
@ -805,7 +807,7 @@ void server::login_client(boost::asio::yield_context yield, SocketPtr socket)
|
|||
|
||||
// Log the IP
|
||||
if(!user_handler_) {
|
||||
connection_log ip_name { username, client_address(socket), 0 };
|
||||
connection_log ip_name { username, client_address(socket), {} };
|
||||
|
||||
if(std::find(ip_log_.begin(), ip_log_.end(), ip_name) == ip_log_.end()) {
|
||||
ip_log_.push_back(ip_name);
|
||||
|
@ -878,7 +880,7 @@ template<class SocketPtr> bool server::is_login_allowed(boost::asio::yield_conte
|
|||
std::string ban_type_desc;
|
||||
std::string ban_reason;
|
||||
const char* msg_numeric;
|
||||
std::string ban_duration = std::to_string(auth_ban.duration);
|
||||
std::string ban_duration = std::to_string(auth_ban.duration.count());
|
||||
|
||||
switch(auth_ban.type) {
|
||||
case user_handler::BAN_USER:
|
||||
|
@ -907,7 +909,7 @@ template<class SocketPtr> bool server::is_login_allowed(boost::asio::yield_conte
|
|||
if(!is_moderator) {
|
||||
LOG_SERVER << log_address(socket) << "\t" << username << "\tis banned by user_handler (" << ban_type_desc
|
||||
<< ")";
|
||||
if(auth_ban.duration) {
|
||||
if(auth_ban.duration > 0s) {
|
||||
// Temporary ban
|
||||
async_send_error(socket, "You are banned from this server: " + ban_reason, msg_numeric, {{"duration", ban_duration}});
|
||||
} else {
|
||||
|
@ -998,7 +1000,7 @@ template<class SocketPtr> bool server::authenticate(
|
|||
}
|
||||
// This name is registered and an incorrect password provided
|
||||
else if(!(user_handler_->login(username, hashed_password))) {
|
||||
const std::time_t now = std::time(nullptr);
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
|
||||
login_log login_ip { client_address(socket), 0, now };
|
||||
auto i = std::find(failed_logins_.begin(), failed_logins_.end(), login_ip);
|
||||
|
@ -1068,7 +1070,7 @@ template<class SocketPtr> void server::send_password_request(SocketPtr socket,
|
|||
|
||||
template<class SocketPtr> void server::handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player)
|
||||
{
|
||||
if(lan_server_)
|
||||
if(lan_server_ > 0s)
|
||||
abort_lan_server_timer();
|
||||
|
||||
BOOST_SCOPE_EXIT_ALL(this, &player) {
|
||||
|
@ -1984,17 +1986,17 @@ void server::remove_player(player_iterator iter)
|
|||
if(user_handler_) {
|
||||
user_handler_->db_update_logout(iter->info().get_login_id());
|
||||
} else {
|
||||
connection_log ip_name { iter->info().name(), ip, 0 };
|
||||
connection_log ip_name { iter->info().name(), ip, {} };
|
||||
|
||||
auto i = std::find(ip_log_.begin(), ip_log_.end(), ip_name);
|
||||
if(i != ip_log_.end()) {
|
||||
i->log_off = std::time(nullptr);
|
||||
i->log_off = std::chrono::system_clock::now();
|
||||
}
|
||||
}
|
||||
|
||||
player_connections_.erase(iter);
|
||||
|
||||
if(lan_server_ && player_connections_.size() == 0)
|
||||
if(lan_server_ > 0s && player_connections_.size() == 0)
|
||||
start_lan_server_timer();
|
||||
|
||||
if(game_ended) delete_game(g->id());
|
||||
|
@ -2118,7 +2120,7 @@ void server::shut_down_handler(
|
|||
acceptor_v6_.close();
|
||||
acceptor_v4_.close();
|
||||
|
||||
timer_.expires_from_now(std::chrono::seconds(10));
|
||||
timer_.expires_from_now(10s);
|
||||
timer_.async_wait(std::bind(&server::handle_graceful_timeout, this, std::placeholders::_1));
|
||||
|
||||
process_command(
|
||||
|
@ -2149,7 +2151,7 @@ void server::restart_handler(const std::string& issuer_name,
|
|||
graceful_restart = true;
|
||||
acceptor_v6_.close();
|
||||
acceptor_v4_.close();
|
||||
timer_.expires_from_now(std::chrono::seconds(10));
|
||||
timer_.expires_from_now(10s);
|
||||
timer_.async_wait(std::bind(&server::handle_graceful_timeout, this, std::placeholders::_1));
|
||||
|
||||
start_new_server();
|
||||
|
@ -2552,9 +2554,9 @@ void server::ban_handler(
|
|||
auto second_space = std::find(first_space + 1, parameters.end(), ' ');
|
||||
const std::string target(parameters.begin(), first_space);
|
||||
const std::string duration(first_space + 1, second_space);
|
||||
std::time_t parsed_time = std::time(nullptr);
|
||||
auto [success, parsed_time] = ban_manager_.parse_time(duration, std::chrono::system_clock::now());
|
||||
|
||||
if(ban_manager_.parse_time(duration, &parsed_time) == false) {
|
||||
if(!success) {
|
||||
*out << "Failed to parse the ban duration: '" << duration << "'\n" << ban_manager_.get_ban_help();
|
||||
return;
|
||||
}
|
||||
|
@ -2614,9 +2616,9 @@ void server::kickban_handler(
|
|||
auto second_space = std::find(first_space + 1, parameters.end(), ' ');
|
||||
const std::string target(parameters.begin(), first_space);
|
||||
const std::string duration(first_space + 1, second_space);
|
||||
std::time_t parsed_time = std::time(nullptr);
|
||||
auto [success, parsed_time] = ban_manager_.parse_time(duration, std::chrono::system_clock::now());
|
||||
|
||||
if(ban_manager_.parse_time(duration, &parsed_time) == false) {
|
||||
if(!success) {
|
||||
*out << "Failed to parse the ban duration: '" << duration << "'\n" << ban_manager_.get_ban_help();
|
||||
return;
|
||||
}
|
||||
|
@ -2695,9 +2697,9 @@ void server::gban_handler(
|
|||
second_space = std::find(first_space + 1, parameters.end(), ' ');
|
||||
|
||||
const std::string duration(first_space + 1, second_space);
|
||||
std::time_t parsed_time = std::time(nullptr);
|
||||
auto [success, parsed_time] = ban_manager_.parse_time(duration, std::chrono::system_clock::now());
|
||||
|
||||
if(ban_manager_.parse_time(duration, &parsed_time) == false) {
|
||||
if(!success) {
|
||||
*out << "Failed to parse the ban duration: '" << duration << "'\n" << ban_manager_.get_ban_help();
|
||||
return;
|
||||
}
|
||||
|
@ -2877,7 +2879,7 @@ void server::searchlog_handler(const std::string& /*issuer_name*/,
|
|||
*out << std::endl << player_status(*player);
|
||||
} else {
|
||||
*out << "\n'" << username << "' @ " << ip
|
||||
<< " last seen: " << lg::get_timestamp(i.log_off, "%H:%M:%S %d.%m.%Y");
|
||||
<< " last seen: " << chrono::format_local_timestamp(i.log_off, "%H:%M:%S %d.%m.%Y");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
|
||||
namespace wesnothd
|
||||
|
@ -95,7 +96,7 @@ private:
|
|||
struct connection_log
|
||||
{
|
||||
std::string nick, ip;
|
||||
std::time_t log_off;
|
||||
std::chrono::system_clock::time_point log_off;
|
||||
|
||||
bool operator==(const connection_log& c) const
|
||||
{
|
||||
|
@ -110,7 +111,7 @@ private:
|
|||
{
|
||||
std::string ip;
|
||||
int attempts;
|
||||
std::time_t first_attempt;
|
||||
std::chrono::system_clock::time_point first_attempt;
|
||||
|
||||
bool operator==(const login_log& l) const
|
||||
{
|
||||
|
@ -151,11 +152,10 @@ private:
|
|||
std::string tournaments_;
|
||||
std::string information_;
|
||||
std::size_t default_max_messages_;
|
||||
std::size_t default_time_period_;
|
||||
std::chrono::seconds default_time_period_;
|
||||
std::size_t concurrent_connections_;
|
||||
bool graceful_restart;
|
||||
std::time_t lan_server_;
|
||||
std::time_t last_user_seen_time_;
|
||||
std::chrono::seconds lan_server_;
|
||||
std::string restart_command;
|
||||
std::size_t max_ip_log_size_;
|
||||
bool deny_unregistered_login_;
|
||||
|
@ -165,7 +165,7 @@ private:
|
|||
std::set<std::string> client_sources_;
|
||||
std::vector<std::string> tor_ip_list_;
|
||||
int failed_login_limit_;
|
||||
std::time_t failed_login_ban_;
|
||||
std::chrono::seconds failed_login_ban_;
|
||||
std::deque<login_log>::size_type failed_login_buffer_size_;
|
||||
|
||||
/** Parse the server config into local variables. */
|
||||
|
|
Loading…
Add table
Reference in a new issue