add auto login

This commit is contained in:
Lion Kortlepel 2024-03-03 13:44:52 +01:00
parent 6c67d07ce3
commit c74967e513
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
4 changed files with 132 additions and 14 deletions

View File

@ -1,6 +1,7 @@
#include "ClientNetwork.h"
#include "ClientPacket.h"
#include "ClientTransport.h"
#include "Http.h"
#include "Identity.h"
#include <nlohmann/json.hpp>
@ -258,11 +259,8 @@ void ClientNetwork::handle_login(bmp::ClientPacket& packet) {
}),
};
client_tcp_write(login_result);
bmp::ClientPacket change_to_quickjoin {
.purpose = bmp::ClientPurpose::StateChangeQuickJoin,
};
client_tcp_write(change_to_quickjoin);
m_client_state = bmp::ClientState::QuickJoin;
start_quick_join();
} catch (const std::exception& e) {
spdlog::error("Failed to read json for purpose 0x{:x}: {}", uint16_t(packet.purpose), e.what());
disconnect(fmt::format("Invalid json in purpose 0x{:x}, see launcher logs for more info", uint16_t(packet.purpose)));
@ -275,27 +273,98 @@ void ClientNetwork::handle_login(bmp::ClientPacket& packet) {
}
void ClientNetwork::handle_quick_join(bmp::ClientPacket& packet) {
switch (packet.purpose) {
default:
disconnect(fmt::format("Invalid packet purpose in state 0x{:x}: 0x{:x}", uint16_t(m_client_state), uint16_t(packet.purpose)));
break;
}
}
void ClientNetwork::handle_browsing(bmp::ClientPacket& packet) {
switch (packet.purpose) {
case bmp::ClientPurpose::ServerListRequest: {
auto list = load_server_list();
if (list.has_value()) {
bmp::ClientPacket response {
.purpose = bmp::ClientPurpose::ServerListResponse,
.raw_data = json_to_vec(list.value()),
};
client_tcp_write(response);
} else {
spdlog::error("Failed to load server list: {}", list.error());
bmp::ClientPacket err {
.purpose = bmp::ClientPurpose::Error,
.raw_data = json_to_vec({ "message", list.error() }),
};
client_tcp_write(err);
}
} break;
case bmp::ClientPurpose::Logout: {
spdlog::error("Logout is not yet implemented");
} break;
case bmp::ClientPurpose::Connect: {
try {
auto details = json::parse(packet.get_readable_data());
std::string host = details.at("host");
uint16_t port = details.at("port");
spdlog::info("Game requesting to connect to server [{}]:{}", host, port);
} catch (const std::exception& e) {
spdlog::error("Failed to read json for purpose 0x{:x}: {}", uint16_t(packet.purpose), e.what());
disconnect(fmt::format("Invalid json in purpose 0x{:x}, see launcher logs for more info", uint16_t(packet.purpose)));
}
} break;
default:
disconnect(fmt::format("Invalid packet purpose in state 0x{:x}: 0x{:x}", uint16_t(m_client_state), uint16_t(packet.purpose)));
break;
}
}
void ClientNetwork::handle_server_identification(bmp::ClientPacket& packet) {
switch (packet.purpose) {
default:
disconnect(fmt::format("Invalid packet purpose in state 0x{:x}: 0x{:x}", uint16_t(m_client_state), uint16_t(packet.purpose)));
break;
}
}
void ClientNetwork::handle_server_authentication(bmp::ClientPacket& packet) {
switch (packet.purpose) {
default:
disconnect(fmt::format("Invalid packet purpose in state 0x{:x}: 0x{:x}", uint16_t(m_client_state), uint16_t(packet.purpose)));
break;
}
}
void ClientNetwork::handle_server_mod_download(bmp::ClientPacket& packet) {
switch (packet.purpose) {
default:
disconnect(fmt::format("Invalid packet purpose in state 0x{:x}: 0x{:x}", uint16_t(m_client_state), uint16_t(packet.purpose)));
break;
}
}
void ClientNetwork::handle_server_session_setup(bmp::ClientPacket& packet) {
switch (packet.purpose) {
default:
disconnect(fmt::format("Invalid packet purpose in state 0x{:x}: 0x{:x}", uint16_t(m_client_state), uint16_t(packet.purpose)));
break;
}
}
void ClientNetwork::handle_server_playing(bmp::ClientPacket& packet) {
switch (packet.purpose) {
default:
disconnect(fmt::format("Invalid packet purpose in state 0x{:x}: 0x{:x}", uint16_t(m_client_state), uint16_t(packet.purpose)));
break;
}
}
void ClientNetwork::handle_server_leaving(bmp::ClientPacket& packet) {
switch (packet.purpose) {
default:
disconnect(fmt::format("Invalid packet purpose in state 0x{:x}: 0x{:x}", uint16_t(m_client_state), uint16_t(packet.purpose)));
break;
}
}
bmp::ClientPacket ClientNetwork::client_tcp_read() {
@ -329,3 +398,35 @@ std::vector<uint8_t> ClientNetwork::json_to_vec(const nlohmann::json& value) {
nlohmann::json ClientNetwork::vec_to_json(const std::vector<uint8_t>& vec) {
return json::parse(std::string(vec.begin(), vec.end()));
}
void ClientNetwork::start_quick_join() {
bmp::ClientPacket change_to_quickjoin {
.purpose = bmp::ClientPurpose::StateChangeQuickJoin,
};
client_tcp_write(change_to_quickjoin);
m_client_state = bmp::ClientState::QuickJoin;
// TODO: Implement DoJoin, etc
start_browsing();
}
void ClientNetwork::start_browsing() {
bmp::ClientPacket change_to_browsing {
.purpose = bmp::ClientPurpose::StateChangeBrowsing,
};
client_tcp_write(change_to_browsing);
m_client_state = bmp::ClientState::Browsing;
}
Result<nlohmann::json, std::string> ClientNetwork::load_server_list() noexcept {
try {
auto list = HTTP::Get("https://backend.beammp.com/servers-list");
if (list == "-1") {
return outcome::failure("Failed to fetch server list, see launcher log for more information.");
}
json result = json::parse(list);
return outcome::success(result);
} catch (const std::exception& e) {
return outcome::failure(fmt::format("Failed to fetch server list from backend: {}", e.what()));
}
}

View File

@ -38,6 +38,10 @@ private:
void disconnect(const std::string& reason);
void start_login();
void start_quick_join();
void start_browsing();
Result<nlohmann::json, std::string> load_server_list() noexcept;
static std::vector<uint8_t> json_to_vec(const nlohmann::json& json);
static nlohmann::json vec_to_json(const std::vector<uint8_t>& vec);

View File

@ -2,11 +2,13 @@
#include "Compression.h"
#include "Hashing.h"
#include "Http.h"
#include "Identity.h"
#include "Platform.h"
#include "Version.h"
#include <boost/asio.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/process.hpp>
#include <charconv>
#include <chrono>
#include <filesystem>
#include <fmt/format.h>
@ -15,7 +17,6 @@
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#include <vector>
#include <charconv>
using namespace boost::asio;
@ -31,6 +32,8 @@ Launcher::Launcher()
if (!m_config->is_valid) {
spdlog::error("Launcher config invalid!");
}
// try logging in immediately, for later update requests and such stuff
try_auto_login();
}
/// Sets shared headers for all backend proxy messages
@ -52,7 +55,7 @@ void Launcher::proxy_main() {
httplib::Client cli("https://backend.beammp.com");
proxy_set_headers(res);
if (req.has_header("X-BMP-Authentication")) {
headers.emplace("X-BMP-Authentication", m_identity->PrivateKey);
headers.emplace("X-BMP-Authentication", identity->PrivateKey);
}
if (req.has_header("X-API-Version")) {
headers.emplace("X-API-Version", req.get_header_value("X-API-Version"));
@ -68,7 +71,7 @@ void Launcher::proxy_main() {
httplib::Client cli("https://backend.beammp.com");
proxy_set_headers(res);
if (req.has_header("X-BMP-Authentication")) {
headers.emplace("X-BMP-Authentication", m_identity->PrivateKey);
headers.emplace("X-BMP-Authentication", identity->PrivateKey);
}
if (req.has_header("X-API-Version")) {
headers.emplace("X-API-Version", req.get_header_value("X-API-Version"));
@ -95,13 +98,12 @@ void Launcher::parse_config() {
}
void Launcher::check_for_updates(int argc, char** argv) {
std::string LatestHash = HTTP::Get(fmt::format("https://backend.beammp.com/sha/launcher?branch={}&pk={}", m_config->branch, m_identity->PublicKey));
std::string LatestVersion = HTTP::Get(fmt::format("https://backend.beammp.com/version/launcher?branch={}&pk={}", m_config->branch, m_identity->PublicKey));
std::string LatestHash = HTTP::Get(fmt::format("https://backend.beammp.com/sha/launcher?branch={}&pk={}", m_config->branch, identity->PublicKey));
std::string LatestVersion = HTTP::Get(fmt::format("https://backend.beammp.com/version/launcher?branch={}&pk={}", m_config->branch,identity->PublicKey));
std::string DownloadURL = fmt::format("https://backend.beammp.com/builds/launcher?download=true"
"&pk={}"
"&branch={}",
m_identity->PublicKey, m_config->branch);
identity->PublicKey, m_config->branch);
spdlog::debug("Latest hash: {}", LatestHash);
spdlog::debug("Latest version: {}", LatestVersion);
@ -170,7 +172,7 @@ void Launcher::pre_game() {
check_mp((std::filesystem::path(m_config->game_dir) / "mods/multiplayer").generic_string());
std::string LatestHash = HTTP::Get(fmt::format("https://backend.beammp.com/sha/mod?branch={}&pk={}", m_config->branch, m_identity->PublicKey));
std::string LatestHash = HTTP::Get(fmt::format("https://backend.beammp.com/sha/mod?branch={}&pk={}", m_config->branch, identity->PublicKey));
transform(LatestHash.begin(), LatestHash.end(), LatestHash.begin(), ::tolower);
LatestHash.erase(std::remove_if(LatestHash.begin(), LatestHash.end(),
[](auto const& c) -> bool { return !std::isalnum(c); }),
@ -277,5 +279,12 @@ void Launcher::game_main() {
void Launcher::start_game() {
m_game_thread = boost::scoped_thread<>(&Launcher::game_main, this);
}
void Launcher::try_auto_login() {
if (identity->PublicKey.empty() && ident::is_login_cached()) {
auto login = ident::login_cached();
if (login.has_value()) {
*identity = login.value();
}
}
}

View File

@ -29,6 +29,8 @@ public:
std::string get_public_key();
Sync<ident::Identity> identity {};
private:
/// Thread main function for the http(s) proxy thread.
void proxy_main();
@ -42,6 +44,8 @@ private:
void enable_mp();
void try_auto_login();
Sync<bool> m_mod_loaded { false };
Sync<Config> m_config;