diff --git a/Source/Engine/Networking/Drivers/ENetDriver.cpp b/Source/Engine/Networking/Drivers/ENetDriver.cpp index d21c3e097..9130d28ee 100644 --- a/Source/Engine/Networking/Drivers/ENetDriver.cpp +++ b/Source/Engine/Networking/Drivers/ENetDriver.cpp @@ -5,6 +5,7 @@ #include "ENetDriver.h" #include "Engine/Networking/NetworkConfig.h" +#include "Engine/Networking/NetworkChannelType.h" #include "Engine/Networking/NetworkEvent.h" #include "Engine/Networking/NetworkManager.h" @@ -17,6 +18,40 @@ #undef _WINSOCK_DEPRECATED_NO_WARNINGS #undef SendMessage +ENetPacketFlag ChannelTypeToPacketFlag(const NetworkChannelType channel) +{ + int flag = 0; // Maybe use ENET_PACKET_FLAG_NO_ALLOCATE? + + // Add reliable flag when it is "reliable" channel + if(channel > NetworkChannelType::UnreliableOrdered) + flag |= ENET_PACKET_FLAG_RELIABLE; + + // Use unsequenced flag when the flag is unreliable. We have to sequence all other packets. + 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(flag); +} + +void SendPacketToPeer(ENetPeer* peer, const NetworkChannelType channelType, const NetworkMessage& message) +{ + // Covert our channel type to the internal ENet packet flags + const ENetPacketFlag flag = ChannelTypeToPacketFlag(channelType); + + // This will copy the data into the packet when ENET_PACKET_FLAG_NO_ALLOCATE is not set. + // Tho, we cannot use it, because we're releasing the message right after the send - and the packet might not + // be sent, yet. To avoid data corruption, we're just using the copy method. We might fix that later, but I'll take + // the smaller risk. + ENetPacket* packet = enet_packet_create(message.Buffer, message.Length, flag); + + // And send it! + enet_peer_send (peer, 0, packet); + + // 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) { _config = config; @@ -117,7 +152,7 @@ bool ENetDriver::PopEvent(NetworkEvent* eventPtr) { case ENET_EVENT_TYPE_CONNECT: eventPtr->EventType = NetworkEventType::Connected; - LOG(Info, "Connected"); // TODO + LOG(Info, "Connected. Peer id={0}", enet_peer_get_id(event.peer)); // TODO break; case ENET_EVENT_TYPE_DISCONNECT: eventPtr->EventType = NetworkEventType::Disconnected; @@ -146,6 +181,11 @@ bool ENetDriver::PopEvent(NetworkEvent* eventPtr) return false; // No events } +void ENetDriver::SendMessage(const NetworkChannelType channelType, const NetworkMessage& message) +{ + SendPacketToPeer((ENetPeer*)_peer, channelType, message); +} + void ENetDriver::SendMessage(NetworkChannelType channelType, const NetworkMessage& message, Array targets) { // TODO: Send messages diff --git a/Source/Engine/Networking/Drivers/ENetDriver.h b/Source/Engine/Networking/Drivers/ENetDriver.h index 2b1ce9cd5..bb105079a 100644 --- a/Source/Engine/Networking/Drivers/ENetDriver.h +++ b/Source/Engine/Networking/Drivers/ENetDriver.h @@ -22,6 +22,7 @@ public: bool PopEvent(NetworkEvent* eventPtr) override; + void SendMessage(NetworkChannelType channelType, const NetworkMessage& message) override; void SendMessage(NetworkChannelType channelType, const NetworkMessage& message, Array targets) override; private: diff --git a/Source/Engine/Networking/INetworkDriver.h b/Source/Engine/Networking/INetworkDriver.h index 412f5f0dc..34abc69f7 100644 --- a/Source/Engine/Networking/INetworkDriver.h +++ b/Source/Engine/Networking/INetworkDriver.h @@ -18,6 +18,7 @@ public: virtual bool PopEvent(NetworkEvent* eventPtr) = 0; + virtual void SendMessage(NetworkChannelType channelType, const NetworkMessage& message) = 0; virtual void SendMessage(NetworkChannelType channelType, const NetworkMessage& message, Array targets) = 0; // TODO: Stats API diff --git a/Source/Engine/Networking/NetworkManager.cpp b/Source/Engine/Networking/NetworkManager.cpp index 03221b494..ba92adb3a 100644 --- a/Source/Engine/Networking/NetworkManager.cpp +++ b/Source/Engine/Networking/NetworkManager.cpp @@ -125,6 +125,18 @@ void NetworkManager::AbortSendMessage(const int hostId, const NetworkMessage& me 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 Array targets) { ASSERT(Hosts[hostId].IsValid()); diff --git a/Source/Engine/Networking/NetworkManager.h b/Source/Engine/Networking/NetworkManager.h index ddfd222e3..ccc4b8809 100644 --- a/Source/Engine/Networking/NetworkManager.h +++ b/Source/Engine/Networking/NetworkManager.h @@ -25,6 +25,7 @@ public: 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, Array targets); // TODO: Stats API diff --git a/Source/Engine/Networking/NetworkMessage.cs b/Source/Engine/Networking/NetworkMessage.cs index 6e5ce3765..3b11eb18b 100644 --- a/Source/Engine/Networking/NetworkMessage.cs +++ b/Source/Engine/Networking/NetworkMessage.cs @@ -1,17 +1,19 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.Networking { public unsafe partial struct NetworkMessage { public void WriteBytes(byte* bytes, int length) { - // TODO + Utils.MemoryCopy(new IntPtr(bytes), new IntPtr(Buffer), length); } public void ReadBytes(byte* buffer, int length) { - // TODO + Utils.MemoryCopy(new IntPtr(Buffer), new IntPtr(buffer), length); } public void WriteUInt32(uint value)