Refactor most NetworkManager functionality into NetworkHost

This commit is contained in:
Damian Korczowski
2021-06-18 20:43:17 +02:00
parent f40bb309d5
commit 040c024dff
7 changed files with 177 additions and 168 deletions

View File

@@ -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 <enet/enet.h>
#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<uint32_t, void*>();
@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<ENetDriver>();
NetworkDriver->Initialize(Config);
NetworkDriver->Initialize(this, Config);
LOG(Info, "NetworkManager initialized using driver = {0}", static_cast<int>(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<NetworkConnection> targets)
{
ASSERT(message.IsValid());
NetworkDriver->SendMessage(channelType, message, targets);
RecycleMessage(message);
return false;
}

View File

@@ -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<uint32, HeapAllocation> 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<NetworkConnection, HeapAllocation> targets);
public:
bool IsValid() const
{
return NetworkDriver != nullptr;
return NetworkDriver != nullptr && HostId >= 0;
}
uint8* GetMessageBuffer(const uint32 messageId) const

View File

@@ -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<NetworkHost, HeapAllocation> Hosts;
Array<NetworkHost*, HeapAllocation> 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>());
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<NetworkConnection> targets)
{
ASSERT(Hosts[hostId].IsValid());
NetworkHost& host = Hosts[hostId];
ASSERT(message.IsValid());
host.NetworkDriver->SendMessage(channelType, message, targets);
RecycleMessage(hostId, message);
return false;
}

View File

@@ -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<NetworkConnection, HeapAllocation> 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);
};