using System;
using System.Net;
using System.Threading.Tasks;
using Impostor.Api.Net.Messages;
using Microsoft.Extensions.ObjectPool;
namespace Impostor.Hazel.Udp
{
///
/// Represents a servers's connection to a client that uses the UDP protocol.
///
///
internal sealed class UdpServerConnection : UdpConnection
{
///
/// 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 UdpConnectionListener Listener { 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 UdpServerConnection(UdpConnectionListener listener, IPEndPoint endPoint, IPMode IPMode, ObjectPool readerPool) : base(listener, readerPool)
{
this.Listener = listener;
this.RemoteEndPoint = endPoint;
this.EndPoint = endPoint;
this.IPMode = IPMode;
State = ConnectionState.Connected;
this.InitializeKeepAliveTimer();
}
///
protected override async ValueTask WriteBytesToConnection(byte[] bytes, int length)
{
await Listener.SendData(bytes, length, RemoteEndPoint);
}
///
///
/// This will always throw a HazelException.
///
public override ValueTask 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 async ValueTask 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 != MessageType.Unreliable) throw new ArgumentException("Disconnect messages can only be unreliable.");
bytes = data.ToByteArray(true);
bytes[0] = (byte)UdpSendOption.Disconnect;
}
try
{
await Listener.SendData(bytes, bytes.Length, RemoteEndPoint);
}
catch { }
return true;
}
protected override void Dispose(bool disposing)
{
Listener.RemoveConnectionTo(RemoteEndPoint);
if (disposing)
{
SendDisconnect();
}
base.Dispose(disposing);
}
}
}