mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2025-07-01 23:46:59 +00:00
implement server network -> client network communication
This commit is contained in:
parent
72a5e7c5b1
commit
e836ad5133
2
deps/BeamMP-Protocol
vendored
2
deps/BeamMP-Protocol
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 18ab3b96d9706dc402670052c05e8ad7c0c63c03
|
Subproject commit 74b4eee8fe2a2ca5b955347eaa2b54248bcbb456
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user