From e836ad51334e1984c47d8ed94ae7a0be48294052 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sun, 10 Mar 2024 15:25:48 +0100 Subject: [PATCH] implement server network -> client network communication --- deps/BeamMP-Protocol | 2 +- src/ClientNetwork.cpp | 119 +++++++++++++++++++++++++++++++++++++----- src/ClientNetwork.h | 5 ++ src/ServerNetwork.cpp | 14 ++--- src/ServerNetwork.h | 2 +- 5 files changed, 121 insertions(+), 21 deletions(-) diff --git a/deps/BeamMP-Protocol b/deps/BeamMP-Protocol index 18ab3b9..74b4eee 160000 --- a/deps/BeamMP-Protocol +++ b/deps/BeamMP-Protocol @@ -1 +1 @@ -Subproject commit 18ab3b96d9706dc402670052c05e8ad7c0c63c03 +Subproject commit 74b4eee8fe2a2ca5b955347eaa2b54248bcbb456 diff --git a/src/ClientNetwork.cpp b/src/ClientNetwork.cpp index cf95ad2..18a8369 100644 --- a/src/ClientNetwork.cpp +++ b/src/ClientNetwork.cpp @@ -4,6 +4,8 @@ #include "Http.h" #include "Identity.h" #include "Launcher.h" +#include "Transport.h" +#include "Util.h" #include #include @@ -297,6 +299,7 @@ void ClientNetwork::handle_browsing(bmp::ClientPacket& packet) { }); } else { spdlog::info("Connected to server!"); + start_server_identification(); } } catch (const std::exception& e) { spdlog::error("Failed to read json for purpose 0x{:x}: {}", uint16_t(packet.purpose), e.what()); @@ -370,7 +373,7 @@ void ClientNetwork::client_tcp_read(std::function han m_tmp_packet.raw_data.resize(hdr.data_size); m_tmp_packet.purpose = hdr.purpose; m_tmp_packet.flags = hdr.flags; - spdlog::debug("Got header: purpose: 0x{:x}, flags: 0x{:x}, pid: {}, vid: {}, size: {}", + spdlog::trace("Got header: purpose: 0x{:x}, flags: 0x{:x}, pid: {}, vid: {}, size: {}", uint16_t(m_tmp_packet.purpose), uint8_t(m_tmp_packet.flags), m_tmp_packet.pid, m_tmp_packet.vid, @@ -401,7 +404,7 @@ void ClientNetwork::client_tcp_write(bmp::ClientPacket&& packet, std::functionpurpose)); + spdlog::trace("Wrote {} bytes for 0x{:x}", size, int(owned_packet->purpose)); if (handler) { handler(ec); } else { @@ -453,27 +456,80 @@ Result, std::string> ClientNetwork::load_server_list() noex } void ClientNetwork::handle_server_packet(bmp::Packet&& packet) { post(m_io, [packet, this] { - spdlog::info("HELLO WORLD: {}", m_listen_port); switch (packet.purpose) { - case bmp::Invalid: - break; - case bmp::ProtocolVersion: - case bmp::ProtocolVersionOk: case bmp::ProtocolVersionBad: + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::ConnectError, + .raw_data = json_to_vec({ "message", "Server is outdated or too new - protocol is incompatible. Please try a different server and make sure your Launcher and Mod are up-to-date." }), + }); + start_browsing(); + break; + case bmp::ProtocolVersionOk: + start_server_authentication(); + break; + case bmp::AuthOk: + uint32_t player_id; + bmp::deserialize(player_id, packet.get_readable_data()); + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::AuthenticationOk, + .raw_data = json_to_vec({ "pid", player_id }), + }); + start_server_mod_download(); + break; + case bmp::AuthFailed: + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::AuthenticationError, + .raw_data = json_to_vec( + { "message", + std::string( + packet.get_readable_data().begin(), + packet.get_readable_data().end()) }), + }); + start_browsing(); + break; + case bmp::PlayerRejected: + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::PlayerRejected, + .raw_data = json_to_vec( + { "message", + std::string( + packet.get_readable_data().begin(), + packet.get_readable_data().end()) }), + }); + start_browsing(); + break; + case bmp::ModsInfo: + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::ModSyncStatus, + .raw_data = json_to_vec(json::array()), // TODO: send more here i guess + }); + spdlog::debug("Mod stuff not implemented, skipping to session setup"); + break; + case bmp::MapInfo: { + auto data = packet.get_readable_data(); + auto map = std::string(data.begin(), data.end()); + spdlog::debug("Map: '{}'", map); + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::MapInfo, + .raw_data = json_to_vec({ "map", map }), + }); + start_server_session_setup(); + } break; + case bmp::PlayersVehiclesInfo: + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::PlayersAndVehiclesInfo, + .raw_data = packet.get_readable_data(), + }); + start_server_playing(); + break; case bmp::ClientInfo: case bmp::ServerInfo: case bmp::PlayerPublicKey: - case bmp::AuthOk: - case bmp::AuthFailed: - case bmp::PlayerRejected: case bmp::StartUDP: - case bmp::ModsInfo: - case bmp::MapInfo: case bmp::ModRequest: case bmp::ModResponse: case bmp::ModRequestInvalid: case bmp::ModsSyncDone: - case bmp::PlayersVehiclesInfo: case bmp::SessionReady: case bmp::Ping: case bmp::VehicleSpawn: @@ -502,6 +558,9 @@ void ClientNetwork::handle_server_packet(bmp::Packet&& packet) { case bmp::StateChangePlaying: case bmp::StateChangeLeaving: break; + case bmp::Invalid: + case bmp::ProtocolVersion: + break; } }); } @@ -521,3 +580,37 @@ void ClientNetwork::handle_accept(boost::system::error_code ec) { } // TODO: We should probably accept() again somewhere once the game disconnected } +void ClientNetwork::start_server_identification() { + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::StateChangeServerIdentification, + }); + m_client_state = bmp::ClientState::ServerIdentification; +} + +void ClientNetwork::start_server_authentication() { + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::StateChangeServerAuthentication, + }); + m_client_state = bmp::ClientState::ServerAuthentication; +} + +void ClientNetwork::start_server_mod_download() { + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::StateChangeServerModDownload, + }); + m_client_state = bmp::ClientState::ServerModDownload; +} + +void ClientNetwork::start_server_session_setup() { + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::StateChangeServerSessionSetup, + }); + m_client_state = bmp::ClientState::ServerSessionSetup; +} + +void ClientNetwork::start_server_playing() { + client_tcp_write(bmp::ClientPacket { + .purpose = bmp::ClientPurpose::StateChangeServerPlaying, + }); + m_client_state = bmp::ClientState::ServerPlaying; +} diff --git a/src/ClientNetwork.h b/src/ClientNetwork.h index 197dfcd..50407eb 100644 --- a/src/ClientNetwork.h +++ b/src/ClientNetwork.h @@ -48,6 +48,11 @@ private: void start_login(); void start_quick_join(); void start_browsing(); + void start_server_identification(); + void start_server_authentication(); + void start_server_mod_download(); + void start_server_session_setup(); + void start_server_playing(); Result, std::string> load_server_list() noexcept; diff --git a/src/ServerNetwork.cpp b/src/ServerNetwork.cpp index f48ab72..a31b4bf 100644 --- a/src/ServerNetwork.cpp +++ b/src/ServerNetwork.cpp @@ -53,7 +53,7 @@ void ServerNetwork::run() { m_io.run(); } -void ServerNetwork::handle_packet(const bmp::Packet& packet) { +void ServerNetwork::handle_packet(bmp::Packet&& packet) { // handle ping immediately if (m_state > bmp::State::Identification && packet.purpose == bmp::Purpose::Ping) { tcp_write(bmp::Packet { @@ -83,6 +83,8 @@ void ServerNetwork::handle_packet(const bmp::Packet& packet) { case bmp::State::Leaving: break; } + + launcher.client_network->handle_server_packet(std::move(packet)); } void ServerNetwork::handle_mod_download(const bmp::Packet& packet) { @@ -263,7 +265,7 @@ void ServerNetwork::tcp_write(bmp::Packet&& packet, std::functionpurpose)); + spdlog::trace("Wrote {} bytes for 0x{:x} to server", size, int(owned_packet->purpose)); if (handler) { handler(ec); } else { @@ -271,7 +273,7 @@ void ServerNetwork::tcp_write(bmp::Packet&& packet, std::functionpurpose)); } else { // ok! - spdlog::debug("Sent packet of type 0x{:x} to server", int(owned_packet->purpose)); + spdlog::trace("Sent packet of type 0x{:x} to server", int(owned_packet->purpose)); } } }); @@ -303,7 +305,7 @@ void ServerNetwork::udp_write(bmp::Packet& packet) { if (ec) { spdlog::error("Failed to UDP write to server: {}", ec.message()); } else { - spdlog::info("Wrote {} bytes to server via UDP", size); + spdlog::trace("Wrote {} bytes to server via UDP", size); } }); } @@ -340,7 +342,7 @@ void ServerNetwork::handle_playing(const bmp::Packet& packet) { void ServerNetwork::start_tcp_read() { tcp_read([this](auto&& packet) { spdlog::debug("Got packet 0x{:x} from server", int(packet.purpose)); - handle_packet(packet); + handle_packet(std::move(packet)); start_tcp_read(); }); } @@ -348,7 +350,7 @@ void ServerNetwork::start_tcp_read() { void ServerNetwork::start_udp_read() { udp_read([this](auto&& ep, auto&& packet) { spdlog::debug("Got packet 0x{:x} from server via UDP", int(packet.purpose)); - handle_packet(packet); + handle_packet(std::move(packet)); start_udp_read(); }); } diff --git a/src/ServerNetwork.h b/src/ServerNetwork.h index 117a64b..3cadd82 100644 --- a/src/ServerNetwork.h +++ b/src/ServerNetwork.h @@ -32,7 +32,7 @@ private: /// Sends a packet to the specified UDP endpoint via the UDP socket. void udp_write(bmp::Packet& packet); - void handle_packet(const bmp::Packet& packet); + void handle_packet(bmp::Packet&& packet); void handle_identification(const bmp::Packet& packet); void handle_authentication(const bmp::Packet& packet); void handle_mod_download(const bmp::Packet& packet);