using System; using System.Net; namespace Hazel.Udp.FewerThreads { /// /// Represents a servers's connection to a client that uses the UDP protocol. /// /// public sealed class ThreadLimitedUdpServerConnection : UdpConnection { public readonly DateTime CreationTime = DateTime.UtcNow; /// /// The connection listener that we use the socket of. /// /// /// Udp server connections utilize the same socket in the listener for sends/receives, this is the listener that /// created this connection and is hence the listener this conenction sends and receives via. /// public ThreadLimitedUdpConnectionListener Listener { get; private set; } public ThreadLimitedUdpConnectionListener.ConnectionId ConnectionId { get; private set; } /// /// Creates a UdpConnection for the virtual connection to the endpoint. /// /// The listener that created this connection. /// The endpoint that we are connected to. /// The IPMode we are connected using. internal ThreadLimitedUdpServerConnection(ThreadLimitedUdpConnectionListener listener, ThreadLimitedUdpConnectionListener.ConnectionId connectionId, IPEndPoint endPoint, IPMode IPMode, ILogger logger) : base(logger) { this.Listener = listener; this.ConnectionId = connectionId; this.EndPoint = endPoint; this.IPMode = IPMode; State = ConnectionState.Connected; this.InitializeKeepAliveTimer(); } /// protected override void WriteBytesToConnection(byte[] bytes, int length) { if (bytes.Length != length) throw new ArgumentException("I made an assumption here. I hope you see this error."); // Hrm, well this is inaccurate for DTLS connections because the Listener does the encryption which may change the size. // but I don't want to have a bunch of client references in the send queue... // Does this perhaps mean the encryption is being done in the wrong class? this.Statistics.LogPacketSend(length); Listener.SendDataRaw(bytes, EndPoint); } /// /// /// This will always throw a HazelException. /// public override void Connect(byte[] bytes = null, int timeout = 5000) { throw new InvalidOperationException("Cannot manually connect a UdpServerConnection, did you mean to use UdpClientConnection?"); } /// /// /// This will always throw a HazelException. /// public override void ConnectAsync(byte[] bytes = null) { throw new InvalidOperationException("Cannot manually connect a UdpServerConnection, did you mean to use UdpClientConnection?"); } /// /// Sends a disconnect message to the end point. /// protected override bool SendDisconnect(MessageWriter data = null) { if (!Listener.RemoveConnectionTo(this.ConnectionId)) 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 { this.WriteBytesToConnection(bytes, bytes.Length); } catch { } return true; } protected override void Dispose(bool disposing) { if (disposing) { SendDisconnect(); } Listener.RemovePeerRecord(this.ConnectionId); base.Dispose(disposing); } } }