Fix ENet network driver to use 3 separate channels for different packet types

This commit is contained in:
2026-09-07 11:46:58 +02:00
parent 5fb99ffe2d
commit bfd603169b
3 changed files with 38 additions and 13 deletions
@@ -10,6 +10,7 @@
#include "Engine/Networking/NetworkStats.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Profiler/ProfilerCPU.h"
#define ENET_IMPLEMENTATION
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <enet/enet.h>
@@ -25,14 +26,34 @@ ENetPacketFlag ChannelTypeToPacketFlag(const NetworkChannelType channel)
flag |= ENET_PACKET_FLAG_RELIABLE;
// Use unsequenced flag when the flag is unreliable. We have to sequence all other packets.
// Note: ENet has no "unreliable ordered" channel type, so we have to use reliable for that.
if (channel == NetworkChannelType::Unreliable)
flag |= ENET_PACKET_FLAG_UNSEQUENCED;
// Note that all reliable channels are exactly the same. TODO: How to handle unordered reliable packets...?
return static_cast<ENetPacketFlag>(flag);
}
// Unreliable - 0
// UnreliableOrdered - 1
// Reliable/ReliableOrdered - 2
#define ENET_CHANNEL_COUNT 3
enet_uint8 ChannelTypeToChannelIndex(const NetworkChannelType channel)
{
switch (channel)
{
case NetworkChannelType::Unreliable:
return 0;
case NetworkChannelType::UnreliableOrdered:
return 1;
case NetworkChannelType::Reliable:
case NetworkChannelType::ReliableOrdered:
return 2;
default:
return 0;
}
}
void SendPacketToPeer(ENetPeer* peer, const NetworkChannelType channelType, const NetworkMessage& message)
{
// Covert our channel type to the internal ENet packet flags
@@ -45,7 +66,7 @@ void SendPacketToPeer(ENetPeer* peer, const NetworkChannelType channelType, cons
ENetPacket* packet = enet_packet_create(message.Buffer, message.Position, flag);
// And send it!
enet_peer_send(peer, 0, packet);
enet_peer_send(peer, ChannelTypeToChannelIndex(channelType), packet);
// TODO: To reduce latency, we can use `enet_host_flush` to flush all packets. Maybe some API, like NetworkManager::FlushQueues()?
}
@@ -57,6 +78,7 @@ ENetDriver::ENetDriver(const SpawnParams& params)
bool ENetDriver::Initialize(NetworkPeer* host, const NetworkConfig& config)
{
PROFILE_CPU();
_networkHost = host;
_config = config;
_peerMap.Clear();
@@ -73,6 +95,7 @@ bool ENetDriver::Initialize(NetworkPeer* host, const NetworkConfig& config)
void ENetDriver::Dispose()
{
PROFILE_CPU();
if (_peer)
enet_peer_disconnect_now(_peer, 0);
enet_host_destroy(_host);
@@ -89,6 +112,7 @@ void ENetDriver::Dispose()
bool ENetDriver::Listen()
{
PROFILE_CPU();
ENetAddress address = { 0 };
address.port = _config.Port;
address.host = ENET_HOST_ANY;
@@ -98,7 +122,7 @@ bool ENetDriver::Listen()
enet_address_set_host(&address, _config.Address.ToStringAnsi().GetText());
// Create ENet host
_host = enet_host_create(&address, _config.ConnectionsLimit, 1, 0, 0);
_host = enet_host_create(&address, _config.ConnectionsLimit, ENET_CHANNEL_COUNT, 0, 0);
if (_host == nullptr)
{
LOG(Error, "Failed to initialize ENet host!");
@@ -111,6 +135,7 @@ bool ENetDriver::Listen()
bool ENetDriver::Connect()
{
PROFILE_CPU();
LOG(Info, "Connecting using ENet...");
ENetAddress address = { 0 };
@@ -118,7 +143,7 @@ bool ENetDriver::Connect()
enet_address_set_host(&address, _config.Address.ToStringAnsi().GetText());
// Create ENet host
_host = enet_host_create(nullptr, 1, 1, 0, 0);
_host = enet_host_create(nullptr, 1, ENET_CHANNEL_COUNT, 0, 0);
if (_host == nullptr)
{
LOG(Error, "Failed to initialize ENet host!");
@@ -126,7 +151,7 @@ bool ENetDriver::Connect()
}
// Create ENet peer/connect to the server
_peer = enet_host_connect(_host, &address, 1, 0);
_peer = enet_host_connect(_host, &address, ENET_CHANNEL_COUNT, 0);
if (_peer == nullptr)
{
LOG(Error, "Failed to create ENet host!");
@@ -139,6 +164,7 @@ bool ENetDriver::Connect()
void ENetDriver::Disconnect()
{
PROFILE_CPU();
if (_peer)
{
enet_peer_disconnect_now(_peer, 0);
@@ -149,6 +175,7 @@ void ENetDriver::Disconnect()
void ENetDriver::Disconnect(const NetworkConnection& connection)
{
PROFILE_CPU();
const int connectionId = connection.ConnectionId;
ENetPeer* peer;
if (_peerMap.TryGet(connectionId, peer))
@@ -164,6 +191,7 @@ void ENetDriver::Disconnect(const NetworkConnection& connection)
bool ENetDriver::PopEvent(NetworkEvent& eventPtr)
{
PROFILE_CPU();
ASSERT(_host);
ENetEvent event;
const int result = enet_host_service(_host, &event, 0);
@@ -215,12 +243,14 @@ bool ENetDriver::PopEvent(NetworkEvent& eventPtr)
void ENetDriver::SendMessage(const NetworkChannelType channelType, const NetworkMessage& message)
{
PROFILE_CPU();
ASSERT(!IsServer());
SendPacketToPeer(_peer, channelType, message);
}
void ENetDriver::SendMessage(NetworkChannelType channelType, const NetworkMessage& message, NetworkConnection target)
{
PROFILE_CPU();
ASSERT(IsServer());
ENetPeer* peer;
if (_peerMap.TryGet(target.ConnectionId, peer) && peer && peer->state == ENET_PEER_STATE_CONNECTED)
@@ -231,6 +261,7 @@ void ENetDriver::SendMessage(NetworkChannelType channelType, const NetworkMessag
void ENetDriver::SendMessage(const NetworkChannelType channelType, const NetworkMessage& message, const Array<NetworkConnection, HeapAllocation>& targets)
{
PROFILE_CPU();
ASSERT(IsServer());
ENetPeer* peer;
for (NetworkConnection target : targets)
+1 -1
View File
@@ -141,7 +141,7 @@ NetworkMessage NetworkPeer::CreateMessage()
{
CHECK_RETURN(MessagePool.HasItems(), NetworkMessage());
const uint32 messageId = MessagePool.Pop();
uint8* messageBuffer = GetMessageBuffer(messageId);
uint8* messageBuffer = (uint8*)MessageBuffer + Config.MessageSize * messageId;
return NetworkMessage(messageBuffer, Config.MessageSize, messageId);
}
-6
View File
@@ -144,12 +144,6 @@ public:
return NetworkDriver != nullptr && HostId >= 0;
}
uint8* GetMessageBuffer(const uint32 messageId) const
{
// Calculate and return the buffer slice using previously calculated slice.
return MessageBuffer + Config.MessageSize * messageId;
}
public:
FORCE_INLINE bool operator==(const NetworkPeer& other) const
{