Fix ENet network driver to use 3 separate channels for different packet types
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user