1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-22 07:13:07 +01:00

Move network units to OpenRCT2::Network namespace

This commit is contained in:
Aaron van Geffen
2025-08-31 15:26:10 +02:00
parent d6e9f3d205
commit 6ea5959b2b
28 changed files with 7396 additions and 7311 deletions

View File

@@ -24,54 +24,51 @@
#include <chrono> #include <chrono>
#include <discord_rpc.h> #include <discord_rpc.h>
using namespace OpenRCT2; namespace OpenRCT2::Network
namespace
{ {
using namespace std::chrono_literals; using namespace std::chrono_literals;
constexpr const char* kApplicationID = "378612438200877056"; constexpr const char* kApplicationID = "378612438200877056";
constexpr const char* kSteamAppID = nullptr; constexpr const char* kSteamAppID = nullptr;
constexpr auto kRefreshInterval = 5.0s; constexpr auto kRefreshInterval = 5.0s;
} // namespace
static void OnReady([[maybe_unused]] const DiscordUser* request) static void OnReady([[maybe_unused]] const DiscordUser* request)
{ {
LOG_VERBOSE("DiscordService::OnReady()"); LOG_VERBOSE("DiscordService::OnReady()");
} }
static void OnDisconnected(int errorCode, const char* message) static void OnDisconnected(int errorCode, const char* message)
{ {
Console::Error::WriteLine("DiscordService::OnDisconnected(%d, %s)", errorCode, message); Console::Error::WriteLine("DiscordService::OnDisconnected(%d, %s)", errorCode, message);
} }
static void OnErrored(int errorCode, const char* message) static void OnErrored(int errorCode, const char* message)
{ {
Console::Error::WriteLine("DiscordService::OnErrored(%d, %s)", errorCode, message); Console::Error::WriteLine("DiscordService::OnErrored(%d, %s)", errorCode, message);
} }
DiscordService::DiscordService() DiscordService::DiscordService()
{ {
DiscordEventHandlers handlers = {}; DiscordEventHandlers handlers = {};
handlers.ready = OnReady; handlers.ready = OnReady;
handlers.disconnected = OnDisconnected; handlers.disconnected = OnDisconnected;
handlers.errored = OnErrored; handlers.errored = OnErrored;
Discord_Initialize(kApplicationID, &handlers, 1, kSteamAppID); Discord_Initialize(kApplicationID, &handlers, 1, kSteamAppID);
} }
DiscordService::~DiscordService() DiscordService::~DiscordService()
{ {
Discord_Shutdown(); Discord_Shutdown();
} }
static std::string GetParkName() static std::string GetParkName()
{ {
auto& gameState = getGameState(); auto& gameState = getGameState();
return gameState.park.name; return gameState.park.name;
} }
void DiscordService::Tick() void DiscordService::Tick()
{ {
Discord_RunCallbacks(); Discord_RunCallbacks();
if (_updateTimer.GetElapsedTime() < kRefreshInterval) if (_updateTimer.GetElapsedTime() < kRefreshInterval)
@@ -79,10 +76,10 @@ void DiscordService::Tick()
RefreshPresence(); RefreshPresence();
_updateTimer.Restart(); _updateTimer.Restart();
} }
void DiscordService::RefreshPresence() const void DiscordService::RefreshPresence() const
{ {
DiscordRichPresence discordPresence = {}; DiscordRichPresence discordPresence = {};
discordPresence.largeImageKey = "logo"; discordPresence.largeImageKey = "logo";
@@ -148,6 +145,7 @@ void DiscordService::RefreshPresence() const
discordPresence.details = details.c_str(); discordPresence.details = details.c_str();
Discord_UpdatePresence(&discordPresence); Discord_UpdatePresence(&discordPresence);
} }
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -15,19 +15,22 @@
#include <limits> #include <limits>
class DiscordService final namespace OpenRCT2::Network
{ {
private: class DiscordService final
{
private:
OpenRCT2::Timer _updateTimer; OpenRCT2::Timer _updateTimer;
public: public:
DiscordService(); DiscordService();
~DiscordService(); ~DiscordService();
void Tick(); void Tick();
private: private:
void RefreshPresence() const; void RefreshPresence() const;
}; };
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -19,12 +19,6 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
constexpr uint16_t kNetworkDefaultPort = 11753;
constexpr uint16_t kNetworkLanBroadcastPort = 11754;
constexpr const char* kNetworkLanBroadcastMsg = "openrct2.server.query";
constexpr const char* kMasterServerURL = "https://servers.openrct2.io";
constexpr uint16_t kMaxServerDescriptionLength = 256;
struct Peep; struct Peep;
struct CoordsXYZ; struct CoordsXYZ;
@@ -36,85 +30,94 @@ namespace OpenRCT2::GameActions
class Result; class Result;
} // namespace OpenRCT2::GameActions } // namespace OpenRCT2::GameActions
enum class NetworkPermission : uint32_t; namespace OpenRCT2::Network
{
constexpr uint16_t kNetworkDefaultPort = 11753;
constexpr uint16_t kNetworkLanBroadcastPort = 11754;
constexpr const char* kNetworkLanBroadcastMsg = "openrct2.server.query";
constexpr const char* kMasterServerURL = "https://servers.openrct2.io";
constexpr uint16_t kMaxServerDescriptionLength = 256;
void NetworkReconnect(); enum class NetworkPermission : uint32_t;
void NetworkShutdownClient();
int32_t NetworkBeginClient(const std::string& host, int32_t port);
int32_t NetworkBeginServer(int32_t port, const std::string& address);
[[nodiscard]] int32_t NetworkGetMode(); void NetworkReconnect();
[[nodiscard]] int32_t NetworkGetStatus(); void NetworkShutdownClient();
bool NetworkIsDesynchronised(); int32_t NetworkBeginClient(const std::string& host, int32_t port);
bool NetworkCheckDesynchronisation(); int32_t NetworkBeginServer(int32_t port, const std::string& address);
void NetworkRequestGamestateSnapshot();
void NetworkSendTick();
bool NetworkGamestateSnapshotsEnabled();
void NetworkUpdate();
void NetworkProcessPending();
void NetworkFlush();
[[nodiscard]] NetworkAuth NetworkGetAuthstatus(); [[nodiscard]] int32_t NetworkGetMode();
[[nodiscard]] uint32_t NetworkGetServerTick(); [[nodiscard]] int32_t NetworkGetStatus();
[[nodiscard]] uint8_t NetworkGetCurrentPlayerId(); bool NetworkIsDesynchronised();
[[nodiscard]] int32_t NetworkGetNumPlayers(); bool NetworkCheckDesynchronisation();
[[nodiscard]] int32_t NetworkGetNumVisiblePlayers(); void NetworkRequestGamestateSnapshot();
[[nodiscard]] const char* NetworkGetPlayerName(uint32_t index); void NetworkSendTick();
[[nodiscard]] uint32_t NetworkGetPlayerFlags(uint32_t index); bool NetworkGamestateSnapshotsEnabled();
[[nodiscard]] int32_t NetworkGetPlayerPing(uint32_t index); void NetworkUpdate();
[[nodiscard]] int32_t NetworkGetPlayerID(uint32_t index); void NetworkProcessPending();
[[nodiscard]] money64 NetworkGetPlayerMoneySpent(uint32_t index); void NetworkFlush();
[[nodiscard]] std::string NetworkGetPlayerIPAddress(uint32_t id);
[[nodiscard]] std::string NetworkGetPlayerPublicKeyHash(uint32_t id); [[nodiscard]] NetworkAuth NetworkGetAuthstatus();
void NetworkIncrementPlayerNumCommands(uint32_t playerIndex); [[nodiscard]] uint32_t NetworkGetServerTick();
void NetworkAddPlayerMoneySpent(uint32_t index, money64 cost); [[nodiscard]] uint8_t NetworkGetCurrentPlayerId();
[[nodiscard]] int32_t NetworkGetPlayerLastAction(uint32_t index, int32_t time); [[nodiscard]] int32_t NetworkGetNumPlayers();
void NetworkSetPlayerLastAction(uint32_t index, GameCommand command); [[nodiscard]] int32_t NetworkGetNumVisiblePlayers();
[[nodiscard]] CoordsXYZ NetworkGetPlayerLastActionCoord(uint32_t index); [[nodiscard]] const char* NetworkGetPlayerName(uint32_t index);
void NetworkSetPlayerLastActionCoord(uint32_t index, const CoordsXYZ& coord); [[nodiscard]] uint32_t NetworkGetPlayerFlags(uint32_t index);
[[nodiscard]] uint32_t NetworkGetPlayerCommandsRan(uint32_t index); [[nodiscard]] int32_t NetworkGetPlayerPing(uint32_t index);
[[nodiscard]] int32_t NetworkGetPlayerIndex(uint32_t id); [[nodiscard]] int32_t NetworkGetPlayerID(uint32_t index);
[[nodiscard]] uint8_t NetworkGetPlayerGroup(uint32_t index); [[nodiscard]] money64 NetworkGetPlayerMoneySpent(uint32_t index);
void NetworkSetPlayerGroup(uint32_t index, uint32_t groupindex); [[nodiscard]] std::string NetworkGetPlayerIPAddress(uint32_t id);
[[nodiscard]] int32_t NetworkGetGroupIndex(uint8_t id); [[nodiscard]] std::string NetworkGetPlayerPublicKeyHash(uint32_t id);
[[nodiscard]] int32_t NetworkGetCurrentPlayerGroupIndex(); void NetworkIncrementPlayerNumCommands(uint32_t playerIndex);
[[nodiscard]] uint8_t NetworkGetGroupID(uint32_t index); void NetworkAddPlayerMoneySpent(uint32_t index, money64 cost);
[[nodiscard]] int32_t NetworkGetNumGroups(); [[nodiscard]] int32_t NetworkGetPlayerLastAction(uint32_t index, int32_t time);
[[nodiscard]] const char* NetworkGetGroupName(uint32_t index); void NetworkSetPlayerLastAction(uint32_t index, GameCommand command);
[[nodiscard]] OpenRCT2::GameActions::Result NetworkSetPlayerGroup( [[nodiscard]] CoordsXYZ NetworkGetPlayerLastActionCoord(uint32_t index);
void NetworkSetPlayerLastActionCoord(uint32_t index, const CoordsXYZ& coord);
[[nodiscard]] uint32_t NetworkGetPlayerCommandsRan(uint32_t index);
[[nodiscard]] int32_t NetworkGetPlayerIndex(uint32_t id);
[[nodiscard]] uint8_t NetworkGetPlayerGroup(uint32_t index);
void NetworkSetPlayerGroup(uint32_t index, uint32_t groupindex);
[[nodiscard]] int32_t NetworkGetGroupIndex(uint8_t id);
[[nodiscard]] int32_t NetworkGetCurrentPlayerGroupIndex();
[[nodiscard]] uint8_t NetworkGetGroupID(uint32_t index);
[[nodiscard]] int32_t NetworkGetNumGroups();
[[nodiscard]] const char* NetworkGetGroupName(uint32_t index);
[[nodiscard]] OpenRCT2::GameActions::Result NetworkSetPlayerGroup(
NetworkPlayerId_t actionPlayerId, NetworkPlayerId_t playerId, uint8_t groupId, bool isExecuting); NetworkPlayerId_t actionPlayerId, NetworkPlayerId_t playerId, uint8_t groupId, bool isExecuting);
[[nodiscard]] OpenRCT2::GameActions::Result NetworkModifyGroups( [[nodiscard]] OpenRCT2::GameActions::Result NetworkModifyGroups(
NetworkPlayerId_t actionPlayerId, OpenRCT2::GameActions::ModifyGroupType type, uint8_t groupId, const std::string& name, NetworkPlayerId_t actionPlayerId, OpenRCT2::GameActions::ModifyGroupType type, uint8_t groupId, const std::string& name,
uint32_t permissionIndex, OpenRCT2::GameActions::PermissionState permissionState, bool isExecuting); uint32_t permissionIndex, OpenRCT2::GameActions::PermissionState permissionState, bool isExecuting);
[[nodiscard]] OpenRCT2::GameActions::Result NetworkKickPlayer(NetworkPlayerId_t playerId, bool isExecuting); [[nodiscard]] OpenRCT2::GameActions::Result NetworkKickPlayer(NetworkPlayerId_t playerId, bool isExecuting);
[[nodiscard]] uint8_t NetworkGetDefaultGroup(); [[nodiscard]] uint8_t NetworkGetDefaultGroup();
[[nodiscard]] int32_t NetworkGetNumActions(); [[nodiscard]] int32_t NetworkGetNumActions();
[[nodiscard]] StringId NetworkGetActionNameStringID(uint32_t index); [[nodiscard]] StringId NetworkGetActionNameStringID(uint32_t index);
[[nodiscard]] int32_t NetworkCanPerformAction(uint32_t groupindex, NetworkPermission index); [[nodiscard]] int32_t NetworkCanPerformAction(uint32_t groupindex, NetworkPermission index);
[[nodiscard]] int32_t NetworkCanPerformCommand(uint32_t groupindex, int32_t index); [[nodiscard]] int32_t NetworkCanPerformCommand(uint32_t groupindex, int32_t index);
void NetworkSetPickupPeep(uint8_t playerid, Peep* peep); void NetworkSetPickupPeep(uint8_t playerid, Peep* peep);
[[nodiscard]] Peep* NetworkGetPickupPeep(uint8_t playerid); [[nodiscard]] Peep* NetworkGetPickupPeep(uint8_t playerid);
void NetworkSetPickupPeepOldX(uint8_t playerid, int32_t x); void NetworkSetPickupPeepOldX(uint8_t playerid, int32_t x);
[[nodiscard]] int32_t NetworkGetPickupPeepOldX(uint8_t playerid); [[nodiscard]] int32_t NetworkGetPickupPeepOldX(uint8_t playerid);
[[nodiscard]] bool NetworkIsServerPlayerInvisible(); [[nodiscard]] bool NetworkIsServerPlayerInvisible();
void NetworkSendChat(const char* text, const std::vector<uint8_t>& playerIds = {}); void NetworkSendChat(const char* text, const std::vector<uint8_t>& playerIds = {});
void NetworkSendGameAction(const OpenRCT2::GameActions::GameAction* action); void NetworkSendGameAction(const OpenRCT2::GameActions::GameAction* action);
void NetworkSendPassword(const std::string& password); void NetworkSendPassword(const std::string& password);
void NetworkSetPassword(const char* password); void NetworkSetPassword(const char* password);
void NetworkAppendChatLog(std::string_view text); void NetworkAppendChatLog(std::string_view text);
void NetworkAppendServerLog(const utf8* text); void NetworkAppendServerLog(const utf8* text);
[[nodiscard]] u8string NetworkGetServerName(); [[nodiscard]] u8string NetworkGetServerName();
[[nodiscard]] u8string NetworkGetServerDescription(); [[nodiscard]] u8string NetworkGetServerDescription();
[[nodiscard]] u8string NetworkGetServerGreeting(); [[nodiscard]] u8string NetworkGetServerGreeting();
[[nodiscard]] u8string NetworkGetServerProviderName(); [[nodiscard]] u8string NetworkGetServerProviderName();
[[nodiscard]] u8string NetworkGetServerProviderEmail(); [[nodiscard]] u8string NetworkGetServerProviderEmail();
[[nodiscard]] u8string NetworkGetServerProviderWebsite(); [[nodiscard]] u8string NetworkGetServerProviderWebsite();
[[nodiscard]] std::string NetworkGetVersion(); [[nodiscard]] std::string NetworkGetVersion();
[[nodiscard]] NetworkStats NetworkGetStats(); [[nodiscard]] NetworkStats NetworkGetStats();
[[nodiscard]] NetworkServerState NetworkGetServerState(); [[nodiscard]] NetworkServerState NetworkGetServerState();
[[nodiscard]] json_t NetworkGetServerInfoAsJson(); [[nodiscard]] json_t NetworkGetServerInfoAsJson();
} // namespace OpenRCT2::Network

View File

@@ -16,8 +16,10 @@
#include <algorithm> #include <algorithm>
NetworkPermission NetworkActions::FindCommand(GameCommand command) namespace OpenRCT2::Network
{ {
NetworkPermission NetworkActions::FindCommand(GameCommand command)
{
auto it = std::find_if(Actions.begin(), Actions.end(), [&command](NetworkAction const& action) { auto it = std::find_if(Actions.begin(), Actions.end(), [&command](NetworkAction const& action) {
for (GameCommand currentCommand : action.Commands) for (GameCommand currentCommand : action.Commands)
{ {
@@ -33,10 +35,10 @@ NetworkPermission NetworkActions::FindCommand(GameCommand command)
return static_cast<NetworkPermission>(it - Actions.begin()); return static_cast<NetworkPermission>(it - Actions.begin());
} }
return NetworkPermission::Count; return NetworkPermission::Count;
} }
NetworkPermission NetworkActions::FindCommandByPermissionName(const std::string& permission_name) NetworkPermission NetworkActions::FindCommandByPermissionName(const std::string& permission_name)
{ {
auto it = std::find_if(Actions.begin(), Actions.end(), [&permission_name](NetworkAction const& action) { auto it = std::find_if(Actions.begin(), Actions.end(), [&permission_name](NetworkAction const& action) {
return action.PermissionName == permission_name; return action.PermissionName == permission_name;
}); });
@@ -45,9 +47,9 @@ NetworkPermission NetworkActions::FindCommandByPermissionName(const std::string&
return static_cast<NetworkPermission>(it - Actions.begin()); return static_cast<NetworkPermission>(it - Actions.begin());
} }
return NetworkPermission::Count; return NetworkPermission::Count;
} }
const std::array<NetworkAction, static_cast<size_t>(NetworkPermission::Count)> NetworkActions::Actions = { const std::array<NetworkAction, static_cast<size_t>(NetworkPermission::Count)> NetworkActions::Actions = {
NetworkAction{ NetworkAction{
STR_ACTION_CHAT, STR_ACTION_CHAT,
"PERMISSION_CHAT", "PERMISSION_CHAT",
@@ -264,6 +266,7 @@ const std::array<NetworkAction, static_cast<size_t>(NetworkPermission::Count)> N
GameCommand::EditScenarioOptions, GameCommand::EditScenarioOptions,
}, },
}, },
}; };
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -16,8 +16,10 @@
#include <string> #include <string>
#include <vector> #include <vector>
enum class NetworkPermission : uint32_t namespace OpenRCT2::Network
{ {
enum class NetworkPermission : uint32_t
{
Chat, Chat,
Terraform, Terraform,
SetWaterLevel, SetWaterLevel,
@@ -43,21 +45,22 @@ enum class NetworkPermission : uint32_t
EditScenarioOptions, EditScenarioOptions,
Count Count
}; };
class NetworkAction final class NetworkAction final
{ {
public: public:
StringId Name; StringId Name;
std::string PermissionName; std::string PermissionName;
std::vector<GameCommand> Commands; std::vector<GameCommand> Commands;
}; };
class NetworkActions final class NetworkActions final
{ {
public: public:
static const std::array<NetworkAction, static_cast<size_t>(NetworkPermission::Count)> Actions; static const std::array<NetworkAction, static_cast<size_t>(NetworkPermission::Count)> Actions;
static NetworkPermission FindCommand(GameCommand command); static NetworkPermission FindCommand(GameCommand command);
static NetworkPermission FindCommandByPermissionName(const std::string& permission_name); static NetworkPermission FindCommandByPermissionName(const std::string& permission_name);
}; };
} // namespace OpenRCT2::Network

File diff suppressed because it is too large Load Diff

View File

@@ -22,16 +22,18 @@ namespace OpenRCT2
struct IContext; struct IContext;
} }
class NetworkBase : public OpenRCT2::System namespace OpenRCT2::Network
{ {
public: class NetworkBase : public OpenRCT2::System
{
public:
NetworkBase(OpenRCT2::IContext& context); NetworkBase(OpenRCT2::IContext& context);
public: // Uncategorized public: // Uncategorized
bool BeginServer(uint16_t port, const std::string& address); bool BeginServer(uint16_t port, const std::string& address);
bool BeginClient(const std::string& host, uint16_t port); bool BeginClient(const std::string& host, uint16_t port);
public: // Common public: // Common
bool Init(); bool Init();
void Close(); void Close();
uint32_t GetServerTick() const noexcept; uint32_t GetServerTick() const noexcept;
@@ -60,7 +62,7 @@ public: // Common
NetworkPlayer* AddPlayer(const std::string& name, const std::string& keyhash); NetworkPlayer* AddPlayer(const std::string& name, const std::string& keyhash);
void ProcessPacket(NetworkConnection& connection, NetworkPacket& packet); void ProcessPacket(NetworkConnection& connection, NetworkPacket& packet);
public: // Server public: // Server
NetworkConnection* GetPlayerConnection(uint8_t id) const; NetworkConnection* GetPlayerConnection(uint8_t id) const;
void KickPlayer(int32_t playerId); void KickPlayer(int32_t playerId);
NetworkGroup* AddGroup(); NetworkGroup* AddGroup();
@@ -117,7 +119,7 @@ public: // Server
void ServerHandleToken(NetworkConnection& connection, NetworkPacket& packet); void ServerHandleToken(NetworkConnection& connection, NetworkPacket& packet);
void ServerHandleMapRequest(NetworkConnection& connection, NetworkPacket& packet); void ServerHandleMapRequest(NetworkConnection& connection, NetworkPacket& packet);
public: // Client public: // Client
void Reconnect(); void Reconnect();
int32_t GetMode() const noexcept; int32_t GetMode() const noexcept;
NetworkAuth GetAuthStatus(); NetworkAuth GetAuthStatus();
@@ -140,7 +142,8 @@ public: // Client
void Client_Send_RequestGameState(uint32_t tick); void Client_Send_RequestGameState(uint32_t tick);
void Client_Send_TOKEN(); void Client_Send_TOKEN();
void Client_Send_AUTH( void Client_Send_AUTH(
const std::string& name, const std::string& password, const std::string& pubkey, const std::vector<uint8_t>& signature); const std::string& name, const std::string& password, const std::string& pubkey,
const std::vector<uint8_t>& signature);
void Client_Send_CHAT(const char* text); void Client_Send_CHAT(const char* text);
void Client_Send_GAME_ACTION(const OpenRCT2::GameActions::GameAction* action); void Client_Send_GAME_ACTION(const OpenRCT2::GameActions::GameAction* action);
void Client_Send_PING(); void Client_Send_PING();
@@ -174,7 +177,7 @@ public: // Client
NetworkKey _key; NetworkKey _key;
NetworkUserManager _userManager; NetworkUserManager _userManager;
public: // Public common public: // Public common
std::string ServerName; std::string ServerName;
std::string ServerDescription; std::string ServerDescription;
std::string ServerGreeting; std::string ServerGreeting;
@@ -185,7 +188,7 @@ public: // Public common
std::vector<std::unique_ptr<NetworkGroup>> group_list; std::vector<std::unique_ptr<NetworkGroup>> group_list;
bool IsServerPlayerInvisible = false; bool IsServerPlayerInvisible = false;
private: // Common Data private: // Common Data
using CommandHandler = void (NetworkBase::*)(NetworkConnection& connection, NetworkPacket& packet); using CommandHandler = void (NetworkBase::*)(NetworkConnection& connection, NetworkPacket& packet);
std::vector<uint8_t> chunk_buffer; std::vector<uint8_t> chunk_buffer;
@@ -197,7 +200,7 @@ private: // Common Data
bool _closeLock = false; bool _closeLock = false;
bool _requireClose = false; bool _requireClose = false;
private: // Server Data private: // Server Data
std::unordered_map<NetworkCommand, CommandHandler> server_command_handlers; std::unordered_map<NetworkCommand, CommandHandler> server_command_handlers;
std::unique_ptr<ITcpSocket> _listenSocket; std::unique_ptr<ITcpSocket> _listenSocket;
std::unique_ptr<INetworkServerAdvertiser> _advertiser; std::unique_ptr<INetworkServerAdvertiser> _advertiser;
@@ -208,7 +211,7 @@ private: // Server Data
uint16_t listening_port = 0; uint16_t listening_port = 0;
bool _playerListInvalidated = false; bool _playerListInvalidated = false;
private: // Client Data private: // Client Data
struct PlayerListUpdate struct PlayerListUpdate
{ {
std::vector<NetworkPlayer> players; std::vector<NetworkPlayer> players;
@@ -251,6 +254,7 @@ private: // Client Data
bool _requireReconnect = false; bool _requireReconnect = false;
bool _clientMapLoaded = false; bool _clientMapLoaded = false;
ServerScriptsData _serverScriptsData{}; ServerScriptsData _serverScriptsData{};
}; };
} // namespace OpenRCT2::Network
#endif // DISABLE_NETWORK #endif // DISABLE_NETWORK

View File

@@ -4,9 +4,12 @@
#ifndef DISABLE_NETWORK #ifndef DISABLE_NETWORK
class NetworkClient final : public NetworkBase namespace OpenRCT2::Network
{ {
public: class NetworkClient final : public NetworkBase
}; {
public:
};
} // namespace OpenRCT2::Network
#endif // DISABLE_NETWORK #endif // DISABLE_NETWORK

View File

@@ -19,23 +19,23 @@
#include <sfl/small_vector.hpp> #include <sfl/small_vector.hpp>
using namespace OpenRCT2; namespace OpenRCT2::Network
{
static constexpr size_t kNetworkDisconnectReasonBufSize = 256; static constexpr size_t kNetworkDisconnectReasonBufSize = 256;
static constexpr size_t kNetworkBufferSize = (1024 * 64) - 1; // 64 KiB, maximum packet size. static constexpr size_t kNetworkBufferSize = (1024 * 64) - 1; // 64 KiB, maximum packet size.
#ifndef DEBUG #ifndef DEBUG
static constexpr size_t kNetworkNoDataTimeout = 20; // Seconds. static constexpr size_t kNetworkNoDataTimeout = 20; // Seconds.
#endif #endif
static_assert(kNetworkBufferSize <= std::numeric_limits<uint16_t>::max(), "kNetworkBufferSize too big, uint16_t is max."); static_assert(kNetworkBufferSize <= std::numeric_limits<uint16_t>::max(), "kNetworkBufferSize too big, uint16_t is max.");
NetworkConnection::NetworkConnection() noexcept NetworkConnection::NetworkConnection() noexcept
{ {
ResetLastPacketTime(); ResetLastPacketTime();
} }
NetworkReadPacket NetworkConnection::ReadPacket() NetworkReadPacket NetworkConnection::ReadPacket()
{ {
size_t bytesRead = 0; size_t bytesRead = 0;
// Read packet header. // Read packet header.
@@ -101,10 +101,10 @@ NetworkReadPacket NetworkConnection::ReadPacket()
} }
return NetworkReadPacket::MoreData; return NetworkReadPacket::MoreData;
} }
static sfl::small_vector<uint8_t, 512> serializePacket(const NetworkPacket& packet) static sfl::small_vector<uint8_t, 512> serializePacket(const NetworkPacket& packet)
{ {
// NOTE: For compatibility reasons for the master server we need to add sizeof(Header.Id) to the size. // NOTE: For compatibility reasons for the master server we need to add sizeof(Header.Id) to the size.
// Previously the Id field was not part of the header rather part of the body. // Previously the Id field was not part of the header rather part of the body.
const auto bodyLength = packet.Data.size() + sizeof(packet.Header.Id); const auto bodyLength = packet.Data.size() + sizeof(packet.Header.Id);
@@ -123,10 +123,10 @@ static sfl::small_vector<uint8_t, 512> serializePacket(const NetworkPacket& pack
buffer.insert(buffer.end(), packet.Data.begin(), packet.Data.end()); buffer.insert(buffer.end(), packet.Data.begin(), packet.Data.end());
return buffer; return buffer;
} }
void NetworkConnection::QueuePacket(const NetworkPacket& packet, bool front) void NetworkConnection::QueuePacket(const NetworkPacket& packet, bool front)
{ {
if (AuthStatus == NetworkAuth::Ok || !packet.CommandRequiresAuth()) if (AuthStatus == NetworkAuth::Ok || !packet.CommandRequiresAuth())
{ {
const auto payload = serializePacket(packet); const auto payload = serializePacket(packet);
@@ -141,20 +141,20 @@ void NetworkConnection::QueuePacket(const NetworkPacket& packet, bool front)
RecordPacketStats(packet, true); RecordPacketStats(packet, true);
} }
} }
void NetworkConnection::Disconnect() noexcept void NetworkConnection::Disconnect() noexcept
{ {
ShouldDisconnect = true; ShouldDisconnect = true;
} }
bool NetworkConnection::IsValid() const bool NetworkConnection::IsValid() const
{ {
return !ShouldDisconnect && Socket->GetStatus() == SocketStatus::Connected; return !ShouldDisconnect && Socket->GetStatus() == SocketStatus::Connected;
} }
void NetworkConnection::SendQueuedData() void NetworkConnection::SendQueuedData()
{ {
if (_outboundBuffer.empty()) if (_outboundBuffer.empty())
{ {
return; return;
@@ -166,15 +166,15 @@ void NetworkConnection::SendQueuedData()
{ {
_outboundBuffer.erase(_outboundBuffer.begin(), _outboundBuffer.begin() + bytesSent); _outboundBuffer.erase(_outboundBuffer.begin(), _outboundBuffer.begin() + bytesSent);
} }
} }
void NetworkConnection::ResetLastPacketTime() noexcept void NetworkConnection::ResetLastPacketTime() noexcept
{ {
_lastPacketTime = Platform::GetTicks(); _lastPacketTime = Platform::GetTicks();
} }
bool NetworkConnection::ReceivedPacketRecently() const noexcept bool NetworkConnection::ReceivedPacketRecently() const noexcept
{ {
#ifndef DEBUG #ifndef DEBUG
constexpr auto kTimeoutMs = kNetworkNoDataTimeout * 1000; constexpr auto kTimeoutMs = kNetworkNoDataTimeout * 1000;
if (Platform::GetTicks() > _lastPacketTime + kTimeoutMs) if (Platform::GetTicks() > _lastPacketTime + kTimeoutMs)
@@ -183,27 +183,27 @@ bool NetworkConnection::ReceivedPacketRecently() const noexcept
} }
#endif #endif
return true; return true;
} }
const utf8* NetworkConnection::GetLastDisconnectReason() const noexcept const utf8* NetworkConnection::GetLastDisconnectReason() const noexcept
{ {
return this->_lastDisconnectReason.c_str(); return this->_lastDisconnectReason.c_str();
} }
void NetworkConnection::SetLastDisconnectReason(std::string_view src) void NetworkConnection::SetLastDisconnectReason(std::string_view src)
{ {
_lastDisconnectReason = src; _lastDisconnectReason = src;
} }
void NetworkConnection::SetLastDisconnectReason(const StringId string_id, void* args) void NetworkConnection::SetLastDisconnectReason(const StringId string_id, void* args)
{ {
char buffer[kNetworkDisconnectReasonBufSize]; char buffer[kNetworkDisconnectReasonBufSize];
OpenRCT2::FormatStringLegacy(buffer, kNetworkDisconnectReasonBufSize, string_id, args); OpenRCT2::FormatStringLegacy(buffer, kNetworkDisconnectReasonBufSize, string_id, args);
SetLastDisconnectReason(buffer); SetLastDisconnectReason(buffer);
} }
void NetworkConnection::RecordPacketStats(const NetworkPacket& packet, bool sending) void NetworkConnection::RecordPacketStats(const NetworkPacket& packet, bool sending)
{ {
uint32_t packetSize = static_cast<uint32_t>(packet.BytesTransferred); uint32_t packetSize = static_cast<uint32_t>(packet.BytesTransferred);
NetworkStatisticsGroup trafficGroup; NetworkStatisticsGroup trafficGroup;
@@ -230,6 +230,7 @@ void NetworkConnection::RecordPacketStats(const NetworkPacket& packet, bool send
Stats.bytesReceived[EnumValue(trafficGroup)] += packetSize; Stats.bytesReceived[EnumValue(trafficGroup)] += packetSize;
Stats.bytesReceived[EnumValue(NetworkStatisticsGroup::Total)] += packetSize; Stats.bytesReceived[EnumValue(NetworkStatisticsGroup::Total)] += packetSize;
} }
} }
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -20,16 +20,18 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
class NetworkPlayer;
namespace OpenRCT2 namespace OpenRCT2
{ {
struct ObjectRepositoryItem; struct ObjectRepositoryItem;
} }
class NetworkConnection final namespace OpenRCT2::Network
{ {
public: class NetworkPlayer;
class NetworkConnection final
{
public:
std::unique_ptr<ITcpSocket> Socket = nullptr; std::unique_ptr<ITcpSocket> Socket = nullptr;
NetworkPacket InboundPacket; NetworkPacket InboundPacket;
NetworkAuth AuthStatus = NetworkAuth::None; NetworkAuth AuthStatus = NetworkAuth::None;
@@ -59,12 +61,13 @@ public:
void SetLastDisconnectReason(std::string_view src); void SetLastDisconnectReason(std::string_view src);
void SetLastDisconnectReason(const StringId string_id, void* args = nullptr); void SetLastDisconnectReason(const StringId string_id, void* args = nullptr);
private: private:
std::vector<uint8_t> _outboundBuffer; std::vector<uint8_t> _outboundBuffer;
uint32_t _lastPacketTime = 0; uint32_t _lastPacketTime = 0;
std::string _lastDisconnectReason; std::string _lastDisconnectReason;
void RecordPacketStats(const NetworkPacket& packet, bool sending); void RecordPacketStats(const NetworkPacket& packet, bool sending);
}; };
} // namespace OpenRCT2::Network
#endif // DISABLE_NETWORK #endif // DISABLE_NETWORK

View File

@@ -15,10 +15,10 @@
#include "NetworkAction.h" #include "NetworkAction.h"
#include "NetworkTypes.h" #include "NetworkTypes.h"
using namespace OpenRCT2; namespace OpenRCT2::Network
NetworkGroup NetworkGroup::FromJson(const json_t& jsonData)
{ {
NetworkGroup NetworkGroup::FromJson(const json_t& jsonData)
{
Guard::Assert(jsonData.is_object(), "NetworkGroup::FromJson expects parameter jsonData to be object"); Guard::Assert(jsonData.is_object(), "NetworkGroup::FromJson expects parameter jsonData to be object");
NetworkGroup group; NetworkGroup group;
@@ -46,10 +46,10 @@ NetworkGroup NetworkGroup::FromJson(const json_t& jsonData)
} }
} }
return group; return group;
} }
json_t NetworkGroup::ToJson() const json_t NetworkGroup::ToJson() const
{ {
json_t jsonGroup = { json_t jsonGroup = {
{ "id", Id }, { "id", Id },
{ "name", GetName() }, { "name", GetName() },
@@ -64,40 +64,40 @@ json_t NetworkGroup::ToJson() const
} }
jsonGroup["permissions"] = actionsArray; jsonGroup["permissions"] = actionsArray;
return jsonGroup; return jsonGroup;
} }
const std::string& NetworkGroup::GetName() const noexcept const std::string& NetworkGroup::GetName() const noexcept
{ {
return _name; return _name;
} }
void NetworkGroup::SetName(std::string_view name) void NetworkGroup::SetName(std::string_view name)
{ {
_name = name; _name = name;
} }
void NetworkGroup::Read(NetworkPacket& packet) void NetworkGroup::Read(NetworkPacket& packet)
{ {
packet >> Id; packet >> Id;
SetName(packet.ReadString()); SetName(packet.ReadString());
for (auto& action : ActionsAllowed) for (auto& action : ActionsAllowed)
{ {
packet >> action; packet >> action;
} }
} }
void NetworkGroup::Write(NetworkPacket& packet) const void NetworkGroup::Write(NetworkPacket& packet) const
{ {
packet << Id; packet << Id;
packet.WriteString(GetName().c_str()); packet.WriteString(GetName().c_str());
for (const auto& action : ActionsAllowed) for (const auto& action : ActionsAllowed)
{ {
packet << action; packet << action;
} }
} }
void NetworkGroup::ToggleActionPermission(NetworkPermission index) void NetworkGroup::ToggleActionPermission(NetworkPermission index)
{ {
size_t index_st = static_cast<size_t>(index); size_t index_st = static_cast<size_t>(index);
size_t byte = index_st / 8; size_t byte = index_st / 8;
size_t bit = index_st % 8; size_t bit = index_st % 8;
@@ -106,10 +106,10 @@ void NetworkGroup::ToggleActionPermission(NetworkPermission index)
return; return;
} }
ActionsAllowed[byte] ^= (1 << bit); ActionsAllowed[byte] ^= (1 << bit);
} }
bool NetworkGroup::CanPerformAction(NetworkPermission index) const noexcept bool NetworkGroup::CanPerformAction(NetworkPermission index) const noexcept
{ {
size_t index_st = static_cast<size_t>(index); size_t index_st = static_cast<size_t>(index);
size_t byte = index_st / 8; size_t byte = index_st / 8;
size_t bit = index_st % 8; size_t bit = index_st % 8;
@@ -118,16 +118,17 @@ bool NetworkGroup::CanPerformAction(NetworkPermission index) const noexcept
return false; return false;
} }
return (ActionsAllowed[byte] & (1 << bit)) != 0; return (ActionsAllowed[byte] & (1 << bit)) != 0;
} }
bool NetworkGroup::CanPerformCommand(GameCommand command) const bool NetworkGroup::CanPerformCommand(GameCommand command) const
{ {
NetworkPermission action = NetworkActions::FindCommand(command); NetworkPermission action = NetworkActions::FindCommand(command);
if (action != NetworkPermission::Count) if (action != NetworkPermission::Count)
{ {
return CanPerformAction(action); return CanPerformAction(action);
} }
return false; return false;
} }
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -16,11 +16,13 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
enum class NetworkPermission : uint32_t; namespace OpenRCT2::Network
class NetworkGroup final
{ {
public: enum class NetworkPermission : uint32_t;
class NetworkGroup final
{
public:
std::array<uint8_t, 8> ActionsAllowed{}; std::array<uint8_t, 8> ActionsAllowed{};
uint8_t Id = 0; uint8_t Id = 0;
@@ -49,6 +51,7 @@ public:
*/ */
json_t ToJson() const; json_t ToJson() const;
private: private:
std::string _name; std::string _name;
}; };
} // namespace OpenRCT2::Network

View File

@@ -19,18 +19,18 @@
#include <vector> #include <vector>
using namespace OpenRCT2; namespace OpenRCT2::Network
NetworkKey::NetworkKey() = default;
NetworkKey::~NetworkKey() = default;
void NetworkKey::Unload()
{ {
NetworkKey::NetworkKey() = default;
NetworkKey::~NetworkKey() = default;
void NetworkKey::Unload()
{
_key = nullptr; _key = nullptr;
} }
bool NetworkKey::Generate() bool NetworkKey::Generate()
{ {
try try
{ {
_key = Crypt::CreateRSAKey(); _key = Crypt::CreateRSAKey();
@@ -42,10 +42,10 @@ bool NetworkKey::Generate()
LOG_ERROR("NetworkKey::Generate failed: %s", e.what()); LOG_ERROR("NetworkKey::Generate failed: %s", e.what());
return false; return false;
} }
} }
bool NetworkKey::LoadPrivate(OpenRCT2::IStream* stream) bool NetworkKey::LoadPrivate(OpenRCT2::IStream* stream)
{ {
Guard::ArgumentNotNull(stream); Guard::ArgumentNotNull(stream);
size_t size = static_cast<size_t>(stream->GetLength()); size_t size = static_cast<size_t>(stream->GetLength());
@@ -74,10 +74,10 @@ bool NetworkKey::LoadPrivate(OpenRCT2::IStream* stream)
LOG_ERROR("NetworkKey::LoadPrivate failed: %s", e.what()); LOG_ERROR("NetworkKey::LoadPrivate failed: %s", e.what());
return false; return false;
} }
} }
bool NetworkKey::LoadPublic(OpenRCT2::IStream* stream) bool NetworkKey::LoadPublic(OpenRCT2::IStream* stream)
{ {
Guard::ArgumentNotNull(stream); Guard::ArgumentNotNull(stream);
size_t size = static_cast<size_t>(stream->GetLength()); size_t size = static_cast<size_t>(stream->GetLength());
@@ -106,10 +106,10 @@ bool NetworkKey::LoadPublic(OpenRCT2::IStream* stream)
LOG_ERROR("NetworkKey::LoadPublic failed: %s", e.what()); LOG_ERROR("NetworkKey::LoadPublic failed: %s", e.what());
return false; return false;
} }
} }
bool NetworkKey::SavePrivate(OpenRCT2::IStream* stream) bool NetworkKey::SavePrivate(OpenRCT2::IStream* stream)
{ {
try try
{ {
if (_key == nullptr) if (_key == nullptr)
@@ -125,10 +125,10 @@ bool NetworkKey::SavePrivate(OpenRCT2::IStream* stream)
LOG_ERROR("NetworkKey::SavePrivate failed: %s", e.what()); LOG_ERROR("NetworkKey::SavePrivate failed: %s", e.what());
return false; return false;
} }
} }
bool NetworkKey::SavePublic(OpenRCT2::IStream* stream) bool NetworkKey::SavePublic(OpenRCT2::IStream* stream)
{ {
try try
{ {
if (_key == nullptr) if (_key == nullptr)
@@ -144,18 +144,18 @@ bool NetworkKey::SavePublic(OpenRCT2::IStream* stream)
LOG_ERROR("NetworkKey::SavePublic failed: %s", e.what()); LOG_ERROR("NetworkKey::SavePublic failed: %s", e.what());
return false; return false;
} }
} }
std::string NetworkKey::PublicKeyString() std::string NetworkKey::PublicKeyString()
{ {
if (_key == nullptr) if (_key == nullptr)
{ {
throw std::runtime_error("No key loaded"); throw std::runtime_error("No key loaded");
} }
return _key->GetPublic(); return _key->GetPublic();
} }
/** /**
* @brief NetworkKey::PublicKeyHash * @brief NetworkKey::PublicKeyHash
* Computes a short, human-readable (e.g. asciif-ied hex) hash for a given * Computes a short, human-readable (e.g. asciif-ied hex) hash for a given
* public key. Serves a purpose of easy identification keys in multiplayer * public key. Serves a purpose of easy identification keys in multiplayer
@@ -166,8 +166,8 @@ std::string NetworkKey::PublicKeyString()
* *
* @return returns a string containing key hash. * @return returns a string containing key hash.
*/ */
std::string NetworkKey::PublicKeyHash() std::string NetworkKey::PublicKeyHash()
{ {
try try
{ {
std::string key = PublicKeyString(); std::string key = PublicKeyString();
@@ -183,10 +183,10 @@ std::string NetworkKey::PublicKeyHash()
LOG_ERROR("Failed to create hash of public key: %s", e.what()); LOG_ERROR("Failed to create hash of public key: %s", e.what());
} }
return nullptr; return nullptr;
} }
bool NetworkKey::Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>& signature) const bool NetworkKey::Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>& signature) const
{ {
try try
{ {
auto rsa = Crypt::CreateRSA(); auto rsa = Crypt::CreateRSA();
@@ -198,10 +198,10 @@ bool NetworkKey::Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>&
LOG_ERROR("NetworkKey::Sign failed: %s", e.what()); LOG_ERROR("NetworkKey::Sign failed: %s", e.what());
return false; return false;
} }
} }
bool NetworkKey::Verify(const uint8_t* md, const size_t len, const std::vector<uint8_t>& signature) const bool NetworkKey::Verify(const uint8_t* md, const size_t len, const std::vector<uint8_t>& signature) const
{ {
try try
{ {
auto rsa = Crypt::CreateRSA(); auto rsa = Crypt::CreateRSA();
@@ -212,6 +212,7 @@ bool NetworkKey::Verify(const uint8_t* md, const size_t len, const std::vector<u
LOG_ERROR("NetworkKey::Verify failed: %s", e.what()); LOG_ERROR("NetworkKey::Verify failed: %s", e.what());
return false; return false;
} }
} }
} // namespace OpenRCT2::Network
#endif // DISABLE_NETWORK #endif // DISABLE_NETWORK

View File

@@ -25,9 +25,11 @@ namespace OpenRCT2::Crypt
class RsaKey; class RsaKey;
} }
class NetworkKey final namespace OpenRCT2::Network
{ {
public: class NetworkKey final
{
public:
NetworkKey(); NetworkKey();
~NetworkKey(); ~NetworkKey();
bool Generate(); bool Generate();
@@ -41,9 +43,10 @@ public:
bool Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>& signature) const; bool Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>& signature) const;
bool Verify(const uint8_t* md, const size_t len, const std::vector<uint8_t>& signature) const; bool Verify(const uint8_t* md, const size_t len, const std::vector<uint8_t>& signature) const;
private: private:
NetworkKey(const NetworkKey&) = delete; NetworkKey(const NetworkKey&) = delete;
std::unique_ptr<OpenRCT2::Crypt::RsaKey> _key; std::unique_ptr<OpenRCT2::Crypt::RsaKey> _key;
}; };
} // namespace OpenRCT2::Network
#endif // DISABLE_NETWORK #endif // DISABLE_NETWORK

View File

@@ -15,35 +15,37 @@
#include <memory> #include <memory>
NetworkPacket::NetworkPacket(NetworkCommand id) noexcept namespace OpenRCT2::Network
{
NetworkPacket::NetworkPacket(NetworkCommand id) noexcept
: Header{ 0, id } : Header{ 0, id }
{ {
} }
uint8_t* NetworkPacket::GetData() noexcept uint8_t* NetworkPacket::GetData() noexcept
{ {
return Data.data(); return Data.data();
} }
const uint8_t* NetworkPacket::GetData() const noexcept const uint8_t* NetworkPacket::GetData() const noexcept
{ {
return Data.data(); return Data.data();
} }
NetworkCommand NetworkPacket::GetCommand() const noexcept NetworkCommand NetworkPacket::GetCommand() const noexcept
{ {
return Header.Id; return Header.Id;
} }
void NetworkPacket::Clear() noexcept void NetworkPacket::Clear() noexcept
{ {
BytesTransferred = 0; BytesTransferred = 0;
BytesRead = 0; BytesRead = 0;
Data.clear(); Data.clear();
} }
bool NetworkPacket::CommandRequiresAuth() const noexcept bool NetworkPacket::CommandRequiresAuth() const noexcept
{ {
switch (GetCommand()) switch (GetCommand())
{ {
case NetworkCommand::Ping: case NetworkCommand::Ping:
@@ -59,22 +61,22 @@ bool NetworkPacket::CommandRequiresAuth() const noexcept
default: default:
return true; return true;
} }
} }
void NetworkPacket::Write(const void* bytes, size_t size) void NetworkPacket::Write(const void* bytes, size_t size)
{ {
const uint8_t* src = reinterpret_cast<const uint8_t*>(bytes); const uint8_t* src = reinterpret_cast<const uint8_t*>(bytes);
Data.insert(Data.end(), src, src + size); Data.insert(Data.end(), src, src + size);
} }
void NetworkPacket::WriteString(std::string_view s) void NetworkPacket::WriteString(std::string_view s)
{ {
Write(s.data(), s.size()); Write(s.data(), s.size());
Data.push_back(0); Data.push_back(0);
} }
const uint8_t* NetworkPacket::Read(size_t size) const uint8_t* NetworkPacket::Read(size_t size)
{ {
if (BytesRead + size > Data.size()) if (BytesRead + size > Data.size())
{ {
return nullptr; return nullptr;
@@ -83,10 +85,10 @@ const uint8_t* NetworkPacket::Read(size_t size)
const uint8_t* data = Data.data() + BytesRead; const uint8_t* data = Data.data() + BytesRead;
BytesRead += size; BytesRead += size;
return data; return data;
} }
std::string_view NetworkPacket::ReadString() std::string_view NetworkPacket::ReadString()
{ {
if (BytesRead >= Data.size()) if (BytesRead >= Data.size())
return {}; return {};
@@ -106,6 +108,7 @@ std::string_view NetworkPacket::ReadString()
BytesRead++; BytesRead++;
return std::string_view(str, stringLen); return std::string_view(str, stringLen);
} }
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -16,17 +16,19 @@
#include <sfl/small_vector.hpp> #include <sfl/small_vector.hpp>
#include <vector> #include <vector>
#pragma pack(push, 1) namespace OpenRCT2::Network
struct PacketHeader
{ {
#pragma pack(push, 1)
struct PacketHeader
{
uint16_t Size = 0; uint16_t Size = 0;
NetworkCommand Id = NetworkCommand::Invalid; NetworkCommand Id = NetworkCommand::Invalid;
}; };
static_assert(sizeof(PacketHeader) == 6); static_assert(sizeof(PacketHeader) == 6);
#pragma pack(pop) #pragma pack(pop)
struct NetworkPacket final struct NetworkPacket final
{ {
NetworkPacket() noexcept = default; NetworkPacket() noexcept = default;
NetworkPacket(NetworkCommand id) noexcept; NetworkPacket(NetworkCommand id) noexcept;
@@ -75,9 +77,10 @@ struct NetworkPacket final
return *this; return *this;
} }
public: public:
PacketHeader Header{}; PacketHeader Header{};
sfl::small_vector<uint8_t, 512> Data; sfl::small_vector<uint8_t, 512> Data;
size_t BytesTransferred = 0; size_t BytesTransferred = 0;
size_t BytesRead = 0; size_t BytesRead = 0;
}; };
} // namespace OpenRCT2::Network

View File

@@ -15,39 +15,42 @@
#include "../ui/WindowManager.h" #include "../ui/WindowManager.h"
#include "NetworkPacket.h" #include "NetworkPacket.h"
void NetworkPlayer::SetName(std::string_view name) namespace OpenRCT2::Network
{ {
void NetworkPlayer::SetName(std::string_view name)
{
// 36 == 31 + strlen(" #255"); // 36 == 31 + strlen(" #255");
Name = name.substr(0, 36); Name = name.substr(0, 36);
} }
void NetworkPlayer::Read(NetworkPacket& packet) void NetworkPlayer::Read(NetworkPacket& packet)
{ {
auto name = packet.ReadString(); auto name = packet.ReadString();
SetName(name); SetName(name);
packet >> Id >> Flags >> Group >> LastAction >> LastActionCoord.x >> LastActionCoord.y >> LastActionCoord.z >> MoneySpent packet >> Id >> Flags >> Group >> LastAction >> LastActionCoord.x >> LastActionCoord.y >> LastActionCoord.z
>> CommandsRan; >> MoneySpent >> CommandsRan;
} }
void NetworkPlayer::Write(NetworkPacket& packet) void NetworkPlayer::Write(NetworkPacket& packet)
{ {
packet.WriteString(Name); packet.WriteString(Name);
packet << Id << Flags << Group << LastAction << LastActionCoord.x << LastActionCoord.y << LastActionCoord.z << MoneySpent packet << Id << Flags << Group << LastAction << LastActionCoord.x << LastActionCoord.y << LastActionCoord.z
<< CommandsRan; << MoneySpent << CommandsRan;
} }
void NetworkPlayer::IncrementNumCommands() void NetworkPlayer::IncrementNumCommands()
{ {
CommandsRan++; CommandsRan++;
auto* windowMgr = OpenRCT2::Ui::GetWindowManager(); auto* windowMgr = OpenRCT2::Ui::GetWindowManager();
windowMgr->InvalidateByNumber(WindowClass::Player, Id); windowMgr->InvalidateByNumber(WindowClass::Player, Id);
} }
void NetworkPlayer::AddMoneySpent(money64 cost) void NetworkPlayer::AddMoneySpent(money64 cost)
{ {
MoneySpent += cost; MoneySpent += cost;
auto* windowMgr = OpenRCT2::Ui::GetWindowManager(); auto* windowMgr = OpenRCT2::Ui::GetWindowManager();
windowMgr->InvalidateByNumber(WindowClass::Player, Id); windowMgr->InvalidateByNumber(WindowClass::Player, Id);
} }
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -17,12 +17,15 @@
#include <string_view> #include <string_view>
#include <unordered_map> #include <unordered_map>
struct NetworkPacket;
struct Peep; struct Peep;
class NetworkPlayer final namespace OpenRCT2::Network
{ {
public: struct NetworkPacket;
class NetworkPlayer final
{
public:
uint8_t Id = 0; uint8_t Id = 0;
std::string Name; std::string Name;
uint16_t Ping = 0; uint16_t Ping = 0;
@@ -47,4 +50,5 @@ public:
void Write(NetworkPacket& packet); void Write(NetworkPacket& packet);
void IncrementNumCommands(); void IncrementNumCommands();
void AddMoneySpent(money64 cost); void AddMoneySpent(money64 cost);
}; };
} // namespace OpenRCT2::Network

View File

@@ -4,9 +4,12 @@
#ifndef DISABLE_NETWORK #ifndef DISABLE_NETWORK
class NetworkServer final : public NetworkBase namespace OpenRCT2::Network
{ {
public: class NetworkServer final : public NetworkBase
}; {
public:
};
} // namespace OpenRCT2::Network
#endif // DISABLE_NETWORK #endif // DISABLE_NETWORK

View File

@@ -34,25 +34,25 @@
#include <random> #include <random>
#include <string> #include <string>
using namespace OpenRCT2; namespace OpenRCT2::Network
enum class MasterServerStatus
{ {
enum class MasterServerStatus
{
Ok = 200, Ok = 200,
InvalidToken = 401, InvalidToken = 401,
ServerNotFound = 404, ServerNotFound = 404,
InternalError = 500 InternalError = 500
}; };
#ifndef DISABLE_HTTP #ifndef DISABLE_HTTP
using namespace std::chrono_literals; using namespace std::chrono_literals;
constexpr int32_t kMasterServerRegisterTime = std::chrono::milliseconds(2min).count(); constexpr int32_t kMasterServerRegisterTime = std::chrono::milliseconds(2min).count();
constexpr int32_t kMasterServerHeartbeatTime = std::chrono::milliseconds(1min).count(); constexpr int32_t kMasterServerHeartbeatTime = std::chrono::milliseconds(1min).count();
#endif #endif
class NetworkServerAdvertiser final : public INetworkServerAdvertiser class NetworkServerAdvertiser final : public INetworkServerAdvertiser
{ {
private: private:
uint16_t _port; uint16_t _port;
std::unique_ptr<IUdpSocket> _lanListener; std::unique_ptr<IUdpSocket> _lanListener;
@@ -74,7 +74,7 @@ private:
bool _forceIPv4 = false; bool _forceIPv4 = false;
#endif #endif
public: public:
explicit NetworkServerAdvertiser(uint16_t port) explicit NetworkServerAdvertiser(uint16_t port)
{ {
_port = port; _port = port;
@@ -100,7 +100,7 @@ public:
#endif #endif
} }
private: private:
void UpdateLAN() void UpdateLAN()
{ {
auto ticks = Platform::GetTicks(); auto ticks = Platform::GetTicks();
@@ -353,11 +353,12 @@ private:
return result; return result;
} }
#endif #endif
}; };
std::unique_ptr<INetworkServerAdvertiser> CreateServerAdvertiser(uint16_t port) std::unique_ptr<INetworkServerAdvertiser> CreateServerAdvertiser(uint16_t port)
{ {
return std::make_unique<NetworkServerAdvertiser>(port); return std::make_unique<NetworkServerAdvertiser>(port);
} }
} // namespace OpenRCT2::Network
#endif // DISABLE_NETWORK #endif // DISABLE_NETWORK

View File

@@ -11,21 +11,24 @@
#include <memory> #include <memory>
enum class AdvertiseStatus namespace OpenRCT2::Network
{ {
enum class AdvertiseStatus
{
disabled, disabled,
unregistered, unregistered,
registered, registered,
}; };
struct INetworkServerAdvertiser struct INetworkServerAdvertiser
{ {
virtual ~INetworkServerAdvertiser() virtual ~INetworkServerAdvertiser()
{ {
} }
virtual AdvertiseStatus GetStatus() const = 0; virtual AdvertiseStatus GetStatus() const = 0;
virtual void Update() = 0; virtual void Update() = 0;
}; };
[[nodiscard]] std::unique_ptr<INetworkServerAdvertiser> CreateServerAdvertiser(uint16_t port); [[nodiscard]] std::unique_ptr<INetworkServerAdvertiser> CreateServerAdvertiser(uint16_t port);
} // namespace OpenRCT2::Network

View File

@@ -13,39 +13,41 @@
#include "../core/EnumUtils.hpp" #include "../core/EnumUtils.hpp"
#include "../ride/RideTypes.h" #include "../ride/RideTypes.h"
enum namespace OpenRCT2::Network
{ {
enum
{
SERVER_EVENT_PLAYER_JOINED, SERVER_EVENT_PLAYER_JOINED,
SERVER_EVENT_PLAYER_DISCONNECTED, SERVER_EVENT_PLAYER_DISCONNECTED,
}; };
enum enum
{ {
NETWORK_TICK_FLAG_CHECKSUMS = 1 << 0, NETWORK_TICK_FLAG_CHECKSUMS = 1 << 0,
}; };
enum enum
{ {
NETWORK_MODE_NONE, NETWORK_MODE_NONE,
NETWORK_MODE_CLIENT, NETWORK_MODE_CLIENT,
NETWORK_MODE_SERVER NETWORK_MODE_SERVER
}; };
enum enum
{ {
NETWORK_PLAYER_FLAG_ISSERVER = 1 << 0, NETWORK_PLAYER_FLAG_ISSERVER = 1 << 0,
}; };
enum enum
{ {
NETWORK_STATUS_NONE, NETWORK_STATUS_NONE,
NETWORK_STATUS_READY, NETWORK_STATUS_READY,
NETWORK_STATUS_CONNECTING, NETWORK_STATUS_CONNECTING,
NETWORK_STATUS_CONNECTED NETWORK_STATUS_CONNECTED
}; };
enum class NetworkAuth : int32_t enum class NetworkAuth : int32_t
{ {
None, None,
Requested, Requested,
Ok, Ok,
@@ -57,10 +59,10 @@ enum class NetworkAuth : int32_t
RequirePassword, RequirePassword,
Verified, Verified,
UnknownKeyDisallowed UnknownKeyDisallowed
}; };
enum class NetworkCommand : uint32_t enum class NetworkCommand : uint32_t
{ {
Auth, Auth,
Map, Map,
Chat, Chat,
@@ -85,32 +87,32 @@ enum class NetworkCommand : uint32_t
Heartbeat, Heartbeat,
Max, Max,
Invalid = static_cast<uint32_t>(-1), Invalid = static_cast<uint32_t>(-1),
}; };
static_assert(NetworkCommand::GameInfo == static_cast<NetworkCommand>(9), "Master server expects this to be 9"); static_assert(NetworkCommand::GameInfo == static_cast<NetworkCommand>(9), "Master server expects this to be 9");
enum class NetworkServerStatus enum class NetworkServerStatus
{ {
Ok, Ok,
Desynced Desynced
}; };
struct NetworkServerState struct NetworkServerState
{ {
NetworkServerStatus state = NetworkServerStatus::Ok; NetworkServerStatus state = NetworkServerStatus::Ok;
uint32_t desyncTick = 0; uint32_t desyncTick = 0;
uint32_t tick = 0; uint32_t tick = 0;
uint32_t srand0 = 0; uint32_t srand0 = 0;
bool gamestateSnapshotsEnabled = false; bool gamestateSnapshotsEnabled = false;
}; };
// Structure is used for networking specific fields with meaning, // Structure is used for networking specific fields with meaning,
// this structure can be used in combination with DataSerialiser // this structure can be used in combination with DataSerialiser
// to provide extra details with template specialization. // to provide extra details with template specialization.
#pragma pack(push, 1) #pragma pack(push, 1)
template<typename T, size_t _TypeID> template<typename T, size_t _TypeID>
struct NetworkObjectId struct NetworkObjectId
{ {
NetworkObjectId(T v) NetworkObjectId(T v)
: id(v) : id(v)
{ {
@@ -124,25 +126,26 @@ struct NetworkObjectId
return id; return id;
} }
T id; T id;
}; };
#pragma pack(pop) #pragma pack(pop)
// NOTE: When adding new types make sure to have no duplicate _TypeID's otherwise // NOTE: When adding new types make sure to have no duplicate _TypeID's otherwise
// there is no way to specialize templates if they have the exact symbol. // there is no way to specialize templates if they have the exact symbol.
using NetworkPlayerId_t = NetworkObjectId<int32_t, 0>; using NetworkPlayerId_t = NetworkObjectId<int32_t, 0>;
using NetworkCheatType_t = NetworkObjectId<int32_t, 2>; using NetworkCheatType_t = NetworkObjectId<int32_t, 2>;
enum class NetworkStatisticsGroup : uint32_t enum class NetworkStatisticsGroup : uint32_t
{ {
Total = 0, // Entire network traffic. Total = 0, // Entire network traffic.
Base, // Messages such as Tick, Ping Base, // Messages such as Tick, Ping
Commands, // Command / Game actions Commands, // Command / Game actions
MapData, MapData,
Max, Max,
}; };
struct NetworkStats struct NetworkStats
{ {
uint64_t bytesReceived[EnumValue(NetworkStatisticsGroup::Max)]; uint64_t bytesReceived[EnumValue(NetworkStatisticsGroup::Max)];
uint64_t bytesSent[EnumValue(NetworkStatisticsGroup::Max)]; uint64_t bytesSent[EnumValue(NetworkStatisticsGroup::Max)];
}; };
} // namespace OpenRCT2::Network

View File

@@ -22,12 +22,12 @@
#include <unordered_set> #include <unordered_set>
using namespace OpenRCT2; namespace OpenRCT2::Network
constexpr const utf8* kUserStoreFilename = "users.json";
std::unique_ptr<NetworkUser> NetworkUser::FromJson(const json_t& jsonData)
{ {
constexpr const utf8* kUserStoreFilename = "users.json";
std::unique_ptr<NetworkUser> NetworkUser::FromJson(const json_t& jsonData)
{
Guard::Assert(jsonData.is_object(), "NetworkUser::FromJson expects parameter jsonData to be object"); Guard::Assert(jsonData.is_object(), "NetworkUser::FromJson expects parameter jsonData to be object");
const std::string hash = Json::GetString(jsonData["hash"]); const std::string hash = Json::GetString(jsonData["hash"]);
@@ -47,10 +47,10 @@ std::unique_ptr<NetworkUser> NetworkUser::FromJson(const json_t& jsonData)
user->Remove = false; user->Remove = false;
} }
return user; return user;
} }
json_t NetworkUser::ToJson() const json_t NetworkUser::ToJson() const
{ {
json_t jsonData; json_t jsonData;
jsonData["hash"] = Hash; jsonData["hash"] = Hash;
jsonData["name"] = Name; jsonData["name"] = Name;
@@ -63,10 +63,10 @@ json_t NetworkUser::ToJson() const
jsonData["groupId"] = jsonGroupId; jsonData["groupId"] = jsonGroupId;
return jsonData; return jsonData;
} }
void NetworkUserManager::Load() void NetworkUserManager::Load()
{ {
const auto path = GetStorePath(); const auto path = GetStorePath();
if (File::Exists(path)) if (File::Exists(path))
@@ -93,10 +93,10 @@ void NetworkUserManager::Load()
Console::Error::WriteLine("Failed to read %s as JSON. %s", path.c_str(), ex.what()); Console::Error::WriteLine("Failed to read %s as JSON. %s", path.c_str(), ex.what());
} }
} }
} }
void NetworkUserManager::Save() void NetworkUserManager::Save()
{ {
const auto path = GetStorePath(); const auto path = GetStorePath();
json_t jsonUsers; json_t jsonUsers;
@@ -151,10 +151,10 @@ void NetworkUserManager::Save()
} }
Json::WriteToFile(path, jsonUsers); Json::WriteToFile(path, jsonUsers);
} }
void NetworkUserManager::UnsetUsersOfGroup(uint8_t groupId) void NetworkUserManager::UnsetUsersOfGroup(uint8_t groupId)
{ {
for (const auto& kvp : _usersByHash) for (const auto& kvp : _usersByHash)
{ {
auto& networkUser = kvp.second; auto& networkUser = kvp.second;
@@ -163,29 +163,29 @@ void NetworkUserManager::UnsetUsersOfGroup(uint8_t groupId)
networkUser->GroupId = std::nullopt; networkUser->GroupId = std::nullopt;
} }
} }
} }
void NetworkUserManager::RemoveUser(const std::string& hash) void NetworkUserManager::RemoveUser(const std::string& hash)
{ {
NetworkUser* networkUser = const_cast<NetworkUser*>(GetUserByHash(hash)); NetworkUser* networkUser = const_cast<NetworkUser*>(GetUserByHash(hash));
if (networkUser != nullptr) if (networkUser != nullptr)
{ {
networkUser->Remove = true; networkUser->Remove = true;
} }
} }
const NetworkUser* NetworkUserManager::GetUserByHash(const std::string& hash) const const NetworkUser* NetworkUserManager::GetUserByHash(const std::string& hash) const
{ {
auto it = _usersByHash.find(hash); auto it = _usersByHash.find(hash);
if (it != _usersByHash.end()) if (it != _usersByHash.end())
{ {
return it->second.get(); return it->second.get();
} }
return nullptr; return nullptr;
} }
const NetworkUser* NetworkUserManager::GetUserByName(const std::string& name) const const NetworkUser* NetworkUserManager::GetUserByName(const std::string& name) const
{ {
for (const auto& kvp : _usersByHash) for (const auto& kvp : _usersByHash)
{ {
const auto& networkUser = kvp.second; const auto& networkUser = kvp.second;
@@ -195,10 +195,10 @@ const NetworkUser* NetworkUserManager::GetUserByName(const std::string& name) co
} }
} }
return nullptr; return nullptr;
} }
NetworkUser* NetworkUserManager::GetOrAddUser(const std::string& hash) NetworkUser* NetworkUserManager::GetOrAddUser(const std::string& hash)
{ {
NetworkUser* networkUser = const_cast<NetworkUser*>(GetUserByHash(hash)); NetworkUser* networkUser = const_cast<NetworkUser*>(GetUserByHash(hash));
if (networkUser == nullptr) if (networkUser == nullptr)
{ {
@@ -208,12 +208,13 @@ NetworkUser* NetworkUserManager::GetOrAddUser(const std::string& hash)
_usersByHash[hash] = std::move(newNetworkUser); _usersByHash[hash] = std::move(newNetworkUser);
} }
return networkUser; return networkUser;
} }
u8string NetworkUserManager::GetStorePath() u8string NetworkUserManager::GetStorePath()
{ {
auto& env = OpenRCT2::GetContext()->GetPlatformEnvironment(); auto& env = OpenRCT2::GetContext()->GetPlatformEnvironment();
return Path::Combine(env.GetDirectoryPath(OpenRCT2::DirBase::user), kUserStoreFilename); return Path::Combine(env.GetDirectoryPath(OpenRCT2::DirBase::user), kUserStoreFilename);
} }
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -16,9 +16,11 @@
#include <optional> #include <optional>
#include <unordered_map> #include <unordered_map>
class NetworkUser final namespace OpenRCT2::Network
{ {
public: class NetworkUser final
{
public:
std::string Hash; std::string Hash;
std::string Name; std::string Name;
std::optional<uint8_t> GroupId; std::optional<uint8_t> GroupId;
@@ -38,11 +40,11 @@ public:
* @return JSON representation of the NetworkUser object * @return JSON representation of the NetworkUser object
*/ */
json_t ToJson() const; json_t ToJson() const;
}; };
class NetworkUserManager final class NetworkUserManager final
{ {
public: public:
void Load(); void Load();
/** /**
@@ -60,8 +62,9 @@ public:
const NetworkUser* GetUserByName(const std::string& name) const; const NetworkUser* GetUserByName(const std::string& name) const;
NetworkUser* GetOrAddUser(const std::string& hash); NetworkUser* GetOrAddUser(const std::string& hash);
private: private:
std::unordered_map<std::string, std::unique_ptr<NetworkUser>> _usersByHash; std::unordered_map<std::string, std::unique_ptr<NetworkUser>> _usersByHash;
static u8string GetStorePath(); static u8string GetStorePath();
}; };
} // namespace OpenRCT2::Network

View File

@@ -31,10 +31,10 @@
#include <numeric> #include <numeric>
#include <optional> #include <optional>
using namespace OpenRCT2; namespace OpenRCT2::Network
int32_t ServerListEntry::CompareTo(const ServerListEntry& other) const
{ {
int32_t ServerListEntry::CompareTo(const ServerListEntry& other) const
{
const auto& a = *this; const auto& a = *this;
const auto& b = other; const auto& b = other;
@@ -66,15 +66,15 @@ int32_t ServerListEntry::CompareTo(const ServerListEntry& other) const
} }
return String::compare(a.Name, b.Name, true); return String::compare(a.Name, b.Name, true);
} }
bool ServerListEntry::IsVersionValid() const noexcept bool ServerListEntry::IsVersionValid() const noexcept
{ {
return Version.empty() || Version == NetworkGetVersion(); return Version.empty() || Version == NetworkGetVersion();
} }
std::optional<ServerListEntry> ServerListEntry::FromJson(json_t& server) std::optional<ServerListEntry> ServerListEntry::FromJson(json_t& server)
{ {
Guard::Assert(server.is_object(), "ServerListEntry::FromJson expects parameter server to be object"); Guard::Assert(server.is_object(), "ServerListEntry::FromJson expects parameter server to be object");
const auto port = Json::GetNumber<int32_t>(server["port"]); const auto port = Json::GetNumber<int32_t>(server["port"]);
@@ -109,10 +109,10 @@ std::optional<ServerListEntry> ServerListEntry::FromJson(json_t& server)
entry.MaxPlayers = maxPlayers; entry.MaxPlayers = maxPlayers;
return entry; return entry;
} }
void ServerList::Sort() void ServerList::Sort()
{ {
_serverEntries.erase( _serverEntries.erase(
std::unique( std::unique(
_serverEntries.begin(), _serverEntries.end(), _serverEntries.begin(), _serverEntries.end(),
@@ -127,36 +127,37 @@ void ServerList::Sort()
std::sort(_serverEntries.begin(), _serverEntries.end(), [](const ServerListEntry& a, const ServerListEntry& b) { std::sort(_serverEntries.begin(), _serverEntries.end(), [](const ServerListEntry& a, const ServerListEntry& b) {
return a.CompareTo(b) < 0; return a.CompareTo(b) < 0;
}); });
} }
ServerListEntry& ServerList::GetServer(size_t index) ServerListEntry& ServerList::GetServer(size_t index)
{ {
return _serverEntries[index]; return _serverEntries[index];
} }
size_t ServerList::GetCount() const size_t ServerList::GetCount() const
{ {
return _serverEntries.size(); return _serverEntries.size();
} }
void ServerList::Add(const ServerListEntry& entry) void ServerList::Add(const ServerListEntry& entry)
{ {
_serverEntries.push_back(entry); _serverEntries.push_back(entry);
Sort(); Sort();
} }
void ServerList::AddRange(const std::vector<ServerListEntry>& entries) void ServerList::AddRange(const std::vector<ServerListEntry>& entries)
{ {
_serverEntries.insert(_serverEntries.end(), entries.begin(), entries.end()); _serverEntries.insert(_serverEntries.end(), entries.begin(), entries.end());
Sort(); Sort();
} }
void ServerList::AddOrUpdateRange(const std::vector<ServerListEntry>& entries) void ServerList::AddOrUpdateRange(const std::vector<ServerListEntry>& entries)
{ {
for (auto& existsEntry : _serverEntries) for (auto& existsEntry : _serverEntries)
{ {
auto match = std::find_if( auto match = std::find_if(entries.begin(), entries.end(), [&](const ServerListEntry& entry) {
entries.begin(), entries.end(), [&](const ServerListEntry& entry) { return existsEntry.Address == entry.Address; }); return existsEntry.Address == entry.Address;
});
if (match != entries.end()) if (match != entries.end())
{ {
// Keep favourites // Keep favourites
@@ -176,15 +177,15 @@ void ServerList::AddOrUpdateRange(const std::vector<ServerListEntry>& entries)
}); });
AddRange(newServers); AddRange(newServers);
} }
void ServerList::Clear() noexcept void ServerList::Clear() noexcept
{ {
_serverEntries.clear(); _serverEntries.clear();
} }
std::vector<ServerListEntry> ServerList::ReadFavourites() const std::vector<ServerListEntry> ServerList::ReadFavourites() const
{ {
LOG_VERBOSE("server_list_read(...)"); LOG_VERBOSE("server_list_read(...)");
std::vector<ServerListEntry> entries; std::vector<ServerListEntry> entries;
try try
@@ -216,30 +217,30 @@ std::vector<ServerListEntry> ServerList::ReadFavourites() const
entries = std::vector<ServerListEntry>(); entries = std::vector<ServerListEntry>();
} }
return entries; return entries;
} }
void ServerList::ReadAndAddFavourites() void ServerList::ReadAndAddFavourites()
{ {
_serverEntries.erase( _serverEntries.erase(
std::remove_if( std::remove_if(
_serverEntries.begin(), _serverEntries.end(), [](const ServerListEntry& entry) { return entry.Favourite; }), _serverEntries.begin(), _serverEntries.end(), [](const ServerListEntry& entry) { return entry.Favourite; }),
_serverEntries.end()); _serverEntries.end());
auto entries = ReadFavourites(); auto entries = ReadFavourites();
AddRange(entries); AddRange(entries);
} }
void ServerList::WriteFavourites() const void ServerList::WriteFavourites() const
{ {
// Save just favourite servers // Save just favourite servers
std::vector<ServerListEntry> favouriteServers; std::vector<ServerListEntry> favouriteServers;
std::copy_if( std::copy_if(
_serverEntries.begin(), _serverEntries.end(), std::back_inserter(favouriteServers), _serverEntries.begin(), _serverEntries.end(), std::back_inserter(favouriteServers),
[](const ServerListEntry& entry) { return entry.Favourite; }); [](const ServerListEntry& entry) { return entry.Favourite; });
WriteFavourites(favouriteServers); WriteFavourites(favouriteServers);
} }
bool ServerList::WriteFavourites(const std::vector<ServerListEntry>& entries) const bool ServerList::WriteFavourites(const std::vector<ServerListEntry>& entries) const
{ {
LOG_VERBOSE("server_list_write(%d, 0x%p)", entries.size(), entries.data()); LOG_VERBOSE("server_list_write(%d, 0x%p)", entries.size(), entries.data());
auto& env = GetContext()->GetPlatformEnvironment(); auto& env = GetContext()->GetPlatformEnvironment();
@@ -262,10 +263,11 @@ bool ServerList::WriteFavourites(const std::vector<ServerListEntry>& entries) co
LOG_ERROR("Unable to write server list: %s", e.what()); LOG_ERROR("Unable to write server list: %s", e.what());
return false; return false;
} }
} }
std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync(const INetworkEndpoint& broadcastEndpoint) const std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync(
{ const INetworkEndpoint& broadcastEndpoint) const
{
auto broadcastAddress = broadcastEndpoint.GetHostname(); auto broadcastAddress = broadcastEndpoint.GetHostname();
return std::async(std::launch::async, [broadcastAddress] { return std::async(std::launch::async, [broadcastAddress] {
constexpr auto kReceiveDelayInMs = 10; constexpr auto kReceiveDelayInMs = 10;
@@ -318,10 +320,10 @@ std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync(
} }
return entries; return entries;
}); });
} }
std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync() const std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync() const
{ {
return std::async(std::launch::async, [&] { return std::async(std::launch::async, [&] {
// Get all possible LAN broadcast addresses // Get all possible LAN broadcast addresses
auto broadcastEndpoints = GetBroadcastAddresses(); auto broadcastEndpoints = GetBroadcastAddresses();
@@ -350,10 +352,10 @@ std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync(
} }
return mergedEntries; return mergedEntries;
}); });
} }
std::future<std::vector<ServerListEntry>> ServerList::FetchOnlineServerListAsync() const std::future<std::vector<ServerListEntry>> ServerList::FetchOnlineServerListAsync() const
{ {
#ifdef DISABLE_HTTP #ifdef DISABLE_HTTP
return {}; return {};
#else #else
@@ -424,19 +426,20 @@ std::future<std::vector<ServerListEntry>> ServerList::FetchOnlineServerListAsync
}); });
return f; return f;
#endif #endif
} }
uint32_t ServerList::GetTotalPlayerCount() const uint32_t ServerList::GetTotalPlayerCount() const
{ {
return std::accumulate(_serverEntries.begin(), _serverEntries.end(), 0, [](uint32_t acc, const ServerListEntry& entry) { return std::accumulate(_serverEntries.begin(), _serverEntries.end(), 0, [](uint32_t acc, const ServerListEntry& entry) {
return acc + entry.Players; return acc + entry.Players;
}); });
} }
const char* MasterServerException::what() const noexcept const char* MasterServerException::what() const noexcept
{ {
static std::string localisedStatusText = LanguageGetString(StatusText); static std::string localisedStatusText = LanguageGetString(StatusText);
return localisedStatusText.c_str(); return localisedStatusText.c_str();
} }
} // namespace OpenRCT2::Network
#endif #endif

View File

@@ -18,10 +18,12 @@
#include <string> #include <string>
#include <vector> #include <vector>
struct INetworkEndpoint; namespace OpenRCT2::Network
struct ServerListEntry
{ {
struct INetworkEndpoint;
struct ServerListEntry
{
std::string Address; std::string Address;
std::string Name; std::string Name;
std::string Description; std::string Description;
@@ -43,11 +45,11 @@ struct ServerListEntry
* @note json is deliberately left non-const: json_t behaviour changes when const * @note json is deliberately left non-const: json_t behaviour changes when const
*/ */
static std::optional<ServerListEntry> FromJson(json_t& server); static std::optional<ServerListEntry> FromJson(json_t& server);
}; };
class ServerList class ServerList
{ {
private: private:
std::vector<ServerListEntry> _serverEntries; std::vector<ServerListEntry> _serverEntries;
void Sort(); void Sort();
@@ -55,7 +57,7 @@ private:
bool WriteFavourites(const std::vector<ServerListEntry>& entries) const; bool WriteFavourites(const std::vector<ServerListEntry>& entries) const;
std::future<std::vector<ServerListEntry>> FetchLocalServerListAsync(const INetworkEndpoint& broadcastEndpoint) const; std::future<std::vector<ServerListEntry>> FetchLocalServerListAsync(const INetworkEndpoint& broadcastEndpoint) const;
public: public:
ServerListEntry& GetServer(size_t index); ServerListEntry& GetServer(size_t index);
size_t GetCount() const; size_t GetCount() const;
void Add(const ServerListEntry& entry); void Add(const ServerListEntry& entry);
@@ -69,11 +71,11 @@ public:
std::future<std::vector<ServerListEntry>> FetchLocalServerListAsync() const; std::future<std::vector<ServerListEntry>> FetchLocalServerListAsync() const;
std::future<std::vector<ServerListEntry>> FetchOnlineServerListAsync() const; std::future<std::vector<ServerListEntry>> FetchOnlineServerListAsync() const;
uint32_t GetTotalPlayerCount() const; uint32_t GetTotalPlayerCount() const;
}; };
class MasterServerException : public std::exception class MasterServerException : public std::exception
{ {
public: public:
StringId StatusText; StringId StatusText;
MasterServerException(StringId statusText) MasterServerException(StringId statusText)
@@ -82,4 +84,5 @@ public:
} }
const char* what() const noexcept override; const char* what() const noexcept override;
}; };
} // namespace OpenRCT2::Network

View File

@@ -73,16 +73,18 @@
#include "Socket.h" #include "Socket.h"
constexpr auto kConnectTimeout = std::chrono::milliseconds(3000); namespace OpenRCT2::Network
{
constexpr auto kConnectTimeout = std::chrono::milliseconds(3000);
// RAII WSA initialisation needed for Windows // RAII WSA initialisation needed for Windows
#ifdef _WIN32 #ifdef _WIN32
class WSA class WSA
{ {
private: private:
bool _isInitialised{}; bool _isInitialised{};
public: public:
bool IsInitialised() const noexcept bool IsInitialised() const noexcept
{ {
return _isInitialised; return _isInitialised;
@@ -113,36 +115,36 @@ public:
_isInitialised = false; _isInitialised = false;
} }
} }
}; };
static bool InitialiseWSA() static bool InitialiseWSA()
{ {
static WSA wsa; static WSA wsa;
return wsa.Initialise(); return wsa.Initialise();
} }
#else #else
static bool InitialiseWSA() static bool InitialiseWSA()
{ {
return true; return true;
} }
#endif #endif
class SocketException : public std::runtime_error class SocketException : public std::runtime_error
{ {
public: public:
explicit SocketException(const std::string& message) explicit SocketException(const std::string& message)
: std::runtime_error(message) : std::runtime_error(message)
{ {
} }
}; };
class NetworkEndpoint final : public INetworkEndpoint class NetworkEndpoint final : public INetworkEndpoint
{ {
private: private:
sockaddr _address{}; sockaddr _address{};
socklen_t _addressLen{}; socklen_t _addressLen{};
public: public:
NetworkEndpoint() noexcept = default; NetworkEndpoint() noexcept = default;
NetworkEndpoint(const sockaddr* address, socklen_t addressLen) NetworkEndpoint(const sockaddr* address, socklen_t addressLen)
@@ -181,11 +183,11 @@ public:
} }
return {}; return {};
} }
}; };
class Socket class Socket
{ {
protected: protected:
static bool ResolveAddress(const std::string& address, uint16_t port, sockaddr_storage* ss, socklen_t* ss_len) static bool ResolveAddress(const std::string& address, uint16_t port, sockaddr_storage* ss, socklen_t* ss_len)
{ {
return ResolveAddress(AF_UNSPEC, address, port, ss, ss_len); return ResolveAddress(AF_UNSPEC, address, port, ss, ss_len);
@@ -213,7 +215,7 @@ protected:
return setsockopt(socket, a, b, reinterpret_cast<const char*>(&ivalue), sizeof(ivalue)) == 0; return setsockopt(socket, a, b, reinterpret_cast<const char*>(&ivalue), sizeof(ivalue)) == 0;
} }
private: private:
static bool ResolveAddress( static bool ResolveAddress(
int32_t family, const std::string& address, uint16_t port, sockaddr_storage* ss, socklen_t* ss_len) int32_t family, const std::string& address, uint16_t port, sockaddr_storage* ss, socklen_t* ss_len)
{ {
@@ -245,11 +247,11 @@ private:
freeaddrinfo(result); freeaddrinfo(result);
return true; return true;
} }
}; };
class TcpSocket final : public ITcpSocket, protected Socket class TcpSocket final : public ITcpSocket, protected Socket
{ {
private: private:
std::atomic<SocketStatus> _status{ SocketStatus::Closed }; std::atomic<SocketStatus> _status{ SocketStatus::Closed };
uint16_t _listeningPort = 0; uint16_t _listeningPort = 0;
SOCKET _socket = INVALID_SOCKET; SOCKET _socket = INVALID_SOCKET;
@@ -259,7 +261,7 @@ private:
std::future<void> _connectFuture; std::future<void> _connectFuture;
std::string _error; std::string _error;
public: public:
TcpSocket() noexcept = default; TcpSocket() noexcept = default;
explicit TcpSocket(SOCKET socket, std::string hostName, std::string ipAddress) noexcept explicit TcpSocket(SOCKET socket, std::string hostName, std::string ipAddress) noexcept
@@ -632,7 +634,7 @@ public:
return _ipAddress; return _ipAddress;
} }
private: private:
void CloseSocket() void CloseSocket()
{ {
if (_socket != INVALID_SOCKET) if (_socket != INVALID_SOCKET)
@@ -661,11 +663,11 @@ private:
} }
return result; return result;
} }
}; };
class UdpSocket final : public IUdpSocket, protected Socket class UdpSocket final : public IUdpSocket, protected Socket
{ {
private: private:
SocketStatus _status = SocketStatus::Closed; SocketStatus _status = SocketStatus::Closed;
uint16_t _listeningPort = 0; uint16_t _listeningPort = 0;
SOCKET _socket = INVALID_SOCKET; SOCKET _socket = INVALID_SOCKET;
@@ -674,7 +676,7 @@ private:
std::string _hostName; std::string _hostName;
std::string _error; std::string _error;
public: public:
UdpSocket() noexcept = default; UdpSocket() noexcept = default;
~UdpSocket() override ~UdpSocket() override
@@ -817,7 +819,7 @@ public:
return _hostName.empty() ? nullptr : _hostName.c_str(); return _hostName.empty() ? nullptr : _hostName.c_str();
} }
private: private:
SOCKET CreateSocket() const SOCKET CreateSocket() const
{ {
auto sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); auto sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
@@ -860,23 +862,23 @@ private:
} }
_status = SocketStatus::Closed; _status = SocketStatus::Closed;
} }
}; };
std::unique_ptr<ITcpSocket> CreateTcpSocket() std::unique_ptr<ITcpSocket> CreateTcpSocket()
{ {
InitialiseWSA(); InitialiseWSA();
return std::make_unique<TcpSocket>(); return std::make_unique<TcpSocket>();
} }
std::unique_ptr<IUdpSocket> CreateUdpSocket() std::unique_ptr<IUdpSocket> CreateUdpSocket()
{ {
InitialiseWSA(); InitialiseWSA();
return std::make_unique<UdpSocket>(); return std::make_unique<UdpSocket>();
} }
#ifdef _WIN32 #ifdef _WIN32
static std::vector<INTERFACE_INFO> GetNetworkInterfaces() static std::vector<INTERFACE_INFO> GetNetworkInterfaces()
{ {
InitialiseWSA(); InitialiseWSA();
int sock = socket(AF_INET, SOCK_DGRAM, 0); int sock = socket(AF_INET, SOCK_DGRAM, 0);
@@ -910,11 +912,11 @@ static std::vector<INTERFACE_INFO> GetNetworkInterfaces()
interfaces.resize(len / sizeof(INTERFACE_INFO)); interfaces.resize(len / sizeof(INTERFACE_INFO));
interfaces.shrink_to_fit(); interfaces.shrink_to_fit();
return interfaces; return interfaces;
} }
#endif #endif
std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses() std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses()
{ {
std::vector<std::unique_ptr<INetworkEndpoint>> baddresses; std::vector<std::unique_ptr<INetworkEndpoint>> baddresses;
#ifdef _WIN32 #ifdef _WIN32
auto interfaces = GetNetworkInterfaces(); auto interfaces = GetNetworkInterfaces();
@@ -959,7 +961,8 @@ std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses()
{ {
ifreq r; ifreq r;
strcpy(r.ifr_name, req->ifr_name); strcpy(r.ifr_name, req->ifr_name);
if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 && (r.ifr_flags & IFF_BROADCAST) && ioctl(sock, SIOCGIFBRDADDR, &r) != -1) if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 && (r.ifr_flags & IFF_BROADCAST)
&& ioctl(sock, SIOCGIFBRDADDR, &r) != -1)
{ {
baddresses.push_back(std::make_unique<NetworkEndpoint>(&r.ifr_broadaddr, sizeof(sockaddr))); baddresses.push_back(std::make_unique<NetworkEndpoint>(&r.ifr_broadaddr, sizeof(sockaddr)));
} }
@@ -972,7 +975,9 @@ std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses()
close(sock); close(sock);
#endif #endif
return baddresses; return baddresses;
} }
} // namespace OpenRCT2::Network
namespace OpenRCT2::Convert namespace OpenRCT2::Convert
{ {

View File

@@ -13,42 +13,44 @@
#include <string> #include <string>
#include <vector> #include <vector>
enum class SocketStatus namespace OpenRCT2::Network
{ {
enum class SocketStatus
{
Closed, Closed,
Waiting, Waiting,
Resolving, Resolving,
Connecting, Connecting,
Connected, Connected,
Listening, Listening,
}; };
enum class NetworkReadPacket : int32_t enum class NetworkReadPacket : int32_t
{ {
Success, Success,
NoData, NoData,
MoreData, MoreData,
Disconnected Disconnected
}; };
/** /**
* Represents an address and port. * Represents an address and port.
*/ */
struct INetworkEndpoint struct INetworkEndpoint
{ {
virtual ~INetworkEndpoint() virtual ~INetworkEndpoint()
{ {
} }
virtual std::string GetHostname() const = 0; virtual std::string GetHostname() const = 0;
}; };
/** /**
* Represents a TCP socket / connection or listener. * Represents a TCP socket / connection or listener.
*/ */
struct ITcpSocket struct ITcpSocket
{ {
public: public:
virtual ~ITcpSocket() = default; virtual ~ITcpSocket() = default;
virtual SocketStatus GetStatus() const = 0; virtual SocketStatus GetStatus() const = 0;
@@ -71,14 +73,14 @@ public:
virtual void Finish() = 0; virtual void Finish() = 0;
virtual void Disconnect() = 0; virtual void Disconnect() = 0;
virtual void Close() = 0; virtual void Close() = 0;
}; };
/** /**
* Represents a UDP socket / listener. * Represents a UDP socket / listener.
*/ */
struct IUdpSocket struct IUdpSocket
{ {
public: public:
virtual ~IUdpSocket() = default; virtual ~IUdpSocket() = default;
virtual SocketStatus GetStatus() const = 0; virtual SocketStatus GetStatus() const = 0;
@@ -95,11 +97,12 @@ public:
= 0; = 0;
virtual void Close() = 0; virtual void Close() = 0;
}; };
[[nodiscard]] std::unique_ptr<ITcpSocket> CreateTcpSocket(); [[nodiscard]] std::unique_ptr<ITcpSocket> CreateTcpSocket();
[[nodiscard]] std::unique_ptr<IUdpSocket> CreateUdpSocket(); [[nodiscard]] std::unique_ptr<IUdpSocket> CreateUdpSocket();
[[nodiscard]] std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses(); [[nodiscard]] std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses();
} // namespace OpenRCT2::Network
namespace OpenRCT2::Convert namespace OpenRCT2::Convert
{ {