MP: cleaned up open_connection

This commit is contained in:
Charles Dang 2020-12-17 14:21:51 +11:00
parent 5feaf973ce
commit 55340a98e4

View file

@ -78,30 +78,22 @@ std::unique_ptr<wesnothd_connection> open_connection(std::string host)
shown_hosts.insert(addr);
// Initializes the connection to the server.
auto sock = std::make_unique<wesnothd_connection>(addr.first, addr.second);
if(!sock) {
return nullptr;
}
auto conn = std::make_unique<wesnothd_connection>(addr.first, addr.second);
// Start stage
gui2::dialogs::loading_screen::progress(loading_stage::connect_to_server);
// First, spin until we get a handshake from the server.
sock->wait_for_handshake();
conn->wait_for_handshake();
gui2::dialogs::loading_screen::progress(loading_stage::waiting);
config data;
bool received_join_lobby = false;
// Then, log in and wait for the lobby/game join prompt.
do {
if(!sock) {
return nullptr;
}
while(true) {
data.clear();
sock->wait_and_receive_data(data);
conn->wait_and_receive_data(data);
if(data.has_child("reject") || data.has_attribute("version")) {
std::string version;
@ -126,39 +118,36 @@ std::unique_ptr<wesnothd_connection> open_connection(std::string host)
auto redirect_host = redirect["host"].str();
auto redirect_port = redirect["port"].str("15000");
if(shown_hosts.find(hostpair(redirect_host, redirect_port)) != shown_hosts.end()) {
bool recorded_host;
std::tie(std::ignore, recorded_host) = shown_hosts.emplace(redirect_host, redirect_port);
if(!recorded_host) {
throw wesnothd_error(_("Server-side redirect loop"));
}
shown_hosts.emplace(redirect_host, redirect_port);
gui2::dialogs::loading_screen::progress(loading_stage::redirect);
// Open a new connection with the new host and port.
sock.reset();
sock = std::make_unique<wesnothd_connection>(redirect_host, redirect_port);
conn.reset();
conn = std::make_unique<wesnothd_connection>(redirect_host, redirect_port);
// Wait for new handshake.
sock->wait_for_handshake();
conn->wait_for_handshake();
gui2::dialogs::loading_screen::progress(loading_stage::waiting);
continue;
}
if(data.has_child("version")) {
config cfg;
config res;
config& cfg = res.add_child("version");
cfg["version"] = game_config::wesnoth_version.str();
cfg["client_source"] = game_config::dist_channel_id();
res.add_child("version", std::move(cfg));
sock->send_data(res);
conn->send_data(res);
}
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);
if(const config& error = data.child("error")) {
throw wesnothd_rejected_client_error(error["message"].str());
}
// Continue if we did not get a direction to login
@ -167,30 +156,28 @@ std::unique_ptr<wesnothd_connection> open_connection(std::string host)
}
// Enter login loop
for(;;) {
while(true) {
std::string login = preferences::login();
config response ;
config& sp = response.add_child("login") ;
sp["username"] = login ;
config response;
config& sp = response.add_child("login");
sp["username"] = login;
sock->send_data(response);
sock->wait_and_receive_data(data);
conn->send_data(response);
conn->wait_and_receive_data(data);
gui2::dialogs::loading_screen::progress(loading_stage::login_response);
config* warning = &data.child("warning");
if(*warning) {
if(const config& warning = data.child("warning")) {
std::string warning_msg;
if((*warning)["warning_code"] == MP_NAME_INACTIVE_WARNING) {
if(warning["warning_code"] == MP_NAME_INACTIVE_WARNING) {
warning_msg = VGETTEXT("The nickname $nick 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.", {{"nick", login}});
} else {
warning_msg = (*warning)["message"].str();
warning_msg = warning["message"].str();
}
warning_msg += "\n\n";
@ -211,7 +198,7 @@ std::unique_ptr<wesnothd_connection> open_connection(std::string host)
do {
std::string password = preferences::password(host, login);
bool fall_through = (*error)["force_confirmation"].to_bool() ?
const bool fall_through = (*error)["force_confirmation"].to_bool() ?
(gui2::show_message(_("Confirm"), (*error)["message"], gui2::dialogs::message::ok_cancel_buttons) == gui2::retval::CANCEL) :
false;
@ -237,21 +224,25 @@ std::unique_ptr<wesnothd_connection> open_connection(std::string host)
password.replace(pos, 1, "&gt;");
const std::string salt = (*error)["salt"];
if(salt.length() < 12) {
throw wesnothd_error(_("Bad data received from server"));
}
if(utils::md5::is_valid_prefix(salt)) {
sp["password"] = utils::md5(utils::md5(password, utils::md5::get_salt(salt),
utils::md5::get_iteration_count(salt)).base64_digest(), salt.substr(12, 8)).base64_digest();
sp["password"] = utils::md5(
utils::md5(password, utils::md5::get_salt(salt), utils::md5::get_iteration_count(salt)).base64_digest(),
salt.substr(12, 8)
).base64_digest();
} else if(utils::bcrypt::is_valid_prefix(salt)) {
try {
auto bcrypt_salt = utils::bcrypt::from_salted_salt(salt);
auto hash = utils::bcrypt::hash_pw(password, bcrypt_salt);
std::string outer_salt = salt.substr(bcrypt_salt.iteration_count_delim_pos + 23);
if(outer_salt.size() != 32)
const std::string outer_salt = salt.substr(bcrypt_salt.iteration_count_delim_pos + 23);
if(outer_salt.size() != 32) {
throw utils::hash_error("salt wrong size");
}
sp["password"] = utils::md5(hash.base64_digest(), outer_salt).base64_digest();
} catch(const utils::hash_error& err) {
ERR_MP << "bcrypt hash failed: " << err.what() << std::endl;
@ -265,8 +256,8 @@ std::unique_ptr<wesnothd_connection> open_connection(std::string host)
}
// Once again send our request...
sock->send_data(response);
sock->wait_and_receive_data(data);
conn->send_data(response);
conn->wait_and_receive_data(data);
gui2::dialogs::loading_screen::progress(loading_stage::login_response);
@ -364,14 +355,15 @@ std::unique_ptr<wesnothd_connection> open_connection(std::string host)
} // end login loop
if(const config& join_lobby = data.child("join_lobby")) {
received_join_lobby = true;
// Flag us as authenticated, if applicable...
preferences::set_admin_authentication(join_lobby["is_moderator"].to_bool(false));
}
} while(!received_join_lobby);
return sock;
// All done!
break;
}
}
return conn;
}
/** The main controller of the MP workflow. */