implement more plumbing between client and server network

This commit is contained in:
Lion Kortlepel 2024-03-03 22:24:35 +01:00
parent 342b3c3075
commit 387bce5033
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
6 changed files with 84 additions and 24 deletions

View File

@ -2,6 +2,7 @@
#include "ClientPacket.h" #include "ClientPacket.h"
#include "ClientTransport.h" #include "ClientTransport.h"
#include "Http.h" #include "Http.h"
#include "Launcher.h"
#include "Identity.h" #include "Identity.h"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
@ -93,12 +94,12 @@ void ClientNetwork::handle_connection(ip::tcp::socket&& socket) {
} }
void ClientNetwork::handle_packet(bmp::ClientPacket& packet) { void ClientNetwork::handle_packet(bmp::ClientPacket& packet) {
spdlog::trace("Got client packet: purpose: 0x{:x}, flags: 0x{:x}, pid: {}, vid: {}, size: {}", spdlog::debug("Got client packet: purpose: 0x{:x}, flags: 0x{:x}, pid: {}, vid: {}, size: {}",
uint16_t(packet.purpose), uint16_t(packet.purpose),
uint8_t(packet.flags), uint8_t(packet.flags),
packet.pid, packet.vid, packet.pid, packet.vid,
packet.get_readable_data().size()); packet.get_readable_data().size());
spdlog::trace("Client State: 0x{:x}", int(m_client_state)); spdlog::debug("Client State: 0x{:x}", int(m_client_state));
switch (m_client_state) { switch (m_client_state) {
case bmp::ClientIdentification: case bmp::ClientIdentification:
@ -147,12 +148,12 @@ void ClientNetwork::handle_client_identification(bmp::ClientPacket& packet) {
disconnect(fmt::format("Incompatible protocol version, expected v{}", "1.x.x")); disconnect(fmt::format("Incompatible protocol version, expected v{}", "1.x.x"));
return; return;
} }
m_mod_version = Version { uint8_t(mod_version.at(0)), uint8_t(mod_version.at(1)), uint8_t(mod_version.at(2)) }; *launcher.mod_version = Version { uint8_t(mod_version.at(0)), uint8_t(mod_version.at(1)), uint8_t(mod_version.at(2)) };
m_game_version = Version { uint8_t(game_version.at(0)), uint8_t(game_version.at(1)), uint8_t(game_version.at(2)) }; *launcher.game_version = Version { uint8_t(game_version.at(0)), uint8_t(game_version.at(1)), uint8_t(game_version.at(2)) };
spdlog::info("Connected to {} (mod v{}, game v{}, protocol v{}.{}.{}", spdlog::info("Connected to {} (mod v{}, game v{}, protocol v{}.{}.{}",
impl, impl,
m_mod_version.to_string(), launcher.mod_version->to_string(),
m_game_version.to_string(), launcher.game_version->to_string(),
protocol_version.at(0), protocol_version.at(0),
protocol_version.at(1), protocol_version.at(2)); protocol_version.at(1), protocol_version.at(2));
} catch (const std::exception& e) { } catch (const std::exception& e) {

View File

@ -19,6 +19,8 @@ public:
void run(); void run();
private: private:
void handle_connection(ip::tcp::socket&& socket); void handle_connection(ip::tcp::socket&& socket);
bmp::ClientPacket client_tcp_read(); bmp::ClientPacket client_tcp_read();
@ -46,9 +48,6 @@ private:
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);
Version m_mod_version;
Version m_game_version;
Sync<ident::Identity> m_identity {}; Sync<ident::Identity> m_identity {};
uint16_t m_listen_port {}; uint16_t m_listen_port {};

View File

@ -1,9 +1,11 @@
#include "Launcher.h" #include "Launcher.h"
#include "ClientNetwork.h"
#include "Compression.h" #include "Compression.h"
#include "Hashing.h" #include "Hashing.h"
#include "Http.h" #include "Http.h"
#include "Identity.h" #include "Identity.h"
#include "Platform.h" #include "Platform.h"
#include "ServerNetwork.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>
@ -30,6 +32,12 @@ Launcher::Launcher() {
} }
// try logging in immediately, for later update requests and such stuff // try logging in immediately, for later update requests and such stuff
try_auto_login(); try_auto_login();
client_network = std::make_unique<ClientNetwork>(*this, m_config->port);
m_client_network_thread = boost::scoped_thread<>([&] {
client_network->run();
});
} }
/// Sets shared headers for all backend proxy messages /// Sets shared headers for all backend proxy messages
@ -95,7 +103,7 @@ 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, 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 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={}",
@ -284,3 +292,35 @@ void Launcher::try_auto_login() {
} }
} }
Result<void, std::string> Launcher::start_server_network(const std::string& host, uint16_t port) {
ip::tcp::resolver resolver(m_io);
boost::system::error_code ec;
auto resolved = resolver.resolve(host, std::to_string(port), ec);
if (ec) {
spdlog::error("Failed to resolve '{}': {}", host, ec.message());
return fmt::format("Failed to resolve '{}': {}", host, ec.message());
}
bool connected = false;
for (const auto& addr : resolved) {
try {
server_network = std::make_unique<ServerNetwork>(*this, addr.endpoint());
spdlog::info("Resolved and connected to '[{}]:{}'",
addr.endpoint().address().to_string(),
addr.endpoint().port());
connected = true;
break;
} catch (...) {
// ignore
}
}
if (!connected) {
spdlog::error("Failed to connect to [{}]:{}", host, port);
return fmt::format("Failed to connect to [{}]:{}", host, port);
} else {
m_server_network_thread = boost::scoped_thread<>([&] {
server_network->run();
});
}
return outcome::success();
}

View File

@ -3,6 +3,7 @@
#include "Config.h" #include "Config.h"
#include "Identity.h" #include "Identity.h"
#include "Sync.h" #include "Sync.h"
#include "Version.h"
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ip/udp.hpp> #include <boost/asio/ip/udp.hpp>
#include <boost/thread/scoped_thread.hpp> #include <boost/thread/scoped_thread.hpp>
@ -11,6 +12,9 @@
#include <string> #include <string>
#include <thread> #include <thread>
class ClientNetwork;
class ServerNetwork;
class Launcher { class Launcher {
public: public:
Launcher(); Launcher();
@ -31,6 +35,14 @@ public:
Sync<ident::Identity> identity {}; Sync<ident::Identity> identity {};
Result<void, std::string> start_server_network(const std::string& host, uint16_t port);
Sync<Version> mod_version {};
Sync<Version> game_version {};
std::unique_ptr<ClientNetwork> client_network {};
std::unique_ptr<ServerNetwork> server_network {};
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();

View File

@ -2,6 +2,7 @@
#include "ClientInfo.h" #include "ClientInfo.h"
#include "Identity.h" #include "Identity.h"
#include "ImplementationInfo.h" #include "ImplementationInfo.h"
#include "Launcher.h"
#include "ProtocolVersion.h" #include "ProtocolVersion.h"
#include "ServerInfo.h" #include "ServerInfo.h"
#include "Transport.h" #include "Transport.h"
@ -13,6 +14,11 @@ ServerNetwork::ServerNetwork(Launcher& launcher, const ip::tcp::endpoint& ep)
: m_tcp_ep(ep) : m_tcp_ep(ep)
, launcher(launcher) { , launcher(launcher) {
spdlog::debug("Server network created"); spdlog::debug("Server network created");
boost::system::error_code ec;
m_tcp_socket.connect(m_tcp_ep, ec);
if (ec) {
throw std::runtime_error(ec.message());
}
} }
ServerNetwork::~ServerNetwork() { ServerNetwork::~ServerNetwork() {
@ -20,12 +26,6 @@ ServerNetwork::~ServerNetwork() {
} }
void ServerNetwork::run() { void ServerNetwork::run() {
boost::system::error_code ec;
m_tcp_socket.connect(m_tcp_ep, ec);
if (ec) {
spdlog::error("Failed to connect to [{}]:{}: {}", m_tcp_ep.address().to_string(), m_tcp_ep.port(), ec.message());
throw std::runtime_error(ec.message());
}
// start the connection by going to the identification state and sending // start the connection by going to the identification state and sending
// the first packet in the identification protocol (protocol version) // the first packet in the identification protocol (protocol version)
m_state = bmp::State::Identification; m_state = bmp::State::Identification;
@ -171,11 +171,18 @@ void ServerNetwork::handle_identification(const bmp::Packet& packet) {
.purpose = bmp::Purpose::ClientInfo, .purpose = bmp::Purpose::ClientInfo,
.raw_data = std::vector<uint8_t>(1024), .raw_data = std::vector<uint8_t>(1024),
}; };
// TODO: Game and mod version
struct bmp::ClientInfo ci { struct bmp::ClientInfo ci {
.program_version = { .major = PRJ_VERSION_MAJOR, .minor = PRJ_VERSION_MINOR, .patch = PRJ_VERSION_PATCH }, .program_version = { .major = PRJ_VERSION_MAJOR, .minor = PRJ_VERSION_MINOR, .patch = PRJ_VERSION_PATCH },
.game_version = { .major = 4, .minor = 5, .patch = 6 }, .game_version = {
.mod_version = { .major = 1, .minor = 2, .patch = 3 }, .major = launcher.game_version->major,
.minor = launcher.game_version->minor,
.patch = launcher.game_version->patch,
},
.mod_version = {
.major = launcher.mod_version->major,
.minor = launcher.mod_version->minor,
.patch = launcher.mod_version->patch,
},
.implementation = bmp::ImplementationInfo { .implementation = bmp::ImplementationInfo {
.value = "Official BeamMP Launcher", .value = "Official BeamMP Launcher",
}, },
@ -202,10 +209,10 @@ void ServerNetwork::handle_identification(const bmp::Packet& packet) {
case bmp::Purpose::StateChangeAuthentication: { case bmp::Purpose::StateChangeAuthentication: {
spdlog::debug("Starting authentication"); spdlog::debug("Starting authentication");
m_state = bmp::State::Authentication; m_state = bmp::State::Authentication;
Identity ident{}; auto ident = launcher.identity.synchronize();
bmp::Packet pubkey_packet { bmp::Packet pubkey_packet {
.purpose = bmp::Purpose::PlayerPublicKey, .purpose = bmp::Purpose::PlayerPublicKey,
.raw_data = std::vector<uint8_t>(ident.PublicKey.begin(), ident.PublicKey.end()) .raw_data = std::vector<uint8_t>(ident->PublicKey.begin(), ident->PublicKey.end())
}; };
tcp_write(pubkey_packet); tcp_write(pubkey_packet);
break; break;
@ -291,4 +298,3 @@ void ServerNetwork::handle_playing(const bmp::Packet& packet) {
break; break;
} }
} }

View File

@ -89,9 +89,11 @@ int main(int argc, char** argv) {
launcher.start_game(); launcher.start_game();
} }
ClientNetwork cn(4444); while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
cn.run(); //auto _ = launcher.start_server_network("beamcruise.com", 10814);
// old: launcher.start_network(); // old: launcher.start_network();