mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2025-07-04 00:47:23 +00:00
implement states until session setup
mod download to be implemented fully
This commit is contained in:
parent
8eb8a80d54
commit
03dc3e3505
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "deps/BeamMP-Protocol"]
|
||||||
|
path = deps/BeamMP-Protocol
|
||||||
|
url = https://github.com/BeamMP/BeamMP-Protocol
|
@ -32,6 +32,7 @@ set(PRJ_HEADERS
|
|||||||
src/Hashing.h
|
src/Hashing.h
|
||||||
src/Compression.h
|
src/Compression.h
|
||||||
src/Config.h
|
src/Config.h
|
||||||
|
src/ServerNetwork.h
|
||||||
)
|
)
|
||||||
# add all source files (.cpp) to this, except the one with main()
|
# add all source files (.cpp) to this, except the one with main()
|
||||||
set(PRJ_SOURCES
|
set(PRJ_SOURCES
|
||||||
@ -45,6 +46,7 @@ set(PRJ_SOURCES
|
|||||||
src/Version.cpp
|
src/Version.cpp
|
||||||
src/Hashing.cpp
|
src/Hashing.cpp
|
||||||
src/Config.cpp
|
src/Config.cpp
|
||||||
|
src/ServerNetwork.cpp
|
||||||
)
|
)
|
||||||
# set the source file containing main()
|
# set the source file containing main()
|
||||||
set(PRJ_MAIN src/main.cpp)
|
set(PRJ_MAIN src/main.cpp)
|
||||||
|
@ -71,9 +71,7 @@ function(set_project_warnings project_name)
|
|||||||
-Werror=write-strings
|
-Werror=write-strings
|
||||||
-Werror=strict-aliasing -fstrict-aliasing
|
-Werror=strict-aliasing -fstrict-aliasing
|
||||||
-Werror=missing-declarations
|
-Werror=missing-declarations
|
||||||
-Werror=missing-field-initializers
|
|
||||||
-Werror=ctor-dtor-privacy
|
-Werror=ctor-dtor-privacy
|
||||||
-Werror=switch-default
|
|
||||||
-Werror=unused-result
|
-Werror=unused-result
|
||||||
-Werror=implicit-fallthrough
|
-Werror=implicit-fallthrough
|
||||||
-Wmissing-include-dirs
|
-Wmissing-include-dirs
|
||||||
|
1
deps/BeamMP-Protocol
vendored
Submodule
1
deps/BeamMP-Protocol
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit ff4a2f5472b997da8947a8b2769a942ccc2d2b20
|
@ -886,3 +886,7 @@ void Launcher::udp_send(const std::string& data) {
|
|||||||
to_send.insert(to_send.end(), vec.begin(), vec.end());
|
to_send.insert(to_send.end(), vec.begin(), vec.end());
|
||||||
m_udp_socket.send_to(buffer(to_send.data(), to_send.size()), m_udp_endpoint);
|
m_udp_socket.send_to(buffer(to_send.data(), to_send.size()), m_udp_endpoint);
|
||||||
}
|
}
|
||||||
|
std::string Launcher::get_public_key() {
|
||||||
|
return m_identity->PublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ public:
|
|||||||
|
|
||||||
void start_network();
|
void start_network();
|
||||||
|
|
||||||
|
std::string get_public_key();
|
||||||
|
|
||||||
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();
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#include "ServerNetwork.h"
|
#include "ServerNetwork.h"
|
||||||
#include "ClientInfo.h"
|
#include "ClientInfo.h"
|
||||||
|
#include "Identity.h"
|
||||||
#include "ImplementationInfo.h"
|
#include "ImplementationInfo.h"
|
||||||
#include "Launcher.h"
|
#include "Launcher.h"
|
||||||
#include "ProtocolVersion.h"
|
#include "ProtocolVersion.h"
|
||||||
#include "ServerInfo.h"
|
#include "ServerInfo.h"
|
||||||
|
#include "Util.h"
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
ServerNetwork::ServerNetwork(Launcher& launcher, const ip::tcp::endpoint& ep)
|
ServerNetwork::ServerNetwork(Launcher& launcher, const ip::tcp::endpoint& ep)
|
||||||
@ -30,6 +33,7 @@ void ServerNetwork::run() {
|
|||||||
.purpose = bmp::Purpose::ProtocolVersion,
|
.purpose = bmp::Purpose::ProtocolVersion,
|
||||||
.raw_data = std::vector<uint8_t>(6),
|
.raw_data = std::vector<uint8_t>(6),
|
||||||
};
|
};
|
||||||
|
spdlog::trace("Protocol version: v{}.{}.{}", 1, 0, 0);
|
||||||
struct bmp::ProtocolVersion version {
|
struct bmp::ProtocolVersion version {
|
||||||
.version = {
|
.version = {
|
||||||
.major = 1,
|
.major = 1,
|
||||||
@ -47,6 +51,14 @@ void ServerNetwork::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerNetwork::handle_packet(const bmp::Packet& packet) {
|
void ServerNetwork::handle_packet(const bmp::Packet& packet) {
|
||||||
|
// handle ping immediately
|
||||||
|
if (m_state > bmp::State::Identification && packet.purpose == bmp::Purpose::Ping) {
|
||||||
|
bmp::Packet pong {
|
||||||
|
.purpose = bmp::Purpose::Ping,
|
||||||
|
};
|
||||||
|
tcp_write(pong);
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (m_state) {
|
switch (m_state) {
|
||||||
case bmp::State::None:
|
case bmp::State::None:
|
||||||
m_state = bmp::State::Identification;
|
m_state = bmp::State::Identification;
|
||||||
@ -55,8 +67,10 @@ void ServerNetwork::handle_packet(const bmp::Packet& packet) {
|
|||||||
handle_identification(packet);
|
handle_identification(packet);
|
||||||
break;
|
break;
|
||||||
case bmp::State::Authentication:
|
case bmp::State::Authentication:
|
||||||
|
handle_authentication(packet);
|
||||||
break;
|
break;
|
||||||
case bmp::State::ModDownload:
|
case bmp::State::ModDownload:
|
||||||
|
handle_mod_download(packet);
|
||||||
break;
|
break;
|
||||||
case bmp::State::SessionSetup:
|
case bmp::State::SessionSetup:
|
||||||
break;
|
break;
|
||||||
@ -67,6 +81,79 @@ void ServerNetwork::handle_packet(const bmp::Packet& packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerNetwork::handle_mod_download(const bmp::Packet& packet) {
|
||||||
|
switch (packet.purpose) {
|
||||||
|
case bmp::Purpose::ModsInfo: {
|
||||||
|
auto data = packet.get_readable_data();
|
||||||
|
auto mods_info = nlohmann::json::parse(data.begin(), data.end());
|
||||||
|
spdlog::info("Got info about {} mod(s)", mods_info.size());
|
||||||
|
for (const auto& mod : mods_info) {
|
||||||
|
spdlog::warn("Mod download not implemented, but data is: {}", mod.dump(4));
|
||||||
|
}
|
||||||
|
// TODO: implement mod download
|
||||||
|
// for now we just pretend we're all good!
|
||||||
|
bmp::Packet ok {
|
||||||
|
.purpose = bmp::Purpose::ModsSyncDone,
|
||||||
|
};
|
||||||
|
spdlog::info("Done syncing mods");
|
||||||
|
tcp_write(ok);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case bmp::Purpose::StateChangeSessionSetup: {
|
||||||
|
spdlog::info("Starting session setup");
|
||||||
|
m_state = bmp::State::SessionSetup;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
spdlog::error("Got 0x{:x} in state {}. This is not allowed. Disconnecting", uint16_t(packet.purpose), int(m_state));
|
||||||
|
// todo: disconnect gracefully
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerNetwork::handle_authentication(const bmp::Packet& packet) {
|
||||||
|
switch (packet.purpose) {
|
||||||
|
case bmp::Purpose::AuthOk: {
|
||||||
|
spdlog::info("Authentication succeeded");
|
||||||
|
uint32_t player_id;
|
||||||
|
bmp::deserialize(player_id, packet.get_readable_data());
|
||||||
|
spdlog::debug("Player id: {}", player_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case bmp::Purpose::AuthFailed: {
|
||||||
|
auto data = packet.get_readable_data();
|
||||||
|
spdlog::error("Authentication failed: {}", std::string(data.begin(), data.end()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case bmp::Purpose::PlayerRejected: {
|
||||||
|
auto data = packet.get_readable_data();
|
||||||
|
spdlog::error("Server rejected me: {}", std::string(data.begin(), data.end()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case bmp::Purpose::StartUDP: {
|
||||||
|
bmp::deserialize(m_udp_magic, packet.get_readable_data());
|
||||||
|
spdlog::debug("UDP start, got magic 0x{:x}", m_udp_magic);
|
||||||
|
m_udp_ep = ip::udp::endpoint(m_tcp_ep.address(), m_tcp_ep.port());
|
||||||
|
m_udp_socket.open(m_tcp_ep.address().is_v4() ? ip::udp::v4() : ip::udp::v6());
|
||||||
|
auto copy = bmp::Packet {
|
||||||
|
.purpose = bmp::Purpose::StartUDP,
|
||||||
|
.raw_data = packet.get_readable_data(),
|
||||||
|
};
|
||||||
|
udp_write(copy);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case bmp::Purpose::StateChangeModDownload: {
|
||||||
|
spdlog::info("Starting mod sync");
|
||||||
|
m_state = bmp::State::ModDownload;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
spdlog::error("Got 0x{:x} in state {}. This is not allowed. Disconnecting", uint16_t(packet.purpose), int(m_state));
|
||||||
|
// todo: disconnect gracefully
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ServerNetwork::handle_identification(const bmp::Packet& packet) {
|
void ServerNetwork::handle_identification(const bmp::Packet& packet) {
|
||||||
switch (packet.purpose) {
|
switch (packet.purpose) {
|
||||||
case bmp::Purpose::ProtocolVersionOk: {
|
case bmp::Purpose::ProtocolVersionOk: {
|
||||||
@ -106,6 +193,13 @@ 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;
|
||||||
|
// TODO: make the launcher provide login properly!
|
||||||
|
auto pubkey = m_launcher.get_public_key();
|
||||||
|
bmp::Packet pubkey_packet {
|
||||||
|
.purpose = bmp::Purpose::PlayerPublicKey,
|
||||||
|
.raw_data = std::vector<uint8_t>(pubkey.begin(), pubkey.end())
|
||||||
|
};
|
||||||
|
tcp_write(pubkey_packet);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -31,6 +31,8 @@ private:
|
|||||||
|
|
||||||
void handle_packet(const bmp::Packet& packet);
|
void handle_packet(const 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_mod_download(const bmp::Packet& packet);
|
||||||
|
|
||||||
io_context m_io {};
|
io_context m_io {};
|
||||||
ip::tcp::socket m_tcp_socket { m_io };
|
ip::tcp::socket m_tcp_socket { m_io };
|
||||||
@ -38,6 +40,8 @@ private:
|
|||||||
|
|
||||||
bmp::State m_state {};
|
bmp::State m_state {};
|
||||||
|
|
||||||
|
uint64_t m_udp_magic {};
|
||||||
|
|
||||||
Launcher& m_launcher;
|
Launcher& m_launcher;
|
||||||
|
|
||||||
ip::tcp::endpoint m_tcp_ep;
|
ip::tcp::endpoint m_tcp_ep;
|
||||||
|
36
src/main.cpp
36
src/main.cpp
@ -1,5 +1,8 @@
|
|||||||
#include "Launcher.h"
|
#include "Launcher.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
#include "ServerNetwork.h"
|
||||||
|
#include <boost/system/detail/errc.hpp>
|
||||||
|
#include <boost/system/detail/error_category.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@ -16,8 +19,10 @@ int main(int argc, char** argv) {
|
|||||||
bool enable_dev = false;
|
bool enable_dev = false;
|
||||||
int custom_port = 0;
|
int custom_port = 0;
|
||||||
std::string_view invalid_arg;
|
std::string_view invalid_arg;
|
||||||
|
std::string all_args = std::string { argv[0] } + " ";
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
std::string_view arg(argv[i]);
|
std::string_view arg(argv[i]);
|
||||||
|
all_args += "'" + std::string(arg) + "' ";
|
||||||
std::string_view next(i + 1 < argc ? argv[i + 1] : "");
|
std::string_view next(i + 1 < argc ? argv[i + 1] : "");
|
||||||
// --debug flag enables debug printing in console
|
// --debug flag enables debug printing in console
|
||||||
if (arg == "--debug") {
|
if (arg == "--debug") {
|
||||||
@ -37,18 +42,30 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
setup_logger(enable_debug || enable_dev);
|
setup_logger(enable_debug || enable_dev);
|
||||||
|
|
||||||
spdlog::debug("Debug enabled");
|
spdlog::trace("BeamMP Launcher invoked as: {}", all_args);
|
||||||
|
|
||||||
|
if (enable_debug) {
|
||||||
|
spdlog::debug("Debug mode enabled");
|
||||||
|
}
|
||||||
|
if (enable_dev) {
|
||||||
|
spdlog::debug("Development mode enabled");
|
||||||
|
}
|
||||||
|
if (custom_port != 0) {
|
||||||
|
spdlog::debug("Custom port set: {}", custom_port);
|
||||||
|
}
|
||||||
|
|
||||||
if (!invalid_arg.empty()) {
|
if (!invalid_arg.empty()) {
|
||||||
spdlog::warn("Invalid argument passed via commandline switches: '{}'. This argument was ignored.", invalid_arg);
|
spdlog::warn("One or more invalid argument(s) passed via commandline switches, last one: '{}'. This argument was ignored.", invalid_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
plat::clear_screen();
|
plat::clear_screen();
|
||||||
plat::set_console_title(fmt::format("BeamMP Launcher v{}.{}.{}", PRJ_VERSION_MAJOR, PRJ_VERSION_MINOR, PRJ_VERSION_PATCH));
|
plat::set_console_title(fmt::format("BeamMP Launcher v{}.{}.{}", PRJ_VERSION_MAJOR, PRJ_VERSION_MINOR, PRJ_VERSION_PATCH));
|
||||||
|
spdlog::trace("BeamMP Launcher v{}.{}.{}", PRJ_VERSION_MAJOR, PRJ_VERSION_MINOR, PRJ_VERSION_PATCH);
|
||||||
|
|
||||||
spdlog::info("BeamMP Launcher v{}.{}.{} is a PRE-RELEASE build. Please report any errors immediately at https://github.com/BeamMP/BeamMP-Launcher.",
|
spdlog::info("BeamMP Launcher v{}.{}.{} is a PRE-RELEASE build. Please report any errors immediately at https://github.com/BeamMP/BeamMP-Launcher.",
|
||||||
PRJ_VERSION_MAJOR, PRJ_VERSION_MINOR, PRJ_VERSION_PATCH);
|
PRJ_VERSION_MAJOR, PRJ_VERSION_MINOR, PRJ_VERSION_PATCH);
|
||||||
|
|
||||||
|
/*
|
||||||
Launcher launcher {};
|
Launcher launcher {};
|
||||||
|
|
||||||
std::filesystem::path arg0(argv[0]);
|
std::filesystem::path arg0(argv[0]);
|
||||||
@ -73,7 +90,19 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
launcher.start_network();
|
launcher.start_network();
|
||||||
|
*/
|
||||||
|
Launcher launcher {};
|
||||||
|
|
||||||
|
std::filesystem::path arg0(argv[0]);
|
||||||
|
launcher.set_exe_name(arg0.filename().generic_string());
|
||||||
|
launcher.set_exe_path(arg0.parent_path());
|
||||||
|
|
||||||
|
try {
|
||||||
|
ServerNetwork sn(launcher, ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), 30814));
|
||||||
|
sn.run();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
spdlog::error("Connection to server closed: {}", e.what());
|
||||||
|
}
|
||||||
spdlog::info("Shutting down.");
|
spdlog::info("Shutting down.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,11 +117,12 @@ void setup_logger(bool debug) {
|
|||||||
|
|
||||||
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("Launcher.log", true);
|
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("Launcher.log", true);
|
||||||
file_sink->set_level(spdlog::level::trace);
|
file_sink->set_level(spdlog::level::trace);
|
||||||
|
file_sink->set_pattern("[%H:%M:%S.%e] [%t] [%L] %v");
|
||||||
|
|
||||||
default_logger = std::make_shared<spdlog::logger>(spdlog::logger("default", { console_sink, file_sink }));
|
default_logger = std::make_shared<spdlog::logger>(spdlog::logger("default", { console_sink, file_sink }));
|
||||||
|
|
||||||
default_logger->set_level(spdlog::level::trace);
|
default_logger->set_level(spdlog::level::trace);
|
||||||
default_logger->flush_on(spdlog::level::info);
|
default_logger->flush_on(spdlog::level::trace);
|
||||||
|
|
||||||
spdlog::set_default_logger(default_logger);
|
spdlog::set_default_logger(default_logger);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user