]> git.deb.at Git - rhonda/impostor.hazel.git/commitdiff
Bug fixes and resendTimeout now based off ping
authorJamJar00 <jamster.30@btinternet.com>
Tue, 14 Jun 2016 14:13:50 +0000 (15:13 +0100)
committerJamJar00 <jamster.30@btinternet.com>
Tue, 14 Jun 2016 14:13:50 +0000 (15:13 +0100)
Hazel/HazelException.cs
Hazel/Udp/UdpConnection.Reliable.cs
Hazel/Udp/UdpConnectionListener.cs

index f04a4b0b986c0dc3a9e232b098b930e00828ae06..c0db05ac417853acbf4276b418ed3bacd7f745af 100644 (file)
@@ -16,7 +16,7 @@ namespace Hazel
 
         }
 
-        internal HazelException(string msg, System.Net.Sockets.SocketException e) : base (msg, e)
+        internal HazelException(string msg, Exception e) : base (msg, e)
         {
 
         }
index 2c40fc1b9c2834154fc5256445ed5136a1fe93ad..05d6b8961084c7b18c32cbbe482cc1f6c1ccd3e1 100644 (file)
@@ -14,13 +14,19 @@ namespace Hazel.Udp
         ///     The starting timeout, in miliseconds, at which data will be resent.
         /// </summary>
         /// <remarks>
-        ///     For reliable delivery data is resent at specified intervals unless an acknowledgement is received from the 
-        ///     receiving device. The ResendTimeout specifies the interval between the packets being resent, each time a packet
-        ///     is resent the interval is doubled for that packet until the number of resends exceeds the 
-        ///     <see cref="ResendsBeforeDisconnect"/> value.
+        ///     <para>
+        ///         For reliable delivery data is resent at specified intervals unless an acknowledgement is received from the 
+        ///         receiving device. The ResendTimeout specifies the interval between the packets being resent, each time a packet
+        ///         is resent the interval is doubled for that packet until the number of resends exceeds the 
+        ///         <see cref="ResendsBeforeDisconnect"/> value.
+        ///     </para>
+        ///     <para>
+        ///         Setting this to its default of 0 will mean the timout is 4 times the value of the average ping, usually 
+        ///         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 = 200;        //TODO this based of average ping?
+        private volatile int resendTimeout = 200;
 
         /// <summary>
         ///     Holds the last ID allocated.
@@ -47,6 +53,35 @@ namespace Hazel.Udp
         /// </summary>
         volatile bool hasReceivedSomething = false;
 
+        /// <summary>
+        ///     The total time it has taken reliable packets to make a round trip.
+        /// </summary>
+        long totalRoundTime = 0;
+
+        /// <summary>
+        ///     The number of reliable messages that have been sent.
+        /// </summary>
+        long totalReliableMessages = 0;
+
+        /// <summary>
+        ///     Returns the average ping to this endpoint.
+        /// </summary>
+        /// <remarks>
+        ///     This returns the average ping for a one-way trip as calculated from the reliable packets that have been sent 
+        ///     and acknowledged by the endpoint.
+        /// </remarks>
+        public double AveragePing
+        {
+            get
+            {
+                long t = Interlocked.Read(ref totalReliableMessages);
+                if (t == 0)
+                    return 0;
+                else
+                    return Interlocked.Read(ref totalRoundTime) / t / 2;
+            }
+        }
+
         /// <summary>
         ///     The maximum times a message should be resent before marking the endpoint as disconnected.
         /// </summary>
@@ -84,6 +119,7 @@ namespace Hazel.Udp
             public Action AckCallback;
             public volatile bool Acknowledged;
             public volatile int Retransmissions;
+            public Stopwatch Stopwatch = new Stopwatch();
 
             Packet()
             {
@@ -105,6 +141,9 @@ namespace Hazel.Udp
                 AckCallback = ackCallback;
                 Acknowledged = false;
                 Retransmissions = 0;
+
+                Stopwatch.Reset();
+                Stopwatch.Start();
             }
 
             /// <summary>
@@ -172,17 +211,29 @@ namespace Hazel.Udp
                                 if (++p.Retransmissions > ResendsBeforeDisconnect)
                                 {
                                     HandleDisconnect();
+                                    
+                                    //Set acknowledged so we dont change the timer again
+                                    p.Acknowledged = true;
+
                                     p.Recycle();
                                     return;
                                 }
                             }
                         }
 
-                        WriteBytesToConnection(p.Data);
+                        try
+                        {
+                            WriteBytesToConnection(p.Data);
+                        }
+                        catch (InvalidOperationException e)
+                        {
+                            //No longer connected
+                            HandleDisconnect(new HazelException("Could not resend data as connection is no longer connected", e));
+                        }
 
                         Trace.WriteLine("Resend.");
                     },
-                    resendTimeout,
+                    resendTimeout > 0 ? resendTimeout : (AveragePing != 0 ? (int)AveragePing * 4 : 200),
                     ackCallback
                 );
 
@@ -288,6 +339,11 @@ namespace Hazel.Udp
                     if (packet.AckCallback != null)
                         packet.AckCallback.Invoke();
 
+                    //Add to average ping
+                    packet.Stopwatch.Stop();
+                    Interlocked.Add(ref totalRoundTime, packet.Stopwatch.Elapsed.Milliseconds);
+                    Interlocked.Increment(ref totalReliableMessages);
+
                     packet.Recycle();
 
                     reliableDataPacketsSent.Remove(id);
index 4d10dcc0388b34475976852d462831e8851e21d7..6d0c9c88d5d30618ea928c47d2d56f159a02152f 100644 (file)
@@ -19,6 +19,8 @@ namespace Hazel.Udp
         /// </summary>
         Socket listener;
 
+        IPEndPoint bindOn;
+
         /// <summary>
         ///     Buffer to store incoming data in.
         /// </summary>
@@ -40,6 +42,8 @@ namespace Hazel.Udp
             this.IPAddress = IPAddress;
             this.Port = port;
 
+             this.bindOn = new IPEndPoint(IPAddress, Port);
+
             if (mode == IPMode.IPv4)
                 this.listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
             else
@@ -55,7 +59,7 @@ namespace Hazel.Udp
             try
             {
                 lock (listener)
-                    listener.Bind(new IPEndPoint(IPAddress, Port));
+                    listener.Bind(bindOn);
             }
             catch (SocketException e)
             {
@@ -70,7 +74,7 @@ namespace Hazel.Udp
         /// </summary>
         void StartListeningForData()
         {
-            EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
+            EndPoint remoteEP = (EndPoint)bindOn;
             
             try
             {
@@ -140,8 +144,8 @@ namespace Hazel.Udp
 
                     connection = new UdpServerConnection(this, remoteEndPoint);
                     connections.Add(remoteEndPoint, connection);
-                    
-                    //Then ping back an ack to make sure they're happy
+
+                    //Then ping back an ack to make sure they're happy (unless we rejected them...)
                     connection.SendAck(buffer[1], buffer[2]);
                 }
             }