]> git.deb.at Git - rhonda/impostor.hazel.git/commitdiff
Clean up some stuff, fix a thing where 0 retries wasn't infinite
authorForest <chocozilla@gmail.com>
Thu, 7 Mar 2019 04:00:02 +0000 (20:00 -0800)
committerForest <chocozilla@gmail.com>
Thu, 7 Mar 2019 04:00:02 +0000 (20:00 -0800)
Hazel/Connection.cs
Hazel/MessageWriter.cs
Hazel/Tcp/TcpConnection.cs
Hazel/Udp/UdpBroadcastListener.cs
Hazel/Udp/UdpBroadcaster.cs
Hazel/Udp/UdpClientConnection.cs
Hazel/Udp/UdpConnection.Reliable.cs
Hazel/Udp/UdpConnectionListener.cs

index 998fe6a9c155b6539f0d3f481901b05d373eff73..964e82d5f5091c045bfb2a2c8e151f0e72c75691 100644 (file)
@@ -51,6 +51,8 @@ namespace Hazel
         public event Action<DataReceivedEventArgs> DataReceived;
 
         public int TestLagMs = -1;
+        public int TestDropRate = 0;
+        protected int testDropCount = 0;
         
         /// <summary>
         ///     Called when the end point disconnects or an error occurs.
index bd00eb540b127709980188673d8d0bdaf0d1ef51..54f0dd108fef9afb10411d8e2ffe74cc4ddfb923 100644 (file)
@@ -57,8 +57,8 @@ namespace Hazel
                         }
                     case SendOption.Tcp:
                         {
-                            byte[] output = new byte[this.Length - 4];
-                            System.Buffer.BlockCopy(this.Buffer, 4, output, 0, this.Length - 4);
+                            byte[] output = new byte[this.Length];
+                            System.Buffer.BlockCopy(this.Buffer, 0, output, 0, this.Length);
                             return output;
                         }
                 }
@@ -113,9 +113,8 @@ namespace Hazel
 
         public void Clear(SendOption sendOption)
         {
-            this.Position = this.Length = 0;
+            this.messageStarts.Clear();
             this.SendOption = sendOption;
-
             this.Buffer[0] = (byte)sendOption;
             switch (sendOption)
             {
@@ -126,6 +125,7 @@ namespace Hazel
                     this.Length = this.Position = 3;
                     break;
                 case SendOption.Tcp:
+                    this.Length = this.Position = 0;
                     break;
             }
         }
index 8c350d957544b3e757a58595024fca91e8d27130..fc63ae7748eb6abc9b1fcd07e6a39f207fda3262 100644 (file)
@@ -84,7 +84,9 @@ namespace Hazel.Tcp
             //Start receiving data
             try
             {
-                ListenForData(InvokeAndListen);
+                var msg = MessageReader.GetSized(ushort.MaxValue);
+
+                ListenForData(msg, InvokeAndListen);
             }
             catch (Exception e)
             {
@@ -170,31 +172,39 @@ namespace Hazel.Tcp
         {
             this.State = ConnectionState.Connected;
 
+            var buffer = MessageReader.GetSized(ushort.MaxValue);
             try
             {
-                ListenForData(
-                    delegate (MessageReader msg)
-                    {
-                        ListenForData(InvokeAndListen);
-
-                        //Remove version byte
-                        msg.Offset = 1;
-                        msg.Length -= 1;
-                        msg.Position = 0;
+                buffer.Offset = 0;
+                buffer.Length = 4;
+                buffer.Position = 0;
 
-                        callback.Invoke(msg);
-                    }
+                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(InvokeAndListen);
+            this.ListenForData();
 
             try
             {
@@ -202,58 +212,42 @@ namespace Hazel.Tcp
             }
             catch { }
         }
-
-        private void ListenForData(Action<MessageReader> callback)
+        
+        private void ListenForData()
         {
-            if (State == ConnectionState.Disconnecting || State == ConnectionState.NotConnected)
-                throw new HazelException("Not connected");
-
             var msg = MessageReader.GetSized(ushort.MaxValue);
-            try
-            {
-                socket.BeginReceive(msg.Buffer, 0, 4, SocketFlags.None, o => HeaderReadCallback(callback, o), msg);
-            }
-            catch (SocketException s)
-            {
-                Disconnect("SocketException while reading header: " + s.Message);
-            }
+            msg.Offset = 0;
+            msg.Length = 4;
+            msg.Position = 0;
+
+            ListenForData(msg, m => ReadHeader(m, null));
         }
 
-        private void HeaderReadCallback(Action<MessageReader> callback, IAsyncResult result)
+        private void ReadHeader(MessageReader msg, Action<MessageReader> callback)
         {
-            int bytesRead;
-            try
-            {
-                bytesRead = socket.EndReceive(result);
-                if (bytesRead == 0)
-                {
-                    Disconnect("Received 0 bytes");
-                    return;
-                }
-
-                Statistics.LogFragmentedReceive(0, bytesRead);
-            }
-            catch (SocketException s)
-            {
-                Disconnect("SocketException while reading header: " + s.Message);
-                return;
-            }
-
-            // TODO: Could possibly fragment here...
-            var msg = (MessageReader)result.AsyncState;
             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, 0, msg.Length, SocketFlags.None, o => BodyReadCallback(callback, o), msg);
+                socket.BeginReceive(msg.Buffer, msg.Position, msg.Length, SocketFlags.None, o => ReadUntilFull(callback, o), msg);
             }
             catch (SocketException s)
             {
-                Disconnect("SocketException while reading body: " + s.Message);
+                msg.Recycle();
+                Disconnect("SocketException while reading header: " + s.Message);
             }
         }
-
-        private void BodyReadCallback(Action<MessageReader> callback, IAsyncResult result)
+        
+        private void ReadUntilFull(Action<MessageReader> callback, IAsyncResult result)
         {
             int bytesRead;
             try
@@ -278,14 +272,7 @@ namespace Hazel.Tcp
 
             if (msg.Position < bytesRead)
             {
-                try
-                {
-                    socket.BeginReceive(msg.Buffer, msg.Position, msg.Length - msg.Position, SocketFlags.None, o => BodyReadCallback(callback, o), msg);
-                }
-                catch (SocketException s)
-                {
-                    Disconnect("SocketException while reading body: " + s.Message);
-                }
+                ListenForData(msg, callback);
             }
             else
             {
index 530433257104d6ac39e83eb9ff5558e587b9ef22..fb8c52ab8daf7d39231ce538d1eacc3e8a5a2856 100644 (file)
@@ -97,7 +97,7 @@ namespace Hazel.Udp
             }
 
             IPEndPoint ipEnd = (IPEndPoint)endpt;
-            string data = ASCIIEncoding.ASCII.GetString(buffer, 2, numBytes - 2);
+            string data = UTF8Encoding.UTF8.GetString(buffer, 2, numBytes - 2);
             int dataHash = data.GetHashCode();
 
             lock (packets)
@@ -139,7 +139,21 @@ namespace Hazel.Udp
         {
             if (this.socket != null)
             {
-                this.socket.Close();
+                try
+                {
+                    this.socket.Shutdown(SocketShutdown.Both);
+                }
+                catch { }
+                try
+                {
+                    this.socket.Close();
+                }
+                catch { }
+                try
+                {
+                    this.socket.Dispose();
+                }
+                catch { }
                 this.socket = null;
             }
         }
index 872e68593fa2119e091f0462f95254354e12911b..d0a9f8454cdf1f1957856e493aa09e775fb6d490 100644 (file)
@@ -28,12 +28,12 @@ namespace Hazel.Udp
         ///
         public void SetData(string data)
         {
-            int len = ASCIIEncoding.ASCII.GetByteCount(data);
+            int len = UTF8Encoding.UTF8.GetByteCount(data);
             this.data = new byte[len + 2];
             this.data[0] = 4;
             this.data[1] = 2;
 
-            ASCIIEncoding.ASCII.GetBytes(data, 0, data.Length, this.data, 2);
+            UTF8Encoding.UTF8.GetBytes(data, 0, data.Length, this.data, 2);
         }
 
         ///
@@ -52,7 +52,21 @@ namespace Hazel.Udp
         {
             if (this.socket != null)
             {
-                this.socket.Close();
+                try
+                {
+                    this.socket.Shutdown(SocketShutdown.Both);
+                }
+                catch { }
+                try
+                {
+                    this.socket.Close();
+                }
+                catch { }
+                try
+                {
+                    this.socket.Dispose();
+                }
+                catch { }
                 this.socket = null;
             }
         }
index a76bdeb38ddfbc35dde3ee575a1a3126fcdad935..58a16be6f841919bb7ddc14605afb404a7b9c0f8 100644 (file)
@@ -18,14 +18,14 @@ namespace Hazel.Udp
         /// <summary>
         ///     The socket we're connected via.
         /// </summary>
-        Socket socket;
+        private Socket socket;
 
         /// <summary>
         ///     The buffer to store incomming data in.
         /// </summary>
-        byte[] dataBuffer = new byte[ushort.MaxValue];
+        private byte[] dataBuffer = new byte[ushort.MaxValue];
 
-        Timer reliablePacketTimer;
+        private Timer reliablePacketTimer;
 
         /// <summary>
         ///     Creates a new UdpClientConnection.
@@ -76,7 +76,6 @@ namespace Hazel.Udp
             }
         }
 
-
         public event Action<byte[], int> DataSentRaw;
         public event Action<byte[]> DataReceivedRaw;
 
@@ -267,6 +266,14 @@ namespace Hazel.Udp
                 Thread.Sleep(this.TestLagMs);
             }
 
+            if (this.TestDropRate > 0)
+            {
+                if ((this.testDropCount++ % this.TestDropRate) == 0)
+                {
+                    return;
+                }
+            }
+
             DataReceivedRaw?.Invoke(bytes);
             MessageReader msg = MessageReader.GetRaw(bytes, 0, bytesReceived);
             HandleReceive(msg, bytesReceived);
index 68e1d9201f3aa95862da627796adba4261182c6b..1b0c342fa0b194bfb5294ff30881be631dfbebf6 100644 (file)
@@ -25,11 +25,17 @@ namespace Hazel.Udp
         ///         resulting in a more dynamic resend that responds to endpoints on slower or faster connections.
         ///     </para>
         /// </remarks>
-        public int ResendTimeout { get { return resendTimeout; } set { resendTimeout = value; } }
-        private volatile int resendTimeout = 0;
+        public volatile int ResendTimeout = 0;
 
+        /// <summary>
+        /// Max number of times to resend. 0 == no limit
+        /// </summary>
         public volatile int ResendLimit = 0;
 
+        /// <summary>
+        /// A compounding multiplier to back off resend timeout.
+        /// Applied to ping before first timeout when ResendTimeout == 0.
+        /// </summary>
         public volatile float ResendPingMultiplier = 3;
 
         /// <summary>
@@ -40,24 +46,24 @@ namespace Hazel.Udp
         /// <summary>
         ///     The packets of data that have been transmitted reliably and not acknowledged.
         /// </summary>
-        ConcurrentDictionary<ushort, Packet> reliableDataPacketsSent = new ConcurrentDictionary<ushort, Packet>();
+        internal ConcurrentDictionary<ushort, Packet> reliableDataPacketsSent = new ConcurrentDictionary<ushort, Packet>();
 
         /// <summary>
         ///     The last packets that were received.
         /// </summary>
-        HashSet<ushort> reliableDataPacketsMissing = new HashSet<ushort>();
+        private HashSet<ushort> reliableDataPacketsMissing = new HashSet<ushort>();
 
         /// <summary>
         ///     The packet id that was received last.
         /// </summary>
-        volatile ushort reliableReceiveLast = 0;
-        
+        private volatile ushort reliableReceiveLast = 0;
+
         /// <summary>
         ///     Has the connection received anything yet
         /// </summary>
-        volatile bool hasReceivedSomething = false;
+        private volatile bool hasReceivedSomething = false;
 
-        object PingLock = new object();
+        private object PingLock = new object();
 
         /// <summary>
         ///     Returns the average ping to this endpoint.
@@ -77,7 +83,7 @@ namespace Hazel.Udp
         ///     connection will be marked as disconnected and the <see cref="Connection.Disconnected">Disconnected</see> event
         ///     will be invoked.
         /// </remarks>
-        public volatile int DisconnectTimeout = 2500;
+        public volatile int DisconnectTimeout = 5000;
 
         /// <summary>
         ///     Class to hold packet data
@@ -110,11 +116,11 @@ namespace Hazel.Udp
 
             public int Retransmissions;
             public Stopwatch Stopwatch = new Stopwatch();
-            
+
             Packet()
             {
             }
-            
+
             internal void Set(ushort id, UdpConnection connection, byte[] data, int length, int timeout, Action ackCallback)
             {
                 this.Id = id;
@@ -151,7 +157,9 @@ namespace Hazel.Udp
 
                     if (lifetime >= this.NextTimeout)
                     {
-                        if (++this.Retransmissions > connection.ResendLimit)
+                        ++this.Retransmissions;
+                        if (connection.ResendLimit != 0
+                            && this.Retransmissions > connection.ResendLimit)
                         {
                             if (connection.reliableDataPacketsSent.TryRemove(this.Id, out Packet self))
                             {
@@ -163,7 +171,7 @@ namespace Hazel.Udp
                             return 0;
                         }
 
-                        this.NextTimeout = (int)Math.Min(this.NextTimeout * 3f, connection.DisconnectTimeout);
+                        this.NextTimeout = (int)Math.Min(this.NextTimeout * connection.ResendPingMultiplier, connection.DisconnectTimeout);
                         try
                         {
                             connection.WriteBytesToConnection(this.Data, this.Length);
@@ -190,13 +198,12 @@ namespace Hazel.Udp
                 PacketPool.PutObject(this);
             }
         }
-                
+
         internal int ManageReliablePackets()
         {
             int output = 0;
             if (this.reliableDataPacketsSent.Count > 0)
             {
-                double minTimeout = int.MaxValue;
                 foreach (var kvp in this.reliableDataPacketsSent)
                 {
                     Packet pkt = kvp.Value;
@@ -206,8 +213,6 @@ namespace Hazel.Udp
                         output += pkt.Resend();
                     }
                     catch { }
-
-                    minTimeout = Math.Min(pkt.NextTimeout, minTimeout);
                 }
             }
 
@@ -238,7 +243,7 @@ namespace Hazel.Udp
                 this,
                 buffer,
                 sendLength,
-                resendTimeout > 0 ? resendTimeout : (int)Math.Max(300, Math.Min(AveragePingMs * this.ResendPingMultiplier, 2000)),
+                ResendTimeout > 0 ? ResendTimeout : (int)Math.Max(300, Math.Min(AveragePingMs * this.ResendPingMultiplier, 2000)),
                 ackCallback);
 
             if (!reliableDataPacketsSent.TryAdd(id, packet))
index 1058980a3ff5e80037dd51df59ebf1d66c063240..b38530da210f852ced7b9bc3d9facd06e7ab91dc 100644 (file)
@@ -67,21 +67,15 @@ namespace Hazel.Udp
         {
             this.Dispose(false);
         }
-
-        public float AveragePacketsTime = 1;
-
-        Stopwatch stopwatch = new Stopwatch();
+        
         private void ManageReliablePackets(object state)
         {
-            stopwatch.Restart();
             foreach (var kvp in this.allConnections)
             {
                 var sock = kvp.Value;
                 sock.ManageReliablePackets();
             }
-
-            this.AveragePacketsTime = this.AveragePacketsTime * .7f + stopwatch.ElapsedMilliseconds * .3f;
-
+            
             this.reliablePacketTimer.Change(100, Timeout.Infinite);
         }
 
@@ -336,6 +330,11 @@ namespace Hazel.Udp
 
             if (this.socket != null)
             {
+                try
+                {
+                    this.socket.Shutdown(SocketShutdown.Both);
+                }
+                catch { }
                 this.socket.Close();
                 this.socket.Dispose();
                 this.socket = null;