Stop hanging when banned

When a banned or connection-limited client attempts to log in, it hangs.

This is because the client does not understand that the server did not finish the handshake. This moves the check to a point just after the handshake has completed (when the server would normally ask for a version number). The client never checked for errors, so added a check.
This commit is contained in:
Gregory A Lundberg 2017-12-29 13:59:27 -06:00
parent 66f740840e
commit d9f9d83a6b
No known key found for this signature in database
GPG Key ID: 149484078AE8AE9E
4 changed files with 39 additions and 18 deletions

View File

@ -158,6 +158,13 @@ std::pair<wesnothd_connection_ptr, config> open_connection(std::string host)
std::swap(initial_lobby_config, data);
}
if(data.has_child("error")) {
std::string error_message;
config* error = &data.child("error");
error_message = (*error)["message"].str();
throw wesnothd_rejected_client_error(error_message);
}
// Continue if we did not get a direction to login
if(!data.has_child("mustlogin")) {
continue;

View File

@ -853,6 +853,8 @@ bool game_launcher::play_multiplayer(mp_selection res)
multiplayer_server_.clear();
}
} catch(wesnothd_rejected_client_error& e) {
gui2::show_error_message(e.message);
} catch(game::mp_server_error& e) {
gui2::show_error_message(_("Error while starting server: ") + e.message);
} catch(game::load_game_failed& e) {

View File

@ -78,23 +78,8 @@ void server_base::accept_connection(const boost::system::error_code& error, sock
return;
}
const std::string ip = client_address(socket);
const std::string reason = is_ip_banned(ip);
if (!reason.empty()) {
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)) {
LOG_SERVER << ip << "\trejected ip due to excessive connections\n";
async_send_error(socket, "Too many connections from your IP.");
return;
} else {
DBG_SERVER << ip << "\tnew connection accepted\n";
serverside_handshake(socket);
}
DBG_SERVER << client_address(socket) << "\tnew connection tentatively accepted\n";
serverside_handshake(socket);
}
void server_base::serverside_handshake(socket_ptr socket)
@ -118,7 +103,25 @@ void server_base::handle_handshake(const boost::system::error_code& error, socke
async_write(
*socket, boost::asio::buffer(handshake_response_.buf, 4),
[=](const boost::system::error_code& error, size_t)
{ if(!check_error(error, socket)) this->handle_new_client(socket); }
{
if(!check_error(error, socket)) {
const std::string ip = client_address(socket);
const std::string reason = is_ip_banned(ip);
if (!reason.empty()) {
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)) {
LOG_SERVER << ip << "\trejected ip due to excessive connections\n";
async_send_error(socket, "Too many connections from your IP.");
return;
} else {
DBG_SERVER << ip << "\tnew connection fully accepted\n";
this->handle_new_client(socket);
}
}
}
);
}

View File

@ -23,6 +23,15 @@ struct wesnothd_error : public game::error
wesnothd_error(const std::string& error) : game::error(error) {}
};
/**
* Error used when the client is rejected by the MP server.
* Technically, this is not an error but the only way to handle the condition is as if it were an error.
*/
struct wesnothd_rejected_client_error : public game::error
{
wesnothd_rejected_client_error (const std::string& msg) : game::error (msg) {}
};
///We received invalid data from wesnothd during a game
///This means we cannot continue with the game but we can stay connected to wesnothd and start a new game
///TODO: find a short name