From: JamJar00 Date: Tue, 14 Jun 2016 14:13:50 +0000 (+0100) Subject: Bug fixes and resendTimeout now based off ping X-Git-Tag: 1.0.0~147 X-Git-Url: https://git.deb.at/?a=commitdiff_plain;h=fb620c498eb1c77621cc5ead1bb08eb91afaad7c;p=rhonda%2Fimpostor.hazel.git Bug fixes and resendTimeout now based off ping --- diff --git a/Hazel/HazelException.cs b/Hazel/HazelException.cs index f04a4b0..c0db05a 100644 --- a/Hazel/HazelException.cs +++ b/Hazel/HazelException.cs @@ -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) { } diff --git a/Hazel/Udp/UdpConnection.Reliable.cs b/Hazel/Udp/UdpConnection.Reliable.cs index 2c40fc1..05d6b89 100644 --- a/Hazel/Udp/UdpConnection.Reliable.cs +++ b/Hazel/Udp/UdpConnection.Reliable.cs @@ -14,13 +14,19 @@ namespace Hazel.Udp /// The starting timeout, in miliseconds, at which data will be resent. /// /// - /// 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 - /// value. + /// + /// 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 + /// value. + /// + /// + /// 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. + /// /// 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; /// /// Holds the last ID allocated. @@ -47,6 +53,35 @@ namespace Hazel.Udp /// volatile bool hasReceivedSomething = false; + /// + /// The total time it has taken reliable packets to make a round trip. + /// + long totalRoundTime = 0; + + /// + /// The number of reliable messages that have been sent. + /// + long totalReliableMessages = 0; + + /// + /// Returns the average ping to this endpoint. + /// + /// + /// 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. + /// + public double AveragePing + { + get + { + long t = Interlocked.Read(ref totalReliableMessages); + if (t == 0) + return 0; + else + return Interlocked.Read(ref totalRoundTime) / t / 2; + } + } + /// /// The maximum times a message should be resent before marking the endpoint as disconnected. /// @@ -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(); } /// @@ -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); diff --git a/Hazel/Udp/UdpConnectionListener.cs b/Hazel/Udp/UdpConnectionListener.cs index 4d10dcc..6d0c9c8 100644 --- a/Hazel/Udp/UdpConnectionListener.cs +++ b/Hazel/Udp/UdpConnectionListener.cs @@ -19,6 +19,8 @@ namespace Hazel.Udp /// Socket listener; + IPEndPoint bindOn; + /// /// Buffer to store incoming data in. /// @@ -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 /// 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]); } }