From 040c024dff8875354652912a51535c4dd70719ce Mon Sep 17 00:00:00 2001 From: Damian Korczowski Date: Fri, 18 Jun 2021 20:43:17 +0200 Subject: [PATCH] Refactor most NetworkManager functionality into NetworkHost --- .../Engine/Networking/Drivers/ENetDriver.cpp | 8 +- Source/Engine/Networking/Drivers/ENetDriver.h | 5 +- Source/Engine/Networking/INetworkDriver.h | 4 +- Source/Engine/Networking/NetworkHost.cpp | 96 ++++++++++- Source/Engine/Networking/NetworkHost.h | 55 ++++++- Source/Engine/Networking/NetworkManager.cpp | 151 ++---------------- Source/Engine/Networking/NetworkManager.h | 26 +-- 7 files changed, 177 insertions(+), 168 deletions(-) diff --git a/Source/Engine/Networking/Drivers/ENetDriver.cpp b/Source/Engine/Networking/Drivers/ENetDriver.cpp index c5c79f69e..1e47d3919 100644 --- a/Source/Engine/Networking/Drivers/ENetDriver.cpp +++ b/Source/Engine/Networking/Drivers/ENetDriver.cpp @@ -7,7 +7,7 @@ #include "Engine/Networking/NetworkConfig.h" #include "Engine/Networking/NetworkChannelType.h" #include "Engine/Networking/NetworkEvent.h" -#include "Engine/Networking/NetworkManager.h" +#include "Engine/Networking/NetworkHost.h" #include "Engine/Core/Log.h" #include "Engine/Core/Collections/Array.h" @@ -15,6 +15,7 @@ #define ENET_IMPLEMENTATION #define _WINSOCK_DEPRECATED_NO_WARNINGS #include + #undef _WINSOCK_DEPRECATED_NO_WARNINGS #undef SendMessage @@ -52,8 +53,9 @@ void SendPacketToPeer(ENetPeer* peer, const NetworkChannelType channelType, cons // TODO: To reduce latency, we can use `enet_host_flush` to flush all packets. Maybe some API, like NetworkManager::FlushQueues()? } -void ENetDriver::Initialize(const NetworkConfig& config) +void ENetDriver::Initialize(NetworkHost* host, const NetworkConfig& config) { + _networkHost = host; _config = config; _peerMap = Dictionary(); @@ -202,7 +204,7 @@ bool ENetDriver::PopEvent(NetworkEvent* eventPtr) eventPtr->EventType = NetworkEventType::Message; // Acquire message and copy message data - eventPtr->Message = NetworkManager::CreateMessage(eventPtr->HostId); + eventPtr->Message = _networkHost->CreateMessage(); eventPtr->Message.Length = event.packet->dataLength; Memory::CopyItems(eventPtr->Message.Buffer, event.packet->data, event.packet->dataLength); break; diff --git a/Source/Engine/Networking/Drivers/ENetDriver.h b/Source/Engine/Networking/Drivers/ENetDriver.h index a64c85783..b79067579 100644 --- a/Source/Engine/Networking/Drivers/ENetDriver.h +++ b/Source/Engine/Networking/Drivers/ENetDriver.h @@ -10,11 +10,13 @@ #include "Engine/Core/Collections/Dictionary.h" #include "Engine/Scripting/ScriptingType.h" +class NetworkHost; + API_CLASS(Namespace="FlaxEngine.Networking", Sealed) class FLAXENGINE_API ENetDriver : public INetworkDriver { DECLARE_SCRIPTING_TYPE_MINIMAL(ENetDriver); public: - void Initialize(const NetworkConfig& config) override; + void Initialize(NetworkHost* host, const NetworkConfig& config) override; void Dispose() override; bool Listen() override; @@ -36,6 +38,7 @@ private: private: NetworkConfig _config; + NetworkHost* _networkHost; void* _host = nullptr; void* _peer = nullptr; diff --git a/Source/Engine/Networking/INetworkDriver.h b/Source/Engine/Networking/INetworkDriver.h index f3b365693..c7768d1c2 100644 --- a/Source/Engine/Networking/INetworkDriver.h +++ b/Source/Engine/Networking/INetworkDriver.h @@ -4,11 +4,13 @@ #include "Engine/Scripting/ScriptingType.h" +class NetworkHost; + API_INTERFACE(Namespace="FlaxEngine.Networking") class FLAXENGINE_API INetworkDriver { DECLARE_SCRIPTING_TYPE_MINIMAL(INetworkDriver); public: - virtual void Initialize(const NetworkConfig& config) = 0; + virtual void Initialize(NetworkHost* host, const NetworkConfig& config) = 0; virtual void Dispose() = 0; virtual bool Listen() = 0; diff --git a/Source/Engine/Networking/NetworkHost.cpp b/Source/Engine/Networking/NetworkHost.cpp index b065c5030..9a1e9b91f 100644 --- a/Source/Engine/Networking/NetworkHost.cpp +++ b/Source/Engine/Networking/NetworkHost.cpp @@ -1,6 +1,8 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "NetworkHost.h" +#include "NetworkEvent.h" + #include "Drivers/ENetDriver.h" @@ -18,6 +20,7 @@ void NetworkHost::Initialize(const NetworkConfig& config) ASSERT(Config.MessageSize > 32); // TODO: Adjust this, not sure what the lowest limit should be. ASSERT(Config.MessagePoolSize > 128); + // TODO: Dynamic message pool allocation // Setup messages CreateMessageBuffers(); MessagePool.Clear(); @@ -28,7 +31,7 @@ void NetworkHost::Initialize(const NetworkConfig& config) // Setup network driver NetworkDriver = New(); - NetworkDriver->Initialize(Config); + NetworkDriver->Initialize(this, Config); LOG(Info, "NetworkManager initialized using driver = {0}", static_cast(Config.NetworkDriverType)); } @@ -65,3 +68,94 @@ void NetworkHost::DisposeMessageBuffers() Platform::FreePages(MessageBuffer); MessageBuffer = nullptr; } + +bool NetworkHost::Listen() +{ + LOG(Info, "NetworkManager starting to listen on address = {0}:{1}", Config.Address, Config.Port); + return NetworkDriver->Listen(); +} + +bool NetworkHost::Connect() +{ + LOG(Info, "Connecting to {0}:{1}...", Config.Address, Config.Port); + return NetworkDriver->Connect(); +} + +void NetworkHost::Disconnect() +{ + LOG(Info, "Disconnecting..."); + NetworkDriver->Disconnect(); +} + +void NetworkHost::Disconnect(const NetworkConnection& connection) +{ + LOG(Info, "Disconnecting connection with id = {0}...", connection.ConnectionId); + NetworkDriver->Disconnect(connection); +} + +bool NetworkHost::PopEvent(NetworkEvent& eventRef) +{ + // Set host id of the event + eventRef.HostId = HostId; + return NetworkDriver->PopEvent(&eventRef); +} + +NetworkMessage NetworkHost::CreateMessage() +{ + const uint32 messageId = MessagePool.Pop(); + uint8* messageBuffer = GetMessageBuffer(messageId); + + return NetworkMessage(messageBuffer, messageId, Config.MessageSize, 0, 0); +} + +void NetworkHost::RecycleMessage(const NetworkMessage& message) +{ + ASSERT(message.IsValid()); +#ifdef BUILD_DEBUG + ASSERT(MessagePool.Contains(message.MessageId) == false); +#endif + + // Return the message id + MessagePool.Push(message.MessageId); +} + +NetworkMessage NetworkHost::BeginSendMessage() +{ + return CreateMessage(); +} + +void NetworkHost::AbortSendMessage(const NetworkMessage& message) +{ + ASSERT(message.IsValid()); + RecycleMessage(message); +} + +bool NetworkHost::EndSendMessage(const NetworkChannelType channelType, const NetworkMessage& message) +{ + ASSERT(message.IsValid()); + + NetworkDriver->SendMessage(channelType, message); + + RecycleMessage(message); + return false; +} + +bool NetworkHost::EndSendMessage(const NetworkChannelType channelType, const NetworkMessage& message, const NetworkConnection& target) +{ + ASSERT(message.IsValid()); + + NetworkDriver->SendMessage(channelType, message, target); + + RecycleMessage(message); + return false; +} + +bool NetworkHost::EndSendMessage(const NetworkChannelType channelType, const NetworkMessage& message, Array targets) +{ + ASSERT(message.IsValid()); + + NetworkDriver->SendMessage(channelType, message, targets); + + RecycleMessage(message); + return false; +} diff --git a/Source/Engine/Networking/NetworkHost.h b/Source/Engine/Networking/NetworkHost.h index dae0f99fd..d22820082 100644 --- a/Source/Engine/Networking/NetworkHost.h +++ b/Source/Engine/Networking/NetworkHost.h @@ -2,15 +2,19 @@ #pragma once +#include "Engine/Scripting/ScriptingType.h" +#include "Engine/Scripting/ScriptingObjectReference.h" #include "Types.h" #include "NetworkConfig.h" #include "Engine/Core/Collections/Array.h" -struct FLAXENGINE_API NetworkHost +API_CLASS(sealed, NoSpawn, Namespace="FlaxEngine.Networking") class FLAXENGINE_API NetworkHost final : public PersistentScriptingObject { +DECLARE_SCRIPTING_TYPE_NO_SPAWN(NetworkHost); + friend class NetworkManager; public: - int HostId; + int HostId = -1; NetworkConfig Config; INetworkDriver* NetworkDriver = nullptr; @@ -18,14 +22,59 @@ public: Array MessagePool; public: + NetworkHost() : PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) + { + } + +private: void Initialize(const NetworkConfig& config); void Shutdown(); + +private: void CreateMessageBuffers(); void DisposeMessageBuffers(); + +public: + API_FUNCTION() + bool Listen(); + API_FUNCTION() + bool Connect(); + + API_FUNCTION() + void Disconnect(); + + API_FUNCTION() + void Disconnect(const NetworkConnection& connection); + + API_FUNCTION() + bool PopEvent(API_PARAM(out) NetworkEvent& eventRef); + + API_FUNCTION() + NetworkMessage CreateMessage(); + + API_FUNCTION() + void RecycleMessage(const NetworkMessage& message); + + API_FUNCTION() + NetworkMessage BeginSendMessage(); + + API_FUNCTION() + void AbortSendMessage(const NetworkMessage& message); + + API_FUNCTION() + bool EndSendMessage(NetworkChannelType channelType, const NetworkMessage& message); + + API_FUNCTION() + bool EndSendMessage(NetworkChannelType channelType, const NetworkMessage& message, const NetworkConnection& target); + + API_FUNCTION() + bool EndSendMessage(NetworkChannelType channelType, const NetworkMessage& message, Array targets); + +public: bool IsValid() const { - return NetworkDriver != nullptr; + return NetworkDriver != nullptr && HostId >= 0; } uint8* GetMessageBuffer(const uint32 messageId) const diff --git a/Source/Engine/Networking/NetworkManager.cpp b/Source/Engine/Networking/NetworkManager.cpp index 4ac75b537..eb2991715 100644 --- a/Source/Engine/Networking/NetworkManager.cpp +++ b/Source/Engine/Networking/NetworkManager.cpp @@ -4,21 +4,17 @@ #include "NetworkMessage.h" #include "NetworkConfig.h" -#include "NetworkConnection.h" -#include "INetworkDriver.h" -#include "NetworkEvent.h" #include "NetworkHost.h" #include "Engine/Core/Log.h" #include "Engine/Core/Collections/Array.h" -#include "Engine/Core/Math/Math.h" namespace { - Array Hosts; + Array Hosts; } -int NetworkManager::Initialize(const NetworkConfig& config) +NetworkHost* NetworkManager::CreateHost(const NetworkConfig& config) { // Validate the address for listen/connect NetworkEndPoint endPoint = {}; @@ -27,142 +23,23 @@ int NetworkManager::Initialize(const NetworkConfig& config) // Alloc new host const int hostId = Hosts.Count(); // TODO: Maybe keep the host count under a limit? Maybe some drivers do not support this? - Hosts.Add(NetworkHost()); - NetworkHost& host = Hosts.Last(); - host.HostId = hostId; + // TODO: Reuse host ids + Hosts.Add(New()); + NetworkHost* host = Hosts.Last(); + host->HostId = hostId; // Initialize the host - host.Initialize(config); + host->Initialize(config); - return hostId; + return host; } -void NetworkManager::Shutdown(const int hostId) +void NetworkManager::ShutdownHost(NetworkHost* host) { - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - host.Shutdown(); + ASSERT(host->IsValid()); + host->Shutdown(); + Hosts[host->HostId] = nullptr; + host->HostId = -1; + // Hosts.Remove(host); // Do not remove hosts, because we need to keep the array unmodified to make the id's work } - -bool NetworkManager::Listen(const int hostId) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - - LOG(Info, "NetworkManager starting to listen on address = {0}:{1}", host.Config.Address, host.Config.Port); - - return host.NetworkDriver->Listen(); -} - -bool NetworkManager::Connect(const int hostId) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - LOG(Info, "Connecting to {0}:{1}...", host.Config.Address, host.Config.Port); - - return host.NetworkDriver->Connect(); -} - -void NetworkManager::Disconnect(const int hostId) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - LOG(Info, "Disconnecting..."); - - host.NetworkDriver->Disconnect(); -} - -void NetworkManager::Disconnect(const int hostId, const NetworkConnection& connection) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - LOG(Info, "Disconnecting connection with id = {0}...", connection.ConnectionId); - - host.NetworkDriver->Disconnect(connection); -} - -bool NetworkManager::PopEvent(const int hostId, NetworkEvent& eventPtr) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - - // Set host id of the event - eventPtr.HostId = hostId; - - return host.NetworkDriver->PopEvent(&eventPtr); -} - -NetworkMessage NetworkManager::CreateMessage(const int hostId) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - ASSERT(host.MessagePool.Count() > 0); - - const uint32 messageId = host.MessagePool.Pop(); - uint8* messageBuffer = host.GetMessageBuffer(messageId); - - return NetworkMessage(messageBuffer, messageId, host.Config.MessageSize, 0, 0); -} - -void NetworkManager::RecycleMessage(const int hostId, const NetworkMessage& message) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - ASSERT(message.IsValid()); -#ifdef BUILD_DEBUG - ASSERT(host.MessagePool.Contains(message.MessageId) == false); -#endif - - // Return the message id - host.MessagePool.Push(message.MessageId); -} - -NetworkMessage NetworkManager::BeginSendMessage(const int hostId) -{ - ASSERT(Hosts[hostId].IsValid()); - return CreateMessage(hostId); -} - -void NetworkManager::AbortSendMessage(const int hostId, const NetworkMessage& message) -{ - ASSERT(Hosts[hostId].IsValid()); - ASSERT(message.IsValid()); - RecycleMessage(hostId, message); -} - -bool NetworkManager::EndSendMessage(const int hostId, const NetworkChannelType channelType, const NetworkMessage& message) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - ASSERT(message.IsValid()); - - host.NetworkDriver->SendMessage(channelType, message); - - RecycleMessage(hostId, message); - return false; -} - -bool NetworkManager::EndSendMessage(const int hostId, const NetworkChannelType channelType, const NetworkMessage& message, const NetworkConnection& target) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - ASSERT(message.IsValid()); - - host.NetworkDriver->SendMessage(channelType, message, target); - - RecycleMessage(hostId, message); - return false; -} - -bool NetworkManager::EndSendMessage(const int hostId, const NetworkChannelType channelType, const NetworkMessage& message, const Array targets) -{ - ASSERT(Hosts[hostId].IsValid()); - NetworkHost& host = Hosts[hostId]; - ASSERT(message.IsValid()); - - host.NetworkDriver->SendMessage(channelType, message, targets); - - RecycleMessage(hostId, message); - return false; -} diff --git a/Source/Engine/Networking/NetworkManager.h b/Source/Engine/Networking/NetworkManager.h index 79289398a..fe7f07444 100644 --- a/Source/Engine/Networking/NetworkManager.h +++ b/Source/Engine/Networking/NetworkManager.h @@ -5,32 +5,14 @@ #include "Engine/Scripting/ScriptingType.h" #include "Types.h" +class NetworkHost; + API_CLASS(Namespace="FlaxEngine.Networking", Static) class FLAXENGINE_API NetworkManager { DECLARE_SCRIPTING_TYPE_NO_SPAWN(NetworkManager); public: - API_FUNCTION() static int Initialize(const NetworkConfig& config); - API_FUNCTION() static void Shutdown(int hostId); - - API_FUNCTION() static bool Listen(int hostId); - API_FUNCTION() static bool Connect(int hostId); - API_FUNCTION() static void Disconnect(int hostId); - API_FUNCTION() static void Disconnect(int hostId, const NetworkConnection& connection); - - API_FUNCTION() static bool PopEvent(int hostId, API_PARAM(out) NetworkEvent& eventPtr); - - API_FUNCTION() static NetworkMessage CreateMessage(int hostId); - API_FUNCTION() static void RecycleMessage(int hostId, const NetworkMessage& message); - - API_FUNCTION() static NetworkMessage BeginSendMessage(int hostId); - API_FUNCTION() static void AbortSendMessage(int hostId, const NetworkMessage& message); - API_FUNCTION() static bool EndSendMessage(int hostId, NetworkChannelType channelType, const NetworkMessage& message); - API_FUNCTION() static bool EndSendMessage(int hostId, NetworkChannelType channelType, const NetworkMessage& message, const NetworkConnection& target); - API_FUNCTION() static bool EndSendMessage(int hostId, NetworkChannelType channelType, const NetworkMessage& message, Array targets); - - // TODO: Stats API - // TODO: Simulation API - // TODO: Optimize 'targets' in EndSendMessage + API_FUNCTION() static NetworkHost* CreateHost(const NetworkConfig& config); + API_FUNCTION() static void ShutdownHost(NetworkHost* host); };