mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-21 23:03:04 +01:00
Move network units to OpenRCT2::Network namespace
This commit is contained in:
@@ -24,54 +24,51 @@
|
||||
#include <chrono>
|
||||
#include <discord_rpc.h>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
namespace
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
constexpr const char* kApplicationID = "378612438200877056";
|
||||
constexpr const char* kSteamAppID = nullptr;
|
||||
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()");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
DiscordService::DiscordService()
|
||||
{
|
||||
DiscordService::DiscordService()
|
||||
{
|
||||
DiscordEventHandlers handlers = {};
|
||||
handlers.ready = OnReady;
|
||||
handlers.disconnected = OnDisconnected;
|
||||
handlers.errored = OnErrored;
|
||||
Discord_Initialize(kApplicationID, &handlers, 1, kSteamAppID);
|
||||
}
|
||||
}
|
||||
|
||||
DiscordService::~DiscordService()
|
||||
{
|
||||
DiscordService::~DiscordService()
|
||||
{
|
||||
Discord_Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
static std::string GetParkName()
|
||||
{
|
||||
static std::string GetParkName()
|
||||
{
|
||||
auto& gameState = getGameState();
|
||||
return gameState.park.name;
|
||||
}
|
||||
}
|
||||
|
||||
void DiscordService::Tick()
|
||||
{
|
||||
void DiscordService::Tick()
|
||||
{
|
||||
Discord_RunCallbacks();
|
||||
|
||||
if (_updateTimer.GetElapsedTime() < kRefreshInterval)
|
||||
@@ -79,10 +76,10 @@ void DiscordService::Tick()
|
||||
|
||||
RefreshPresence();
|
||||
_updateTimer.Restart();
|
||||
}
|
||||
}
|
||||
|
||||
void DiscordService::RefreshPresence() const
|
||||
{
|
||||
void DiscordService::RefreshPresence() const
|
||||
{
|
||||
DiscordRichPresence discordPresence = {};
|
||||
discordPresence.largeImageKey = "logo";
|
||||
|
||||
@@ -148,6 +145,7 @@ void DiscordService::RefreshPresence() const
|
||||
discordPresence.details = details.c_str();
|
||||
|
||||
Discord_UpdatePresence(&discordPresence);
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,19 +15,22 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
class DiscordService final
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
private:
|
||||
class DiscordService final
|
||||
{
|
||||
private:
|
||||
OpenRCT2::Timer _updateTimer;
|
||||
|
||||
public:
|
||||
public:
|
||||
DiscordService();
|
||||
~DiscordService();
|
||||
|
||||
void Tick();
|
||||
|
||||
private:
|
||||
private:
|
||||
void RefreshPresence() const;
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
#include <string_view>
|
||||
#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 CoordsXYZ;
|
||||
|
||||
@@ -36,85 +30,94 @@ namespace OpenRCT2::GameActions
|
||||
class Result;
|
||||
} // 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();
|
||||
void NetworkShutdownClient();
|
||||
int32_t NetworkBeginClient(const std::string& host, int32_t port);
|
||||
int32_t NetworkBeginServer(int32_t port, const std::string& address);
|
||||
enum class NetworkPermission : uint32_t;
|
||||
|
||||
[[nodiscard]] int32_t NetworkGetMode();
|
||||
[[nodiscard]] int32_t NetworkGetStatus();
|
||||
bool NetworkIsDesynchronised();
|
||||
bool NetworkCheckDesynchronisation();
|
||||
void NetworkRequestGamestateSnapshot();
|
||||
void NetworkSendTick();
|
||||
bool NetworkGamestateSnapshotsEnabled();
|
||||
void NetworkUpdate();
|
||||
void NetworkProcessPending();
|
||||
void NetworkFlush();
|
||||
void NetworkReconnect();
|
||||
void NetworkShutdownClient();
|
||||
int32_t NetworkBeginClient(const std::string& host, int32_t port);
|
||||
int32_t NetworkBeginServer(int32_t port, const std::string& address);
|
||||
|
||||
[[nodiscard]] NetworkAuth NetworkGetAuthstatus();
|
||||
[[nodiscard]] uint32_t NetworkGetServerTick();
|
||||
[[nodiscard]] uint8_t NetworkGetCurrentPlayerId();
|
||||
[[nodiscard]] int32_t NetworkGetNumPlayers();
|
||||
[[nodiscard]] int32_t NetworkGetNumVisiblePlayers();
|
||||
[[nodiscard]] const char* NetworkGetPlayerName(uint32_t index);
|
||||
[[nodiscard]] uint32_t NetworkGetPlayerFlags(uint32_t index);
|
||||
[[nodiscard]] int32_t NetworkGetPlayerPing(uint32_t index);
|
||||
[[nodiscard]] int32_t NetworkGetPlayerID(uint32_t index);
|
||||
[[nodiscard]] money64 NetworkGetPlayerMoneySpent(uint32_t index);
|
||||
[[nodiscard]] std::string NetworkGetPlayerIPAddress(uint32_t id);
|
||||
[[nodiscard]] std::string NetworkGetPlayerPublicKeyHash(uint32_t id);
|
||||
void NetworkIncrementPlayerNumCommands(uint32_t playerIndex);
|
||||
void NetworkAddPlayerMoneySpent(uint32_t index, money64 cost);
|
||||
[[nodiscard]] int32_t NetworkGetPlayerLastAction(uint32_t index, int32_t time);
|
||||
void NetworkSetPlayerLastAction(uint32_t index, GameCommand command);
|
||||
[[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(
|
||||
[[nodiscard]] int32_t NetworkGetMode();
|
||||
[[nodiscard]] int32_t NetworkGetStatus();
|
||||
bool NetworkIsDesynchronised();
|
||||
bool NetworkCheckDesynchronisation();
|
||||
void NetworkRequestGamestateSnapshot();
|
||||
void NetworkSendTick();
|
||||
bool NetworkGamestateSnapshotsEnabled();
|
||||
void NetworkUpdate();
|
||||
void NetworkProcessPending();
|
||||
void NetworkFlush();
|
||||
|
||||
[[nodiscard]] NetworkAuth NetworkGetAuthstatus();
|
||||
[[nodiscard]] uint32_t NetworkGetServerTick();
|
||||
[[nodiscard]] uint8_t NetworkGetCurrentPlayerId();
|
||||
[[nodiscard]] int32_t NetworkGetNumPlayers();
|
||||
[[nodiscard]] int32_t NetworkGetNumVisiblePlayers();
|
||||
[[nodiscard]] const char* NetworkGetPlayerName(uint32_t index);
|
||||
[[nodiscard]] uint32_t NetworkGetPlayerFlags(uint32_t index);
|
||||
[[nodiscard]] int32_t NetworkGetPlayerPing(uint32_t index);
|
||||
[[nodiscard]] int32_t NetworkGetPlayerID(uint32_t index);
|
||||
[[nodiscard]] money64 NetworkGetPlayerMoneySpent(uint32_t index);
|
||||
[[nodiscard]] std::string NetworkGetPlayerIPAddress(uint32_t id);
|
||||
[[nodiscard]] std::string NetworkGetPlayerPublicKeyHash(uint32_t id);
|
||||
void NetworkIncrementPlayerNumCommands(uint32_t playerIndex);
|
||||
void NetworkAddPlayerMoneySpent(uint32_t index, money64 cost);
|
||||
[[nodiscard]] int32_t NetworkGetPlayerLastAction(uint32_t index, int32_t time);
|
||||
void NetworkSetPlayerLastAction(uint32_t index, GameCommand command);
|
||||
[[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);
|
||||
[[nodiscard]] OpenRCT2::GameActions::Result NetworkModifyGroups(
|
||||
[[nodiscard]] OpenRCT2::GameActions::Result NetworkModifyGroups(
|
||||
NetworkPlayerId_t actionPlayerId, OpenRCT2::GameActions::ModifyGroupType type, uint8_t groupId, const std::string& name,
|
||||
uint32_t permissionIndex, OpenRCT2::GameActions::PermissionState permissionState, bool isExecuting);
|
||||
[[nodiscard]] OpenRCT2::GameActions::Result NetworkKickPlayer(NetworkPlayerId_t playerId, bool isExecuting);
|
||||
[[nodiscard]] uint8_t NetworkGetDefaultGroup();
|
||||
[[nodiscard]] int32_t NetworkGetNumActions();
|
||||
[[nodiscard]] StringId NetworkGetActionNameStringID(uint32_t index);
|
||||
[[nodiscard]] int32_t NetworkCanPerformAction(uint32_t groupindex, NetworkPermission index);
|
||||
[[nodiscard]] int32_t NetworkCanPerformCommand(uint32_t groupindex, int32_t index);
|
||||
void NetworkSetPickupPeep(uint8_t playerid, Peep* peep);
|
||||
[[nodiscard]] Peep* NetworkGetPickupPeep(uint8_t playerid);
|
||||
void NetworkSetPickupPeepOldX(uint8_t playerid, int32_t x);
|
||||
[[nodiscard]] int32_t NetworkGetPickupPeepOldX(uint8_t playerid);
|
||||
[[nodiscard]] bool NetworkIsServerPlayerInvisible();
|
||||
[[nodiscard]] OpenRCT2::GameActions::Result NetworkKickPlayer(NetworkPlayerId_t playerId, bool isExecuting);
|
||||
[[nodiscard]] uint8_t NetworkGetDefaultGroup();
|
||||
[[nodiscard]] int32_t NetworkGetNumActions();
|
||||
[[nodiscard]] StringId NetworkGetActionNameStringID(uint32_t index);
|
||||
[[nodiscard]] int32_t NetworkCanPerformAction(uint32_t groupindex, NetworkPermission index);
|
||||
[[nodiscard]] int32_t NetworkCanPerformCommand(uint32_t groupindex, int32_t index);
|
||||
void NetworkSetPickupPeep(uint8_t playerid, Peep* peep);
|
||||
[[nodiscard]] Peep* NetworkGetPickupPeep(uint8_t playerid);
|
||||
void NetworkSetPickupPeepOldX(uint8_t playerid, int32_t x);
|
||||
[[nodiscard]] int32_t NetworkGetPickupPeepOldX(uint8_t playerid);
|
||||
[[nodiscard]] bool NetworkIsServerPlayerInvisible();
|
||||
|
||||
void NetworkSendChat(const char* text, const std::vector<uint8_t>& playerIds = {});
|
||||
void NetworkSendGameAction(const OpenRCT2::GameActions::GameAction* action);
|
||||
void NetworkSendPassword(const std::string& password);
|
||||
void NetworkSendChat(const char* text, const std::vector<uint8_t>& playerIds = {});
|
||||
void NetworkSendGameAction(const OpenRCT2::GameActions::GameAction* action);
|
||||
void NetworkSendPassword(const std::string& password);
|
||||
|
||||
void NetworkSetPassword(const char* password);
|
||||
void NetworkSetPassword(const char* password);
|
||||
|
||||
void NetworkAppendChatLog(std::string_view text);
|
||||
void NetworkAppendServerLog(const utf8* text);
|
||||
[[nodiscard]] u8string NetworkGetServerName();
|
||||
[[nodiscard]] u8string NetworkGetServerDescription();
|
||||
[[nodiscard]] u8string NetworkGetServerGreeting();
|
||||
[[nodiscard]] u8string NetworkGetServerProviderName();
|
||||
[[nodiscard]] u8string NetworkGetServerProviderEmail();
|
||||
[[nodiscard]] u8string NetworkGetServerProviderWebsite();
|
||||
void NetworkAppendChatLog(std::string_view text);
|
||||
void NetworkAppendServerLog(const utf8* text);
|
||||
[[nodiscard]] u8string NetworkGetServerName();
|
||||
[[nodiscard]] u8string NetworkGetServerDescription();
|
||||
[[nodiscard]] u8string NetworkGetServerGreeting();
|
||||
[[nodiscard]] u8string NetworkGetServerProviderName();
|
||||
[[nodiscard]] u8string NetworkGetServerProviderEmail();
|
||||
[[nodiscard]] u8string NetworkGetServerProviderWebsite();
|
||||
|
||||
[[nodiscard]] std::string NetworkGetVersion();
|
||||
[[nodiscard]] std::string NetworkGetVersion();
|
||||
|
||||
[[nodiscard]] NetworkStats NetworkGetStats();
|
||||
[[nodiscard]] NetworkServerState NetworkGetServerState();
|
||||
[[nodiscard]] json_t NetworkGetServerInfoAsJson();
|
||||
[[nodiscard]] NetworkStats NetworkGetStats();
|
||||
[[nodiscard]] NetworkServerState NetworkGetServerState();
|
||||
[[nodiscard]] json_t NetworkGetServerInfoAsJson();
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
#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) {
|
||||
for (GameCommand currentCommand : action.Commands)
|
||||
{
|
||||
@@ -33,10 +35,10 @@ NetworkPermission NetworkActions::FindCommand(GameCommand command)
|
||||
return static_cast<NetworkPermission>(it - Actions.begin());
|
||||
}
|
||||
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) {
|
||||
return action.PermissionName == permission_name;
|
||||
});
|
||||
@@ -45,9 +47,9 @@ NetworkPermission NetworkActions::FindCommandByPermissionName(const std::string&
|
||||
return static_cast<NetworkPermission>(it - Actions.begin());
|
||||
}
|
||||
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{
|
||||
STR_ACTION_CHAT,
|
||||
"PERMISSION_CHAT",
|
||||
@@ -264,6 +266,7 @@ const std::array<NetworkAction, static_cast<size_t>(NetworkPermission::Count)> N
|
||||
GameCommand::EditScenarioOptions,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum class NetworkPermission : uint32_t
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
enum class NetworkPermission : uint32_t
|
||||
{
|
||||
Chat,
|
||||
Terraform,
|
||||
SetWaterLevel,
|
||||
@@ -43,21 +45,22 @@ enum class NetworkPermission : uint32_t
|
||||
EditScenarioOptions,
|
||||
|
||||
Count
|
||||
};
|
||||
};
|
||||
|
||||
class NetworkAction final
|
||||
{
|
||||
public:
|
||||
class NetworkAction final
|
||||
{
|
||||
public:
|
||||
StringId Name;
|
||||
std::string PermissionName;
|
||||
std::vector<GameCommand> Commands;
|
||||
};
|
||||
};
|
||||
|
||||
class NetworkActions final
|
||||
{
|
||||
public:
|
||||
class NetworkActions final
|
||||
{
|
||||
public:
|
||||
static const std::array<NetworkAction, static_cast<size_t>(NetworkPermission::Count)> Actions;
|
||||
|
||||
static NetworkPermission FindCommand(GameCommand command);
|
||||
static NetworkPermission FindCommandByPermissionName(const std::string& permission_name);
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,16 +22,18 @@ namespace OpenRCT2
|
||||
struct IContext;
|
||||
}
|
||||
|
||||
class NetworkBase : public OpenRCT2::System
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
public:
|
||||
class NetworkBase : public OpenRCT2::System
|
||||
{
|
||||
public:
|
||||
NetworkBase(OpenRCT2::IContext& context);
|
||||
|
||||
public: // Uncategorized
|
||||
public: // Uncategorized
|
||||
bool BeginServer(uint16_t port, const std::string& address);
|
||||
bool BeginClient(const std::string& host, uint16_t port);
|
||||
|
||||
public: // Common
|
||||
public: // Common
|
||||
bool Init();
|
||||
void Close();
|
||||
uint32_t GetServerTick() const noexcept;
|
||||
@@ -60,7 +62,7 @@ public: // Common
|
||||
NetworkPlayer* AddPlayer(const std::string& name, const std::string& keyhash);
|
||||
void ProcessPacket(NetworkConnection& connection, NetworkPacket& packet);
|
||||
|
||||
public: // Server
|
||||
public: // Server
|
||||
NetworkConnection* GetPlayerConnection(uint8_t id) const;
|
||||
void KickPlayer(int32_t playerId);
|
||||
NetworkGroup* AddGroup();
|
||||
@@ -117,7 +119,7 @@ public: // Server
|
||||
void ServerHandleToken(NetworkConnection& connection, NetworkPacket& packet);
|
||||
void ServerHandleMapRequest(NetworkConnection& connection, NetworkPacket& packet);
|
||||
|
||||
public: // Client
|
||||
public: // Client
|
||||
void Reconnect();
|
||||
int32_t GetMode() const noexcept;
|
||||
NetworkAuth GetAuthStatus();
|
||||
@@ -140,7 +142,8 @@ public: // Client
|
||||
void Client_Send_RequestGameState(uint32_t tick);
|
||||
void Client_Send_TOKEN();
|
||||
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_GAME_ACTION(const OpenRCT2::GameActions::GameAction* action);
|
||||
void Client_Send_PING();
|
||||
@@ -174,7 +177,7 @@ public: // Client
|
||||
NetworkKey _key;
|
||||
NetworkUserManager _userManager;
|
||||
|
||||
public: // Public common
|
||||
public: // Public common
|
||||
std::string ServerName;
|
||||
std::string ServerDescription;
|
||||
std::string ServerGreeting;
|
||||
@@ -185,7 +188,7 @@ public: // Public common
|
||||
std::vector<std::unique_ptr<NetworkGroup>> group_list;
|
||||
bool IsServerPlayerInvisible = false;
|
||||
|
||||
private: // Common Data
|
||||
private: // Common Data
|
||||
using CommandHandler = void (NetworkBase::*)(NetworkConnection& connection, NetworkPacket& packet);
|
||||
|
||||
std::vector<uint8_t> chunk_buffer;
|
||||
@@ -197,7 +200,7 @@ private: // Common Data
|
||||
bool _closeLock = false;
|
||||
bool _requireClose = false;
|
||||
|
||||
private: // Server Data
|
||||
private: // Server Data
|
||||
std::unordered_map<NetworkCommand, CommandHandler> server_command_handlers;
|
||||
std::unique_ptr<ITcpSocket> _listenSocket;
|
||||
std::unique_ptr<INetworkServerAdvertiser> _advertiser;
|
||||
@@ -208,7 +211,7 @@ private: // Server Data
|
||||
uint16_t listening_port = 0;
|
||||
bool _playerListInvalidated = false;
|
||||
|
||||
private: // Client Data
|
||||
private: // Client Data
|
||||
struct PlayerListUpdate
|
||||
{
|
||||
std::vector<NetworkPlayer> players;
|
||||
@@ -251,6 +254,7 @@ private: // Client Data
|
||||
bool _requireReconnect = false;
|
||||
bool _clientMapLoaded = false;
|
||||
ServerScriptsData _serverScriptsData{};
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif // DISABLE_NETWORK
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#ifndef DISABLE_NETWORK
|
||||
|
||||
class NetworkClient final : public NetworkBase
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
public:
|
||||
};
|
||||
class NetworkClient final : public NetworkBase
|
||||
{
|
||||
public:
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif // DISABLE_NETWORK
|
||||
|
||||
@@ -19,23 +19,23 @@
|
||||
|
||||
#include <sfl/small_vector.hpp>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
static constexpr size_t kNetworkDisconnectReasonBufSize = 256;
|
||||
static constexpr size_t kNetworkBufferSize = (1024 * 64) - 1; // 64 KiB, maximum packet size.
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
static constexpr size_t kNetworkDisconnectReasonBufSize = 256;
|
||||
static constexpr size_t kNetworkBufferSize = (1024 * 64) - 1; // 64 KiB, maximum packet size.
|
||||
#ifndef DEBUG
|
||||
static constexpr size_t kNetworkNoDataTimeout = 20; // Seconds.
|
||||
static constexpr size_t kNetworkNoDataTimeout = 20; // Seconds.
|
||||
#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();
|
||||
}
|
||||
}
|
||||
|
||||
NetworkReadPacket NetworkConnection::ReadPacket()
|
||||
{
|
||||
NetworkReadPacket NetworkConnection::ReadPacket()
|
||||
{
|
||||
size_t bytesRead = 0;
|
||||
|
||||
// Read packet header.
|
||||
@@ -101,10 +101,10 @@ NetworkReadPacket NetworkConnection::ReadPacket()
|
||||
}
|
||||
|
||||
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.
|
||||
// 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);
|
||||
@@ -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());
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkConnection::QueuePacket(const NetworkPacket& packet, bool front)
|
||||
{
|
||||
void NetworkConnection::QueuePacket(const NetworkPacket& packet, bool front)
|
||||
{
|
||||
if (AuthStatus == NetworkAuth::Ok || !packet.CommandRequiresAuth())
|
||||
{
|
||||
const auto payload = serializePacket(packet);
|
||||
@@ -141,20 +141,20 @@ void NetworkConnection::QueuePacket(const NetworkPacket& packet, bool front)
|
||||
|
||||
RecordPacketStats(packet, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkConnection::Disconnect() noexcept
|
||||
{
|
||||
void NetworkConnection::Disconnect() noexcept
|
||||
{
|
||||
ShouldDisconnect = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkConnection::IsValid() const
|
||||
{
|
||||
bool NetworkConnection::IsValid() const
|
||||
{
|
||||
return !ShouldDisconnect && Socket->GetStatus() == SocketStatus::Connected;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkConnection::SendQueuedData()
|
||||
{
|
||||
void NetworkConnection::SendQueuedData()
|
||||
{
|
||||
if (_outboundBuffer.empty())
|
||||
{
|
||||
return;
|
||||
@@ -166,15 +166,15 @@ void NetworkConnection::SendQueuedData()
|
||||
{
|
||||
_outboundBuffer.erase(_outboundBuffer.begin(), _outboundBuffer.begin() + bytesSent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkConnection::ResetLastPacketTime() noexcept
|
||||
{
|
||||
void NetworkConnection::ResetLastPacketTime() noexcept
|
||||
{
|
||||
_lastPacketTime = Platform::GetTicks();
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkConnection::ReceivedPacketRecently() const noexcept
|
||||
{
|
||||
bool NetworkConnection::ReceivedPacketRecently() const noexcept
|
||||
{
|
||||
#ifndef DEBUG
|
||||
constexpr auto kTimeoutMs = kNetworkNoDataTimeout * 1000;
|
||||
if (Platform::GetTicks() > _lastPacketTime + kTimeoutMs)
|
||||
@@ -183,27 +183,27 @@ bool NetworkConnection::ReceivedPacketRecently() const noexcept
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const utf8* NetworkConnection::GetLastDisconnectReason() const noexcept
|
||||
{
|
||||
const utf8* NetworkConnection::GetLastDisconnectReason() const noexcept
|
||||
{
|
||||
return this->_lastDisconnectReason.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkConnection::SetLastDisconnectReason(std::string_view src)
|
||||
{
|
||||
void NetworkConnection::SetLastDisconnectReason(std::string_view src)
|
||||
{
|
||||
_lastDisconnectReason = src;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkConnection::SetLastDisconnectReason(const StringId string_id, void* args)
|
||||
{
|
||||
void NetworkConnection::SetLastDisconnectReason(const StringId string_id, void* args)
|
||||
{
|
||||
char buffer[kNetworkDisconnectReasonBufSize];
|
||||
OpenRCT2::FormatStringLegacy(buffer, kNetworkDisconnectReasonBufSize, string_id, args);
|
||||
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);
|
||||
NetworkStatisticsGroup trafficGroup;
|
||||
|
||||
@@ -230,6 +230,7 @@ void NetworkConnection::RecordPacketStats(const NetworkPacket& packet, bool send
|
||||
Stats.bytesReceived[EnumValue(trafficGroup)] += packetSize;
|
||||
Stats.bytesReceived[EnumValue(NetworkStatisticsGroup::Total)] += packetSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,16 +20,18 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
class NetworkPlayer;
|
||||
|
||||
namespace OpenRCT2
|
||||
{
|
||||
struct ObjectRepositoryItem;
|
||||
}
|
||||
|
||||
class NetworkConnection final
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
public:
|
||||
class NetworkPlayer;
|
||||
|
||||
class NetworkConnection final
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<ITcpSocket> Socket = nullptr;
|
||||
NetworkPacket InboundPacket;
|
||||
NetworkAuth AuthStatus = NetworkAuth::None;
|
||||
@@ -59,12 +61,13 @@ public:
|
||||
void SetLastDisconnectReason(std::string_view src);
|
||||
void SetLastDisconnectReason(const StringId string_id, void* args = nullptr);
|
||||
|
||||
private:
|
||||
private:
|
||||
std::vector<uint8_t> _outboundBuffer;
|
||||
uint32_t _lastPacketTime = 0;
|
||||
std::string _lastDisconnectReason;
|
||||
|
||||
void RecordPacketStats(const NetworkPacket& packet, bool sending);
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif // DISABLE_NETWORK
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
#include "NetworkAction.h"
|
||||
#include "NetworkTypes.h"
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
NetworkGroup NetworkGroup::FromJson(const json_t& jsonData)
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
NetworkGroup NetworkGroup::FromJson(const json_t& jsonData)
|
||||
{
|
||||
Guard::Assert(jsonData.is_object(), "NetworkGroup::FromJson expects parameter jsonData to be object");
|
||||
|
||||
NetworkGroup group;
|
||||
@@ -46,10 +46,10 @@ NetworkGroup NetworkGroup::FromJson(const json_t& jsonData)
|
||||
}
|
||||
}
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
json_t NetworkGroup::ToJson() const
|
||||
{
|
||||
json_t NetworkGroup::ToJson() const
|
||||
{
|
||||
json_t jsonGroup = {
|
||||
{ "id", Id },
|
||||
{ "name", GetName() },
|
||||
@@ -64,40 +64,40 @@ json_t NetworkGroup::ToJson() const
|
||||
}
|
||||
jsonGroup["permissions"] = actionsArray;
|
||||
return jsonGroup;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& NetworkGroup::GetName() const noexcept
|
||||
{
|
||||
const std::string& NetworkGroup::GetName() const noexcept
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkGroup::SetName(std::string_view name)
|
||||
{
|
||||
void NetworkGroup::SetName(std::string_view name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkGroup::Read(NetworkPacket& packet)
|
||||
{
|
||||
void NetworkGroup::Read(NetworkPacket& packet)
|
||||
{
|
||||
packet >> Id;
|
||||
SetName(packet.ReadString());
|
||||
for (auto& action : ActionsAllowed)
|
||||
{
|
||||
packet >> action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkGroup::Write(NetworkPacket& packet) const
|
||||
{
|
||||
void NetworkGroup::Write(NetworkPacket& packet) const
|
||||
{
|
||||
packet << Id;
|
||||
packet.WriteString(GetName().c_str());
|
||||
for (const auto& action : ActionsAllowed)
|
||||
{
|
||||
packet << action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkGroup::ToggleActionPermission(NetworkPermission index)
|
||||
{
|
||||
void NetworkGroup::ToggleActionPermission(NetworkPermission index)
|
||||
{
|
||||
size_t index_st = static_cast<size_t>(index);
|
||||
size_t byte = index_st / 8;
|
||||
size_t bit = index_st % 8;
|
||||
@@ -106,10 +106,10 @@ void NetworkGroup::ToggleActionPermission(NetworkPermission index)
|
||||
return;
|
||||
}
|
||||
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 byte = index_st / 8;
|
||||
size_t bit = index_st % 8;
|
||||
@@ -118,16 +118,17 @@ bool NetworkGroup::CanPerformAction(NetworkPermission index) const noexcept
|
||||
return false;
|
||||
}
|
||||
return (ActionsAllowed[byte] & (1 << bit)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkGroup::CanPerformCommand(GameCommand command) const
|
||||
{
|
||||
bool NetworkGroup::CanPerformCommand(GameCommand command) const
|
||||
{
|
||||
NetworkPermission action = NetworkActions::FindCommand(command);
|
||||
if (action != NetworkPermission::Count)
|
||||
{
|
||||
return CanPerformAction(action);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
enum class NetworkPermission : uint32_t;
|
||||
|
||||
class NetworkGroup final
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
public:
|
||||
enum class NetworkPermission : uint32_t;
|
||||
|
||||
class NetworkGroup final
|
||||
{
|
||||
public:
|
||||
std::array<uint8_t, 8> ActionsAllowed{};
|
||||
uint8_t Id = 0;
|
||||
|
||||
@@ -49,6 +51,7 @@ public:
|
||||
*/
|
||||
json_t ToJson() const;
|
||||
|
||||
private:
|
||||
private:
|
||||
std::string _name;
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
@@ -19,18 +19,18 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
NetworkKey::NetworkKey() = default;
|
||||
NetworkKey::~NetworkKey() = default;
|
||||
|
||||
void NetworkKey::Unload()
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
NetworkKey::NetworkKey() = default;
|
||||
NetworkKey::~NetworkKey() = default;
|
||||
|
||||
void NetworkKey::Unload()
|
||||
{
|
||||
_key = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkKey::Generate()
|
||||
{
|
||||
bool NetworkKey::Generate()
|
||||
{
|
||||
try
|
||||
{
|
||||
_key = Crypt::CreateRSAKey();
|
||||
@@ -42,10 +42,10 @@ bool NetworkKey::Generate()
|
||||
LOG_ERROR("NetworkKey::Generate failed: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkKey::LoadPrivate(OpenRCT2::IStream* stream)
|
||||
{
|
||||
bool NetworkKey::LoadPrivate(OpenRCT2::IStream* stream)
|
||||
{
|
||||
Guard::ArgumentNotNull(stream);
|
||||
|
||||
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());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkKey::LoadPublic(OpenRCT2::IStream* stream)
|
||||
{
|
||||
bool NetworkKey::LoadPublic(OpenRCT2::IStream* stream)
|
||||
{
|
||||
Guard::ArgumentNotNull(stream);
|
||||
|
||||
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());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkKey::SavePrivate(OpenRCT2::IStream* stream)
|
||||
{
|
||||
bool NetworkKey::SavePrivate(OpenRCT2::IStream* stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_key == nullptr)
|
||||
@@ -125,10 +125,10 @@ bool NetworkKey::SavePrivate(OpenRCT2::IStream* stream)
|
||||
LOG_ERROR("NetworkKey::SavePrivate failed: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkKey::SavePublic(OpenRCT2::IStream* stream)
|
||||
{
|
||||
bool NetworkKey::SavePublic(OpenRCT2::IStream* stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_key == nullptr)
|
||||
@@ -144,18 +144,18 @@ bool NetworkKey::SavePublic(OpenRCT2::IStream* stream)
|
||||
LOG_ERROR("NetworkKey::SavePublic failed: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string NetworkKey::PublicKeyString()
|
||||
{
|
||||
std::string NetworkKey::PublicKeyString()
|
||||
{
|
||||
if (_key == nullptr)
|
||||
{
|
||||
throw std::runtime_error("No key loaded");
|
||||
}
|
||||
return _key->GetPublic();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief NetworkKey::PublicKeyHash
|
||||
* 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
|
||||
@@ -166,8 +166,8 @@ std::string NetworkKey::PublicKeyString()
|
||||
*
|
||||
* @return returns a string containing key hash.
|
||||
*/
|
||||
std::string NetworkKey::PublicKeyHash()
|
||||
{
|
||||
std::string NetworkKey::PublicKeyHash()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string key = PublicKeyString();
|
||||
@@ -183,10 +183,10 @@ std::string NetworkKey::PublicKeyHash()
|
||||
LOG_ERROR("Failed to create hash of public key: %s", e.what());
|
||||
}
|
||||
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
|
||||
{
|
||||
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());
|
||||
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
|
||||
{
|
||||
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());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif // DISABLE_NETWORK
|
||||
|
||||
@@ -25,9 +25,11 @@ namespace OpenRCT2::Crypt
|
||||
class RsaKey;
|
||||
}
|
||||
|
||||
class NetworkKey final
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
public:
|
||||
class NetworkKey final
|
||||
{
|
||||
public:
|
||||
NetworkKey();
|
||||
~NetworkKey();
|
||||
bool Generate();
|
||||
@@ -41,9 +43,10 @@ public:
|
||||
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;
|
||||
|
||||
private:
|
||||
private:
|
||||
NetworkKey(const NetworkKey&) = delete;
|
||||
std::unique_ptr<OpenRCT2::Crypt::RsaKey> _key;
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif // DISABLE_NETWORK
|
||||
|
||||
@@ -15,35 +15,37 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
NetworkPacket::NetworkPacket(NetworkCommand id) noexcept
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
NetworkPacket::NetworkPacket(NetworkCommand id) noexcept
|
||||
: Header{ 0, id }
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t* NetworkPacket::GetData() noexcept
|
||||
{
|
||||
uint8_t* NetworkPacket::GetData() noexcept
|
||||
{
|
||||
return Data.data();
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* NetworkPacket::GetData() const noexcept
|
||||
{
|
||||
const uint8_t* NetworkPacket::GetData() const noexcept
|
||||
{
|
||||
return Data.data();
|
||||
}
|
||||
}
|
||||
|
||||
NetworkCommand NetworkPacket::GetCommand() const noexcept
|
||||
{
|
||||
NetworkCommand NetworkPacket::GetCommand() const noexcept
|
||||
{
|
||||
return Header.Id;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkPacket::Clear() noexcept
|
||||
{
|
||||
void NetworkPacket::Clear() noexcept
|
||||
{
|
||||
BytesTransferred = 0;
|
||||
BytesRead = 0;
|
||||
Data.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkPacket::CommandRequiresAuth() const noexcept
|
||||
{
|
||||
bool NetworkPacket::CommandRequiresAuth() const noexcept
|
||||
{
|
||||
switch (GetCommand())
|
||||
{
|
||||
case NetworkCommand::Ping:
|
||||
@@ -59,22 +61,22 @@ bool NetworkPacket::CommandRequiresAuth() const noexcept
|
||||
default:
|
||||
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);
|
||||
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());
|
||||
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())
|
||||
{
|
||||
return nullptr;
|
||||
@@ -83,10 +85,10 @@ const uint8_t* NetworkPacket::Read(size_t size)
|
||||
const uint8_t* data = Data.data() + BytesRead;
|
||||
BytesRead += size;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view NetworkPacket::ReadString()
|
||||
{
|
||||
std::string_view NetworkPacket::ReadString()
|
||||
{
|
||||
if (BytesRead >= Data.size())
|
||||
return {};
|
||||
|
||||
@@ -106,6 +108,7 @@ std::string_view NetworkPacket::ReadString()
|
||||
BytesRead++;
|
||||
|
||||
return std::string_view(str, stringLen);
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,17 +16,19 @@
|
||||
#include <sfl/small_vector.hpp>
|
||||
#include <vector>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct PacketHeader
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
struct PacketHeader
|
||||
{
|
||||
uint16_t Size = 0;
|
||||
NetworkCommand Id = NetworkCommand::Invalid;
|
||||
};
|
||||
static_assert(sizeof(PacketHeader) == 6);
|
||||
};
|
||||
static_assert(sizeof(PacketHeader) == 6);
|
||||
#pragma pack(pop)
|
||||
|
||||
struct NetworkPacket final
|
||||
{
|
||||
struct NetworkPacket final
|
||||
{
|
||||
NetworkPacket() noexcept = default;
|
||||
NetworkPacket(NetworkCommand id) noexcept;
|
||||
|
||||
@@ -75,9 +77,10 @@ struct NetworkPacket final
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
PacketHeader Header{};
|
||||
sfl::small_vector<uint8_t, 512> Data;
|
||||
size_t BytesTransferred = 0;
|
||||
size_t BytesRead = 0;
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
@@ -15,39 +15,42 @@
|
||||
#include "../ui/WindowManager.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");
|
||||
Name = name.substr(0, 36);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkPlayer::Read(NetworkPacket& packet)
|
||||
{
|
||||
void NetworkPlayer::Read(NetworkPacket& packet)
|
||||
{
|
||||
auto name = packet.ReadString();
|
||||
SetName(name);
|
||||
packet >> Id >> Flags >> Group >> LastAction >> LastActionCoord.x >> LastActionCoord.y >> LastActionCoord.z >> MoneySpent
|
||||
>> CommandsRan;
|
||||
}
|
||||
packet >> Id >> Flags >> Group >> LastAction >> LastActionCoord.x >> LastActionCoord.y >> LastActionCoord.z
|
||||
>> MoneySpent >> CommandsRan;
|
||||
}
|
||||
|
||||
void NetworkPlayer::Write(NetworkPacket& packet)
|
||||
{
|
||||
void NetworkPlayer::Write(NetworkPacket& packet)
|
||||
{
|
||||
packet.WriteString(Name);
|
||||
packet << Id << Flags << Group << LastAction << LastActionCoord.x << LastActionCoord.y << LastActionCoord.z << MoneySpent
|
||||
<< CommandsRan;
|
||||
}
|
||||
packet << Id << Flags << Group << LastAction << LastActionCoord.x << LastActionCoord.y << LastActionCoord.z
|
||||
<< MoneySpent << CommandsRan;
|
||||
}
|
||||
|
||||
void NetworkPlayer::IncrementNumCommands()
|
||||
{
|
||||
void NetworkPlayer::IncrementNumCommands()
|
||||
{
|
||||
CommandsRan++;
|
||||
auto* windowMgr = OpenRCT2::Ui::GetWindowManager();
|
||||
windowMgr->InvalidateByNumber(WindowClass::Player, Id);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkPlayer::AddMoneySpent(money64 cost)
|
||||
{
|
||||
void NetworkPlayer::AddMoneySpent(money64 cost)
|
||||
{
|
||||
MoneySpent += cost;
|
||||
auto* windowMgr = OpenRCT2::Ui::GetWindowManager();
|
||||
windowMgr->InvalidateByNumber(WindowClass::Player, Id);
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
struct NetworkPacket;
|
||||
struct Peep;
|
||||
|
||||
class NetworkPlayer final
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
public:
|
||||
struct NetworkPacket;
|
||||
|
||||
class NetworkPlayer final
|
||||
{
|
||||
public:
|
||||
uint8_t Id = 0;
|
||||
std::string Name;
|
||||
uint16_t Ping = 0;
|
||||
@@ -47,4 +50,5 @@ public:
|
||||
void Write(NetworkPacket& packet);
|
||||
void IncrementNumCommands();
|
||||
void AddMoneySpent(money64 cost);
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#ifndef DISABLE_NETWORK
|
||||
|
||||
class NetworkServer final : public NetworkBase
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
public:
|
||||
};
|
||||
class NetworkServer final : public NetworkBase
|
||||
{
|
||||
public:
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif // DISABLE_NETWORK
|
||||
|
||||
@@ -34,25 +34,25 @@
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
enum class MasterServerStatus
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
enum class MasterServerStatus
|
||||
{
|
||||
Ok = 200,
|
||||
InvalidToken = 401,
|
||||
ServerNotFound = 404,
|
||||
InternalError = 500
|
||||
};
|
||||
};
|
||||
|
||||
#ifndef DISABLE_HTTP
|
||||
using namespace std::chrono_literals;
|
||||
constexpr int32_t kMasterServerRegisterTime = std::chrono::milliseconds(2min).count();
|
||||
constexpr int32_t kMasterServerHeartbeatTime = std::chrono::milliseconds(1min).count();
|
||||
using namespace std::chrono_literals;
|
||||
constexpr int32_t kMasterServerRegisterTime = std::chrono::milliseconds(2min).count();
|
||||
constexpr int32_t kMasterServerHeartbeatTime = std::chrono::milliseconds(1min).count();
|
||||
#endif
|
||||
|
||||
class NetworkServerAdvertiser final : public INetworkServerAdvertiser
|
||||
{
|
||||
private:
|
||||
class NetworkServerAdvertiser final : public INetworkServerAdvertiser
|
||||
{
|
||||
private:
|
||||
uint16_t _port;
|
||||
|
||||
std::unique_ptr<IUdpSocket> _lanListener;
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
bool _forceIPv4 = false;
|
||||
#endif
|
||||
|
||||
public:
|
||||
public:
|
||||
explicit NetworkServerAdvertiser(uint16_t port)
|
||||
{
|
||||
_port = port;
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
void UpdateLAN()
|
||||
{
|
||||
auto ticks = Platform::GetTicks();
|
||||
@@ -353,11 +353,12 @@ private:
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
std::unique_ptr<INetworkServerAdvertiser> CreateServerAdvertiser(uint16_t port)
|
||||
{
|
||||
std::unique_ptr<INetworkServerAdvertiser> CreateServerAdvertiser(uint16_t port)
|
||||
{
|
||||
return std::make_unique<NetworkServerAdvertiser>(port);
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif // DISABLE_NETWORK
|
||||
|
||||
@@ -11,21 +11,24 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
enum class AdvertiseStatus
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
enum class AdvertiseStatus
|
||||
{
|
||||
disabled,
|
||||
unregistered,
|
||||
registered,
|
||||
};
|
||||
};
|
||||
|
||||
struct INetworkServerAdvertiser
|
||||
{
|
||||
struct INetworkServerAdvertiser
|
||||
{
|
||||
virtual ~INetworkServerAdvertiser()
|
||||
{
|
||||
}
|
||||
|
||||
virtual AdvertiseStatus GetStatus() const = 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
|
||||
|
||||
@@ -13,39 +13,41 @@
|
||||
#include "../core/EnumUtils.hpp"
|
||||
#include "../ride/RideTypes.h"
|
||||
|
||||
enum
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
enum
|
||||
{
|
||||
SERVER_EVENT_PLAYER_JOINED,
|
||||
SERVER_EVENT_PLAYER_DISCONNECTED,
|
||||
};
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum
|
||||
{
|
||||
NETWORK_TICK_FLAG_CHECKSUMS = 1 << 0,
|
||||
};
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum
|
||||
{
|
||||
NETWORK_MODE_NONE,
|
||||
NETWORK_MODE_CLIENT,
|
||||
NETWORK_MODE_SERVER
|
||||
};
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum
|
||||
{
|
||||
NETWORK_PLAYER_FLAG_ISSERVER = 1 << 0,
|
||||
};
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum
|
||||
{
|
||||
NETWORK_STATUS_NONE,
|
||||
NETWORK_STATUS_READY,
|
||||
NETWORK_STATUS_CONNECTING,
|
||||
NETWORK_STATUS_CONNECTED
|
||||
};
|
||||
};
|
||||
|
||||
enum class NetworkAuth : int32_t
|
||||
{
|
||||
enum class NetworkAuth : int32_t
|
||||
{
|
||||
None,
|
||||
Requested,
|
||||
Ok,
|
||||
@@ -57,10 +59,10 @@ enum class NetworkAuth : int32_t
|
||||
RequirePassword,
|
||||
Verified,
|
||||
UnknownKeyDisallowed
|
||||
};
|
||||
};
|
||||
|
||||
enum class NetworkCommand : uint32_t
|
||||
{
|
||||
enum class NetworkCommand : uint32_t
|
||||
{
|
||||
Auth,
|
||||
Map,
|
||||
Chat,
|
||||
@@ -85,32 +87,32 @@ enum class NetworkCommand : uint32_t
|
||||
Heartbeat,
|
||||
Max,
|
||||
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,
|
||||
Desynced
|
||||
};
|
||||
};
|
||||
|
||||
struct NetworkServerState
|
||||
{
|
||||
struct NetworkServerState
|
||||
{
|
||||
NetworkServerStatus state = NetworkServerStatus::Ok;
|
||||
uint32_t desyncTick = 0;
|
||||
uint32_t tick = 0;
|
||||
uint32_t srand0 = 0;
|
||||
bool gamestateSnapshotsEnabled = false;
|
||||
};
|
||||
};
|
||||
|
||||
// Structure is used for networking specific fields with meaning,
|
||||
// this structure can be used in combination with DataSerialiser
|
||||
// to provide extra details with template specialization.
|
||||
#pragma pack(push, 1)
|
||||
template<typename T, size_t _TypeID>
|
||||
struct NetworkObjectId
|
||||
{
|
||||
template<typename T, size_t _TypeID>
|
||||
struct NetworkObjectId
|
||||
{
|
||||
NetworkObjectId(T v)
|
||||
: id(v)
|
||||
{
|
||||
@@ -124,25 +126,26 @@ struct NetworkObjectId
|
||||
return id;
|
||||
}
|
||||
T id;
|
||||
};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// 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.
|
||||
using NetworkPlayerId_t = NetworkObjectId<int32_t, 0>;
|
||||
using NetworkCheatType_t = NetworkObjectId<int32_t, 2>;
|
||||
// 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.
|
||||
using NetworkPlayerId_t = NetworkObjectId<int32_t, 0>;
|
||||
using NetworkCheatType_t = NetworkObjectId<int32_t, 2>;
|
||||
|
||||
enum class NetworkStatisticsGroup : uint32_t
|
||||
{
|
||||
enum class NetworkStatisticsGroup : uint32_t
|
||||
{
|
||||
Total = 0, // Entire network traffic.
|
||||
Base, // Messages such as Tick, Ping
|
||||
Commands, // Command / Game actions
|
||||
MapData,
|
||||
Max,
|
||||
};
|
||||
};
|
||||
|
||||
struct NetworkStats
|
||||
{
|
||||
struct NetworkStats
|
||||
{
|
||||
uint64_t bytesReceived[EnumValue(NetworkStatisticsGroup::Max)];
|
||||
uint64_t bytesSent[EnumValue(NetworkStatisticsGroup::Max)];
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
constexpr const utf8* kUserStoreFilename = "users.json";
|
||||
|
||||
std::unique_ptr<NetworkUser> NetworkUser::FromJson(const json_t& jsonData)
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
json_t NetworkUser::ToJson() const
|
||||
{
|
||||
json_t NetworkUser::ToJson() const
|
||||
{
|
||||
json_t jsonData;
|
||||
jsonData["hash"] = Hash;
|
||||
jsonData["name"] = Name;
|
||||
@@ -63,10 +63,10 @@ json_t NetworkUser::ToJson() const
|
||||
jsonData["groupId"] = jsonGroupId;
|
||||
|
||||
return jsonData;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkUserManager::Load()
|
||||
{
|
||||
void NetworkUserManager::Load()
|
||||
{
|
||||
const auto path = GetStorePath();
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkUserManager::Save()
|
||||
{
|
||||
void NetworkUserManager::Save()
|
||||
{
|
||||
const auto path = GetStorePath();
|
||||
|
||||
json_t jsonUsers;
|
||||
@@ -151,10 +151,10 @@ void NetworkUserManager::Save()
|
||||
}
|
||||
|
||||
Json::WriteToFile(path, jsonUsers);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkUserManager::UnsetUsersOfGroup(uint8_t groupId)
|
||||
{
|
||||
void NetworkUserManager::UnsetUsersOfGroup(uint8_t groupId)
|
||||
{
|
||||
for (const auto& kvp : _usersByHash)
|
||||
{
|
||||
auto& networkUser = kvp.second;
|
||||
@@ -163,29 +163,29 @@ void NetworkUserManager::UnsetUsersOfGroup(uint8_t groupId)
|
||||
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));
|
||||
if (networkUser != nullptr)
|
||||
{
|
||||
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);
|
||||
if (it != _usersByHash.end())
|
||||
{
|
||||
return it->second.get();
|
||||
}
|
||||
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)
|
||||
{
|
||||
const auto& networkUser = kvp.second;
|
||||
@@ -195,10 +195,10 @@ const NetworkUser* NetworkUserManager::GetUserByName(const std::string& name) co
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NetworkUser* NetworkUserManager::GetOrAddUser(const std::string& hash)
|
||||
{
|
||||
NetworkUser* NetworkUserManager::GetOrAddUser(const std::string& hash)
|
||||
{
|
||||
NetworkUser* networkUser = const_cast<NetworkUser*>(GetUserByHash(hash));
|
||||
if (networkUser == nullptr)
|
||||
{
|
||||
@@ -208,12 +208,13 @@ NetworkUser* NetworkUserManager::GetOrAddUser(const std::string& hash)
|
||||
_usersByHash[hash] = std::move(newNetworkUser);
|
||||
}
|
||||
return networkUser;
|
||||
}
|
||||
}
|
||||
|
||||
u8string NetworkUserManager::GetStorePath()
|
||||
{
|
||||
u8string NetworkUserManager::GetStorePath()
|
||||
{
|
||||
auto& env = OpenRCT2::GetContext()->GetPlatformEnvironment();
|
||||
return Path::Combine(env.GetDirectoryPath(OpenRCT2::DirBase::user), kUserStoreFilename);
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
class NetworkUser final
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
public:
|
||||
class NetworkUser final
|
||||
{
|
||||
public:
|
||||
std::string Hash;
|
||||
std::string Name;
|
||||
std::optional<uint8_t> GroupId;
|
||||
@@ -38,11 +40,11 @@ public:
|
||||
* @return JSON representation of the NetworkUser object
|
||||
*/
|
||||
json_t ToJson() const;
|
||||
};
|
||||
};
|
||||
|
||||
class NetworkUserManager final
|
||||
{
|
||||
public:
|
||||
class NetworkUserManager final
|
||||
{
|
||||
public:
|
||||
void Load();
|
||||
|
||||
/**
|
||||
@@ -60,8 +62,9 @@ public:
|
||||
const NetworkUser* GetUserByName(const std::string& name) const;
|
||||
NetworkUser* GetOrAddUser(const std::string& hash);
|
||||
|
||||
private:
|
||||
private:
|
||||
std::unordered_map<std::string, std::unique_ptr<NetworkUser>> _usersByHash;
|
||||
|
||||
static u8string GetStorePath();
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
int32_t ServerListEntry::CompareTo(const ServerListEntry& other) const
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
int32_t ServerListEntry::CompareTo(const ServerListEntry& other) const
|
||||
{
|
||||
const auto& a = *this;
|
||||
const auto& b = other;
|
||||
|
||||
@@ -66,15 +66,15 @@ int32_t ServerListEntry::CompareTo(const ServerListEntry& other) const
|
||||
}
|
||||
|
||||
return String::compare(a.Name, b.Name, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerListEntry::IsVersionValid() const noexcept
|
||||
{
|
||||
bool ServerListEntry::IsVersionValid() const noexcept
|
||||
{
|
||||
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");
|
||||
|
||||
const auto port = Json::GetNumber<int32_t>(server["port"]);
|
||||
@@ -109,10 +109,10 @@ std::optional<ServerListEntry> ServerListEntry::FromJson(json_t& server)
|
||||
entry.MaxPlayers = maxPlayers;
|
||||
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
void ServerList::Sort()
|
||||
{
|
||||
void ServerList::Sort()
|
||||
{
|
||||
_serverEntries.erase(
|
||||
std::unique(
|
||||
_serverEntries.begin(), _serverEntries.end(),
|
||||
@@ -127,36 +127,37 @@ void ServerList::Sort()
|
||||
std::sort(_serverEntries.begin(), _serverEntries.end(), [](const ServerListEntry& a, const ServerListEntry& b) {
|
||||
return a.CompareTo(b) < 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ServerListEntry& ServerList::GetServer(size_t index)
|
||||
{
|
||||
ServerListEntry& ServerList::GetServer(size_t index)
|
||||
{
|
||||
return _serverEntries[index];
|
||||
}
|
||||
}
|
||||
|
||||
size_t ServerList::GetCount() const
|
||||
{
|
||||
size_t ServerList::GetCount() const
|
||||
{
|
||||
return _serverEntries.size();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerList::Add(const ServerListEntry& entry)
|
||||
{
|
||||
void ServerList::Add(const ServerListEntry& entry)
|
||||
{
|
||||
_serverEntries.push_back(entry);
|
||||
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());
|
||||
Sort();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerList::AddOrUpdateRange(const std::vector<ServerListEntry>& entries)
|
||||
{
|
||||
void ServerList::AddOrUpdateRange(const std::vector<ServerListEntry>& entries)
|
||||
{
|
||||
for (auto& existsEntry : _serverEntries)
|
||||
{
|
||||
auto match = std::find_if(
|
||||
entries.begin(), entries.end(), [&](const ServerListEntry& entry) { return existsEntry.Address == entry.Address; });
|
||||
auto match = std::find_if(entries.begin(), entries.end(), [&](const ServerListEntry& entry) {
|
||||
return existsEntry.Address == entry.Address;
|
||||
});
|
||||
if (match != entries.end())
|
||||
{
|
||||
// Keep favourites
|
||||
@@ -176,15 +177,15 @@ void ServerList::AddOrUpdateRange(const std::vector<ServerListEntry>& entries)
|
||||
});
|
||||
|
||||
AddRange(newServers);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerList::Clear() noexcept
|
||||
{
|
||||
void ServerList::Clear() noexcept
|
||||
{
|
||||
_serverEntries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ServerListEntry> ServerList::ReadFavourites() const
|
||||
{
|
||||
std::vector<ServerListEntry> ServerList::ReadFavourites() const
|
||||
{
|
||||
LOG_VERBOSE("server_list_read(...)");
|
||||
std::vector<ServerListEntry> entries;
|
||||
try
|
||||
@@ -216,30 +217,30 @@ std::vector<ServerListEntry> ServerList::ReadFavourites() const
|
||||
entries = std::vector<ServerListEntry>();
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
|
||||
void ServerList::ReadAndAddFavourites()
|
||||
{
|
||||
void ServerList::ReadAndAddFavourites()
|
||||
{
|
||||
_serverEntries.erase(
|
||||
std::remove_if(
|
||||
_serverEntries.begin(), _serverEntries.end(), [](const ServerListEntry& entry) { return entry.Favourite; }),
|
||||
_serverEntries.end());
|
||||
auto entries = ReadFavourites();
|
||||
AddRange(entries);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerList::WriteFavourites() const
|
||||
{
|
||||
void ServerList::WriteFavourites() const
|
||||
{
|
||||
// Save just favourite servers
|
||||
std::vector<ServerListEntry> favouriteServers;
|
||||
std::copy_if(
|
||||
_serverEntries.begin(), _serverEntries.end(), std::back_inserter(favouriteServers),
|
||||
[](const ServerListEntry& entry) { return entry.Favourite; });
|
||||
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());
|
||||
|
||||
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());
|
||||
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();
|
||||
return std::async(std::launch::async, [broadcastAddress] {
|
||||
constexpr auto kReceiveDelayInMs = 10;
|
||||
@@ -318,10 +320,10 @@ std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync(
|
||||
}
|
||||
return entries;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync() const
|
||||
{
|
||||
std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync() const
|
||||
{
|
||||
return std::async(std::launch::async, [&] {
|
||||
// Get all possible LAN broadcast addresses
|
||||
auto broadcastEndpoints = GetBroadcastAddresses();
|
||||
@@ -350,10 +352,10 @@ std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync(
|
||||
}
|
||||
return mergedEntries;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::future<std::vector<ServerListEntry>> ServerList::FetchOnlineServerListAsync() const
|
||||
{
|
||||
std::future<std::vector<ServerListEntry>> ServerList::FetchOnlineServerListAsync() const
|
||||
{
|
||||
#ifdef DISABLE_HTTP
|
||||
return {};
|
||||
#else
|
||||
@@ -424,19 +426,20 @@ std::future<std::vector<ServerListEntry>> ServerList::FetchOnlineServerListAsync
|
||||
});
|
||||
return f;
|
||||
#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 acc + entry.Players;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const char* MasterServerException::what() const noexcept
|
||||
{
|
||||
const char* MasterServerException::what() const noexcept
|
||||
{
|
||||
static std::string localisedStatusText = LanguageGetString(StatusText);
|
||||
return localisedStatusText.c_str();
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct INetworkEndpoint;
|
||||
|
||||
struct ServerListEntry
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
struct INetworkEndpoint;
|
||||
|
||||
struct ServerListEntry
|
||||
{
|
||||
std::string Address;
|
||||
std::string Name;
|
||||
std::string Description;
|
||||
@@ -43,11 +45,11 @@ struct ServerListEntry
|
||||
* @note json is deliberately left non-const: json_t behaviour changes when const
|
||||
*/
|
||||
static std::optional<ServerListEntry> FromJson(json_t& server);
|
||||
};
|
||||
};
|
||||
|
||||
class ServerList
|
||||
{
|
||||
private:
|
||||
class ServerList
|
||||
{
|
||||
private:
|
||||
std::vector<ServerListEntry> _serverEntries;
|
||||
|
||||
void Sort();
|
||||
@@ -55,7 +57,7 @@ private:
|
||||
bool WriteFavourites(const std::vector<ServerListEntry>& entries) const;
|
||||
std::future<std::vector<ServerListEntry>> FetchLocalServerListAsync(const INetworkEndpoint& broadcastEndpoint) const;
|
||||
|
||||
public:
|
||||
public:
|
||||
ServerListEntry& GetServer(size_t index);
|
||||
size_t GetCount() const;
|
||||
void Add(const ServerListEntry& entry);
|
||||
@@ -69,11 +71,11 @@ public:
|
||||
std::future<std::vector<ServerListEntry>> FetchLocalServerListAsync() const;
|
||||
std::future<std::vector<ServerListEntry>> FetchOnlineServerListAsync() const;
|
||||
uint32_t GetTotalPlayerCount() const;
|
||||
};
|
||||
};
|
||||
|
||||
class MasterServerException : public std::exception
|
||||
{
|
||||
public:
|
||||
class MasterServerException : public std::exception
|
||||
{
|
||||
public:
|
||||
StringId StatusText;
|
||||
|
||||
MasterServerException(StringId statusText)
|
||||
@@ -82,4 +84,5 @@ public:
|
||||
}
|
||||
|
||||
const char* what() const noexcept override;
|
||||
};
|
||||
};
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
@@ -73,16 +73,18 @@
|
||||
|
||||
#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
|
||||
#ifdef _WIN32
|
||||
class WSA
|
||||
{
|
||||
private:
|
||||
class WSA
|
||||
{
|
||||
private:
|
||||
bool _isInitialised{};
|
||||
|
||||
public:
|
||||
public:
|
||||
bool IsInitialised() const noexcept
|
||||
{
|
||||
return _isInitialised;
|
||||
@@ -113,36 +115,36 @@ public:
|
||||
_isInitialised = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
static bool InitialiseWSA()
|
||||
{
|
||||
static bool InitialiseWSA()
|
||||
{
|
||||
static WSA wsa;
|
||||
return wsa.Initialise();
|
||||
}
|
||||
}
|
||||
#else
|
||||
static bool InitialiseWSA()
|
||||
{
|
||||
static bool InitialiseWSA()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
class SocketException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
class SocketException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit SocketException(const std::string& message)
|
||||
: std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class NetworkEndpoint final : public INetworkEndpoint
|
||||
{
|
||||
private:
|
||||
class NetworkEndpoint final : public INetworkEndpoint
|
||||
{
|
||||
private:
|
||||
sockaddr _address{};
|
||||
socklen_t _addressLen{};
|
||||
|
||||
public:
|
||||
public:
|
||||
NetworkEndpoint() noexcept = default;
|
||||
|
||||
NetworkEndpoint(const sockaddr* address, socklen_t addressLen)
|
||||
@@ -181,11 +183,11 @@ public:
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class Socket
|
||||
{
|
||||
protected:
|
||||
class Socket
|
||||
{
|
||||
protected:
|
||||
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);
|
||||
@@ -213,7 +215,7 @@ protected:
|
||||
return setsockopt(socket, a, b, reinterpret_cast<const char*>(&ivalue), sizeof(ivalue)) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
static bool ResolveAddress(
|
||||
int32_t family, const std::string& address, uint16_t port, sockaddr_storage* ss, socklen_t* ss_len)
|
||||
{
|
||||
@@ -245,11 +247,11 @@ private:
|
||||
freeaddrinfo(result);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class TcpSocket final : public ITcpSocket, protected Socket
|
||||
{
|
||||
private:
|
||||
class TcpSocket final : public ITcpSocket, protected Socket
|
||||
{
|
||||
private:
|
||||
std::atomic<SocketStatus> _status{ SocketStatus::Closed };
|
||||
uint16_t _listeningPort = 0;
|
||||
SOCKET _socket = INVALID_SOCKET;
|
||||
@@ -259,7 +261,7 @@ private:
|
||||
std::future<void> _connectFuture;
|
||||
std::string _error;
|
||||
|
||||
public:
|
||||
public:
|
||||
TcpSocket() noexcept = default;
|
||||
|
||||
explicit TcpSocket(SOCKET socket, std::string hostName, std::string ipAddress) noexcept
|
||||
@@ -632,7 +634,7 @@ public:
|
||||
return _ipAddress;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
void CloseSocket()
|
||||
{
|
||||
if (_socket != INVALID_SOCKET)
|
||||
@@ -661,11 +663,11 @@ private:
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class UdpSocket final : public IUdpSocket, protected Socket
|
||||
{
|
||||
private:
|
||||
class UdpSocket final : public IUdpSocket, protected Socket
|
||||
{
|
||||
private:
|
||||
SocketStatus _status = SocketStatus::Closed;
|
||||
uint16_t _listeningPort = 0;
|
||||
SOCKET _socket = INVALID_SOCKET;
|
||||
@@ -674,7 +676,7 @@ private:
|
||||
std::string _hostName;
|
||||
std::string _error;
|
||||
|
||||
public:
|
||||
public:
|
||||
UdpSocket() noexcept = default;
|
||||
|
||||
~UdpSocket() override
|
||||
@@ -817,7 +819,7 @@ public:
|
||||
return _hostName.empty() ? nullptr : _hostName.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
SOCKET CreateSocket() const
|
||||
{
|
||||
auto sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
@@ -860,23 +862,23 @@ private:
|
||||
}
|
||||
_status = SocketStatus::Closed;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
std::unique_ptr<ITcpSocket> CreateTcpSocket()
|
||||
{
|
||||
std::unique_ptr<ITcpSocket> CreateTcpSocket()
|
||||
{
|
||||
InitialiseWSA();
|
||||
return std::make_unique<TcpSocket>();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<IUdpSocket> CreateUdpSocket()
|
||||
{
|
||||
std::unique_ptr<IUdpSocket> CreateUdpSocket()
|
||||
{
|
||||
InitialiseWSA();
|
||||
return std::make_unique<UdpSocket>();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static std::vector<INTERFACE_INFO> GetNetworkInterfaces()
|
||||
{
|
||||
static std::vector<INTERFACE_INFO> GetNetworkInterfaces()
|
||||
{
|
||||
InitialiseWSA();
|
||||
|
||||
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.shrink_to_fit();
|
||||
return interfaces;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses()
|
||||
{
|
||||
std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses()
|
||||
{
|
||||
std::vector<std::unique_ptr<INetworkEndpoint>> baddresses;
|
||||
#ifdef _WIN32
|
||||
auto interfaces = GetNetworkInterfaces();
|
||||
@@ -959,7 +961,8 @@ std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses()
|
||||
{
|
||||
ifreq r;
|
||||
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)));
|
||||
}
|
||||
@@ -972,7 +975,9 @@ std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses()
|
||||
close(sock);
|
||||
#endif
|
||||
return baddresses;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
namespace OpenRCT2::Convert
|
||||
{
|
||||
|
||||
@@ -13,42 +13,44 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum class SocketStatus
|
||||
namespace OpenRCT2::Network
|
||||
{
|
||||
enum class SocketStatus
|
||||
{
|
||||
Closed,
|
||||
Waiting,
|
||||
Resolving,
|
||||
Connecting,
|
||||
Connected,
|
||||
Listening,
|
||||
};
|
||||
};
|
||||
|
||||
enum class NetworkReadPacket : int32_t
|
||||
{
|
||||
enum class NetworkReadPacket : int32_t
|
||||
{
|
||||
Success,
|
||||
NoData,
|
||||
MoreData,
|
||||
Disconnected
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Represents an address and port.
|
||||
*/
|
||||
struct INetworkEndpoint
|
||||
{
|
||||
struct INetworkEndpoint
|
||||
{
|
||||
virtual ~INetworkEndpoint()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string GetHostname() const = 0;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Represents a TCP socket / connection or listener.
|
||||
*/
|
||||
struct ITcpSocket
|
||||
{
|
||||
public:
|
||||
struct ITcpSocket
|
||||
{
|
||||
public:
|
||||
virtual ~ITcpSocket() = default;
|
||||
|
||||
virtual SocketStatus GetStatus() const = 0;
|
||||
@@ -71,14 +73,14 @@ public:
|
||||
virtual void Finish() = 0;
|
||||
virtual void Disconnect() = 0;
|
||||
virtual void Close() = 0;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Represents a UDP socket / listener.
|
||||
*/
|
||||
struct IUdpSocket
|
||||
{
|
||||
public:
|
||||
struct IUdpSocket
|
||||
{
|
||||
public:
|
||||
virtual ~IUdpSocket() = default;
|
||||
|
||||
virtual SocketStatus GetStatus() const = 0;
|
||||
@@ -95,11 +97,12 @@ public:
|
||||
= 0;
|
||||
|
||||
virtual void Close() = 0;
|
||||
};
|
||||
};
|
||||
|
||||
[[nodiscard]] std::unique_ptr<ITcpSocket> CreateTcpSocket();
|
||||
[[nodiscard]] std::unique_ptr<IUdpSocket> CreateUdpSocket();
|
||||
[[nodiscard]] std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses();
|
||||
[[nodiscard]] std::unique_ptr<ITcpSocket> CreateTcpSocket();
|
||||
[[nodiscard]] std::unique_ptr<IUdpSocket> CreateUdpSocket();
|
||||
[[nodiscard]] std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses();
|
||||
} // namespace OpenRCT2::Network
|
||||
|
||||
namespace OpenRCT2::Convert
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user