using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; namespace Hazel { public enum HazelInternalErrors { SocketExceptionSend, SocketExceptionReceive, ReceivedZeroBytes, PingsWithoutResponse, ReliablePacketWithoutResponse, ConnectionDisconnected, DtlsNegotiationFailed } /// /// Abstract base class for a to a remote end point via a network protocol like TCP or UDP. /// /// public abstract class NetworkConnection : Connection { /// /// An event that gives us a chance to send well-formed disconnect messages to clients when an internal disconnect happens. /// public Func OnInternalDisconnect; public virtual float AveragePingMs { get; } public long GetIP4Address() { if (IPMode == IPMode.IPv4) { return this.EndPoint.Address.Address; } else { var bytes = this.EndPoint.Address.GetAddressBytes(); return BitConverter.ToInt64(bytes, bytes.Length - 8); } } /// /// 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. /// protected void DisconnectRemote(string reason, MessageReader reader) { if (this.SendDisconnect(null)) { try { InvokeDisconnected(reason, reader); } catch { } } this.Dispose(); } /// /// Called when socket is disconnected internally /// internal void DisconnectInternal(HazelInternalErrors error, string reason) { var handler = this.OnInternalDisconnect; if (handler != null) { MessageWriter messageToRemote = handler(error); if (messageToRemote != null) { try { Disconnect(reason, messageToRemote); } finally { messageToRemote.Recycle(); } } else { Disconnect(reason); } } else { Disconnect(reason); } } /// /// Called when the socket has been disconnected locally. /// public override void Disconnect(string reason, MessageWriter writer = null) { if (this.SendDisconnect(writer)) { try { InvokeDisconnected(reason, null); } catch { } } this.Dispose(); } } }