From 9d05ec22e0350b576b90f927f3118ae71bebf7e2 Mon Sep 17 00:00:00 2001 From: Forest Date: Thu, 27 Dec 2018 14:29:43 -0800 Subject: [PATCH] Strip away a bunch of Interlocked debug stuff, add a bit more logging during exceptions --- Hazel/MessageReader.cs | 14 +- Hazel/Udp/UdpConnection.KeepAlive.cs | 4 - Hazel/Udp/UdpConnection.Reliable.cs | 18 +-- Hazel/Udp/UdpConnectionListener.cs | 195 ++++++++++++--------------- 4 files changed, 95 insertions(+), 136 deletions(-) diff --git a/Hazel/MessageReader.cs b/Hazel/MessageReader.cs index 6f7bd59..f7d0d76 100644 --- a/Hazel/MessageReader.cs +++ b/Hazel/MessageReader.cs @@ -10,9 +10,6 @@ namespace Hazel { public class MessageReader : IRecyclable { - public static int Readers = 0; - public int ReaderId = 0; - public static readonly ObjectPool ReaderPool = new ObjectPool(() => new MessageReader()); public byte[] Buffer; @@ -33,16 +30,7 @@ namespace Hazel private int _position; private int readHead; - - public MessageReader() - { - this.ReaderId = Interlocked.Increment(ref Readers); - } - public override string ToString() - { - return $"{ReaderId}: BL:{Buffer.Length} O:{Offset} L:{Length}"; - } - + public static MessageReader GetSized(int minSize) { var output = ReaderPool.GetObject(); diff --git a/Hazel/Udp/UdpConnection.KeepAlive.cs b/Hazel/Udp/UdpConnection.KeepAlive.cs index a0d5f5a..67abe78 100644 --- a/Hazel/Udp/UdpConnection.KeepAlive.cs +++ b/Hazel/Udp/UdpConnection.KeepAlive.cs @@ -40,8 +40,6 @@ namespace Hazel.Udp } int keepAliveInterval = 3000; - public int KeepAlivesSent; - /// /// The timer creating keepalive pulses. /// @@ -58,11 +56,9 @@ namespace Hazel.Udp try { ReliableSend((byte)UdpSendOption.Ping); - Interlocked.Increment(ref KeepAlivesSent); } catch { - Trace.WriteLine("Keepalive packet failed to send."); DisposeKeepAliveTimer(); } }, diff --git a/Hazel/Udp/UdpConnection.Reliable.cs b/Hazel/Udp/UdpConnection.Reliable.cs index f5e8968..4788cdb 100644 --- a/Hazel/Udp/UdpConnection.Reliable.cs +++ b/Hazel/Udp/UdpConnection.Reliable.cs @@ -35,7 +35,7 @@ namespace Hazel.Udp /// /// Holds the last ID allocated. /// - volatile int lastIDAllocated = ushort.MaxValue + 1; + private int lastIDAllocated = ushort.MaxValue + 1; /// /// The packets of data that have been transmitted reliably and not acknowledged. @@ -51,9 +51,7 @@ namespace Hazel.Udp /// The packet id that was received last. /// volatile ushort reliableReceiveLast = 0; - - public int DuplicateRecieves; - + /// /// Has the connection received anything yet /// @@ -68,7 +66,7 @@ namespace Hazel.Udp /// 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 volatile float AveragePingMs = 500; + public float AveragePingMs = 500; /// /// The maximum times a message should be resent before marking the endpoint as disconnected. @@ -105,12 +103,12 @@ namespace Hazel.Udp private UdpConnection Connection; private int Length; - public volatile int NextTimeout; + public int NextTimeout; public volatile bool Acknowledged; public Action AckCallback; - public volatile int Retransmissions; + public int Retransmissions; public Stopwatch Stopwatch = new Stopwatch(); Packet() @@ -143,7 +141,7 @@ namespace Hazel.Udp { if (connection.reliableDataPacketsSent.TryRemove(this.Id, out Packet self)) { - connection.Disconnect($"Reliable packet {self.Id} was not ack'd after {lifetime}ms"); + connection.Disconnect($"Reliable packet {self.Id} was not ack'd after {lifetime}ms ({self.Retransmissions} resends)"); self.Recycle(); } @@ -157,7 +155,7 @@ namespace Hazel.Udp { if (connection.reliableDataPacketsSent.TryRemove(this.Id, out Packet self)) { - connection.Disconnect($"Reliable packet {self.Id} was not ack'd after {self.Retransmissions} resends"); + connection.Disconnect($"Reliable packet {self.Id} was not ack'd after {self.Retransmissions} resends ({lifetime}ms)"); self.Recycle(); } @@ -173,7 +171,6 @@ namespace Hazel.Udp } catch (InvalidOperationException) { - //No longer connected connection.Disconnect("Could not resend data as connection is no longer connected"); } } @@ -319,7 +316,6 @@ namespace Hazel.Udp } else { - Interlocked.Increment(ref this.DuplicateRecieves); message.Recycle(); } diff --git a/Hazel/Udp/UdpConnectionListener.cs b/Hazel/Udp/UdpConnectionListener.cs index 4c2584d..7f251fa 100644 --- a/Hazel/Udp/UdpConnectionListener.cs +++ b/Hazel/Udp/UdpConnectionListener.cs @@ -16,10 +16,7 @@ namespace Hazel.Udp /// public class UdpConnectionListener : NetworkConnectionListener { - public long BytesReceived; - public long BytesSent; - - public const int BufferSize = ushort.MaxValue / 4; + public const int BufferSize = ushort.MaxValue; public int MinConnectionLength = 0; @@ -69,9 +66,6 @@ namespace Hazel.Udp } public float AveragePacketsTime = 1; - public int PacketsResent = 0; - public int KeepAlives = 0; - public int DuplicateRecieves = 0; Stopwatch stopwatch = new Stopwatch(); private void ManageReliablePackets(object state) @@ -80,9 +74,7 @@ namespace Hazel.Udp foreach (var kvp in this.allConnections) { var sock = kvp.Value; - Interlocked.Add(ref PacketsResent, sock.ManageReliablePackets(state)); - KeepAlives += Interlocked.Exchange(ref sock.KeepAlivesSent, 0); - DuplicateRecieves += Interlocked.Exchange(ref sock.DuplicateRecieves, 0); + sock.ManageReliablePackets(state); } this.AveragePacketsTime = this.AveragePacketsTime * .7f + stopwatch.ElapsedMilliseconds * .3f; @@ -108,7 +100,7 @@ namespace Hazel.Udp /// /// Instructs the listener to begin listening. /// - void StartListeningForData() + public void StartListeningForData() { EndPoint remoteEP = EndPoint; @@ -120,10 +112,6 @@ namespace Hazel.Udp socket.BeginReceiveFrom(message.Buffer, 0, message.Buffer.Length, SocketFlags.None, ref remoteEP, ReadCallback, message); Interlocked.Increment(ref ActiveListeners); } - catch (ObjectDisposedException) - { - return; - } catch (SocketException) { //Client no longer reachable, pretend it didn't happen @@ -132,6 +120,12 @@ namespace Hazel.Udp StartListeningForData(); return; } + catch (Exception ex) + { + //If the socket's been disposed then we can just end there. + this.Logger?.Invoke("Stopped due to: " + ex.Message); + return; + } } /// @@ -140,133 +134,117 @@ namespace Hazel.Udp /// The asyncronous operation's result. public int ActiveListeners; - public int ActiveCallbacks; void ReadCallback(IAsyncResult result) { - Interlocked.Increment(ref ActiveCallbacks); Interlocked.Decrement(ref ActiveListeners); + var message = (MessageReader)result.AsyncState; + int bytesReceived; + EndPoint remoteEndPoint = new IPEndPoint(IPMode == IPMode.IPv4 ? IPAddress.Any : IPAddress.IPv6Any, 0); + + //End the receive operation try { - var message = (MessageReader)result.AsyncState; - int bytesReceived; - EndPoint remoteEndPoint = new IPEndPoint(IPMode == IPMode.IPv4 ? IPAddress.Any : IPAddress.IPv6Any, 0); + bytesReceived = socket.EndReceiveFrom(result, ref remoteEndPoint); - //End the receive operation - try - { - bytesReceived = socket.EndReceiveFrom(result, ref remoteEndPoint); - Interlocked.Add(ref BytesReceived, bytesReceived); + message.Offset = 0; + message.Length = bytesReceived; + } + catch (SocketException) + { + // Client no longer reachable, pretend it didn't happen + // TODO should this not inform the connection this client is lost??? - message.Offset = 0; - message.Length = bytesReceived; - } - catch (NullReferenceException) - { - return; - } - catch (ObjectDisposedException) - { - //If the socket's been disposed then we can just end there. - return; - } - catch (SocketException) - { - // Client no longer reachable, pretend it didn't happen - // TODO should this not inform the connection this client is lost??? + // This thread suggests the IP is not passed out from WinSoc so maybe not possible + // http://stackoverflow.com/questions/2576926/python-socket-error-on-udp-data-receive-10054 + message.Recycle(); + + StartListeningForData(); + return; + } + catch (Exception ex) + { + //If the socket's been disposed then we can just end there. + this.Logger?.Invoke("Stopped due to: " + ex.Message); + return; + } - // This thread suggests the IP is not passed out from WinSoc so maybe not possible - // http://stackoverflow.com/questions/2576926/python-socket-error-on-udp-data-receive-10054 - message.Recycle(); + // Exit if no bytes read, we've closed. + if (bytesReceived == 0) + { + message.Recycle(); + this.Logger?.Invoke("Stopped due to receiving 0 bytes"); + return; + } - UdpServerConnection dead; - if (this.allConnections.TryRemove(remoteEndPoint, out dead)) - { - dead.Dispose(); - } + //Begin receiving again + StartListeningForData(); - StartListeningForData(); - return; - } + bool aware = true; + bool hasHelloByte = message.Buffer[0] == (byte)UdpSendOption.Hello; + bool isHello = hasHelloByte && message.Length >= MinConnectionLength; - // Exit if no bytes read, we've closed. - if (bytesReceived == 0) + //If we're aware of this connection use the one already + //If this is a new client then connect with them! + UdpServerConnection connection; + if (!this.allConnections.TryGetValue(remoteEndPoint, out connection)) + { + //Check for malformed connection attempts + if (!isHello) { message.Recycle(); return; } - //Begin receiving again - StartListeningForData(); - - bool aware = true; - bool hasHelloByte = message.Buffer[0] == (byte)UdpSendOption.Hello; - bool isHello = hasHelloByte && message.Length >= MinConnectionLength; - - //If we're aware of this connection use the one already - //If this is a new client then connect with them! - UdpServerConnection connection; - if (!this.allConnections.TryGetValue(remoteEndPoint, out connection)) + lock (this.allConnections) { - //Check for malformed connection attempts - if (!isHello) - { - message.Recycle(); - return; - } - - lock (this.allConnections) + aware = this.allConnections.TryGetValue(remoteEndPoint, out connection); + if (!aware) { - aware = this.allConnections.TryGetValue(remoteEndPoint, out connection); - if (!aware) + connection = new UdpServerConnection(this, remoteEndPoint, this.IPMode); + if (!this.allConnections.TryAdd(remoteEndPoint, connection)) { - connection = new UdpServerConnection(this, remoteEndPoint, this.IPMode); - if (!this.allConnections.TryAdd(remoteEndPoint, connection)) - { - throw new Exception(); - } + throw new Exception(); } } } + } - var stopwatch = System.Diagnostics.Stopwatch.StartNew(); - try - { - //Inform the connection of the buffer (new connections need to send an ack back to client) - connection.HandleReceive(message, bytesReceived); - } - finally + var stopwatch = System.Diagnostics.Stopwatch.StartNew(); + try + { + //Inform the connection of the buffer (new connections need to send an ack back to client) + connection.HandleReceive(message, bytesReceived); + } + finally + { + var el = stopwatch.ElapsedMilliseconds; + if (el > 5) { - var el = stopwatch.ElapsedMilliseconds; - if (el > 5) - { - this.Logger?.Invoke($"Long Packet {el}ms = {string.Join(" ", message.Buffer.Take(bytesReceived))}"); - } + this.Logger?.Invoke($"Long Packet {el}ms = {string.Join(" ", message.Buffer.Take(bytesReceived))}"); } + } - //If it's a new connection invoke the NewConnection event. - if (!aware) - { - // Skip header and hello byte; - message.Offset = 4; - message.Length = bytesReceived - 4; - message.Position = 0; - InvokeNewConnection(message, connection); - } - else if (isHello || (!isHello && hasHelloByte)) - { - message.Recycle(); - } + //If it's a new connection invoke the NewConnection event. + if (!aware) + { + // Skip header and hello byte; + message.Offset = 4; + message.Length = bytesReceived - 4; + message.Position = 0; + InvokeNewConnection(message, connection); } - finally + else if (isHello || (!isHello && hasHelloByte)) { - Interlocked.Decrement(ref ActiveCallbacks); + message.Recycle(); } } +#if DEBUG public int TestDropRate = -1; private int dropCounter = 0; +#endif /// /// Sends data from the listener socket. @@ -276,8 +254,8 @@ namespace Hazel.Udp internal void SendData(byte[] bytes, int length, EndPoint endPoint) { if (length > bytes.Length) return; - Interlocked.Add(ref BytesSent, length); +#if DEBUG if (TestDropRate > 0) { if (Interlocked.Increment(ref dropCounter) % TestDropRate == 0) @@ -285,6 +263,7 @@ namespace Hazel.Udp return; } } +#endif try { -- 2.39.5