]> git.deb.at Git - rhonda/impostor.hazel.git/commitdiff
Re-remove TCP (this time for good), add a counter to track potentionally fragmented...
authorForest <chocozilla@gmail.com>
Fri, 26 Apr 2019 19:26:53 +0000 (12:26 -0700)
committerForest <chocozilla@gmail.com>
Fri, 26 Apr 2019 19:26:53 +0000 (12:26 -0700)
Hazel.UnitTests/UdpConnectionTests.cs
Hazel/ConnectionStatistics.cs
Hazel/Hazel.csproj
Hazel/MessageWriter.cs
Hazel/NetworkConnection.cs
Hazel/SendOption.cs
Hazel/Tcp/StateObject.cs [deleted file]
Hazel/Tcp/TcpConnection.cs [deleted file]
Hazel/Tcp/TcpConnectionListener.cs [deleted file]
Hazel/Udp/UdpClientConnection.cs

index c30696fe78aa12d7dcf796c7c13de339a2ce3945..17515f4dafc0288c5e6cbc913ea0e651a5c27a6b 100644 (file)
@@ -2,9 +2,9 @@
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using System.Net;
 using System.Threading;
-
 using Hazel.Udp;
 using System.Linq;
+using System.Collections.Generic;
 
 namespace Hazel.UnitTests
 {
@@ -95,7 +95,7 @@ namespace Hazel.UnitTests
                 }
             }
         }
-        
+
         /// <summary>
         ///     Tests IPv4 connectivity.
         /// </summary>
index dc44c08eff199db5436aa66fb5764edbe7b0c70d..7e11c204d4465d3d5f04af32760b24ebb240de1e 100644 (file)
@@ -24,6 +24,27 @@ namespace Hazel
             }
         }
 
+        /// <summary>
+        ///     The number of messages sent larger than 1400 bytes. This is smaller than most default MTUs.
+        /// </summary>
+        /// <remarks>
+        ///     This is the number of unreliable messages that were sent from the <see cref="Connection"/>, incremented 
+        ///     each time that LogUnreliableSend is called by the Connection. Messages that caused an error are not 
+        ///     counted and messages are only counted once all other operations in the send are complete.
+        /// </remarks>
+        public int FragmentableMessagesSent
+        {
+            get
+            {
+                return fragmentableMessagesSent;
+            }
+        }
+
+        /// <summary>
+        ///     The number of messages sent larger than 1400 bytes.
+        /// </summary>
+        int fragmentableMessagesSent;
+
         /// <summary>
         ///     The number of unreliable messages sent.
         /// </summary>
@@ -358,6 +379,11 @@ namespace Hazel
             Interlocked.Increment(ref unreliableMessagesSent);
             Interlocked.Add(ref dataBytesSent, dataLength);
             Interlocked.Add(ref totalBytesSent, totalLength);
+
+            if (totalLength > 1400)
+            {
+                Interlocked.Increment(ref fragmentableMessagesSent);
+            }
         }
 
         /// <summary>
@@ -373,6 +399,11 @@ namespace Hazel
             Interlocked.Increment(ref reliableMessagesSent);
             Interlocked.Add(ref dataBytesSent, dataLength);
             Interlocked.Add(ref totalBytesSent, totalLength);
+
+            if (totalLength > 1400)
+            {
+                Interlocked.Increment(ref fragmentableMessagesSent);
+            }
         }
 
         /// <summary>
@@ -388,6 +419,11 @@ namespace Hazel
             Interlocked.Increment(ref fragmentedMessagesSent);
             Interlocked.Add(ref dataBytesSent, dataLength);
             Interlocked.Add(ref totalBytesSent, totalLength);
+
+            if (totalLength > 1400)
+            {
+                Interlocked.Increment(ref fragmentableMessagesSent);
+            }
         }
 
         /// <summary>
index 23cd33e63d56516108340cefcc7402ab8b18cdb3..6466a403b71b27967bb14d305a86e283428bd114 100644 (file)
@@ -80,9 +80,6 @@
     <Compile Include="ObjectPool.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="SendOption.cs" />
-    <Compile Include="Tcp\StateObject.cs" />
-    <Compile Include="Tcp\TcpConnection.cs" />
-    <Compile Include="Tcp\TcpConnectionListener.cs" />
     <Compile Include="Udp\SendOptionInternal.cs" />
     <Compile Include="ConnectionStatistics.cs" />
     <Compile Include="Udp\UdpBroadcaster.cs" />
index 54f0dd108fef9afb10411d8e2ffe74cc4ddfb923..37d9c94e523609d335e03265e5144b5a078f70f6 100644 (file)
@@ -55,12 +55,6 @@ namespace Hazel
                             System.Buffer.BlockCopy(this.Buffer, 1, output, 0, this.Length - 1);
                             return output;
                         }
-                    case SendOption.Tcp:
-                        {
-                            byte[] output = new byte[this.Length];
-                            System.Buffer.BlockCopy(this.Buffer, 0, output, 0, this.Length);
-                            return output;
-                        }
                 }
             }
 
@@ -124,9 +118,6 @@ namespace Hazel
                 case SendOption.Reliable:
                     this.Length = this.Position = 3;
                     break;
-                case SendOption.Tcp:
-                    this.Length = this.Position = 0;
-                    break;
             }
         }
 
index 8e7bd7efeedf0312d77349a7a14d4d24b0d0dbbd..0a224a87c2a0533ec2693e28db77a5042224a999 100644 (file)
@@ -22,11 +22,6 @@ namespace Hazel
         /// </remarks>
         public EndPoint RemoteEndPoint { get; protected set; }
 
-        /// <summary>
-        ///     The <see cref="IPMode">IPMode</see> the client is connected using.
-        /// </summary>
-        public IPMode IPMode { get; protected set; }
-
         public long GetIP4Address()
         {
             if (IPMode == IPMode.IPv4)
index 23d92cc995841cb220bfd569d3e01b5cf9d2177f..c2ffb224716ac0e50928703ff1a22f03e21d6d86 100644 (file)
@@ -31,7 +31,5 @@ namespace Hazel
         ///     a larger number of protocol bytes and can be slower than unreliable delivery.
         /// </remarks>
         Reliable = 1,
-
-        Tcp = 2,
     }
 }
diff --git a/Hazel/Tcp/StateObject.cs b/Hazel/Tcp/StateObject.cs
deleted file mode 100644 (file)
index bee3d66..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Hazel.Tcp
-{
-    /// <summary>
-    ///     Represents the state of the current receive operation for TCP connections.
-    /// </summary>
-    struct StateObject
-    {
-        /// <summary>
-        ///     The buffer we're receiving.
-        /// </summary>
-        internal MessageReader message;
-
-        /// <summary>
-        ///     The total number of bytes received so far.
-        /// </summary>
-        internal int totalBytesReceived;
-
-        /// <summary>
-        ///     The callback to invoke once the buffer has been filled.
-        /// </summary>
-        internal Action<MessageReader> callback;
-
-        internal readonly int ExpectedSize;
-
-        /// <summary>
-        ///     Creates a StateObject with the specified length.
-        /// </summary>
-        /// <param name="length">The number of bytes expected to be received.</param>
-        /// <param name="callback">The callback to invoke once data has been received.</param>
-        internal StateObject(int length, Action<MessageReader> callback)
-        {
-            this.message = MessageReader.GetSized(ushort.MaxValue);
-            this.totalBytesReceived = 0;
-            this.callback = callback;
-            this.ExpectedSize = length;
-        }
-    }
-}
\ No newline at end of file
diff --git a/Hazel/Tcp/TcpConnection.cs b/Hazel/Tcp/TcpConnection.cs
deleted file mode 100644 (file)
index 8103885..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading;
-
-namespace Hazel.Tcp
-{
-    /// <summary>
-    ///     Represents a connection that uses the TCP protocol.
-    /// </summary>
-    /// <inheritdoc />
-    public sealed class TcpConnection : NetworkConnection
-    {
-        /// <summary>
-        ///     The socket we're managing.
-        /// </summary>
-        Socket socket;
-
-        /// <summary>
-        ///     Creates a TcpConnection from a given TCP Socket.
-        /// </summary>
-        /// <param name="socket">The TCP socket to wrap.</param>
-        internal TcpConnection(Socket socket)
-        {
-            //Check it's a TCP socket
-            if (socket.ProtocolType != ProtocolType.Tcp)
-                throw new ArgumentException("A TcpConnection requires a TCP socket.");
-
-            this.EndPoint = (IPEndPoint)socket.RemoteEndPoint;
-            this.RemoteEndPoint = socket.RemoteEndPoint;
-
-            this.socket = socket;
-            this.socket.NoDelay = true;
-
-            State = ConnectionState.Connected;
-        }
-
-        /// <summary>
-        ///     Creates a new TCP connection.
-        /// </summary>
-        /// <param name="remoteEndPoint">A <see cref="NetworkEndPoint"/> to connect to.</param>
-        public TcpConnection(IPEndPoint remoteEndPoint, IPMode ipMode = IPMode.IPv4)
-        {
-            this.EndPoint = remoteEndPoint;
-            this.RemoteEndPoint = remoteEndPoint;
-            this.IPMode = ipMode;
-
-            //Create a socket
-            if (ipMode == IPMode.IPv4)
-                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
-            else
-            {
-                if (!Socket.OSSupportsIPv6)
-                    throw new InvalidOperationException("IPV6 not supported!");
-
-                socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
-                socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
-            }
-
-            socket.NoDelay = true;
-        }
-
-        /// <inheritdoc />
-        public override void Connect(byte[] bytes = null, int timeout = 5000)
-        {
-            //Connect
-            State = ConnectionState.Connecting;
-
-            try
-            {
-                IAsyncResult result = socket.BeginConnect(RemoteEndPoint, null, null);
-
-                result.AsyncWaitHandle.WaitOne(timeout);
-
-                socket.EndConnect(result);
-            }
-            catch (Exception e)
-            {
-                throw new HazelException("Could not connect as an exception occured.", e);
-            }
-
-            //Start receiving data
-            try
-            {
-                var msg = MessageReader.GetSized(ushort.MaxValue);
-
-                ListenForData(msg, InvokeAndListen);
-            }
-            catch (Exception e)
-            {
-                throw new HazelException("An exception occured while initiating the first receive operation.", e);
-            }
-
-            //Set connected
-            State = ConnectionState.Connected;
-
-            //Send handshake
-            byte[] actualBytes;
-            if (bytes == null)
-            {
-                actualBytes = new byte[1];
-            }
-            else
-            {
-                actualBytes = new byte[bytes.Length + 1];
-                Buffer.BlockCopy(bytes, 0, actualBytes, 1, bytes.Length);
-            }
-
-            SendBytes(actualBytes);
-        }
-
-        public override void ConnectAsync(byte[] bytes = null, int timeout = 5000)
-        {
-            throw new NotImplementedException("I don't need this, so I didn't make it.");
-        }
-
-        public override void Send(MessageWriter msg)
-        {
-            if (msg.SendOption != SendOption.Tcp) throw new InvalidOperationException("Sorry, no can do, holmes.");
-
-            if (State != ConnectionState.Connected)
-                throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?");
-
-            var fullBytes = PrependLengthHeader(msg.Buffer, msg.Length);
-
-            try
-            {
-                socket.BeginSend(fullBytes, 0, fullBytes.Length, SocketFlags.None, FinishSend, null);
-            }
-            catch (Exception e)
-            {
-                Disconnect("Could not send data as an occured: " + e.Message);
-            }
-
-            Statistics.LogFragmentedSend(msg.Length, fullBytes.Length);
-        }
-
-        /// <inheritdoc/>
-        /// <remarks>
-        ///     <include file="DocInclude/common.xml" path="docs/item[@name='Connection_SendBytes_General']/*" />
-        ///     <para>
-        ///         The sendOption parameter is ignored by the TcpConnection as TCP only supports FragmentedReliable 
-        ///         communication, specifying anything else will have no effect.
-        ///     </para>
-        /// </remarks>
-        public override void SendBytes(byte[] bytes, SendOption sendOption = SendOption.Tcp)
-        {
-            if (State != ConnectionState.Connected)
-                throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?");
-
-            var fullBytes = PrependLengthHeader(bytes);
-
-            try
-            {
-                socket.BeginSend(fullBytes, 0, fullBytes.Length, SocketFlags.None, FinishSend, null);
-            }
-            catch (Exception e)
-            {
-                Disconnect("Could not send data as an occured: " + e.Message);
-            }
-
-            Statistics.LogFragmentedSend(bytes.Length, fullBytes.Length);
-        }
-
-        private void FinishSend(IAsyncResult ar)
-        {
-            try
-            {
-                this.socket.EndSend(ar);
-            }
-            catch { }
-        }
-
-        /// <summary>
-        ///     Starts waiting for a first handshake packet to be received.
-        /// </summary>
-        /// <param name="callback">The callback to invoke when the handshake has been received.</param>
-        internal void StartWaitingForHandshake(Action<MessageReader> callback)
-        {
-            this.State = ConnectionState.Connected;
-
-            var buffer = MessageReader.GetSized(ushort.MaxValue);
-            try
-            {
-                buffer.Offset = 0;
-                buffer.Length = 4;
-                buffer.Position = 0;
-
-                ListenForData(
-                    buffer,
-                    m => ReadHeader(m,
-                        delegate (MessageReader msg)
-                        {
-                            ListenForData();
-
-                            //Remove version byte
-                            msg.Offset = 1;
-                            msg.Length -= 1;
-                            msg.Position = 0;
-
-                            callback.Invoke(msg);
-                        })
-                );
-            }
-            catch (Exception e)
-            {
-                buffer.Recycle();
-                Disconnect("An exception occured while initiating the first receive operation: " + e.Message);
-            }
-        }
-
-        private void InvokeAndListen(MessageReader msg)
-        {
-            this.ListenForData();
-
-            try
-            {
-                this.InvokeDataReceived(msg, SendOption.Tcp);
-            }
-            catch { }
-        }
-        
-        private void ListenForData()
-        {
-            var msg = MessageReader.GetSized(ushort.MaxValue);
-            msg.Offset = 0;
-            msg.Length = 4;
-            msg.Position = 0;
-
-            ListenForData(msg, m => ReadHeader(m, null));
-        }
-
-        private void ReadHeader(MessageReader msg, Action<MessageReader> callback)
-        {
-            msg.Length = GetLengthFromBytes(msg.Buffer);
-            msg.Position = 0;
-
-            ListenForData(msg, callback ?? InvokeAndListen);
-        }
-
-        private void ListenForData(MessageReader msg, Action<MessageReader> callback)
-        {
-            if (State == ConnectionState.Disconnecting || State == ConnectionState.NotConnected)
-                throw new HazelException("Not connected");
-            
-            try
-            {
-                socket.BeginReceive(msg.Buffer, msg.Position, msg.Length, SocketFlags.None, o => ReadUntilFull(callback, o), msg);
-            }
-            catch (SocketException s)
-            {
-                msg.Recycle();
-                Disconnect("SocketException while reading header: " + s.Message);
-            }
-        }
-        
-        private void ReadUntilFull(Action<MessageReader> callback, IAsyncResult result)
-        {
-            int bytesRead;
-            try
-            {
-                bytesRead = socket.EndReceive(result);
-                if (bytesRead == 0)
-                {
-                    Disconnect("Received 0 bytes");
-                    return;
-                }
-            }
-            catch (ObjectDisposedException) { return; }
-            catch (SocketException s)
-            {
-                Disconnect("SocketException while reading body: " + s.Message);
-                return;
-            }
-
-            var msg = (MessageReader)result.AsyncState;
-            msg.Position += bytesRead;
-
-            Statistics.LogFragmentedReceive(bytesRead, 0);
-
-            if (msg.Position < msg.Length)
-            {
-                ListenForData(msg, callback);
-            }
-            else
-            {
-                try
-                {
-                    msg.Position = 0;
-                    callback(msg);
-                }
-                catch { }
-            }
-        }
-
-        protected override void SendDisconnect()
-        {
-            // Just dispose the connection, it's inherent to TCP.
-        }
-
-        /// <summary>
-        ///     Appends the length header to the bytes.
-        /// </summary>
-        /// <param name="bytes">The source bytes.</param>
-        /// <returns>The new bytes.</returns>
-        private static byte[] PrependLengthHeader(byte[] bytes, int length = -1)
-        {
-            length = length > -1 ? length : bytes.Length;
-
-            byte[] fullBytes = new byte[length + 4];
-            Buffer.BlockCopy(bytes, 0, fullBytes, 4, length);
-
-            fullBytes[0] = (byte)(length >> 24);
-            fullBytes[1] = (byte)(length >> 16);
-            fullBytes[2] = (byte)(length >> 8);
-            fullBytes[3] = (byte)length;
-
-            return fullBytes;
-        }
-
-        /// <summary>
-        ///     Returns the length from a length header.
-        /// </summary>
-        /// <param name="bytes">The bytes received.</param>
-        /// <returns>The number of bytes.</returns>
-        static int GetLengthFromBytes(byte[] bytes)
-        {
-            if (bytes.Length < 4)
-                throw new IndexOutOfRangeException("Not enough bytes passed to calculate length.");
-
-            return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
-        }
-
-        /// <inheritdoc />
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing)
-            {
-                lock (this)
-                {
-                    State = ConnectionState.NotConnected;
-
-                    try { this.socket.Shutdown(SocketShutdown.Both); } catch { }
-                    try { this.socket.Close(); } catch { }
-                    try { this.socket.Dispose(); } catch { }
-                }
-            }
-
-            base.Dispose(disposing);
-        }
-    }
-}
\ No newline at end of file
diff --git a/Hazel/Tcp/TcpConnectionListener.cs b/Hazel/Tcp/TcpConnectionListener.cs
deleted file mode 100644 (file)
index 4b9fcd2..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Sockets;
-
-namespace Hazel.Tcp
-{
-    public sealed class TcpConnectionListener : NetworkConnectionListener
-    {
-        private Socket listener;
-
-        /// <summary>
-        ///     Creates a new TcpConnectionListener for the given <see cref="IPAddress"/>, port and <see cref="IPMode"/>.
-        /// </summary>
-        /// <param name="endPoint">The end point to listen on.</param>
-        public TcpConnectionListener(IPEndPoint endPoint, IPMode ipMode = IPMode.IPv4)
-        {
-            this.EndPoint = endPoint;
-            this.IPMode = ipMode;
-
-            if (this.IPMode == IPMode.IPv4)
-                this.listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-            else
-            {
-                if (!Socket.OSSupportsIPv6)
-                    throw new InvalidOperationException("IPV6 not supported!");
-
-                this.listener = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
-                this.listener.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
-            }
-        }
-
-        /// <inheritdoc />
-        public override void Start()
-        {
-            try
-            {
-                listener.Bind(EndPoint);
-                listener.Listen(1000);
-
-                listener.BeginAccept(AcceptConnection, null);
-            }
-            catch (SocketException e)
-            {
-                throw new HazelException("Could not start listening as a SocketException occured", e);
-            }
-        }
-
-        /// <summary>
-        ///     Called when a new connection has been accepted by the listener.
-        /// </summary>
-        /// <param name="result">The asyncronous operation's result.</param>
-        void AcceptConnection(IAsyncResult result)
-        {
-            //Accept Tcp socket
-            Socket tcpSocket;
-            try
-            {
-                tcpSocket = listener.EndAccept(result);
-            }
-            catch (ObjectDisposedException)
-            {
-                //If the socket's been disposed then we can just end there.
-                return;
-            }
-
-            //Start listening for the next connection
-            listener.BeginAccept(AcceptConnection, null);
-
-            //Sort the event out
-            TcpConnection tcpConnection = new TcpConnection(tcpSocket);
-
-            //Wait for handshake
-            tcpConnection.StartWaitingForHandshake(
-                delegate (MessageReader msg)
-                {
-                    InvokeNewConnection(msg, tcpConnection);
-                }
-            );
-        }
-
-        /// <inheritdoc/>
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing)
-            {
-                listener.Dispose();
-            }
-
-            base.Dispose(disposing);
-        }
-    }
-}
\ No newline at end of file
index ee678fbbfc35b7f72f0662974848ca0797e90499..9ada44aac608f7e55fa068a36a85ed649f99c7c9 100644 (file)
@@ -55,7 +55,11 @@ namespace Hazel.Udp
         private void ManageReliablePacketsInternal(object state)
         {
             base.ManageReliablePackets();
-            reliablePacketTimer.Change(100, Timeout.Infinite);
+            try
+            {
+                reliablePacketTimer.Change(100, Timeout.Infinite);
+            }
+            catch { }
         }
 
         /// <inheritdoc />