]> git.deb.at Git - rhonda/impostor.git/commitdiff
Refactor messages
authorAeonLucid <aeonlucid@gmail.com>
Mon, 19 Oct 2020 12:39:36 +0000 (14:39 +0200)
committerAeonLucid <aeonlucid@gmail.com>
Mon, 19 Oct 2020 12:39:36 +0000 (14:39 +0200)
39 files changed:
src/Impostor.Api/Games/Extensions/GameExtensions.cs [new file with mode: 0644]
src/Impostor.Api/Games/IGame.cs
src/Impostor.Api/Net/Extensions/GameMessageWriterExtensions.cs [deleted file]
src/Impostor.Api/Net/IConnection.cs
src/Impostor.Api/Net/Messages/IConnectionMessageWriter.cs [deleted file]
src/Impostor.Api/Net/Messages/IGameMessageWriter.cs [deleted file]
src/Impostor.Api/Net/Messages/IMessage.cs [deleted file]
src/Impostor.Api/Net/Messages/IMessageWriter.cs
src/Impostor.Api/Net/Messages/MessageType.cs
src/Impostor.Hazel/Connection.cs
src/Impostor.Hazel/ConnectionListener.cs
src/Impostor.Hazel/DataReceivedEventArgs.cs
src/Impostor.Hazel/DisconnectedEventArgs.cs
src/Impostor.Hazel/Impostor.Hazel.csproj
src/Impostor.Hazel/MessageReader.cs
src/Impostor.Hazel/MessageWriter.cs
src/Impostor.Hazel/NetworkConnection.cs
src/Impostor.Hazel/NewConnectionEventArgs.cs
src/Impostor.Hazel/SendOption.cs [deleted file]
src/Impostor.Hazel/Udp/UdpConnection.Reliable.cs
src/Impostor.Hazel/Udp/UdpConnection.cs
src/Impostor.Hazel/Udp/UdpServerConnection.cs
src/Impostor.Server/Net/Client.cs
src/Impostor.Server/Net/ClientBase.cs
src/Impostor.Server/Net/Hazel/HazelConnection.cs
src/Impostor.Server/Net/Hazel/Messages/BufferMessageReader.cs [deleted file]
src/Impostor.Server/Net/Hazel/Messages/HazelConnectionMessageWriter.cs [deleted file]
src/Impostor.Server/Net/Hazel/Messages/HazelGameMessageWriter.cs [deleted file]
src/Impostor.Server/Net/Hazel/Messages/HazelMessage.cs [deleted file]
src/Impostor.Server/Net/Hazel/Messages/HazelMessageWriter.cs [deleted file]
src/Impostor.Server/Net/Manager/ClientManager.cs
src/Impostor.Server/Net/Redirector/ClientRedirector.cs
src/Impostor.Server/Net/State/Game.Api.cs
src/Impostor.Server/Net/State/Game.Incoming.cs
src/Impostor.Server/Net/State/Game.Outgoing.cs
src/Impostor.Server/Net/State/Game.State.cs
src/Impostor.Server/Net/State/Game.cs
src/Impostor.Tests/Hazel/BufferMessageReaderTests.cs
src/Impostor.Tools.Proxy/Program.cs

diff --git a/src/Impostor.Api/Games/Extensions/GameExtensions.cs b/src/Impostor.Api/Games/Extensions/GameExtensions.cs
new file mode 100644 (file)
index 0000000..a736978
--- /dev/null
@@ -0,0 +1,42 @@
+using System;
+using System.Threading.Tasks;
+using Impostor.Api.Net;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Api.Games
+{
+    public static class GameExtensions
+    {
+        public static ValueTask SendToAllExceptAsync(this IGame game, IMessageWriter writer, LimboStates states, int? id)
+        {
+            return id.HasValue
+                ? game.SendToAllExceptAsync(writer, id.Value, states)
+                : game.SendToAllAsync(writer, states);
+        }
+
+        public static ValueTask SendToAllExceptAsync(this IGame game, IMessageWriter writer, LimboStates states, IClient client)
+        {
+            if (client == null)
+            {
+                throw new ArgumentNullException(nameof(client));
+            }
+
+            return game.SendToAllExceptAsync(writer, client.Id, states);
+        }
+
+        public static ValueTask SendToAsync(this IGame game, IMessageWriter writer, IClient client)
+        {
+            if (client == null)
+            {
+                throw new ArgumentNullException(nameof(client));
+            }
+
+            return game.SendToAsync(writer, client.Id);
+        }
+
+        public static ValueTask SendToAsync(this IGame game, IMessageWriter writer, IClientPlayer player)
+        {
+            return game.SendToAsync(writer, player.Client);
+        }
+    }
+}
\ No newline at end of file
index 6de41f08d52f85655733237da51d84857490dd2d..17fa2b87ed624e6a7ce33c4edb9ccc16e08cb9d9 100644 (file)
@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using System.Net;
+using System.Threading.Tasks;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Data;
 using Impostor.Api.Net;
@@ -29,6 +30,29 @@ namespace Impostor.Api.Games
 
         int HostId { get; }
 
-        IGameMessageWriter CreateMessage(MessageType type);
+        /// <summary>
+        ///     Send the message to all players.
+        /// </summary>
+        /// <param name="writer">Message to send.</param>
+        /// <param name="states">Required limbo state of the player.</param>
+        /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+        ValueTask SendToAllAsync(IMessageWriter writer, LimboStates states = LimboStates.NotLimbo);
+
+        /// <summary>
+        ///     Send the message to all players except one.
+        /// </summary>
+        /// <param name="writer">Message to send.</param>
+        /// <param name="senderId">The player to exclude from sending the message.</param>
+        /// <param name="states">Required limbo state of the player.</param>
+        /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+        ValueTask SendToAllExceptAsync(IMessageWriter writer, int senderId, LimboStates states = LimboStates.NotLimbo);
+
+        /// <summary>
+        ///     Send a message to a specific player.
+        /// </summary>
+        /// <param name="writer">Message to send.</param>
+        /// <param name="id">ID of the client.</param>
+        /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+        ValueTask SendToAsync(IMessageWriter writer, int id);
     }
 }
\ No newline at end of file
diff --git a/src/Impostor.Api/Net/Extensions/GameMessageWriterExtensions.cs b/src/Impostor.Api/Net/Extensions/GameMessageWriterExtensions.cs
deleted file mode 100644 (file)
index 5f90bb5..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using Impostor.Api.Net.Messages;
-
-namespace Impostor.Api.Net
-{
-    public static class GameMessageWriterExtensions
-    {
-        public static ValueTask SendToAllExceptAsync(this IGameMessageWriter writer, LimboStates states, int? id)
-        {
-            return id.HasValue
-                ? writer.SendToAllExceptAsync(id.Value, states)
-                : writer.SendToAllAsync(states);
-        }
-
-        public static ValueTask SendToAllExceptAsync(this IGameMessageWriter writer, LimboStates states, IClient client)
-        {
-            if (client == null)
-            {
-                throw new ArgumentNullException(nameof(client));
-            }
-
-            return writer.SendToAllExceptAsync(client.Id, states);
-        }
-
-        public static ValueTask SendToAsync(this IGameMessageWriter writer, IClient client)
-        {
-            if (client == null)
-            {
-                throw new ArgumentNullException(nameof(client));
-            }
-
-            return writer.SendToAsync(client.Id);
-        }
-
-        public static ValueTask SendToAsync(this IGameMessageWriter writer, IClientPlayer player)
-        {
-            return SendToAsync(writer, player.Client);
-        }
-    }
-}
\ No newline at end of file
index 70edd01e1eb334aa6ad8922fe701dbc20fcb8c56..3c8e1f5ee474cd029c18d1f5254ce0d8944d10ff 100644 (file)
@@ -1,5 +1,5 @@
 using System.Net;
-using Impostor.Api.Games;
+using System.Threading.Tasks;
 using Impostor.Api.Net.Messages;
 
 namespace Impostor.Api.Net
@@ -25,14 +25,10 @@ namespace Impostor.Api.Net
         IClient? Client { get; }
 
         /// <summary>
-        ///     Create a message writer that can be send to the connection.
+        ///     Sends a message writer to the connection.
         /// </summary>
-        /// <remarks>
-        ///     Be aware when implementing a custom connection handler that this method is not called when a message
-        ///     is being send in <see cref="IGame"/>.
-        /// </remarks>
-        /// <param name="messageType">Type of the message.</param>
-        /// <returns>Message writer for the current connection.</returns>
-        IConnectionMessageWriter CreateMessage(MessageType messageType);
+        /// <param name="writer">The message.</param>
+        /// <returns></returns>
+        ValueTask SendAsync(IMessageWriter writer);
     }
 }
\ No newline at end of file
diff --git a/src/Impostor.Api/Net/Messages/IConnectionMessageWriter.cs b/src/Impostor.Api/Net/Messages/IConnectionMessageWriter.cs
deleted file mode 100644 (file)
index 620046c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Threading.Tasks;
-
-namespace Impostor.Api.Net.Messages
-{
-    /// <summary>
-    ///     Represents the message writer for <see cref="IConnection"/>.
-    /// </summary>
-    public interface IConnectionMessageWriter : IMessageWriter
-    {
-        /// <summary>
-        ///     Gets the connection where the message writer belongs to.
-        /// </summary>
-        public IConnection Connection { get; }
-
-        /// <summary>
-        ///     Sends the message to the <see cref="Connection"/>.
-        /// </summary>
-        /// <returns>Task.</returns>
-        ValueTask SendAsync();
-    }
-}
\ No newline at end of file
diff --git a/src/Impostor.Api/Net/Messages/IGameMessageWriter.cs b/src/Impostor.Api/Net/Messages/IGameMessageWriter.cs
deleted file mode 100644 (file)
index 69c286c..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Threading.Tasks;
-using Impostor.Api.Games;
-
-namespace Impostor.Api.Net.Messages
-{
-    /// <summary>
-    ///     Represents the message writer for <see cref="IGame"/>.
-    /// </summary>
-    public interface IGameMessageWriter : IMessageWriter
-    {
-        /// <summary>
-        ///     Send the message to all players.
-        /// </summary>
-        /// <param name="states">Required limbo state of the player.</param>
-        /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
-        ValueTask SendToAllAsync(LimboStates states = LimboStates.NotLimbo);
-
-        /// <summary>
-        ///     Send the message to all players except one.
-        /// </summary>
-        /// <param name="senderId">The player to exclude from sending the message.</param>
-        /// <param name="states">Required limbo state of the player.</param>
-        /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
-        ValueTask SendToAllExceptAsync(int senderId, LimboStates states = LimboStates.NotLimbo);
-
-        /// <summary>
-        ///     Send a message to a specific player.
-        /// </summary>
-        /// <param name="id">ID of the client.</param>
-        /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
-        ValueTask SendToAsync(int id);
-    }
-}
\ No newline at end of file
diff --git a/src/Impostor.Api/Net/Messages/IMessage.cs b/src/Impostor.Api/Net/Messages/IMessage.cs
deleted file mode 100644 (file)
index a7eb63e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Impostor.Api.Net.Messages
-{
-    public interface IMessage
-    {
-        MessageType Type { get; }
-
-        IMessageReader CreateReader();
-    }
-}
\ No newline at end of file
index eb009abbc593627750ac49d2025386790505a4d5..5eb5798704abc08936c81bc3fecbe60d31158585 100644 (file)
@@ -9,6 +9,14 @@ namespace Impostor.Api.Net.Messages
     /// </summary>
     public interface IMessageWriter : IDisposable
     {
+        public byte[] Buffer { get; }
+
+        public int Length { get; set; }
+
+        public int Position { get; set; }
+
+        public MessageType SendOption { get; }
+
         /// <summary>
         ///     Writes a boolean to the message.
         /// </summary>
index 66335eba536ef7058f85dbdc3682491e2addcec9..92fa153857eaf057dd86e8ef3dcb27802d1e7c40 100644 (file)
@@ -1,9 +1,12 @@
-namespace Impostor.Api.Net.Messages
+using System;
+
+namespace Impostor.Api.Net.Messages
 {
     /// <summary>
     ///     Specifies how a message should be sent between connections.
     /// </summary>
-    public enum MessageType
+    [Flags]
+    public enum MessageType : byte
     {
         /// <summary>
         ///     Requests unreliable delivery with no fragmentation.
index 0495cface25827945261bb7519249782392b101c..c2ab579908f745b775563a5a9530d26ba1152d17 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Net;
 using System.Threading.Tasks;
+using Impostor.Api.Net.Messages;
 using Serilog;
 
 namespace Hazel
@@ -127,33 +128,33 @@ namespace Hazel
         }
 
         /// <summary>
-        ///     Sends a number of bytes to the end point of the connection using the specified <see cref="SendOption"/>.
+        ///     Sends a number of bytes to the end point of the connection using the specified <see cref="MessageType"/>.
         /// </summary>
         /// <param name="msg">The message to send.</param>
         /// <remarks>
         ///     <include file="DocInclude/common.xml" path="docs/item[@name='Connection_SendBytes_General']/*" />
         ///     <para>
-        ///         The sendOptions parameter is only a request to use those options and the actual method used to send the
+        ///         The messageType parameter is only a request to use those options and the actual method used to send the
         ///         data is up to the implementation. There are circumstances where this parameter may be ignored but in 
         ///         general any implementer should aim to always follow the user's request.
         ///     </para>
         /// </remarks>
-        public abstract ValueTask Send(MessageWriter msg);
+        public abstract ValueTask Send(IMessageWriter msg);
 
         /// <summary>
-        ///     Sends a number of bytes to the end point of the connection using the specified <see cref="SendOption"/>.
+        ///     Sends a number of bytes to the end point of the connection using the specified <see cref="MessageType"/>.
         /// </summary>
         /// <param name="bytes">The bytes of the message to send.</param>
-        /// <param name="sendOption">The option specifying how the message should be sent.</param>
+        /// <param name="messageType">The option specifying how the message should be sent.</param>
         /// <remarks>
         ///     <include file="DocInclude/common.xml" path="docs/item[@name='Connection_SendBytes_General']/*" />
         ///     <para>
-        ///         The sendOptions parameter is only a request to use those options and the actual method used to send the
+        ///         The messageType parameter is only a request to use those options and the actual method used to send the
         ///         data is up to the implementation. There are circumstances where this parameter may be ignored but in 
         ///         general any implementer should aim to always follow the user's request.
         ///     </para>
         /// </remarks>
-        public abstract ValueTask SendBytes(byte[] bytes, SendOption sendOption = SendOption.None);
+        public abstract ValueTask SendBytes(byte[] bytes, MessageType messageType = MessageType.Unreliable);
         
         /// <summary>
         ///     Connects the connection to a server and begins listening.
@@ -174,13 +175,13 @@ namespace Hazel
         ///     Invokes the DataReceived event.
         /// </summary>
         /// <param name="msg">The bytes received.</param>
-        /// <param name="sendOption">The <see cref="SendOption"/> the message was received with.</param>
+        /// <param name="messageType">The <see cref="MessageType"/> the message was received with.</param>
         /// <remarks>
         ///     Invokes the <see cref="DataReceived"/> event on this connection to alert subscribers a new message has been
         ///     received. The bytes and the send option that the message was sent with should be passed in to give to the
         ///     subscribers.
         /// </remarks>
-        protected async ValueTask InvokeDataReceived(MessageReader msg, SendOption sendOption)
+        protected async ValueTask InvokeDataReceived(IMessageReader msg, MessageType messageType)
         {
             // Make a copy to avoid race condition between null check and invocation
             var handler = DataReceived;
@@ -188,7 +189,7 @@ namespace Hazel
             {
                 try
                 {
-                    await handler(new DataReceivedEventArgs(this, msg, sendOption));
+                    await handler(new DataReceivedEventArgs(this, msg, messageType));
                 }
                 catch (Exception e)
                 {
@@ -208,7 +209,7 @@ namespace Hazel
         ///     by the end point or because an error occurred. If an error occurred the error should be passed in in order to 
         ///     pass to the subscribers, otherwise null can be passed in.
         /// </remarks>
-        protected async ValueTask InvokeDisconnected(string e, MessageReader reader)
+        protected async ValueTask InvokeDisconnected(string e, IMessageReader reader)
         {
             // Make a copy to avoid race condition between null check and invocation
             var handler = Disconnected;
index 156f253d78abcebea73b4f03cdb9d6a5bf054b5b..f595432010856b9893ce24635771b7f7d169555b 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Threading.Tasks;
+using Impostor.Api.Net.Messages;
 using Serilog;
 
 namespace Hazel
@@ -69,7 +70,7 @@ namespace Hazel
         ///     Implementers should call this to invoke the <see cref="NewConnection"/> event before data is received so that
         ///     subscribers do not miss any data that may have been sent immediately after connecting.
         /// </remarks>
-        internal async Task InvokeNewConnection(MessageReader msg, Connection connection)
+        internal async Task InvokeNewConnection(IMessageReader msg, Connection connection)
         {
             // Make a copy to avoid race condition between null check and invocation
             var handler = NewConnection;
index 18432fe8bb3a1cb3f8ef651321f65e8b5d81db6a..7aa824ebf27cd9166a2684086c47e1b3d63d9f54 100644 (file)
@@ -1,4 +1,6 @@
-namespace Hazel
+using Impostor.Api.Net.Messages;
+
+namespace Hazel
 {
     public struct DataReceivedEventArgs
     {
@@ -7,18 +9,18 @@
         /// <summary>
         ///     The bytes received from the client.
         /// </summary>
-        public readonly MessageReader Message;
+        public readonly IMessageReader Message;
 
         /// <summary>
-        ///     The <see cref="SendOption"/> the data was sent with.
+        ///     The <see cref="Type"/> the data was sent with.
         /// </summary>
-        public readonly SendOption SendOption;
+        public readonly MessageType Type;
         
-        public DataReceivedEventArgs(Connection sender, MessageReader msg, SendOption sendOption)
+        public DataReceivedEventArgs(Connection sender, IMessageReader msg, MessageType type)
         {
             this.Sender = sender;
             this.Message = msg;
-            this.SendOption = sendOption;
+            this.Type = type;
         }
     }
 }
index a7fb05cab8967b554ab15dd995d7ac42c119ea4a..a029c7b5af351eeaa7bcd29ee970bdab2c40addd 100644 (file)
@@ -1,4 +1,5 @@
 using System;
+using Impostor.Api.Net.Messages;
 
 namespace Hazel
 {
@@ -13,9 +14,9 @@ namespace Hazel
         /// Optional data sent with a disconnect message. May be null. 
         /// You must not recycle this. If you need the message outside of a callback, you should copy it.
         /// </summary>
-        public readonly MessageReader Message;
+        public readonly IMessageReader Message;
 
-        public DisconnectedEventArgs(string reason, MessageReader message)
+        public DisconnectedEventArgs(string reason, IMessageReader message)
         {
             this.Reason = reason;
             this.Message = message;
index 40ed1886c0cb5a902d91c19a947c9eb10a7fcd71..cf1540095d980c9bf6ee69437f67d08f08079c3e 100644 (file)
@@ -11,4 +11,8 @@
         <PackageReference Include="Serilog" Version="2.10.0" />
     </ItemGroup>
 
+    <ItemGroup>
+      <ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
+    </ItemGroup>
+
 </Project>
index f22042be79e6c97f0091e902e308e7795216b1a8..84e9ff2e48f856590fd3ed31a9af0d9f8cde5d83 100644 (file)
@@ -2,10 +2,11 @@
 using System.Buffers.Binary;
 using System.Runtime.CompilerServices;
 using System.Text;
+using Impostor.Api.Net.Messages;
 
 namespace Hazel
 {
-    public class MessageReader
+    public class MessageReader : IMessageReader
     {
         public byte Tag { get; }
         public ReadOnlyMemory<byte> Buffer { get; }
@@ -24,7 +25,7 @@ namespace Hazel
             Buffer = buffer;
         }
 
-        public MessageReader ReadMessage()
+        public IMessageReader ReadMessage()
         {
             var length = ReadUInt16();
             var tag = ReadByte();
@@ -138,19 +139,19 @@ namespace Hazel
             return output;
         }
 
-        public void CopyTo(MessageWriter writer)
+        public void CopyTo(IMessageWriter writer)
         {
             writer.Write((ushort) Length);
             writer.Write((byte) Tag);
             writer.Write(Buffer);
         }
 
-        public MessageReader Slice(int start)
+        public IMessageReader Slice(int start)
         {
             return new MessageReader(Tag, Buffer.Slice(start));
         }
 
-        public MessageReader Slice(int start, int length)
+        public IMessageReader Slice(int start, int length)
         {
             return new MessageReader(Tag, Buffer.Slice(start, length));
         }
index 099e6144316e7b81a436fde39c27916c0946d7a7..276c174869e9717dc4bc6db7134a9f128e0b0478 100644 (file)
@@ -1,20 +1,19 @@
 using System;
 using System.Collections.Generic;
+using System.Net;
 using System.Text;
+using Impostor.Api.Games;
+using Impostor.Api.Net.Messages;
 
 namespace Hazel
 {
     ///
-    public class MessageWriter : IRecyclable, IDisposable
+    public class MessageWriter : IMessageWriter, IRecyclable, IDisposable
     {
         public static int BufferSize = 64000;
         public static readonly ObjectPool<MessageWriter> WriterPool = new ObjectPool<MessageWriter>(() => new MessageWriter(BufferSize));
 
-        public byte[] Buffer;
-        public int Length;
-        public int Position;
-
-        public SendOption SendOption { get; private set; }
+        public MessageType SendOption { get; private set; }
 
         private Stack<int> messageStarts = new Stack<int>();
         
@@ -24,12 +23,15 @@ namespace Hazel
             this.Length = this.Buffer.Length;
         }
 
-        ///
         public MessageWriter(int bufferSize)
         {
             this.Buffer = new byte[bufferSize];
         }
 
+        public byte[] Buffer { get; }
+        public int Length { get; set; }
+        public int Position { get; set; }
+
         public byte[] ToByteArray(bool includeHeader)
         {
             if (includeHeader)
@@ -42,13 +44,13 @@ namespace Hazel
             {
                 switch (this.SendOption)
                 {
-                    case SendOption.Reliable:
+                    case MessageType.Reliable:
                         {
                             byte[] output = new byte[this.Length - 3];
                             System.Buffer.BlockCopy(this.Buffer, 3, output, 0, this.Length - 3);
                             return output;
                         }
-                    case SendOption.None:
+                    case MessageType.Unreliable:
                         {
                             byte[] output = new byte[this.Length - 1];
                             System.Buffer.BlockCopy(this.Buffer, 1, output, 0, this.Length - 1);
@@ -62,7 +64,7 @@ namespace Hazel
 
         ///
         /// <param name="sendOption">The option specifying how the message should be sent.</param>
-        public static MessageWriter Get(SendOption sendOption = SendOption.None)
+        public static MessageWriter Get(MessageType sendOption = MessageType.Unreliable)
         {
             var output = WriterPool.GetObject();
             output.Clear(sendOption);
@@ -72,7 +74,7 @@ namespace Hazel
 
         public bool HasBytes(int expected)
         {
-            if (this.SendOption == SendOption.None)
+            if (this.SendOption == MessageType.Unreliable)
             {
                 return this.Length > 1 + expected;
             }
@@ -80,6 +82,11 @@ namespace Hazel
             return this.Length > 3 + expected;
         }
 
+        public void Write(GameCode value)
+        {
+            this.Write(value.Value);
+        }
+
         ///
         public void StartMessage(byte typeFlag)
         {
@@ -104,7 +111,7 @@ namespace Hazel
             this.Length = this.Position;
         }
 
-        public void Clear(SendOption sendOption)
+        public void Clear(MessageType sendOption)
         {
             this.messageStarts.Clear();
             this.SendOption = sendOption;
@@ -112,10 +119,10 @@ namespace Hazel
             switch (sendOption)
             {
                 default:
-                case SendOption.None:
+                case MessageType.Unreliable:
                     this.Length = this.Position = 1;
                     break;
-                case SendOption.Reliable:
+                case MessageType.Reliable:
                     this.Length = this.Position = 3;
                     break;
             }
@@ -203,6 +210,11 @@ namespace Hazel
             this.Write(bytes);
         }
 
+        public void Write(IPAddress value)
+        {
+            this.Write(value.GetAddressBytes());
+        }
+
         public void WriteBytesAndSize(byte[] bytes)
         {
             this.WritePacked((uint)bytes.Length);
@@ -277,10 +289,10 @@ namespace Hazel
             {
                 switch (msg.SendOption)
                 {
-                    case SendOption.None:
+                    case MessageType.Unreliable:
                         offset = 1;
                         break;
-                    case SendOption.Reliable:
+                    case MessageType.Reliable:
                         offset = 3;
                         break;
                 }
index fd155f7046a7d5046334baf49342a3c3d3e94d16..68966bad00378e192dde51a856bf466740897321 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Net;
 using System.Threading.Tasks;
+using Impostor.Api.Net.Messages;
 
 
 namespace Hazel
@@ -56,7 +57,7 @@ namespace Hazel
         /// <summary>
         ///     Called when the socket has been disconnected at the remote host.
         /// </summary>
-        protected async ValueTask DisconnectRemote(string reason, MessageReader reader)
+        protected async ValueTask DisconnectRemote(string reason, IMessageReader reader)
         {
             if (this.SendDisconnect(null))
             {
index 68fd37f15896b8260a85c42234a121373b7eef38..efc84bbaed22da964c31c4dac947fad90b815c02 100644 (file)
@@ -1,4 +1,6 @@
-namespace Hazel
+using Impostor.Api.Net.Messages;
+
+namespace Hazel
 {
     public struct NewConnectionEventArgs
     {
@@ -6,14 +8,14 @@
         /// The data received from the client in the handshake.
         /// This data is yours. Remember to recycle it.
         /// </summary>
-        public readonly MessageReader HandshakeData;
+        public readonly IMessageReader HandshakeData;
 
         /// <summary>
         /// The <see cref="Connection"/> to the new client.
         /// </summary>
         public readonly Connection Connection;
 
-        public NewConnectionEventArgs(MessageReader handshakeData, Connection connection)
+        public NewConnectionEventArgs(IMessageReader handshakeData, Connection connection)
         {
             this.HandshakeData = handshakeData;
             this.Connection = connection;
diff --git a/src/Impostor.Hazel/SendOption.cs b/src/Impostor.Hazel/SendOption.cs
deleted file mode 100644 (file)
index 385e88c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-
-namespace Hazel
-{
-    /// <summary>
-    ///     Specifies how a message should be sent between connections.
-    /// </summary>
-    [Flags]
-    public enum SendOption : byte
-    {
-        /// <summary>
-        ///     Requests unreliable delivery with no framentation.
-        /// </summary>
-        /// <remarks>
-        ///     Sending data using unreliable delivery means that data is not guaranteed to arrive at it's destination nor is 
-        ///     it guarenteed to arrive only once. However, unreliable delivery can be faster than other methods and it 
-        ///     typically requires a smaller number of protocol bytes than other methods. There is also typically less 
-        ///     processing involved and less memory needed as packets are not stored once sent.
-        /// </remarks>
-        None = 0,
-
-        /// <summary>
-        ///     Requests data be sent reliably but with no fragmentation.
-        /// </summary>
-        /// <remarks>
-        ///     Sending data reliably means that data is guarenteed to arrive and to arrive only once. Reliable delivery
-        ///     typically requires more processing, more memory (as packets need to be stored in case they need resending), 
-        ///     a larger number of protocol bytes and can be slower than unreliable delivery.
-        /// </remarks>
-        Reliable = 1,
-    }
-}
index 11f15d89cf5773f4eafcae8840a6a7c76fe0af7f..d39cb5d7181f31f46cdb114650b614206d12f83a 100644 (file)
@@ -4,6 +4,7 @@ using System.Collections.Generic;
 using System.Diagnostics;
 using System.Threading;
 using System.Threading.Tasks;
+using Impostor.Api.Net.Messages;
 
 
 namespace Hazel.Udp
@@ -285,7 +286,7 @@ namespace Hazel.Udp
         {
             if (await ProcessReliableReceive(message.Buffer, 1))
             {
-                await InvokeDataReceived(message.Slice(3), SendOption.Reliable);
+                await InvokeDataReceived(message.Slice(3), MessageType.Reliable);
             }
 
             Statistics.LogReliableReceive(message.Length - 3, message.Length);
index 96429d7341766bb2b65d07160c9f772763ee29fc..c33ffb3d8bfd2db34934265e2eb198e6b9e7bfb2 100644 (file)
@@ -2,6 +2,7 @@
 using System.Threading;
 using System.Threading.Channels;
 using System.Threading.Tasks;
+using Impostor.Api.Net.Messages;
 using Serilog;
 
 namespace Hazel.Udp
@@ -110,7 +111,7 @@ namespace Hazel.Udp
         protected abstract ValueTask WriteBytesToConnection(byte[] bytes, int length);
 
         /// <inheritdoc/>
-        public override async ValueTask Send(MessageWriter msg)
+        public override async ValueTask Send(IMessageWriter msg)
         {
             if (this._state != ConnectionState.Connected)
                 throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?");
@@ -120,7 +121,7 @@ namespace Hazel.Udp
 
             switch (msg.SendOption)
             {
-                case SendOption.Reliable:
+                case MessageType.Reliable:
                     ResetKeepAliveTimer();
 
                     AttachReliableID(buffer, 1, buffer.Length);
@@ -144,7 +145,7 @@ namespace Hazel.Udp
         ///         <see cref="SendOption.None"/> until implemented.
         ///     </para>
         /// </remarks>
-        public override async ValueTask SendBytes(byte[] bytes, SendOption sendOption = SendOption.None)
+        public override async ValueTask SendBytes(byte[] bytes, MessageType sendOption = MessageType.Unreliable)
         {
             //Add header information and send
             await HandleSend(bytes, (byte)sendOption);
@@ -162,7 +163,7 @@ namespace Hazel.Udp
             switch (sendOption)
             {
                 case (byte)UdpSendOption.Ping:
-                case (byte)SendOption.Reliable:
+                case (byte)MessageType.Reliable:
                 case (byte)UdpSendOption.Hello:
                     await ReliableSend(sendOption, data, ackCallback);
                     break;
@@ -192,7 +193,7 @@ namespace Hazel.Udp
             switch (message.Buffer.Span[0])
             {
                 //Handle reliable receives
-                case (byte)SendOption.Reliable:
+                case (byte)MessageType.Reliable:
                     await ReliableMessageReceive(message);
                     break;
 
@@ -217,7 +218,7 @@ namespace Hazel.Udp
                     
                 //Treat everything else as unreliable
                 default:
-                    await InvokeDataReceived(message.Slice(1), SendOption.None);
+                    await InvokeDataReceived(message.Slice(1), MessageType.Unreliable);
                     Statistics.LogUnreliableReceive(message.Length - 1, message.Length);
                     break;
             }
index 8885ad4a55aa805289bd2e4a101fc9ea64209138..c95cdb20b66708885d96e6065175b291fefe93ba 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Net;
 using System.Threading.Tasks;
+using Impostor.Api.Net.Messages;
 
 namespace Hazel.Udp
 {
@@ -74,7 +75,7 @@ namespace Hazel.Udp
             var bytes = EmptyDisconnectBytes;
             if (data != null && data.Length > 0)
             {
-                if (data.SendOption != SendOption.None) throw new ArgumentException("Disconnect messages can only be unreliable.");
+                if (data.SendOption != MessageType.Unreliable) throw new ArgumentException("Disconnect messages can only be unreliable.");
 
                 bytes = data.ToByteArray(true);
                 bytes[0] = (byte)UdpSendOption.Disconnect;
index dec73df86d4236639b711143b405655d33f3bc15..42a17ce59bb9d8f8b6837a599ff66182d8f0a699 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Threading.Tasks;
+using Hazel;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Data;
@@ -26,10 +27,8 @@ namespace Impostor.Server.Net
             _gameManager = gameManager;
         }
 
-        public override async ValueTask HandleMessageAsync(IMessage message)
+        public override async ValueTask HandleMessageAsync(IMessageReader reader, MessageType messageType)
         {
-            var reader = message.CreateReader();
-
             var flag = reader.Tag;
 
             _logger.LogTrace("[{0}] Server got {1}.", Id, flag);
@@ -45,10 +44,11 @@ namespace Impostor.Server.Net
                     var game = await _gameManager.CreateAsync(gameInfo);
 
                     // Code in the packet below will be used in JoinGame.
-                    using var writer = Connection.CreateMessage(MessageType.Reliable);
-                    Message00HostGame.Serialize(writer, game.Code);
-
-                    await writer.SendAsync();
+                    using (var writer = MessageWriter.Get(MessageType.Reliable))
+                    {
+                        Message00HostGame.Serialize(writer, game.Code);
+                        await Connection.SendAsync(writer);
+                    }
 
                     break;
                 }
@@ -150,18 +150,19 @@ namespace Impostor.Server.Net
                     await Player.Game.HandleGameData(readerCopy, Player, toPlayer);
 
                     // Broadcast packet to all other players.
-                    using var writer = Player.Game.CreateMessage(message.Type);
-
-                    if (toPlayer)
-                    {
-                        var target = reader.ReadPackedInt32();
-                        reader.CopyTo(writer);
-                        await writer.SendToAsync(target);
-                    }
-                    else
+                    using (var writer = MessageWriter.Get(messageType))
                     {
-                        reader.CopyTo(writer);
-                        await writer.SendToAllExceptAsync(Id);
+                        if (toPlayer)
+                        {
+                            var target = reader.ReadPackedInt32();
+                            reader.CopyTo(writer);
+                            await Player.Game.SendToAsync(writer, target);
+                        }
+                        else
+                        {
+                            reader.CopyTo(writer);
+                            await Player.Game.SendToAllExceptAsync(writer, Id);
+                        }
                     }
 
                     break;
@@ -297,9 +298,10 @@ namespace Impostor.Server.Net
         ///     All options given.
         ///     At this moment, the client can only specify the map, impostor count and chat language.
         /// </param>
-        private async ValueTask OnRequestGameList(GameOptionsData options)
+        private ValueTask OnRequestGameList(GameOptionsData options)
         {
-            using var message = Connection.CreateMessage(MessageType.Reliable);
+            using var message = MessageWriter.Get(MessageType.Reliable);
+
             var games = _gameManager.FindListings((MapFlags)options.MapId, options.NumImpostors, options.Keywords);
 
             var skeldGameCount = _gameManager.GetGameCount(MapFlags.Skeld);
@@ -308,19 +310,19 @@ namespace Impostor.Server.Net
 
             Message16GetGameListV2.Serialize(message, skeldGameCount, miraHqGameCount, polusGameCount, games);
 
-            await message.SendAsync();
+            return Connection.SendAsync(message);
         }
 
-        private async ValueTask SendDisconnectReason(DisconnectReason reason, string message = null)
+        private ValueTask SendDisconnectReason(DisconnectReason reason, string message = null)
         {
             if (Connection == null)
             {
-                return;
+                return default;
             }
 
-            using var packet = Connection.CreateMessage(MessageType.Reliable);
+            using var packet = MessageWriter.Get(MessageType.Reliable);
             Message01JoinGame.SerializeError(packet, false, reason, message);
-            await packet.SendAsync();
+            return Connection.SendAsync(packet);
         }
     }
 }
\ No newline at end of file
index ec2efcb9bd6ce0e6ae90ec76070671f6fd6e3ff4..3dda4caae68d23d907a90614072328a654cb1c7e 100644 (file)
@@ -29,7 +29,7 @@ namespace Impostor.Server.Net
 
         public ClientPlayer Player { get; set; }
 
-        public abstract ValueTask HandleMessageAsync(IMessage message);
+        public abstract ValueTask HandleMessageAsync(IMessageReader message, MessageType messageType);
 
         public abstract ValueTask HandleDisconnectAsync(string reason);
     }
index e2694f8d31f94e14cb52aaf7c5f5521e327f43ab..e80e2ef07cdb0fdf53d933b61db09bc0ff13f13b 100644 (file)
@@ -1,20 +1,16 @@
-using System;
-using System.Net;
+using System.Net;
 using System.Threading.Tasks;
 using Hazel;
 using Impostor.Api.Net.Messages;
-using Impostor.Server.Hazel.Messages;
-using Impostor.Server.Net.Hazel.Messages;
-using Impostor.Server.Net.Messages;
 using Microsoft.Extensions.Logging;
 
 namespace Impostor.Server.Net.Hazel
 {
     internal partial class HazelConnection
     {
-        private readonly ILogger<Net.Hazel.HazelConnection> _logger;
+        private readonly ILogger<HazelConnection> _logger;
 
-        public HazelConnection(Connection innerConnection, ILogger<Net.Hazel.HazelConnection> logger)
+        public HazelConnection(Connection innerConnection, ILogger<HazelConnection> logger)
         {
             _logger = logger;
             InnerConnection = innerConnection;
@@ -30,6 +26,11 @@ namespace Impostor.Server.Net.Hazel
 
         public ClientBase Client { get; set; }
 
+        public ValueTask SendAsync(IMessageWriter writer)
+        {
+            return InnerConnection.Send(writer);
+        }
+
         private async ValueTask ConnectionOnDisconnected(DisconnectedEventArgs e)
         {
             if (Client != null)
@@ -53,23 +54,8 @@ namespace Impostor.Server.Net.Hazel
                     break;
                 }
 
-                var reader = e.Message.ReadMessage();
-                var type = e.SendOption switch
-                {
-                    SendOption.None => MessageType.Unreliable,
-                    SendOption.Reliable => MessageType.Reliable,
-                    _ => throw new NotSupportedException()
-                };
-
-                using var message = new HazelMessage(reader, type);
-
-                await Client.HandleMessageAsync(message);
+                await Client.HandleMessageAsync(e.Message.ReadMessage(), e.Type);
             }
         }
-
-        public IConnectionMessageWriter CreateMessage(MessageType messageType)
-        {
-            return new HazelConnectionMessageWriter(messageType, this);
-        }
     }
 }
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Hazel/Messages/BufferMessageReader.cs b/src/Impostor.Server/Net/Hazel/Messages/BufferMessageReader.cs
deleted file mode 100644 (file)
index 8491835..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-using System;
-using System.Buffers.Binary;
-using System.Runtime.CompilerServices;
-using System.Text;
-using Impostor.Api.Net.Messages;
-using Impostor.Server.Net.Messages;
-
-namespace Impostor.Server.Hazel.Messages
-{
-    public class BufferMessageReader : IMessageReader
-    {
-        public byte Tag { get; }
-        public ReadOnlyMemory<byte> Buffer { get; }
-        public int Position { get; set; }
-        public int Length => Buffer.Length;
-
-        public BufferMessageReader(byte tag, ReadOnlyMemory<byte> buffer)
-        {
-            Tag = tag;
-            Buffer = buffer;
-        }
-
-        public IMessageReader ReadMessage()
-        {
-            var length = ReadUInt16();
-            var tag = ReadByte();
-            var pos = Position;
-
-            Position += length;
-
-            return new BufferMessageReader(tag, Buffer.Slice(pos, length));
-        }
-
-        public bool ReadBoolean()
-        {
-            byte val = FastByte();
-            return val != 0;
-        }
-
-        public sbyte ReadSByte()
-        {
-            return (sbyte)FastByte();
-        }
-
-        public byte ReadByte()
-        {
-            return FastByte();
-        }
-
-        public ushort ReadUInt16()
-        {
-            var output = BinaryPrimitives.ReadUInt16LittleEndian(Buffer.Span.Slice(Position));
-            Position += sizeof(ushort);
-            return output;
-        }
-
-        public short ReadInt16()
-        {
-            var output = BinaryPrimitives.ReadInt16LittleEndian(Buffer.Span.Slice(Position));
-            Position += sizeof(short);
-            return output;
-        }
-
-        public uint ReadUInt32()
-        {
-            var output = BinaryPrimitives.ReadUInt32LittleEndian(Buffer.Span.Slice(Position));
-            Position += sizeof(uint);
-            return output;
-        }
-
-        public int ReadInt32()
-        {
-            var output = BinaryPrimitives.ReadInt32LittleEndian(Buffer.Span.Slice(Position));
-            Position += sizeof(int);
-            return output;
-        }
-
-        public float ReadSingle()
-        {
-            var output = BinaryPrimitives.ReadSingleLittleEndian(Buffer.Span.Slice(Position));
-            Position += sizeof(float);
-            return output;
-        }
-
-        public string ReadString()
-        {
-            var len = ReadPackedInt32();
-            var output = Encoding.UTF8.GetString(Buffer.Span.Slice(Position, len));
-            Position += len;
-            return output;
-        }
-
-        public ReadOnlyMemory<byte> ReadBytesAndSize()
-        {
-            var len = ReadPackedInt32();
-            return ReadBytes(len);
-        }
-
-        public ReadOnlyMemory<byte> ReadBytes(int length)
-        {
-            var output = Buffer.Slice(Position, length);
-            Position += length;
-            return output;
-        }
-
-        public int ReadPackedInt32()
-        {
-            return (int)ReadPackedUInt32();
-        }
-
-        public uint ReadPackedUInt32()
-        {
-            bool readMore = true;
-            int shift = 0;
-            uint output = 0;
-
-            while (readMore)
-            {
-                byte b = ReadByte();
-                if (b >= 0x80)
-                {
-                    readMore = true;
-                    b ^= 0x80;
-                }
-                else
-                {
-                    readMore = false;
-                }
-
-                output |= (uint)(b << shift);
-                shift += 7;
-            }
-
-            return output;
-        }
-
-        public void CopyTo(IMessageWriter writer)
-        {
-            writer.Write((ushort) Length);
-            writer.Write(Tag);
-            writer.Write(Buffer);
-        }
-
-        public IMessageReader Slice(int start)
-        {
-            return new BufferMessageReader(Tag, Buffer.Slice(start));
-        }
-
-        public IMessageReader Slice(int start, int length)
-        {
-            return new BufferMessageReader(Tag, Buffer.Slice(start, length));
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private byte FastByte()
-        {
-            return Buffer.Span[Position++];
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Hazel/Messages/HazelConnectionMessageWriter.cs b/src/Impostor.Server/Net/Hazel/Messages/HazelConnectionMessageWriter.cs
deleted file mode 100644 (file)
index 4c77514..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.Threading.Tasks;
-using Impostor.Api.Net;
-using Impostor.Api.Net.Messages;
-using Impostor.Server.Net;
-using Impostor.Server.Net.Messages;
-
-namespace Impostor.Server.Hazel.Messages
-{
-    internal class HazelConnectionMessageWriter : HazelMessageWriter, IConnectionMessageWriter
-    {
-        private readonly Net.Hazel.HazelConnection _connection;
-
-        public HazelConnectionMessageWriter(MessageType type, Net.Hazel.HazelConnection connection)
-            : base(type)
-        {
-            _connection = connection;
-        }
-
-        public IConnection Connection => _connection;
-
-        public async ValueTask SendAsync()
-        {
-            await _connection.InnerConnection.Send(Writer);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Hazel/Messages/HazelGameMessageWriter.cs b/src/Impostor.Server/Net/Hazel/Messages/HazelGameMessageWriter.cs
deleted file mode 100644 (file)
index 3e4f6e2..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Hazel;
-using Impostor.Api.Net;
-using Impostor.Api.Net.Messages;
-using Impostor.Server.Net;
-using Impostor.Server.Net.Messages;
-using Impostor.Server.Net.State;
-
-namespace Impostor.Server.Hazel.Messages
-{
-    internal class HazelGameMessageWriter : HazelMessageWriter, IGameMessageWriter
-    {
-        private readonly Game _game;
-
-        public HazelGameMessageWriter(MessageType type, Game game)
-            : base(type)
-        {
-            _game = game;
-        }
-
-        private IEnumerable<Connection> GetConnections(Func<IClientPlayer, bool> filter)
-        {
-            return _game.Players
-                .Where(filter)
-                .Select(p => p.Client.Connection)
-                .OfType<Net.Hazel.HazelConnection>()
-                .Select(c => c.InnerConnection);
-        }
-
-        public ValueTask SendToAllAsync(LimboStates states)
-        {
-            foreach (var connection in GetConnections(x => x.Limbo.HasFlag(states)))
-            {
-                connection.Send(Writer);
-            }
-
-            return default;
-        }
-
-        public ValueTask SendToAllExceptAsync(int senderId, LimboStates states)
-        {
-            foreach (var connection in GetConnections(x =>
-                x.Limbo.HasFlag(states) &&
-                x.Client.Id != senderId))
-            {
-                connection.Send(Writer);
-            }
-            return default;
-        }
-
-        public ValueTask SendToAsync(int id)
-        {
-            if (_game.TryGetPlayer(id, out var player)
-                && player.Client.Connection is Net.Hazel.HazelConnection hazelConnection)
-            {
-                hazelConnection.InnerConnection.Send(Writer);
-            }
-
-            return default;
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Hazel/Messages/HazelMessage.cs b/src/Impostor.Server/Net/Hazel/Messages/HazelMessage.cs
deleted file mode 100644 (file)
index 8799c48..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using Hazel;
-using Impostor.Api.Net.Messages;
-using Impostor.Server.Hazel.Messages;
-using Impostor.Server.Net.Messages;
-
-namespace Impostor.Server.Net.Hazel.Messages
-{
-    internal class HazelMessage : IMessage, IDisposable
-    {
-        private bool _isDisposed;
-        private readonly MessageReader _reader;
-
-        public HazelMessage(MessageReader reader, MessageType type)
-        {
-            _reader = reader;
-            Type = type;
-        }
-
-        public MessageType Type { get; }
-
-        public IMessageReader CreateReader()
-        {
-            if (_isDisposed)
-            {
-                throw new ObjectDisposedException(nameof(_reader));
-            }
-
-            return new BufferMessageReader(_reader.Tag, _reader.Buffer);
-        }
-
-        private void Dispose(bool disposing)
-        {
-            if (disposing)
-            {
-                _isDisposed = true;
-            }
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        ~HazelMessage()
-        {
-            Dispose(false);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Hazel/Messages/HazelMessageWriter.cs b/src/Impostor.Server/Net/Hazel/Messages/HazelMessageWriter.cs
deleted file mode 100644 (file)
index c43cdfb..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-using System;
-using System.Net;
-using Hazel;
-using Impostor.Api.Games;
-using Impostor.Api.Net.Messages;
-using Impostor.Server.Net.Messages;
-
-namespace Impostor.Server.Hazel.Messages
-{
-    internal abstract class HazelMessageWriter : IMessageWriter
-    {
-        protected readonly MessageWriter Writer;
-
-        protected HazelMessageWriter(MessageType type)
-        {
-            Writer = MessageWriter.Get(ToSendOption(type));
-        }
-
-        private static SendOption ToSendOption(MessageType type)
-        {
-            return type switch
-            {
-                MessageType.Unreliable => SendOption.None,
-                MessageType.Reliable => SendOption.Reliable,
-                _ => throw new NotSupportedException($"Message type {type} is not supported")
-            };
-        }
-
-        protected virtual void Dispose(bool disposing)
-        {
-            if (disposing)
-            {
-                Writer.Recycle();
-            }
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        public void Write(bool value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(sbyte value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(byte value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(short value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(ushort value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(uint value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(int value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(float value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(string value)
-        {
-            Writer.Write(value);
-        }
-
-        public void Write(IPAddress value)
-        {
-            Writer.Write(value.GetAddressBytes());
-        }
-
-        public void WritePacked(int value)
-        {
-            Writer.WritePacked(value);
-        }
-
-        public void WritePacked(uint value)
-        {
-            Writer.WritePacked(value);
-        }
-
-        public void Write(ReadOnlyMemory<byte> data)
-        {
-            Writer.Write(data.ToArray()); // TODO: Fix memory allocation.
-        }
-
-        public void StartMessage(byte typeFlag)
-        {
-            Writer.StartMessage(typeFlag);
-        }
-
-        public void Write(GameCode value)
-        {
-            Write(value.Value);
-        }
-
-        public void EndMessage()
-        {
-            Writer.EndMessage();
-        }
-
-        public void Clear(MessageType type)
-        {
-            Writer.Clear(ToSendOption(type));
-        }
-    }
-}
\ No newline at end of file
index 7a62fdeaf2b7e3be92ad112872ed084c09584f4b..4a6a99623792bee6ffb4b70b6ddb3b13a28052b6 100644 (file)
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
+using Hazel;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Data;
 using Impostor.Api.Net;
@@ -56,17 +57,17 @@ namespace Impostor.Server.Net.Manager
         {
             if (name.Length > 10)
             {
-                using var packet = connection.CreateMessage(MessageType.Reliable);
+                using var packet = MessageWriter.Get(MessageType.Reliable);
                 Message01JoinGame.SerializeError(packet, false, DisconnectReason.Custom, DisconnectMessages.UsernameLength);
-                await packet.SendAsync();
+                await connection.SendAsync(packet);
                 return;
             }
 
             if (!SupportedVersions.Contains(clientVersion))
             {
-                using var packet = connection.CreateMessage(MessageType.Reliable);
+                using var packet = MessageWriter.Get(MessageType.Reliable);
                 Message01JoinGame.SerializeError(packet, false, DisconnectReason.IncorrectVersion);
-                await packet.SendAsync();
+                await connection.SendAsync(packet);
                 return;
             }
 
index acdb9cf1088ba63ec7798f61a90c7d48505e760f..a9ffa68753940903a472ef1e51793c3e07c3324b 100644 (file)
@@ -1,4 +1,5 @@
 using System.Threading.Tasks;
+using Hazel;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Data;
 using Impostor.Api.Net.Messages;
@@ -32,9 +33,8 @@ namespace Impostor.Server.Net.Redirector
             _nodeLocator = nodeLocator;
         }
 
-        public override async ValueTask HandleMessageAsync(IMessage message)
+        public override async ValueTask HandleMessageAsync(IMessageReader reader, MessageType messageType)
         {
-            var reader = message.CreateReader();
             var flag = reader.Tag;
 
             Logger.Verbose("Server got {0}.", flag);
@@ -43,9 +43,9 @@ namespace Impostor.Server.Net.Redirector
             {
                 case MessageFlags.HostGame:
                 {
-                    using var packet = Connection.CreateMessage(MessageType.Reliable);
+                    using var packet = MessageWriter.Get(MessageType.Reliable);
                     Message13Redirect.Serialize(packet, false, _nodeProvider.Get());
-                    await packet.SendAsync();
+                    await Connection.SendAsync(packet);
                     break;
                 }
 
@@ -56,7 +56,7 @@ namespace Impostor.Server.Net.Redirector
                         out var gameCode,
                         out _);
 
-                    using var packet = Connection.CreateMessage(MessageType.Reliable);
+                    using var packet = MessageWriter.Get(MessageType.Reliable);
                     var endpoint = _nodeLocator.Find(GameCodeParser.IntToGameName(gameCode));
                     if (endpoint == null)
                     {
@@ -67,16 +67,16 @@ namespace Impostor.Server.Net.Redirector
                         Message13Redirect.Serialize(packet, false, endpoint);
                     }
 
-                    await packet.SendAsync();
+                    await Connection.SendAsync(packet);
                     break;
                 }
 
                 case MessageFlags.GetGameListV2:
                 {
                     // TODO: Implement.
-                    using var packet = Connection.CreateMessage(MessageType.Reliable);
+                    using var packet = MessageWriter.Get(MessageType.Reliable);
                     Message01JoinGame.SerializeError(packet, false, DisconnectReason.Custom, DisconnectMessages.NotImplemented);
-                    await packet.SendAsync();
+                    await Connection.SendAsync(packet);
                     break;
                 }
 
index b90394f60db6f33166d0a4b49d7dfc07a0a84b34..a0d8b6f923df67b8ec5aae17bdfb2f0902ede48c 100644 (file)
@@ -3,7 +3,7 @@ using Impostor.Api.Net;
 
 namespace Impostor.Server.Net.State
 {
-    internal partial class Game : IGame
+    internal partial class Game
     {
         IClientPlayer IGame.Host => Host;
     }
index 9a502b407290d98c1a7fba58a7134aca2921bfb8..b162c4d2aa76eacaaba0f36e10951ed7f5d53292 100644 (file)
@@ -1,9 +1,9 @@
 using System.Threading.Tasks;
+using Hazel;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth.Data;
 using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
-using Impostor.Server.Net.Messages;
 
 namespace Impostor.Server.Net.State
 {
@@ -13,9 +13,9 @@ namespace Impostor.Server.Net.State
         {
             GameState = GameStates.Started;
 
-            using var packet = CreateMessage(MessageType.Reliable);
+            using var packet = MessageWriter.Get(MessageType.Reliable);
             message.CopyTo(packet);
-            await packet.SendToAllAsync();
+            await SendToAllAsync(packet);
         }
 
         public async ValueTask<GameJoinResult> AddClientAsync(ClientBase client)
@@ -83,10 +83,10 @@ namespace Impostor.Server.Net.State
             GameState = GameStates.Ended;
 
             // Broadcast end of the game.
-            using (var packet = CreateMessage(MessageType.Reliable))
+            using (var packet = MessageWriter.Get(MessageType.Reliable))
             {
                 message.CopyTo(packet);
-                await packet.SendToAllAsync();
+                await SendToAllAsync(packet);
             }
 
             // Put all players in the correct limbo state.
@@ -100,9 +100,9 @@ namespace Impostor.Server.Net.State
         {
             IsPublic = isPublic;
 
-            using var packet = CreateMessage(MessageType.Reliable);
+            using var packet = MessageWriter.Get(MessageType.Reliable);
             message.CopyTo(packet);
-            await packet.SendToAllExceptAsync(sender.Client.Id);
+            await SendToAllExceptAsync(packet, sender.Client.Id);
         }
 
         public async ValueTask HandleRemovePlayer(int playerId, DisconnectReason reason)
@@ -115,21 +115,21 @@ namespace Impostor.Server.Net.State
                 return;
             }
 
-            using var packet = CreateMessage(MessageType.Reliable);
+            using var packet = MessageWriter.Get(MessageType.Reliable);
             WriteRemovePlayerMessage(packet, false, playerId, reason);
-            await packet.SendToAllExceptAsync(playerId);
+            await SendToAllExceptAsync(packet, playerId);
         }
 
         public async ValueTask HandleKickPlayer(int playerId, bool isBan)
         {
             Logger.Information("{0} - Player {1} has left.", Code, playerId);
 
-            using var message = CreateMessage(MessageType.Reliable);
+            using var message = MessageWriter.Get(MessageType.Reliable);
 
             // Send message to everyone that this player was kicked.
             WriteKickPlayerMessage(message, false, playerId, isBan);
-            await message.SendToAllAsync();
 
+            await SendToAllAsync(message);
             await PlayerRemove(playerId, isBan);
 
             // Remove the player from everyone's game.
@@ -138,7 +138,8 @@ namespace Impostor.Server.Net.State
                 true,
                 playerId,
                 isBan ? DisconnectReason.Banned : DisconnectReason.Kicked);
-            await message.SendToAllExceptAsync(playerId);
+
+            await SendToAllExceptAsync(message, playerId);
         }
 
         private async ValueTask HandleJoinGameNew(ClientPlayer sender, bool isNew)
@@ -151,14 +152,14 @@ namespace Impostor.Server.Net.State
                 await PlayerAdd(sender);
             }
 
-            using (var message = CreateMessage(MessageType.Reliable))
+            using (var message = MessageWriter.Get(MessageType.Reliable))
             {
                 WriteJoinedGameMessage(message, false, sender);
                 WriteAlterGameMessage(message, false, IsPublic);
 
                 sender.Limbo = LimboStates.NotLimbo;
-                await message.SendToAsync(sender);
 
+                await SendToAsync(message, sender.Client.Id);
                 await BroadcastJoinMessage(message, true, sender);
             }
         }
@@ -188,12 +189,13 @@ namespace Impostor.Server.Net.State
 
             sender.Limbo = LimboStates.WaitingForHost;
 
-            using var packet = CreateMessage(MessageType.Reliable);
-
-            WriteWaitForHostMessage(packet, false, sender);
-            await packet.SendToAsync(sender.Client);
+            using (var packet = MessageWriter.Get(MessageType.Reliable))
+            {
+                WriteWaitForHostMessage(packet, false, sender);
 
-            await BroadcastJoinMessage(packet, true, sender);
+                await SendToAsync(packet, sender.Client.Id);
+                await BroadcastJoinMessage(packet, true, sender);
+            }
         }
     }
 }
\ No newline at end of file
index 2fc4f3cacc6e0a399e7d6e24c0ac805847a09751..bc832e408b09e1bf6d560df52dd1dbafb71aed57 100644 (file)
@@ -1,13 +1,47 @@
 using System.Linq;
+using System.Threading.Tasks;
 using Impostor.Api.Innersloth.Data;
 using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
+using Impostor.Server.Net.Hazel;
 using Impostor.Server.Net.Messages;
 
 namespace Impostor.Server.Net.State
 {
     internal partial class Game
     {
+        public ValueTask SendToAllAsync(IMessageWriter writer, LimboStates states = LimboStates.NotLimbo)
+        {
+            foreach (var connection in GetConnections(x => x.Limbo.HasFlag(states)))
+            {
+                connection.Send(writer);
+            }
+
+            return default;
+        }
+
+        public ValueTask SendToAllExceptAsync(IMessageWriter writer, int senderId, LimboStates states = LimboStates.NotLimbo)
+        {
+            foreach (var connection in GetConnections(x =>
+                x.Limbo.HasFlag(states) &&
+                x.Client.Id != senderId))
+            {
+                connection.Send(writer);
+            }
+
+            return default;
+        }
+
+        public ValueTask SendToAsync(IMessageWriter writer, int id)
+        {
+            if (TryGetPlayer(id, out var player) && player.Client.Connection is HazelConnection hazelConnection)
+            {
+                hazelConnection.InnerConnection.Send(writer);
+            }
+
+            return default;
+        }
+
         private void WriteRemovePlayerMessage(IMessageWriter message, bool clear, int playerId, DisconnectReason reason)
         {
             Message04RemovePlayer.Serialize(message, clear, Code, playerId, HostId, reason);
index ab9dfbbdfdb0a29dc770944eef0f007013231071..60f6e978dbba697469b0b4f83dbd677e0ce154b6 100644 (file)
@@ -1,5 +1,6 @@
 using System.Linq;
 using System.Threading.Tasks;
+using Hazel;
 using Impostor.Api;
 using Impostor.Api.Events;
 using Impostor.Api.Innersloth.Data;
@@ -95,7 +96,7 @@ namespace Impostor.Server.Net.State
 
         private async ValueTask CheckLimboPlayers()
         {
-            using var message = CreateMessage(MessageType.Reliable);
+            using var message = MessageWriter.Get(MessageType.Reliable);
 
             foreach (var (_, player) in _players.Where(x => x.Value.Limbo == LimboStates.WaitingForHost))
             {
@@ -103,7 +104,8 @@ namespace Impostor.Server.Net.State
                 WriteAlterGameMessage(message, false, IsPublic);
 
                 player.Limbo = LimboStates.NotLimbo;
-                await message.SendToAsync(player.Client);
+
+                await SendToAsync(message, player.Client.Id);
             }
         }
     }
index 4654c34acd15a6ae059a4b9b6e19f7c153326a36..4b7f014e15101ed50eedfb1c076dd8238e5673b8 100644 (file)
@@ -4,6 +4,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
+using Hazel;
 using Impostor.Api.Events.Managers;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth;
@@ -11,7 +12,7 @@ using Impostor.Api.Innersloth.Data;
 using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 using Impostor.Server.Hazel;
-using Impostor.Server.Hazel.Messages;
+using Impostor.Server.Net.Hazel;
 using Impostor.Server.Net.Manager;
 using Impostor.Server.Net.Messages;
 using Impostor.Server.Net.Redirector;
@@ -20,7 +21,7 @@ using ILogger = Serilog.ILogger;
 
 namespace Impostor.Server.Net.State
 {
-    internal partial class Game
+    internal partial class Game : IGame
     {
         private static readonly ILogger Logger = Log.ForContext<Game>();
 
@@ -79,11 +80,6 @@ namespace Impostor.Server.Net.State
 
         public IEnumerable<IClientPlayer> Players => _players.Select(p => p.Value);
 
-        public IGameMessageWriter CreateMessage(MessageType type)
-        {
-            return new HazelGameMessageWriter(type, this);
-        }
-
         public bool TryGetPlayer(int id, out ClientPlayer player)
         {
             if (_players.TryGetValue(id, out var result))
@@ -101,11 +97,20 @@ namespace Impostor.Server.Net.State
             return _gameManager.RemoveAsync(Code);
         }
 
-        private ValueTask BroadcastJoinMessage(IGameMessageWriter message, bool clear, ClientPlayer player)
+        private ValueTask BroadcastJoinMessage(IMessageWriter message, bool clear, ClientPlayer player)
         {
             Message01JoinGame.SerializeJoin(message, clear, Code, player.Client.Id, HostId);
 
-            return message.SendToAllExceptAsync(player.Client.Id);
+            return SendToAllExceptAsync(message, player.Client.Id);
+        }
+
+        private IEnumerable<Connection> GetConnections(Func<IClientPlayer, bool> filter)
+        {
+            return Players
+                .Where(filter)
+                .Select(p => p.Client.Connection)
+                .OfType<HazelConnection>()
+                .Select(c => c.InnerConnection);
         }
     }
 }
\ No newline at end of file
index 840fde333b1cfd32c9a92b9c1976f373d22e0620..6e516ed70794e0dc614255fb02136edc03176103 100644 (file)
@@ -1,7 +1,4 @@
 using Hazel;
-using Impostor.Api.Net.Messages;
-using Impostor.Server.Net.Hazel.Messages;
-using Impostor.Server.Net.Messages;
 using Xunit;
 
 namespace Impostor.Tests.Hazel
@@ -23,8 +20,7 @@ namespace Impostor.Tests.Hazel
             Assert.Equal(11, msg.Length);
             Assert.Equal(msg.Length, msg.Position);
 
-            var message = new HazelMessage(new MessageReader(msg.Buffer), MessageType.Reliable);
-            var reader = message.CreateReader();
+            var reader = new MessageReader(msg.Buffer);
 
             Assert.Equal(Test1, reader.ReadInt32());
             Assert.Equal(Test2, reader.ReadInt32());
@@ -45,8 +41,7 @@ namespace Impostor.Tests.Hazel
             Assert.Equal(5, msg.Length);
             Assert.Equal(msg.Length, msg.Position);
 
-            var message = new HazelMessage(new MessageReader(msg.Buffer), MessageType.Reliable);
-            var reader = message.CreateReader();
+            var reader = new MessageReader(msg.Buffer);
 
             Assert.Equal(Test1, reader.ReadBoolean());
             Assert.Equal(Test2, reader.ReadBoolean());
@@ -67,8 +62,7 @@ namespace Impostor.Tests.Hazel
 
             Assert.Equal(msg.Length, msg.Position);
 
-            var message = new HazelMessage(new MessageReader(msg.Buffer), MessageType.Reliable);
-            var reader = message.CreateReader();
+            var reader = new MessageReader(msg.Buffer);
 
             Assert.Equal(Test1, reader.ReadString());
             Assert.Equal(Test2, reader.ReadString());
@@ -89,8 +83,7 @@ namespace Impostor.Tests.Hazel
             Assert.Equal(7, msg.Length);
             Assert.Equal(msg.Length, msg.Position);
 
-            var message = new HazelMessage(new MessageReader(msg.Buffer), MessageType.Reliable);
-            var reader = message.CreateReader();
+            var reader = new MessageReader(msg.Buffer);
 
             Assert.Equal(Test1, reader.ReadSingle());
         }
@@ -111,8 +104,7 @@ namespace Impostor.Tests.Hazel
 
             msg.EndMessage();
 
-            var message = new HazelMessage(new MessageReader(msg.Buffer), MessageType.Reliable);
-            var handleMessage = message.CreateReader();
+            var handleMessage = new MessageReader(msg.Buffer);
             Assert.Equal(1, handleMessage.Tag);
 
             var parentReader = handleMessage.Slice(handleMessage.Position);
@@ -142,8 +134,7 @@ namespace Impostor.Tests.Hazel
 
             Assert.Equal(msg.Length, msg.Position);
 
-            var message = new HazelMessage(new MessageReader(msg.Buffer), MessageType.Reliable);
-            var reader = message.CreateReader();
+            var reader = new MessageReader(msg.Buffer);
             Assert.Equal(1, reader.Tag);
             Assert.Equal(65534, reader.ReadInt32()); // Content
 
index 7af07f32e1ac291fb47770cb13dc8d7a763c6bf5..30234205eb4d3ec86bc20f56c68db6fe01d75a03 100644 (file)
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using Hazel;
 using Hazel.Udp;
+using Impostor.Api.Net.Messages;
 using PcapDotNet.Core;
 using PcapDotNet.Packets;
 
@@ -68,9 +69,9 @@ namespace Impostor.Tools.Proxy
             // True if this is our own packet.
             using (var stream = udp.Payload.ToMemoryStream())
             {
-                var reader = new MessageReader(stream.ToArray());
+                var reader = (IMessageReader) new MessageReader(stream.ToArray());
                 var option = reader.Buffer.Span[0];
-                if (option == (byte) SendOption.Reliable)
+                if (option == (byte) MessageType.Reliable)
                 {
                     reader = reader.Slice(3);
                 }
@@ -114,7 +115,7 @@ namespace Impostor.Tools.Proxy
             }
         }
 
-        private static void HandleToClient(string source, MessageReader packet)
+        private static void HandleToClient(string source, IMessageReader packet)
         {
             var tagName = TagMap.ContainsKey(packet.Tag) ? TagMap[packet.Tag] : "Unknown";
             Console.ForegroundColor = ConsoleColor.Cyan;
@@ -124,7 +125,7 @@ namespace Impostor.Tools.Proxy
             {
                 case 14:
                 case 13:
-                    packet.Position = packet.Length;
+                    // packet.Position = packet.Length;
                     break;
                 case 0:
                     Console.WriteLine("- GameCode        " + packet.ReadInt32());
@@ -132,7 +133,7 @@ namespace Impostor.Tools.Proxy
                 case 5:
                 case 6:
                     Console.WriteLine(HexUtils.HexDump(packet.Buffer.ToArray().Take(packet.Length).ToArray()));
-                    packet.Position = packet.Length;
+                    // packet.Position = packet.Length;
                     break;
                 case 7:
                     Console.WriteLine("- GameCode        " + packet.ReadInt32());
@@ -153,7 +154,7 @@ namespace Impostor.Tools.Proxy
             }
         }
 
-        private static void HandleToServer(string source, MessageReader packet)
+        private static void HandleToServer(string source, IMessageReader packet)
         {
             var tagName = TagMap.ContainsKey(packet.Tag) ? TagMap[packet.Tag] : "Unknown";
             Console.ForegroundColor = ConsoleColor.White;
@@ -172,7 +173,7 @@ namespace Impostor.Tools.Proxy
                 case 6:
                     Console.WriteLine("- GameCode        " + packet.ReadInt32());
                     Console.WriteLine(HexUtils.HexDump(packet.Buffer.ToArray().Take(packet.Length).ToArray()));
-                    packet.Position = packet.Length;
+                    // packet.Position = packet.Length;
                     break;
             }
         }