implement server network -> client network communication

This commit is contained in:
Lion Kortlepel 2024-03-10 15:25:48 +01:00
parent 72a5e7c5b1
commit e836ad5133
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
5 changed files with 121 additions and 21 deletions

@ -1 +1 @@
Subproject commit 18ab3b96d9706dc402670052c05e8ad7c0c63c03 Subproject commit 74b4eee8fe2a2ca5b955347eaa2b54248bcbb456

View File

@ -4,6 +4,8 @@
#include "Http.h" #include "Http.h"
#include "Identity.h" #include "Identity.h"
#include "Launcher.h" #include "Launcher.h"
#include "Transport.h"
#include "Util.h"
#include <boost/asio/socket_base.hpp> #include <boost/asio/socket_base.hpp>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
@ -297,6 +299,7 @@ void ClientNetwork::handle_browsing(bmp::ClientPacket& packet) {
}); });
} else { } else {
spdlog::info("Connected to server!"); spdlog::info("Connected to server!");
start_server_identification();
} }
} 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());
@ -370,7 +373,7 @@ void ClientNetwork::client_tcp_read(std::function<void(bmp::ClientPacket&&)> han
m_tmp_packet.raw_data.resize(hdr.data_size); m_tmp_packet.raw_data.resize(hdr.data_size);
m_tmp_packet.purpose = hdr.purpose; m_tmp_packet.purpose = hdr.purpose;
m_tmp_packet.flags = hdr.flags; 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), uint16_t(m_tmp_packet.purpose),
uint8_t(m_tmp_packet.flags), uint8_t(m_tmp_packet.flags),
m_tmp_packet.pid, m_tmp_packet.vid, m_tmp_packet.pid, m_tmp_packet.vid,
@ -401,7 +404,7 @@ void ClientNetwork::client_tcp_write(bmp::ClientPacket&& packet, std::function<v
}; };
boost::asio::async_write(m_game_socket, buffers, boost::asio::async_write(m_game_socket, buffers,
[this, header_data, owned_packet, handler](auto ec, auto size) { [this, header_data, owned_packet, handler](auto ec, auto size) {
spdlog::debug("Wrote {} bytes for 0x{:x}", size, int(owned_packet->purpose)); spdlog::trace("Wrote {} bytes for 0x{:x}", size, int(owned_packet->purpose));
if (handler) { if (handler) {
handler(ec); handler(ec);
} else { } else {
@ -453,27 +456,80 @@ Result<std::vector<uint8_t>, std::string> ClientNetwork::load_server_list() noex
} }
void ClientNetwork::handle_server_packet(bmp::Packet&& packet) { void ClientNetwork::handle_server_packet(bmp::Packet&& packet) {
post(m_io, [packet, this] { post(m_io, [packet, this] {
spdlog::info("HELLO WORLD: {}", m_listen_port);
switch (packet.purpose) { switch (packet.purpose) {
case bmp::Invalid:
break;
case bmp::ProtocolVersion:
case bmp::ProtocolVersionOk:
case bmp::ProtocolVersionBad: 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::ClientInfo:
case bmp::ServerInfo: case bmp::ServerInfo:
case bmp::PlayerPublicKey: case bmp::PlayerPublicKey:
case bmp::AuthOk:
case bmp::AuthFailed:
case bmp::PlayerRejected:
case bmp::StartUDP: case bmp::StartUDP:
case bmp::ModsInfo:
case bmp::MapInfo:
case bmp::ModRequest: case bmp::ModRequest:
case bmp::ModResponse: case bmp::ModResponse:
case bmp::ModRequestInvalid: case bmp::ModRequestInvalid:
case bmp::ModsSyncDone: case bmp::ModsSyncDone:
case bmp::PlayersVehiclesInfo:
case bmp::SessionReady: case bmp::SessionReady:
case bmp::Ping: case bmp::Ping:
case bmp::VehicleSpawn: case bmp::VehicleSpawn:
@ -502,6 +558,9 @@ void ClientNetwork::handle_server_packet(bmp::Packet&& packet) {
case bmp::StateChangePlaying: case bmp::StateChangePlaying:
case bmp::StateChangeLeaving: case bmp::StateChangeLeaving:
break; 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 // 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;
}

View File

@ -48,6 +48,11 @@ private:
void start_login(); void start_login();
void start_quick_join(); void start_quick_join();
void start_browsing(); 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::vector<uint8_t>, std::string> load_server_list() noexcept; Result<std::vector<uint8_t>, std::string> load_server_list() noexcept;

View File

@ -53,7 +53,7 @@ void ServerNetwork::run() {
m_io.run(); m_io.run();
} }
void ServerNetwork::handle_packet(const bmp::Packet& packet) { void ServerNetwork::handle_packet(bmp::Packet&& packet) {
// handle ping immediately // handle ping immediately
if (m_state > bmp::State::Identification && packet.purpose == bmp::Purpose::Ping) { if (m_state > bmp::State::Identification && packet.purpose == bmp::Purpose::Ping) {
tcp_write(bmp::Packet { tcp_write(bmp::Packet {
@ -83,6 +83,8 @@ void ServerNetwork::handle_packet(const bmp::Packet& packet) {
case bmp::State::Leaving: case bmp::State::Leaving:
break; break;
} }
launcher.client_network->handle_server_packet(std::move(packet));
} }
void ServerNetwork::handle_mod_download(const bmp::Packet& packet) { void ServerNetwork::handle_mod_download(const bmp::Packet& packet) {
@ -263,7 +265,7 @@ void ServerNetwork::tcp_write(bmp::Packet&& packet, std::function<void(boost::sy
}; };
boost::asio::async_write(m_tcp_socket, buffers, boost::asio::async_write(m_tcp_socket, buffers,
[this, header_data, owned_packet, handler](auto ec, auto size) { [this, header_data, owned_packet, handler](auto ec, auto size) {
spdlog::debug("Wrote {} bytes for 0x{:x} to server", size, int(owned_packet->purpose)); spdlog::trace("Wrote {} bytes for 0x{:x} to server", size, int(owned_packet->purpose));
if (handler) { if (handler) {
handler(ec); handler(ec);
} else { } else {
@ -271,7 +273,7 @@ void ServerNetwork::tcp_write(bmp::Packet&& packet, std::function<void(boost::sy
spdlog::error("Failed to send packet of type 0x{:x} to server", int(owned_packet->purpose)); spdlog::error("Failed to send packet of type 0x{:x} to server", int(owned_packet->purpose));
} else { } else {
// ok! // 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) { if (ec) {
spdlog::error("Failed to UDP write to server: {}", ec.message()); spdlog::error("Failed to UDP write to server: {}", ec.message());
} else { } 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() { void ServerNetwork::start_tcp_read() {
tcp_read([this](auto&& packet) { tcp_read([this](auto&& packet) {
spdlog::debug("Got packet 0x{:x} from server", int(packet.purpose)); spdlog::debug("Got packet 0x{:x} from server", int(packet.purpose));
handle_packet(packet); handle_packet(std::move(packet));
start_tcp_read(); start_tcp_read();
}); });
} }
@ -348,7 +350,7 @@ void ServerNetwork::start_tcp_read() {
void ServerNetwork::start_udp_read() { void ServerNetwork::start_udp_read() {
udp_read([this](auto&& ep, auto&& packet) { udp_read([this](auto&& ep, auto&& packet) {
spdlog::debug("Got packet 0x{:x} from server via UDP", int(packet.purpose)); spdlog::debug("Got packet 0x{:x} from server via UDP", int(packet.purpose));
handle_packet(packet); handle_packet(std::move(packet));
start_udp_read(); start_udp_read();
}); });
} }

View File

@ -32,7 +32,7 @@ private:
/// Sends a packet to the specified UDP endpoint via the UDP socket. /// Sends a packet to the specified UDP endpoint via the UDP socket.
void udp_write(bmp::Packet& packet); 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_identification(const bmp::Packet& packet);
void handle_authentication(const bmp::Packet& packet); void handle_authentication(const bmp::Packet& packet);
void handle_mod_download(const bmp::Packet& packet); void handle_mod_download(const bmp::Packet& packet);