]> git.deb.at Git - rhonda/impostor.hazel.git/commitdiff
Clean up some stuff, fix some bugs, add a new type of copy to MessageReader, add...
authorForest <chocozilla@gmail.com>
Wed, 29 May 2019 04:26:52 +0000 (21:26 -0700)
committerForest <chocozilla@gmail.com>
Wed, 29 May 2019 04:26:52 +0000 (21:26 -0700)
15 files changed:
Hazel.UnitTests/Hazel.UnitTests.csproj
Hazel.UnitTests/MessageReaderTests.cs
Hazel.UnitTests/MessageWriterTests.cs
Hazel.UnitTests/StressTests.cs [new file with mode: 0644]
Hazel.UnitTests/UdpConnectionTests.cs
Hazel.UnitTests/UnitTest1.cs [deleted file]
Hazel/Connection.cs
Hazel/ConnectionStatistics.cs
Hazel/MessageReader.cs
Hazel/Udp/UdpClientConnection.cs
Hazel/Udp/UdpConnection.KeepAlive.cs
Hazel/Udp/UdpConnection.Reliable.cs
Hazel/Udp/UdpConnection.cs
Hazel/Udp/UdpConnectionListener.cs
Hazel/Udp/UdpServerConnection.cs

index d29fb811029e7f4def354d6c04bcbda3b05ecf52..88f9a7388c2494408be926a97a47407dec139d94 100644 (file)
@@ -63,7 +63,7 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="UdpConnectionTests.cs" />
     <Compile Include="MessageWriterTests.cs" />
-    <Compile Include="UnitTest1.cs" />
+    <Compile Include="StressTests.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Hazel\Hazel.csproj">
index 9655ba5a8ea37f4c20af6b6e58baf6ace069ec43..1d5c218c52a9301670590be07102ccc162ba72f9 100644 (file)
@@ -91,6 +91,49 @@ namespace Hazel.UnitTests
 
         }
 
+        [TestMethod]
+        public void CopySubMessage()
+        {
+            const byte Test1 = 12;
+            const byte Test2 = 146;
+
+            var msg = new MessageWriter(2048);
+            msg.StartMessage(1);
+
+            msg.StartMessage(2);
+            msg.Write(Test1);
+            msg.Write(Test2);
+            msg.EndMessage();
+
+            msg.EndMessage();
+
+            MessageReader handleMessage = MessageReader.Get(msg.Buffer, 0);
+            Assert.AreEqual(1, handleMessage.Tag);
+
+            var parentReader = MessageReader.Get(handleMessage);
+
+            handleMessage.Recycle();
+            SetZero(handleMessage);
+
+            Assert.AreEqual(1, parentReader.Tag);
+
+            for (int i = 0; i < 5; ++i)
+            {
+
+                var reader = parentReader.ReadMessage();
+                Assert.AreEqual(2, reader.Tag);
+                Assert.AreEqual(Test1, reader.ReadByte());
+                Assert.AreEqual(Test2, reader.ReadByte());
+
+                var temp = parentReader;
+                parentReader = MessageReader.CopyMessageIntoParent(reader);
+
+                temp.Recycle();
+                SetZero(temp);
+                SetZero(reader);
+            }
+        }
+
         [TestMethod]
         public void ReadMessageLength()
         {
@@ -127,5 +170,12 @@ namespace Hazel.UnitTests
         {
             Assert.IsTrue(MessageWriter.IsLittleEndian());
         }
+
+        private void SetZero(MessageReader reader)
+        {
+            for (int i = 0; i < reader.Buffer.Length; ++i)
+                reader.Buffer[i] = 0;
+        }
     }
+
 }
\ No newline at end of file
index c4096be3301807957fc0650cb7b7df618f478928..b292a5db6d63544362ab5b72d1f5db602c736667 100644 (file)
@@ -145,7 +145,6 @@ namespace Hazel.UnitTests
             Assert.AreEqual(68000u, reader.ReadPackedUInt32());
         }
 
-
         [TestMethod]
         public void WritePackedInt()
         {
@@ -154,12 +153,18 @@ namespace Hazel.UnitTests
             msg.WritePacked(8);
             msg.WritePacked(250);
             msg.WritePacked(68000);
+            msg.WritePacked(60168000);
             msg.WritePacked(-68000);
             msg.WritePacked(-250);
             msg.WritePacked(-8);
+
+            msg.WritePacked(0);
+            msg.WritePacked(-1);
+            msg.WritePacked(int.MinValue);
+            msg.WritePacked(int.MaxValue);
             msg.EndMessage();
 
-            Assert.AreEqual(3 + 1 + 2 + 3 + 5 + 5 + 5, msg.Position);
+            Assert.AreEqual(3 + 1 + 2 + 3 + 4 + 5 + 5 + 5 + 1 + 5 + 5 + 5, msg.Position);
             Assert.AreEqual(msg.Length, msg.Position);
 
             MessageReader reader = MessageReader.Get(msg.Buffer, 0);
@@ -167,11 +172,16 @@ namespace Hazel.UnitTests
             Assert.AreEqual(8, reader.ReadPackedInt32());
             Assert.AreEqual(250, reader.ReadPackedInt32());
             Assert.AreEqual(68000, reader.ReadPackedInt32());
-            
-            
+            Assert.AreEqual(60168000, reader.ReadPackedInt32());
+
             Assert.AreEqual(-68000, reader.ReadPackedInt32());
             Assert.AreEqual(-250, reader.ReadPackedInt32());
             Assert.AreEqual(-8, reader.ReadPackedInt32());
+
+            Assert.AreEqual(0, reader.ReadPackedInt32());
+            Assert.AreEqual(-1, reader.ReadPackedInt32());
+            Assert.AreEqual(int.MinValue, reader.ReadPackedInt32());
+            Assert.AreEqual(int.MaxValue, reader.ReadPackedInt32());
         }
 
         [TestMethod]
diff --git a/Hazel.UnitTests/StressTests.cs b/Hazel.UnitTests/StressTests.cs
new file mode 100644 (file)
index 0000000..b670edc
--- /dev/null
@@ -0,0 +1,30 @@
+using System;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+using Hazel.Udp;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Hazel.UnitTests
+{
+    [TestClass]
+    public class StressTests
+    {
+        // [TestMethod]
+        public void StressTestOpeningConnections()
+        {
+            // Start a listener in another process, or even better, 
+            // adjust the target IP and start listening on another computer.
+            var ep = new IPEndPoint(IPAddress.Loopback, 22023);
+            Parallel.For(0, 10000,
+                new ParallelOptions { MaxDegreeOfParallelism = 64 },
+                (i) => {
+                    
+                var connection = new UdpClientConnection(ep);
+                connection.KeepAliveInterval = 50;
+
+                connection.Connect(new byte[5]);
+            });
+        }
+    }
+}
index 17515f4dafc0288c5e6cbc913ea0e651a5c27a6b..26352b5d4aa093c0e76f075954c4d9949e074561 100644 (file)
@@ -11,6 +11,69 @@ namespace Hazel.UnitTests
     [TestClass]
     public class UdpConnectionTests
     {
+        [TestMethod]
+        public void ServerDisposeDisconnectsTest()
+        {
+            IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 4296);
+
+            bool serverConnected = false;
+            bool serverDisconnected = false;
+            bool clientDisconnected = false;
+
+            using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296)))
+            using (UdpConnection connection = new UdpClientConnection(ep))
+            {
+                listener.NewConnection += (evt) =>
+                {
+                    serverConnected = true;
+                    evt.Connection.Disconnected += (o, et) => serverDisconnected = true;
+                };
+                connection.Disconnected += (o, evt) => clientDisconnected = true;
+
+                listener.Start();
+                connection.Connect();
+
+                listener.Dispose();
+                Thread.Sleep(10);
+
+                Assert.IsTrue(serverConnected);
+                Assert.IsTrue(clientDisconnected);
+                Assert.IsFalse(serverDisconnected);
+            }
+        }
+
+        [TestMethod]
+        public void ClientServerDisposeDisconnectsTest()
+        {
+            IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 4296);
+
+            bool serverConnected = false;
+            bool serverDisconnected = false;
+            bool clientDisconnected = false;
+
+            using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296)))
+            using (UdpConnection connection = new UdpClientConnection(ep))
+            {
+                listener.NewConnection += (evt) =>
+                {
+                    serverConnected = true;
+                    evt.Connection.Disconnected += (o, et) => serverDisconnected = true;
+                };
+
+                connection.Disconnected += (o, et) => clientDisconnected = true;
+
+                listener.Start();
+                connection.Connect();
+                connection.Dispose();
+
+                Thread.Sleep(10);
+
+                Assert.IsTrue(serverConnected);
+                Assert.IsTrue(serverDisconnected);
+                Assert.IsFalse(clientDisconnected);
+            }
+        }
+
         /// <summary>
         ///     Tests the fields on UdpConnection.
         /// </summary>
@@ -208,7 +271,37 @@ namespace Hazel.UnitTests
                 TestHelper.RunClientToServerTest(listener, connection, 10, SendOption.Reliable);
             }
         }
-        
+
+        /// <summary>
+        ///     Tests the keepalive functionality from the client,
+        /// </summary>
+        [TestMethod]
+        public void PingDisconnectClientTest()
+        {
+#if DEBUG
+            using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296)))
+            using (UdpConnection connection = new UdpClientConnection(new IPEndPoint(IPAddress.Loopback, 4296)))
+            {
+                listener.Start();
+
+                connection.Connect();
+
+                // After connecting, quietly stop responding to all messages to fake connection loss.
+                Thread.Sleep(10);
+                listener.TestDropRate = 1;
+
+                connection.KeepAliveInterval = 100;
+
+                Thread.Sleep(1050);    //Enough time for ~10 keep alive packets
+
+                Assert.AreEqual(ConnectionState.NotConnected, connection.State);
+                Assert.AreEqual(3 * connection.MissingPingsUntilDisconnect + 4, connection.Statistics.TotalBytesSent); // + 4 for connecting overhead
+            }
+#else
+            Assert.Inconclusive("Only works in DEBUG");
+#endif
+        }
+
         /// <summary>
         ///     Tests the keepalive functionality from the client,
         /// </summary>
@@ -225,6 +318,7 @@ namespace Hazel.UnitTests
 
                 System.Threading.Thread.Sleep(1050);    //Enough time for ~10 keep alive packets
 
+                Assert.AreEqual(ConnectionState.Connected, connection.State);
                 Assert.IsTrue(
                     connection.Statistics.TotalBytesSent >= 30 &&
                     connection.Statistics.TotalBytesSent <= 50,
@@ -244,24 +338,15 @@ namespace Hazel.UnitTests
             using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296)))
             using (UdpConnection connection = new UdpClientConnection(new IPEndPoint(IPAddress.Loopback, 4296)))
             {
-                listener.NewConnection += delegate(NewConnectionEventArgs args)
+                UdpConnection client = null;
+                listener.NewConnection += delegate (NewConnectionEventArgs args)
                 {
-                    ((UdpConnection)args.Connection).KeepAliveInterval = 100;
+                    client = (UdpConnection)args.Connection;
+                    client.KeepAliveInterval = 100;
 
                     Thread.Sleep(1050);    //Enough time for ~10 keep alive packets
 
-                    try
-                    {
-                        Assert.IsTrue(
-                            args.Connection.Statistics.TotalBytesSent >= 30 &&
-                            args.Connection.Statistics.TotalBytesSent <= 50,
-                            "Sent: " + args.Connection.Statistics.TotalBytesSent
-                        );
-                    }
-                    finally
-                    {
-                        mutex.Set();
-                    }
+                    mutex.Set();
                 };
 
                 listener.Start();
@@ -269,6 +354,14 @@ namespace Hazel.UnitTests
                 connection.Connect();
 
                 mutex.WaitOne();
+
+                Assert.AreEqual(ConnectionState.Connected, client.State);
+
+                Assert.IsTrue(
+                    client.Statistics.TotalBytesSent >= 27 &&
+                    client.Statistics.TotalBytesSent <= 50,
+                    "Sent: " + client.Statistics.TotalBytesSent
+                );
             }
         }
 
diff --git a/Hazel.UnitTests/UnitTest1.cs b/Hazel.UnitTests/UnitTest1.cs
deleted file mode 100644 (file)
index 0bc8026..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using Hazel.Udp;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace Hazel.UnitTests
-{
-    [TestClass]
-    public class UnitTest1
-    {
-        // [TestMethod]
-        public void StressTest()
-        {
-            var ep = new IPEndPoint(IPAddress.Loopback, 22023);
-            Parallel.For(0, 10000,
-                new ParallelOptions { MaxDegreeOfParallelism = 64 },
-                (i) => {
-                    
-                var connection = new UdpClientConnection(ep);
-                connection.KeepAliveInterval = 50;
-
-                connection.Connect(new byte[5]);
-            });
-        }
-    }
-}
index 964e82d5f5091c045bfb2a2c8e151f0e72c75691..f30d948054209cb4ebfb355b5eb3e482578f7c0c 100644 (file)
@@ -133,7 +133,7 @@ namespace Hazel
         /// <summary>
         ///     Reset event that is triggered when the connection is marked Connected.
         /// </summary>
-        ManualResetEvent connectWaitLock = new ManualResetEvent(false);
+        private ManualResetEvent connectWaitLock = new ManualResetEvent(false);
 
         /// <summary>
         ///     Constructor that initializes the ConnecitonStatistics object.
@@ -291,6 +291,7 @@ namespace Hazel
             {
                 this.DataReceived = null;
                 this.Disconnected = null;
+                this.connectWaitLock.Dispose();
             }
         }
     }
index 7e11c204d4465d3d5f04af32760b24ebb240de1e..22a09c2c4cfaca096149b7684096e691e12b0900 100644 (file)
@@ -294,6 +294,26 @@ namespace Hazel
         /// </summary>
         int acknowledgementMessagesReceived;
 
+        /// <summary>
+        ///     The number of ping messages received.
+        /// </summary>
+        /// <remarks>
+        ///     This is the number of hello messages that were received by the <see cref="Connection"/>, incremented
+        ///     each time that LogHelloReceive is called by the Connection. Messages are counted before the receive event is invoked.
+        /// </remarks>
+        public int PingMessagesReceived
+        {
+            get
+            {
+                return pingMessagesReceived;
+            }
+        }
+
+        /// <summary>
+        ///     The number of hello messages received.
+        /// </summary>
+        int pingMessagesReceived;
+
         /// <summary>
         ///     The number of hello messages received.
         /// </summary>
@@ -510,6 +530,19 @@ namespace Hazel
             Interlocked.Add(ref totalBytesReceived, totalLength);
         }
 
+        /// <summary>
+        ///     Logs the receiving of a hello data packet in the statistics.
+        /// </summary>
+        /// <param name="totalLength">The total number of bytes received.</param>
+        /// <remarks>
+        ///     This should be called before the received event is invoked so it is up to date for subscribers to that event.
+        /// </remarks>
+        internal void LogPingReceive(int totalLength)
+        {
+            Interlocked.Increment(ref pingMessagesReceived);
+            Interlocked.Add(ref totalBytesReceived, totalLength);
+        }
+
         /// <summary>
         ///     Logs the receiving of a hello data packet in the statistics.
         /// </summary>
index 447c04d7dd721b000495a35072e13e3ac840e443..f73fa4933c23d06616f93920b6b6301b6c40f6b2 100644 (file)
@@ -57,6 +57,18 @@ namespace Hazel
             return output;
         }
 
+        public static MessageReader CopyMessageIntoParent(MessageReader source)
+        {
+            var output = MessageReader.GetSized(source.Length + 3);
+            System.Buffer.BlockCopy(source.Buffer, source.Offset - 3, output.Buffer, 0, source.Length + 3);
+
+            output.Offset = 0;
+            output.Position = 0;
+            output.Length = source.Length + 3;
+            
+            return output;
+        }
+
         public static MessageReader Get(MessageReader source)
         {
             var output = GetSized(source.Buffer.Length);
index 9ada44aac608f7e55fa068a36a85ed649f99c7c9..16b7d155bcc8e836f698ceaaf1ac54ff6a259a27 100644 (file)
@@ -41,7 +41,7 @@ namespace Hazel.Udp
                     throw new InvalidOperationException("IPV6 not supported!");
 
                 socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
-                socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);    //TODO these lines shouldn't be needed anymore
+                socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
             }
 
             reliablePacketTimer = new Timer(ManageReliablePacketsInternal, null, 100, Timeout.Infinite);
@@ -90,59 +90,34 @@ namespace Hazel.Udp
                     length,
                     SocketFlags.None,
                     RemoteEndPoint,
-                    delegate (IAsyncResult result)
-                    {
-                        try
-                        {
-                            socket.EndSendTo(result);
-                        }
-                        catch (NullReferenceException) { }
-                        catch (ObjectDisposedException)
-                        {
-                            Disconnect("Could not send as the socket was disposed of.");
-                        }
-                        catch (SocketException)
-                        {
-                            Disconnect("Could not send data as a SocketException occured.");
-                        }
-                    },
-                    null
-                );
+                    HandleSendTo,
+                    null);
             }
+            catch (NullReferenceException) { }
             catch (ObjectDisposedException)
             {
-                //User probably called Disconnect in between this method starting and here so report the issue
-                throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?");
+                // Already disposed and disconnected...
             }
-            catch (SocketException)
+            catch (SocketException ex)
             {
-                Disconnect("Could not send data as a SocketException occured.");
-                throw;
+                Disconnect("Could not send data as a SocketException occured: " + ex.Message, true);
             }
         }
 
-        protected override void WriteBytesToConnectionSync(byte[] bytes, int length)
+        private void HandleSendTo(IAsyncResult result)
         {
-            DataSentRaw?.Invoke(bytes, length);
-
             try
             {
-                socket.SendTo(
-                    bytes,
-                    0,
-                    length,
-                    SocketFlags.None,
-                    RemoteEndPoint);
+                socket.EndSendTo(result);
             }
+            catch (NullReferenceException) { }
             catch (ObjectDisposedException)
             {
-                //User probably called Disconnect in between this method starting and here so report the issue
-                throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?");
+                // Already disposed and disconnected...
             }
-            catch (SocketException)
+            catch (SocketException ex)
             {
-                Disconnect("Could not send data as a SocketException occured.");
-                throw;
+                Disconnect("Could not send data as a SocketException occured: " + ex.Message, true);
             }
         }
 
@@ -295,7 +270,12 @@ namespace Hazel.Udp
         {
             try
             {
-                WriteBytesToConnectionSync(DisconnectBytes, 1);
+                socket.SendTo(
+                    DisconnectBytes,
+                    0,
+                    1,
+                    SocketFlags.None,
+                    RemoteEndPoint);
             }
             catch { }
         }
@@ -308,8 +288,8 @@ namespace Hazel.Udp
                 if (this._state == ConnectionState.Connected
                     || this._state == ConnectionState.Disconnecting)
                 {
-                    SendDisconnect();
                     this._state = ConnectionState.NotConnected;
+                    SendDisconnect();
                 }
             }
 
index eccfc9861df46961e998d4ac11ec4c15f562609b..121ae18aaa199337c841864f3400665a6ed63d80 100644 (file)
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
@@ -10,6 +11,30 @@ namespace Hazel.Udp
 {
     partial class UdpConnection
     {
+
+        /// <summary>
+        ///     Class to hold packet data
+        /// </summary>
+        public class PingPacket : IRecyclable
+        {
+            private static readonly ObjectPool<PingPacket> PacketPool = new ObjectPool<PingPacket>(() => new PingPacket());
+
+            public readonly Stopwatch Stopwatch = new Stopwatch();
+
+            internal static PingPacket GetObject()
+            {
+                return PacketPool.GetObject();
+            }
+
+            public void Recycle()
+            {
+                Stopwatch.Stop();
+                PacketPool.PutObject(this);
+            }
+        }
+
+        internal ConcurrentDictionary<ushort, PingPacket> activePingPackets = new ConcurrentDictionary<ushort, PingPacket>();
+
         /// <summary>
         ///     The interval from data being received or transmitted to a keepalive packet being sent in milliseconds.
         /// </summary>
@@ -33,12 +58,15 @@ namespace Hazel.Udp
             set
             {
                 keepAliveInterval = value;
-                
+
                 //Update timer
                 ResetKeepAliveTimer();
             }
         }
-        int keepAliveInterval = 2000;
+        int keepAliveInterval = 1500;
+
+        public int MissingPingsUntilDisconnect { get; set; } = 6;
+        int pingsSinceAck = 0;
 
         /// <summary>
         ///     The timer creating keepalive pulses.
@@ -53,9 +81,16 @@ namespace Hazel.Udp
             keepAliveTimer = new Timer(
                 (o) =>
                 {
+                    if (this.pingsSinceAck >= this.MissingPingsUntilDisconnect)
+                    {
+                        this.Disconnect($"Sent {this.pingsSinceAck} pings that remote has not responded to.");
+                        return;
+                    }
+
                     try
                     {
-                        ReliableSend((byte)UdpSendOption.Ping);
+                        SendPing();
+                        this.pingsSinceAck++;
                     }
                     catch
                     {
@@ -68,6 +103,36 @@ namespace Hazel.Udp
             );
         }
 
+        // Pings are special, quasi-reliable packets. 
+        // We send them to trigger responses that validate our connection is alive
+        // They should never be the *cause* of a disconnect.
+        // Rather, the responses will reset our 
+        void SendPing()
+        {
+            ushort id = (ushort)Interlocked.Increment(ref lastIDAllocated);
+
+            byte[] bytes = new byte[3];
+            bytes[0] = (byte)UdpSendOption.Ping;
+            bytes[1] = (byte)(id >> 8);
+            bytes[2] = (byte)id;
+
+            PingPacket pkt;
+            if (!this.activePingPackets.TryGetValue(id, out pkt))
+            {
+                pkt = PingPacket.GetObject();
+                if (!this.activePingPackets.TryAdd(id, pkt))
+                {
+                    throw new Exception("This shouldn't be possible");
+                }
+            }
+
+            pkt.Stopwatch.Restart();
+
+            WriteBytesToConnection(bytes, bytes.Length);
+
+            Statistics.LogReliableSend(0, bytes.Length);
+        }
+
         /// <summary>
         ///     Resets the keepalive timer to zero.
         /// </summary>
@@ -93,4 +158,4 @@ namespace Hazel.Udp
             }
         }
     }
-}
+}
\ No newline at end of file
index af8251e24dbe9b86e4bfefc22f5a6f13b557b99c..a7e915e249aab3c064c655745e95ac6ff1b14206 100644 (file)
@@ -228,16 +228,13 @@ namespace Hazel.Udp
         void AttachReliableID(byte[] buffer, int offset, int sendLength, Action ackCallback = null)
         {
             //Find an ID not used yet.
-            ushort id;
-
-            //Create packet object
-            Packet packet = Packet.GetObject();
+            ushort id = (ushort)Interlocked.Increment(ref lastIDAllocated);
 
-            id = (ushort)Interlocked.Increment(ref lastIDAllocated);
-
-            buffer[offset] = (byte)((id >> 8) & 0xFF);
+            buffer[offset] = (byte)(id >> 8);
             buffer[offset + 1] = (byte)id;
 
+            //Create packet object
+            Packet packet = Packet.GetObject();
             packet.Set(
                 id,
                 this,
@@ -300,20 +297,6 @@ namespace Hazel.Udp
             Statistics.LogReliableSend(length, bytes.Length);
         }
 
-        void ReliableSend(byte sendOption)
-        {
-            byte[] bytes = new byte[3];
-            bytes[0] = sendOption;
-
-            //Add reliable ID
-            AttachReliableID(bytes, 1, bytes.Length, null);
-
-            //Write to connection
-            WriteBytesToConnection(bytes, bytes.Length);
-
-            Statistics.LogReliableSend(0, bytes.Length);
-        }
-
         /// <summary>
         ///     Handles a reliable message being received and invokes the data event.
         /// </summary>
@@ -421,6 +404,8 @@ namespace Hazel.Udp
         /// <param name="bytes">The buffer containing the data.</param>
         void AcknowledgementMessageReceive(byte[] bytes)
         {
+            this.pingsSinceAck = 0;
+
             //Get ID
             ushort id = (ushort)((bytes[1] << 8) + bytes[2]);
 
@@ -438,6 +423,16 @@ namespace Hazel.Udp
                     this.AveragePingMs = Math.Max(50, this.AveragePingMs * .7f + rt * .3f);
                 }
             }
+            else if (this.activePingPackets.TryRemove(id, out PingPacket pingPkt))
+            {
+                float rt = pingPkt.Stopwatch.ElapsedMilliseconds;
+                lock (PingLock)
+                {
+                    this.AveragePingMs = Math.Max(50, this.AveragePingMs * .7f + rt * .3f);
+                }
+
+                pingPkt.Recycle();
+            }
 
             Statistics.LogReliableReceive(0, bytes.Length);
         }
index ddac37e87d78edadb79d9b03eca3580ca1497e5f..503b1c6b6b4e4f740ed22234ea3efc5b9ab6e4d8 100644 (file)
@@ -31,12 +31,6 @@ namespace Hazel.Udp
         /// <param name="bytes">The bytes to write.</param>
         protected abstract void WriteBytesToConnection(byte[] bytes, int length);
 
-        /// <summary>
-        ///     Writes the given bytes to the connection synchronously.
-        /// </summary>
-        /// <param name="bytes">The bytes to write.</param>
-        protected abstract void WriteBytesToConnectionSync(byte[] bytes, int length);
-
         /// <inheritdoc/>
         public override void Send(MessageWriter msg)
         {
index c137776e3aad4cf8fd5d77f3f99cf5b2b4437a79..9a8a3d93bc80fa8975c5ebe8d8e637cf3c53b7b6 100644 (file)
@@ -54,7 +54,7 @@ namespace Hazel.Udp
                     throw new HazelException("IPV6 not supported!");
 
                 this.socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
-                this.socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
+                this.socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
             }
 
             socket.ReceiveBufferSize = BufferSize;
@@ -75,8 +75,12 @@ namespace Hazel.Udp
                 var sock = kvp.Value;
                 sock.ManageReliablePackets();
             }
-            
-            this.reliablePacketTimer.Change(100, Timeout.Infinite);
+
+            try
+            {
+                this.reliablePacketTimer.Change(100, Timeout.Infinite);
+            }
+            catch { }
         }
 
         /// <inheritdoc />
@@ -300,15 +304,7 @@ namespace Hazel.Udp
                     endPoint
                 );
             }
-            catch (SocketException e)
-            {
-                throw new HazelException("Could not send data as a SocketException occured.", e);
-            }
-            catch (ObjectDisposedException)
-            {
-                //Keep alive timer probably ran, ignore
-                return;
-            }
+            catch { }
         }
 
         /// <summary>
index 0cdf03e9e94cd2e78d5ad009d0923b878dcf809c..4c18a6e41741ac70071e6c1fb1aa5897672a4afa 100644 (file)
@@ -45,14 +45,6 @@ namespace Hazel.Udp
             Listener.SendData(bytes, length, RemoteEndPoint);
         }
 
-        /// <inheritdoc />
-        protected override void WriteBytesToConnectionSync(byte[] bytes, int length)
-        {
-            // No throw: As an internal interface, I want to try sending bytes whenever the I feel like it.
-
-            Listener.SendDataSync(bytes, length, RemoteEndPoint);
-        }
-
         /// <inheritdoc />
         /// <remarks>
         ///     This will always throw a HazelException.
@@ -79,7 +71,7 @@ namespace Hazel.Udp
         {
             try
             {
-                WriteBytesToConnection(DisconnectBytes, 1);
+                Listener.SendDataSync(DisconnectBytes, 1, RemoteEndPoint);
             }
             catch { }
         }