wesnothd: avoid a race condition when logging on
Ensure that there is no coroutine yield between confirmation of login and update of player_connections_. Otherwise another login under same name could succeed if it happened before handle_player() which resulted in an assert later.
This commit is contained in:
parent
8863cd1bcd
commit
c10c47ebb1
2 changed files with 19 additions and 19 deletions
|
@ -752,15 +752,8 @@ void server::login_client(boost::asio::yield_context yield, SocketPtr socket)
|
|||
async_send_error(socket, "You must login first.", MP_MUST_LOGIN);
|
||||
}
|
||||
|
||||
simple_wml::document join_lobby_response;
|
||||
join_lobby_response.root().add_child("join_lobby").set_attr("is_moderator", is_moderator ? "yes" : "no");
|
||||
join_lobby_response.root().child("join_lobby")->set_attr_dup("profile_url_prefix", "https://r.wesnoth.org/u");
|
||||
coro_send_doc(socket, join_lobby_response, yield);
|
||||
|
||||
simple_wml::node& player_cfg = games_and_users_list_.root().add_child("user");
|
||||
|
||||
boost::asio::spawn(io_service_,
|
||||
[this, socket, new_player = wesnothd::player{
|
||||
wesnothd::player player_data {
|
||||
username,
|
||||
player_cfg,
|
||||
user_handler_ ? user_handler_->get_forum_id(username) : 0,
|
||||
|
@ -771,7 +764,19 @@ void server::login_client(boost::asio::yield_context yield, SocketPtr socket)
|
|||
default_max_messages_,
|
||||
default_time_period_,
|
||||
is_moderator
|
||||
}](boost::asio::yield_context yield) { handle_player(yield, socket, new_player); }
|
||||
};
|
||||
bool inserted;
|
||||
player_iterator new_player;
|
||||
std::tie(new_player, inserted) = player_connections_.insert(player_connections::value_type(socket, player_data));
|
||||
assert(inserted && "unexpected duplicate username");
|
||||
|
||||
simple_wml::document join_lobby_response;
|
||||
join_lobby_response.root().add_child("join_lobby").set_attr("is_moderator", is_moderator ? "yes" : "no");
|
||||
join_lobby_response.root().child("join_lobby")->set_attr_dup("profile_url_prefix", "https://r.wesnoth.org/u");
|
||||
coro_send_doc(socket, join_lobby_response, yield);
|
||||
|
||||
boost::asio::spawn(io_service_,
|
||||
[this, socket, new_player](boost::asio::yield_context yield) { handle_player(yield, socket, new_player); }
|
||||
);
|
||||
|
||||
LOG_SERVER << log_address(socket) << "\t" << username << "\thas logged on"
|
||||
|
@ -1050,16 +1055,11 @@ template<class SocketPtr> void server::send_password_request(SocketPtr socket,
|
|||
async_send_doc_queued(socket, doc);
|
||||
}
|
||||
|
||||
template<class SocketPtr> void server::handle_player(boost::asio::yield_context yield, SocketPtr socket, const player& player_data)
|
||||
template<class SocketPtr> void server::handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player)
|
||||
{
|
||||
if(lan_server_)
|
||||
abort_lan_server_timer();
|
||||
|
||||
bool inserted;
|
||||
player_iterator player;
|
||||
std::tie(player, inserted) = player_connections_.insert(player_connections::value_type(socket, player_data));
|
||||
assert(inserted);
|
||||
|
||||
BOOST_SCOPE_EXIT_ALL(this, &player) {
|
||||
if(!destructed) {
|
||||
remove_player(player);
|
||||
|
@ -1073,10 +1073,10 @@ template<class SocketPtr> void server::handle_player(boost::asio::yield_context
|
|||
}
|
||||
send_server_message(player, information_, "server_info");
|
||||
send_server_message(player, announcements_+tournaments_, "announcements");
|
||||
if(version_info(player_data.version()) < secure_version ){
|
||||
send_server_message(player, "You are using version " + player_data.version() + " which has known security issues that can be used to compromise your computer. We strongly recommend updating to a Wesnoth version " + secure_version.str() + " or newer!", "alert");
|
||||
if(version_info(player->info().version()) < secure_version ){
|
||||
send_server_message(player, "You are using version " + player->info().version() + " which has known security issues that can be used to compromise your computer. We strongly recommend updating to a Wesnoth version " + secure_version.str() + " or newer!", "alert");
|
||||
}
|
||||
if(version_info(player_data.version()) < version_info(recommended_version_)) {
|
||||
if(version_info(player->info().version()) < version_info(recommended_version_)) {
|
||||
send_server_message(player, "A newer Wesnoth version, " + recommended_version_ + ", is out!", "alert");
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ private:
|
|||
template<class SocketPtr> void send_password_request(SocketPtr socket, const std::string& msg, const char* error_code = "", bool force_confirmation = false);
|
||||
bool accepting_connections() const { return !graceful_restart; }
|
||||
|
||||
template<class SocketPtr> void handle_player(boost::asio::yield_context yield, SocketPtr socket, const player& player);
|
||||
template<class SocketPtr> void handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player);
|
||||
void handle_player_in_lobby(player_iterator player, simple_wml::document& doc);
|
||||
void handle_player_in_game(player_iterator player, simple_wml::document& doc);
|
||||
void handle_whisper(player_iterator player, simple_wml::node& whisper);
|
||||
|
|
Loading…
Add table
Reference in a new issue