From: Forest Date: Thu, 20 Jun 2019 21:13:36 +0000 (-0700) Subject: Add the ability to send extra data along side a disconnect message X-Git-Tag: 1.0.0~42 X-Git-Url: https://git.deb.at/?a=commitdiff_plain;h=6a2287017d202e8ed0fc4302394cf649e19a5ffa;p=rhonda%2Fimpostor.hazel.git Add the ability to send extra data along side a disconnect message --- diff --git a/Hazel.UnitTests/UdpConnectionTests.cs b/Hazel.UnitTests/UdpConnectionTests.cs index d363a23..efd4857 100644 --- a/Hazel.UnitTests/UdpConnectionTests.cs +++ b/Hazel.UnitTests/UdpConnectionTests.cs @@ -64,7 +64,7 @@ namespace Hazel.UnitTests connection.Connect(); connection.Dispose(); - Thread.Sleep(50); + Thread.Sleep(100); Assert.IsTrue(serverConnected); Assert.IsTrue(serverDisconnected); diff --git a/Hazel/Connection.cs b/Hazel/Connection.cs index f30d948..3615c51 100644 --- a/Hazel/Connection.cs +++ b/Hazel/Connection.cs @@ -202,11 +202,6 @@ namespace Hazel /// public abstract void ConnectAsync(byte[] bytes = null, int timeout = 5000); - /// - /// Sends a disconnect message to the end point. - /// - protected abstract void SendDisconnect(); - /// /// Invokes the DataReceived event. /// @@ -235,19 +230,19 @@ namespace Hazel /// Invokes the Disconnected event. /// /// The exception, if any, that occured to cause this. + /// Extra disconnect data /// /// Invokes the event to alert subscribres this connection has been disconnected either /// by the end point or because an error occured. If an error occured the error should be passed in in order to /// pass to the subscribers, otherwise null can be passed in. /// - protected void InvokeDisconnected(string e) + protected void InvokeDisconnected(string e, MessageReader reader) { //Make a copy to avoid race condition between null check and invocation EventHandler handler = Disconnected; if (handler != null) { - DisconnectedEventArgs args = DisconnectedEventArgs.GetObject(); - args.Set(e); + DisconnectedEventArgs args = new DisconnectedEventArgs(e, reader); handler.Invoke(this, args); } } @@ -270,7 +265,7 @@ namespace Hazel /// For times when you want to force the disconnect handler to fire as well as close it. /// If you only want to close it, just use Dispose. /// - public abstract void Disconnect(string reason); + public abstract void Disconnect(string reason, MessageWriter writer = null, bool fireEvent = true); /// /// Disposes of this NetworkConnection. diff --git a/Hazel/ConnectionState.cs b/Hazel/ConnectionState.cs index 5036b90..5d3f5c9 100644 --- a/Hazel/ConnectionState.cs +++ b/Hazel/ConnectionState.cs @@ -24,10 +24,5 @@ namespace Hazel /// The Connection is connected and data can be transfered. /// Connected, - - /// - /// The Connection is currently disconnecting. - /// - Disconnecting } } diff --git a/Hazel/DisconnectedEventArgs.cs b/Hazel/DisconnectedEventArgs.cs index 58969c4..3d87d66 100644 --- a/Hazel/DisconnectedEventArgs.cs +++ b/Hazel/DisconnectedEventArgs.cs @@ -18,15 +18,6 @@ namespace Hazel /// public class DisconnectedEventArgs : EventArgs { - /// - /// Returns an instance of this object from the pool. - /// - /// A new or recycled DisconnectedEventArgs object. - internal static DisconnectedEventArgs GetObject() - { - return new DisconnectedEventArgs(); - } - /// /// The exception, if any, that caused the disconnect. /// @@ -36,23 +27,13 @@ namespace Hazel /// that caused it or a with the details of the exception, if the disconnection /// wasn't caused by an error then this will contain null. /// - public string Reason { get; private set; } + public readonly string Reason; - /// - /// Private constructor for object pool. - /// - DisconnectedEventArgs() - { - - } + public readonly MessageReader Message; - /// - /// Sets the given exception for the arguments. - /// - /// The exception if the cause. - internal void Set(string reason) + public DisconnectedEventArgs(string reason, MessageReader reader) { - this.Reason = reason; + } } } diff --git a/Hazel/MessageWriter.cs b/Hazel/MessageWriter.cs index 37d9c94..95b0143 100644 --- a/Hazel/MessageWriter.cs +++ b/Hazel/MessageWriter.cs @@ -43,13 +43,13 @@ namespace Hazel { switch (this.SendOption) { - case Hazel.SendOption.Reliable: + case SendOption.Reliable: { byte[] output = new byte[this.Length - 3]; System.Buffer.BlockCopy(this.Buffer, 3, output, 0, this.Length - 3); return output; } - case Hazel.SendOption.None: + case SendOption.None: { byte[] output = new byte[this.Length - 1]; System.Buffer.BlockCopy(this.Buffer, 1, output, 0, this.Length - 1); diff --git a/Hazel/NetworkConnection.cs b/Hazel/NetworkConnection.cs index c6426fc..ba81822 100644 --- a/Hazel/NetworkConnection.cs +++ b/Hazel/NetworkConnection.cs @@ -35,27 +35,23 @@ namespace Hazel } } + /// + /// Sends a disconnect message to the end point. + /// + protected abstract bool SendDisconnect(MessageWriter writer); + + /// /// Called when the socket has been disconnected at the remote host. /// /// The exception if one was the cause. - public override void Disconnect(string reason) + public override void Disconnect(string reason, MessageWriter writer = null, bool fireEvent = true) { - bool invoke = false; - lock (this) - { - if (this._state == ConnectionState.Connected) - { - this._state = ConnectionState.Disconnecting; - invoke = true; - } - } - - if (invoke) + if (this.SendDisconnect(writer) && fireEvent) { try { - InvokeDisconnected(reason); + InvokeDisconnected(reason, null); } catch { } } diff --git a/Hazel/Udp/UdpClientConnection.cs b/Hazel/Udp/UdpClientConnection.cs index a09f830..7d155f2 100644 --- a/Hazel/Udp/UdpClientConnection.cs +++ b/Hazel/Udp/UdpClientConnection.cs @@ -262,19 +262,37 @@ namespace Hazel.Udp /// /// Sends a disconnect message to the end point. + /// You may include optional disconnect data. The SendOption must be unreliable. /// - protected override void SendDisconnect() + protected override bool SendDisconnect(MessageWriter data = null) { + lock (this) + { + if (this._state != ConnectionState.Connected) return false; + this._state = ConnectionState.NotConnected; + } + + var bytes = EmptyDisconnectBytes; + if (data != null && data.Length > 0) + { + if (data.SendOption != SendOption.None) throw new ArgumentException("Disconnect messages can only be unreliable."); + + bytes = data.ToByteArray(true); + bytes[0] = (byte)UdpSendOption.Disconnect; + } + try { socket.SendTo( - DisconnectBytes, + bytes, 0, - 1, + bytes.Length, SocketFlags.None, RemoteEndPoint); } catch { } + + return true; } /// @@ -282,12 +300,7 @@ namespace Hazel.Udp { if (disposing) { - if (this._state == ConnectionState.Connected - || this._state == ConnectionState.Disconnecting) - { - this._state = ConnectionState.NotConnected; - SendDisconnect(); - } + SendDisconnect(); } if (this.socket != null) diff --git a/Hazel/Udp/UdpConnection.cs b/Hazel/Udp/UdpConnection.cs index c1e6cf4..8889a1f 100644 --- a/Hazel/Udp/UdpConnection.cs +++ b/Hazel/Udp/UdpConnection.cs @@ -1,11 +1,4 @@ using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; namespace Hazel.Udp { @@ -15,7 +8,7 @@ namespace Hazel.Udp /// public abstract partial class UdpConnection : NetworkConnection { - protected static readonly byte[] DisconnectBytes = new byte[] { (byte)UdpSendOption.Disconnect }; + protected static readonly byte[] EmptyDisconnectBytes = new byte[] { (byte)UdpSendOption.Disconnect }; /// /// Creates a new UdpConnection and initializes the keep alive timer. diff --git a/Hazel/Udp/UdpServerConnection.cs b/Hazel/Udp/UdpServerConnection.cs index 1d01c76..9dad8c7 100644 --- a/Hazel/Udp/UdpServerConnection.cs +++ b/Hazel/Udp/UdpServerConnection.cs @@ -59,17 +59,33 @@ namespace Hazel.Udp throw new InvalidOperationException("Cannot manually connect a UdpServerConnection, did you mean to use UdpClientConnection?"); } - /// /// Sends a disconnect message to the end point. /// - protected override void SendDisconnect() + protected override bool SendDisconnect(MessageWriter data = null) { + lock (this) + { + if (this._state != ConnectionState.Connected) return false; + this._state = ConnectionState.NotConnected; + } + + var bytes = EmptyDisconnectBytes; + if (data != null && data.Length > 0) + { + if (data.SendOption != SendOption.None) throw new ArgumentException("Disconnect messages can only be unreliable."); + + bytes = data.ToByteArray(true); + bytes[0] = (byte)UdpSendOption.Disconnect; + } + try { - Listener.SendDataSync(DisconnectBytes, 1, RemoteEndPoint); + Listener.SendDataSync(bytes, bytes.Length, RemoteEndPoint); } catch { } + + return true; } protected override void Dispose(bool disposing) @@ -78,12 +94,7 @@ namespace Hazel.Udp if (disposing) { - if (this._state == ConnectionState.Connected - || this._state == ConnectionState.Disconnecting) - { - this._state = ConnectionState.NotConnected; - SendDisconnect(); - } + SendDisconnect(); }