diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/ForgeNetworkMediator.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/ForgeNetworkMediator.cs index 93f46038..dd48cf60 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/ForgeNetworkMediator.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/ForgeNetworkMediator.cs @@ -91,12 +91,12 @@ public void SendReliableMessage(IMessage message) public void SendReliableMessage(IMessage message, INetPlayer player) { - MessageBus.SendMessage(message, SocketFacade.ManagedSocket, player.EndPoint); + MessageBus.SendReliableMessage(message, SocketFacade.ManagedSocket, player.EndPoint); } public void SendReliableMessage(IMessage message, EndPoint endpoint) { - MessageBus.SendMessage(message, SocketFacade.ManagedSocket, endpoint); + MessageBus.SendReliableMessage(message, SocketFacade.ManagedSocket, endpoint); } } } diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessage.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessage.cs index 84d844fc..e4931955 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessage.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessage.cs @@ -1,4 +1,4 @@ -using Forge.Serialization; +using Forge.Serialization; namespace Forge.Networking.Messaging { @@ -9,8 +9,17 @@ public abstract class ForgeMessage : IMessage public abstract IMessageInterpreter Interpreter { get; } public abstract void Serialize(BMSByte buffer); public abstract void Deserialize(BMSByte buffer); + public bool IsPooled { get; set; } = false; + public bool IsBuffered { get; set; } = false; + public bool IsSent { get; set; } = false; public void Sent() { + IsSent = true; + OnMessageSent?.Invoke(this); + } + public void Unbuffered() + { + IsBuffered = false; OnMessageSent?.Invoke(this); } } diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageBus.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageBus.cs index 9b25faed..73d25283 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageBus.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageBus.cs @@ -70,8 +70,8 @@ public void SendMessage(IMessage message, ISocket sender, EndPoint receiver) public IMessageReceiptSignature SendReliableMessage(IMessage message, ISocket sender, EndPoint receiver) { message.Receipt = AbstractFactory.Get().GetNew(); - SendMessage(message, sender, receiver); _messageRepeater.AddMessageToRepeat(message, receiver); + SendMessage(message, sender, receiver); return message.Receipt; } diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageCodes.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageCodes.cs index c8afe777..a16569ce 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageCodes.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageCodes.cs @@ -53,6 +53,20 @@ public static int GetCodeFromType(Type type) return code; } + /// + /// Instantiate a message of Type T + /// + /// + /// var dieMsg = ForgeMessageCodes.Instantiate(); + /// + /// + /// + public static T Instantiate() + { + int code = GetCodeFromType(typeof(T)); + return (T)Instantiate(code); + } + public static void Clear() { _messageTypes.Clear(); diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageRepository.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageRepository.cs index eebbb2a6..be45a6ab 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageRepository.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/ForgeMessageRepository.cs @@ -30,6 +30,7 @@ public void Clear() lock (_messages) { _messages.Clear(); + // TODO: Need to unbuffer the messages, otherwise they will never return to message pool } } @@ -74,6 +75,7 @@ public void AddMessage(IMessage message, EndPoint sender) kv = new Dictionary(); _messages.Add(sender, kv); } + message.IsBuffered = true; kv.Add(message.Receipt, message); } } @@ -104,11 +106,24 @@ public void AddMessage(IMessage message, EndPoint sender, int ttlMilliseconds) public void RemoveAllFor(EndPoint sender) { + var copy = new List(); + lock (_messages) { var removals = new List(); + if (_messages.TryGetValue(sender, out var kv)) + { + foreach (var mkv in kv) + copy.Add(mkv.Value); + } _messages.Remove(sender); } + + try + { + foreach (var m in copy) m.Unbuffered(); + } + catch { } } public void RemoveMessage(EndPoint sender, IMessage message) @@ -127,7 +142,14 @@ private void RemoveFromMessageLookup(EndPoint sender, IMessageReceiptSignature r lock (_messages) { if (_messages.TryGetValue(sender, out var kv)) + { + try + { + kv[receipt].Unbuffered(); + } + catch { } // Catch just in case message already removed kv.Remove(receipt); + } } } diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/IMessage.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/IMessage.cs index c2111ffa..3660822d 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/IMessage.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/IMessage.cs @@ -1,4 +1,4 @@ -using Forge.Serialization; +using Forge.Serialization; namespace Forge.Networking.Messaging { @@ -12,5 +12,9 @@ public interface IMessage void Serialize(BMSByte buffer); void Deserialize(BMSByte buffer); void Sent(); + void Unbuffered(); + bool IsPooled { get; set; } + bool IsBuffered { get; set; } + bool IsSent { get; set; } } } diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/MessagePoolMulti.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/MessagePoolMulti.cs index e2c7040e..1a76e2e1 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/MessagePoolMulti.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Messaging/MessagePoolMulti.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; namespace Forge.Networking.Messaging { public class MessagePoolMulti { - private readonly Dictionary> _messagePools = new Dictionary>(); + private readonly Dictionary> _messagePools = new Dictionary>(); public IMessage Get(Type t) { @@ -13,7 +14,16 @@ public IMessage Get(Type t) if (pool.Count == 0) return CreateNewMessageForPool(t, pool); else - return pool.Dequeue(); + { + // Try to dequeue, but if locked default to create new + IMessage item; + if (pool.TryDequeue(out item)) + { + item.IsPooled = false; + return item; + } + else return CreateNewMessageForPool(t, pool); + } } public T Get() where T : IMessage, new() @@ -22,27 +32,36 @@ public IMessage Get(Type t) if (pool.Count == 0) return CreateNewMessageForPool(pool); else - return (T)pool.Dequeue(); + { + // Try to dequeue, but if locked default to create new + IMessage item; + if (pool.TryDequeue(out item)) + { + item.IsPooled = false; + return (T)item; + } + else return CreateNewMessageForPool(pool); + } } - private Queue GetPool(Type type) + private ConcurrentQueue GetPool(Type type) { if (!_messagePools.TryGetValue(type, out var pool)) { - pool = new Queue(); + pool = new ConcurrentQueue(); _messagePools.Add(type, pool); } return pool; } - private T CreateNewMessageForPool(Queue pool) where T : IMessage, new() + private T CreateNewMessageForPool(ConcurrentQueue pool) where T : IMessage, new() { T m = new T(); m.OnMessageSent += Release; return m; } - private IMessage CreateNewMessageForPool(Type t, Queue pool) + private IMessage CreateNewMessageForPool(Type t, ConcurrentQueue pool) { IMessage m = (IMessage)Activator.CreateInstance(t); m.OnMessageSent += Release; @@ -51,7 +70,12 @@ private IMessage CreateNewMessageForPool(Type t, Queue pool) private void Release(IMessage message) { - Queue pool = GetPool(message.GetType()); + if (message.IsPooled) return; // Message has already been returned to pool + if (!message.IsSent) return; // Message has not been sent, not ready to return to pool + if (message.IsBuffered) return; // Message is still buffered, not ready to return to pool + message.IsSent = false; + message.IsPooled = true; + ConcurrentQueue pool = GetPool(message.GetType()); pool.Enqueue(message); } } diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Sockets/ForgeUDPSocketServerFacade.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Sockets/ForgeUDPSocketServerFacade.cs index 59df53d8..36b1a6e4 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Sockets/ForgeUDPSocketServerFacade.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Networking/Sockets/ForgeUDPSocketServerFacade.cs @@ -45,21 +45,28 @@ public override void ShutDown() base.ShutDown(); } - public void ChallengeSuccess(INetworkMediator netContainer, EndPoint endpoint) + public void ChallengeSuccess(INetworkMediator netContainer, EndPoint endpoint) { INetPlayer player; - ForgeNetworkIdentityMessage netIdentity; + ForgeNetworkIdentityMessage netIdentity = null; lock (_challengedPlayers) { - player = _challengedPlayers.GetPlayer(endpoint); - netContainer.PlayerRepository.AddPlayer(player); - netIdentity = new ForgeNetworkIdentityMessage + if (_challengedPlayers.Exists(endpoint)) // CHANGE: Trap mallicious client sending multiple creates { - Identity = player.Id - }; - _challengedPlayers.RemovePlayer(player); + player = _challengedPlayers.GetPlayer(endpoint); + if (!netContainer.PlayerRepository.Exists(endpoint)) // CHANGE: Check for duplicate + { + netContainer.PlayerRepository.AddPlayer(player); + netIdentity = new ForgeNetworkIdentityMessage + { + Identity = player.Id + }; + } + _challengedPlayers.RemovePlayer(player); + } } - netContainer.MessageBus.SendReliableMessage(netIdentity, ManagedSocket, endpoint); + if (netIdentity != null) + netContainer.MessageBus.SendReliableMessage(netIdentity, ManagedSocket, endpoint); } protected override void ProcessMessageRead(BMSByte buffer, EndPoint sender) @@ -83,13 +90,26 @@ protected override void ProcessMessageRead(BMSByte buffer, EndPoint sender) private void CreatePlayer(object state) { + bool sendChallenge = false; var sender = (EndPoint)state; - var newPlayer = AbstractFactory.Get().GetNew(); - newPlayer.EndPoint = sender; - newPlayer.LastCommunication = DateTime.Now; - _challengedPlayers.AddPlayer(newPlayer); - var challengeMessage = AbstractFactory.Get().GetNew(); - networkMediator.MessageBus.SendReliableMessage(challengeMessage, ManagedSocket, sender); + + lock (_challengedPlayers) // CHANGE: Need to lock because this runs on different thread + { + if (!_challengedPlayers.Exists(sender)) // CHANGE: ProcessMessageRead may run multiple times CreatePlayer and call this multiple times before the player gets created. + { + var newPlayer = AbstractFactory.Get().GetNew(); + newPlayer.EndPoint = sender; + newPlayer.LastCommunication = DateTime.Now; + _challengedPlayers.AddPlayer(newPlayer); + sendChallenge = true; + } + } + + if (sendChallenge) + { + var challengeMessage = AbstractFactory.Get().GetNew(); + networkMediator.MessageBus.SendReliableMessage(challengeMessage, ManagedSocket, sender); + } } protected void ProcessPlayerMessageRead(INetPlayer player, BMSByte buffer) diff --git a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Serialization/BMSBytePool.cs b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Serialization/BMSBytePool.cs index cb17bf10..14ea48fa 100644 --- a/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Serialization/BMSBytePool.cs +++ b/ForgeAlloy/ForgeAlloyUnity/Assets/ForgeNetworking/Serialization/BMSBytePool.cs @@ -8,37 +8,51 @@ public class BMSBytePool private const int APPROX_SIZE_ZONE = 128; private readonly List _availableBuffers = new List(); private readonly List _inUseBuffers = new List(); + private System.Object syncLock = new object(); public BMSByte Get(int size) { - if (_availableBuffers.Count == 0) - return CreateNewBuffer(size); - else + BMSByte buff; + + lock (syncLock) { - BMSByte buff = GetAvailableBuffer(size); - if (buff.byteArr.Length < size) - buff.SetArraySize(size); - return buff; + if (_availableBuffers.Count == 0) + buff = CreateNewBuffer(size); + else + { + buff = GetAvailableBuffer(size); + if (buff.byteArr.Length < size) + buff.SetArraySize(size); + } } + return buff; } public void Release(BMSByte buffer) { // TODO: Figure out why _inUseBuffers.Remove(buffer) is returning false bool found = false; - for (int i = 0; i < _inUseBuffers.Count; i++) + + lock (syncLock) { - if (_inUseBuffers[i] == buffer) + for (int i = 0; i < _inUseBuffers.Count; i++) { - _inUseBuffers.RemoveAt(i); - found = true; - break; + if (_inUseBuffers[i] == buffer) + { + _inUseBuffers.RemoveAt(i); + found = true; + break; + } + } + if (found) + { + _availableBuffers.Add(buffer); + buffer.Clear(); } } if (!found) throw new BMSBytePoolReleaseUnmanagedBufferException(); - _availableBuffers.Add(buffer); - buffer.Clear(); + } private BMSByte GetAvailableBuffer(int size) diff --git a/ForgeAlloy/ForgeNatHolePunch/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs b/ForgeAlloy/ForgeNatHolePunch/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs new file mode 100644 index 00000000..cc083fe5 --- /dev/null +++ b/ForgeAlloy/ForgeNatHolePunch/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v3.0", FrameworkDisplayName = "")] diff --git a/ForgeAlloy/ForgeNatHolePunch/obj/Release/netcoreapp3.0/ForgeNatHolePunch.AssemblyInfo.cs b/ForgeAlloy/ForgeNatHolePunch/obj/Release/netcoreapp3.0/ForgeNatHolePunch.AssemblyInfo.cs new file mode 100644 index 00000000..8caeb7d8 --- /dev/null +++ b/ForgeAlloy/ForgeNatHolePunch/obj/Release/netcoreapp3.0/ForgeNatHolePunch.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("ForgeNatHolePunch")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("ForgeNatHolePunch")] +[assembly: System.Reflection.AssemblyTitleAttribute("ForgeNatHolePunch")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/ForgeAlloy/ForgeSampleGameServer/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs b/ForgeAlloy/ForgeSampleGameServer/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs new file mode 100644 index 00000000..cc083fe5 --- /dev/null +++ b/ForgeAlloy/ForgeSampleGameServer/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v3.0", FrameworkDisplayName = "")] diff --git a/ForgeAlloy/ForgeSampleGameServer/obj/Release/netcoreapp3.0/ForgeSampleGameServer.AssemblyInfo.cs b/ForgeAlloy/ForgeSampleGameServer/obj/Release/netcoreapp3.0/ForgeSampleGameServer.AssemblyInfo.cs new file mode 100644 index 00000000..0fc20923 --- /dev/null +++ b/ForgeAlloy/ForgeSampleGameServer/obj/Release/netcoreapp3.0/ForgeSampleGameServer.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("ForgeSampleGameServer")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("ForgeSampleGameServer")] +[assembly: System.Reflection.AssemblyTitleAttribute("ForgeSampleGameServer")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/ForgeAlloy/ForgeServerRegistryService/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs b/ForgeAlloy/ForgeServerRegistryService/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs new file mode 100644 index 00000000..cc083fe5 --- /dev/null +++ b/ForgeAlloy/ForgeServerRegistryService/obj/Release/netcoreapp3.0/.NETCoreApp,Version=v3.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v3.0", FrameworkDisplayName = "")] diff --git a/ForgeAlloy/ForgeServerRegistryService/obj/Release/netcoreapp3.0/ForgeServerRegistryService.AssemblyInfo.cs b/ForgeAlloy/ForgeServerRegistryService/obj/Release/netcoreapp3.0/ForgeServerRegistryService.AssemblyInfo.cs new file mode 100644 index 00000000..12f437a2 --- /dev/null +++ b/ForgeAlloy/ForgeServerRegistryService/obj/Release/netcoreapp3.0/ForgeServerRegistryService.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("ForgeServerRegistryService")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("ForgeServerRegistryService")] +[assembly: System.Reflection.AssemblyTitleAttribute("ForgeServerRegistryService")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. +