MP: cleaned up open_connection
This commit is contained in:
parent
5feaf973ce
commit
55340a98e4
1 changed files with 42 additions and 50 deletions
|
@ -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, ">");
|
||||
|
||||
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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue