mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2025-07-04 00:47:23 +00:00
add auto login
This commit is contained in:
parent
6c67d07ce3
commit
c74967e513
@ -1,6 +1,7 @@
|
|||||||
#include "ClientNetwork.h"
|
#include "ClientNetwork.h"
|
||||||
#include "ClientPacket.h"
|
#include "ClientPacket.h"
|
||||||
#include "ClientTransport.h"
|
#include "ClientTransport.h"
|
||||||
|
#include "Http.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
@ -258,11 +259,8 @@ void ClientNetwork::handle_login(bmp::ClientPacket& packet) {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
client_tcp_write(login_result);
|
client_tcp_write(login_result);
|
||||||
bmp::ClientPacket change_to_quickjoin {
|
|
||||||
.purpose = bmp::ClientPurpose::StateChangeQuickJoin,
|
start_quick_join();
|
||||||
};
|
|
||||||
client_tcp_write(change_to_quickjoin);
|
|
||||||
m_client_state = bmp::ClientState::QuickJoin;
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::error("Failed to read json for purpose 0x{:x}: {}", uint16_t(packet.purpose), e.what());
|
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)));
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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() {
|
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) {
|
nlohmann::json ClientNetwork::vec_to_json(const std::vector<uint8_t>& vec) {
|
||||||
return json::parse(std::string(vec.begin(), vec.end()));
|
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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -38,6 +38,10 @@ private:
|
|||||||
|
|
||||||
void disconnect(const std::string& reason);
|
void disconnect(const std::string& reason);
|
||||||
void start_login();
|
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 std::vector<uint8_t> json_to_vec(const nlohmann::json& json);
|
||||||
static nlohmann::json vec_to_json(const std::vector<uint8_t>& vec);
|
static nlohmann::json vec_to_json(const std::vector<uint8_t>& vec);
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
#include "Compression.h"
|
#include "Compression.h"
|
||||||
#include "Hashing.h"
|
#include "Hashing.h"
|
||||||
#include "Http.h"
|
#include "Http.h"
|
||||||
|
#include "Identity.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
#include "Version.h"
|
#include "Version.h"
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/iostreams/device/mapped_file.hpp>
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
#include <boost/process.hpp>
|
#include <boost/process.hpp>
|
||||||
|
#include <charconv>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
@ -15,7 +17,6 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <charconv>
|
|
||||||
|
|
||||||
using namespace boost::asio;
|
using namespace boost::asio;
|
||||||
|
|
||||||
@ -31,6 +32,8 @@ Launcher::Launcher()
|
|||||||
if (!m_config->is_valid) {
|
if (!m_config->is_valid) {
|
||||||
spdlog::error("Launcher config invalid!");
|
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
|
/// Sets shared headers for all backend proxy messages
|
||||||
@ -52,7 +55,7 @@ void Launcher::proxy_main() {
|
|||||||
httplib::Client cli("https://backend.beammp.com");
|
httplib::Client cli("https://backend.beammp.com");
|
||||||
proxy_set_headers(res);
|
proxy_set_headers(res);
|
||||||
if (req.has_header("X-BMP-Authentication")) {
|
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")) {
|
if (req.has_header("X-API-Version")) {
|
||||||
headers.emplace("X-API-Version", req.get_header_value("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");
|
httplib::Client cli("https://backend.beammp.com");
|
||||||
proxy_set_headers(res);
|
proxy_set_headers(res);
|
||||||
if (req.has_header("X-BMP-Authentication")) {
|
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")) {
|
if (req.has_header("X-API-Version")) {
|
||||||
headers.emplace("X-API-Version", req.get_header_value("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) {
|
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 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, m_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"
|
std::string DownloadURL = fmt::format("https://backend.beammp.com/builds/launcher?download=true"
|
||||||
"&pk={}"
|
"&pk={}"
|
||||||
"&branch={}",
|
"&branch={}",
|
||||||
m_identity->PublicKey, m_config->branch);
|
identity->PublicKey, m_config->branch);
|
||||||
|
|
||||||
spdlog::debug("Latest hash: {}", LatestHash);
|
spdlog::debug("Latest hash: {}", LatestHash);
|
||||||
spdlog::debug("Latest version: {}", LatestVersion);
|
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());
|
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);
|
transform(LatestHash.begin(), LatestHash.end(), LatestHash.begin(), ::tolower);
|
||||||
LatestHash.erase(std::remove_if(LatestHash.begin(), LatestHash.end(),
|
LatestHash.erase(std::remove_if(LatestHash.begin(), LatestHash.end(),
|
||||||
[](auto const& c) -> bool { return !std::isalnum(c); }),
|
[](auto const& c) -> bool { return !std::isalnum(c); }),
|
||||||
@ -277,5 +279,12 @@ void Launcher::game_main() {
|
|||||||
void Launcher::start_game() {
|
void Launcher::start_game() {
|
||||||
m_game_thread = boost::scoped_thread<>(&Launcher::game_main, this);
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ public:
|
|||||||
|
|
||||||
std::string get_public_key();
|
std::string get_public_key();
|
||||||
|
|
||||||
|
Sync<ident::Identity> identity {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Thread main function for the http(s) proxy thread.
|
/// Thread main function for the http(s) proxy thread.
|
||||||
void proxy_main();
|
void proxy_main();
|
||||||
@ -42,6 +44,8 @@ private:
|
|||||||
|
|
||||||
void enable_mp();
|
void enable_mp();
|
||||||
|
|
||||||
|
void try_auto_login();
|
||||||
|
|
||||||
Sync<bool> m_mod_loaded { false };
|
Sync<bool> m_mod_loaded { false };
|
||||||
|
|
||||||
Sync<Config> m_config;
|
Sync<Config> m_config;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user