Remove dependency of wesnothd on SDL_net updating scons accordingly

This commit is contained in:
loonycyborg 2015-10-28 12:08:26 +03:00
parent 9ef2d1a103
commit e961b087e7
9 changed files with 126 additions and 772 deletions

View file

@ -347,28 +347,28 @@ if env["prereqs"]:
if env['sdl2']:
def have_sdl_net():
return \
conf.CheckSDL(require_version = '2.0.0') & \
conf.CheckSDL("SDL2_net", header_file = "SDL_net")
conf.CheckSDL(require_version = '2.0.0')
def have_sdl_other():
return \
conf.CheckSDL(require_version = '2.0.0') & \
conf.CheckSDL("SDL2_ttf", header_file = "SDL_ttf") & \
conf.CheckSDL("SDL2_mixer", header_file = "SDL_mixer") & \
conf.CheckSDL("SDL2_image", header_file = "SDL_image")
conf.CheckSDL("SDL2_image", header_file = "SDL_image") & \
conf.CheckSDL("SDL2_net", header_file = "SDL_net")
else:
def have_sdl_net():
return \
conf.CheckSDL(require_version = '1.2.10') & \
conf.CheckSDL('SDL_net')
conf.CheckSDL(require_version = '1.2.10')
def have_sdl_other():
return \
conf.CheckSDL(require_version = '1.2.10') & \
conf.CheckSDL("SDL_ttf", require_version = "2.0.8") & \
conf.CheckSDL("SDL_mixer", require_version = '1.2.12') & \
conf.CheckSDL("SDL_image", require_version = '1.2.0')
conf.CheckSDL("SDL_image", require_version = '1.2.0') & \
conf.CheckSDL('SDL_net')
if env["libintl"]:
def have_i18n_prereqs():

View file

@ -687,9 +687,7 @@ wesnothd_sources = Split("""
server/metrics.cpp
server/player.cpp
server/player_network.cpp
server/proxy.cpp
server/room.cpp
server/room_manager.cpp
server/rooms.cpp
server/sample_user_handler.cpp
server/simple_wml.cpp

View file

@ -15,7 +15,6 @@
#ifndef GAME_HPP_INCLUDED
#define GAME_HPP_INCLUDED
#include "../network.hpp"
#include "player_connection.hpp"
#include "player.hpp"

View file

@ -41,35 +41,4 @@ void truncate_message(const simple_wml::string_span& str, simple_wml::node& mess
} // end chat_message namespace
bool send_to_one(simple_wml::document& data, const network::connection sock, std::string packet_type)
{
if (packet_type.empty())
packet_type = data.root().first_child().to_string();
try {
simple_wml::string_span s = data.output_compressed();
network::send_raw_data(s.begin(), s.size(), sock, packet_type);
} catch (simple_wml::error& e) {
WRN_CONFIG << __func__ << ": simple_wml error: " << e.message << std::endl;
return false;
}
return true;
}
void send_to_many(simple_wml::document& data, const connection_vector& vec,
const network::connection exclude, std::string packet_type)
{
if (packet_type.empty())
packet_type = data.root().first_child().to_string();
try {
simple_wml::string_span s = data.output_compressed();
for(connection_vector::const_iterator i = vec.begin(); i != vec.end(); ++i) {
if (*i != exclude) {
network::send_raw_data(s.begin(), s.size(), *i, packet_type);
}
}
} catch (simple_wml::error& e) {
WRN_CONFIG << __func__ << ": simple_wml error: " << e.message << std::endl;
}
}
} //end namespace wesnothd

View file

@ -16,7 +16,6 @@
#ifndef SERVER_PLAYER_NETWORK_HPP_INCLUDED
#define SERVER_PLAYER_NETWORK_HPP_INCLUDED
#include "../network.hpp"
#include "player.hpp"
#include "simple_wml.hpp"
@ -34,71 +33,6 @@ namespace chat_message {
simple_wml::node& message);
} // end chat_message namespace
typedef std::map<network::connection,player> player_map;
typedef std::vector<network::connection> connection_vector;
/**
* Send a wml document to a single player
* @param data the document to send
* @param sock the socket id to send to
* @param packet_type the packet type, if empty the root node name is used
*/
bool send_to_one(simple_wml::document& data,
const network::connection sock,
std::string packet_type = "");
/**
* Send a wml document to a vector of players. More efficient than calling
* send_to_one many times.
* @param data the document to send
* @param vec the vector of player socket ids to send to
* @param exclude if nonzero, do not send to this player
* @param packet_type the packet type, if empty the root node name is used
*/
void send_to_many(simple_wml::document& data,
const connection_vector& vec,
const network::connection exclude = 0,
std::string packet_type = "");
/**
* A more powerful version of send_to_many, allowing the use of a predicate
* connection->bool. The document will be sent only to those sockets for which
* the predicate evaluates to false.
* @param data the document to send
* @param vec the vector of player socket ids to send to
* @param pred the predicate
* @param exclude if nonzero, do not send to this player
* @param packet_type the packet type, if empty the root node name is used
*/
/*
void send_to_many(simple_wml::document& data,
const connection_vector& vec,
boost::function<bool (network::connection)> pred,
const network::connection exclude = 0,
std::string packet_type = "");
*/
template<typename TFilter>
void send_to_many(simple_wml::document& data,
const connection_vector& vec,
const TFilter& pred,
const network::connection exclude = 0,
std::string packet_type = "")
{
if (packet_type.empty()) {
packet_type = data.root().first_child().to_string();
}
try {
simple_wml::string_span s = data.output_compressed();
for(connection_vector::const_iterator i = vec.begin(); i != vec.end(); ++i) {
if ((*i != exclude) && pred(*i)) {
network::send_raw_data(s.begin(), s.size(), *i, packet_type);
}
}
} catch (simple_wml::error& e) {
LOG_STREAM(warn, log_config_pn) << __func__ << ": simple_wml error: " << e.message << std::endl;
}
}
} //end namespace wesnothd
#endif

View file

@ -29,7 +29,6 @@ namespace wesnothd {
room::room(const std::string& name)
: name_(name)
, members_()
, persistent_(false)
, topic_()
, logged_(false)
@ -38,7 +37,6 @@ room::room(const std::string& name)
room::room(const config& wml)
: name_(wml["name"])
, members_()
, persistent_(wml["persistent"].to_bool())
, topic_(wml["topic"])
, logged_(wml["logged"].to_bool())
@ -88,7 +86,7 @@ void room::set_logged(bool v)
logged_ = v;
}
bool room::add_player(network::connection player)
/*bool room::add_player(network::connection player)
{
if (is_member(player)) {
ERR_ROOM << "ERROR: Player is already in this room. (socket: "
@ -97,7 +95,7 @@ bool room::add_player(network::connection player)
}
members_.push_back(player);
return true;
}
}*/
/*
void room::remove_player(network::connection player)
@ -113,7 +111,7 @@ void room::remove_player(network::connection player)
}
*/
void room::send_data(simple_wml::document& data,
/*void room::send_data(simple_wml::document& data,
const network::connection exclude,
std::string packet_type) const
{
@ -144,11 +142,12 @@ void room::send_server_message(const char* message, network::connection sock,
send_to_one(doc, sock, "message");
}
}
*/
void room::process_message(simple_wml::document& /*data*/,
const player_map::iterator /*user*/)
{
}
//void room::process_message(simple_wml::document& /*data*/,
// const player_map::iterator /*user*/)
//{
//}

View file

@ -15,14 +15,11 @@
#ifndef SERVER_ROOM_HPP_INCLUDED
#define SERVER_ROOM_HPP_INCLUDED
#include "../network.hpp"
#include "player.hpp"
#include "simple_wml.hpp"
namespace wesnothd {
typedef std::vector<network::connection> connection_vector;
typedef std::map<network::connection,player> player_map;
class game;
/**
@ -84,37 +81,37 @@ public:
/**
* Return the number of players in this room
*/
size_t size() const {
return members_.size();
}
//size_t size() const {
// return members_.size();
//}
/**
* Return true iif the room is empty
*/
bool empty() const {
return members_.empty();
}
//bool empty() const {
// return members_.empty();
//}
/**
* Return the members of this room
*/
const std::vector<network::connection>& members() const {
return members_;
}
//const std::vector<network::connection>& members() const {
// return members_;
//}
/**
* Membership checker.
* @return true iif player is a member of this room
*/
bool is_member(network::connection player) const {
return std::find(members_.begin(), members_.end(), player) != members_.end();
}
//bool is_member(network::connection player) const {
// return std::find(members_.begin(), members_.end(), player) != members_.end();
//}
/**
* Joining the room
* @return true if the player was successfully added
*/
bool add_player(network::connection player);
//bool add_player(network::connection player);
/**
* Leaving the room
@ -124,7 +121,7 @@ public:
/**
* Chat message processing
*/
void process_message(simple_wml::document& data, const player_map::iterator user);
//void process_message(simple_wml::document& data, const player_map::iterator user);
/**
* Convenience function for sending a wml document to all (or all except
@ -134,18 +131,18 @@ public:
* @param exclude if nonzero, do not send to this player
* @param packet_type the packet type, if empty the root node name is used
*/
void send_data(simple_wml::document& data, const network::connection exclude=0, std::string packet_type = "") const;
//void send_data(simple_wml::document& data, const network::connection exclude=0, std::string packet_type = "") const;
/**
* Send a text message to all members
* @param message the message text
* @param exclude if nonzero, do not send to this player
*/
void send_server_message_to_all(const char* message, network::connection exclude=0) const;
void send_server_message_to_all(const std::string& message, network::connection exclude=0) const
{
send_server_message_to_all(message.c_str(), exclude);
}
//void send_server_message_to_all(const char* message, network::connection exclude=0) const;
//void send_server_message_to_all(const std::string& message, network::connection exclude=0) const
//{
// send_server_message_to_all(message.c_str(), exclude);
//}
/**
* Prepare a text message and/or send it to a player. If a nonzero sock
@ -156,19 +153,19 @@ public:
* @param sock the socket to send the message to, if nonzero
* @param docptr the wml document to store the message in, if nonnull
*/
void send_server_message(const char* message, network::connection sock,
simple_wml::document* docptr = NULL) const;
//void send_server_message(const char* message, network::connection sock,
// simple_wml::document* docptr = NULL) const;
void send_server_message(const std::string& message, network::connection sock,
simple_wml::document* docptr = NULL) const
{
send_server_message(message.c_str(), sock, docptr);
}
//void send_server_message(const std::string& message, network::connection sock,
// simple_wml::document* docptr = NULL) const
//{
// send_server_message(message.c_str(), sock, docptr);
//}
private:
std::string name_;
connection_vector members_;
//connection_vector members_;
bool persistent_;
std::string topic_;
bool logged_;

View file

@ -25,7 +25,6 @@
#include "../game_config.hpp"
#include "../log.hpp"
#include "../map.hpp" // gamemap::MAX_PLAYERS
#include "../network.hpp"
#include "../filesystem.hpp"
#include "../multiplayer_error_codes.hpp"
#include "../serialization/parser.hpp"
@ -38,7 +37,6 @@
#include "input_stream.hpp"
#include "metrics.hpp"
#include "player.hpp"
#include "proxy.hpp"
#include "simple_wml.hpp"
#include "ban.hpp"
@ -100,9 +98,9 @@ clock_t get_cpu_time(bool /*active*/) {
namespace {
bool match_user(std::pair<network::connection, wesnothd::player> pl, const std::string& username, const std::string& ip) {
return pl.second.name() == username && network::ip_address(pl.first) == ip;
}
//bool match_user(std::pair<network::connection, wesnothd::player> pl, const std::string& username, const std::string& ip) {
// return pl.second.name() == username && network::ip_address(pl.first) == ip;
//}
}
static lg::log_domain log_server("server");
@ -167,18 +165,6 @@ namespace {
// we take profiling info on every n requests
int request_sample_frequency = 1;
void send_doc(simple_wml::document& doc, network::connection connection, std::string type = "")
{
if (type.empty())
type = doc.root().first_child().to_string();
try {
simple_wml::string_span s = doc.output_compressed();
network::send_raw_data(s.begin(), s.size(), connection, type);
} catch (simple_wml::error& e) {
WRN_CONFIG << __func__ << ": simple_wml error: " << e.message << std::endl;
}
}
bool check_error(const boost::system::error_code& error, socket_ptr socket)
{
if(error) {
@ -393,7 +379,7 @@ bool make_change_diff(const simple_wml::node& src,
return true;
}
std::string player_status(wesnothd::player_map::const_iterator pl) {
/*std::string player_status(wesnothd::player_map::const_iterator pl) {
std::ostringstream out;
const network::connection_stats& stats = network::get_connection_stats(pl->first);
const int time_connected = stats.time_connected / 1000;
@ -405,40 +391,10 @@ std::string player_status(wesnothd::player_map::const_iterator pl) {
<< " sent " << stats.bytes_sent << " bytes, received "
<< stats.bytes_received << " bytes";
return out.str();
}
}*/
} // namespace
class fps_limiter {
size_t start_ticks_;
size_t ms_per_frame_;
public:
fps_limiter(size_t ms_per_frame = 20) : start_ticks_(0), ms_per_frame_(ms_per_frame)
{}
void limit() {
size_t current_ticks = SDL_GetTicks();
if (current_ticks - start_ticks_ < ms_per_frame_) {
SDL_Delay(ms_per_frame_ - (current_ticks - start_ticks_));
start_ticks_ += ms_per_frame_;
} else {
start_ticks_ = current_ticks;
}
}
void set_ms_per_frame(size_t ms_per_frame)
{
ms_per_frame_ = ms_per_frame;
}
void set_fps(size_t fps)
{
ms_per_frame_ = 1000 / fps;
}
};
static fps_limiter fps_limit_;
namespace {
const std::string denied_msg = "You're not allowed to execute this command.";
const std::string help_msg = "Available commands are: adminmsg <msg>,"
@ -453,22 +409,15 @@ namespace {
}
server::server(int port, bool keep_alive, const std::string& config_file, size_t min_threads,
size_t max_threads) :
server::server(int port, bool keep_alive, const std::string& config_file, size_t /*min_threads*/,
size_t /*max_threads*/) :
io_service_(),
acceptor_(io_service_),
net_manager_(min_threads, max_threads),
server_(6666),
ban_manager_(),
ip_log_(),
failed_logins_(),
user_handler_(NULL),
seeds_(),
players_(),
ghost_players_(),
games_(),
not_logged_in_(),
rooms_(players_),
room_list_(player_connections_),
input_(),
input_path_(),
@ -479,7 +428,6 @@ server::server(int port, bool keep_alive, const std::string& config_file, size_t
proxy_versions_(),
disallowed_names_(),
admin_passwd_(),
admins_(),
motd_(),
default_max_messages_(0),
default_time_period_(0),
@ -521,7 +469,6 @@ server::server(int port, bool keep_alive, const std::string& config_file, size_t
setup_handlers();
load_config();
ban_manager_.read();
rooms_.read_rooms();
#ifndef _MSC_VER
signal(SIGHUP, reload_config);
@ -566,17 +513,6 @@ void server::setup_handlers()
cmd_handlers_["deny_unregistered_login"] = &server::dul_handler;
}
void server::send_error(network::connection sock, const char* msg, const char* error_code) const
{
simple_wml::document doc;
doc.root().add_child("error").set_attr("message", msg);
if(*error_code != '\0') {
doc.child("error")->set_attr("error_code", error_code);
}
send_doc(doc, sock, "error");
}
void async_send_error(socket_ptr socket, const std::string& msg, const char* error_code)
{
simple_wml::document doc;
@ -588,17 +524,6 @@ void async_send_error(socket_ptr socket, const std::string& msg, const char* err
async_send_doc(socket, doc);
}
void server::send_warning(network::connection sock, const char* msg, const char* warning_code) const
{
simple_wml::document doc;
doc.root().add_child("warning").set_attr("message", msg);
if(*warning_code != '\0') {
doc.child("warning")->set_attr("warning_code", warning_code);
}
send_doc(doc, sock, "warning");
}
void async_send_warning(socket_ptr socket, const std::string& msg, const char* warning_code)
{
simple_wml::document doc;
@ -610,7 +535,7 @@ void async_send_warning(socket_ptr socket, const std::string& msg, const char* w
async_send_doc(socket, doc);
}
void server::send_password_request(network::connection sock, const std::string& msg,
/*void server::send_password_request(network::connection sock, const std::string& msg,
const std::string& user, const char* error_code, bool force_confirmation)
{
std::string salt = user_handler_->create_salt();
@ -639,6 +564,7 @@ void server::send_password_request(network::connection sock, const std::string&
send_doc(doc, sock, "error");
}
*/
config server::read_config() const {
config configuration;
@ -718,8 +644,6 @@ void server::load_config() {
// remember to make new one as a daemon or it will block old one
restart_command = cfg_["restart_command"].str();
fps_limit_.set_ms_per_frame(cfg_["ms_per_frame"].to_int(20));
accepted_versions_.clear();
const std::string& versions = cfg_["versions_accepted"];
if (versions.empty() == false) {
@ -743,7 +667,7 @@ void server::load_config() {
}
}
ban_manager_.load_config(cfg_);
rooms_.load_config(cfg_);
//rooms_.load_config(cfg_);
// If there is a [user_handler] tag in the config file
// allow nick registration, otherwise we set user_handler_
@ -766,18 +690,6 @@ void server::load_config() {
}
}
bool server::ip_exceeds_connection_limit(const std::string& ip) const {
if (concurrent_connections_ == 0) return false;
size_t connections = 0;
for (wesnothd::player_map::const_iterator i = players_.begin(); i != players_.end(); ++i) {
if (network::ip_address(i->first) == ip) {
++connections;
}
}
return connections >= concurrent_connections_;
}
std::string server::is_ip_banned(const std::string& ip) const {
if (!tor_ip_list_.empty()) {
if (find(tor_ip_list_.begin(), tor_ip_list_.end(), ip) != tor_ip_list_.end()) return "TOR IP";
@ -789,8 +701,7 @@ void server::dump_stats(const time_t& now) {
last_stats_ = now;
LOG_SERVER << "Statistics:"
<< "\tnumber_of_games = " << games_.size()
<< "\tnumber_of_users = " << players_.size()
<< "\tlobby_users = " << rooms_.lobby().size() << "\n";
<< "\tnumber_of_users = " << player_connections_.size() << "\n";
}
void server::clean_user_handler(const time_t& now) {
@ -822,10 +733,10 @@ void server::accept_connection(const boost::system::error_code& error, socket_pt
LOG_SERVER << ip << "\trejected banned user. Reason: " << reason << "\n";
async_send_error(socket, "You are banned. Reason: " + reason);
return;
} else if (ip_exceeds_connection_limit(ip)) {
/*} else if (ip_exceeds_connection_limit(ip)) {
LOG_SERVER << ip << "\trejected ip due to excessive connections\n";
async_send_error(socket, "Too many connections from your IP.");
return;
return;*/
} else {
DBG_SERVER << ip << "\tnew connection accepted\n";
@ -1011,7 +922,7 @@ void server::handle_login(socket_ptr socket, boost::shared_ptr<simple_wml::docum
// Reset the random seed
seeds_.erase((unsigned long)socket.get());
login_log login_ip = login_log(network::ip_address((long int)socket.get()), 0, now);
login_log login_ip = login_log(client_address(socket), 0, now);
std::deque<login_log>::iterator i = std::find(failed_logins_.begin(), failed_logins_.end(), login_ip);
if(i == failed_logins_.end()) {
failed_logins_.push_back(login_ip);
@ -1356,7 +1267,7 @@ void server::handle_create_game(socket_ptr socket, simple_wml::node& create_game
simple_wml::document diff;
if(make_change_diff(games_and_users_list_.root(), NULL,
"user", player_connections_.left.info_at(socket).config_address(), diff)) {
rooms_.lobby().send_data(diff);
room_list_.send_to_room("lobby", diff);
}
return;
}
@ -1425,7 +1336,7 @@ void server::handle_join_game(socket_ptr socket, simple_wml::node& join)
bool diff2 = make_change_diff(games_and_users_list_.root(), NULL,
"user", player_connections_.left.info_at(socket).config_address(), diff);
if (diff1 || diff2) {
rooms_.lobby().send_data(diff);
room_list_.send_to_room("lobby", diff);
}
}
@ -1530,7 +1441,7 @@ void server::handle_player_in_game(socket_ptr socket, boost::shared_ptr<simple_w
// Send the update of the game description to the lobby.
simple_wml::document diff;
make_add_diff(*games_and_users_list_.child("gamelist"), "gamelist", "game", diff);
rooms_.lobby().send_data(diff);
room_list_.send_to_room("lobby", diff);
/** @todo FIXME: Why not save the level data in the history_? */
return;
// Everything below should only be processed if the game is already intialized.
@ -2165,403 +2076,6 @@ void server::process_data(const network::connection sock,
*/
void server::process_login(const network::connection sock,
simple_wml::document& data) {
// See if the client is sending their version number.
if (const simple_wml::node* const version = data.child("version")) {
const simple_wml::string_span& version_str_span = (*version)["version"];
const std::string version_str(version_str_span.begin(),
version_str_span.end());
std::vector<std::string>::const_iterator accepted_it;
// Check if it is an accepted version.
for (accepted_it = accepted_versions_.begin();
accepted_it != accepted_versions_.end(); ++accepted_it) {
if (utils::wildcard_string_match(version_str, *accepted_it)) break;
}
if (accepted_it != accepted_versions_.end()) {
LOG_SERVER << network::ip_address(sock)
<< "\tplayer joined using accepted version " << version_str
<< ":\ttelling them to log in.\n";
send_doc(login_response_, sock);
return;
}
std::map<std::string, config>::const_iterator config_it;
// Check if it is a redirected version
for (config_it = redirected_versions_.begin();
config_it != redirected_versions_.end(); ++config_it)
{
if (utils::wildcard_string_match(version_str, config_it->first))
break;
}
if (config_it != redirected_versions_.end()) {
LOG_SERVER << network::ip_address(sock)
<< "\tplayer joined using version " << version_str
<< ":\tredirecting them to " << config_it->second["host"]
<< ":" << config_it->second["port"] << "\n";
config response;
response.add_child("redirect", config_it->second);
network::send_data(response, sock, "redirect");
return;
}
// Check if it's a version we should start a proxy for.
for (config_it = proxy_versions_.begin();
config_it != proxy_versions_.end(); ++config_it)
{
if (utils::wildcard_string_match(version_str, config_it->first))
break;
}
if (config_it != proxy_versions_.end()) {
LOG_SERVER << network::ip_address(sock)
<< "\tplayer joined using version " << version_str
<< ":\tconnecting them by proxy to " << config_it->second["host"]
<< ":" << config_it->second["port"] << "\n";
proxy::create_proxy(sock, config_it->second["host"],
config_it->second["port"].to_int(15000));
return;
}
// No match, send a response and reject them.
LOG_SERVER << network::ip_address(sock)
<< "\tplayer joined using unknown version " << version_str
<< ":\trejecting them\n";
config response;
// For compatibility with older clients
response["version"] = *accepted_versions_.begin();
config &reject = response.add_child("reject");
reject["accepted_versions"] = utils::join(accepted_versions_);
if (accepted_versions_.empty()) {
// This cannot happen with the current way accepted_versions_ is populated
ERR_SERVER << "ERROR: This server doesn't accept any versions at all." << std::endl;
}
network::send_data(response, sock, "error");
return;
}
const simple_wml::node* const login = data.child("login");
// Client must send a login first.
if (login == NULL) {
send_error(sock, "You must login first.", MP_MUST_LOGIN);
return;
}
// Check if the username is valid (all alpha-numeric plus underscore and hyphen)
std::string username = (*login)["username"].to_string();
if (!utils::isvalid_username(username)) {
send_error(sock, "The nickname '" + username + "' contains invalid "
"characters. Only alpha-numeric characters, underscores and hyphens"
"are allowed.", MP_INVALID_CHARS_IN_NAME_ERROR);
return;
}
if (username.size() > 20) {
send_error(sock, "The nickname '" + username + "' is too long. Nicks must be 20 characters or less.",
MP_NAME_TOO_LONG_ERROR);
return;
}
// Check if the username is allowed.
for (std::vector<std::string>::const_iterator d_it = disallowed_names_.begin();
d_it != disallowed_names_.end(); ++d_it)
{
try {
if (utils::wildcard_string_match(utf8::lowercase(username),
utf8::lowercase(*d_it)))
{
send_error(sock, "The nickname '" + username + "' is reserved and cannot be used by players",
MP_NAME_RESERVED_ERROR);
return;
}
} catch ( utf8::invalid_utf8_exception & e ) {
ERR_SERVER << "While checking a username vs a list of disallowed names, caught an invalid utf8 exception: " << e.what() << std::endl;
}
}
// If this is a request for password reminder
if(user_handler_) {
std::string password_reminder = (*login)["password_reminder"].to_string();
if(password_reminder == "yes") {
try {
user_handler_->password_reminder(username);
send_error(sock, "Your password reminder email has been sent.");
} catch (user_handler::error& e) {
send_error(sock, "There was an error sending your password reminder email. The error message was: " +
e.message);
}
return;
}
}
// Check the username isn't already taken
bool name_taken = false;
wesnothd::player_map::const_iterator p;
for (p = players_.begin(); p != players_.end(); ++p) {
if (p->second.name() == username) {
name_taken = true;
break;
}
}
// unregistered users may not get auto-kicked to prevent abuse
if (name_taken && !p->second.registered()) {
send_error(sock, "The nickname '" + username + "' is already taken.", MP_NAME_TAKEN_ERROR);
return;
}
// Check for password
// Current login procedure for registered nicks is:
// - Client asks to log in with a particular nick
// - Server sends client random salt plus some info
// generated from the original hash that is required to
// regenerate the hash
// - Client generates hash for the user provided password
// and mixes it with the received random salt
// - Server received salted hash, salts the valid hash with
// the same salt it sent to the client and compares the results
bool registered = false;
if(user_handler_) {
std::string password = (*login)["password"].to_string();
const bool exists = user_handler_->user_exists(username);
// This name is registered but the account is not active
if(exists && !user_handler_->user_is_active(username)) {
send_warning(sock, "The nickname '" + username + "' is inactive. You cannot claim ownership of this "
"nickname until you activate your account via email or ask an administrator to do it for you.", MP_NAME_INACTIVE_WARNING);
//registered = false;
}
else if(exists) {
// This name is registered and no password provided
if(password.empty()) {
if (!name_taken) {
send_password_request(sock, "The nickname '" + username +"' is registered on this server.",
username, MP_PASSWORD_REQUEST);
} else {
send_password_request(sock, "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);
}
return;
}
// A password (or hashed password) was provided, however
// there is no seed
if(seeds_[sock].empty()) {
send_password_request(sock, "Please try again.", username, MP_NO_SEED_ERROR);
}
// This name is registered and an incorrect password provided
else if(!(user_handler_->login(username, password, seeds_[sock]))) {
const time_t now = time(NULL);
// Reset the random seed
seeds_.erase(sock);
login_log login_ip = login_log(network::ip_address(sock), 0, now);
std::deque<login_log>::iterator i = std::find(failed_logins_.begin(), failed_logins_.end(), login_ip);
if(i == failed_logins_.end()) {
failed_logins_.push_back(login_ip);
i = --failed_logins_.end();
// Remove oldest entry if maximum size is exceeded
if(failed_logins_.size() > failed_login_buffer_size_)
failed_logins_.pop_front();
}
if (i->first_attempt + failed_login_ban_ < now) {
// Clear and move to the beginning
failed_logins_.erase(i);
failed_logins_.push_back(login_ip);
i = --failed_logins_.end();
}
i->attempts++;
if (i->attempts > failed_login_limit_) {
LOG_SERVER << ban_manager_.ban(login_ip.ip, now + failed_login_ban_, "Maximum login attempts exceeded", "automatic", "", username);
send_error(sock, "You have made too many failed login attempts.", MP_TOO_MANY_ATTEMPTS_ERROR);
network::queue_disconnect(sock);
} else {
send_password_request(sock, "The password you provided for the nickname '" + username +
"' was incorrect.", username, MP_INCORRECT_PASSWORD_ERROR);
}
// Log the failure
LOG_SERVER << network::ip_address(sock) << "\t"
<< "Login attempt with incorrect password for nickname '" << username << "'.\n";
return;
}
// This name exists and the password was neither empty nor incorrect
registered = true;
// Reset the random seed
seeds_.erase(sock);
user_handler_->user_logged_in(username);
if (name_taken) {
// If there is already a client using this username kick it
process_command("kick " + username + " autokick by registered user", username);
}
}
}
// If we disallow unregistered users and this user is not registered send an error
if(user_handler_ && !registered && deny_unregistered_login_) {
send_error(sock, "The nickname '" + username + "' is not registered. "
"This server disallows unregistered nicknames.", MP_NAME_UNREGISTERED_ERROR);
return;
}
// if registered, the old client got kicked
if (name_taken && !registered) {
send_error(sock, "The nickname '" + username + "' is already taken.", MP_NAME_TAKEN_ERROR);
return;
}
// Check if the version is now available. If it is not, this player must
// always be pinged.
bool selective_ping = false ;
if( (*login)["selective_ping"].to_bool() ) {
selective_ping = true ;
DBG_SERVER << "selective ping is ENABLED for " << sock << "\n" ;
} else {
DBG_SERVER << "selective ping is DISABLED for " << sock << "\n" ;
}
send_doc(join_lobby_response_, sock);
simple_wml::node& player_cfg = games_and_users_list_.root().add_child("user");
const wesnothd::player new_player(username, player_cfg, registered,
default_max_messages_, default_time_period_, selective_ping,
user_handler_ && user_handler_->user_is_moderator(username));
// If the new player does not have selective ping enabled, immediately
// add the player to the ghost player's list. This ensures a client won't
// have to wait as long as x2 the current ping delay; which could cause
// a client-side disconnection.
players_.insert(std::make_pair(sock, new_player));
if( !selective_ping )
ghost_players_.insert(sock) ;
not_logged_in_.erase(sock);
rooms_.enter_lobby(sock);
// Send the new player the entire list of games and players
send_doc(games_and_users_list_, sock);
if (motd_ != "") {
rooms_.lobby().send_server_message(motd_, sock);
}
// Send other players in the lobby the update that the player has joined
simple_wml::document diff;
make_add_diff(games_and_users_list_.root(), NULL, "user", diff);
rooms_.lobby().send_data(diff, sock);
LOG_SERVER << network::ip_address(sock) << "\t" << username
<< "\thas logged on" << (registered ? " to a registered account" : "")
<< ". (socket: " << sock << ")\n";
for (t_games::const_iterator g = games_.begin(); g != games_.end(); ++g) {
// Note: This string is parsed by the client to identify lobby join messages!
g->send_server_message_to_all(username + " has logged into the lobby");
}
if(user_handler_ && user_handler_->user_is_moderator(username)) {
LOG_SERVER << "Admin automatically recognized: IP: "
<< network::ip_address(sock) << "\tnick: "
<< username << std::endl;
// This string is parsed by the client!
rooms_.lobby().send_server_message("You are now recognized as an administrator. "
"If you no longer want to be automatically authenticated use '/query signout'.", sock);
}
// Log the IP
connection_log ip_name = connection_log(username, network::ip_address(sock), 0);
if (std::find(ip_log_.begin(), ip_log_.end(), ip_name) == ip_log_.end()) {
ip_log_.push_back(ip_name);
// Remove the oldest entry if the size of the IP log exceeds the maximum size
if(ip_log_.size() > max_ip_log_size_) ip_log_.pop_front();
}
}
void server::process_query(const network::connection sock,
simple_wml::node& query) {
const wesnothd::player_map::iterator pl = players_.find(sock);
if (pl == players_.end()) {
DBG_SERVER << "ERROR: process_query(): Could not find player with socket: " << sock << std::endl;
return;
}
const std::string command(query["type"].to_string());
std::ostringstream response;
const std::string& help_msg = "Available commands are: adminmsg <msg>, help, games, metrics,"
" motd, netstats [all], requests, sample, stats, status, wml.";
// Commands a player may issue.
if (command == "status") {
response << process_command(command + " " + pl->second.name(), pl->second.name());
} else if (command.find("adminmsg") == 0
|| command == "games"
|| command == "metrics"
|| command == "motd"
|| command == "netstats"
|| command == "netstats all"
|| command == "requests"
|| command == "sample"
|| command == "stats"
|| command == "status " + pl->second.name()
|| command == "wml")
{
response << process_command(command, pl->second.name());
} else if (pl->second.is_moderator()) {
if (command == "signout") {
LOG_SERVER << "Admin signed out: IP: "
<< network::ip_address(sock) << "\tnick: "
<< pl->second.name() << std::endl;
pl->second.set_moderator(false);
// This string is parsed by the client!
response << "You are no longer recognized as an administrator.";
if(user_handler_) {
user_handler_->set_is_moderator(pl->second.name(), false);
}
} else {
LOG_SERVER << "Admin Command: type: " << command
<< "\tIP: "<< network::ip_address(sock)
<< "\tnick: "<< pl->second.name() << std::endl;
response << process_command(command, pl->second.name());
LOG_SERVER << response.str() << std::endl;
}
} else if (command == "help" || command.empty()) {
response << help_msg;
} else if (command == "admin" || command.find("admin ") == 0) {
if (admin_passwd_.empty()) {
rooms_.lobby().send_server_message("No password set.", sock);
return;
}
std::string passwd;
if (command.size() >= 6) passwd = command.substr(6);
if (passwd == admin_passwd_) {
LOG_SERVER << "New Admin recognized: IP: "
<< network::ip_address(sock) << "\tnick: "
<< pl->second.name() << std::endl;
pl->second.set_moderator(true);
// This string is parsed by the client!
response << "You are now recognized as an administrator.";
if (user_handler_) {
user_handler_->set_is_moderator(pl->second.name(), true);
}
} else {
WRN_SERVER << "FAILED Admin attempt with password: '" << passwd << "'\tIP: "
<< network::ip_address(sock) << "\tnick: "
<< pl->second.name() << std::endl;
response << "Error: wrong password";
}
} else {
response << "Error: unrecognized query: '" << command << "'\n" << help_msg;
}
rooms_.lobby().send_server_message(response.str(), sock);
}
void server::start_new_server() {
if (restart_command.empty())
return;
@ -2627,7 +2141,8 @@ std::string server::process_command(std::string query, std::string issuer_name)
}
// Shutdown, restart and sample commands can only be issued via the socket.
void server::shut_down_handler(const std::string& issuer_name, const std::string& /*query*/, std::string& parameters, std::ostringstream *out) {
void server::shut_down_handler(const std::string& /*issuer_name*/, const std::string& /*query*/, std::string& /*parameters*/, std::ostringstream */*out*/) {
/*
assert(out != NULL);
if (issuer_name != "*socket*" && !allow_remote_shutdown_) {
@ -2638,12 +2153,13 @@ void server::shut_down_handler(const std::string& issuer_name, const std::string
throw network::error("shut down");
} else {
// Graceful shut down.
server_.stop();
// TODO: Shutdown
input_.reset();
graceful_restart = true;
process_command("msg The server is shutting down. You may finish your games but can't start new ones. Once all games have ended the server will exit.", issuer_name);
*out << "Server is doing graceful shut down.";
}
*/
}
void server::restart_handler(const std::string& issuer_name, const std::string& /*query*/, std::string& /*parameters*/, std::ostringstream *out) {
@ -2659,7 +2175,7 @@ void server::restart_handler(const std::string& issuer_name, const std::string&
} else {
graceful_restart = true;
// stop listening socket
server_.stop();
// TODO: Shutdown
input_.reset();
// start new server
start_new_server();
@ -2695,8 +2211,7 @@ void server::stats_handler(const std::string& /*issuer_name*/, const std::string
assert(out != NULL);
*out << "Number of games = " << games_.size()
<< "\nTotal number of users = " << players_.size()
<< "\nNumber of users in the lobby = " << rooms_.lobby().size();
<< "\nTotal number of users = " << player_connections_.size() << "\n";
}
void server::metrics_handler(const std::string& /*issuer_name*/, const std::string& /*query*/, std::string& /*parameters*/, std::ostringstream *out) {
@ -2719,7 +2234,8 @@ void server::wml_handler(const std::string& /*issuer_name*/, const std::string&
*out << simple_wml::document::stats();
}
void server::netstats_handler(const std::string& /*issuer_name*/, const std::string& /*query*/, std::string& parameters, std::ostringstream *out) {
void server::netstats_handler(const std::string& /*issuer_name*/, const std::string& /*query*/, std::string& /*parameters*/, std::ostringstream */*out*/) {
/*
assert(out != NULL);
network::pending_statistics stats = network::get_pending_stats();
@ -2738,6 +2254,7 @@ void server::netstats_handler(const std::string& /*issuer_name*/, const std::str
} catch ( utf8::invalid_utf8_exception & e ) {
ERR_SERVER << "While handling a netstats command, caught an invalid utf8 exception: " << e.what() << std::endl;
}
*/
}
void server::adminmsg_handler(const std::string& issuer_name, const std::string& /*query*/, std::string& parameters, std::ostringstream *out) {
@ -2759,10 +2276,10 @@ void server::adminmsg_handler(const std::string& issuer_name, const std::string&
msg.set_attr_dup("sender", ("admin message from " + sender).c_str());
msg.set_attr_dup("message", message.c_str());
int n = 0;
for (wesnothd::player_map::const_iterator pl = players_.begin(); pl != players_.end(); ++pl) {
if (pl->second.is_moderator()) {
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it) {
if (it->info.is_moderator()) {
++n;
send_doc(data, pl->first);
send_to_player(it->left, data);
}
}
@ -2797,11 +2314,11 @@ void server::pm_handler(const std::string& issuer_name, const std::string& /*que
// This string is parsed by the client!
msg.set_attr_dup("sender", ("server message from " + sender).c_str());
msg.set_attr_dup("message", message.c_str());
for (wesnothd::player_map::const_iterator pl = players_.begin(); pl != players_.end(); ++pl) {
if (receiver != pl->second.name().c_str()) {
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it) {
if (receiver != it->info.name().c_str()) {
continue;
}
send_doc(data, pl->first);
send_to_player(it->left, data);
*out << "Message to " << receiver << " successfully sent.";
return;
}
@ -2817,7 +2334,7 @@ void server::msg_handler(const std::string& /*issuer_name*/, const std::string&
return;
}
rooms_.lobby().send_server_message_to_all(parameters);
room_list_.send_server_message("lobby", parameters);
for (t_games::const_iterator g = games_.begin(); g != games_.end(); ++g) {
g->send_server_message_to_all(parameters);
}
@ -2837,7 +2354,7 @@ void server::lobbymsg_handler(const std::string& /*issuer_name*/, const std::str
return;
}
rooms_.lobby().send_server_message_to_all(parameters);
room_list_.send_server_message("lobby", parameters);
LOG_SERVER << "<server" << (parameters.find("/me ") == 0
? std::string(parameters.begin() + 3, parameters.end()) + ">"
: "> " + parameters) << "\n";
@ -2852,9 +2369,9 @@ void server::status_handler(const std::string& issuer_name, const std::string& /
bool found_something = false;
// If a simple username is given we'll check for its IP instead.
if (utils::isvalid_username(parameters)) {
for (wesnothd::player_map::const_iterator pl = players_.begin(); pl != players_.end(); ++pl) {
if (parameters == pl->second.name()) {
parameters = network::ip_address(pl->first);
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it) {
if (parameters == it->info.name()) {
parameters = client_address(it->left);
found_something = true;
break;
}
@ -2867,12 +2384,12 @@ void server::status_handler(const std::string& issuer_name, const std::string& /
}
}
const bool match_ip = (std::count(parameters.begin(), parameters.end(), '.') >= 1);
for (wesnothd::player_map::const_iterator pl = players_.begin(); pl != players_.end(); ++pl) {
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it) {
if (parameters == "" || parameters == "*"
|| (match_ip && utils::wildcard_string_match(network::ip_address(pl->first), parameters))
|| (!match_ip && utils::wildcard_string_match(pl->second.name(), parameters))) {
|| (match_ip && utils::wildcard_string_match(client_address(it->left), parameters))
|| (!match_ip && utils::wildcard_string_match(it->info.name(), parameters))) {
found_something = true;
*out << std::endl << player_status(pl);
//*out << std::endl << player_status(it->left);
}
}
if (!found_something) *out << "\nNo match found. You may want to check with 'searchlog'.";
@ -2883,17 +2400,17 @@ void server::clones_handler(const std::string& /*issuer_name*/, const std::strin
*out << "CLONES STATUS REPORT";
std::set<std::string> clones;
for (wesnothd::player_map::const_iterator pl = players_.begin(); pl != players_.end(); ++pl) {
if (clones.find(network::ip_address(pl->first)) != clones.end()) continue;
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it) {
if (clones.find(client_address(it->left)) != clones.end()) continue;
bool found = false;
for (wesnothd::player_map::const_iterator clone = boost::next(pl); clone != players_.end(); ++clone) {
if (network::ip_address(pl->first) == network::ip_address(clone->first)) {
for (PlayerMap::iterator clone = boost::next(it); clone != player_connections_.end(); ++clone) {
if (client_address(it->left) == client_address(clone->left)) {
if (!found) {
found = true;
clones.insert(network::ip_address(pl->first));
*out << std::endl << player_status(pl);
clones.insert(client_address(it->left));
//*out << std::endl << player_status(pl);
}
*out << std::endl << player_status(clone);
//*out << std::endl << player_status(clone);
}
}
}
@ -2965,13 +2482,12 @@ void server::ban_handler(const std::string& issuer_name, const std::string& /*qu
*out << ban_manager_.ban(target, parsed_time, reason, issuer_name, dummy_group);
} else {
for (wesnothd::player_map::const_iterator pl = players_.begin();
pl != players_.end(); ++pl)
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it)
{
if (utils::wildcard_string_match(pl->second.name(), target)) {
if (utils::wildcard_string_match(it->info.name(), target)) {
if (banned) *out << "\n";
else banned = true;
const std::string ip = network::ip_address(pl->first);
const std::string ip = client_address(it->left);
*out << ban_manager_.ban(ip, parsed_time, reason, issuer_name, dummy_group, target);
}
}
@ -3034,28 +2550,26 @@ void server::kickban_handler(const std::string& issuer_name, const std::string&
*out << ban_manager_.ban(target, parsed_time, reason, issuer_name, dummy_group);
for (wesnothd::player_map::const_iterator pl = players_.begin();
pl != players_.end(); ++pl)
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it)
{
if (utils::wildcard_string_match(network::ip_address(pl->first), target)) {
*out << "\nKicked " << pl->second.name() << " ("
<< network::ip_address(pl->first) << ").";
send_error(pl->first, "You have been banned. Reason: " + reason);
network::queue_disconnect(pl->first);
if (utils::wildcard_string_match(client_address(it->left), target)) {
*out << "\nKicked " << it->info.name() << " ("
<< client_address(it->left) << ").";
//send_error(pl->first, "You have been banned. Reason: " + reason);
//network::queue_disconnect(pl->first);
}
}
} else {
for (wesnothd::player_map::const_iterator pl = players_.begin();
pl != players_.end(); ++pl)
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it)
{
if (utils::wildcard_string_match(pl->second.name(), target)) {
if (utils::wildcard_string_match(it->info.name(), target)) {
if (banned) *out << "\n";
else banned = true;
const std::string ip = network::ip_address(pl->first);
const std::string ip = client_address(it->left);
*out << ban_manager_.ban(ip, parsed_time, reason, issuer_name, dummy_group, target);
*out << "\nKicked " << pl->second.name() << " (" << ip << ").";
send_error(pl->first, "You have been banned. Reason: " + reason);
network::queue_disconnect(pl->first);
*out << "\nKicked " << it->info.name() << " (" << ip << ").";
//send_error(pl->first, "You have been banned. Reason: " + reason);
//network::queue_disconnect(pl->first);
}
}
if (!banned) {
@ -3120,13 +2634,12 @@ void server::gban_handler(const std::string& issuer_name, const std::string& /*q
*out << ban_manager_.ban(target, parsed_time, reason, issuer_name, group);
} else {
for (wesnothd::player_map::const_iterator pl = players_.begin();
pl != players_.end(); ++pl)
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it)
{
if (utils::wildcard_string_match(pl->second.name(), target)) {
if (utils::wildcard_string_match(it->info.name(), target)) {
if (banned) *out << "\n";
else banned = true;
const std::string ip = network::ip_address(pl->first);
const std::string ip = client_address(it->left);
*out << ban_manager_.ban(ip, parsed_time, reason, issuer_name, group, target);
}
}
@ -3186,18 +2699,17 @@ void server::kick_handler(const std::string& /*issuer_name*/, const std::string&
bool kicked = false;
// if we find a '.' consider it an ip mask
const bool match_ip = (std::count(kick_mask.begin(), kick_mask.end(), '.') >= 1);
for (wesnothd::player_map::const_iterator pl = players_.begin();
pl != players_.end(); ++pl)
for (PlayerMap::iterator it = player_connections_.begin(); it != player_connections_.end(); ++it)
{
if ((match_ip && utils::wildcard_string_match(network::ip_address(pl->first), kick_mask))
|| (!match_ip && utils::wildcard_string_match(pl->second.name(), kick_mask))) {
if ((match_ip && utils::wildcard_string_match(client_address(it->left), kick_mask))
|| (!match_ip && utils::wildcard_string_match(it->info.name(), kick_mask))) {
if (kicked) *out << "\n";
else kicked = true;
*out << "Kicked " << pl->second.name() << " ("
<< network::ip_address(pl->first) << "). '"
*out << "Kicked " << it->info.name() << " ("
<< client_address(it->left) << "). '"
<< kick_message << "'";
send_error(pl->first, kick_message);
network::queue_disconnect(pl->first);
//send_error(pl->first, kick_message);
//network::queue_disconnect(pl->first);
}
}
if (!kicked) *out << "No user matched '" << kick_mask << "'.";
@ -3233,8 +2745,8 @@ void server::searchlog_handler(const std::string& /*issuer_name*/, const std::st
// If this looks like an IP look up which nicks have been connected from it
// Otherwise look for the last IP the nick used to connect
const bool match_ip = (std::count(parameters.begin(), parameters.end(), '.') >= 1);
for (std::deque<connection_log>::const_iterator i = ip_log_.begin();
//const bool match_ip = (std::count(parameters.begin(), parameters.end(), '.') >= 1);
/*for (std::deque<connection_log>::const_iterator i = ip_log_.begin();
i != ip_log_.end(); ++i) {
const std::string& username = i->nick;
const std::string& ip = i->ip;
@ -3248,7 +2760,7 @@ void server::searchlog_handler(const std::string& /*issuer_name*/, const std::st
*out << "\n'" << username << "' @ " << ip << " last seen: " << lg::get_timestamp(i->log_off, "%H:%M:%S %d.%m.%Y");
}
}
}
}*/
if (!found_something) *out << "\nNo match found.";
}
@ -3269,7 +2781,7 @@ void server::dul_handler(const std::string& /*issuer_name*/, const std::string&
}
}
void server::process_nickserv(const network::connection sock, simple_wml::node& data) {
/*void server::process_nickserv(const network::connection sock, simple_wml::node& data) {
const wesnothd::player_map::iterator pl = players_.find(sock);
if (pl == players_.end()) {
DBG_SERVER << "ERROR: Could not find player with socket: " << sock << std::endl;
@ -3386,6 +2898,7 @@ void server::process_nickserv(const network::connection sock, simple_wml::node&
return;
}
}
*/
/*
void server::process_whisper(const network::connection sock,
@ -4126,20 +3639,7 @@ int main(int argc, char** argv) {
}
}
network::set_raw_data_only();
try {
server(port, keep_alive, config_file, min_threads, max_threads).run();
} catch(network::error& e) {
ERR_SERVER << "Caught network error while server was running. Aborting.: "
<< e.message << "\n";
/**
* @todo errno should be passed here with the error or it might not be
* the true errno anymore. Seems to work good enough for now though.
*/
return errno;
}
server(port, keep_alive, config_file, min_threads, max_threads).run();
return 0;
}

View file

@ -19,10 +19,8 @@
#include "user_handler.hpp"
#include "input_stream.hpp"
#include "metrics.hpp"
#include "../network.hpp"
#include "ban.hpp"
#include "player.hpp"
#include "room_manager.hpp"
#include "simple_wml.hpp"
#include "player_connection.hpp"
#include "rooms.hpp"
@ -38,24 +36,6 @@ public:
server(int port, bool keep_alive, const std::string& config_file, size_t min_threads,size_t max_threads);
void run();
private:
void send_error(network::connection sock, const char* msg, const char* error_code ="") const;
void send_error(network::connection sock, const std::string &msg, const char* error_code = "") const
{
send_error(sock, msg.c_str(), error_code);
}
void send_warning(network::connection sock, const char* msg, const char* warning_code ="") const;
void send_warning(network::connection sock, const std::string &msg, const char* warning_code = "") const
{
send_warning(sock, msg.c_str(), warning_code);
}
// The same as send_error(), we just add an extra child to the response
// telling the client the chosen username requires a password.
void send_password_request(network::connection sock, const std::string& msg,
const std::string& user, const char* error_code ="",
bool force_confirmation = false);
boost::asio::io_service io_service_;
boost::asio::ip::tcp::acceptor acceptor_;
void serve();
@ -92,8 +72,6 @@ private:
void handle_join_game(socket_ptr socket, simple_wml::node& join);
void remove_player(socket_ptr socket);
const network::manager net_manager_;
network::server_manager server_;
wesnothd::ban_manager ban_manager_;
struct connection_log {
@ -128,19 +106,18 @@ private:
std::deque<login_log> failed_logins_;
boost::scoped_ptr<user_handler> user_handler_;
std::map<network::connection,std::string> seeds_;
std::map<long int,std::string> seeds_;
/** std::map<network::connection,player>. */
wesnothd::player_map players_;
std::set<network::connection> ghost_players_;
//wesnothd::player_map players_;
//std::set<network::connection> ghost_players_;
PlayerMap player_connections_;
typedef boost::ptr_vector<wesnothd::game> t_games;
t_games games_;
std::set<network::connection> not_logged_in_;
//std::set<network::connection> not_logged_in_;
wesnothd::room_manager rooms_;
RoomList room_list_;
/** server socket/fifo. */
@ -159,7 +136,7 @@ private:
std::map<std::string,config> proxy_versions_;
std::vector<std::string> disallowed_names_;
std::string admin_passwd_;
std::set<network::connection> admins_;
//std::set<network::connection> admins_;
std::string motd_;
size_t default_max_messages_;
size_t default_time_period_;
@ -199,28 +176,9 @@ private:
time_t last_uh_clean_;
void clean_user_handler(const time_t& now);
void process_data(const network::connection sock,
simple_wml::document& data);
void process_login(const network::connection sock,
simple_wml::document& data);
/** Handle queries from clients. */
void process_query(const network::connection sock,
simple_wml::node& query);
/** Process commands from admins and users. */
std::string process_command(std::string cmd, std::string issuer_name);
/** Handle private messages between players. */
void process_whisper(const network::connection sock,
simple_wml::node& whisper) const;
/** Handle nickname registration related requests from clients. */
void process_nickserv(const network::connection sock, simple_wml::node& data);
void process_data_lobby(const network::connection sock,
simple_wml::document& data);
void process_data_game(const network::connection sock,
simple_wml::document& data);
void delete_game(t_games::iterator game_it);
void update_game_in_lobby(const wesnothd::game& g, const socket_ptr& exclude=socket_ptr());