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);
}
}
}