From ba6afa4d1706a30c067a15ab26c1ab3b9ef5b87b Mon Sep 17 00:00:00 2001 From: gfgtdf Date: Sat, 2 Jun 2018 20:46:54 +0200 Subject: [PATCH] add player_version mp command to tell you what wesnoth version another player is using. --- src/server/player.cpp | 3 ++- src/server/player.hpp | 4 +++- src/server/server.cpp | 51 +++++++++++++++++++++++++++++-------------- src/server/server.hpp | 11 +++++----- 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/server/player.cpp b/src/server/player.cpp index 557a6d83ff7b..888563b692c1 100644 --- a/src/server/player.cpp +++ b/src/server/player.cpp @@ -16,10 +16,11 @@ #include "lexical_cast.hpp" wesnothd::player::player(const std::string& n, simple_wml::node& cfg, - bool registered, const std::size_t max_messages, + bool registered, const std::string& version, const std::size_t max_messages, const std::size_t time_period, const bool moderator) : name_(n) + , version_(version) , cfg_(cfg) , registered_(registered) , flood_start_(0) diff --git a/src/server/player.hpp b/src/server/player.hpp index b6f4fd2d19dc..b1cf88421b11 100644 --- a/src/server/player.hpp +++ b/src/server/player.hpp @@ -32,7 +32,7 @@ class player OBSERVING }; - player(const std::string& n, simple_wml::node& cfg, bool registered, + player(const std::string& n, simple_wml::node& cfg, bool registered, const std::string& version, const std::size_t max_messages=4, const std::size_t time_period=10, const bool moderator=false); @@ -47,6 +47,7 @@ class player const std::string& name() const { return name_; } + const std::string& version() const { return version_; } const simple_wml::node* config_address() const { return &cfg_; } bool is_message_flooding(); @@ -69,6 +70,7 @@ class player private: const std::string name_; + std::string version_; simple_wml::node& cfg_; bool registered_; diff --git a/src/server/server.cpp b/src/server/server.cpp index 056fcff84d58..229946ce5a98 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -355,6 +355,7 @@ void server::setup_handlers() SETUP_HANDLER("sample", &server::sample_handler); SETUP_HANDLER("help", &server::help_handler); SETUP_HANDLER("stats", &server::stats_handler); + SETUP_HANDLER("player_version", &server::player_version_handler); SETUP_HANDLER("metrics", &server::metrics_handler); SETUP_HANDLER("requests", &server::requests_handler); SETUP_HANDLER("games", &server::games_handler); @@ -582,7 +583,7 @@ void server::read_version(socket_ptr socket, std::shared_ptr doc) +void server::handle_login(socket_ptr socket, std::shared_ptr doc, std::string version) { if(const simple_wml::node* const login = doc->child("login")) { - if(!is_login_allowed(socket, login)) { - server::login(socket); // keep reading logins from client until we get a successful one + if(!is_login_allowed(socket, login, version)) { + server::login(socket, version); // keep reading logins from client until we get a successful one } } else { async_send_error(socket, "You must login first.", MP_MUST_LOGIN); } } -bool server::is_login_allowed(socket_ptr socket, const simple_wml::node* const login) +bool server::is_login_allowed(socket_ptr socket, const simple_wml::node* const login, const std::string& version) { // Check if the username is valid (all alpha-numeric plus underscore and hyphen) std::string username = (*login)["username"].to_string(); @@ -672,7 +673,7 @@ bool server::is_login_allowed(socket_ptr socket, const simple_wml::node* const l // Check for password bool registered; - if(!authenticate(socket, username, (*login)["password"].to_string(), name_taken, registered)) + if(!authenticate(socket, username, (*login)["password"].to_string(), version, name_taken, registered)) return true; // it's a failed login but we don't want to call server::login again // because send_password_request() will handle the next network write and read instead @@ -747,6 +748,7 @@ bool server::is_login_allowed(socket_ptr socket, const simple_wml::node* const l username, player_cfg, registered, + version, default_max_messages_, default_time_period_, user_handler_ && user_handler_->user_is_moderator(username) @@ -787,7 +789,7 @@ bool server::is_login_allowed(socket_ptr socket, const simple_wml::node* const l } bool server::authenticate( - socket_ptr socket, const std::string& username, const std::string& password, bool name_taken, bool& registered) + socket_ptr socket, const std::string& username, const std::string& password, const std::string& version, bool name_taken, bool& registered) { // Current login procedure for registered nicks is: // - Client asks to log in with a particular nick @@ -816,14 +818,14 @@ bool server::authenticate( // This name is registered and no password provided if(password.empty()) { if(!name_taken) { - send_password_request(socket, "The nickname '" + username + "' is registered on this server.", - username, MP_PASSWORD_REQUEST); + send_password_request(socket, "The nickname '" + username + "' is registered on this server.", + username, version, MP_PASSWORD_REQUEST); } else { send_password_request(socket, "The nickname '" + username + "' is registered on this server." "\n\nWARNING: There is already a client using this username, " "logging in will cause that client to be kicked!", - username, MP_PASSWORD_REQUEST_FOR_LOGGED_IN_NAME, true + username, version, MP_PASSWORD_REQUEST_FOR_LOGGED_IN_NAME, true ); } @@ -833,7 +835,7 @@ bool server::authenticate( // A password (or hashed password) was provided, however // there is no seed if(seeds_[reinterpret_cast(socket.get())].empty()) { - send_password_request(socket, "Please try again.", username, MP_NO_SEED_ERROR); + send_password_request(socket, "Please try again.", username, version, MP_NO_SEED_ERROR); return false; } @@ -874,7 +876,7 @@ bool server::authenticate( "You have made too many failed login attempts.", MP_TOO_MANY_ATTEMPTS_ERROR); } else { send_password_request(socket, - "The password you provided for the nickname '" + username + "' was incorrect.", username, + "The password you provided for the nickname '" + username + "' was incorrect.", username,version, MP_INCORRECT_PASSWORD_ERROR); } @@ -899,6 +901,7 @@ bool server::authenticate( void server::send_password_request(socket_ptr socket, const std::string& msg, const std::string& user, + const std::string& version, const char* error_code, bool force_confirmation) { @@ -917,7 +920,7 @@ void server::send_password_request(socket_ptr socket, "cannot log in due to an error in the hashing algorithm. " "Logging into your forum account on https://forums.wesnoth.org " "may fix this problem."); - login(socket); + login(socket, version); return; } @@ -935,7 +938,7 @@ void server::send_password_request(socket_ptr socket, e.set_attr("error_code", error_code); } - async_send_doc(socket, doc, std::bind(&server::login, this, _1)); + async_send_doc(socket, doc, std::bind(&server::login, this, _1, version)); } void server::add_player(socket_ptr socket, const wesnothd::player& player) @@ -1078,6 +1081,7 @@ void server::handle_query(socket_ptr socket, simple_wml::node& query) command == "motd" || command == "netstats" || command == "netstats all" || + command == "player_version" || command == "requests" || command == "sample" || command == "stats" || @@ -2280,6 +2284,21 @@ void server::lobbymsg_handler(const std::string& /*issuer_name*/, *out << "message '" << parameters << "' relayed to players"; } +void server::player_version_handler( + const std::string& /*issuer_name*/, const std::string& /*query*/, std::string& parameters, std::ostringstream* out) +{ + assert(out != nullptr); + + + for(const auto& player : player_connections_) { + if(parameters == player.info().name()) { + *out << "Player " << parameters << " is using wesnoth " << player.info().version(); + return; + } + } + *out << "Player " << parameters << " not found."; +} + void server::status_handler( const std::string& issuer_name, const std::string& /*query*/, std::string& parameters, std::ostringstream* out) { diff --git a/src/server/server.hpp b/src/server/server.hpp index 10dc8f94df6d..736dc2ea0f3e 100644 --- a/src/server/server.hpp +++ b/src/server/server.hpp @@ -41,12 +41,12 @@ class server : public server_base void handle_version(socket_ptr socket); void read_version(socket_ptr socket, std::shared_ptr doc); - void login(socket_ptr socket); - void handle_login(socket_ptr socket, std::shared_ptr doc); - bool is_login_allowed(socket_ptr socket, const simple_wml::node* const login); - bool authenticate(socket_ptr socket, const std::string& username, const std::string& password, bool name_taken, bool& registered); + void login(socket_ptr socket, std::string version); + void handle_login(socket_ptr socket, std::shared_ptr doc, std::string version); + bool is_login_allowed(socket_ptr socket, const simple_wml::node* const login, const std::string& version); + bool authenticate(socket_ptr socket, const std::string& username, const std::string& password, const std::string& version, bool name_taken, bool& registered); void send_password_request(socket_ptr socket, const std::string& msg, - const std::string& user, const char* error_code = "", bool force_confirmation = false); + const std::string& user, const std::string& version, const char* error_code = "", bool force_confirmation = false); bool accepting_connections() const { return !graceful_restart; } void add_player(socket_ptr socket, const wesnothd::player&); @@ -204,6 +204,7 @@ class server : public server_base void netstats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *); void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *); void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *); + void player_version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *); void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *); void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *); void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);