NetSharp

NetSharp.git
git clone git://git.lenczewski.org/NetSharp.git
Log | Files | Refs | README | LICENSE

commit 97cf9b9f20d1a0ee9781222d9a07bb645400fb39
parent d652bdc062aefec5267d47284a4db0b651c36fc9
Author: Mikolaj Lenczewski <mikolaj.lenczewski308@gmail.com>
Date:   Fri, 10 Apr 2020 15:17:21 +0100

Improved on DatagramSocketClient, implementing synchronous and asynchronous methods.

Diffstat:
DNetSharp/NetSharp/Deprecated/Builtin/ConnectPacket.cs | 33---------------------------------
DNetSharp/NetSharp/Deprecated/Builtin/ConnectResponsePacket.cs | 36------------------------------------
DNetSharp/NetSharp/Deprecated/Builtin/DataPacket.cs | 56--------------------------------------------------------
DNetSharp/NetSharp/Deprecated/Builtin/DataResponsePacket.cs | 59-----------------------------------------------------------
DNetSharp/NetSharp/Deprecated/Builtin/DisconnectPacket.cs | 33---------------------------------
DNetSharp/NetSharp/Deprecated/Builtin/PingPacket.cs | 33---------------------------------
DNetSharp/NetSharp/Deprecated/Builtin/PingResponsePacket.cs | 36------------------------------------
DNetSharp/NetSharp/Deprecated/Builtin/SimpleDataPacket.cs | 56--------------------------------------------------------
DNetSharp/NetSharp/Deprecated/Client.cs | 192-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/ClientExtensions.cs | 209-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/Connection.cs | 354-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/ConnectionBase.cs | 466-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/ConnectionBuilder.cs | 187-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/ConnectionBuilderExtensions.cs | 28----------------------------
DNetSharp/NetSharp/Deprecated/ConnectionExtensions.cs | 74--------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/Constants.cs | 16----------------
DNetSharp/NetSharp/Deprecated/CryptographyHelpers.cs | 97-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/DefaultSocketOptions.cs | 47-----------------------------------------------
DNetSharp/NetSharp/Deprecated/IClient.cs | 89-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/INetworkSerialisable.cs | 23-----------------------
DNetSharp/NetSharp/Deprecated/IPacket.cs | 19-------------------
DNetSharp/NetSharp/Deprecated/IPacketHandler.cs | 52----------------------------------------------------
DNetSharp/NetSharp/Deprecated/IRequestPacket.cs | 10----------
DNetSharp/NetSharp/Deprecated/IResponsePacket.cs | 15---------------
DNetSharp/NetSharp/Deprecated/IServer.cs | 45---------------------------------------------
DNetSharp/NetSharp/Deprecated/Logger.cs | 195-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/NetworkErrorCode.cs | 19-------------------
DNetSharp/NetSharp/Deprecated/NetworkPacket.cs | 219-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/PacketPipeline.cs | 66------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/PacketPipelineBuilder.cs | 88-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/PacketRegistry.cs | 286-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/PacketTypeIdAttribute.cs | 27---------------------------
DNetSharp/NetSharp/Deprecated/RemoteSocketClient.cs | 74--------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/RingBuffer.cs | 49-------------------------------------------------
DNetSharp/NetSharp/Deprecated/SerialisedPacket.cs | 48------------------------------------------------
DNetSharp/NetSharp/Deprecated/Server.cs | 594-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/ServerClientConnection.cs | 88-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/ServerExtensions.cs | 47-----------------------------------------------
DNetSharp/NetSharp/Deprecated/SocketAcceptor.cs | 282-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/SocketClient.cs | 133-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/SocketOperationTokens.cs | 81-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/SocketOperations.cs | 470-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/SocketOptions.cs | 107-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/SocketReader.cs | 154-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/SocketServer.cs | 122-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/SocketWriter.cs | 145-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/TcpClient.cs | 65-----------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/TcpServer.cs | 130-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/TcpSocketOptions.cs | 37-------------------------------------
DNetSharp/NetSharp/Deprecated/UdpClient.cs | 69---------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/UdpServer.cs | 170-------------------------------------------------------------------------------
DNetSharp/NetSharp/Deprecated/UdpSocketOptions.cs | 37-------------------------------------
MNetSharp/NetSharp/NetSharp.xml | 2172+------------------------------------------------------------------------------
MNetSharp/NetSharp/Sockets/Datagram/DatagramSocketClient.cs | 165++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
MNetSharp/NetSharp/Sockets/Datagram/DatagramSocketServer.cs | 453++++++++++---------------------------------------------------------------------
MNetSharp/NetSharp/Sockets/SocketAsyncOperations.cs | 16++++++++--------
MNetSharp/NetSharp/Sockets/SocketClient.cs | 14--------------
MNetSharp/NetSharp/Sockets/SocketConnection.cs | 21+++++++++++++++++++++
MNetSharp/NetSharp/Sockets/SocketServer.cs | 38+-------------------------------------
MNetSharp/NetSharp/Sockets/Stream/StreamSocketClient.cs | 25+++++++++++++++++++++++++
MNetSharp/NetSharp/Sockets/Stream/StreamSocketServer.cs | 55++++++++++++++++++++++++++++++++++++++++++++++---------
DNetSharp/NetSharp/Utils/MyObjectPool.cs | 55-------------------------------------------------------
ANetSharp/NetSharp/Utils/SlimObjectPool.cs | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
MNetSharp/NetSharp/Utils/TransmissionResult.cs | 21++++++++++++++-------
MNetSharp/NetSharpExamples/Program.cs | 17+++++++++--------
65 files changed, 417 insertions(+), 8757 deletions(-)

diff --git a/NetSharp/NetSharp/Deprecated/Builtin/ConnectPacket.cs b/NetSharp/NetSharp/Deprecated/Builtin/ConnectPacket.cs @@ -1,32 +0,0 @@ -using System; - -namespace NetSharp.Deprecated.Builtin -{ - /// <summary> - /// A simple connection request packet for the UDP protocol. - /// </summary> - [PacketTypeId(1)] - internal class ConnectPacket : IRequestPacket - { - /// <inheritdoc /> - public void AfterDeserialisation() - { - } - - /// <inheritdoc /> - public void BeforeSerialisation() - { - } - - /// <inheritdoc /> - public void Deserialise(ReadOnlyMemory<byte> serialisedObject) - { - } - - /// <inheritdoc /> - public Memory<byte> Serialise() - { - return Memory<byte>.Empty; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Builtin/ConnectResponsePacket.cs b/NetSharp/NetSharp/Deprecated/Builtin/ConnectResponsePacket.cs @@ -1,35 +0,0 @@ -using System; - -namespace NetSharp.Deprecated.Builtin -{ - /// <summary> - /// A response packet for the <see cref="ConnectPacket"/>. - /// </summary> - [PacketTypeId(2)] - internal class ConnectResponsePacket : IResponsePacket<ConnectPacket> - { - /// <inheritdoc /> - public ConnectPacket RequestPacket { get; set; } = new ConnectPacket(); - - /// <inheritdoc /> - public void AfterDeserialisation() - { - } - - /// <inheritdoc /> - public void BeforeSerialisation() - { - } - - /// <inheritdoc /> - public void Deserialise(ReadOnlyMemory<byte> serialisedObject) - { - } - - /// <inheritdoc /> - public Memory<byte> Serialise() - { - return Memory<byte>.Empty; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Builtin/DataPacket.cs b/NetSharp/NetSharp/Deprecated/Builtin/DataPacket.cs @@ -1,55 +0,0 @@ -using System; - -namespace NetSharp.Deprecated.Builtin -{ - /// <summary> - /// A simple data transfer packet, that allows for the transmission of an arbitrary number of frames. - /// </summary> - [PacketTypeId(5)] - public class DataPacket : IRequestPacket - { - /// <summary> - /// The data that should be transferred across the network. - /// </summary> - public Memory<byte> RequestBuffer; - - /// <summary> - /// Initialises a new instance of the <see cref="DataPacket"/> class. - /// </summary> - public DataPacket() - { - RequestBuffer = new byte[0]; - } - - /// <summary> - /// Initialises a new instance of the <see cref="DataPacket"/> class. - /// </summary> - /// <param name="buffer">The data that this request packet should contain.</param> - public DataPacket(Memory<byte> buffer) - { - RequestBuffer = buffer; - } - - /// <inheritdoc /> - public void AfterDeserialisation() - { - } - - /// <inheritdoc /> - public void BeforeSerialisation() - { - } - - /// <inheritdoc /> - public void Deserialise(ReadOnlyMemory<byte> serialisedObject) - { - RequestBuffer = serialisedObject.ToArray(); - } - - /// <inheritdoc /> - public Memory<byte> Serialise() - { - return RequestBuffer; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Builtin/DataResponsePacket.cs b/NetSharp/NetSharp/Deprecated/Builtin/DataResponsePacket.cs @@ -1,58 +0,0 @@ -using System; - -namespace NetSharp.Deprecated.Builtin -{ - /// <summary> - /// A response packet for the <see cref="DataPacket"/>. - /// </summary> - [PacketTypeId(6)] - public class DataResponsePacket : IResponsePacket<DataPacket> - { - /// <summary> - /// The data that should be transferred across the network. - /// </summary> - public Memory<byte> ResponseBuffer; - - /// <summary> - /// Initialises a new instance of the <see cref="DataResponsePacket"/> class. - /// </summary> - public DataResponsePacket() - { - ResponseBuffer = new byte[0]; - } - - /// <summary> - /// Initialises a new instance of the <see cref="DataResponsePacket"/> class. - /// </summary> - /// <param name="buffer">The data that this response packet should contain.</param> - public DataResponsePacket(Memory<byte> buffer) - { - ResponseBuffer = buffer; - } - - /// <inheritdoc /> - public DataPacket RequestPacket { get; internal set; } = new DataPacket(); - - /// <inheritdoc /> - public void AfterDeserialisation() - { - } - - /// <inheritdoc /> - public void BeforeSerialisation() - { - } - - /// <inheritdoc /> - public void Deserialise(ReadOnlyMemory<byte> serialisedObject) - { - ResponseBuffer = serialisedObject.ToArray(); - } - - /// <inheritdoc /> - public Memory<byte> Serialise() - { - return ResponseBuffer; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Builtin/DisconnectPacket.cs b/NetSharp/NetSharp/Deprecated/Builtin/DisconnectPacket.cs @@ -1,32 +0,0 @@ -using System; - -namespace NetSharp.Deprecated.Builtin -{ - /// <summary> - /// A simple disconnect packet for the UDP protocol. - /// </summary> - [PacketTypeId(0)] - internal class DisconnectPacket : IRequestPacket - { - /// <inheritdoc /> - public void AfterDeserialisation() - { - } - - /// <inheritdoc /> - public void BeforeSerialisation() - { - } - - /// <inheritdoc /> - public void Deserialise(ReadOnlyMemory<byte> serialisedObject) - { - } - - /// <inheritdoc /> - public Memory<byte> Serialise() - { - return Memory<byte>.Empty; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Builtin/PingPacket.cs b/NetSharp/NetSharp/Deprecated/Builtin/PingPacket.cs @@ -1,32 +0,0 @@ -using System; - -namespace NetSharp.Deprecated.Builtin -{ - /// <summary> - /// A simple ping request packet for heartbeat monitoring and RTT measurement. - /// </summary> - [PacketTypeId(3)] - public class PingPacket : IRequestPacket - { - /// <inheritdoc /> - public void AfterDeserialisation() - { - } - - /// <inheritdoc /> - public void BeforeSerialisation() - { - } - - /// <inheritdoc /> - public void Deserialise(ReadOnlyMemory<byte> serialisedObject) - { - } - - /// <inheritdoc /> - public Memory<byte> Serialise() - { - return Memory<byte>.Empty; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Builtin/PingResponsePacket.cs b/NetSharp/NetSharp/Deprecated/Builtin/PingResponsePacket.cs @@ -1,35 +0,0 @@ -using System; - -namespace NetSharp.Deprecated.Builtin -{ - /// <summary> - /// A response packet for the <see cref="PingPacket"/>. - /// </summary> - [PacketTypeId(4)] - public class PingResponsePacket : IResponsePacket<PingPacket> - { - /// <inheritdoc /> - public PingPacket RequestPacket { get; internal set; } = new PingPacket(); - - /// <inheritdoc /> - public void AfterDeserialisation() - { - } - - /// <inheritdoc /> - public void BeforeSerialisation() - { - } - - /// <inheritdoc /> - public void Deserialise(ReadOnlyMemory<byte> serialisedObject) - { - } - - /// <inheritdoc /> - public Memory<byte> Serialise() - { - return Memory<byte>.Empty; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Builtin/SimpleDataPacket.cs b/NetSharp/NetSharp/Deprecated/Builtin/SimpleDataPacket.cs @@ -1,55 +0,0 @@ -using System; - -namespace NetSharp.Deprecated.Builtin -{ - /// <summary> - /// A simple one-time-use data transfer packet, that allows for the transmission of an arbitrary number of frames. - /// </summary> - [PacketTypeId(7)] - public class SimpleDataPacket : IRequestPacket - { - /// <summary> - /// The data that should be transferred across the network. - /// </summary> - public Memory<byte> RequestBuffer; - - /// <summary> - /// Initialises a new instance of the <see cref="SimpleDataPacket"/> class. - /// </summary> - public SimpleDataPacket() - { - RequestBuffer = new byte[0]; - } - - /// <summary> - /// Initialises a new instance of the <see cref="SimpleDataPacket"/> class. - /// </summary> - /// <param name="buffer">The data that this request packet should contain.</param> - public SimpleDataPacket(Memory<byte> buffer) - { - RequestBuffer = buffer; - } - - /// <inheritdoc /> - public void AfterDeserialisation() - { - } - - /// <inheritdoc /> - public void BeforeSerialisation() - { - } - - /// <inheritdoc /> - public void Deserialise(ReadOnlyMemory<byte> serialisedObject) - { - RequestBuffer = serialisedObject.ToArray(); - } - - /// <inheritdoc /> - public Memory<byte> Serialise() - { - return RequestBuffer; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Client.cs b/NetSharp/NetSharp/Deprecated/Client.cs @@ -1,191 +0,0 @@ -using NetSharp.Deprecated.Builtin; - -using System; -using System.Net; -using System.Net.Sockets; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides methods for connecting to and talking with a <see cref="IServer"/> instance. - /// </summary> - public abstract class Client : ServerClientConnection, IClient, IDisposable - { - /// <summary> - /// Initialises a new instance of the <see cref="Client"/> class. - /// </summary> - private Client() - { - remoteEndPoint = new IPEndPoint(IPAddress.None, IPEndPoint.MinPort); - socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - - socketOptions = new DefaultSocketOptions(ref socket); - } - - /// <summary> - /// Destroys an instance of the <see cref="Client"/> class. - /// </summary> - ~Client() - { - Dispose(false); - } - - /// <summary> - /// The <see cref="Socket"/> underlying the connection. - /// </summary> - protected readonly Socket socket; - - /// <summary> - /// Backing field for the <see cref="SocketOptions"/> property. - /// </summary> - protected readonly SocketOptions socketOptions; - - /// <summary> - /// The remote endpoint with which this client communicates. - /// </summary> - protected EndPoint remoteEndPoint; - - /// <summary> - /// Initialises a new instance of the <see cref="Client"/> class. - /// </summary> - /// <param name="socketType">The socket type for the underlying socket.</param> - /// <param name="protocolType">The protocol type for the underlying socket.</param> - /// <param name="socketManager">The <see cref="Utils.Socket_Options.SocketOptions"/> manager to use.</param> - protected Client(SocketType socketType, ProtocolType protocolType) : this() - { - socket = new Socket(AddressFamily.InterNetwork, socketType, protocolType); - } - - /// <summary> - /// Disposes of this <see cref="Client"/> instance. - /// </summary> - /// <param name="disposing">Whether this instance is being disposed.</param> - protected override void Dispose(bool disposing) - { - if (disposing) - { - socket.Dispose(); - } - - base.Dispose(disposing); - } - - /// <summary> - /// Invokes the <see cref="Connected"/> event. - /// </summary> - /// <param name="endPoint">The remote endpoint with which a connection was made.</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void OnConnected(EndPoint endPoint) => Connected?.Invoke(endPoint); - - /// <summary> - /// Invokes the <see cref="Disconnected"/> event. - /// </summary> - /// <param name="endPoint">The remote endpoint with which a connection was lost.</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void OnDisconnected(EndPoint endPoint) => Disconnected?.Invoke(endPoint); - - /// <inheritdoc /> - public event Action<EndPoint>? Connected; - - /// <inheritdoc /> - public event Action<EndPoint>? Disconnected; - - /// <summary> - /// The configured socket options for the underlying connection. - /// </summary> - public SocketOptions SocketOptions - { - get { return socketOptions; } - } - - /// <summary> - /// Disconnects the client from the remote endpoint. - /// </summary> - public void Disconnect() - { - SendSimpleAsync(new DisconnectPacket(), Timeout.InfiniteTimeSpan).Wait(); - - socket.Shutdown(SocketShutdown.Both); - - if (socketOptions is TcpSocketOptions) - { - socket.Disconnect(true); - } - - socket.Close(); - } - - /// <inheritdoc /> - public abstract Task<bool> SendBytesAsync(byte[] buffer, TimeSpan timeout); - - /// <inheritdoc /> - public abstract Task<byte[]> SendBytesWithResponseAsync(byte[] buffer, TimeSpan timeout); - - /// <inheritdoc /> - public abstract Task<Rep> SendComplexAsync<Req, Rep>(Req request, TimeSpan timeout) - where Req : IRequestPacket, new() where Rep : IResponsePacket<Req>, new(); - - /// <inheritdoc /> - public abstract Task<bool> SendSimpleAsync<Req>(Req request, TimeSpan timeout) where Req : IRequestPacket, new(); - - /// <inheritdoc /> - public Task<bool> TryBindAsync(IPAddress? localAddress, int? localPort, TimeSpan timeout) - { - using CancellationTokenSource cts = new CancellationTokenSource(timeout); - EndPoint localEndPoint = new IPEndPoint(localAddress ?? IPAddress.Any, localPort ?? 0); - - try - { - return Task.Run(() => - { - socket.Bind(localEndPoint); - - return true; - }, cts.Token); - } - catch (TaskCanceledException) - { - return Task.FromResult(false); - } - catch (SocketException ex) - { - logger.LogException($"Socket exception on binding socket to {localEndPoint}:", ex); - return Task.FromResult(false); - } - } - - /// <inheritdoc /> - public async Task<bool> TryConnectAsync(IPAddress remoteAddress, int remotePort, TimeSpan timeout) - { - using CancellationTokenSource cts = new CancellationTokenSource(timeout); - remoteEndPoint = new IPEndPoint(remoteAddress, remotePort); - - try - { - return await Task.Run(async () => - { - await socket.ConnectAsync(remoteEndPoint); - - ConnectResponsePacket connectionResponsePacket = - await SendComplexAsync<ConnectPacket, ConnectResponsePacket>(new ConnectPacket(), timeout); - - OnConnected(remoteEndPoint); - - return true; - }, cts.Token); - } - catch (TaskCanceledException) - { - return false; - } - catch (SocketException ex) - { - logger.LogException($"Socket exception on connection to {remoteEndPoint}:", ex); - return false; - } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/ClientExtensions.cs b/NetSharp/NetSharp/Deprecated/ClientExtensions.cs @@ -1,208 +0,0 @@ -using System; -using System.Net; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides additional methods and functionality to the <see cref="Client"/> class. - /// </summary> - public static class ClientExtensions - { - /// <summary> - /// Sends the given byte buffer to the connected remote endpoint. Blocks until the bytes are all sent, and does - /// not timeout. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - public static bool SendBytes(this Client instance, byte[] buffer) => - instance.SendBytesAsync(buffer, Timeout.InfiniteTimeSpan).Result; - - /// <summary> - /// Sends the given byte buffer to the connected remote endpoint. Blocks until the bytes are all sent, whilst - /// observing a timeout of the given length. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - /// <param name="timeout">The timeout after which to cancel the transmission attempt.</param> - public static bool SendBytes(this Client instance, byte[] buffer, TimeSpan timeout) => - instance.SendBytesAsync(buffer, timeout).Result; - - /// <summary> - /// Sends the given byte buffer to the connected remote endpoint asynchronously. Does not block, and does not - /// timeout. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - public static async Task<bool> SendBytesAsync(this Client instance, byte[] buffer) => - await instance.SendBytesAsync(buffer, Timeout.InfiniteTimeSpan); - - /// <summary> - /// Sends the given byte buffer to the connected remote endpoint and waits for the response. Blocks until the - /// bytes are all sent and the response has been received, and does not timeout. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - /// <returns>The byte buffer that was received as a response.</returns> - public static byte[] SendBytesWithResponse(this Client instance, byte[] buffer) => - instance.SendBytesWithResponseAsync(buffer, Timeout.InfiniteTimeSpan).Result; - - /// <summary> - /// Sends the given byte buffer to the connected remote endpoint and waits for the response. Blocks until the - /// bytes are all sent and the response has been received, whilst observing a timeout of the given length. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - /// <param name="timeout">The timeout after which to cancel the transmission attempt.</param> - /// <returns>The byte buffer that was received as a response.</returns> - public static byte[] SendBytesWithResponse(this Client instance, byte[] buffer, TimeSpan timeout) => - instance.SendBytesWithResponseAsync(buffer, timeout).Result; - - /// <summary> - /// Sends the given byte buffer to the connected remote endpoint and waits for the response asynchronously. - /// Does not block, and does not timeout. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - /// <returns>The byte buffer received as a response to the sent buffer.</returns> - public static async Task<byte[]> SendBytesWithResponseAsync(this Client instance, byte[] buffer) => - await instance.SendBytesWithResponseAsync(buffer, Timeout.InfiniteTimeSpan); - - /// <summary> - /// Sends the given request and listens for a response of the given type. Blocks until the response is received. - /// Does not timeout. - /// </summary> - /// <typeparam name="Req">The type of request packet to send.</typeparam> - /// <typeparam name="Rep">The type of response packet to receive.</typeparam> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="request">The request packet to send.</param> - /// <returns>The received instance.</returns> - public static Rep SendComplex<Req, Rep>(this Client instance, Req request) - where Req : IRequestPacket, new() where Rep : IResponsePacket<Req>, new() => - instance.SendComplexAsync<Req, Rep>(request, Timeout.InfiniteTimeSpan).Result; - - /// <summary> - /// Sends the given request and listens for a response of the given type. Blocks until the response is received. - /// Cancels the operation if the given timeout is exceeded. - /// </summary> - /// <typeparam name="Req">The type of request packet to send.</typeparam> - /// <typeparam name="Rep">The type of response packet to receive.</typeparam> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="request">The request packet to send.</param> - /// <param name="timeout">The timeout for which to wait for the operation to complete.</param> - /// <returns>The received instance.</returns> - public static Rep SendComplex<Req, Rep>(this Client instance, Req request, TimeSpan timeout) - where Req : IRequestPacket, new() where Rep : IResponsePacket<Req>, new() => - instance.SendComplexAsync<Req, Rep>(request, timeout).Result; - - /// <summary> - /// Sends the given request and listens for a response of the given type asynchronously. Does not block. Does not timeout. - /// </summary> - /// <typeparam name="Req">The type of request packet to send.</typeparam> - /// <typeparam name="Rep">The type of response packet to receive.</typeparam> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="request">The request packet to send.</param> - /// <returns>The received instance.</returns> - public static async Task<Rep> SendComplexAsync<Req, Rep>(this Client instance, Req request) - where Req : IRequestPacket, new() where Rep : IResponsePacket<Req>, new() => - await instance.SendComplexAsync<Req, Rep>(request, Timeout.InfiniteTimeSpan); - - /// <summary> - /// Sends the given request without listening for a response, blocking until it is sent. Does not timeout. - /// </summary> - /// <typeparam name="Req">The type of request packet to send.</typeparam> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="request">The request packet to send.</param> - public static bool SendSimple<Req>(this Client instance, Req request) where Req : IRequestPacket, new() => - instance.SendSimpleAsync(request, Timeout.InfiniteTimeSpan).Result; - - /// <summary> - /// Sends the given request without listening for a response, blocking until it is sent. - /// Cancels the operation if the given timeout is exceeded. - /// </summary> - /// <typeparam name="Req">The type of request packet to send.</typeparam> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="request">The request packet to send.</param> - /// <param name="timeout">The timeout for which to wait for the operation to complete.</param> - public static bool SendSimple<Req>(this Client instance, Req request, TimeSpan timeout) where Req : IRequestPacket, new() => - instance.SendSimpleAsync(request, timeout).Result; - - /// <summary> - /// Sends the given request asynchronously without listening for a response, not blocking until it is sent. - /// Does not timeout. - /// </summary> - /// <typeparam name="Req">The type of request packet to send.</typeparam> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="request">The request packet to send.</param> - public static async Task<bool> SendSimpleAsync<Req>(this Client instance, Req request) where Req : IRequestPacket, new() => - await instance.SendSimpleAsync(request, Timeout.InfiniteTimeSpan); - - /// <summary> - /// Attempts to synchronously bind the underlying socket to the given local address and port. Blocks. Does not timeout. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="localAddress">The local IP address to bind to. Null if any IP address will suffice.</param> - /// <param name="localPort">The local port to bind to. Null if any port will suffice.</param> - /// <returns>Whether the binding was successful or not.</returns> - public static bool TryBind(this Client instance, IPAddress? localAddress, int? localPort) - => instance.TryBindAsync(localAddress, localPort, Timeout.InfiniteTimeSpan).Result; - - /// <summary> - /// Attempts to synchronously bind the underlying socket to the given local address and port. Blocks. - /// If the timeout is exceeded the binding attempt is aborted and the method returns false. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="localAddress">The local IP address to bind to. Null if any IP address will suffice.</param> - /// <param name="localPort">The local port to bind to. Null if any port will suffice.</param> - /// <param name="timeout">The timeout within which to attempt the binding.</param> - /// <returns>Whether the binding was successful or not.</returns> - public static bool TryBind(this Client instance, IPAddress? localAddress, int? localPort, TimeSpan timeout) - => instance.TryBindAsync(localAddress, localPort, timeout).Result; - - /// <summary> - /// Attempts to asynchronously bind the underlying socket to the given local address and port. Does not block. - /// Does not timeout. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="localAddress">The local IP address to bind to. Null if any IP address will suffice.</param> - /// <param name="localPort">The local port to bind to. Null if any port will suffice.</param> - /// <returns>Whether the binding was successful or not.</returns> - public static async Task<bool> TryBindAsync(this Client instance, IPAddress? localAddress, int? localPort) - => await instance.TryBindAsync(localAddress, localPort, Timeout.InfiniteTimeSpan); - - /// <summary> - /// Attempts to connect to the remote <see cref="Server"/> at the given <see cref="IPAddress"/> and over the - /// given port. Does not timeout. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="remoteAddress">The remote IP address to connect to.</param> - /// <param name="remotePort">The remote port to connect over.</param> - /// <returns>Whether the connection was successful or not.</returns> - public static bool TryConnect(this Client instance, IPAddress remoteAddress, int remotePort) => - instance.TryConnectAsync(remoteAddress, remotePort).Wait(Timeout.InfiniteTimeSpan); - - /// <summary> - /// Attempts to connect to the remote <see cref="Server"/> at the given <see cref="IPAddress"/> and over the - /// given port. If the timeout is exceeded the connection attempt is aborted and the method returns false. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="remoteAddress">The remote IP address to connect to.</param> - /// <param name="remotePort">The remote port to connect over.</param> - /// <param name="timeout">The timeout within which to attempt the connection.</param> - /// <returns>Whether the connection was successful or not.</returns> - public static bool TryConnect(this Client instance, IPAddress remoteAddress, int remotePort, TimeSpan timeout) => - instance.TryConnectAsync(remoteAddress, remotePort).Wait(timeout); - - /// <summary> - /// Attempts to connect asynchronously to the remote <see cref="Server"/> at the given <see cref="IPAddress"/> - /// and over the given port. Does not timeout. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="remoteAddress">The remote IP address to connect to.</param> - /// <param name="remotePort">The remote port to connect over.</param> - /// <returns>Whether the connection was successful or not.</returns> - public static async Task<bool> TryConnectAsync(this Client instance, IPAddress remoteAddress, int remotePort) => - await instance.TryConnectAsync(remoteAddress, remotePort, Timeout.InfiniteTimeSpan); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Connection.cs b/NetSharp/NetSharp/Deprecated/Connection.cs @@ -1,353 +0,0 @@ -using Microsoft.Extensions.ObjectPool; - -using NetSharp.Utils; - -using System; -using System.Buffers; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Channels; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Encapsulates a connection capable of receiving packets and responding to them with registered packet handlers. - /// </summary> - public sealed partial class Connection : IDisposable - { - private readonly HashSet<EndPoint> datagramConnections; - private readonly Channel<(EndPoint origin, Memory<byte> packet)> incomingPacketChannel; - - /// <summary> - /// Pipeline to convert incoming byte buffers to <see cref="NetworkPacket"/> instances. - /// </summary> - private readonly PacketPipeline<Memory<byte>, Memory<byte>, NetworkPacket> incomingPacketPipeline; - - /// <summary> - /// Lock synchronisation object for the <see cref="logger"/> variable. - /// </summary> - private readonly object loggerLockObject = new object(); - - private readonly Channel<(EndPoint destination, NetworkPacket packet)> outgoingPacketChannel; - - /// <summary> - /// Pipeline to convert outgoing <see cref="NetworkPacket"/> instances to a byte buffer for sending. - /// </summary> - private readonly PacketPipeline<NetworkPacket, Memory<byte>, Memory<byte>> outgoingPacketPipeline; - - private readonly Channel<(EndPoint origin, IRequestPacket request)> requestChannel; - - /// <summary> - /// Cancellation token which allows observing the shutdown of the server. It is set when <see cref="ShutdownServer"/> is called. - /// </summary> - private readonly CancellationToken ServerShutdownToken; - - private readonly ConcurrentDictionary<EndPoint, Socket> streamConnections; - - /// <summary> - /// A logger object allowing for writing debug messages to an output stream. - /// </summary> - private Logger logger; - - /// <summary> - /// Destroys a <see cref="Connection"/> class instance, freeing all managed resources. - /// </summary> - ~Connection() - { - Dispose(false); - } - - private async Task AcceptorWork(object shutdownToken) - { - CancellationToken cancellationToken = (CancellationToken)shutdownToken; - - logger.LogMessage("Started stream acceptor task."); - - async Task StreamListenerWork(object clientArgsObj) - { - Socket clientSocket = (Socket)clientArgsObj; - EndPoint clientEndPoint = clientSocket.RemoteEndPoint; - - logger.LogMessage($"Client handler started for {clientEndPoint}"); - - while (!cancellationToken.IsCancellationRequested) - { - // TODO: implement receive buffer pooling - byte[] receiveBuffer = new byte[NetworkPacket.PacketSize]; - Memory<byte> receiveBufferMemory = new Memory<byte>(receiveBuffer); - - TransmissionResult result = - await DoReceiveFromAsync(clientSocket, clientEndPoint, SocketFlags.None, receiveBufferMemory, cancellationToken); - - if (result.Count == 0) - { - break; - } - - await incomingPacketChannel.Writer.WriteAsync((result.RemoteEndPoint, receiveBufferMemory), - cancellationToken); - } - - logger.LogMessage($"Client handler stopped for {clientEndPoint}"); - - await DoDisconnectAsync(clientSocket, cancellationToken); - - clientSocket.Shutdown(SocketShutdown.Both); - clientSocket.Close(1); - } - - streamSocket.Listen(MaximumConnectionBacklog); - - while (!cancellationToken.IsCancellationRequested) - { - Socket clientSocket = await DoAcceptAsync(streamSocket, cancellationToken); - - if (!streamConnections.ContainsKey(clientSocket.RemoteEndPoint)) - { - streamConnections[clientSocket.RemoteEndPoint] = clientSocket; - - await Task.Factory.StartNew(StreamListenerWork, streamConnections[clientSocket.RemoteEndPoint], ServerShutdownToken); - } - else - { - logger.LogWarning($"Accepted duplicate connection from {clientSocket.RemoteEndPoint}"); - } - } - - logger.LogMessage("Stopped stream acceptor task."); - } - - private async Task DatagramListenerWork(object shutdownToken) - { - CancellationToken cancellationToken = (CancellationToken)shutdownToken; - - logger.LogMessage("Started datagram listener task."); - - while (!cancellationToken.IsCancellationRequested) - { - // TODO: implement receive buffer pooling - byte[] receiveBuffer = new byte[NetworkPacket.PacketSize]; - Memory<byte> receiveBufferMemory = new Memory<byte>(receiveBuffer); - - TransmissionResult result = - await DoReceiveFromAsync(datagramSocket, AnyRemoteEndPoint, SocketFlags.None, - receiveBufferMemory, cancellationToken); - - if (!datagramConnections.Contains(result.RemoteEndPoint)) - { - datagramConnections.Add(result.RemoteEndPoint); - } - - await incomingPacketChannel.Writer.WriteAsync((result.RemoteEndPoint, receiveBufferMemory), cancellationToken); - } - - logger.LogMessage("Stopped datagram listener task."); - } - - private async Task IncomingPacketHandlerWork(object shutdownToken) - { - CancellationToken cancellationToken = (CancellationToken)shutdownToken; - - logger.LogMessage("Started incoming packet handler task."); - - while (!cancellationToken.IsCancellationRequested) - { - (EndPoint origin, Memory<byte> packet) = - await incomingPacketChannel.Reader.ReadAsync(cancellationToken); - - NetworkPacket deserialisedRequest = incomingPacketPipeline.ProcessPacket(packet); - - // TODO implement deserialisation according to registered packet deserialisers - - // TODO: write to requestChannel, not to outgoingPacketChannel - await outgoingPacketChannel.Writer.WriteAsync((origin, deserialisedRequest), cancellationToken); - } - - logger.LogMessage("Stopped incoming packet handler task."); - } - - private async Task OutgoingPacketHandlerWork(object shutdownToken) - { - CancellationToken cancellationToken = (CancellationToken)shutdownToken; - - logger.LogMessage("Started outgoing packet handler task."); - - while (!cancellationToken.IsCancellationRequested) - { - (EndPoint destination, NetworkPacket packet) = - await outgoingPacketChannel.Reader.ReadAsync(cancellationToken); - - Memory<byte> serialisedResponse = outgoingPacketPipeline.ProcessPacket(packet); - - if (streamConnections.ContainsKey(destination)) - { - Socket streamConnection = streamConnections[destination]; - - await DoSendToAsync(streamConnection, destination, SocketFlags.None, - serialisedResponse, cancellationToken); - } - else if (datagramConnections.Contains(destination)) - { - await DoSendToAsync(datagramSocket, destination, SocketFlags.None, - serialisedResponse, cancellationToken); - } - else - { - logger.LogWarning($"Packet destined for unknown destination: {destination}"); - } - } - - logger.LogMessage("Stopped outgoing packet handler task."); - } - - private async Task RequestHandlerInvocationWork(object shutdownToken) - { - CancellationToken cancellationToken = (CancellationToken)shutdownToken; - - logger.LogMessage("Started request handler invocation task."); - - while (!cancellationToken.IsCancellationRequested) - { - (EndPoint origin, IRequestPacket request) = await requestChannel.Reader.ReadAsync(cancellationToken); - - // TODO: implement proper request handling, and conversion to IResponsePacket<IRequestPacke> - - NetworkPacket serialisedResponsePacket = new NetworkPacket(); - - await outgoingPacketChannel.Writer.WriteAsync((origin, serialisedResponsePacket), cancellationToken); - } - - logger.LogMessage("Stopped request handler invocation task."); - } - - internal Connection( - PacketPipeline<Memory<byte>, Memory<byte>, NetworkPacket> incomingPacketPipeline, - PacketPipeline<NetworkPacket, Memory<byte>, Memory<byte>> outgoingPacketPipeline, - int objectPoolSize = 10, bool preallocateBuffers = false, Stream? loggingStream = default, - LogLevel minimumLoggedSeverity = LogLevel.Info) - { - serverShutdownTokenSource = new CancellationTokenSource(); - ServerShutdownToken = serverShutdownTokenSource.Token; - - streamSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - datagramSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - - sendToBufferPool = ArrayPool<byte>.Create(NetworkPacket.PacketSize, objectPoolSize); - receiveFromBufferPool = ArrayPool<byte>.Create(NetworkPacket.PacketSize, objectPoolSize); - - clientSocketArgsPool = - new LeakTrackingObjectPool<SocketAsyncEventArgs>( - new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>(), - objectPoolSize)); - receiveArgsPool = - new LeakTrackingObjectPool<SocketAsyncEventArgs>( - new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>(), - objectPoolSize)); - sendArgsPool = - new LeakTrackingObjectPool<SocketAsyncEventArgs>( - new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>(), - objectPoolSize)); - - for (int i = 0; i < objectPoolSize; i++) - { - SocketAsyncEventArgs clientArgs = new SocketAsyncEventArgs(); - clientArgs.Completed += HandleIOCompleted; - clientSocketArgsPool.Return(clientArgs); - - SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs(); - receiveArgs.Completed += HandleIOCompleted; - receiveArgsPool.Return(receiveArgs); - - SocketAsyncEventArgs sendArgs = new SocketAsyncEventArgs(); - sendArgs.Completed += HandleIOCompleted; - sendArgsPool.Return(sendArgs); - } - - if (preallocateBuffers) - { - //TODO: Preallocate buffers someday - } - - streamConnections = new ConcurrentDictionary<EndPoint, Socket>(); - datagramConnections = new HashSet<EndPoint>(); - - this.incomingPacketPipeline = incomingPacketPipeline; - BoundedChannelOptions incomingChannelOptions = new BoundedChannelOptions(MaximumPacketBacklog) - { - FullMode = BoundedChannelFullMode.DropOldest, - SingleReader = true, - SingleWriter = false, - }; - incomingPacketChannel = Channel.CreateBounded<(EndPoint origin, Memory<byte> packet)>(incomingChannelOptions); - - BoundedChannelOptions requestChannelOptions = new BoundedChannelOptions(MaximumPacketBacklog) - { - FullMode = BoundedChannelFullMode.DropOldest, - SingleReader = true, - SingleWriter = true, - }; - requestChannel = Channel.CreateBounded<(EndPoint origin, IRequestPacket request)>(requestChannelOptions); - - this.outgoingPacketPipeline = outgoingPacketPipeline; - BoundedChannelOptions outgoingChannelOptions = new BoundedChannelOptions(MaximumPacketBacklog) - { - FullMode = BoundedChannelFullMode.DropOldest, - SingleReader = true, - SingleWriter = true, - }; - outgoingPacketChannel = Channel.CreateBounded<(EndPoint destination, NetworkPacket packet)>(outgoingChannelOptions); - - logger = new Logger(loggingStream ?? Stream.Null, minimumLoggedSeverity); - } - - /// <summary> - /// Makes the connection listen for incoming request packets, and handle them according to registered packet handler delegates. - /// This work can be cancelled by calling <see cref="ShutdownServer"/>. - /// </summary> - /// <returns>The task representing the connection work.</returns> - public Task RunServerAsync() - { - logger.LogMessage("Starting stream acceptor task..."); - Task acceptorThread = - Task.Factory.StartNew(AcceptorWork, ServerShutdownToken, ServerShutdownToken, TaskCreationOptions.LongRunning, - TaskScheduler.Default).Result; - - logger.LogMessage("Starting datagram listener task..."); - Task datagramListenerThread = - Task.Factory.StartNew(DatagramListenerWork, ServerShutdownToken, ServerShutdownToken, TaskCreationOptions.LongRunning, - TaskScheduler.Default); - - logger.LogMessage("Starting incoming packet handler task..."); - Task incomingPacketHandlerThread = - Task.Factory.StartNew(IncomingPacketHandlerWork, ServerShutdownToken, ServerShutdownToken, TaskCreationOptions.LongRunning, - TaskScheduler.Default); - - logger.LogMessage("Starting request packet invocation task..."); - Task requestHandlerInvocationThread = - Task.Factory.StartNew(RequestHandlerInvocationWork, ServerShutdownToken, ServerShutdownToken, TaskCreationOptions.LongRunning, - TaskScheduler.Default).Result; - - logger.LogMessage("Starting outgoing packet handler task..."); - Task outgoingPacketHandlerThread = - Task.Factory.StartNew(OutgoingPacketHandlerWork, ServerShutdownToken, ServerShutdownToken, TaskCreationOptions.LongRunning, - TaskScheduler.Default); - - return Task.WhenAll(acceptorThread, datagramListenerThread, - incomingPacketHandlerThread, requestHandlerInvocationThread, outgoingPacketHandlerThread); - } - - /// <summary> - /// Shuts down the connection, and releases managed and unmanaged resources. - /// </summary> - public void ShutdownServer() - { - logger.LogMessage("Signalling shutdown to all client connection handlers..."); - serverShutdownTokenSource.Cancel(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/ConnectionBase.cs b/NetSharp/NetSharp/Deprecated/ConnectionBase.cs @@ -1,465 +0,0 @@ -using Microsoft.Extensions.ObjectPool; - -using NetSharp.Utils; - -using System; -using System.Buffers; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Implements low-level network access on top of which the rest of the connection is built upon. - /// </summary> - public sealed partial class Connection : IDisposable - { - /// <summary> - /// Represents any remote endpoint for datagram operations. - /// </summary> - private static readonly EndPoint AnyRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - - private readonly ObjectPool<SocketAsyncEventArgs> clientSocketArgsPool; - - private readonly Socket datagramSocket; - - private readonly ObjectPool<SocketAsyncEventArgs> receiveArgsPool; - - private readonly ArrayPool<byte> receiveFromBufferPool; - - private readonly ObjectPool<SocketAsyncEventArgs> sendArgsPool; - - private readonly ArrayPool<byte> sendToBufferPool; - - private readonly CancellationTokenSource serverShutdownTokenSource; - - private readonly Socket streamSocket; - - /// <summary> - /// Disposes of the managed and unmanaged resources held by this instance. - /// </summary> - /// <param name="disposing">Whether this method is called by <see cref="Dispose()"/> or by the finaliser.</param> - private void Dispose(bool disposing) - { - if (disposing) - { - serverShutdownTokenSource.Cancel(); - serverShutdownTokenSource.Dispose(); - - streamSocket.Dispose(); - datagramSocket.Dispose(); - } - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket accept operation. - /// </summary> - /// <param name="serverSocket">The socket which should be used to accept an incoming connection attempt.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - /// <returns>The accepted socket.</returns> - private async Task<Socket> DoAcceptAsync(Socket serverSocket, CancellationToken cancellationToken = default) - { - TaskCompletionSource<Socket> tcs = new TaskCompletionSource<Socket>(); - - cancellationToken.Register(() => tcs.SetCanceled()); - - Task<Socket> task = serverSocket.AcceptAsync(); - Task<Socket> completedTask = await Task.WhenAny(task, tcs.Task); - - if (completedTask == task) - { - Socket result = await task; - - tcs.SetResult(result); - } - - return await tcs.Task; - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket connect operation. - /// </summary> - /// <param name="socket">The socket which should asynchronously connect to the remote endpoint.</param> - /// <param name="remoteEndPoint">The remote endpoint to which the socket should connect.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - private async Task DoConnectAsync(Socket socket, EndPoint remoteEndPoint, CancellationToken cancellationToken = default) - { - TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); - - cancellationToken.Register(() => tcs.SetCanceled()); - - Task task = socket.ConnectAsync(remoteEndPoint); - Task completedTask = await Task.WhenAny(task, tcs.Task); - - if (completedTask == task) - { - await task; - tcs.SetResult(true); - } - - await tcs.Task; - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket disconnect operation. - /// </summary> - /// <param name="connectedSocket">The socket which should asynchronously disconnect from its remote endpoint.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - private Task DoDisconnectAsync(Socket connectedSocket, CancellationToken cancellationToken = default) - { - return Task.Factory.StartNew(() => - { - connectedSocket.Disconnect(true); - }, cancellationToken); - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket receive operation. - /// </summary> - /// <param name="listenerSocket">The socket which should receive data from the remote endpoint.</param> - /// <param name="remoteEndPoint">The remove endpoint from which data should be received.</param> - /// <param name="socketFlags">The socket flags associated with the receive operation.</param> - /// <param name="inputBuffer">The memory buffer into which received data will be stored.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - /// <returns>The result of the receive operation from the remote endpoint.</returns> - private Task<TransmissionResult> DoReceiveFromAsync(Socket listenerSocket, EndPoint remoteEndPoint, SocketFlags socketFlags, - Memory<byte> inputBuffer, CancellationToken cancellationToken = default) - { - TaskCompletionSource<TransmissionResult> tcs = new TaskCompletionSource<TransmissionResult>(); - - byte[] rentedReceiveFromBuffer = receiveFromBufferPool.Rent(NetworkPacket.PacketSize); - Memory<byte> rentedReceiveFromBufferMemory = new Memory<byte>(rentedReceiveFromBuffer); - - SocketAsyncEventArgs clientArgs = receiveArgsPool.Get(); - clientArgs.SetBuffer(rentedReceiveFromBufferMemory); - clientArgs.SocketFlags = socketFlags; - clientArgs.RemoteEndPoint = remoteEndPoint; - clientArgs.UserToken = new AsyncReadToken(rentedReceiveFromBuffer, inputBuffer, tcs, cancellationToken); - - // if the receive operation doesn't complete synchronously, returns the awaitable task - if (listenerSocket.ReceiveFromAsync(clientArgs)) return tcs.Task; - - clientArgs.MemoryBuffer.CopyTo(inputBuffer); - - TransmissionResult result = new TransmissionResult(clientArgs); - - receiveFromBufferPool.Return(rentedReceiveFromBuffer, true); - receiveArgsPool.Return(clientArgs); - - return Task.FromResult(result); - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket send operation. - /// </summary> - /// <param name="transmitterSocket">The socket which should send the data to the remote endpoint.</param> - /// <param name="remoteEndPoint">The remote endpoint to which data should be written.</param> - /// <param name="socketFlags">The socket flags associated with the send operation.</param> - /// <param name="outputBuffer">The data buffer which should be sent.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - /// <returns>The result of the send operation to the remote endpoint.</returns> - private ValueTask<int> DoSendToAsync(Socket transmitterSocket, EndPoint remoteEndPoint, SocketFlags socketFlags, - Memory<byte> outputBuffer, CancellationToken cancellationToken = default) - { - TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); - - byte[] rentedSendToBuffer = sendToBufferPool.Rent(NetworkPacket.PacketSize); - Memory<byte> rentedSendToBufferMemory = new Memory<byte>(rentedSendToBuffer); - - outputBuffer.CopyTo(rentedSendToBufferMemory); - - SocketAsyncEventArgs clientArgs = sendArgsPool.Get(); - clientArgs.SetBuffer(rentedSendToBufferMemory); - clientArgs.SocketFlags = socketFlags; - clientArgs.RemoteEndPoint = remoteEndPoint; - clientArgs.UserToken = new AsyncWriteToken(rentedSendToBuffer, tcs, cancellationToken); - - /* NOT WORKING, NEED SOLUTION AT SOME POINT!!! - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - sendBufferPool.Return(rentedSendToBuffer, true); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - sendAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the send operation doesn't complete synchronously, return the awaitable task - if (transmitterSocket.SendToAsync(clientArgs)) return new ValueTask<int>(tcs.Task); - - int result = clientArgs.BytesTransferred; - - sendToBufferPool.Return(rentedSendToBuffer, true); - sendArgsPool.Return(clientArgs); - - return new ValueTask<int>(result); - } - - private void HandleIOCompleted(object? sender, SocketAsyncEventArgs args) - { - switch (args.LastOperation) - { - case SocketAsyncOperation.SendTo: - AsyncWriteToken asyncSendToToken = (AsyncWriteToken)args.UserToken; - - if (asyncSendToToken.CancellationToken.IsCancellationRequested) - { - asyncSendToToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncSendToToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - asyncSendToToken.CompletionSource.SetResult(args.BytesTransferred); - } - } - - sendToBufferPool.Return(asyncSendToToken.RentedBuffer, true); - sendArgsPool.Return(args); - - break; - - case SocketAsyncOperation.ReceiveFrom: - AsyncReadToken asyncReceiveFromToken = (AsyncReadToken)args.UserToken; - - if (asyncReceiveFromToken.CancellationToken.IsCancellationRequested) - { - asyncReceiveFromToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncReceiveFromToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else if (args.BytesTransferred <= 0) - { - TransmissionResult result = new TransmissionResult(args); - - asyncReceiveFromToken.CompletionSource.SetResult(result); - } - else - { - args.MemoryBuffer.CopyTo(asyncReceiveFromToken.UserBuffer); - - TransmissionResult result = new TransmissionResult(args); - - asyncReceiveFromToken.CompletionSource.SetResult(result); - } - } - - receiveFromBufferPool.Return(asyncReceiveFromToken.RentedBuffer, true); - receiveArgsPool.Return(args); - - break; - - default: - throw new InvalidOperationException( - $"The {nameof(Connection)} class doesn't support the {args.LastOperation} operation."); - } - } - - private readonly struct AsyncReadToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<TransmissionResult> CompletionSource; - public readonly byte[] RentedBuffer; - public readonly Memory<byte> UserBuffer; - - public AsyncReadToken(byte[] rentedBuffer, Memory<byte> userBuffer, TaskCompletionSource<TransmissionResult> tcs, - CancellationToken cancellationToken = default) - { - RentedBuffer = rentedBuffer; - UserBuffer = userBuffer; - - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - private readonly struct AsyncWriteToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<int> CompletionSource; - public readonly byte[] RentedBuffer; - - public AsyncWriteToken(byte[] rentedBuffer, TaskCompletionSource<int> tcs, - CancellationToken cancellationToken = default) - { - RentedBuffer = rentedBuffer; - - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - /// <summary> - /// The maximum number of stream connection that will be accepted. - /// </summary> - /// TODO change this to a configurable builder option - public const int MaximumConnectionBacklog = 10; - - /// <summary> - /// The maximum number of packets that will be stored before older packets start to be dropped. - /// </summary> - /// TODO change this to a configurable builder option - public const int MaximumPacketBacklog = 64; - - /// <inheritdoc /> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public Task<TransmissionResult> ReceiveAsync(Memory<byte> inputBuffer, SocketFlags flags, TimeSpan timeout) - { - using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout); - using CancellationTokenSource cts = - CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, ServerShutdownToken); - - return DoReceiveFromAsync(streamSocket, streamSocket.RemoteEndPoint, flags, inputBuffer, cts.Token); - } - - public Task<TransmissionResult> ReceiveFromAsync(EndPoint remoteEndPoint, Memory<byte> inputBuffer, SocketFlags flags, TimeSpan timeout) - { - using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout); - using CancellationTokenSource cts = - CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, ServerShutdownToken); - - return DoReceiveFromAsync(datagramSocket, remoteEndPoint, flags, inputBuffer, cts.Token); - } - - public ValueTask<int> SendAsync(Memory<byte> outputBuffer, SocketFlags flags, TimeSpan timeout) - { - using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout); - using CancellationTokenSource cts = - CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, ServerShutdownToken); - - return DoSendToAsync(streamSocket, streamSocket.RemoteEndPoint, flags, outputBuffer, cts.Token); - } - - public ValueTask<int> SendToAsync(EndPoint remoteEndPoint, Memory<byte> outputBuffer, SocketFlags flags, TimeSpan timeout) - { - using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout); - using CancellationTokenSource cts = - CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, ServerShutdownToken); - - return DoSendToAsync(datagramSocket, remoteEndPoint, flags, outputBuffer, cts.Token); - } - - /// <summary> - /// Configures the logger to log messages to the given stream (or to <see cref="Stream.Null"/> if <c>null</c>) and - /// to only log messages that are of severity <paramref name="minimumLoggedSeverity"/> or higher. - /// </summary> - /// <param name="loggingStream">The stream to which messages will be logged.</param> - /// <param name="minimumLoggedSeverity">The minimum severity a message must be to be logged.</param> - public void SetLoggingStream(Stream? loggingStream, LogLevel minimumLoggedSeverity = LogLevel.Info) - { - lock (loggerLockObject) - { - logger = new Logger(loggingStream ?? Stream.Null, minimumLoggedSeverity); - } - } - - /// <summary> - /// Attempts to asynchronously bind the underlying socket to the given local endpoint. Does not block. - /// If the timeout is exceeded the binding attempt is aborted and the method returns false. - /// </summary> - /// <param name="localEndPoint">The local endpoint to bind to.</param> - /// <param name="timeout">The timeout within which to attempt the binding.</param> - /// <returns>Whether the binding was successful or not.</returns> - public async Task<bool> TryBindAsync(EndPoint localEndPoint, TimeSpan timeout) - { - using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout); - using CancellationTokenSource cts = - CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, ServerShutdownToken); - - try - { - return await Task.Run(() => - { - streamSocket.Bind(localEndPoint); - datagramSocket.Bind(localEndPoint); - - return true; - }, cts.Token); - } - catch (TaskCanceledException) - { - return false; - } - catch (SocketException ex) - { - logger.LogException($"Socket exception on binding socket to {localEndPoint}:", ex); - return false; - } - } - - public async Task<bool> TryConnectAsync(EndPoint remoteEndPoint, TimeSpan timeout) - { - using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout); - using CancellationTokenSource cts = - CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, ServerShutdownToken); - - try - { - await DoConnectAsync(streamSocket, remoteEndPoint, cts.Token); - - return true; - } - catch (TaskCanceledException) - { - return false; - } - catch (SocketException ex) - { - logger.LogException($"Socket exception on connecting socket to {remoteEndPoint}:", ex); - return false; - } - } - - public async Task<bool> TryDisconnectAsync(TimeSpan timeout) - { - using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout); - using CancellationTokenSource cts = - CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, ServerShutdownToken); - - try - { - await DoDisconnectAsync(streamSocket, cts.Token); - - streamSocket.Shutdown(SocketShutdown.Both); - streamSocket.Close(1); - - return true; - } - catch (TaskCanceledException) - { - return false; - } - catch (SocketException ex) - { - logger.LogException($"Socket exception on disconnecting socket:", ex); - return false; - } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/ConnectionBuilder.cs b/NetSharp/NetSharp/Deprecated/ConnectionBuilder.cs @@ -1,186 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Allows for configuring and subsequently building a <see cref="Connection"/> instance. - /// </summary> - public sealed class ConnectionBuilder - { - private static readonly LoggingSettings DefaultLoggingSettings = - new LoggingSettings(Stream.Null, LogLevel.Warn); - - private static readonly PoolingSettings DefaultPoolingSettings = - new PoolingSettings(10, false); - - private readonly List<Func<Memory<byte>, Memory<byte>>> incomingPipelineStages = - new List<Func<Memory<byte>, Memory<byte>>>(); - - private readonly List<Func<Memory<byte>, Memory<byte>>> outgoingPipelineStages = - new List<Func<Memory<byte>, Memory<byte>>>(); - - private LoggingSettings? loggingSettings; - private PoolingSettings? poolingSettings; - - /// <summary> - /// The number of stages in the currently configured incoming packet pipeline. - /// </summary> - public int IncomingPacketPipelineStageCount - { - get { return incomingPipelineStages.Count; } - } - - /// <summary> - /// The number of stages in the currently configured outgoing packet pipeline. - /// </summary> - public int OutgoingPacketPipelineStageCount - { - get { return outgoingPipelineStages.Count; } - } - - /// <summary> - /// Returns a new <see cref="Connection"/> instance with the current configuration. - /// </summary> - /// <returns>The configured <see cref="Connection"/> instance.</returns> - public Connection Build() - { - PacketPipelineBuilder<Memory<byte>, Memory<byte>, NetworkPacket> incomingPipelineBuilder = - new PacketPipelineBuilder<Memory<byte>, Memory<byte>, NetworkPacket>(); - - incomingPipelineBuilder.WithInputStage(memory => memory); - foreach (Func<Memory<byte>, Memory<byte>> stage in incomingPipelineStages) - { - incomingPipelineBuilder = incomingPipelineBuilder.WithIntermediateStage(stage); - } - - incomingPipelineBuilder.WithOutputStage(NetworkPacket.Deserialise); - - PacketPipelineBuilder<NetworkPacket, Memory<byte>, Memory<byte>> outgoingPipelineBuilder = - new PacketPipelineBuilder<NetworkPacket, Memory<byte>, Memory<byte>>(); - - outgoingPipelineBuilder.WithInputStage(NetworkPacket.Serialise); - foreach (Func<Memory<byte>, Memory<byte>> stage in outgoingPipelineStages) - { - outgoingPipelineBuilder = outgoingPipelineBuilder.WithIntermediateStage(stage); - } - - outgoingPipelineBuilder.WithOutputStage(memory => memory); - - Connection connection = new Connection( - incomingPipelineBuilder.Build(), - outgoingPipelineBuilder.Build(), - poolingSettings?.ObjectPoolSize ?? DefaultPoolingSettings.ObjectPoolSize, - poolingSettings?.PreallocateBuffers ?? DefaultPoolingSettings.PreallocateBuffers, - loggingSettings?.LoggingStream ?? DefaultLoggingSettings.LoggingStream, - loggingSettings?.MinimumLevel ?? DefaultLoggingSettings.MinimumLevel); - - return connection; - } - - /// <summary> - /// Adds an extra pipeline stage to the currently configured incoming packet pipeline, at the given index. - /// </summary> - /// <param name="transform"> - /// The transformation that should be applied when a packet passes through the pipeline. - /// </param> - /// <param name="index">The position in the pipeline at which to place the transform.</param> - /// <returns>The builder instance for further configuration.</returns> - public ConnectionBuilder WithIncomingPipelineStage(in Func<Memory<byte>, Memory<byte>> transform, int index) - { - incomingPipelineStages.Insert(index, transform); - return this; - } - - /// <summary> - /// Sets the logging settings for the currently configured connection. - /// </summary> - /// <param name="settings">The logging settings to use.</param> - /// <returns>The builder instance for further configuration.</returns> - public ConnectionBuilder WithLogging(LoggingSettings settings) - { - loggingSettings = settings; - return this; - } - - /// <summary> - /// Adds an extra pipeline stage to the currently configured outgoing packet pipeline, at the given index. - /// </summary> - /// <param name="transform"> - /// The transformation that should be applied when a packet passes through the pipeline. - /// </param> - /// <param name="index">The position in the pipeline at which to place the transform.</param> - /// <returns>The builder instance for further configuration.</returns> - public ConnectionBuilder WithOutgoingPipelineStage(in Func<Memory<byte>, Memory<byte>> transform, int index) - { - outgoingPipelineStages.Insert(index, transform); - return this; - } - - /// <summary> - /// Sets the pooling settings for the currently configured connection. - /// </summary> - /// <param name="settings">The pooling settings to use.</param> - /// <returns>The builder instance for further configuration.</returns> - public ConnectionBuilder WithPooling(PoolingSettings settings) - { - poolingSettings = settings; - return this; - } - - /// <summary> - /// Holds settings for configuring a connection's logging. - /// </summary> - public readonly struct LoggingSettings - { - /// <summary> - /// The stream to which messages will be logged. - /// </summary> - public readonly Stream LoggingStream; - - /// <summary> - /// The minimum severity that a log message must have to be recorded. - /// </summary> - public readonly LogLevel MinimumLevel; - - /// <summary> - /// Initialises a new instance of the <see cref="LoggingStream"/> struct. - /// </summary> - /// <param name="stream">The stream to which messages will be logged..</param> - /// <param name="minimumLevel">The minimum severity that a log message must have to be recorded.</param> - public LoggingSettings(Stream stream, LogLevel minimumLevel) - { - LoggingStream = stream; - MinimumLevel = minimumLevel; - } - } - - /// <summary> - /// Holds settings for configuring a connection's buffer pooling. - /// </summary> - public readonly struct PoolingSettings - { - /// <summary> - /// The number of objects that will be held in the object pools. - /// </summary> - public readonly int ObjectPoolSize; - - /// <summary> - /// Whether the buffers for receiving messages should be preallocated. - /// </summary> - public readonly bool PreallocateBuffers; - - /// <summary> - /// Initialises a new instance of the <see cref="PoolingSettings"/> struct. - /// </summary> - /// <param name="poolSize">The number of objects that will be held in the object pools.</param> - /// <param name="preallocateBuffers">Whether the buffers for receiving messages should be preallocated.</param> - public PoolingSettings(int poolSize, bool preallocateBuffers) - { - ObjectPoolSize = poolSize; - PreallocateBuffers = preallocateBuffers; - } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/ConnectionBuilderExtensions.cs b/NetSharp/NetSharp/Deprecated/ConnectionBuilderExtensions.cs @@ -1,27 +0,0 @@ -using System; -using System.IO; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides additional methods and functionality to the <see cref="ConnectionBuilder"/> class. - /// </summary> - public static class ConnectionBuilderExtensions - { - public static ConnectionBuilder AppendIncomingPipelineStage(this ConnectionBuilder instance, - in Func<Memory<byte>, Memory<byte>> transform) - => instance.WithIncomingPipelineStage(transform, instance.IncomingPacketPipelineStageCount); - - public static ConnectionBuilder AppendOutgoingPipelineStage(this ConnectionBuilder instance, - in Func<Memory<byte>, Memory<byte>> transform) - => instance.WithOutgoingPipelineStage(transform, instance.OutgoingPacketPipelineStageCount); - - public static ConnectionBuilder WithLogging(this ConnectionBuilder instance, - Stream loggingStream, LogLevel minimumLogLevel) - => instance.WithLogging(new ConnectionBuilder.LoggingSettings(loggingStream, minimumLogLevel)); - - public static ConnectionBuilder WithPooling(this ConnectionBuilder instance, - int poolSize, bool preallocateBuffers) - => instance.WithPooling(new ConnectionBuilder.PoolingSettings(poolSize, preallocateBuffers)); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/ConnectionExtensions.cs b/NetSharp/NetSharp/Deprecated/ConnectionExtensions.cs @@ -1,73 +0,0 @@ -using NetSharp.Utils; - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides additional methods and functionality to the <see cref="Connection"/> class. - /// </summary> - public static class ConnectionExtensions - { - public static Task<TransmissionResult> ReceiveAsync(this Connection instance, - EndPoint remoteEndPoint, Memory<byte> inputBuffer, SocketFlags flags) - => instance.ReceiveAsync(inputBuffer, flags, Timeout.InfiniteTimeSpan); - - public static Task<TransmissionResult> ReceiveFromAsync(this Connection instance, - EndPoint remoteEndPoint, Memory<byte> inputBuffer, SocketFlags flags) - => instance.ReceiveFromAsync(remoteEndPoint, inputBuffer, flags, Timeout.InfiniteTimeSpan); - - public static ValueTask<int> SendAsync(this Connection instance, - EndPoint remoteEndPoint, Memory<byte> outputBuffer, SocketFlags flags) - => instance.SendAsync(outputBuffer, flags, Timeout.InfiniteTimeSpan); - - public static ValueTask<int> SendToAsync(this Connection instance, - EndPoint remoteEndPoint, Memory<byte> outputBuffer, SocketFlags flags) - => instance.SendToAsync(remoteEndPoint, outputBuffer, flags, Timeout.InfiniteTimeSpan); - - /// <summary> - /// Attempts to synchronously bind the underlying socket to the given local endpoint. Blocks. - /// If the timeout is exceeded the binding attempt is aborted and the method returns false. - /// </summary> - /// <param name="localEndPoint">The local endpoint to bind to.</param> - /// <param name="timeout">The timeout within which to attempt the binding.</param> - /// <returns>Whether the binding was successful or not.</returns> - public static bool TryBind(this Connection instance, - EndPoint localEndPoint, TimeSpan timeout) - => instance.TryBindAsync(localEndPoint, timeout).Result; - - public static bool TryBind(this Connection instance, - EndPoint localEndPoint) - => instance.TryBindAsync(localEndPoint, Timeout.InfiniteTimeSpan).Result; - - public static Task<bool> TryBindAsync(this Connection instance, - EndPoint localEndPoint) - => instance.TryBindAsync(localEndPoint, Timeout.InfiniteTimeSpan); - - public static bool TryConnect(this Connection instance, - EndPoint remoteEndPoint) - => instance.TryConnectAsync(remoteEndPoint, Timeout.InfiniteTimeSpan).Result; - - public static bool TryConnect(this Connection instance, - EndPoint remoteEndPoint, TimeSpan timeout) - => instance.TryConnectAsync(remoteEndPoint, timeout).Result; - - public static Task<bool> TryConnectAsync(this Connection instance, - EndPoint remoteEndPoint) - => instance.TryConnectAsync(remoteEndPoint, Timeout.InfiniteTimeSpan); - - public static bool TryDisconnect(this Connection instance) - => instance.TryDisconnectAsync(Timeout.InfiniteTimeSpan).Result; - - public static bool TryDisconnect(this Connection instance, - TimeSpan timeout) - => instance.TryDisconnectAsync(timeout).Result; - - public static Task<bool> TryDisconnectAsync(this Connection instance) - => instance.TryDisconnectAsync(Timeout.InfiniteTimeSpan); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Constants.cs b/NetSharp/NetSharp/Deprecated/Constants.cs @@ -1,15 +0,0 @@ -namespace NetSharp.Deprecated -{ - /// <summary> - /// Holds internal default configurations and constants. - /// </summary> - internal static class Constants - { - /// <summary> - /// The default port over which a connection is made. - /// </summary> - internal const int DefaultPort = 12374; - - internal const int MaximumUdpPacketBytes = 65507; - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/CryptographyHelpers.cs b/NetSharp/NetSharp/Deprecated/CryptographyHelpers.cs @@ -1,96 +0,0 @@ -using System; -using System.IO; -using System.Security.Cryptography; -using System.Text; - -namespace NetSharp.Deprecated -{ - internal static class CryptographyHelpers - { - #region Settings - - private static string _hash = "SHA1"; - private static int _iterations = 2; - private static int _keySize = 256; - private static string _salt = "aselrias38490a32"; // Random - private static string _vector = "8947az34awl34kjq"; // Random - - #endregion Settings - - public static string Decrypt(byte[] value, string password) - { - return Decrypt<AesManaged>(value, password); - } - - public static string Decrypt<T>(byte[] value, string password) where T : SymmetricAlgorithm, new() - { - byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector); // GetBytes<ASCIIEncoding>(_vector); - byte[] saltBytes = Encoding.ASCII.GetBytes(_salt); // GetBytes<ASCIIEncoding>(_salt); - byte[] valueBytes = value; - - byte[] decrypted; - int decryptedByteCount = 0; - - using (T cipher = new T()) - { - PasswordDeriveBytes _passwordBytes = new PasswordDeriveBytes(password, saltBytes, _hash, _iterations); - byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8); - - cipher.Mode = CipherMode.CBC; - - try - { - using (ICryptoTransform decryptor = cipher.CreateDecryptor(keyBytes, vectorBytes)) - { - using MemoryStream from = new MemoryStream(valueBytes); - using CryptoStream reader = new CryptoStream(@from, decryptor, CryptoStreamMode.Read); - - decrypted = new byte[valueBytes.Length]; - decryptedByteCount = reader.Read(decrypted, 0, decrypted.Length); - } - } - catch (Exception ex) - { - return String.Empty; - } - - cipher.Clear(); - } - return Encoding.UTF8.GetString(decrypted, 0, decryptedByteCount); - } - - public static byte[] Encrypt(string value, string password) - { - return Encrypt<AesManaged>(value, password); - } - - public static byte[] Encrypt<T>(string value, string password) where T : SymmetricAlgorithm, new() - { - byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector); // GetBytes<ASCIIEncoding>(_vector); - byte[] saltBytes = Encoding.ASCII.GetBytes(_salt); // GetBytes<ASCIIEncoding>(_salt); - byte[] valueBytes = Encoding.UTF8.GetBytes(value); // GetBytes<UTF8Encoding>(value); - - byte[] encrypted; - using (T cipher = new T()) - { - PasswordDeriveBytes _passwordBytes = - new PasswordDeriveBytes(password, saltBytes, _hash, _iterations); - byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8); - - cipher.Mode = CipherMode.CBC; - - using (ICryptoTransform encryptor = cipher.CreateEncryptor(keyBytes, vectorBytes)) - { - using MemoryStream to = new MemoryStream(); - using CryptoStream writer = new CryptoStream(to, encryptor, CryptoStreamMode.Write); - - writer.Write(valueBytes, 0, valueBytes.Length); - writer.FlushFinalBlock(); - encrypted = to.ToArray(); - } - cipher.Clear(); - } - return encrypted; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/DefaultSocketOptions.cs b/NetSharp/NetSharp/Deprecated/DefaultSocketOptions.cs @@ -1,46 +0,0 @@ -using System; -using System.Net.Sockets; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Allows for manipulation of socket options. - /// </summary> - public sealed class DefaultSocketOptions : SocketOptions - { - /// <inheritdoc /> - public DefaultSocketOptions(ref Socket socket) : base(ref socket) - { - } - - /// <inheritdoc /> - /// <exception cref="NotSupportedException"> - /// This property is not supported when using the default socket option manager. - /// </exception> - public override int HopLimit - { - get { throw new NotSupportedException("This property is not supported in the default socket options manager."); } - set { throw new NotSupportedException("This property is not supported in the default socket options manager."); } - } - - /// <inheritdoc /> - /// <exception cref="NotSupportedException"> - /// This property is not supported when using the default socket option manager. - /// </exception> - public override bool IsRoutingEnabled - { - get { throw new NotSupportedException("This property is not supported in the default socket options manager."); } - set { throw new NotSupportedException("This property is not supported in the default socket options manager."); } - } - - /// <inheritdoc /> - /// <exception cref="NotSupportedException"> - /// This property is not supported when using the default socket option manager. - /// </exception> - public override bool UseLoopback - { - get { throw new NotSupportedException("This property is not supported in the default socket options manager."); } - set { throw new NotSupportedException("This property is not supported in the default socket options manager."); } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/IClient.cs b/NetSharp/NetSharp/Deprecated/IClient.cs @@ -1,88 +0,0 @@ -using System; -using System.Net; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Describes a client capable of asynchronous communication with an <see cref="IServer"/> connection. - /// </summary> - public interface IClient - { - /// <summary> - /// Signifies that a connection with the remote endpoint has been made. - /// </summary> - public event Action<EndPoint>? Connected; - - /// <summary> - /// Signifies that the connection with the remote endpoint was severed. - /// </summary> - public event Action<EndPoint>? Disconnected; - - /// <summary> - /// Sends the given byte buffer to the connected remote endpoint asynchronously. Does not block, and observes - /// a timeout of the given length. - /// timeout. - /// </summary> - /// <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - /// <param name="timeout">The timeout after which to cancel the transmission attempt.</param> - /// <returns>Whether the transmission attempt was successful.</returns> - public Task<bool> SendBytesAsync(byte[] buffer, TimeSpan timeout); - - /// <summary> - /// Sends the given byte buffer to the connected remote endpoint and waits for the response asynchronously. - /// Does not block, and observes a timeout of the given length. - /// timeout. - /// </summary> - /// <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - /// <param name="timeout"> - /// The timeout after which to cancel the transmission attempt. This timeout is reused by both the 'send' and - /// 'receive' parts of the transmission attempt, such that the maximum timeout is equal to 2 times the given - /// value. - /// </param> - /// <returns>The byte buffer received as a response to the sent buffer.</returns> - public Task<byte[]> SendBytesWithResponseAsync(byte[] buffer, TimeSpan timeout); - - /// <summary> - /// Sends the given request and listens for a response of the given type asynchronously. Does not block. - /// Cancels the operation if the given timeout is exceeded - /// </summary> - /// <typeparam name="Req">The type of request packet to send.</typeparam> - /// <typeparam name="Rep">The type of response packet to receive.</typeparam> - /// <param name="request">The request packet to send.</param> - /// <param name="timeout">The timeout for which to wait for the operation to complete.</param> - /// <returns>The received instance.</returns> - public Task<Rep> SendComplexAsync<Req, Rep>(Req request, TimeSpan timeout) - where Req : IRequestPacket, new() where Rep : IResponsePacket<Req>, new(); - - /// <summary> - /// Sends the given request asynchronously without listening for a response, not blocking until it is sent. - /// Cancels the operation if the given timeout is exceeded. - /// </summary> - /// <typeparam name="Req">The type of request packet to send.</typeparam> - /// <param name="request">The request packet to send.</param> - /// <param name="timeout">The timeout for which to wait for the operation to complete.</param> - /// <returns>Whether the transmission attempt was successful.</returns> - public Task<bool> SendSimpleAsync<Req>(Req request, TimeSpan timeout) where Req : IRequestPacket, new(); - - /// <summary> - /// Attempts to asynchronously bind the underlying socket to the given local address and port. Does not block. - /// If the timeout is exceeded the binding attempt is aborted and the method returns false. - /// </summary> - /// <param name="localAddress">The local IP address to bind to. Null if any IP address will suffice.</param> - /// <param name="localPort">The local port to bind to. Null if any port will suffice.</param> - /// <param name="timeout">The timeout within which to attempt the binding.</param> - /// <returns>Whether the binding was successful or not.</returns> - public Task<bool> TryBindAsync(IPAddress? localAddress, int? localPort, TimeSpan timeout); - - /// <summary> - /// Attempts to connect asynchronously to the remote <see cref="Server"/> at the given <see cref="IPAddress"/> - /// and over the given port. If the timeout is exceeded the connection attempt is aborted and the method returns false. - /// </summary> - /// <param name="remoteAddress">The remote IP address to connect to.</param> - /// <param name="remotePort">The remote port to connect over.</param> - /// <param name="timeout">The timeout within which to attempt the connection.</param> - /// <returns>Whether the connection was successful or not.</returns> - public Task<bool> TryConnectAsync(IPAddress remoteAddress, int remotePort, TimeSpan timeout); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/INetworkSerialisable.cs b/NetSharp/NetSharp/Deprecated/INetworkSerialisable.cs @@ -1,22 +0,0 @@ -using System; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Describes an object that can be serialised to be sent across the network. - /// </summary> - public interface INetworkSerialisable - { - /// <summary> - /// Deserialises the object instance from a byte array. - /// </summary> - /// <param name="serialisedObject">The memory containing the serialised object instance.</param> - void Deserialise(ReadOnlyMemory<byte> serialisedObject); - - /// <summary> - /// Serialises the object instance into a byte array. - /// </summary> - /// <returns>The memory containing the serialised object instance.</returns> - Memory<byte> Serialise(); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/IPacket.cs b/NetSharp/NetSharp/Deprecated/IPacket.cs @@ -1,18 +0,0 @@ -namespace NetSharp.Deprecated -{ - /// <summary> - /// Describes the methods and properties that every packet - /// </summary> - public interface IPacket - { - /// <summary> - /// Allows for custom fields to be converted from their serialised format, after being received from the network. - /// </summary> - void AfterDeserialisation(); - - /// <summary> - /// Allows for custom fields to be converted into another format prior to being sent via the network. - /// </summary> - void BeforeSerialisation(); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/IPacketHandler.cs b/NetSharp/NetSharp/Deprecated/IPacketHandler.cs @@ -1,51 +0,0 @@ -namespace NetSharp.Deprecated -{ - /// <summary> - /// Describes a class capable of registering and deregistering packet handlers, and capable of - /// handling incoming packets according to the currently registered packet handlers. - /// </summary> - public interface IPacketHandler - { - /// <summary> - /// Attempts to deregister the complex packet handler delegate for all packets of the given type. If a handler - /// method doesn't exist for the given packet type, <paramref name="oldHandlerDelegate"/> will be <c>default</c>. - /// </summary> - /// <typeparam name="Req">The type of request packet for which to deregister the handler delegate.</typeparam> - /// <typeparam name="Rep">The type of response packet that is generated by the delegate method.</typeparam> - /// <param name="oldHandlerDelegate">The old handler delegate method that was previously registered.</param> - /// <returns>Whether the packet handler delegate was successfully deregistered.</returns> - public bool TryDeregisterComplexPacketHandler<Req, Rep>(out ComplexPacketHandler<Req, Rep>? oldHandlerDelegate) - where Req : class, IRequestPacket, new() where Rep : class, IResponsePacket<Req>, new(); - - /// <summary> - /// Attempts to deregister the simple packet handler delegate for all packets of the given type. If a handler - /// method doesn't exist for the given packet type, <paramref name="oldHandlerDelegate"/> will be <c>default</c>. - /// </summary> - /// <typeparam name="Req">The type of request packet for which to deregister the handler delegate.</typeparam> - /// <param name="oldHandlerDelegate">The old handler delegate method that was previously registered.</param> - /// <returns>Whether the packet handler delegate was successfully deregistered.</returns> - public bool TryDeregisterSimplePacketHandler<Req>(out SimplePacketHandler<Req>? oldHandlerDelegate) - where Req : class, IRequestPacket, new(); - - /// <summary> - /// Attempts to register a complex packet handler delegate for all packets of the given type. If a handler - /// method already exists for the given packet type, it will be updated and replaced with the given one. - /// </summary> - /// <typeparam name="Req">The type of request packet for which to register the handler delegate.</typeparam> - /// <typeparam name="Rep">The type of response packet that is generated by the delegate method.</typeparam> - /// <param name="handlerDelegate">The delegate method to register as the complex packet handler.</param> - /// <returns>Whether the packet handler delegate was successfully registered.</returns> - public bool TryRegisterComplexPacketHandler<Req, Rep>(ComplexPacketHandler<Req, Rep> handlerDelegate) - where Req : class, IRequestPacket, new() where Rep : class, IResponsePacket<Req>, new(); - - /// <summary> - /// Attempts to register a simple packet handler delegate for all packets of the given type. If a handler - /// method already exists for the given packet type, it will be updated and replaced with the given one. - /// </summary> - /// <typeparam name="Req">The type of request packet for which to register the handler delegate.</typeparam> - /// <param name="handlerDelegate">The delegate method to register as the simple packet handler.</param> - /// <returns>Whether the packet handler delegate was successfully registered.</returns> - public bool TryRegisterSimplePacketHandler<Req>(SimplePacketHandler<Req> handlerDelegate) - where Req : class, IRequestPacket, new(); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/IRequestPacket.cs b/NetSharp/NetSharp/Deprecated/IRequestPacket.cs @@ -1,9 +0,0 @@ -namespace NetSharp.Deprecated -{ - /// <summary> - /// Describes a request packet. - /// </summary> - public interface IRequestPacket : IPacket, INetworkSerialisable - { - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/IResponsePacket.cs b/NetSharp/NetSharp/Deprecated/IResponsePacket.cs @@ -1,14 +0,0 @@ -namespace NetSharp.Deprecated -{ - /// <summary> - /// Describes a response packet to a request packet. - /// </summary> - /// <typeparam name="TReq">The request packet that this type is a response to.</typeparam> - public interface IResponsePacket<out TReq> : IPacket, INetworkSerialisable where TReq : IRequestPacket - { - /// <summary> - /// The request packet that was handled with this response packet. - /// </summary> - TReq RequestPacket { get; } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/IServer.cs b/NetSharp/NetSharp/Deprecated/IServer.cs @@ -1,44 +0,0 @@ -using System; -using System.Net; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Describes a server capable of asynchronously handling multiple <see cref="IClient"/> connections at once. - /// </summary> - public interface IServer - { - /// <summary> - /// Signifies that a connection with a remote endpoint has been made. - /// </summary> - public event Action<EndPoint>? ClientConnected; - - //protected IResponsePacket<IRequestPacket> DeserialiseResponsePacket(in Packet) - /// <summary> - /// Signifies that a connection with a remote endpoint has been lost. - /// </summary> - public event Action<EndPoint>? ClientDisconnected; - - /// <summary> - /// Signifies that the server was started and clients will start being accepted. - /// </summary> - public event Action? ServerStarted; - - /// <summary> - /// Signifies that the server was stopped and clients will stop being accepted. - /// </summary> - public event Action? ServerStopped; - - /// <summary> - /// Starts the server asynchronously and starts accepting client connections. Does not block. - /// </summary> - /// <param name="localEndPoint">The local endpoint to bind to.</param> - public Task RunAsync(EndPoint localEndPoint); - - /// <summary> - /// Shuts down the server. - /// </summary> - public void Shutdown(); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Logger.cs b/NetSharp/NetSharp/Deprecated/Logger.cs @@ -1,194 +0,0 @@ -using System; -using System.IO; -using System.Text; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Specifies the severity level of a log message. - /// </summary> - public enum LogLevel - { - /// <summary> - /// The logged message contains some information. Lowest severity. - /// </summary> - Info, - - /// <summary> - /// The logged message contains a warning. Higher severity. - /// </summary> - Warn, - - /// <summary> - /// The logged message contains details about an error. Higher severity. - /// </summary> - Error, - - /// <summary> - /// The logged message contains details about an exception. Highest severity. - /// </summary> - Exception - } - - /// <summary> - /// A simple logger capable of writing text to a stream. - /// </summary> - public readonly struct Logger : IDisposable - { - /// <summary> - /// The stream to which messages will be logged. - /// </summary> - private readonly Stream loggingStream; - - /// <summary> - /// The minimum severity that log messages need to be logged to the underlying stream. - /// </summary> - private readonly LogLevel minimumSeverity; - - /// <summary> - /// The text writer we will use to log messages to the underlying stream. - /// </summary> - private readonly StreamWriter writer; - - /// <summary> - /// Initialises a new instance of the <see cref="Logger"/> struct. - /// </summary> - /// <param name="outputStream">The stream that the logger instance should log messages to.</param> - /// <param name="minimumLogSeverity">The minimum log level that will be logged to the output stream.</param> - public Logger(Stream outputStream, LogLevel minimumLogSeverity = LogLevel.Info) - { - loggingStream = outputStream; - writer = new StreamWriter(loggingStream, Encoding.Default) { AutoFlush = true }; - - minimumSeverity = minimumLogSeverity; - } - - /// <inheritdoc /> - public void Dispose() - { - loggingStream.Dispose(); - writer.Dispose(); - } - - /// <summary> - /// Logs a message to the underlying stream, along with the given exception and at the given severity. - /// </summary> - /// <param name="message">The message that should be logged.</param> - /// <param name="exception">The exception that occurred (if any).</param> - /// <param name="severity">The severity of the message that is being logged.</param> - public void Log(string message, Exception? exception, LogLevel severity) - { - if (severity < minimumSeverity) return; - - string severityTag = severity switch - { - LogLevel.Info => "Info ", - LogLevel.Warn => "Warn ", - LogLevel.Error => "Error", - LogLevel.Exception => "Excep", - _ => "Info " - }; - - writer.WriteLine($"[{severityTag}] {message} {exception}"); - } - - /// <summary> - /// Logs a message asynchronously to the underlying stream, along with the given exception and at the given severity. - /// </summary> - /// <param name="message">The message that should be logged.</param> - /// <param name="exception">The exception that occurred (if any).</param> - /// <param name="severity">The severity of the message that is being logged.</param> - public async Task LogAsync(string message, Exception? exception, LogLevel severity) - { - if (loggingStream.Equals(Stream.Null)) - { - // ignore log request if the underlying stream is null - return; - } - - if (!exception?.Equals(default) ?? false) - { - severity = LogLevel.Exception; - } - - if (severity >= minimumSeverity) - { - string severityTag = severity switch - { - LogLevel.Info => "Info ", - LogLevel.Warn => "Warn ", - LogLevel.Error => "Error", - LogLevel.Exception => "Excep", - _ => "Info " - }; - - await writer.WriteLineAsync($"[{severityTag}] {message} {exception}"); - } - } - - /// <summary> - /// Logs an error to the underlying stream, with severity <see cref="LogLevel.Info"/>. - /// </summary> - /// <param name="message">The error that should be logged.</param> - public void LogError(string message) => Log(message, null, LogLevel.Error); - - /// <summary> - /// Logs an error to the underlying stream asynchronously, with severity <see cref="LogLevel.Error"/>. - /// </summary> - /// <param name="message">The error that should be logged.</param> - public async Task LogErrorAsync(string message) => await LogAsync(message, null, LogLevel.Error); - - /// <summary> - /// Logs an exception to the underlying stream, with severity <see cref="LogLevel.Exception"/>. - /// </summary> - /// <param name="exception">The exception that should be logged.</param> - public void LogException(Exception exception) => Log("", exception, LogLevel.Exception); - - /// <summary> - /// Logs an exception to the underlying stream, along with a short debug message, with severity - /// <see cref="LogLevel.Exception"/>. - /// </summary> - /// <param name="message">The debug message that should be logged with the exception.</param> - /// <param name="exception">The exception that should be logged.</param> - public void LogException(string message, Exception exception) => Log(message, exception, LogLevel.Exception); - - /// <summary> - /// Logs an exception to the underlying stream asynchronously, with severity <see cref="LogLevel.Exception"/>. - /// </summary> - /// <param name="exception">The exception that should be logged.</param> - public async Task LogExceptionAsync(Exception exception) => await LogAsync("", exception, LogLevel.Exception); - - /// <summary> - /// Logs an exception to the underlying stream asynchronously, along with a short debug message, with severity - /// <see cref="LogLevel.Exception"/>. - /// </summary> - /// <param name="message">The debug message that should be logged with the exception.</param> - /// <param name="exception">The exception that should be logged.</param> - public async Task LogExceptionAsync(string message, Exception exception) => await LogAsync(message, exception, LogLevel.Exception); - - /// <summary> - /// Logs a message to the underlying stream, with severity <see cref="LogLevel.Info"/>. - /// </summary> - /// <param name="message">The message that should be logged.</param> - public void LogMessage(string message) => Log(message, null, LogLevel.Info); - - /// <summary> - /// Logs a message to the underlying stream asynchronously, with severity <see cref="LogLevel.Info"/>. - /// </summary> - /// <param name="message">The message that should be logged.</param> - public async Task LogMessageAsync(string message) => await LogAsync(message, null, LogLevel.Info); - - /// <summary> - /// Logs a warning to the underlying stream, with severity <see cref="LogLevel.Info"/>. - /// </summary> - /// <param name="message">The warning that should be logged.</param> - public void LogWarning(string message) => Log(message, null, LogLevel.Warn); - - /// <summary> - /// Logs a warning to the underlying stream asynchronously, with severity <see cref="LogLevel.Warn"/>. - /// </summary> - /// <param name="message">The warning that should be logged.</param> - public async Task LogWarningAsync(string message) => await LogAsync(message, null, LogLevel.Warn); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/NetworkErrorCode.cs b/NetSharp/NetSharp/Deprecated/NetworkErrorCode.cs @@ -1,18 +0,0 @@ -namespace NetSharp.Deprecated -{ - /// <summary> - /// Enumerates the possible error codes for network operations, being held in the packet. - /// </summary> - public enum NetworkErrorCode : uint - { - /// <summary> - /// Signifies that there was no error during transmission. - /// </summary> - Ok = 0, - - /// <summary> - /// A generic error occurred during packet transmission. - /// </summary> - Error = 1 << 1, - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/NetworkPacket.cs b/NetSharp/NetSharp/Deprecated/NetworkPacket.cs @@ -1,218 +0,0 @@ -using NetSharp.Deprecated.Conversion; - -using System; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Represents a low-level packet that is transmitted over the network. - /// </summary> - public readonly struct NetworkPacket - { - /// <summary> - /// Initialises a new instance of the <see cref="NetworkPacket"/> struct. - /// </summary> - /// <param name="data">The data that should be transmitted in the packet.</param> - /// <param name="header">The header for the packet.</param> - /// <param name="footer">The footer for the packet.</param> - private NetworkPacket(ReadOnlyMemory<byte> data, NetworkPacketHeader header, NetworkPacketFooter footer) - { - Header = header; - - DataBuffer = data; - - Footer = footer; - } - - /// <summary> - /// The number of bytes allocated in each packet for user data. - /// </summary> - public const int DataSegmentSize = PacketSize - HeaderSize - FooterSize; - - /// <summary> - /// The number of bytes taken up in each packet by its footer. - /// </summary> - public const int FooterSize = NetworkPacketFooter.Size; - - /// <summary> - /// The number of bytes taken up in each packet by its header. - /// </summary> - public const int HeaderSize = NetworkPacketHeader.Size; - - /// <summary> - /// The size of each packet, including its header, footer, and data segment. - /// </summary> - public const int PacketSize = 4096; - - /// <summary> - /// The data held in this packet. - /// </summary> - public readonly ReadOnlyMemory<byte> DataBuffer; - - public readonly NetworkPacketFooter Footer; - public readonly NetworkPacketHeader Header; - - /// <summary> - /// Initialises a new instance of the <see cref="NetworkPacket"/> struct. - /// </summary> - /// <param name="data">The data that should be transmitted in the packet.</param> - /// <param name="dataLength">The number of bytes that are held in the given data buffer.</param> - /// <param name="type">The packet type.</param> - /// <param name="errorCode">The error code associated with this transmission.</param> - /// <param name="hasSucceedingPacket">Whether this packet has a succeeding packet in the packet chain.</param> - public NetworkPacket(ReadOnlyMemory<byte> data, int dataLength, uint type, NetworkErrorCode errorCode, bool hasSucceedingPacket) - { - Header = new NetworkPacketHeader(type, errorCode, dataLength); - - DataBuffer = data; - - Footer = new NetworkPacketFooter(hasSucceedingPacket); - } - - /// <summary> - /// Deserialises the given buffer into a packet instance. - /// </summary> - /// <param name="buffer">The byte buffer to serialise.</param> - /// <returns>The deserialised packet instance.</returns> - public static NetworkPacket Deserialise(Memory<byte> buffer) - { - Span<byte> serialisedPacketHeader = buffer.Slice(0, HeaderSize).Span; - NetworkPacketHeader header = NetworkPacketHeader.Deserialise(serialisedPacketHeader); - - Span<byte> serialisedPacketFooter = buffer.Slice(HeaderSize + DataSegmentSize, FooterSize).Span; - NetworkPacketFooter footer = NetworkPacketFooter.Deserialise(serialisedPacketFooter); - - Memory<byte> serialisedInstanceData = buffer.Slice(HeaderSize, DataSegmentSize); - - return new NetworkPacket(serialisedInstanceData, header, footer); - } - - /// <summary> - /// Serialises the given packet instance to a new byte buffer. - /// </summary> - /// <param name="instance">The packet instance to serialise.</param> - /// <returns>The byte buffer that represents the packet instance.</returns> - public static Memory<byte> Serialise(NetworkPacket instance) - { - byte[] buffer = new byte[PacketSize]; - SerialiseToBuffer(buffer, instance); - return buffer; - } - - /// <summary> - /// Serialises the given packet instance into the given byte buffer. - /// </summary> - /// <param name="buffer"> - /// The buffer to which the instance should be serialised. Must be at least of size <see cref="PacketSize"/>. - /// </param> - /// <param name="instance">The packet instance to serialise.</param> - /// <exception cref="ArgumentException">Thrown if the given buffer is too small.</exception> - public static void SerialiseToBuffer(Memory<byte> buffer, NetworkPacket instance) - { - if (buffer.Length < PacketSize) - { - throw new ArgumentException("Given buffer is too small to serialise the packet instance into.", nameof(buffer)); - } - - Span<byte> serialisedPacketHeader = buffer.Slice(0, HeaderSize).Span; - NetworkPacketHeader.Serialise(serialisedPacketHeader, instance.Header); - - Span<byte> serialisedPacketFooter = buffer.Slice(HeaderSize + DataSegmentSize, FooterSize).Span; - NetworkPacketFooter.Serialise(serialisedPacketFooter, instance.Footer); - - Memory<byte> serialisedInstanceData = buffer.Slice(HeaderSize, DataSegmentSize); - instance.DataBuffer.CopyTo(serialisedInstanceData); - } - } - - // TODO: Document - public readonly struct NetworkPacketFooter - { - private const int PacketHasNextStart = 0; - - /// <summary> - /// The number of bytes taken up by a packet footer. - /// </summary> - public const int Size = sizeof(bool); - - public readonly bool HasSucceedingPacket; - - public NetworkPacketFooter(bool hasSucceedingPacket) - { - HasSucceedingPacket = hasSucceedingPacket; - } - - public static NetworkPacketFooter Deserialise(Span<byte> buffer) - { - Span<byte> serialisedHasNextFlag = buffer.Slice(PacketHasNextStart, sizeof(bool)); - - return new NetworkPacketFooter( - EndianAwareBitConverter.ToBoolean(serialisedHasNextFlag)); - } - - public static void Serialise(Span<byte> buffer, NetworkPacketFooter instance) - { - Span<byte> serialisedHasNextFlag = buffer.Slice(PacketHasNextStart, sizeof(bool)); - - EndianAwareBitConverter.GetBytes(instance.HasSucceedingPacket).CopyTo(serialisedHasNextFlag); - } - } - - // TODO: Document - public readonly struct NetworkPacketHeader - { - private const int PacketDataLengthStart = 2 * sizeof(uint); - private const int PacketErrorCodeStart = sizeof(uint); - private const int PacketTypeStart = 0; - - /// <summary> - /// The number of bytes taken up by a packet header. - /// </summary> - public const int Size = sizeof(uint) + sizeof(uint) + sizeof(int); - - /// <summary> - /// The number of bytes of data held in the packet. - /// </summary> - public readonly int DataLength; - - /// <summary> - /// The error code for this packet. - /// </summary> - public readonly NetworkErrorCode ErrorCode; - - /// <summary> - /// The packet type. - /// </summary> - public readonly uint Type; - - public NetworkPacketHeader(uint packetType, NetworkErrorCode packetErrorCode, int packetDataLength) - { - Type = packetType; - ErrorCode = packetErrorCode; - DataLength = packetDataLength; - } - - public static NetworkPacketHeader Deserialise(Span<byte> buffer) - { - Span<byte> serialisedType = buffer.Slice(PacketTypeStart, sizeof(uint)); - Span<byte> serialisedErrorCode = buffer.Slice(PacketErrorCodeStart, sizeof(uint)); - Span<byte> serialisedDataLength = buffer.Slice(PacketDataLengthStart, sizeof(int)); - - return new NetworkPacketHeader( - EndianAwareBitConverter.ToUInt32(serialisedType), - (NetworkErrorCode)EndianAwareBitConverter.ToUInt32(serialisedErrorCode), - EndianAwareBitConverter.ToInt32(serialisedDataLength)); - } - - public static void Serialise(Span<byte> buffer, NetworkPacketHeader instance) - { - Span<byte> serialisedType = buffer.Slice(PacketTypeStart, sizeof(uint)); - Span<byte> serialisedErrorCode = buffer.Slice(PacketErrorCodeStart, sizeof(uint)); - Span<byte> serialisedDataLength = buffer.Slice(PacketDataLengthStart, sizeof(int)); - - EndianAwareBitConverter.GetBytes(instance.Type).CopyTo(serialisedType); - EndianAwareBitConverter.GetBytes((uint)instance.ErrorCode).CopyTo(serialisedErrorCode); - EndianAwareBitConverter.GetBytes(instance.DataLength).CopyTo(serialisedDataLength); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/PacketPipeline.cs b/NetSharp/NetSharp/Deprecated/PacketPipeline.cs @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Represents a pipeline of transformations that packets must undergo. - /// </summary> - /// <typeparam name="TInput">The type of packet the pipeline receives.</typeparam> - /// <typeparam name="TIntermediate">The type of packet the pipeline internally handles.</typeparam> - /// <typeparam name="TOutput">The type of packet the pipeline outputs.</typeparam> - // TODO: Implement a packet pipeline, with multiple transform stages to allow encryption, compression, and various other bytewise manipulation stages. - internal readonly struct PacketPipeline<TInput, TIntermediate, TOutput> - { - private readonly PacketPipelineStage<TInput, TIntermediate> pipelineInputStage; - private readonly IReadOnlyCollection<PacketPipelineStage<TIntermediate, TIntermediate>> pipelineIntermediateStages; - private readonly PacketPipelineStage<TIntermediate, TOutput> pipelineOutputStage; - - internal PacketPipeline( - PacketPipelineStage<TInput, TIntermediate> firstStage, - PacketPipelineStage<TIntermediate, TOutput> lastStage, - IReadOnlyCollection<PacketPipelineStage<TIntermediate, TIntermediate>> intermediateStages) - { - pipelineInputStage = firstStage; - pipelineOutputStage = lastStage; - - pipelineIntermediateStages = intermediateStages; - } - - /// <summary> - /// Passes the given packet through the pipeline. - /// </summary> - /// <param name="inputPacket">The incoming packet.</param> - /// <returns>The outgoing transformed packet.</returns> - internal TOutput ProcessPacket(TInput inputPacket) - { - TIntermediate intermediatePacket = pipelineInputStage.Process(inputPacket); - - intermediatePacket = pipelineIntermediateStages.Aggregate(intermediatePacket, (current, stage) => stage.Process(current)); - - return pipelineOutputStage.Process(intermediatePacket); - } - } - - /// <summary> - /// Represents a single transformation applied to a packet traveling through the pipeline. - /// </summary> - /// <typeparam name="TInput">The type the transformation takes as input.</typeparam> - /// <typeparam name="TOutput">The type the transformation produces as output.</typeparam> - internal readonly struct PacketPipelineStage<TInput, TOutput> - { - private readonly Func<TInput, TOutput> stageDelegate; - - internal PacketPipelineStage(in Func<TInput, TOutput> stageProcessingDelegate) - { - stageDelegate = stageProcessingDelegate; - } - - internal TOutput Process(TInput input) - { - return stageDelegate(input); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/PacketPipelineBuilder.cs b/NetSharp/NetSharp/Deprecated/PacketPipelineBuilder.cs @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Allows for configuring and subsequently building a <see cref="PacketPipeline{TInput,TIntermediate,TOutput}"/> instance. - /// </summary> - /// <typeparam name="TInput">The type of packet that will be submitted to the pipeline.</typeparam> - /// <typeparam name="TIntermediate">The type of packet that will be handled internally by the pipeline.</typeparam> - /// <typeparam name="TOutput">The type of packet that will be requested from the pipeline.</typeparam> - internal sealed class PacketPipelineBuilder<TInput, TIntermediate, TOutput> - { - private readonly List<PacketPipelineStage<TIntermediate, TIntermediate>> intermediateStages; - - private PacketPipelineStage<TInput, TIntermediate>? inputStage; - private PacketPipelineStage<TIntermediate, TOutput>? outputStage; - - internal PacketPipelineBuilder() - { - intermediateStages = new List<PacketPipelineStage<TIntermediate, TIntermediate>>(); - } - - /// <summary> - /// Returns the currently configured <see cref="PacketPipeline{TInput,TIntermediate,TOutput}"/> instance. - /// </summary> - /// <returns>The configured <see cref="PacketPipeline{TInput,TIntermediate,TOutput}"/> instance.</returns> - /// <exception cref="ArgumentNullException"> - /// Thrown when either <see cref="WithInputStage"/> or <see cref="WithOutputStage"/> have not been called. - /// </exception> - internal PacketPipeline<TInput, TIntermediate, TOutput> Build() - { - if (inputStage == null) - { - throw new ArgumentNullException(nameof(inputStage), $"{nameof(WithInputStage)} has not been called."); - } - - if (outputStage == null) - { - throw new ArgumentNullException(nameof(outputStage), $"{nameof(WithOutputStage)} has not been called."); - } - - return new PacketPipeline<TInput, TIntermediate, TOutput>(inputStage.Value, outputStage.Value, intermediateStages); - } - - /// <summary> - /// Configures the input stage for the pipeline. - /// </summary> - /// <param name="stage"> - /// The transformation that should be applied to incoming packets, to convert them from the <typeparamref name="TInput"/> - /// type to the <typeparamref name="TIntermediate"/> type that the pipeline handles internally. - /// </param> - /// <returns>The builder instance for further configuration.</returns> - internal PacketPipelineBuilder<TInput, TIntermediate, TOutput> WithInputStage(in Func<TInput, TIntermediate> stage) - { - inputStage = new PacketPipelineStage<TInput, TIntermediate>(in stage); - return this; - } - - /// <summary> - /// Adds the given intermediate stage to the pipeline. - /// </summary> - /// <param name="stage"> - /// The transformation that should be applied to packets traveling through the pipeline. - /// </param> - /// <returns>The builder instance for further configuration.</returns> - internal PacketPipelineBuilder<TInput, TIntermediate, TOutput> WithIntermediateStage(in Func<TIntermediate, TIntermediate> stage) - { - intermediateStages.Add(new PacketPipelineStage<TIntermediate, TIntermediate>(in stage)); - return this; - } - - /// <summary> - /// Configures the output stage for the pipeline. - /// </summary> - /// <param name="stage"> - /// The transformation that should be applied to outgoing packets, to convert them from the - /// <typeparamref name="TIntermediate"/> type used internally to the <typeparamref name="TOutput"/> type. - /// </param> - /// <returns>The builder instance for further configuration.</returns> - internal PacketPipelineBuilder<TInput, TIntermediate, TOutput> WithOutputStage(in Func<TIntermediate, TOutput> stage) - { - outputStage = new PacketPipelineStage<TIntermediate, TOutput>(in stage); - return this; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/PacketRegistry.cs b/NetSharp/NetSharp/Deprecated/PacketRegistry.cs @@ -1,285 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides method of registering request packets and their relevant response packets, as well as mapping their ids. - /// </summary> - internal static class PacketRegistry - { - /// <summary> - /// The start id for automatically generated packet type ids. Any custom packet type ids lower than this value - /// that come from external assemblies will be incremented by this value, to ensure that there are no clashes. - /// </summary> - private const uint AutomaticPacketTypeIdStartPoint = 100; - - /// <summary> - /// The lock object for synchronising access to the <see cref="currentAutomaticPacketTypeIdCounter"/> field. - /// </summary> - private static readonly object currentAutomaticPacketTypeIdCounterLockObject = new object(); - - /// <summary> - /// Maps a packet type id to its relevant packet type, and vice-versa. - /// </summary> - private static readonly BiDictionary<uint, Type> idToPacketTypeMap; - - /// <summary> - /// The assembly that represents the library, where all of the builtin packets are defined. - /// </summary> - private static readonly Assembly LibraryAssembly = Assembly.GetAssembly(typeof(PacketRegistry)); - - /// <summary> - /// Maps a request packet to its relevant response packet, and vice-versa. - /// </summary> - private static readonly BiDictionary<Type, Type> requestToResponseMap; - - /// <summary> - /// The current id for registered packets. - /// </summary> - private static uint currentAutomaticPacketTypeIdCounter = AutomaticPacketTypeIdStartPoint; - - /// <summary> - /// Fetches the packet type id of the given packet type. If the packet type is declared outside of the library - /// assembly, then its value is incremented by the <see cref="AutomaticPacketTypeIdStartPoint"/> value. This ensure that - /// there are no clashes between the packet type ids of packets declared in the library and external packets. - /// </summary> - /// <param name="packetType">The packet type whose id should be fetched.</param> - /// <returns>The id of the given packet type.</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint GetNewPacketTypeId(Type packetType) - { - uint packetTypeId; - - if (packetType.Assembly != LibraryAssembly) - { - lock (currentAutomaticPacketTypeIdCounterLockObject) - { - packetTypeId = currentAutomaticPacketTypeIdCounter++; - } - } - else - { - PacketTypeIdAttribute customPacketTypeIdAttribute = - (PacketTypeIdAttribute)packetType.GetCustomAttributes(typeof(PacketTypeIdAttribute)).First(); - - packetTypeId = customPacketTypeIdAttribute.Id; - } - - return packetTypeId; - } - - /// <summary> - /// Deregisters the given packet type from the registry. - /// </summary> - /// <param name="requestPacketType">The request packet type to deregister, if it is registered.</param> - /// <param name="responsePacketType">The response packet associated with the request packet.</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void DeregisterPacketType(Type requestPacketType, Type? responsePacketType) - { - if (idToPacketTypeMap.ContainsValue(requestPacketType)) - { - idToPacketTypeMap.TryClearKey(requestPacketType, out _); - } - - // if the given response packet is null, then skip deregistering a response packet type - if (responsePacketType == default) return; - - if (!idToPacketTypeMap.ContainsValue(responsePacketType)) - { - idToPacketTypeMap.TryClearKey(responsePacketType, out _); - } - - if (!requestToResponseMap.ContainsValue(requestPacketType)) - { - requestToResponseMap.TryClearKey(requestPacketType, out _); - } - } - - /// <summary> - /// Deregisters the given packet types from the registry. - /// </summary> - /// <param name="requestToResponsePacketTypeMap">The list of packet types to deregister, if they are registered.</param> - internal static void DeregisterPacketTypes(Dictionary<Type, Type?> requestToResponsePacketTypeMap) - { - foreach ((Type requestPacketType, Type? responsePacketType) in requestToResponsePacketTypeMap) - { - DeregisterPacketType(requestPacketType, responsePacketType); - } - } - - /// <summary> - /// Returns the packet type id associated with the given packet type. - /// </summary> - /// <param name="packetType">The packet type whose id to fetch.</param> - /// <returns>The id of the packet type given.</returns> - internal static uint GetPacketId(Type packetType) => idToPacketTypeMap[packetType]; - - /// <summary> - /// Returns the packet type id associated with the given packet type. - /// </summary> - /// <typeparam name="TPacket">The packet type whose id to fetch.</typeparam> - /// <returns>The id of the packet type given.</returns> - internal static uint GetPacketId<TPacket>() where TPacket : IPacket => idToPacketTypeMap[typeof(TPacket)]; - - /// <summary> - /// Returns the packet type associated with the given id. - /// </summary> - /// <param name="packetTypeId">The packet id whose mapped type to fetch.</param> - /// <returns>The packet type mapped by the given id.</returns> - internal static Type GetPacketType(uint packetTypeId) => idToPacketTypeMap[packetTypeId]; - - /// <summary> - /// Returns the type of request packet mapped by the given response packet type. - /// </summary> - /// <typeparam name="TResponse">The response packet type whose request packet type to fetch.</typeparam> - /// <returns>The request packet type, <c>null</c> if no type is mapped.</returns> - internal static Type GetRequestPacketType<TResponse>() where TResponse : IResponsePacket<IRequestPacket> - { - requestToResponseMap.TryGetKey(typeof(TResponse), out Type requestPacketType); - - return requestPacketType; - } - - /// <summary> - /// Returns the type of request packet mapped by the given response packet type. - /// </summary> - /// <param name="responsePacketType">The response packet type whose request packet type to fetch.</param> - /// <returns>The request packet type, <c>null</c> if no type is mapped.</returns> - internal static Type GetRequestPacketType(Type responsePacketType) - { - requestToResponseMap.TryGetKey(responsePacketType, out Type requestPacketType); - - return requestPacketType; - } - - /// <summary> - /// Returns the type of response packet mapped by the given request packet type. - /// </summary> - /// <typeparam name="TRequest">The request packet type whose response packet type to fetch.</typeparam> - /// <returns>The response packet type, <c>null</c> if no type is mapped.</returns> - internal static Type? GetResponsePacketType<TRequest>() where TRequest : IRequestPacket - { - return requestToResponseMap.TryGetValue(typeof(TRequest), out Type responsePacketType) ? responsePacketType : default; - } - - /// <summary> - /// Returns the type of response packet mapped by the given request packet type. - /// </summary> - /// <param name="requestPacketType">The request packet type whose response packet type to fetch.</param> - /// <returns>The response packet type, <c>null</c> if no type is mapped.</returns> - internal static Type? GetResponsePacketType(Type requestPacketType) - { - return requestToResponseMap.TryGetValue(requestPacketType, out Type responsePacketType) ? responsePacketType : default; - } - - /// <summary> - /// Rebuilds the packet registry, by registering every <see cref="IPacket"/> inheritor in the given assemblies. - /// </summary> - /// <param name="packetSourceAssemblies"> - /// The assemblies from which the packet types to register are sourced. - /// </param> - internal static void RegisterPacketSourceAssemblies(params Assembly[] packetSourceAssemblies) - { - foreach (Assembly assembly in packetSourceAssemblies) - { - RegisterPacketSourceAssembly(assembly); - } - } - - /// <summary> - /// Registers all the <see cref="IPacket"/> implementors in the given assembly. - /// </summary> - /// <param name="packetSourceAssembly">The assembly whose packet types to register.</param> - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void RegisterPacketSourceAssembly(Assembly packetSourceAssembly) - { - Dictionary<Type, Type?> requestToResponseTypeMap = new Dictionary<Type, Type?>(); - - foreach (Type type in packetSourceAssembly.DefinedTypes) - { - foreach (Type interfaceType in type.GetInterfaces()) - { - if (!typeof(IPacket).IsAssignableFrom(interfaceType) || interfaceType == typeof(IPacket)) - { - continue; - } - - if (interfaceType == typeof(IRequestPacket)) - { - requestToResponseTypeMap[type] = default; - } - else //if (interfaceType == typeof(IResponsePacket<>)) - { - Type handledRequestType = interfaceType.GetGenericArguments()[0]; - - requestToResponseTypeMap[handledRequestType] = type; - } - } - } - - RegisterPacketTypes(requestToResponseTypeMap); - } - - /// <summary> - /// Registers the given packet type to the registry. - /// </summary> - /// <param name="requestPacketType">The request packet type to register, if it is not registered.</param> - /// <param name="responsePacketType">The response packet associated with the request packet.</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void RegisterPacketType(Type requestPacketType, Type? responsePacketType) - { - if (!idToPacketTypeMap.ContainsValue(requestPacketType)) - { - uint requestPacketTypeId = GetNewPacketTypeId(requestPacketType); - - idToPacketTypeMap.TrySetValue(requestPacketTypeId, requestPacketType); - } - - // if the given response packet is null, then skip registering a response packet type - if (responsePacketType == default) return; - - if (!idToPacketTypeMap.ContainsValue(responsePacketType)) - { - uint responsePacketTypeId = GetNewPacketTypeId(responsePacketType); - - idToPacketTypeMap.TrySetValue(responsePacketTypeId, responsePacketType); - } - - if (!requestToResponseMap.ContainsValue(requestPacketType)) - { - requestToResponseMap.TrySetValue(requestPacketType, responsePacketType); - } - } - - /// <summary> - /// Registers the given packet types to the registry. - /// </summary> - /// <param name="requestToResponsePacketTypeMap"> - /// The dictionary mapping the request packet types to register, to their relevant response packet types. - /// The response packet type can be null; then the request packet type is treated as a 'simple' packet. - /// </param> - internal static void RegisterPacketTypes(Dictionary<Type, Type?> requestToResponsePacketTypeMap) - { - foreach ((Type requestPacketType, Type? responsePacketType) in requestToResponsePacketTypeMap) - { - RegisterPacketType(requestPacketType, responsePacketType); - } - } - - /// <summary> - /// Initialises a new instance of the <see cref="PacketRegistry"/> class. - /// </summary> - static PacketRegistry() - { - idToPacketTypeMap = new BiDictionary<uint, Type>(); - - requestToResponseMap = new BiDictionary<Type, Type>(); - - RegisterPacketSourceAssembly(LibraryAssembly); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/PacketTypeIdAttribute.cs b/NetSharp/NetSharp/Deprecated/PacketTypeIdAttribute.cs @@ -1,26 +0,0 @@ -using System; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Allows the placing of a custom packet type on a class or struct. This is used if the class or struct - /// inherits from <see cref="IRequestPacket"/> or <see cref="IResponsePacket{TReq}"/>. - /// </summary> - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] - internal sealed class PacketTypeIdAttribute : Attribute - { - /// <summary> - /// Initialises a new instance of the <see cref="PacketTypeIdAttribute"/> attribute. - /// </summary> - /// <param name="type">The custom type id that the decorated packet type should have.</param> - internal PacketTypeIdAttribute(uint type) - { - Id = type; - } - - /// <summary> - /// The custom type id that the decorated packet type should have. This overrides the automatically generated id. - /// </summary> - internal uint Id { get; } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/RemoteSocketClient.cs b/NetSharp/NetSharp/Deprecated/RemoteSocketClient.cs @@ -1,73 +0,0 @@ -using Microsoft.Extensions.ObjectPool; - -using NetSharp.Utils; - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - public class RemoteSocketClient : IDisposable - { - private readonly ObjectPool<SocketAsyncEventArgs> transmissionArgsPool; - - protected readonly Socket transmitterSocket; - - internal RemoteSocketClient(Socket clientSocket) - { - transmitterSocket = clientSocket; - - transmissionArgsPool = new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>()); - } - - /// <inheritdoc /> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <summary> - /// Implementation of dispose pattern. - /// </summary> - /// <param name="disposing"> - /// Whether this method is being called by the object finalizer, or by the <see cref="Dispose()"/> method. - /// </param> - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - transmitterSocket.Dispose(); - } - } - - public async ValueTask<TransmissionResult> ReceiveAsync(EndPoint remoteEndPoint, SocketFlags receiveFlags, Memory<byte> receiveBuffer, - CancellationToken cancellationToken = default) - { - SocketAsyncEventArgs transmissionArgs = transmissionArgsPool.Get(); - - TransmissionResult receiveResult = await SocketOperations.ReceiveFromAsync(transmissionArgs, transmitterSocket, - remoteEndPoint, receiveFlags, receiveBuffer, cancellationToken); - - transmissionArgsPool.Return(transmissionArgs); - - return receiveResult; - } - - public async ValueTask<TransmissionResult> SendAsync(EndPoint remoteEndPoint, SocketFlags sendFlags, Memory<byte> sendBuffer, - CancellationToken cancellationToken = default) - { - SocketAsyncEventArgs transmissionArgs = transmissionArgsPool.Get(); - - TransmissionResult sendResult = await SocketOperations.SendToAsync(transmissionArgs, transmitterSocket, - remoteEndPoint, sendFlags, sendBuffer, cancellationToken); - - transmissionArgsPool.Return(transmissionArgs); - - return sendResult; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/RingBuffer.cs b/NetSharp/NetSharp/Deprecated/RingBuffer.cs @@ -1,48 +0,0 @@ -namespace NetSharp.Deprecated -{ - public class RingBuffer<T> - { - private readonly T[] buffer; - - private int currentIndex; - - public RingBuffer(int capacity) - { - buffer = new T[capacity]; - - Capacity = capacity; - Count = 0; - } - - public int Capacity { get; } - - public int Count { get; } - - public T Pop() - { - T removedItem = buffer[currentIndex--]; - - currentIndex = currentIndex < 0 ? currentIndex + Capacity : currentIndex; - - return removedItem; - } - - public bool Push(T newItem, out T removedItem) - { - bool overwroteItem = false; - removedItem = default; - - if (buffer[currentIndex] != null) - { - removedItem = buffer[currentIndex]; - overwroteItem = true; - } - - buffer[currentIndex] = newItem; - - currentIndex = (currentIndex + 1) % Capacity; - - return overwroteItem; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SerialisedPacket.cs b/NetSharp/NetSharp/Deprecated/SerialisedPacket.cs @@ -1,47 +0,0 @@ -using System; - -namespace NetSharp.Deprecated -{ - public readonly struct SerialisedPacket - { - public static readonly SerialisedPacket Null = new SerialisedPacket(Memory<byte>.Empty, 0); - public readonly Memory<byte> Contents; - public readonly uint Type; - - public SerialisedPacket(Memory<byte> contents, uint type) - { - Contents = contents; - - Type = type; - } - - /// <summary> - /// Serialises the given serialisable packet instance and returns the <see cref="SerialisedPacket"/> instance - /// that was generated. This method invokes <see cref="IPacket.BeforeSerialisation"/>. - /// </summary> - /// <typeparam name="T">The packet type that will be serialised.</typeparam> - /// <param name="serialisable">The packet instance that should be serialised.</param> - /// <returns>The serialised instance.</returns> - public static SerialisedPacket From<T>(T serialisable) where T : class, IPacket, INetworkSerialisable - { - serialisable.BeforeSerialisation(); - return new SerialisedPacket(serialisable.Serialise(), PacketRegistry.GetPacketId<T>()); - } - - /// <summary> - /// Deserialises and returns a packet instance of the given type from the <see cref="SerialisedPacket"/> instance - /// that was given. This method invokes <see cref="IPacket.AfterDeserialisation"/>. - /// </summary> - /// <typeparam name="T">The packet type to which the packet should be deserialised.</typeparam> - /// <param name="instance">The serialised packet instance that should be deserialised.</param> - /// <returns>The deserialised instance.</returns> - public static T To<T>(in SerialisedPacket instance) where T : class, IPacket, INetworkSerialisable, new() - { - T packet = new T(); - packet.Deserialise(instance.Contents); - packet.AfterDeserialisation(); - - return packet; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/Server.cs b/NetSharp/NetSharp/Deprecated/Server.cs @@ -1,593 +0,0 @@ -using NetSharp.Deprecated.Builtin; - -using System; -using System.Collections.Concurrent; -using System.Net; -using System.Net.Sockets; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Represents a method that receives a request packet of the given type (<typeparamref name="TReq"/>) and - /// handles the request, returning a response packet of the given type (<typeparamref name="TRep"/>). - /// </summary> - /// <typeparam name="TReq">The type of request packet handled by this delegate method.</typeparam> - /// <typeparam name="TRep">The type of response packet returned by this delegate method.</typeparam> - /// <param name="requestPacket">The request packet that should be handled by this delegate method.</param> - /// <param name="remoteEndPoint">The remote endpoint from which the request originated.</param> - /// <returns>The response packet to send back to the remote endpoint from which the request originated.</returns> - public delegate TRep ComplexPacketHandler<in TReq, out TRep>(TReq requestPacket, EndPoint remoteEndPoint) - where TReq : class, IRequestPacket, new() where TRep : class, IResponsePacket<TReq>, new(); - - /// <summary> - /// Represents a method that receives a simple request packet of the given type (<typeparamref name="TReq"/>) and - /// handles the request, not returning any response packets. - /// </summary> - /// <typeparam name="TReq">The type of request packet handled by this delegate method.</typeparam> - /// <param name="requestPacket">The request packet that should be handled by this delegate method.</param> - /// <param name="remoteEndPoint">The remote endpoint from which the request originated.</param> - public delegate void SimplePacketHandler<in TReq>(TReq requestPacket, EndPoint remoteEndPoint) - where TReq : class, IRequestPacket, new(); - - /// <summary> - /// Provides methods for handling connected <see cref="IClient"/> instances. - /// </summary> - public abstract class Server : ServerClientConnection, IServer, IPacketHandler, IDisposable - { - /// <summary> - /// Maps a packet type id to the complex packet handler for that packet type. - /// </summary> - private readonly ConcurrentDictionary<uint, Func<IRequestPacket, EndPoint, IResponsePacket<IRequestPacket>>> - complexPacketHandlers; - - /// <summary> - /// Maps a packet type id to the raw packet deserialiser that deserialises raw packets to - /// <see cref="IRequestPacket"/> implementors. - /// </summary> - private readonly ConcurrentDictionary<uint, RawRequestPacketDeserialiser> requestPacketDeserialisers; - - /// <summary> - /// Cancellation token source to stop handling client sockets when the server should be shut down. - /// </summary> - private readonly CancellationTokenSource serverShutdownCancellationTokenSource; - - /// <summary> - /// Maps a packet type id to the simple packet handler for that packet type. - /// </summary> - private readonly ConcurrentDictionary<uint, Action<IRequestPacket, EndPoint>> simplePacketHandlers; - - /// <summary> - /// Initialises a new instance of the <see cref="Server"/> class. - /// </summary> - private Server() - { - serverShutdownCancellationTokenSource = new CancellationTokenSource(); - - serverShutdownCancellationToken = serverShutdownCancellationTokenSource.Token; - - requestPacketDeserialisers = new ConcurrentDictionary<uint, RawRequestPacketDeserialiser>(); - - simplePacketHandlers = new ConcurrentDictionary<uint, Action<IRequestPacket, EndPoint>>(); - complexPacketHandlers = - new ConcurrentDictionary<uint, Func<IRequestPacket, EndPoint, IResponsePacket<IRequestPacket>>>(); - - RegisterInternalPacketHandlers(); - - socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - socketOptions = new DefaultSocketOptions(ref socket); - } - - /// <summary> - /// Destroys an instance of the <see cref="Server"/> class. - /// </summary> - ~Server() - { - Dispose(false); - } - - /// <summary> - /// Represents a method that receives a raw packet, and deserialises it into an <see cref="IRequestPacket"/> implementor. - /// </summary> - /// <param name="rawPacket">The raw packet that was received from the network.</param> - /// <returns>The deserialised instance of the packet.</returns> - private delegate IRequestPacket RawRequestPacketDeserialiser(in SerialisedPacket rawPacket); - - /// <summary> - /// Registers packet handlers for every internal library packet. - /// </summary> - private void RegisterInternalPacketHandlers() - { - TryRegisterSimplePacketHandler((DisconnectPacket packet, EndPoint remoteEndPoint) => - { -#if DEBUG - logger.LogMessage($"Received disconnect packet from {remoteEndPoint}"); -#endif - OnClientDisconnected(remoteEndPoint); - }); - - TryRegisterSimplePacketHandler((SimpleDataPacket packet, EndPoint remoteEndPoint) => - { -#if DEBUG - logger.LogMessage($"Received {packet.RequestBuffer.Length} bytes from {remoteEndPoint}"); -#endif - }); - - TryRegisterComplexPacketHandler((ConnectPacket packet, EndPoint remoteEndPoint) => - { - OnClientConnected(remoteEndPoint); -#if DEBUG - logger.LogMessage($"Received connection request from {remoteEndPoint}"); -#endif - return new ConnectResponsePacket { RequestPacket = packet }; - }); - - TryRegisterComplexPacketHandler((PingPacket packet, EndPoint remoteEndPoint) => - new PingResponsePacket { RequestPacket = packet }); - - TryRegisterComplexPacketHandler((DataPacket packet, EndPoint remoteEndPoint) => - { -#if DEBUG - logger.LogMessage($"Received {packet.RequestBuffer.Length} bytes from {remoteEndPoint}"); - logger.LogMessage($"Sending {packet.RequestBuffer.Length} bytes to {remoteEndPoint}"); -#endif - return new DataResponsePacket { RequestPacket = packet, ResponseBuffer = packet.RequestBuffer }; - }); - } - - /// <summary> - /// The maximum number of connections that are allowed in the connection backlog. - /// </summary> - protected const int PendingConnectionBacklog = 100; - - /// <summary> - /// The default timeout value for all network operations. - /// </summary> - protected static readonly TimeSpan DefaultNetworkOperationTimeout = TimeSpan.FromMilliseconds(10_000); - - /// <summary> - /// The cancellation token that will be set when the server must be shut down. - /// </summary> - protected readonly CancellationToken serverShutdownCancellationToken; - - /// <summary> - /// The <see cref="Socket"/> underlying the connection. - /// </summary> - protected readonly Socket socket; - - /// <summary> - /// Backing field for the <see cref="SocketOptions"/> property. - /// </summary> - protected readonly SocketOptions socketOptions; - - /// <summary> - /// Whether the server should be ran. - /// </summary> - protected volatile bool runServer; - - /// <summary> - /// Initialises a new instance of the <see cref="Server"/> class. - /// </summary> - /// <param name="socketType">The socket type for the underlying socket.</param> - /// <param name="protocolType">The protocol type for the underlying socket.</param> - /// <param name="socketManager">The <see cref="Utils.Socket_Options.SocketOptions"/> implementation to use.</param> - protected Server(SocketType socketType, ProtocolType protocolType) - : this(socketType, protocolType, DefaultNetworkOperationTimeout) - { - } - - /// <summary> - /// Initialises a new instance of the <see cref="Server"/> class. - /// </summary> - /// <param name="socketType">The socket type for the underlying socket.</param> - /// <param name="protocolType">The protocol type for the underlying socket.</param> - /// <param name="socketManager">The <see cref="Utils.Socket_Options.SocketOptions"/> manager to use.</param> - /// <param name="networkOperationTimeout">The timeout value for send and receive operations over the network.</param> - protected Server(SocketType socketType, ProtocolType protocolType, TimeSpan networkOperationTimeout) : this() - { - socket = new Socket(AddressFamily.InterNetwork, socketType, protocolType); - - socketOptions = new DefaultSocketOptions(ref socket); - - NetworkOperationTimeout = networkOperationTimeout; - } - - /// <summary> - /// Deserialises the given <see cref="NetworkPacket"/> struct into an <see cref="IRequestPacket"/> implementor. - /// </summary> - /// <param name="packetType">The type id of packet that we should deserialise to.</param> - /// <param name="rawRequestPacket">The packet that should be deserialised.</param> - /// <returns>The deserialised packet instance, cast to the <see cref="IRequestPacket"/> interface.</returns> - protected IRequestPacket? DeserialiseRequestPacket(uint packetType, in SerialisedPacket rawRequestPacket) - { - if (requestPacketDeserialisers.TryGetValue(packetType, out RawRequestPacketDeserialiser deserialiser)) - { - return deserialiser.Invoke(rawRequestPacket); - } -#if DEBUG - logger.LogWarning($"No packet deserialiser was registered for packet of type {packetType}"); -#endif - return default; - } - - /// <summary> - /// Disposes of this <see cref="Server"/> instance. - /// </summary> - /// <param name="disposing">Whether this instance is being disposed.</param> - protected override void Dispose(bool disposing) - { - if (disposing) - { - serverShutdownCancellationTokenSource?.Cancel(); - serverShutdownCancellationTokenSource?.Dispose(); - - socket.Dispose(); - } - - base.Dispose(disposing); - } - - /// <summary> - /// Provides a task that represents the handling of a client. Calls the abstract <see cref="HandleClientAsync"/> method. - /// </summary> - /// <param name="clientHandlerArgsObj">The object representing the passed <see cref="ClientHandlerArgs"/> instance.</param> - protected async Task DoHandleClientAsync(object clientHandlerArgsObj) - { - ClientHandlerArgs clientHandlerArgs = (ClientHandlerArgs)clientHandlerArgsObj; - - try - { - await HandleClientAsync(clientHandlerArgs, serverShutdownCancellationTokenSource.Token); - } - catch (TaskCanceledException) - { - logger.LogWarning("Client handling was cancelled via a task cancellation."); - } - catch (OperationCanceledException) - { - logger.LogWarning("Client handling was cancelled via an operation cancellation."); - } - catch (Exception ex) - { - logger.LogException("Exception during client handling", ex); - } - finally - { - if (clientHandlerArgs.ClientSocket != null) - { - logger.LogMessage("Closing and releasing all resources associated with client handler socket"); - - clientHandlerArgs.ClientSocket.Shutdown(SocketShutdown.Both); - clientHandlerArgs.ClientSocket.Disconnect(true); - clientHandlerArgs.ClientSocket.Close(1); - clientHandlerArgs.ClientSocket.Dispose(); - } - } - } - - /// <summary> - /// Handles a client asynchronously. - /// </summary> - /// <param name="args">The client handler arguments that should be passed to the client handler.</param> - /// <param name="cancellationToken">Cancellation token set when the server is shutting down.</param> - protected abstract Task HandleClientAsync(ClientHandlerArgs args, CancellationToken cancellationToken); - - /// <summary> - /// Handles the given request packet with a registered packet handler. In this case, a complex packet handler - /// will override any registered simple packet handlers. - /// </summary> - /// <param name="packetType">The type id of the packet that we should handle.</param> - /// <param name="requestPacket">The packet instance that should be handled.</param> - /// <param name="remoteEndPoint">The remote endpoint from which the request packet originated.</param> - /// <returns>The response packet that should be sent back to the remote endpoint.</returns> - protected IResponsePacket<IRequestPacket>? HandleRequestPacket(uint packetType, in IRequestPacket requestPacket, - in EndPoint remoteEndPoint) - { - try - { - if (complexPacketHandlers.ContainsKey(packetType)) - { - IResponsePacket<IRequestPacket> response = - complexPacketHandlers[packetType].Invoke(requestPacket, remoteEndPoint); - - return response; - } - - if (simplePacketHandlers.ContainsKey(packetType)) - { - simplePacketHandlers[packetType].Invoke(requestPacket, remoteEndPoint); - return null; - } - -#if DEBUG - logger.LogWarning($"No packet handler was registered for packet of type {packetType}"); -#endif - } - catch (Exception ex) - { - logger.LogException( - $"Exception when invoking packet handler for packet (type: {packetType}) received from {remoteEndPoint}", - ex); - } - - return default; - } - - /// <summary> - /// Invokes the <see cref="ClientConnected"/> event. - /// </summary> - /// <param name="remoteEndPoint">The remote endpoint with which a connection was made.</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void OnClientConnected(EndPoint remoteEndPoint) => ClientConnected?.Invoke(remoteEndPoint); - - /// <summary> - /// Invokes the <see cref="ClientDisconnected"/> event. - /// </summary> - /// <param name="remoteEndPoint">The remote endpoint with which a connection was lost.</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void OnClientDisconnected(EndPoint remoteEndPoint) => ClientDisconnected?.Invoke(remoteEndPoint); - - /// <summary> - /// Invokes the <see cref="ServerStarted"/> event. - /// </summary> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void OnServerStarted() => ServerStarted?.Invoke(); - - /// <summary> - /// Invokes the <see cref="ServerStopped"/> event. - /// </summary> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void OnServerStopped() => ServerStopped?.Invoke(); - - /// <summary> - /// Attempts to synchronously bind the underlying socket to the given local endpoint. Blocks. - /// If the timeout is exceeded the binding attempt is aborted and the method returns false. - /// </summary> - /// <param name="localEndPoint">The local endpoint to bind to.</param> - /// <param name="timeout">The timeout within which to attempt the binding.</param> - /// <returns>Whether the binding was successful or not.</returns> - protected bool TryBind(EndPoint localEndPoint, TimeSpan timeout) => - TryBindAsync(localEndPoint, timeout).Result; - - /// <summary> - /// Attempts to asynchronously bind the underlying socket to the given local endpoint. Does not block. - /// If the timeout is exceeded the binding attempt is aborted and the method returns false. - /// </summary> - /// <param name="localEndPoint">The local endpoint to bind to.</param> - /// <param name="timeout">The timeout within which to attempt the binding.</param> - /// <returns>Whether the binding was successful or not.</returns> - protected async Task<bool> TryBindAsync(EndPoint localEndPoint, TimeSpan timeout) - { - using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout); - using CancellationTokenSource cts = - CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, serverShutdownCancellationToken); - - try - { - return await Task.Run(() => - { - socket.Bind(localEndPoint); - - return true; - }, cts.Token); - } - catch (TaskCanceledException) - { - return false; - } - catch (SocketException ex) - { - logger.LogException($"Socket exception on binding socket to {localEndPoint}:", ex); - return false; - } - } - - /// <summary> - /// Holds information about the arguments passed to every client handler task. - /// </summary> - protected readonly struct ClientHandlerArgs - { - /// <summary> - /// Initialises a new instance of the <see cref="ClientHandlerArgs"/> struct. - /// </summary> - /// <param name="remoteEndPoint">The remote endpoint of the client that should be handled.</param> - /// <param name="handlerSocket">The handler socket of the client that should be handled.</param> - private ClientHandlerArgs(EndPoint remoteEndPoint, Socket? handlerSocket) - { - ClientEndPoint = remoteEndPoint; - - ClientSocket = handlerSocket; - } - - /// <summary> - /// The remote endpoint for the client being handled. - /// </summary> - public readonly EndPoint ClientEndPoint; - - /// <summary> - /// The client handler socket for the client being handled. Is only set if using TCP. - /// </summary> - public readonly Socket? ClientSocket; - - /// <summary> - /// Constructs a new instance of the <see cref="ClientHandlerArgs"/> for a TCP client. - /// </summary> - /// <returns>A new instance of the <see cref="ClientHandlerArgs"/>, setup for a TCP client.</returns> - public static ClientHandlerArgs ForTcpClientHandler(in Socket clientHandlerSocket) - { - return new ClientHandlerArgs(clientHandlerSocket.RemoteEndPoint, clientHandlerSocket); - } - - /// <summary> - /// Constructs a new instance of the <see cref="ClientHandlerArgs"/> for a UDP client. - /// </summary> - /// <returns>A new instance of the <see cref="ClientHandlerArgs"/>, setup for a UDP client.</returns> - public static ClientHandlerArgs ForUdpClientHandler(in EndPoint clientEndPoint) - { - return new ClientHandlerArgs(clientEndPoint, null); - } - } - - /// <summary> - /// Signifies that a connection with a remote endpoint has been made. - /// </summary> - public event Action<EndPoint>? ClientConnected; - - //protected IResponsePacket<IRequestPacket> DeserialiseResponsePacket(in Packet) - /// <summary> - /// Signifies that a connection with a remote endpoint has been lost. - /// </summary> - public event Action<EndPoint>? ClientDisconnected; - - /// <summary> - /// Signifies that the server was started and clients will start being accepted. - /// </summary> - public event Action? ServerStarted; - - /// <summary> - /// Signifies that the server was stopped and clients will stop being accepted. - /// </summary> - public event Action? ServerStopped; - - /// <summary> - /// The timeout value for network operations such as sending bytes or receiving bytes over the network. - /// </summary> - public TimeSpan NetworkOperationTimeout { get; protected set; } - - /// <summary> - /// The configured socket options for the underlying connection. - /// </summary> - public SocketOptions SocketOptions - { - get { return socketOptions; } - } - - /// <inheritdoc /> - public abstract Task RunAsync(EndPoint localEndPoint); - - /// <inheritdoc /> - public void Shutdown() - { - runServer = false; - logger.LogMessage("Signalling server shutdown to all client handlers..."); - serverShutdownCancellationTokenSource.Cancel(); - } - - /// <inheritdoc /> - public bool TryDeregisterComplexPacketHandler<Req, Rep>(out ComplexPacketHandler<Req, Rep>? oldHandlerDelegate) - where Req : class, IRequestPacket, new() where Rep : class, IResponsePacket<Req>, new() - { - uint packetTypeId = PacketRegistry.GetPacketId<Req>(); - oldHandlerDelegate = default; - - try - { - requestPacketDeserialisers.TryRemove(packetTypeId, out _); - - if (!complexPacketHandlers.TryGetValue(packetTypeId, - out Func<IRequestPacket, EndPoint, IResponsePacket<IRequestPacket>> oldDelegate)) - return false; - - oldHandlerDelegate = (p, ep) => (Rep)oldDelegate(p, ep); - return true; - } - catch (Exception ex) - { - logger.LogException("Exception when deregistering complex packet handler", ex); - } - - return false; - } - - /// <inheritdoc /> - public bool TryDeregisterSimplePacketHandler<Req>(out SimplePacketHandler<Req>? oldHandlerDelegate) - where Req : class, IRequestPacket, new() - { - uint packetTypeId = PacketRegistry.GetPacketId<Req>(); - oldHandlerDelegate = default; - - try - { - requestPacketDeserialisers.TryRemove(packetTypeId, out _); - - if (!simplePacketHandlers.TryGetValue(packetTypeId, out Action<IRequestPacket, EndPoint> oldDelegate)) - return false; - - oldHandlerDelegate = (p, ep) => oldDelegate(p, ep); - return true; - } - catch (Exception ex) - { - logger.LogException("Exception when deregistering simple packet handler", ex); - } - - return false; - } - - /// <inheritdoc /> - public bool TryRegisterComplexPacketHandler<Req, Rep>(ComplexPacketHandler<Req, Rep> handlerDelegate) - where Req : class, IRequestPacket, new() where Rep : class, IResponsePacket<Req>, new() - { - uint packetTypeId = PacketRegistry.GetPacketId<Req>(); - - static IRequestPacket PacketDeserialiser(in SerialisedPacket packet) => SerialisedPacket.To<Req>(packet); - - IResponsePacket<IRequestPacket> MappedHandlerDelegate(IRequestPacket p, EndPoint ep) - { - Rep responsePacket = handlerDelegate((Req)p, ep); - return responsePacket; - } - - try - { - requestPacketDeserialisers.AddOrUpdate(packetTypeId, - key => PacketDeserialiser, - (key, oldDeserialiser) => PacketDeserialiser); - - complexPacketHandlers.AddOrUpdate(packetTypeId, - key => MappedHandlerDelegate, - (key, oldDelegate) => MappedHandlerDelegate); - - return true; - } - catch (Exception ex) - { - logger.LogException("Exception when registering complex packet handler", ex); - } - - return false; - } - - /// <inheritdoc /> - public bool TryRegisterSimplePacketHandler<Req>(SimplePacketHandler<Req> handlerDelegate) - where Req : class, IRequestPacket, new() - { - uint packetTypeId = PacketRegistry.GetPacketId<Req>(); - - static IRequestPacket PacketDeserialiser(in SerialisedPacket packet) => SerialisedPacket.To<Req>(packet); - - void MappedHandlerDelegate(IRequestPacket p, EndPoint ep) => handlerDelegate((Req)p, ep); - - try - { - requestPacketDeserialisers.AddOrUpdate(packetTypeId, - key => PacketDeserialiser, - (key, oldDeserialiser) => PacketDeserialiser); - - simplePacketHandlers.AddOrUpdate(packetTypeId, - key => MappedHandlerDelegate, - (key, oldDelegate) => MappedHandlerDelegate); - - return true; - } - catch (Exception ex) - { - logger.LogException("Exception when registering simple packet handler", ex); - } - - return false; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/ServerClientConnection.cs b/NetSharp/NetSharp/Deprecated/ServerClientConnection.cs @@ -1,87 +0,0 @@ -using System; -using System.IO; -using System.Net; -using System.Runtime.CompilerServices; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Base class for connections, holding methods shared between the <see cref="Client"/> and <see cref="Server"/> classes. - /// </summary> - public abstract class ServerClientConnection : IDisposable - { - /// <summary> - /// The logger to which the server can log messages. - /// </summary> - protected Logger logger; - - /// <summary> - /// Initialises a new instance of the <see cref="ServerClientConnection"/> class. - /// </summary> - protected ServerClientConnection() - { - //networkManager = new NetworkOperationsManager(); - - logger = new Logger(Stream.Null); - } - - /// <summary> - /// Disposes of this <see cref="ServerClientConnection"/> instance. - /// </summary> - /// <param name="disposing">Whether this instance is being disposed.</param> - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - logger.Dispose(); - } - } - - /// <summary> - /// Invokes the <see cref="BytesReceived"/> event. - /// </summary> - /// <param name="remoteEndPoint">The remote endpoint from which the bytes were received.</param> - /// <param name="bytesReceived">The number of bytes that were received from the remote endpoint.</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void OnBytesReceived(EndPoint remoteEndPoint, int bytesReceived) => - BytesReceived?.Invoke(remoteEndPoint, bytesReceived); - - /// <summary> - /// Invokes the <see cref="BytesSent"/> event. - /// </summary> - /// <param name="remoteEndPoint">The remote endpoint to which the bytes were sent.</param> - /// <param name="bytesSent">The number of bytes that were sent to the remote endpoint.</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void OnBytesSent(EndPoint remoteEndPoint, int bytesSent) => - BytesSent?.Invoke(remoteEndPoint, bytesSent); - - /// <summary> - /// Signifies that some data has been received from the remote endpoint. - /// </summary> - public event Action<EndPoint, int>? BytesReceived; - - /// <summary> - /// Signifies that some data was sent to the remote endpoint. - /// </summary> - public event Action<EndPoint, int>? BytesSent; - - /// <summary> - /// Makes the client log to the given stream. - /// </summary> - /// <param name="loggingStream">The stream that new messages should be logged to.</param> - /// <param name="minimumMessageSeverityLevel"> - /// The minimum severity level that new messages must have to be logged to the stream. - /// </param> - public void ChangeLoggingStream(Stream loggingStream, LogLevel minimumMessageSeverityLevel = LogLevel.Info) - { - logger = new Logger(loggingStream, minimumMessageSeverityLevel); - } - - /// <inheritdoc /> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/ServerExtensions.cs b/NetSharp/NetSharp/Deprecated/ServerExtensions.cs @@ -1,46 +0,0 @@ -using System.Net; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides additional methods and functionality to the <see cref="Server"/> class. - /// </summary> - public static class ServerExtensions - { - /// <summary> - /// Starts the server synchronously and starts accepting client connections. Blocks. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="localAddress">The local IP address to bind to.</param> - /// <param name="localPort">The local port to bind to.</param> - public static void Run(this Server instance, IPAddress localAddress, int localPort) => - instance.RunAsync(localAddress, localPort).Wait(); - - /// <summary> - /// Starts the server synchronously and starts accepting client connections. Blocks. Uses the default connection port. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="localAddress">The local IP address to bind to.</param> - public static void Run(this Server instance, IPAddress localAddress) => - instance.RunAsync(localAddress, Constants.DefaultPort).Wait(); - - /// <summary> - /// Starts the server asynchronously and starts accepting client connections. Does not block. Uses the default - /// connection port. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="localAddress">The local IP address to bind to.</param> - public static async Task RunAsync(this Server instance, IPAddress localAddress) => - await instance.RunAsync(localAddress, Constants.DefaultPort); - - /// <summary> - /// Starts the server asynchronously and starts accepting client connections. Does not block. - /// </summary> - /// <param name="instance">The instance on which this extension method should be called.</param> - /// <param name="localAddress">The local IP address to bind to.</param> - /// <param name="localPort">The local port to bind to.</param> - public static async Task RunAsync(this Server instance, IPAddress localAddress, int localPort) => - await instance.RunAsync(new IPEndPoint(localAddress, localPort)); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SocketAcceptor.cs b/NetSharp/NetSharp/Deprecated/SocketAcceptor.cs @@ -1,281 +0,0 @@ -using Microsoft.Extensions.ObjectPool; - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Helper class providing awaitable wrappers around asynchronous Accept, Connect, and Disconnect operations. - /// </summary> - public sealed class SocketAcceptor - { - private readonly ObjectPool<SocketAsyncEventArgs> acceptAsyncEventArgsPool; - private readonly ObjectPool<SocketAsyncEventArgs> connectAsyncEventArgsPool; - private readonly ObjectPool<SocketAsyncEventArgs> disconnectAsyncEventArgsPool; - - private void HandleIOCompleted(object? sender, SocketAsyncEventArgs args) - { - switch (args.LastOperation) - { - case SocketAsyncOperation.Accept: - AsyncAcceptToken asyncAcceptToken = (AsyncAcceptToken)args.UserToken; - - if (asyncAcceptToken.CancellationToken.IsCancellationRequested) - { - asyncAcceptToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncAcceptToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - asyncAcceptToken.CompletionSource.SetResult(args.AcceptSocket); - } - } - - acceptAsyncEventArgsPool.Return(args); - - break; - - case SocketAsyncOperation.Connect: - AsyncConnectToken asyncConnectToken = (AsyncConnectToken)args.UserToken; - - if (asyncConnectToken.CancellationToken.IsCancellationRequested) - { - asyncConnectToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncConnectToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - asyncConnectToken.CompletionSource.SetResult(true); - } - } - - connectAsyncEventArgsPool.Return(args); - - break; - - case SocketAsyncOperation.Disconnect: - AsyncDisconnectToken asyncDisconnectToken = (AsyncDisconnectToken)args.UserToken; - - if (asyncDisconnectToken.CancellationToken.IsCancellationRequested) - { - asyncDisconnectToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncDisconnectToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - asyncDisconnectToken.CompletionSource.SetResult(true); - } - } - - disconnectAsyncEventArgsPool.Return(args); - - break; - - default: - throw new InvalidOperationException( - $"The {nameof(SocketAcceptor)} class doesn't support the {args.LastOperation} operation."); - } - } - - private readonly struct AsyncAcceptToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<Socket> CompletionSource; - - public AsyncAcceptToken(TaskCompletionSource<Socket> tcs, CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - private readonly struct AsyncConnectToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<bool> CompletionSource; - - public AsyncConnectToken(TaskCompletionSource<bool> tcs, CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - private readonly struct AsyncDisconnectToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<bool> CompletionSource; - - public AsyncDisconnectToken(TaskCompletionSource<bool> tcs, CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - internal SocketAcceptor(int maxPooledObjects = 10) - { - acceptAsyncEventArgsPool = - new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>(), - maxPooledObjects); - - connectAsyncEventArgsPool = - new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>(), - maxPooledObjects); - - disconnectAsyncEventArgsPool = - new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>(), - maxPooledObjects); - - for (int i = 0; i < maxPooledObjects; i++) - { - SocketAsyncEventArgs acceptArgs = new SocketAsyncEventArgs(); - acceptArgs.Completed += HandleIOCompleted; - acceptAsyncEventArgsPool.Return(acceptArgs); - - SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs(); - connectArgs.Completed += HandleIOCompleted; - connectAsyncEventArgsPool.Return(connectArgs); - - SocketAsyncEventArgs disconnectArgs = new SocketAsyncEventArgs(); - disconnectArgs.Completed += HandleIOCompleted; - connectAsyncEventArgsPool.Return(disconnectArgs); - } - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket accept operation. - /// </summary> - /// <param name="socket">The socket which should be used to accept an incoming connection attempt.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - /// <returns>The accepted socket.</returns> - public Task<Socket> AcceptAsync(Socket socket, CancellationToken cancellationToken = default) - { - TaskCompletionSource<Socket> tcs = new TaskCompletionSource<Socket>(); - - SocketAsyncEventArgs args = acceptAsyncEventArgsPool.Get(); - args.UserToken = new AsyncAcceptToken(tcs, cancellationToken); - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - acceptAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the accept operation doesn't complete synchronously, return the awaitable task - if (socket.AcceptAsync(args)) return tcs.Task; - - Socket result = args.AcceptSocket; - - acceptAsyncEventArgsPool.Return(args); - - return Task.FromResult(result); - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket connect operation. - /// </summary> - /// <param name="socket">The socket which should asynchronously connect to the remote endpoint.</param> - /// <param name="remoteEndPoint">The remote endpoint to which the socket should connect.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - public Task ConnectAsync(Socket socket, EndPoint remoteEndPoint, CancellationToken cancellationToken = default) - { - TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); - - SocketAsyncEventArgs args = connectAsyncEventArgsPool.Get(); - args.RemoteEndPoint = remoteEndPoint; - args.UserToken = new AsyncConnectToken(tcs, cancellationToken); - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - connectAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the connect operation doesn't complete synchronously, return the awaitable task - if (socket.ConnectAsync(args)) return tcs.Task; - - connectAsyncEventArgsPool.Return(args); - - return Task.CompletedTask; - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket disconnect operation. - /// </summary> - /// <param name="socket">The socket which should asynchronously disconnect from its remote endpoint.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - public Task DisconnectAsync(Socket socket, CancellationToken cancellationToken = default) - { - TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); - - SocketAsyncEventArgs args = connectAsyncEventArgsPool.Get(); - args.UserToken = new AsyncDisconnectToken(tcs, cancellationToken); - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - disconnectAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the disconnect operation doesn't complete synchronously, return the awaitable task - if (socket.DisconnectAsync(args)) return tcs.Task; - - connectAsyncEventArgsPool.Return(args); - - return Task.CompletedTask; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SocketClient.cs b/NetSharp/NetSharp/Deprecated/SocketClient.cs @@ -1,132 +0,0 @@ -using Microsoft.Extensions.ObjectPool; - -using NetSharp.Utils; - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - public class SocketClient : IDisposable - { - private readonly ObjectPool<SocketAsyncEventArgs> transmissionArgsPool; - - /// <summary> - /// Destroys a socket client instance. - /// </summary> - ~SocketClient() - { - Dispose(false); - } - - protected readonly Socket transmitterSocket; - - /// <summary> - /// Implementation of dispose pattern. - /// </summary> - /// <param name="disposing"> - /// Whether this method is being called by the object finalizer, or by the <see cref="Dispose()"/> method. - /// </param> - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - transmitterSocket.Dispose(); - } - } - - public SocketClient(AddressFamily transmitterAddressFamily, SocketType transmitterSocketType, - ProtocolType transmitterProtocolType) - { - transmitterSocket = new Socket(transmitterAddressFamily, transmitterSocketType, transmitterProtocolType); - - transmissionArgsPool = new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>()); - } - - /// <inheritdoc /> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public async ValueTask<TransmissionResult> ReceiveAsync(EndPoint remoteEndPoint, SocketFlags receiveFlags, Memory<byte> receiveBuffer, - CancellationToken cancellationToken = default) - { - SocketAsyncEventArgs transmissionArgs = transmissionArgsPool.Get(); - - TransmissionResult receiveResult = - await SocketOperations.ReceiveFromAsync(transmissionArgs, transmitterSocket, - remoteEndPoint, receiveFlags, receiveBuffer, cancellationToken).ConfigureAwait(false); - - transmissionArgsPool.Return(transmissionArgs); - - return receiveResult; - } - - public async ValueTask<TransmissionResult> SendAsync(EndPoint remoteEndPoint, SocketFlags sendFlags, Memory<byte> sendBuffer, - CancellationToken cancellationToken = default) - { - SocketAsyncEventArgs transmissionArgs = transmissionArgsPool.Get(); - - TransmissionResult sendResult = - await SocketOperations.SendToAsync(transmissionArgs, transmitterSocket, - remoteEndPoint, sendFlags, sendBuffer, cancellationToken).ConfigureAwait(false); - - transmissionArgsPool.Return(transmissionArgs); - - return sendResult; - } - - public Task<bool> TryBindAsync(EndPoint localEndPoint, TimeSpan timeout) - { - using CancellationTokenSource cts = new CancellationTokenSource(timeout); - - try - { - return Task.Run(() => - { - transmitterSocket.Bind(localEndPoint); - - return true; - }, cts.Token); - } - catch (TaskCanceledException) - { - return Task.FromResult(false); - } - catch (SocketException ex) - { - Console.WriteLine($"Socket exception on binding socket to {localEndPoint}: {ex}"); - return Task.FromResult(false); - } - } - - public Task<bool> TryConnectAsync(EndPoint remoteEndPoint, TimeSpan timeout) - { - using CancellationTokenSource cts = new CancellationTokenSource(timeout); - - try - { - return Task.Run(() => - { - transmitterSocket.Connect(remoteEndPoint); - - return true; - }, cts.Token); - } - catch (TaskCanceledException) - { - return Task.FromResult(false); - } - catch (SocketException ex) - { - Console.WriteLine($"Socket exception on connecting to {remoteEndPoint}: {ex}"); - return Task.FromResult(false); - } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SocketOperationTokens.cs b/NetSharp/NetSharp/Deprecated/SocketOperationTokens.cs @@ -1,80 +0,0 @@ -using NetSharp.Utils; - -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - internal readonly struct AsyncAcceptToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<Socket> CompletionSource; - - public AsyncAcceptToken(in TaskCompletionSource<Socket> tcs, in CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - internal readonly struct AsyncConnectToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<Socket> CompletionSource; - - public AsyncConnectToken(in TaskCompletionSource<Socket> tcs, in CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - internal readonly struct AsyncDisconnectToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<bool> CompletionSource; - - public AsyncDisconnectToken(in TaskCompletionSource<bool> tcs, in CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - internal readonly struct AsyncReadToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<TransmissionResult> CompletionSource; - - public AsyncReadToken(in TaskCompletionSource<TransmissionResult> tcs, in CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - internal readonly struct AsyncWriteToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<TransmissionResult> CompletionSource; - - public AsyncWriteToken(in TaskCompletionSource<TransmissionResult> tcs, in CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - internal readonly struct AsyncReadFromToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<TransmissionResult> CompletionSource; - - public AsyncReadFromToken(in TaskCompletionSource<TransmissionResult> tcs, in CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SocketOperations.cs b/NetSharp/NetSharp/Deprecated/SocketOperations.cs @@ -1,469 +0,0 @@ -using NetSharp.Utils; - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides helper awaitable functions for wrapping the <see cref="SocketAsyncEventArgs"/> pattern. - /// </summary> - public static class SocketOperations - { - private static void HandleIOCompleted(object? sender, SocketAsyncEventArgs args) - { - args.Completed -= HandleIOCompleted; - - switch (args.LastOperation) - { - case SocketAsyncOperation.Receive: - AsyncReadToken asyncReceiveToken = (AsyncReadToken)args.UserToken; - - if (asyncReceiveToken.CancellationToken.IsCancellationRequested) - { - asyncReceiveToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncReceiveToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else if (args.BytesTransferred > 0) - { - TransmissionResult result = new TransmissionResult(args); - - asyncReceiveToken.CompletionSource.SetResult(result); - } - else - { - asyncReceiveToken.CompletionSource.SetException( - new Exception($"Receive method received 0 bytes from remote endpoint!")); - } - } - - break; - - case SocketAsyncOperation.ReceiveFrom: - AsyncReadFromToken asyncReceiveFromToken = (AsyncReadFromToken)args.UserToken; - - if (asyncReceiveFromToken.CancellationToken.IsCancellationRequested) - { - asyncReceiveFromToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncReceiveFromToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - TransmissionResult result = new TransmissionResult(args); - - asyncReceiveFromToken.CompletionSource.SetResult(result); - } - } - - break; - - case SocketAsyncOperation.Send: - AsyncWriteToken asyncSendToken = (AsyncWriteToken)args.UserToken; - - if (asyncSendToken.CancellationToken.IsCancellationRequested) - { - asyncSendToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncSendToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - TransmissionResult result = new TransmissionResult(args); - - asyncSendToken.CompletionSource.SetResult(result); - } - } - - break; - - case SocketAsyncOperation.SendTo: - AsyncWriteToToken asyncSendToToken = (AsyncWriteToToken)args.UserToken; - - if (asyncSendToToken.CancellationToken.IsCancellationRequested) - { - asyncSendToToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncSendToToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - TransmissionResult result = new TransmissionResult(args); - - asyncSendToToken.CompletionSource.SetResult(result); - } - } - - break; - - case SocketAsyncOperation.Accept: - AsyncAcceptToken asyncAcceptToken = (AsyncAcceptToken)args.UserToken; - - if (asyncAcceptToken.CancellationToken.IsCancellationRequested) - { - asyncAcceptToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncAcceptToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - asyncAcceptToken.CompletionSource.SetResult(args.AcceptSocket); - } - } - - break; - - case SocketAsyncOperation.Connect: - AsyncConnectToken asyncConnectToken = (AsyncConnectToken)args.UserToken; - - if (asyncConnectToken.CancellationToken.IsCancellationRequested) - { - asyncConnectToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncConnectToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - asyncConnectToken.CompletionSource.SetResult(args.ConnectSocket); - } - } - - break; - - case SocketAsyncOperation.Disconnect: - AsyncDisconnectToken asyncDisconnectToken = (AsyncDisconnectToken)args.UserToken; - - if (asyncDisconnectToken.CancellationToken.IsCancellationRequested) - { - asyncDisconnectToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncDisconnectToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - asyncDisconnectToken.CompletionSource.SetResult(true); - } - } - - break; - - default: - throw new InvalidOperationException( - $"{nameof(SocketOperations)} doesn't support the {args.LastOperation} operation."); - } - } - - private readonly struct AsyncWriteToToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<TransmissionResult> CompletionSource; - - public AsyncWriteToToken(in TaskCompletionSource<TransmissionResult> tcs, in CancellationToken cancellationToken = default) - { - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - public static ValueTask<Socket> AcceptAsync(SocketAsyncEventArgs clientAcceptArgs, Socket socket, - CancellationToken cancellationToken = default) - { - TaskCompletionSource<Socket> tcs = new TaskCompletionSource<Socket>(); - - clientAcceptArgs.UserToken = new AsyncAcceptToken(tcs, cancellationToken); - - clientAcceptArgs.Completed += HandleIOCompleted; - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - acceptAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the accept operation doesn't complete synchronously, return the awaitable task - if (socket.AcceptAsync(clientAcceptArgs)) return new ValueTask<Socket>(tcs.Task); - - Socket result = clientAcceptArgs.AcceptSocket; - clientAcceptArgs.Completed -= HandleIOCompleted; - - return new ValueTask<Socket>(result); - } - - public static ValueTask<Socket> ConnectAsync(SocketAsyncEventArgs clientConnectArgs, Socket socket, EndPoint remoteEndPoint, - CancellationToken cancellationToken = default) - { - TaskCompletionSource<Socket> tcs = new TaskCompletionSource<Socket>(); - - clientConnectArgs.RemoteEndPoint = remoteEndPoint; - clientConnectArgs.UserToken = new AsyncConnectToken(tcs, cancellationToken); - - clientConnectArgs.Completed += HandleIOCompleted; - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - connectAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the connect operation doesn't complete synchronously, return the awaitable task - if (socket.ConnectAsync(clientConnectArgs)) return new ValueTask<Socket>(tcs.Task); - - Socket result = clientConnectArgs.ConnectSocket; - clientConnectArgs.Completed -= HandleIOCompleted; - - return new ValueTask<Socket>(result); - } - - public static ValueTask DisconnectAsync(SocketAsyncEventArgs clientDisconnectArgs, Socket socket, - CancellationToken cancellationToken = default) - { - TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); - - clientDisconnectArgs.UserToken = new AsyncDisconnectToken(tcs, cancellationToken); - - clientDisconnectArgs.Completed += HandleIOCompleted; - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - disconnectAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the disconnect operation doesn't complete synchronously, return the awaitable task - if (socket.DisconnectAsync(clientDisconnectArgs)) return new ValueTask(tcs.Task); - - clientDisconnectArgs.Completed -= HandleIOCompleted; - - return new ValueTask(); - } - - public static ValueTask<TransmissionResult> ReceiveAsync(SocketAsyncEventArgs socketArgs, Socket socket, EndPoint remoteEndPoint, - SocketFlags socketFlags, Memory<byte> inputBuffer, CancellationToken cancellationToken = default) - { - TaskCompletionSource<TransmissionResult> tcs = new TaskCompletionSource<TransmissionResult>(); - - socketArgs.SetBuffer(inputBuffer); - socketArgs.SocketFlags = socketFlags; - socketArgs.RemoteEndPoint = remoteEndPoint; - socketArgs.UserToken = new AsyncReadToken(tcs, cancellationToken); - - socketArgs.Completed += HandleIOCompleted; - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - receiveBufferPool.Return(rentedReceiveFromBuffer, true); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - receiveAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the receive operation doesn't complete synchronously, returns the awaitable task - if (socket.ReceiveAsync(socketArgs)) return new ValueTask<TransmissionResult>(tcs.Task); - - socketArgs.Completed -= HandleIOCompleted; - - TransmissionResult result = new TransmissionResult(socketArgs); - - return new ValueTask<TransmissionResult>(result); - } - - public static ValueTask<TransmissionResult> ReceiveFromAsync(SocketAsyncEventArgs socketArgs, Socket socket, EndPoint remoteEndPoint, - SocketFlags socketFlags, Memory<byte> inputBuffer, CancellationToken cancellationToken = default) - { - TaskCompletionSource<TransmissionResult> tcs = new TaskCompletionSource<TransmissionResult>(); - - socketArgs.SetBuffer(inputBuffer); - socketArgs.SocketFlags = socketFlags; - socketArgs.RemoteEndPoint = remoteEndPoint; - socketArgs.UserToken = new AsyncReadFromToken(tcs, cancellationToken); - - socketArgs.Completed += HandleIOCompleted; - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - receiveBufferPool.Return(rentedReceiveFromBuffer, true); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - receiveAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the receive operation doesn't complete synchronously, returns the awaitable task - if (socket.ReceiveFromAsync(socketArgs)) return new ValueTask<TransmissionResult>(tcs.Task); - - socketArgs.Completed -= HandleIOCompleted; - - TransmissionResult result = new TransmissionResult(socketArgs); - - return new ValueTask<TransmissionResult>(result); - } - - public static ValueTask<TransmissionResult> SendAsync(SocketAsyncEventArgs socketArgs, Socket socket, EndPoint remoteEndPoint, - SocketFlags socketFlags, Memory<byte> outputBuffer, CancellationToken cancellationToken = default) - { - TaskCompletionSource<TransmissionResult> tcs = new TaskCompletionSource<TransmissionResult>(); - - socketArgs.SetBuffer(outputBuffer); - socketArgs.SocketFlags = socketFlags; - socketArgs.RemoteEndPoint = remoteEndPoint; - socketArgs.UserToken = new AsyncWriteToken(tcs, cancellationToken); - - socketArgs.Completed += HandleIOCompleted; - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - sendBufferPool.Return(rentedSendToBuffer, true); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - sendAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the send operation doesn't complete synchronously, return the awaitable task - if (socket.SendAsync(socketArgs)) return new ValueTask<TransmissionResult>(tcs.Task); - - socketArgs.Completed -= HandleIOCompleted; - - TransmissionResult result = new TransmissionResult(socketArgs); - - return new ValueTask<TransmissionResult>(result); - } - - public static ValueTask<TransmissionResult> SendToAsync(SocketAsyncEventArgs socketArgs, Socket socket, EndPoint remoteEndPoint, - SocketFlags socketFlags, Memory<byte> outputBuffer, CancellationToken cancellationToken = default) - { - TaskCompletionSource<TransmissionResult> tcs = new TaskCompletionSource<TransmissionResult>(); - - socketArgs.SetBuffer(outputBuffer); - socketArgs.SocketFlags = socketFlags; - socketArgs.RemoteEndPoint = remoteEndPoint; - socketArgs.UserToken = new AsyncWriteToToken(tcs, cancellationToken); - - socketArgs.Completed += HandleIOCompleted; - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - sendBufferPool.Return(rentedSendToBuffer, true); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - sendAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the send operation doesn't complete synchronously, return the awaitable task - if (socket.SendToAsync(socketArgs)) return new ValueTask<TransmissionResult>(tcs.Task); - - socketArgs.Completed -= HandleIOCompleted; - - TransmissionResult result = new TransmissionResult(socketArgs); - - return new ValueTask<TransmissionResult>(result); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SocketOptions.cs b/NetSharp/NetSharp/Deprecated/SocketOptions.cs @@ -1,106 +0,0 @@ -using System.Net; -using System.Net.Sockets; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Allows for manipulation of socket options. - /// </summary> - public abstract class SocketOptions - { - /// <summary> - /// The <see cref="Socket"/> instance whose settings are being managed. - /// </summary> - protected readonly Socket managedSocket; - - /// <summary> - /// Initialises a new instance of the <see cref="SocketOptions"/> class. - /// </summary> - /// <param name="socket">The <see cref="Socket"/> instance whose options should be managed.</param> - protected SocketOptions(ref Socket socket) - { - managedSocket = socket; - } - - /// <summary> - /// Whether this <see cref="Socket"/> can operate in dual IPv4 / IPv6 mode. - /// </summary> - public bool DualMode { get { return managedSocket.DualMode; } set { managedSocket.DualMode = value; } } - - /// <summary> - /// Whether sending a packet flushes underlying <see cref="NetworkStream"/>. - /// </summary> - /// <remarks> - /// This value is only used in a <see cref="System.Net.Sockets.TcpClient"/> instance, which uses a <see cref="NetworkStream"/> - /// to send and receive data. A <see cref="System.Net.Sockets.UdpClient"/> is unaffected by this value. - /// </remarks> - public bool ForceFlush { get; set; } = true; - - /// <summary> - /// Whether this <see cref="Socket"/> is allowed to fragment frames that are too large to send in one go. - /// </summary> - public bool Fragment { get { return !managedSocket.DontFragment; } set { managedSocket.DontFragment = !value; } } - - /// <summary> - /// The hop limit for packets sent by this <see cref="Socket"/>. Comparable to IPv4s TTL (Time To Live). - /// </summary> - public abstract int HopLimit { get; set; } - - /// <summary> - /// Whether a checksum should be created for each UDP packet sent. - /// </summary> - public bool IsChecksumEnabled - { - get { return (int)managedSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoChecksum) == 0; } - set { managedSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoChecksum, value ? 0 : -1); } - } - - /// <summary> - /// Whether the packet should be sent directly to its destination or allowed to be routed through multiple destinations - /// first. - /// </summary> - public abstract bool IsRoutingEnabled { get; set; } - - /// <summary> - /// The local <see cref="EndPoint"/> for the <see cref="managedSocket"/>. - /// </summary> - public EndPoint LocalEndPoint { get { return managedSocket.LocalEndPoint; } } - - /// <summary> - /// The local <see cref="IPEndPoint"/> for this <see cref="Socket"/> instance. - /// </summary> - public EndPoint LocalIPEndPoint - { - get - { - return managedSocket?.LocalEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.None, IPEndPoint.MinPort); - } - } - - /// <summary> - /// The remote <see cref="EndPoint"/> for the <see cref="managedSocket"/>. - /// </summary> - public EndPoint RemoteEndPoint { get { return managedSocket.RemoteEndPoint; } } - - /// <summary> - /// The remote <see cref="IPEndPoint"/> that this <see cref="Socket"/> instance communicates with. - /// </summary> - public EndPoint RemoteIPEndPoint - { - get - { - return managedSocket?.RemoteEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.None, IPEndPoint.MinPort); - } - } - - /// <summary> - /// The 'Time To Live' for this <see cref="Socket"/>. - /// </summary> - public short Ttl { get { return managedSocket.Ttl; } set { managedSocket.Ttl = value; } } - - /// <summary> - /// Whether this <see cref="Socket"/> should use a loopback address and bypass hardware. - /// </summary> - public abstract bool UseLoopback { get; set; } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SocketReader.cs b/NetSharp/NetSharp/Deprecated/SocketReader.cs @@ -1,153 +0,0 @@ -using Microsoft.Extensions.ObjectPool; - -using NetSharp.Utils; - -using System; -using System.Buffers; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Helper class providing awaitable wrappers around asynchronous Receive and ReceiveFrom operations. - /// </summary> - public sealed class SocketReader - { - private readonly int PacketBufferLength; - private readonly ObjectPool<SocketAsyncEventArgs> receiveFromAsyncEventArgsPool; - private readonly ArrayPool<byte> receiveFromBufferPool; - - private void HandleIOCompleted(object? sender, SocketAsyncEventArgs args) - { - switch (args.LastOperation) - { - case SocketAsyncOperation.ReceiveFrom: - AsyncReadToken asyncReceiveFromToken = (AsyncReadToken)args.UserToken; - - if (asyncReceiveFromToken.CancellationToken.IsCancellationRequested) - { - asyncReceiveFromToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncReceiveFromToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - args.MemoryBuffer.CopyTo(asyncReceiveFromToken.UserBuffer); - - TransmissionResult result = new TransmissionResult(args); - - asyncReceiveFromToken.CompletionSource.SetResult(result); - } - } - - receiveFromBufferPool.Return(asyncReceiveFromToken.RentedBuffer, true); - receiveFromAsyncEventArgsPool.Return(args); - - break; - - default: - throw new InvalidOperationException( - $"The {nameof(SocketReader)} class doesn't support the {args.LastOperation} operation."); - } - } - - private readonly struct AsyncReadToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<TransmissionResult> CompletionSource; - public readonly byte[] RentedBuffer; - public readonly Memory<byte> UserBuffer; - - public AsyncReadToken(byte[] rentedBuffer, Memory<byte> userBuffer, TaskCompletionSource<TransmissionResult> tcs, - CancellationToken cancellationToken = default) - { - RentedBuffer = rentedBuffer; - UserBuffer = userBuffer; - - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - internal SocketReader(int packetBufferLength = NetworkPacket.PacketSize, int maxPooledObjects = 10, - bool preallocateBuffers = false) - { - PacketBufferLength = packetBufferLength; - - receiveFromBufferPool = ArrayPool<byte>.Create(packetBufferLength, maxPooledObjects); - - receiveFromAsyncEventArgsPool = - new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>(), - maxPooledObjects); - - for (int i = 0; i < maxPooledObjects; i++) - { - SocketAsyncEventArgs receiveFromArgs = new SocketAsyncEventArgs(); - receiveFromArgs.Completed += HandleIOCompleted; - receiveFromAsyncEventArgsPool.Return(receiveFromArgs); - } - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket receive operation. - /// </summary> - /// <param name="socket">The socket which should receive data from the remote endpoint.</param> - /// <param name="remoteEndPoint">The remove endpoint from which data should be received.</param> - /// <param name="socketFlags">The socket flags associated with the receive operation.</param> - /// <param name="inputBuffer">The memory buffer into which received data will be stored.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - /// <returns>The result of the receive operation.</returns> - public Task<TransmissionResult> ReceiveFromAsync(Socket socket, EndPoint remoteEndPoint, SocketFlags socketFlags, - Memory<byte> inputBuffer, CancellationToken cancellationToken = default) - { - TaskCompletionSource<TransmissionResult> tcs = new TaskCompletionSource<TransmissionResult>(); - - byte[] rentedReceiveFromBuffer = receiveFromBufferPool.Rent(PacketBufferLength); - Memory<byte> rentedReceiveFromBufferMemory = new Memory<byte>(rentedReceiveFromBuffer); - - SocketAsyncEventArgs args = receiveFromAsyncEventArgsPool.Get(); - args.SetBuffer(rentedReceiveFromBufferMemory); - args.SocketFlags = socketFlags; - args.RemoteEndPoint = remoteEndPoint; - args.UserToken = new AsyncReadToken(rentedReceiveFromBuffer, inputBuffer, tcs, cancellationToken); - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - receiveBufferPool.Return(rentedReceiveFromBuffer, true); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - receiveAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the receive operation doesn't complete synchronously, returns the awaitable task - if (socket.ReceiveFromAsync(args)) return tcs.Task; - - args.MemoryBuffer.CopyTo(inputBuffer); - - TransmissionResult result = new TransmissionResult(args); - - receiveFromBufferPool.Return(rentedReceiveFromBuffer, true); - receiveFromAsyncEventArgsPool.Return(args); - - return Task.FromResult(result); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SocketServer.cs b/NetSharp/NetSharp/Deprecated/SocketServer.cs @@ -1,121 +0,0 @@ -using Microsoft.Extensions.ObjectPool; - -using NetSharp.Utils; - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - public class SocketServer : IDisposable - { - private readonly ObjectPool<SocketAsyncEventArgs> transmissionArgsPool; - - /// <summary> - /// Destroys a socket server instance. - /// </summary> - ~SocketServer() - { - Dispose(false); - } - - /// <summary> - /// The socket which should be used to listen for incoming data and to send outgoing data. - /// </summary> - protected readonly Socket listenerSocket; - - /// <summary> - /// Implementation of dispose pattern. - /// </summary> - /// <param name="disposing"> - /// Whether this method is being called by the object finalizer, or by the <see cref="Dispose()"/> method. - /// </param> - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - listenerSocket.Dispose(); - } - } - - public SocketServer(AddressFamily listenerAddressFamily, SocketType listenerSocketType, - ProtocolType listenerProtocolType) - { - listenerSocket = new Socket(listenerAddressFamily, listenerSocketType, listenerProtocolType); - - transmissionArgsPool = new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>()); - } - - /// <inheritdoc /> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public async ValueTask<TransmissionResult> ReceiveAsync(EndPoint remoteEndPoint, SocketFlags receiveFlags, Memory<byte> receiveBuffer, - CancellationToken cancellationToken = default) - { - SocketAsyncEventArgs transmissionArgs = transmissionArgsPool.Get(); - - TransmissionResult receiveResult = - await SocketOperations.ReceiveFromAsync(transmissionArgs, listenerSocket, remoteEndPoint, receiveFlags, - receiveBuffer, cancellationToken).ConfigureAwait(false); - - transmissionArgsPool.Return(transmissionArgs); - - return receiveResult; - } - - public async ValueTask<TransmissionResult> SendAsync(EndPoint remoteEndPoint, SocketFlags sendFlags, Memory<byte> sendBuffer, - CancellationToken cancellationToken = default) - { - SocketAsyncEventArgs transmissionArgs = transmissionArgsPool.Get(); - - TransmissionResult sendResult = - await SocketOperations.SendToAsync(transmissionArgs, listenerSocket, remoteEndPoint, sendFlags, - sendBuffer, cancellationToken).ConfigureAwait(false); - - transmissionArgsPool.Return(transmissionArgs); - - return sendResult; - } - - public async Task<RemoteSocketClient> AcceptAsync(CancellationToken cancellationToken = default) - { - using SocketAsyncEventArgs clientAcceptArgs = new SocketAsyncEventArgs(); - - Socket clientSocket = await SocketOperations - .AcceptAsync(clientAcceptArgs, listenerSocket, cancellationToken).ConfigureAwait(false); - - return new RemoteSocketClient(clientSocket); - } - - public Task<bool> TryBindAsync(EndPoint localEndPoint, TimeSpan timeout) - { - using CancellationTokenSource cts = new CancellationTokenSource(timeout); - - try - { - return Task.Run(() => - { - listenerSocket.Bind(localEndPoint); - - return true; - }, cts.Token); - } - catch (TaskCanceledException) - { - return Task.FromResult(false); - } - catch (SocketException ex) - { - Console.WriteLine($"Socket exception on binding socket to {localEndPoint}: {ex}"); - return Task.FromResult(false); - } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/SocketWriter.cs b/NetSharp/NetSharp/Deprecated/SocketWriter.cs @@ -1,144 +0,0 @@ -using Microsoft.Extensions.ObjectPool; - -using System; -using System.Buffers; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Helper class providing awaitable wrappers around asynchronous Send and SendTo operations. - /// </summary> - public sealed class SocketWriter - { - private readonly int PacketBufferLength; - private readonly ObjectPool<SocketAsyncEventArgs> sendToAsyncEventArgsPool; - private readonly ArrayPool<byte> sendToBufferPool; - - private void HandleIOCompleted(object? sender, SocketAsyncEventArgs args) - { - switch (args.LastOperation) - { - case SocketAsyncOperation.SendTo: - AsyncWriteToken asyncSendToToken = (AsyncWriteToken)args.UserToken; - - if (asyncSendToToken.CancellationToken.IsCancellationRequested) - { - asyncSendToToken.CompletionSource.SetCanceled(); - } - else - { - if (args.SocketError != SocketError.Success) - { - asyncSendToToken.CompletionSource.SetException( - new SocketException((int)args.SocketError)); - } - else - { - asyncSendToToken.CompletionSource.SetResult(args.BytesTransferred); - } - } - - sendToBufferPool.Return(asyncSendToToken.RentedBuffer, true); - sendToAsyncEventArgsPool.Return(args); - break; - - default: - throw new InvalidOperationException( - $"The {nameof(SocketWriter)} class doesn't support the {args.LastOperation} operation."); - } - } - - private readonly struct AsyncWriteToken - { - public readonly CancellationToken CancellationToken; - public readonly TaskCompletionSource<int> CompletionSource; - public readonly byte[] RentedBuffer; - - public AsyncWriteToken(byte[] rentedBuffer, TaskCompletionSource<int> tcs, - CancellationToken cancellationToken = default) - { - RentedBuffer = rentedBuffer; - - CompletionSource = tcs; - CancellationToken = cancellationToken; - } - } - - internal SocketWriter(int packetBufferLength = NetworkPacket.PacketSize, int maxPooledObjects = 10, - bool preallocateBuffers = false) - { - PacketBufferLength = packetBufferLength; - - sendToBufferPool = ArrayPool<byte>.Create(packetBufferLength, maxPooledObjects); - - sendToAsyncEventArgsPool = - new DefaultObjectPool<SocketAsyncEventArgs>(new DefaultPooledObjectPolicy<SocketAsyncEventArgs>(), - maxPooledObjects); - - for (int i = 0; i < maxPooledObjects; i++) - { - SocketAsyncEventArgs sendToArgs = new SocketAsyncEventArgs(); - sendToArgs.Completed += HandleIOCompleted; - sendToAsyncEventArgsPool.Return(sendToArgs); - } - } - - /// <summary> - /// Provides an awaitable wrapper around an asynchronous socket send operation. - /// </summary> - /// <param name="socket">The socket which should send the data to the remote endpoint.</param> - /// <param name="remoteEndPoint">The remote endpoint to which data should be written.</param> - /// <param name="socketFlags">The socket flags associated with the send operation.</param> - /// <param name="outputBuffer">The data buffer which should be sent.</param> - /// <param name="cancellationToken">The cancellation token to observe for the operation.</param> - /// <returns>The number of bytes of data which were written to the remote endpoint.</returns> - public ValueTask<int> SendToAsync(Socket socket, EndPoint remoteEndPoint, SocketFlags socketFlags, - Memory<byte> outputBuffer, CancellationToken cancellationToken = default) - { - TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); - - byte[] rentedSendToBuffer = sendToBufferPool.Rent(PacketBufferLength); - Memory<byte> rentedSendToBufferMemory = new Memory<byte>(rentedSendToBuffer); - - outputBuffer.CopyTo(rentedSendToBufferMemory); - - SocketAsyncEventArgs args = sendToAsyncEventArgsPool.Get(); - args.SetBuffer(rentedSendToBufferMemory); - args.SocketFlags = socketFlags; - args.RemoteEndPoint = remoteEndPoint; - args.UserToken = new AsyncWriteToken(rentedSendToBuffer, tcs, cancellationToken); - - /* - // register cleanup action for when the cancellation token is thrown - cancellationToken.Register(() => - { - tcs.SetCanceled(); - - sendBufferPool.Return(rentedSendToBuffer, true); - - //TODO this is probably a hideous solution. find a better one - args.Completed -= HandleIOCompleted; - args.Dispose(); - - SocketAsyncEventArgs newArgs = new SocketAsyncEventArgs(); - newArgs.Completed += HandleIOCompleted; - sendAsyncEventArgsPool.Return(newArgs); - }); - */ - - // if the send operation doesn't complete synchronously, return the awaitable task - if (socket.SendToAsync(args)) return new ValueTask<int>(tcs.Task); - - int result = args.BytesTransferred; - - sendToBufferPool.Return(rentedSendToBuffer, true); - sendToAsyncEventArgsPool.Return(args); - - return new ValueTask<int>(result); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/TcpClient.cs b/NetSharp/NetSharp/Deprecated/TcpClient.cs @@ -1,64 +0,0 @@ -using NetSharp.Deprecated.Builtin; - -using System; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides methods for TCP communication with a connected <see cref="TcpServer"/> instance. - /// </summary> - public sealed class TcpClient : Client - { - /// <inheritdoc /> - public TcpClient() : base(SocketType.Stream, ProtocolType.Tcp) - { - } - - /// <inheritdoc /> - public override async Task<bool> SendBytesAsync(byte[] buffer, TimeSpan timeout) - { - SimpleDataPacket packet = new SimpleDataPacket(buffer); - return await SendSimpleAsync(packet, timeout); - } - - /// <inheritdoc /> - public override async Task<byte[]> SendBytesWithResponseAsync(byte[] buffer, TimeSpan timeout) - { - DataPacket packet = new DataPacket(buffer); - DataResponsePacket response = await SendComplexAsync<DataPacket, DataResponsePacket>(packet, timeout); - - return response.ResponseBuffer.ToArray(); - } - - /// <inheritdoc /> - public override async Task<Rep> SendComplexAsync<Req, Rep>(Req request, TimeSpan timeout) - { - uint packetTypeId = PacketRegistry.GetPacketId<Req>(); - - request.BeforeSerialisation(); - Memory<byte> serialisedRequest = request.Serialise(); - SerialisedPacket rawRequest = new SerialisedPacket(serialisedRequest, packetTypeId); - //await DoSendPacketAsync(socket, rawRequest, SocketFlags.None, timeout); - - //SerialisedPacket rawResponsePacket = await DoReceivePacketAsync(socket, SocketFlags.None, timeout); - Rep responsePacket = new Rep(); - //responsePacket.Deserialise(rawResponsePacket.Contents); - responsePacket.AfterDeserialisation(); - - return responsePacket; - } - - /// <inheritdoc /> - public override async Task<bool> SendSimpleAsync<Req>(Req request, TimeSpan timeout) - { - uint packetTypeId = PacketRegistry.GetPacketId<Req>(); - - request.BeforeSerialisation(); - Memory<byte> serialisedRequest = request.Serialise(); - SerialisedPacket rawRequest = new SerialisedPacket(serialisedRequest, packetTypeId); - return false; //await DoSendPacketAsync(socket, rawRequest, SocketFlags.None, timeout); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/TcpServer.cs b/NetSharp/NetSharp/Deprecated/TcpServer.cs @@ -1,129 +0,0 @@ -using NetSharp.Deprecated.Builtin; - -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides methods for TCP communication with connected <see cref="TcpClient"/> instances. - /// </summary> - public sealed class TcpServer : Server - { - /// <inheritdoc /> - protected override async Task HandleClientAsync(ClientHandlerArgs args, CancellationToken cancellationToken) - { - Socket clientHandlerSocket = args.ClientSocket ?? new Socket(SocketType.Unknown, ProtocolType.Unknown); - EndPoint remoteEp = clientHandlerSocket.RemoteEndPoint; - - logger.LogMessage($"Initialised client handler for client socket: [Remote EP: {remoteEp}]"); - - try - { - do - { - // receive a single raw packet from the network - SerialisedPacket rawRequest = SerialisedPacket.Null; //await DoReceivePacketAsync(clientHandlerSocket, SocketFlags.None, Timeout.InfiniteTimeSpan, cancellationToken); - - if (rawRequest.Equals(SerialisedPacket.Null) || - rawRequest.Type == PacketRegistry.GetPacketId<DisconnectPacket>()) - { - logger.LogMessage( - $"Received a disconnect packet from client socket: [Remote EP: {remoteEp}]"); - break; - } - - IRequestPacket? requestPacket = DeserialiseRequestPacket(rawRequest.Type, in rawRequest); - Type requestPacketType = PacketRegistry.GetPacketType(rawRequest.Type); - - // the request packet is only null if no packet handler was registered for it - if (requestPacket == default) continue; - - logger.LogMessage($"Received {rawRequest.Contents.Length} bytes from {remoteEp}"); - - logger.LogMessage($"Received request: {Encoding.UTF8.GetString(rawRequest.Contents.Span)}"); - - IResponsePacket<IRequestPacket>? responsePacket = - HandleRequestPacket(rawRequest.Type, requestPacket, remoteEp); - - // the response packet is only null if the given request packet was registered as a 'simple' request packet - if (responsePacket == default) continue; - - Type? responsePacketType = - PacketRegistry.GetResponsePacketType(requestPacketType); - - if (responsePacketType == default) - { - logger.LogError( - $"Response packet type for request packet of type {requestPacketType} is null"); - continue; - } - - SerialisedPacket rawResponse = SerialisedPacket.From(responsePacket); - // uint responsePacketTypeId = PacketRegistry.GetPacketId(responsePacketType); - // responsePacket.BeforeSerialisation(); - // SerialisedPacket rawResponse = new SerialisedPacket(responsePacket.Serialise(), responsePacketTypeId); - - // echo back the processed raw response to the network - bool sentCorrectly = false; //await DoSendPacketAsync(clientHandlerSocket, rawResponse, SocketFlags.None, NetworkOperationTimeout, cancellationToken); - - if (!sentCorrectly) - { - logger.LogMessage( - $"Could not send response back to client socket: [Remote EP: {remoteEp}]"); - } - - logger.LogMessage($"Sent {rawResponse.Contents.Length} bytes to {remoteEp}"); - } while (true); - } - finally - { - logger.LogMessage($"Stopping client handler for client socket: [Remote EP: {remoteEp}]"); - } - } - - /// <inheritdoc /> - public TcpServer(TimeSpan networkOperationTimeout) : base(SocketType.Stream, ProtocolType.Tcp, networkOperationTimeout) - { - } - - /// <inheritdoc /> - public TcpServer() : this(DefaultNetworkOperationTimeout) - { - } - - /// <inheritdoc /> - public override async Task RunAsync(EndPoint localEndPoint) - { - bool bound = await TryBindAsync(localEndPoint, Timeout.InfiniteTimeSpan); - - logger.LogMessage($"Is server socket bound: {bound}"); - - if (!bound) - { - logger.LogError("Server socket was not bound successfully, shutting down server."); - return; - } - - socket.Listen(PendingConnectionBacklog); - - OnServerStarted(); - runServer = true; - - while (runServer) - { - Socket clientSocket = await socket.AcceptAsync(); - ClientHandlerArgs args = ClientHandlerArgs.ForTcpClientHandler(in clientSocket); - - await Task.Factory.StartNew(DoHandleClientAsync, args, serverShutdownCancellationToken, - TaskCreationOptions.LongRunning, TaskScheduler.Default); - } - - OnServerStopped(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/TcpSocketOptions.cs b/NetSharp/NetSharp/Deprecated/TcpSocketOptions.cs @@ -1,36 +0,0 @@ -using System.Net.Sockets; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Allows for manipulation of TCP socket options. - /// </summary> - public sealed class TcpSocketOptions : SocketOptions - { - /// <inheritdoc /> - public TcpSocketOptions(ref Socket socket) : base(ref socket) - { - } - - /// <inheritdoc /> - public override int HopLimit - { - get { return (int)managedSocket.GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.HopLimit); } - set { managedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.HopLimit, value); } - } - - /// <inheritdoc /> - public override bool IsRoutingEnabled - { - get { return !(bool)managedSocket.GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.DontRoute); } - set { managedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.DontRoute, !value); } - } - - /// <inheritdoc /> - public override bool UseLoopback - { - get { return (bool)managedSocket.GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.UseLoopback); } - set { managedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.UseLoopback, value); } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/UdpClient.cs b/NetSharp/NetSharp/Deprecated/UdpClient.cs @@ -1,68 +0,0 @@ -using NetSharp.Deprecated.Builtin; - -using System; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides methods for UDP communication with a connected <see cref="UdpServer"/> instance. - /// </summary> - public sealed class UdpClient : Client - { - /// <inheritdoc /> - public UdpClient() : base(SocketType.Dgram, ProtocolType.Udp) - { - } - - /// <inheritdoc /> - public override async Task<bool> SendBytesAsync(byte[] buffer, TimeSpan timeout) - { - SimpleDataPacket packet = new SimpleDataPacket(buffer); - return await SendSimpleAsync(packet, timeout); - } - - /// <inheritdoc /> - public override async Task<byte[]> SendBytesWithResponseAsync(byte[] buffer, TimeSpan timeout) - { - DataPacket packet = new DataPacket(buffer); - DataResponsePacket response = await SendComplexAsync<DataPacket, DataResponsePacket>(packet, timeout); - - return response.ResponseBuffer.ToArray(); - } - - /// <inheritdoc /> - public override async Task<Rep> SendComplexAsync<Req, Rep>(Req request, TimeSpan timeout) - { - uint packetTypeId = PacketRegistry.GetPacketId<Req>(); - - request.BeforeSerialisation(); - Memory<byte> serialisedRequest = request.Serialise(); - SerialisedPacket rawRequest = new SerialisedPacket(serialisedRequest, packetTypeId); - - bool sentPacket = false; //await DoSendPacketToAsync(socket, remoteEndPoint, rawRequest, SocketFlags.None, timeout); - - //(SerialisedPacket rawResponsePacket, EndPoint responseEndPoint) = await DoReceivePacketFromAsync(socket, remoteEndPoint, SocketFlags.None, timeout); - //remoteEndPoint = responseEndPoint; - - Rep responsePacket = new Rep(); - //responsePacket.Deserialise(rawResponsePacket.Contents); - responsePacket.AfterDeserialisation(); - - return responsePacket; - } - - /// <inheritdoc /> - public override async Task<bool> SendSimpleAsync<Req>(Req request, TimeSpan timeout) - { - uint packetTypeId = PacketRegistry.GetPacketId<Req>(); - - request.BeforeSerialisation(); - Memory<byte> serialisedRequest = request.Serialise(); - SerialisedPacket rawRequest = new SerialisedPacket(serialisedRequest, packetTypeId); - - return false; //await DoSendPacketToAsync(socket, remoteEndPoint, rawRequest, SocketFlags.None, timeout); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/UdpServer.cs b/NetSharp/NetSharp/Deprecated/UdpServer.cs @@ -1,169 +0,0 @@ -using NetSharp.Deprecated.Builtin; - -using System; -using System.Collections.Concurrent; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Channels; -using System.Threading.Tasks; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Provides methods for UDP communication with connected <see cref="UdpClient"/> instances. - /// </summary> - public sealed class UdpServer : Server - { - /// <summary> - /// The options that should be applied to every channel created to handle a client. - /// </summary> - private static readonly UnboundedChannelOptions clientChannelOptions = new UnboundedChannelOptions - { - SingleReader = true, - SingleWriter = true - }; - - /// <summary> - /// Holds currently connected and active clients, as well as their current received packet queues. - /// </summary> - private readonly ConcurrentDictionary<EndPoint, Channel<SerialisedPacket>> activeClients; - - /// <inheritdoc /> - protected override async Task HandleClientAsync(ClientHandlerArgs args, CancellationToken cancellationToken) - { - EndPoint clientEndPoint = args.ClientEndPoint; - Channel<SerialisedPacket> clientPacketBuffer = activeClients[clientEndPoint]; - - logger.LogMessage($"Initialised client handler for client socket: [Remote EP: {clientEndPoint}]"); - - try - { - do - { - // receive a single raw packet from the network - SerialisedPacket rawRequest = await clientPacketBuffer.Reader.ReadAsync(cancellationToken); - - if (rawRequest.Equals(SerialisedPacket.Null) || - rawRequest.Type == PacketRegistry.GetPacketId<DisconnectPacket>()) - { - logger.LogMessage( - $"Received a disconnect packet from client socket: [Remote EP: {clientEndPoint}]"); - break; - } - - IRequestPacket? requestPacket = DeserialiseRequestPacket(rawRequest.Type, in rawRequest); - Type requestPacketType = PacketRegistry.GetPacketType(rawRequest.Type); - - // the request packet is only null if no packet handler was registered for it - if (requestPacket == default) continue; - - logger.LogMessage($"Received {rawRequest.Contents.Length} bytes from {clientEndPoint}"); - - logger.LogMessage($"Received request: {Encoding.UTF8.GetString(rawRequest.Contents.Span)}"); - - IResponsePacket<IRequestPacket>? responsePacket = - HandleRequestPacket(rawRequest.Type, requestPacket, clientEndPoint); - - // the response packet is only null if the given request packet was registered as a 'simple' request packet - if (responsePacket == default) continue; - - Type? responsePacketType = - PacketRegistry.GetResponsePacketType(requestPacketType); - - if (responsePacketType == default) - { - logger.LogError( - $"Response packet type for request packet of type {requestPacketType} is null"); - continue; - } - - SerialisedPacket rawResponse = SerialisedPacket.From(responsePacket); - // uint responsePacketTypeId = PacketRegistry.GetPacketId(responsePacketType); - // responsePacket.BeforeSerialisation(); - // SerialisedPacket rawResponse = new SerialisedPacket(responsePacket.Serialise(), responsePacketTypeId); - - // echo back the processed raw response to the network - bool sentCorrectly = false; //await DoSendPacketToAsync(socket, clientEndPoint, rawResponse, SocketFlags.None,NetworkOperationTimeout, cancellationToken); - - if (!sentCorrectly) - { - logger.LogWarning( - $"Could not send response back to client socket: [Remote EP: {clientEndPoint}]"); - } - } while (true); - } - finally - { - logger.LogMessage($"Stopping client handler for client socket: [Remote EP: {clientEndPoint}]"); - - if (activeClients.TryRemove(clientEndPoint, out Channel<SerialisedPacket> packetChannel)) - { - packetChannel.Writer.Complete(); - logger.LogMessage( - $"Shutting down packet channel for client socket: [Remote EP: {clientEndPoint}]"); - } - else - { - logger.LogMessage( - $"Couldn't shut down packet channel for client socket: [Remote EP: {clientEndPoint}]"); - } - } - } - - /// <inheritdoc /> - public UdpServer(TimeSpan networkOperationTimeout) : base(SocketType.Dgram, ProtocolType.Udp, networkOperationTimeout) - { - activeClients = new ConcurrentDictionary<EndPoint, Channel<SerialisedPacket>>(); - } - - /// <inheritdoc /> - public UdpServer() : this(DefaultNetworkOperationTimeout) - { - } - - /// <inheritdoc /> - public override async Task RunAsync(EndPoint localEndPoint) - { - bool bound = await TryBindAsync(localEndPoint, Timeout.InfiniteTimeSpan); - - if (!bound) - { - logger.LogError("Server socket was not bound successfully, shutting down server."); - return; - } - - OnServerStarted(); - runServer = true; - - while (runServer) - { - EndPoint nullEndPoint = new IPEndPoint(IPAddress.Any, 0); - /* - //(SerialisedPacket request, EndPoint remoteEndPoint) = await DoReceivePacketFromAsync(socket, nullEndPoint, SocketFlags.None, Timeout.InfiniteTimeSpan, serverShutdownCancellationToken); - //EndPoint clientEndPoint = remoteEndPoint; - - if (request.Equals(SerialisedPacket.Null)) - { - continue; - } - - if (!activeClients.ContainsKey(clientEndPoint)) - { - ClientHandlerArgs args = ClientHandlerArgs.ForUdpClientHandler(in clientEndPoint); - - activeClients.TryAdd(clientEndPoint, Channel.CreateUnbounded<SerialisedPacket>(clientChannelOptions)); - - await Task.Factory.StartNew(DoHandleClientAsync, args, serverShutdownCancellationToken, - TaskCreationOptions.LongRunning, TaskScheduler.Default); - } - */ - - //await activeClients[clientEndPoint].Writer.WriteAsync(request); - } - - OnServerStopped(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Deprecated/UdpSocketOptions.cs b/NetSharp/NetSharp/Deprecated/UdpSocketOptions.cs @@ -1,36 +0,0 @@ -using System.Net.Sockets; - -namespace NetSharp.Deprecated -{ - /// <summary> - /// Allows for manipulation of UDP socket options. - /// </summary> - public sealed class UdpSocketOptions : SocketOptions - { - /// <inheritdoc /> - public UdpSocketOptions(ref Socket socket) : base(ref socket) - { - } - - /// <inheritdoc /> - public override int HopLimit - { - get { return (int)managedSocket.GetSocketOption(SocketOptionLevel.Udp, SocketOptionName.HopLimit); } - set { managedSocket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.HopLimit, value); } - } - - /// <inheritdoc /> - public override bool IsRoutingEnabled - { - get { return !(bool)managedSocket.GetSocketOption(SocketOptionLevel.Udp, SocketOptionName.DontRoute); } - set { managedSocket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.DontRoute, !value); } - } - - /// <inheritdoc /> - public override bool UseLoopback - { - get { return (bool)managedSocket.GetSocketOption(SocketOptionLevel.Udp, SocketOptionName.UseLoopback); } - set { managedSocket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.UseLoopback, value); } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/NetSharp.xml b/NetSharp/NetSharp/NetSharp.xml @@ -4,2138 +4,23 @@ <name>NetSharp</name> </assembly> <members> - <member name="T:NetSharp.Deprecated.Builtin.ConnectPacket"> - <summary> - A simple connection request packet for the UDP protocol. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.ConnectPacket.AfterDeserialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.ConnectPacket.BeforeSerialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.ConnectPacket.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.ConnectPacket.Serialise"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.Builtin.ConnectResponsePacket"> - <summary> - A response packet for the <see cref="T:NetSharp.Deprecated.Builtin.ConnectPacket"/>. - </summary> - </member> - <member name="P:NetSharp.Deprecated.Builtin.ConnectResponsePacket.RequestPacket"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.ConnectResponsePacket.AfterDeserialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.ConnectResponsePacket.BeforeSerialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.ConnectResponsePacket.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.ConnectResponsePacket.Serialise"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.Builtin.DataPacket"> - <summary> - A simple data transfer packet, that allows for the transmission of an arbitrary number of frames. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Builtin.DataPacket.RequestBuffer"> - <summary> - The data that should be transferred across the network. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataPacket.#ctor"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Builtin.DataPacket"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataPacket.#ctor(System.Memory{System.Byte})"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Builtin.DataPacket"/> class. - </summary> - <param name="buffer">The data that this request packet should contain.</param> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataPacket.AfterDeserialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataPacket.BeforeSerialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataPacket.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataPacket.Serialise"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.Builtin.DataResponsePacket"> - <summary> - A response packet for the <see cref="T:NetSharp.Deprecated.Builtin.DataPacket"/>. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Builtin.DataResponsePacket.ResponseBuffer"> - <summary> - The data that should be transferred across the network. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataResponsePacket.#ctor"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Builtin.DataResponsePacket"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataResponsePacket.#ctor(System.Memory{System.Byte})"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Builtin.DataResponsePacket"/> class. - </summary> - <param name="buffer">The data that this response packet should contain.</param> - </member> - <member name="P:NetSharp.Deprecated.Builtin.DataResponsePacket.RequestPacket"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataResponsePacket.AfterDeserialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataResponsePacket.BeforeSerialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataResponsePacket.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DataResponsePacket.Serialise"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.Builtin.DisconnectPacket"> - <summary> - A simple disconnect packet for the UDP protocol. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DisconnectPacket.AfterDeserialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DisconnectPacket.BeforeSerialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DisconnectPacket.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.DisconnectPacket.Serialise"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.Builtin.PingPacket"> - <summary> - A simple ping request packet for heartbeat monitoring and RTT measurement. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.PingPacket.AfterDeserialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.PingPacket.BeforeSerialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.PingPacket.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.PingPacket.Serialise"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.Builtin.PingResponsePacket"> - <summary> - A response packet for the <see cref="T:NetSharp.Deprecated.Builtin.PingPacket"/>. - </summary> - </member> - <member name="P:NetSharp.Deprecated.Builtin.PingResponsePacket.RequestPacket"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.PingResponsePacket.AfterDeserialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.PingResponsePacket.BeforeSerialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.PingResponsePacket.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.PingResponsePacket.Serialise"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.Builtin.SimpleDataPacket"> - <summary> - A simple one-time-use data transfer packet, that allows for the transmission of an arbitrary number of frames. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Builtin.SimpleDataPacket.RequestBuffer"> - <summary> - The data that should be transferred across the network. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.SimpleDataPacket.#ctor"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Builtin.SimpleDataPacket"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Builtin.SimpleDataPacket.#ctor(System.Memory{System.Byte})"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Builtin.SimpleDataPacket"/> class. - </summary> - <param name="buffer">The data that this request packet should contain.</param> - </member> - <member name="M:NetSharp.Deprecated.Builtin.SimpleDataPacket.AfterDeserialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.SimpleDataPacket.BeforeSerialisation"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.SimpleDataPacket.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Builtin.SimpleDataPacket.Serialise"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.Client"> - <summary> - Provides methods for connecting to and talking with a <see cref="T:NetSharp.Deprecated.IServer"/> instance. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Client.#ctor"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Client"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Client.Finalize"> - <summary> - Destroys an instance of the <see cref="T:NetSharp.Deprecated.Client"/> class. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Client.socket"> - <summary> - The <see cref="T:System.Net.Sockets.Socket"/> underlying the connection. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Client.socketOptions"> - <summary> - Backing field for the <see cref="P:NetSharp.Deprecated.Client.SocketOptions"/> property. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Client.remoteEndPoint"> - <summary> - The remote endpoint with which this client communicates. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Client.#ctor(System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Client"/> class. - </summary> - <param name="socketType">The socket type for the underlying socket.</param> - <param name="protocolType">The protocol type for the underlying socket.</param> - <param name="socketManager">The <see cref="!:Utils.Socket_Options.SocketOptions"/> manager to use.</param> - </member> - <member name="M:NetSharp.Deprecated.Client.Dispose(System.Boolean)"> - <summary> - Disposes of this <see cref="T:NetSharp.Deprecated.Client"/> instance. - </summary> - <param name="disposing">Whether this instance is being disposed.</param> - </member> - <member name="M:NetSharp.Deprecated.Client.OnConnected(System.Net.EndPoint)"> - <summary> - Invokes the <see cref="E:NetSharp.Deprecated.Client.Connected"/> event. - </summary> - <param name="endPoint">The remote endpoint with which a connection was made.</param> - </member> - <member name="M:NetSharp.Deprecated.Client.OnDisconnected(System.Net.EndPoint)"> - <summary> - Invokes the <see cref="E:NetSharp.Deprecated.Client.Disconnected"/> event. - </summary> - <param name="endPoint">The remote endpoint with which a connection was lost.</param> - </member> - <member name="E:NetSharp.Deprecated.Client.Connected"> - <inheritdoc /> - </member> - <member name="E:NetSharp.Deprecated.Client.Disconnected"> - <inheritdoc /> - </member> - <member name="P:NetSharp.Deprecated.Client.SocketOptions"> - <summary> - The configured socket options for the underlying connection. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Client.Disconnect"> - <summary> - Disconnects the client from the remote endpoint. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Client.SendBytesAsync(System.Byte[],System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Client.SendBytesWithResponseAsync(System.Byte[],System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Client.SendComplexAsync``2(``0,System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Client.SendSimpleAsync``1(``0,System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Client.TryBindAsync(System.Net.IPAddress,System.Nullable{System.Int32},System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Client.TryConnectAsync(System.Net.IPAddress,System.Int32,System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.ClientExtensions"> - <summary> - Provides additional methods and functionality to the <see cref="T:NetSharp.Deprecated.Client"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendBytes(NetSharp.Deprecated.Client,System.Byte[])"> - <summary> - Sends the given byte buffer to the connected remote endpoint. Blocks until the bytes are all sent, and does - not timeout. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendBytes(NetSharp.Deprecated.Client,System.Byte[],System.TimeSpan)"> - <summary> - Sends the given byte buffer to the connected remote endpoint. Blocks until the bytes are all sent, whilst - observing a timeout of the given length. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - <param name="timeout">The timeout after which to cancel the transmission attempt.</param> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendBytesAsync(NetSharp.Deprecated.Client,System.Byte[])"> - <summary> - Sends the given byte buffer to the connected remote endpoint asynchronously. Does not block, and does not - timeout. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendBytesWithResponse(NetSharp.Deprecated.Client,System.Byte[])"> - <summary> - Sends the given byte buffer to the connected remote endpoint and waits for the response. Blocks until the - bytes are all sent and the response has been received, and does not timeout. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - <returns>The byte buffer that was received as a response.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendBytesWithResponse(NetSharp.Deprecated.Client,System.Byte[],System.TimeSpan)"> - <summary> - Sends the given byte buffer to the connected remote endpoint and waits for the response. Blocks until the - bytes are all sent and the response has been received, whilst observing a timeout of the given length. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - <param name="timeout">The timeout after which to cancel the transmission attempt.</param> - <returns>The byte buffer that was received as a response.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendBytesWithResponseAsync(NetSharp.Deprecated.Client,System.Byte[])"> - <summary> - Sends the given byte buffer to the connected remote endpoint and waits for the response asynchronously. - Does not block, and does not timeout. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - <returns>The byte buffer received as a response to the sent buffer.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendComplex``2(NetSharp.Deprecated.Client,``0)"> - <summary> - Sends the given request and listens for a response of the given type. Blocks until the response is received. - Does not timeout. - </summary> - <typeparam name="Req">The type of request packet to send.</typeparam> - <typeparam name="Rep">The type of response packet to receive.</typeparam> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="request">The request packet to send.</param> - <returns>The received instance.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendComplex``2(NetSharp.Deprecated.Client,``0,System.TimeSpan)"> - <summary> - Sends the given request and listens for a response of the given type. Blocks until the response is received. - Cancels the operation if the given timeout is exceeded. - </summary> - <typeparam name="Req">The type of request packet to send.</typeparam> - <typeparam name="Rep">The type of response packet to receive.</typeparam> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="request">The request packet to send.</param> - <param name="timeout">The timeout for which to wait for the operation to complete.</param> - <returns>The received instance.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendComplexAsync``2(NetSharp.Deprecated.Client,``0)"> - <summary> - Sends the given request and listens for a response of the given type asynchronously. Does not block. Does not timeout. - </summary> - <typeparam name="Req">The type of request packet to send.</typeparam> - <typeparam name="Rep">The type of response packet to receive.</typeparam> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="request">The request packet to send.</param> - <returns>The received instance.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendSimple``1(NetSharp.Deprecated.Client,``0)"> - <summary> - Sends the given request without listening for a response, blocking until it is sent. Does not timeout. - </summary> - <typeparam name="Req">The type of request packet to send.</typeparam> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="request">The request packet to send.</param> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendSimple``1(NetSharp.Deprecated.Client,``0,System.TimeSpan)"> - <summary> - Sends the given request without listening for a response, blocking until it is sent. - Cancels the operation if the given timeout is exceeded. - </summary> - <typeparam name="Req">The type of request packet to send.</typeparam> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="request">The request packet to send.</param> - <param name="timeout">The timeout for which to wait for the operation to complete.</param> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.SendSimpleAsync``1(NetSharp.Deprecated.Client,``0)"> - <summary> - Sends the given request asynchronously without listening for a response, not blocking until it is sent. - Does not timeout. - </summary> - <typeparam name="Req">The type of request packet to send.</typeparam> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="request">The request packet to send.</param> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.TryBind(NetSharp.Deprecated.Client,System.Net.IPAddress,System.Nullable{System.Int32})"> - <summary> - Attempts to synchronously bind the underlying socket to the given local address and port. Blocks. Does not timeout. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="localAddress">The local IP address to bind to. Null if any IP address will suffice.</param> - <param name="localPort">The local port to bind to. Null if any port will suffice.</param> - <returns>Whether the binding was successful or not.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.TryBind(NetSharp.Deprecated.Client,System.Net.IPAddress,System.Nullable{System.Int32},System.TimeSpan)"> - <summary> - Attempts to synchronously bind the underlying socket to the given local address and port. Blocks. - If the timeout is exceeded the binding attempt is aborted and the method returns false. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="localAddress">The local IP address to bind to. Null if any IP address will suffice.</param> - <param name="localPort">The local port to bind to. Null if any port will suffice.</param> - <param name="timeout">The timeout within which to attempt the binding.</param> - <returns>Whether the binding was successful or not.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.TryBindAsync(NetSharp.Deprecated.Client,System.Net.IPAddress,System.Nullable{System.Int32})"> - <summary> - Attempts to asynchronously bind the underlying socket to the given local address and port. Does not block. - Does not timeout. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="localAddress">The local IP address to bind to. Null if any IP address will suffice.</param> - <param name="localPort">The local port to bind to. Null if any port will suffice.</param> - <returns>Whether the binding was successful or not.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.TryConnect(NetSharp.Deprecated.Client,System.Net.IPAddress,System.Int32)"> - <summary> - Attempts to connect to the remote <see cref="T:NetSharp.Deprecated.Server"/> at the given <see cref="T:System.Net.IPAddress"/> and over the - given port. Does not timeout. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="remoteAddress">The remote IP address to connect to.</param> - <param name="remotePort">The remote port to connect over.</param> - <returns>Whether the connection was successful or not.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.TryConnect(NetSharp.Deprecated.Client,System.Net.IPAddress,System.Int32,System.TimeSpan)"> - <summary> - Attempts to connect to the remote <see cref="T:NetSharp.Deprecated.Server"/> at the given <see cref="T:System.Net.IPAddress"/> and over the - given port. If the timeout is exceeded the connection attempt is aborted and the method returns false. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="remoteAddress">The remote IP address to connect to.</param> - <param name="remotePort">The remote port to connect over.</param> - <param name="timeout">The timeout within which to attempt the connection.</param> - <returns>Whether the connection was successful or not.</returns> - </member> - <member name="M:NetSharp.Deprecated.ClientExtensions.TryConnectAsync(NetSharp.Deprecated.Client,System.Net.IPAddress,System.Int32)"> - <summary> - Attempts to connect asynchronously to the remote <see cref="T:NetSharp.Deprecated.Server"/> at the given <see cref="T:System.Net.IPAddress"/> - and over the given port. Does not timeout. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="remoteAddress">The remote IP address to connect to.</param> - <param name="remotePort">The remote port to connect over.</param> - <returns>Whether the connection was successful or not.</returns> - </member> - <member name="T:NetSharp.Deprecated.Connection"> - <summary> - Encapsulates a connection capable of receiving packets and responding to them with registered packet handlers. - </summary> - <summary> - Implements low-level network access on top of which the rest of the connection is built upon. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Connection.incomingPacketPipeline"> - <summary> - Pipeline to convert incoming byte buffers to <see cref="T:NetSharp.Deprecated.NetworkPacket"/> instances. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Connection.loggerLockObject"> - <summary> - Lock synchronisation object for the <see cref="F:NetSharp.Deprecated.Connection.logger"/> variable. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Connection.outgoingPacketPipeline"> - <summary> - Pipeline to convert outgoing <see cref="T:NetSharp.Deprecated.NetworkPacket"/> instances to a byte buffer for sending. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Connection.ServerShutdownToken"> - <summary> - Cancellation token which allows observing the shutdown of the server. It is set when <see cref="M:NetSharp.Deprecated.Connection.ShutdownServer"/> is called. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Connection.logger"> - <summary> - A logger object allowing for writing debug messages to an output stream. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Connection.Finalize"> - <summary> - Destroys a <see cref="T:NetSharp.Deprecated.Connection"/> class instance, freeing all managed resources. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Connection.RunServerAsync"> - <summary> - Makes the connection listen for incoming request packets, and handle them according to registered packet handler delegates. - This work can be cancelled by calling <see cref="M:NetSharp.Deprecated.Connection.ShutdownServer"/>. - </summary> - <returns>The task representing the connection work.</returns> - </member> - <member name="M:NetSharp.Deprecated.Connection.ShutdownServer"> - <summary> - Shuts down the connection, and releases managed and unmanaged resources. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Connection.AnyRemoteEndPoint"> - <summary> - Represents any remote endpoint for datagram operations. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Connection.Dispose(System.Boolean)"> - <summary> - Disposes of the managed and unmanaged resources held by this instance. - </summary> - <param name="disposing">Whether this method is called by <see cref="M:NetSharp.Deprecated.Connection.Dispose"/> or by the finaliser.</param> - </member> - <member name="M:NetSharp.Deprecated.Connection.DoAcceptAsync(System.Net.Sockets.Socket,System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket accept operation. - </summary> - <param name="serverSocket">The socket which should be used to accept an incoming connection attempt.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - <returns>The accepted socket.</returns> - </member> - <member name="M:NetSharp.Deprecated.Connection.DoConnectAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket connect operation. - </summary> - <param name="socket">The socket which should asynchronously connect to the remote endpoint.</param> - <param name="remoteEndPoint">The remote endpoint to which the socket should connect.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - </member> - <member name="M:NetSharp.Deprecated.Connection.DoDisconnectAsync(System.Net.Sockets.Socket,System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket disconnect operation. - </summary> - <param name="connectedSocket">The socket which should asynchronously disconnect from its remote endpoint.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - </member> - <member name="M:NetSharp.Deprecated.Connection.DoReceiveFromAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Net.Sockets.SocketFlags,System.Memory{System.Byte},System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket receive operation. - </summary> - <param name="listenerSocket">The socket which should receive data from the remote endpoint.</param> - <param name="remoteEndPoint">The remove endpoint from which data should be received.</param> - <param name="socketFlags">The socket flags associated with the receive operation.</param> - <param name="inputBuffer">The memory buffer into which received data will be stored.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - <returns>The result of the receive operation from the remote endpoint.</returns> - </member> - <member name="M:NetSharp.Deprecated.Connection.DoSendToAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Net.Sockets.SocketFlags,System.Memory{System.Byte},System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket send operation. - </summary> - <param name="transmitterSocket">The socket which should send the data to the remote endpoint.</param> - <param name="remoteEndPoint">The remote endpoint to which data should be written.</param> - <param name="socketFlags">The socket flags associated with the send operation.</param> - <param name="outputBuffer">The data buffer which should be sent.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - <returns>The result of the send operation to the remote endpoint.</returns> - </member> - <member name="F:NetSharp.Deprecated.Connection.MaximumConnectionBacklog"> - <summary> - The maximum number of stream connection that will be accepted. - </summary> - TODO change this to a configurable builder option - </member> - <member name="F:NetSharp.Deprecated.Connection.MaximumPacketBacklog"> - <summary> - The maximum number of packets that will be stored before older packets start to be dropped. - </summary> - TODO change this to a configurable builder option - </member> - <member name="M:NetSharp.Deprecated.Connection.Dispose"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Connection.SetLoggingStream(System.IO.Stream,NetSharp.Deprecated.LogLevel)"> - <summary> - Configures the logger to log messages to the given stream (or to <see cref="F:System.IO.Stream.Null"/> if <c>null</c>) and - to only log messages that are of severity <paramref name="minimumLoggedSeverity"/> or higher. - </summary> - <param name="loggingStream">The stream to which messages will be logged.</param> - <param name="minimumLoggedSeverity">The minimum severity a message must be to be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Connection.TryBindAsync(System.Net.EndPoint,System.TimeSpan)"> - <summary> - Attempts to asynchronously bind the underlying socket to the given local endpoint. Does not block. - If the timeout is exceeded the binding attempt is aborted and the method returns false. - </summary> - <param name="localEndPoint">The local endpoint to bind to.</param> - <param name="timeout">The timeout within which to attempt the binding.</param> - <returns>Whether the binding was successful or not.</returns> - </member> - <member name="T:NetSharp.Deprecated.ConnectionBuilder"> - <summary> - Allows for configuring and subsequently building a <see cref="T:NetSharp.Deprecated.Connection"/> instance. - </summary> - </member> - <member name="P:NetSharp.Deprecated.ConnectionBuilder.IncomingPacketPipelineStageCount"> - <summary> - The number of stages in the currently configured incoming packet pipeline. - </summary> - </member> - <member name="P:NetSharp.Deprecated.ConnectionBuilder.OutgoingPacketPipelineStageCount"> - <summary> - The number of stages in the currently configured outgoing packet pipeline. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ConnectionBuilder.Build"> - <summary> - Returns a new <see cref="T:NetSharp.Deprecated.Connection"/> instance with the current configuration. - </summary> - <returns>The configured <see cref="T:NetSharp.Deprecated.Connection"/> instance.</returns> - </member> - <member name="M:NetSharp.Deprecated.ConnectionBuilder.WithIncomingPipelineStage(System.Func{System.Memory{System.Byte},System.Memory{System.Byte}}@,System.Int32)"> - <summary> - Adds an extra pipeline stage to the currently configured incoming packet pipeline, at the given index. - </summary> - <param name="transform"> - The transformation that should be applied when a packet passes through the pipeline. - </param> - <param name="index">The position in the pipeline at which to place the transform.</param> - <returns>The builder instance for further configuration.</returns> - </member> - <member name="M:NetSharp.Deprecated.ConnectionBuilder.WithLogging(NetSharp.Deprecated.ConnectionBuilder.LoggingSettings)"> - <summary> - Sets the logging settings for the currently configured connection. - </summary> - <param name="settings">The logging settings to use.</param> - <returns>The builder instance for further configuration.</returns> - </member> - <member name="M:NetSharp.Deprecated.ConnectionBuilder.WithOutgoingPipelineStage(System.Func{System.Memory{System.Byte},System.Memory{System.Byte}}@,System.Int32)"> - <summary> - Adds an extra pipeline stage to the currently configured outgoing packet pipeline, at the given index. - </summary> - <param name="transform"> - The transformation that should be applied when a packet passes through the pipeline. - </param> - <param name="index">The position in the pipeline at which to place the transform.</param> - <returns>The builder instance for further configuration.</returns> - </member> - <member name="M:NetSharp.Deprecated.ConnectionBuilder.WithPooling(NetSharp.Deprecated.ConnectionBuilder.PoolingSettings)"> - <summary> - Sets the pooling settings for the currently configured connection. - </summary> - <param name="settings">The pooling settings to use.</param> - <returns>The builder instance for further configuration.</returns> - </member> - <member name="T:NetSharp.Deprecated.ConnectionBuilder.LoggingSettings"> - <summary> - Holds settings for configuring a connection's logging. - </summary> - </member> - <member name="F:NetSharp.Deprecated.ConnectionBuilder.LoggingSettings.LoggingStream"> - <summary> - The stream to which messages will be logged. - </summary> - </member> - <member name="F:NetSharp.Deprecated.ConnectionBuilder.LoggingSettings.MinimumLevel"> - <summary> - The minimum severity that a log message must have to be recorded. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ConnectionBuilder.LoggingSettings.#ctor(System.IO.Stream,NetSharp.Deprecated.LogLevel)"> - <summary> - Initialises a new instance of the <see cref="F:NetSharp.Deprecated.ConnectionBuilder.LoggingSettings.LoggingStream"/> struct. - </summary> - <param name="stream">The stream to which messages will be logged..</param> - <param name="minimumLevel">The minimum severity that a log message must have to be recorded.</param> - </member> - <member name="T:NetSharp.Deprecated.ConnectionBuilder.PoolingSettings"> - <summary> - Holds settings for configuring a connection's buffer pooling. - </summary> - </member> - <member name="F:NetSharp.Deprecated.ConnectionBuilder.PoolingSettings.ObjectPoolSize"> - <summary> - The number of objects that will be held in the object pools. - </summary> - </member> - <member name="F:NetSharp.Deprecated.ConnectionBuilder.PoolingSettings.PreallocateBuffers"> - <summary> - Whether the buffers for receiving messages should be preallocated. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ConnectionBuilder.PoolingSettings.#ctor(System.Int32,System.Boolean)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.ConnectionBuilder.PoolingSettings"/> struct. - </summary> - <param name="poolSize">The number of objects that will be held in the object pools.</param> - <param name="preallocateBuffers">Whether the buffers for receiving messages should be preallocated.</param> - </member> - <member name="T:NetSharp.Deprecated.ConnectionBuilderExtensions"> - <summary> - Provides additional methods and functionality to the <see cref="T:NetSharp.Deprecated.ConnectionBuilder"/> class. - </summary> - </member> - <member name="T:NetSharp.Deprecated.ConnectionExtensions"> - <summary> - Provides additional methods and functionality to the <see cref="T:NetSharp.Deprecated.Connection"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ConnectionExtensions.TryBind(NetSharp.Deprecated.Connection,System.Net.EndPoint,System.TimeSpan)"> - <summary> - Attempts to synchronously bind the underlying socket to the given local endpoint. Blocks. - If the timeout is exceeded the binding attempt is aborted and the method returns false. - </summary> - <param name="localEndPoint">The local endpoint to bind to.</param> - <param name="timeout">The timeout within which to attempt the binding.</param> - <returns>Whether the binding was successful or not.</returns> - </member> - <member name="T:NetSharp.Deprecated.Constants"> - <summary> - Holds internal default configurations and constants. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Constants.DefaultPort"> - <summary> - The default port over which a connection is made. - </summary> - </member> - <member name="T:NetSharp.Deprecated.DefaultSocketOptions"> - <summary> - Allows for manipulation of socket options. - </summary> - </member> - <member name="M:NetSharp.Deprecated.DefaultSocketOptions.#ctor(System.Net.Sockets.Socket@)"> - <inheritdoc /> - </member> - <member name="P:NetSharp.Deprecated.DefaultSocketOptions.HopLimit"> - <inheritdoc /> - <exception cref="T:System.NotSupportedException"> - This property is not supported when using the default socket option manager. - </exception> - </member> - <member name="P:NetSharp.Deprecated.DefaultSocketOptions.IsRoutingEnabled"> - <inheritdoc /> - <exception cref="T:System.NotSupportedException"> - This property is not supported when using the default socket option manager. - </exception> - </member> - <member name="P:NetSharp.Deprecated.DefaultSocketOptions.UseLoopback"> - <inheritdoc /> - <exception cref="T:System.NotSupportedException"> - This property is not supported when using the default socket option manager. - </exception> - </member> - <member name="T:NetSharp.Deprecated.IClient"> - <summary> - Describes a client capable of asynchronous communication with an <see cref="T:NetSharp.Deprecated.IServer"/> connection. - </summary> - </member> - <member name="E:NetSharp.Deprecated.IClient.Connected"> - <summary> - Signifies that a connection with the remote endpoint has been made. - </summary> - </member> - <member name="E:NetSharp.Deprecated.IClient.Disconnected"> - <summary> - Signifies that the connection with the remote endpoint was severed. - </summary> - </member> - <member name="M:NetSharp.Deprecated.IClient.SendBytesAsync(System.Byte[],System.TimeSpan)"> - <summary> - Sends the given byte buffer to the connected remote endpoint asynchronously. Does not block, and observes - a timeout of the given length. - timeout. - </summary> - <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - <param name="timeout">The timeout after which to cancel the transmission attempt.</param> - <returns>Whether the transmission attempt was successful.</returns> - </member> - <member name="M:NetSharp.Deprecated.IClient.SendBytesWithResponseAsync(System.Byte[],System.TimeSpan)"> - <summary> - Sends the given byte buffer to the connected remote endpoint and waits for the response asynchronously. - Does not block, and observes a timeout of the given length. - timeout. - </summary> - <param name="buffer">The bytes that should be sent to the connected remote endpoint.</param> - <param name="timeout"> - The timeout after which to cancel the transmission attempt. This timeout is reused by both the 'send' and - 'receive' parts of the transmission attempt, such that the maximum timeout is equal to 2 times the given - value. - </param> - <returns>The byte buffer received as a response to the sent buffer.</returns> - </member> - <member name="M:NetSharp.Deprecated.IClient.SendComplexAsync``2(``0,System.TimeSpan)"> - <summary> - Sends the given request and listens for a response of the given type asynchronously. Does not block. - Cancels the operation if the given timeout is exceeded - </summary> - <typeparam name="Req">The type of request packet to send.</typeparam> - <typeparam name="Rep">The type of response packet to receive.</typeparam> - <param name="request">The request packet to send.</param> - <param name="timeout">The timeout for which to wait for the operation to complete.</param> - <returns>The received instance.</returns> - </member> - <member name="M:NetSharp.Deprecated.IClient.SendSimpleAsync``1(``0,System.TimeSpan)"> - <summary> - Sends the given request asynchronously without listening for a response, not blocking until it is sent. - Cancels the operation if the given timeout is exceeded. - </summary> - <typeparam name="Req">The type of request packet to send.</typeparam> - <param name="request">The request packet to send.</param> - <param name="timeout">The timeout for which to wait for the operation to complete.</param> - <returns>Whether the transmission attempt was successful.</returns> - </member> - <member name="M:NetSharp.Deprecated.IClient.TryBindAsync(System.Net.IPAddress,System.Nullable{System.Int32},System.TimeSpan)"> - <summary> - Attempts to asynchronously bind the underlying socket to the given local address and port. Does not block. - If the timeout is exceeded the binding attempt is aborted and the method returns false. - </summary> - <param name="localAddress">The local IP address to bind to. Null if any IP address will suffice.</param> - <param name="localPort">The local port to bind to. Null if any port will suffice.</param> - <param name="timeout">The timeout within which to attempt the binding.</param> - <returns>Whether the binding was successful or not.</returns> - </member> - <member name="M:NetSharp.Deprecated.IClient.TryConnectAsync(System.Net.IPAddress,System.Int32,System.TimeSpan)"> - <summary> - Attempts to connect asynchronously to the remote <see cref="T:NetSharp.Deprecated.Server"/> at the given <see cref="T:System.Net.IPAddress"/> - and over the given port. If the timeout is exceeded the connection attempt is aborted and the method returns false. - </summary> - <param name="remoteAddress">The remote IP address to connect to.</param> - <param name="remotePort">The remote port to connect over.</param> - <param name="timeout">The timeout within which to attempt the connection.</param> - <returns>Whether the connection was successful or not.</returns> - </member> - <member name="T:NetSharp.Deprecated.INetworkSerialisable"> - <summary> - Describes an object that can be serialised to be sent across the network. - </summary> - </member> - <member name="M:NetSharp.Deprecated.INetworkSerialisable.Deserialise(System.ReadOnlyMemory{System.Byte})"> - <summary> - Deserialises the object instance from a byte array. - </summary> - <param name="serialisedObject">The memory containing the serialised object instance.</param> - </member> - <member name="M:NetSharp.Deprecated.INetworkSerialisable.Serialise"> - <summary> - Serialises the object instance into a byte array. - </summary> - <returns>The memory containing the serialised object instance.</returns> - </member> - <member name="T:NetSharp.Deprecated.IPacket"> - <summary> - Describes the methods and properties that every packet - </summary> - </member> - <member name="M:NetSharp.Deprecated.IPacket.AfterDeserialisation"> - <summary> - Allows for custom fields to be converted from their serialised format, after being received from the network. - </summary> - </member> - <member name="M:NetSharp.Deprecated.IPacket.BeforeSerialisation"> - <summary> - Allows for custom fields to be converted into another format prior to being sent via the network. - </summary> - </member> - <member name="T:NetSharp.Deprecated.IPacketHandler"> - <summary> - Describes a class capable of registering and deregistering packet handlers, and capable of - handling incoming packets according to the currently registered packet handlers. - </summary> - </member> - <member name="M:NetSharp.Deprecated.IPacketHandler.TryDeregisterComplexPacketHandler``2(NetSharp.Deprecated.ComplexPacketHandler{``0,``1}@)"> - <summary> - Attempts to deregister the complex packet handler delegate for all packets of the given type. If a handler - method doesn't exist for the given packet type, <paramref name="oldHandlerDelegate"/> will be <c>default</c>. - </summary> - <typeparam name="Req">The type of request packet for which to deregister the handler delegate.</typeparam> - <typeparam name="Rep">The type of response packet that is generated by the delegate method.</typeparam> - <param name="oldHandlerDelegate">The old handler delegate method that was previously registered.</param> - <returns>Whether the packet handler delegate was successfully deregistered.</returns> - </member> - <member name="M:NetSharp.Deprecated.IPacketHandler.TryDeregisterSimplePacketHandler``1(NetSharp.Deprecated.SimplePacketHandler{``0}@)"> - <summary> - Attempts to deregister the simple packet handler delegate for all packets of the given type. If a handler - method doesn't exist for the given packet type, <paramref name="oldHandlerDelegate"/> will be <c>default</c>. - </summary> - <typeparam name="Req">The type of request packet for which to deregister the handler delegate.</typeparam> - <param name="oldHandlerDelegate">The old handler delegate method that was previously registered.</param> - <returns>Whether the packet handler delegate was successfully deregistered.</returns> - </member> - <member name="M:NetSharp.Deprecated.IPacketHandler.TryRegisterComplexPacketHandler``2(NetSharp.Deprecated.ComplexPacketHandler{``0,``1})"> - <summary> - Attempts to register a complex packet handler delegate for all packets of the given type. If a handler - method already exists for the given packet type, it will be updated and replaced with the given one. - </summary> - <typeparam name="Req">The type of request packet for which to register the handler delegate.</typeparam> - <typeparam name="Rep">The type of response packet that is generated by the delegate method.</typeparam> - <param name="handlerDelegate">The delegate method to register as the complex packet handler.</param> - <returns>Whether the packet handler delegate was successfully registered.</returns> - </member> - <member name="M:NetSharp.Deprecated.IPacketHandler.TryRegisterSimplePacketHandler``1(NetSharp.Deprecated.SimplePacketHandler{``0})"> - <summary> - Attempts to register a simple packet handler delegate for all packets of the given type. If a handler - method already exists for the given packet type, it will be updated and replaced with the given one. - </summary> - <typeparam name="Req">The type of request packet for which to register the handler delegate.</typeparam> - <param name="handlerDelegate">The delegate method to register as the simple packet handler.</param> - <returns>Whether the packet handler delegate was successfully registered.</returns> - </member> - <member name="T:NetSharp.Deprecated.IRequestPacket"> - <summary> - Describes a request packet. - </summary> - </member> - <member name="T:NetSharp.Deprecated.IResponsePacket`1"> - <summary> - Describes a response packet to a request packet. - </summary> - <typeparam name="TReq">The request packet that this type is a response to.</typeparam> - </member> - <member name="P:NetSharp.Deprecated.IResponsePacket`1.RequestPacket"> - <summary> - The request packet that was handled with this response packet. - </summary> - </member> - <member name="T:NetSharp.Deprecated.IServer"> - <summary> - Describes a server capable of asynchronously handling multiple <see cref="T:NetSharp.Deprecated.IClient"/> connections at once. - </summary> - </member> - <member name="E:NetSharp.Deprecated.IServer.ClientConnected"> - <summary> - Signifies that a connection with a remote endpoint has been made. - </summary> - </member> - <member name="E:NetSharp.Deprecated.IServer.ClientDisconnected"> - <summary> - Signifies that a connection with a remote endpoint has been lost. - </summary> - </member> - <member name="E:NetSharp.Deprecated.IServer.ServerStarted"> - <summary> - Signifies that the server was started and clients will start being accepted. - </summary> - </member> - <member name="E:NetSharp.Deprecated.IServer.ServerStopped"> - <summary> - Signifies that the server was stopped and clients will stop being accepted. - </summary> - </member> - <member name="M:NetSharp.Deprecated.IServer.RunAsync(System.Net.EndPoint)"> - <summary> - Starts the server asynchronously and starts accepting client connections. Does not block. - </summary> - <param name="localEndPoint">The local endpoint to bind to.</param> - </member> - <member name="M:NetSharp.Deprecated.IServer.Shutdown"> - <summary> - Shuts down the server. - </summary> - </member> - <member name="T:NetSharp.Deprecated.LogLevel"> - <summary> - Specifies the severity level of a log message. - </summary> - </member> - <member name="F:NetSharp.Deprecated.LogLevel.Info"> - <summary> - The logged message contains some information. Lowest severity. - </summary> - </member> - <member name="F:NetSharp.Deprecated.LogLevel.Warn"> - <summary> - The logged message contains a warning. Higher severity. - </summary> - </member> - <member name="F:NetSharp.Deprecated.LogLevel.Error"> - <summary> - The logged message contains details about an error. Higher severity. - </summary> - </member> - <member name="F:NetSharp.Deprecated.LogLevel.Exception"> - <summary> - The logged message contains details about an exception. Highest severity. - </summary> - </member> - <member name="T:NetSharp.Deprecated.Logger"> - <summary> - A simple logger capable of writing text to a stream. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Logger.loggingStream"> - <summary> - The stream to which messages will be logged. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Logger.minimumSeverity"> - <summary> - The minimum severity that log messages need to be logged to the underlying stream. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Logger.writer"> - <summary> - The text writer we will use to log messages to the underlying stream. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Logger.#ctor(System.IO.Stream,NetSharp.Deprecated.LogLevel)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Logger"/> struct. - </summary> - <param name="outputStream">The stream that the logger instance should log messages to.</param> - <param name="minimumLogSeverity">The minimum log level that will be logged to the output stream.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.Dispose"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Logger.Log(System.String,System.Exception,NetSharp.Deprecated.LogLevel)"> - <summary> - Logs a message to the underlying stream, along with the given exception and at the given severity. - </summary> - <param name="message">The message that should be logged.</param> - <param name="exception">The exception that occurred (if any).</param> - <param name="severity">The severity of the message that is being logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogAsync(System.String,System.Exception,NetSharp.Deprecated.LogLevel)"> - <summary> - Logs a message asynchronously to the underlying stream, along with the given exception and at the given severity. - </summary> - <param name="message">The message that should be logged.</param> - <param name="exception">The exception that occurred (if any).</param> - <param name="severity">The severity of the message that is being logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogError(System.String)"> - <summary> - Logs an error to the underlying stream, with severity <see cref="F:NetSharp.Deprecated.LogLevel.Info"/>. - </summary> - <param name="message">The error that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogErrorAsync(System.String)"> - <summary> - Logs an error to the underlying stream asynchronously, with severity <see cref="F:NetSharp.Deprecated.LogLevel.Error"/>. - </summary> - <param name="message">The error that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogException(System.Exception)"> - <summary> - Logs an exception to the underlying stream, with severity <see cref="F:NetSharp.Deprecated.LogLevel.Exception"/>. - </summary> - <param name="exception">The exception that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogException(System.String,System.Exception)"> - <summary> - Logs an exception to the underlying stream, along with a short debug message, with severity - <see cref="F:NetSharp.Deprecated.LogLevel.Exception"/>. - </summary> - <param name="message">The debug message that should be logged with the exception.</param> - <param name="exception">The exception that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogExceptionAsync(System.Exception)"> - <summary> - Logs an exception to the underlying stream asynchronously, with severity <see cref="F:NetSharp.Deprecated.LogLevel.Exception"/>. - </summary> - <param name="exception">The exception that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogExceptionAsync(System.String,System.Exception)"> - <summary> - Logs an exception to the underlying stream asynchronously, along with a short debug message, with severity - <see cref="F:NetSharp.Deprecated.LogLevel.Exception"/>. - </summary> - <param name="message">The debug message that should be logged with the exception.</param> - <param name="exception">The exception that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogMessage(System.String)"> - <summary> - Logs a message to the underlying stream, with severity <see cref="F:NetSharp.Deprecated.LogLevel.Info"/>. - </summary> - <param name="message">The message that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogMessageAsync(System.String)"> - <summary> - Logs a message to the underlying stream asynchronously, with severity <see cref="F:NetSharp.Deprecated.LogLevel.Info"/>. - </summary> - <param name="message">The message that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogWarning(System.String)"> - <summary> - Logs a warning to the underlying stream, with severity <see cref="F:NetSharp.Deprecated.LogLevel.Info"/>. - </summary> - <param name="message">The warning that should be logged.</param> - </member> - <member name="M:NetSharp.Deprecated.Logger.LogWarningAsync(System.String)"> - <summary> - Logs a warning to the underlying stream asynchronously, with severity <see cref="F:NetSharp.Deprecated.LogLevel.Warn"/>. - </summary> - <param name="message">The warning that should be logged.</param> - </member> - <member name="T:NetSharp.Deprecated.NetworkErrorCode"> - <summary> - Enumerates the possible error codes for network operations, being held in the packet. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkErrorCode.Ok"> - <summary> - Signifies that there was no error during transmission. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkErrorCode.Error"> - <summary> - A generic error occurred during packet transmission. - </summary> - </member> - <member name="T:NetSharp.Deprecated.NetworkPacket"> - <summary> - Represents a low-level packet that is transmitted over the network. - </summary> - </member> - <member name="M:NetSharp.Deprecated.NetworkPacket.#ctor(System.ReadOnlyMemory{System.Byte},NetSharp.Deprecated.NetworkPacketHeader,NetSharp.Deprecated.NetworkPacketFooter)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.NetworkPacket"/> struct. - </summary> - <param name="data">The data that should be transmitted in the packet.</param> - <param name="header">The header for the packet.</param> - <param name="footer">The footer for the packet.</param> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacket.DataSegmentSize"> - <summary> - The number of bytes allocated in each packet for user data. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacket.FooterSize"> - <summary> - The number of bytes taken up in each packet by its footer. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacket.HeaderSize"> - <summary> - The number of bytes taken up in each packet by its header. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacket.PacketSize"> - <summary> - The size of each packet, including its header, footer, and data segment. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacket.DataBuffer"> - <summary> - The data held in this packet. - </summary> - </member> - <member name="M:NetSharp.Deprecated.NetworkPacket.#ctor(System.ReadOnlyMemory{System.Byte},System.Int32,System.UInt32,NetSharp.Deprecated.NetworkErrorCode,System.Boolean)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.NetworkPacket"/> struct. - </summary> - <param name="data">The data that should be transmitted in the packet.</param> - <param name="dataLength">The number of bytes that are held in the given data buffer.</param> - <param name="type">The packet type.</param> - <param name="errorCode">The error code associated with this transmission.</param> - <param name="hasSucceedingPacket">Whether this packet has a succeeding packet in the packet chain.</param> - </member> - <member name="M:NetSharp.Deprecated.NetworkPacket.Deserialise(System.Memory{System.Byte})"> - <summary> - Deserialises the given buffer into a packet instance. - </summary> - <param name="buffer">The byte buffer to serialise.</param> - <returns>The deserialised packet instance.</returns> - </member> - <member name="M:NetSharp.Deprecated.NetworkPacket.Serialise(NetSharp.Deprecated.NetworkPacket)"> - <summary> - Serialises the given packet instance to a new byte buffer. - </summary> - <param name="instance">The packet instance to serialise.</param> - <returns>The byte buffer that represents the packet instance.</returns> - </member> - <member name="M:NetSharp.Deprecated.NetworkPacket.SerialiseToBuffer(System.Memory{System.Byte},NetSharp.Deprecated.NetworkPacket)"> - <summary> - Serialises the given packet instance into the given byte buffer. - </summary> - <param name="buffer"> - The buffer to which the instance should be serialised. Must be at least of size <see cref="F:NetSharp.Deprecated.NetworkPacket.PacketSize"/>. - </param> - <param name="instance">The packet instance to serialise.</param> - <exception cref="T:System.ArgumentException">Thrown if the given buffer is too small.</exception> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacketFooter.Size"> - <summary> - The number of bytes taken up by a packet footer. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacketHeader.Size"> - <summary> - The number of bytes taken up by a packet header. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacketHeader.DataLength"> - <summary> - The number of bytes of data held in the packet. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacketHeader.ErrorCode"> - <summary> - The error code for this packet. - </summary> - </member> - <member name="F:NetSharp.Deprecated.NetworkPacketHeader.Type"> - <summary> - The packet type. - </summary> - </member> - <member name="T:NetSharp.Deprecated.PacketPipeline`3"> - <summary> - Represents a pipeline of transformations that packets must undergo. - </summary> - <typeparam name="TInput">The type of packet the pipeline receives.</typeparam> - <typeparam name="TIntermediate">The type of packet the pipeline internally handles.</typeparam> - <typeparam name="TOutput">The type of packet the pipeline outputs.</typeparam> - </member> - <member name="M:NetSharp.Deprecated.PacketPipeline`3.ProcessPacket(`0)"> - <summary> - Passes the given packet through the pipeline. - </summary> - <param name="inputPacket">The incoming packet.</param> - <returns>The outgoing transformed packet.</returns> - </member> - <member name="T:NetSharp.Deprecated.PacketPipelineStage`2"> - <summary> - Represents a single transformation applied to a packet traveling through the pipeline. - </summary> - <typeparam name="TInput">The type the transformation takes as input.</typeparam> - <typeparam name="TOutput">The type the transformation produces as output.</typeparam> - </member> - <member name="T:NetSharp.Deprecated.PacketPipelineBuilder`3"> - <summary> - Allows for configuring and subsequently building a <see cref="T:NetSharp.Deprecated.PacketPipeline`3"/> instance. - </summary> - <typeparam name="TInput">The type of packet that will be submitted to the pipeline.</typeparam> - <typeparam name="TIntermediate">The type of packet that will be handled internally by the pipeline.</typeparam> - <typeparam name="TOutput">The type of packet that will be requested from the pipeline.</typeparam> - </member> - <member name="M:NetSharp.Deprecated.PacketPipelineBuilder`3.Build"> - <summary> - Returns the currently configured <see cref="T:NetSharp.Deprecated.PacketPipeline`3"/> instance. - </summary> - <returns>The configured <see cref="T:NetSharp.Deprecated.PacketPipeline`3"/> instance.</returns> - <exception cref="T:System.ArgumentNullException"> - Thrown when either <see cref="M:NetSharp.Deprecated.PacketPipelineBuilder`3.WithInputStage(System.Func{`0,`1}@)"/> or <see cref="M:NetSharp.Deprecated.PacketPipelineBuilder`3.WithOutputStage(System.Func{`1,`2}@)"/> have not been called. - </exception> - </member> - <member name="M:NetSharp.Deprecated.PacketPipelineBuilder`3.WithInputStage(System.Func{`0,`1}@)"> - <summary> - Configures the input stage for the pipeline. - </summary> - <param name="stage"> - The transformation that should be applied to incoming packets, to convert them from the <typeparamref name="TInput"/> - type to the <typeparamref name="TIntermediate"/> type that the pipeline handles internally. - </param> - <returns>The builder instance for further configuration.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketPipelineBuilder`3.WithIntermediateStage(System.Func{`1,`1}@)"> - <summary> - Adds the given intermediate stage to the pipeline. - </summary> - <param name="stage"> - The transformation that should be applied to packets traveling through the pipeline. - </param> - <returns>The builder instance for further configuration.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketPipelineBuilder`3.WithOutputStage(System.Func{`1,`2}@)"> - <summary> - Configures the output stage for the pipeline. - </summary> - <param name="stage"> - The transformation that should be applied to outgoing packets, to convert them from the - <typeparamref name="TIntermediate"/> type used internally to the <typeparamref name="TOutput"/> type. - </param> - <returns>The builder instance for further configuration.</returns> - </member> - <member name="T:NetSharp.Deprecated.PacketRegistry"> - <summary> - Provides method of registering request packets and their relevant response packets, as well as mapping their ids. - </summary> - </member> - <member name="F:NetSharp.Deprecated.PacketRegistry.AutomaticPacketTypeIdStartPoint"> - <summary> - The start id for automatically generated packet type ids. Any custom packet type ids lower than this value - that come from external assemblies will be incremented by this value, to ensure that there are no clashes. - </summary> - </member> - <member name="F:NetSharp.Deprecated.PacketRegistry.currentAutomaticPacketTypeIdCounterLockObject"> - <summary> - The lock object for synchronising access to the <see cref="F:NetSharp.Deprecated.PacketRegistry.currentAutomaticPacketTypeIdCounter"/> field. - </summary> - </member> - <member name="F:NetSharp.Deprecated.PacketRegistry.idToPacketTypeMap"> - <summary> - Maps a packet type id to its relevant packet type, and vice-versa. - </summary> - </member> - <member name="F:NetSharp.Deprecated.PacketRegistry.LibraryAssembly"> - <summary> - The assembly that represents the library, where all of the builtin packets are defined. - </summary> - </member> - <member name="F:NetSharp.Deprecated.PacketRegistry.requestToResponseMap"> - <summary> - Maps a request packet to its relevant response packet, and vice-versa. - </summary> - </member> - <member name="F:NetSharp.Deprecated.PacketRegistry.currentAutomaticPacketTypeIdCounter"> - <summary> - The current id for registered packets. - </summary> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.GetNewPacketTypeId(System.Type)"> - <summary> - Fetches the packet type id of the given packet type. If the packet type is declared outside of the library - assembly, then its value is incremented by the <see cref="F:NetSharp.Deprecated.PacketRegistry.AutomaticPacketTypeIdStartPoint"/> value. This ensure that - there are no clashes between the packet type ids of packets declared in the library and external packets. - </summary> - <param name="packetType">The packet type whose id should be fetched.</param> - <returns>The id of the given packet type.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.DeregisterPacketType(System.Type,System.Type)"> - <summary> - Deregisters the given packet type from the registry. - </summary> - <param name="requestPacketType">The request packet type to deregister, if it is registered.</param> - <param name="responsePacketType">The response packet associated with the request packet.</param> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.DeregisterPacketTypes(System.Collections.Generic.Dictionary{System.Type,System.Type})"> - <summary> - Deregisters the given packet types from the registry. - </summary> - <param name="requestToResponsePacketTypeMap">The list of packet types to deregister, if they are registered.</param> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.GetPacketId(System.Type)"> - <summary> - Returns the packet type id associated with the given packet type. - </summary> - <param name="packetType">The packet type whose id to fetch.</param> - <returns>The id of the packet type given.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.GetPacketId``1"> - <summary> - Returns the packet type id associated with the given packet type. - </summary> - <typeparam name="TPacket">The packet type whose id to fetch.</typeparam> - <returns>The id of the packet type given.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.GetPacketType(System.UInt32)"> - <summary> - Returns the packet type associated with the given id. - </summary> - <param name="packetTypeId">The packet id whose mapped type to fetch.</param> - <returns>The packet type mapped by the given id.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.GetRequestPacketType``1"> - <summary> - Returns the type of request packet mapped by the given response packet type. - </summary> - <typeparam name="TResponse">The response packet type whose request packet type to fetch.</typeparam> - <returns>The request packet type, <c>null</c> if no type is mapped.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.GetRequestPacketType(System.Type)"> - <summary> - Returns the type of request packet mapped by the given response packet type. - </summary> - <param name="responsePacketType">The response packet type whose request packet type to fetch.</param> - <returns>The request packet type, <c>null</c> if no type is mapped.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.GetResponsePacketType``1"> - <summary> - Returns the type of response packet mapped by the given request packet type. - </summary> - <typeparam name="TRequest">The request packet type whose response packet type to fetch.</typeparam> - <returns>The response packet type, <c>null</c> if no type is mapped.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.GetResponsePacketType(System.Type)"> - <summary> - Returns the type of response packet mapped by the given request packet type. - </summary> - <param name="requestPacketType">The request packet type whose response packet type to fetch.</param> - <returns>The response packet type, <c>null</c> if no type is mapped.</returns> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.RegisterPacketSourceAssemblies(System.Reflection.Assembly[])"> - <summary> - Rebuilds the packet registry, by registering every <see cref="T:NetSharp.Deprecated.IPacket"/> inheritor in the given assemblies. - </summary> - <param name="packetSourceAssemblies"> - The assemblies from which the packet types to register are sourced. - </param> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.RegisterPacketSourceAssembly(System.Reflection.Assembly)"> - <summary> - Registers all the <see cref="T:NetSharp.Deprecated.IPacket"/> implementors in the given assembly. - </summary> - <param name="packetSourceAssembly">The assembly whose packet types to register.</param> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.RegisterPacketType(System.Type,System.Type)"> - <summary> - Registers the given packet type to the registry. - </summary> - <param name="requestPacketType">The request packet type to register, if it is not registered.</param> - <param name="responsePacketType">The response packet associated with the request packet.</param> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.RegisterPacketTypes(System.Collections.Generic.Dictionary{System.Type,System.Type})"> - <summary> - Registers the given packet types to the registry. - </summary> - <param name="requestToResponsePacketTypeMap"> - The dictionary mapping the request packet types to register, to their relevant response packet types. - The response packet type can be null; then the request packet type is treated as a 'simple' packet. - </param> - </member> - <member name="M:NetSharp.Deprecated.PacketRegistry.#cctor"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.PacketRegistry"/> class. - </summary> - </member> - <member name="T:NetSharp.Deprecated.PacketTypeIdAttribute"> - <summary> - Allows the placing of a custom packet type on a class or struct. This is used if the class or struct - inherits from <see cref="T:NetSharp.Deprecated.IRequestPacket"/> or <see cref="T:NetSharp.Deprecated.IResponsePacket`1"/>. - </summary> - </member> - <member name="M:NetSharp.Deprecated.PacketTypeIdAttribute.#ctor(System.UInt32)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.PacketTypeIdAttribute"/> attribute. - </summary> - <param name="type">The custom type id that the decorated packet type should have.</param> - </member> - <member name="P:NetSharp.Deprecated.PacketTypeIdAttribute.Id"> - <summary> - The custom type id that the decorated packet type should have. This overrides the automatically generated id. - </summary> - </member> - <member name="M:NetSharp.Deprecated.RemoteSocketClient.Dispose"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.RemoteSocketClient.Dispose(System.Boolean)"> - <summary> - Implementation of dispose pattern. - </summary> - <param name="disposing"> - Whether this method is being called by the object finalizer, or by the <see cref="M:NetSharp.Deprecated.RemoteSocketClient.Dispose"/> method. - </param> - </member> - <member name="M:NetSharp.Deprecated.SerialisedPacket.From``1(``0)"> - <summary> - Serialises the given serialisable packet instance and returns the <see cref="T:NetSharp.Deprecated.SerialisedPacket"/> instance - that was generated. This method invokes <see cref="M:NetSharp.Deprecated.IPacket.BeforeSerialisation"/>. - </summary> - <typeparam name="T">The packet type that will be serialised.</typeparam> - <param name="serialisable">The packet instance that should be serialised.</param> - <returns>The serialised instance.</returns> - </member> - <member name="M:NetSharp.Deprecated.SerialisedPacket.To``1(NetSharp.Deprecated.SerialisedPacket@)"> - <summary> - Deserialises and returns a packet instance of the given type from the <see cref="T:NetSharp.Deprecated.SerialisedPacket"/> instance - that was given. This method invokes <see cref="M:NetSharp.Deprecated.IPacket.AfterDeserialisation"/>. - </summary> - <typeparam name="T">The packet type to which the packet should be deserialised.</typeparam> - <param name="instance">The serialised packet instance that should be deserialised.</param> - <returns>The deserialised instance.</returns> - </member> - <member name="T:NetSharp.Deprecated.ComplexPacketHandler`2"> - <summary> - Represents a method that receives a request packet of the given type (<typeparamref name="TReq"/>) and - handles the request, returning a response packet of the given type (<typeparamref name="TRep"/>). - </summary> - <typeparam name="TReq">The type of request packet handled by this delegate method.</typeparam> - <typeparam name="TRep">The type of response packet returned by this delegate method.</typeparam> - <param name="requestPacket">The request packet that should be handled by this delegate method.</param> - <param name="remoteEndPoint">The remote endpoint from which the request originated.</param> - <returns>The response packet to send back to the remote endpoint from which the request originated.</returns> - </member> - <member name="T:NetSharp.Deprecated.SimplePacketHandler`1"> - <summary> - Represents a method that receives a simple request packet of the given type (<typeparamref name="TReq"/>) and - handles the request, not returning any response packets. - </summary> - <typeparam name="TReq">The type of request packet handled by this delegate method.</typeparam> - <param name="requestPacket">The request packet that should be handled by this delegate method.</param> - <param name="remoteEndPoint">The remote endpoint from which the request originated.</param> - </member> - <member name="T:NetSharp.Deprecated.Server"> - <summary> - Provides methods for handling connected <see cref="T:NetSharp.Deprecated.IClient"/> instances. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.complexPacketHandlers"> - <summary> - Maps a packet type id to the complex packet handler for that packet type. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.requestPacketDeserialisers"> - <summary> - Maps a packet type id to the raw packet deserialiser that deserialises raw packets to - <see cref="T:NetSharp.Deprecated.IRequestPacket"/> implementors. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.serverShutdownCancellationTokenSource"> - <summary> - Cancellation token source to stop handling client sockets when the server should be shut down. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.simplePacketHandlers"> - <summary> - Maps a packet type id to the simple packet handler for that packet type. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Server.#ctor"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Server"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Server.Finalize"> - <summary> - Destroys an instance of the <see cref="T:NetSharp.Deprecated.Server"/> class. - </summary> - </member> - <member name="T:NetSharp.Deprecated.Server.RawRequestPacketDeserialiser"> - <summary> - Represents a method that receives a raw packet, and deserialises it into an <see cref="T:NetSharp.Deprecated.IRequestPacket"/> implementor. - </summary> - <param name="rawPacket">The raw packet that was received from the network.</param> - <returns>The deserialised instance of the packet.</returns> - </member> - <member name="M:NetSharp.Deprecated.Server.RegisterInternalPacketHandlers"> - <summary> - Registers packet handlers for every internal library packet. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.PendingConnectionBacklog"> - <summary> - The maximum number of connections that are allowed in the connection backlog. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.DefaultNetworkOperationTimeout"> - <summary> - The default timeout value for all network operations. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.serverShutdownCancellationToken"> - <summary> - The cancellation token that will be set when the server must be shut down. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.socket"> - <summary> - The <see cref="T:System.Net.Sockets.Socket"/> underlying the connection. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.socketOptions"> - <summary> - Backing field for the <see cref="P:NetSharp.Deprecated.Server.SocketOptions"/> property. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.runServer"> - <summary> - Whether the server should be ran. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Server.#ctor(System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Server"/> class. - </summary> - <param name="socketType">The socket type for the underlying socket.</param> - <param name="protocolType">The protocol type for the underlying socket.</param> - <param name="socketManager">The <see cref="!:Utils.Socket_Options.SocketOptions"/> implementation to use.</param> - </member> - <member name="M:NetSharp.Deprecated.Server.#ctor(System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,System.TimeSpan)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Server"/> class. - </summary> - <param name="socketType">The socket type for the underlying socket.</param> - <param name="protocolType">The protocol type for the underlying socket.</param> - <param name="socketManager">The <see cref="!:Utils.Socket_Options.SocketOptions"/> manager to use.</param> - <param name="networkOperationTimeout">The timeout value for send and receive operations over the network.</param> - </member> - <member name="M:NetSharp.Deprecated.Server.DeserialiseRequestPacket(System.UInt32,NetSharp.Deprecated.SerialisedPacket@)"> - <summary> - Deserialises the given <see cref="T:NetSharp.Deprecated.NetworkPacket"/> struct into an <see cref="T:NetSharp.Deprecated.IRequestPacket"/> implementor. - </summary> - <param name="packetType">The type id of packet that we should deserialise to.</param> - <param name="rawRequestPacket">The packet that should be deserialised.</param> - <returns>The deserialised packet instance, cast to the <see cref="T:NetSharp.Deprecated.IRequestPacket"/> interface.</returns> - </member> - <member name="M:NetSharp.Deprecated.Server.Dispose(System.Boolean)"> - <summary> - Disposes of this <see cref="T:NetSharp.Deprecated.Server"/> instance. - </summary> - <param name="disposing">Whether this instance is being disposed.</param> - </member> - <member name="M:NetSharp.Deprecated.Server.DoHandleClientAsync(System.Object)"> - <summary> - Provides a task that represents the handling of a client. Calls the abstract <see cref="M:NetSharp.Deprecated.Server.HandleClientAsync(NetSharp.Deprecated.Server.ClientHandlerArgs,System.Threading.CancellationToken)"/> method. - </summary> - <param name="clientHandlerArgsObj">The object representing the passed <see cref="T:NetSharp.Deprecated.Server.ClientHandlerArgs"/> instance.</param> - </member> - <member name="M:NetSharp.Deprecated.Server.HandleClientAsync(NetSharp.Deprecated.Server.ClientHandlerArgs,System.Threading.CancellationToken)"> - <summary> - Handles a client asynchronously. - </summary> - <param name="args">The client handler arguments that should be passed to the client handler.</param> - <param name="cancellationToken">Cancellation token set when the server is shutting down.</param> - </member> - <member name="M:NetSharp.Deprecated.Server.HandleRequestPacket(System.UInt32,NetSharp.Deprecated.IRequestPacket@,System.Net.EndPoint@)"> - <summary> - Handles the given request packet with a registered packet handler. In this case, a complex packet handler - will override any registered simple packet handlers. - </summary> - <param name="packetType">The type id of the packet that we should handle.</param> - <param name="requestPacket">The packet instance that should be handled.</param> - <param name="remoteEndPoint">The remote endpoint from which the request packet originated.</param> - <returns>The response packet that should be sent back to the remote endpoint.</returns> - </member> - <member name="M:NetSharp.Deprecated.Server.OnClientConnected(System.Net.EndPoint)"> - <summary> - Invokes the <see cref="E:NetSharp.Deprecated.Server.ClientConnected"/> event. - </summary> - <param name="remoteEndPoint">The remote endpoint with which a connection was made.</param> - </member> - <member name="M:NetSharp.Deprecated.Server.OnClientDisconnected(System.Net.EndPoint)"> - <summary> - Invokes the <see cref="E:NetSharp.Deprecated.Server.ClientDisconnected"/> event. - </summary> - <param name="remoteEndPoint">The remote endpoint with which a connection was lost.</param> - </member> - <member name="M:NetSharp.Deprecated.Server.OnServerStarted"> - <summary> - Invokes the <see cref="E:NetSharp.Deprecated.Server.ServerStarted"/> event. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Server.OnServerStopped"> - <summary> - Invokes the <see cref="E:NetSharp.Deprecated.Server.ServerStopped"/> event. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Server.TryBind(System.Net.EndPoint,System.TimeSpan)"> - <summary> - Attempts to synchronously bind the underlying socket to the given local endpoint. Blocks. - If the timeout is exceeded the binding attempt is aborted and the method returns false. - </summary> - <param name="localEndPoint">The local endpoint to bind to.</param> - <param name="timeout">The timeout within which to attempt the binding.</param> - <returns>Whether the binding was successful or not.</returns> - </member> - <member name="M:NetSharp.Deprecated.Server.TryBindAsync(System.Net.EndPoint,System.TimeSpan)"> - <summary> - Attempts to asynchronously bind the underlying socket to the given local endpoint. Does not block. - If the timeout is exceeded the binding attempt is aborted and the method returns false. - </summary> - <param name="localEndPoint">The local endpoint to bind to.</param> - <param name="timeout">The timeout within which to attempt the binding.</param> - <returns>Whether the binding was successful or not.</returns> - </member> - <member name="T:NetSharp.Deprecated.Server.ClientHandlerArgs"> - <summary> - Holds information about the arguments passed to every client handler task. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Server.ClientHandlerArgs.#ctor(System.Net.EndPoint,System.Net.Sockets.Socket)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.Server.ClientHandlerArgs"/> struct. - </summary> - <param name="remoteEndPoint">The remote endpoint of the client that should be handled.</param> - <param name="handlerSocket">The handler socket of the client that should be handled.</param> - </member> - <member name="F:NetSharp.Deprecated.Server.ClientHandlerArgs.ClientEndPoint"> - <summary> - The remote endpoint for the client being handled. - </summary> - </member> - <member name="F:NetSharp.Deprecated.Server.ClientHandlerArgs.ClientSocket"> - <summary> - The client handler socket for the client being handled. Is only set if using TCP. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Server.ClientHandlerArgs.ForTcpClientHandler(System.Net.Sockets.Socket@)"> - <summary> - Constructs a new instance of the <see cref="T:NetSharp.Deprecated.Server.ClientHandlerArgs"/> for a TCP client. - </summary> - <returns>A new instance of the <see cref="T:NetSharp.Deprecated.Server.ClientHandlerArgs"/>, setup for a TCP client.</returns> - </member> - <member name="M:NetSharp.Deprecated.Server.ClientHandlerArgs.ForUdpClientHandler(System.Net.EndPoint@)"> - <summary> - Constructs a new instance of the <see cref="T:NetSharp.Deprecated.Server.ClientHandlerArgs"/> for a UDP client. - </summary> - <returns>A new instance of the <see cref="T:NetSharp.Deprecated.Server.ClientHandlerArgs"/>, setup for a UDP client.</returns> - </member> - <member name="E:NetSharp.Deprecated.Server.ClientConnected"> - <summary> - Signifies that a connection with a remote endpoint has been made. - </summary> - </member> - <member name="E:NetSharp.Deprecated.Server.ClientDisconnected"> - <summary> - Signifies that a connection with a remote endpoint has been lost. - </summary> - </member> - <member name="E:NetSharp.Deprecated.Server.ServerStarted"> - <summary> - Signifies that the server was started and clients will start being accepted. - </summary> - </member> - <member name="E:NetSharp.Deprecated.Server.ServerStopped"> - <summary> - Signifies that the server was stopped and clients will stop being accepted. - </summary> - </member> - <member name="P:NetSharp.Deprecated.Server.NetworkOperationTimeout"> - <summary> - The timeout value for network operations such as sending bytes or receiving bytes over the network. - </summary> - </member> - <member name="P:NetSharp.Deprecated.Server.SocketOptions"> - <summary> - The configured socket options for the underlying connection. - </summary> - </member> - <member name="M:NetSharp.Deprecated.Server.RunAsync(System.Net.EndPoint)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Server.Shutdown"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Server.TryDeregisterComplexPacketHandler``2(NetSharp.Deprecated.ComplexPacketHandler{``0,``1}@)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Server.TryDeregisterSimplePacketHandler``1(NetSharp.Deprecated.SimplePacketHandler{``0}@)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Server.TryRegisterComplexPacketHandler``2(NetSharp.Deprecated.ComplexPacketHandler{``0,``1})"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.Server.TryRegisterSimplePacketHandler``1(NetSharp.Deprecated.SimplePacketHandler{``0})"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.ServerClientConnection"> - <summary> - Base class for connections, holding methods shared between the <see cref="T:NetSharp.Deprecated.Client"/> and <see cref="T:NetSharp.Deprecated.Server"/> classes. - </summary> - </member> - <member name="F:NetSharp.Deprecated.ServerClientConnection.logger"> - <summary> - The logger to which the server can log messages. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ServerClientConnection.#ctor"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.ServerClientConnection"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ServerClientConnection.Dispose(System.Boolean)"> - <summary> - Disposes of this <see cref="T:NetSharp.Deprecated.ServerClientConnection"/> instance. - </summary> - <param name="disposing">Whether this instance is being disposed.</param> - </member> - <member name="M:NetSharp.Deprecated.ServerClientConnection.OnBytesReceived(System.Net.EndPoint,System.Int32)"> - <summary> - Invokes the <see cref="E:NetSharp.Deprecated.ServerClientConnection.BytesReceived"/> event. - </summary> - <param name="remoteEndPoint">The remote endpoint from which the bytes were received.</param> - <param name="bytesReceived">The number of bytes that were received from the remote endpoint.</param> - </member> - <member name="M:NetSharp.Deprecated.ServerClientConnection.OnBytesSent(System.Net.EndPoint,System.Int32)"> - <summary> - Invokes the <see cref="E:NetSharp.Deprecated.ServerClientConnection.BytesSent"/> event. - </summary> - <param name="remoteEndPoint">The remote endpoint to which the bytes were sent.</param> - <param name="bytesSent">The number of bytes that were sent to the remote endpoint.</param> - </member> - <member name="E:NetSharp.Deprecated.ServerClientConnection.BytesReceived"> - <summary> - Signifies that some data has been received from the remote endpoint. - </summary> - </member> - <member name="E:NetSharp.Deprecated.ServerClientConnection.BytesSent"> - <summary> - Signifies that some data was sent to the remote endpoint. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ServerClientConnection.ChangeLoggingStream(System.IO.Stream,NetSharp.Deprecated.LogLevel)"> - <summary> - Makes the client log to the given stream. - </summary> - <param name="loggingStream">The stream that new messages should be logged to.</param> - <param name="minimumMessageSeverityLevel"> - The minimum severity level that new messages must have to be logged to the stream. - </param> - </member> - <member name="M:NetSharp.Deprecated.ServerClientConnection.Dispose"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.ServerExtensions"> - <summary> - Provides additional methods and functionality to the <see cref="T:NetSharp.Deprecated.Server"/> class. - </summary> - </member> - <member name="M:NetSharp.Deprecated.ServerExtensions.Run(NetSharp.Deprecated.Server,System.Net.IPAddress,System.Int32)"> - <summary> - Starts the server synchronously and starts accepting client connections. Blocks. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="localAddress">The local IP address to bind to.</param> - <param name="localPort">The local port to bind to.</param> - </member> - <member name="M:NetSharp.Deprecated.ServerExtensions.Run(NetSharp.Deprecated.Server,System.Net.IPAddress)"> - <summary> - Starts the server synchronously and starts accepting client connections. Blocks. Uses the default connection port. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="localAddress">The local IP address to bind to.</param> - </member> - <member name="M:NetSharp.Deprecated.ServerExtensions.RunAsync(NetSharp.Deprecated.Server,System.Net.IPAddress)"> - <summary> - Starts the server asynchronously and starts accepting client connections. Does not block. Uses the default - connection port. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="localAddress">The local IP address to bind to.</param> - </member> - <member name="M:NetSharp.Deprecated.ServerExtensions.RunAsync(NetSharp.Deprecated.Server,System.Net.IPAddress,System.Int32)"> - <summary> - Starts the server asynchronously and starts accepting client connections. Does not block. - </summary> - <param name="instance">The instance on which this extension method should be called.</param> - <param name="localAddress">The local IP address to bind to.</param> - <param name="localPort">The local port to bind to.</param> - </member> - <member name="T:NetSharp.Deprecated.SocketAcceptor"> - <summary> - Helper class providing awaitable wrappers around asynchronous Accept, Connect, and Disconnect operations. - </summary> - </member> - <member name="M:NetSharp.Deprecated.SocketAcceptor.AcceptAsync(System.Net.Sockets.Socket,System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket accept operation. - </summary> - <param name="socket">The socket which should be used to accept an incoming connection attempt.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - <returns>The accepted socket.</returns> - </member> - <member name="M:NetSharp.Deprecated.SocketAcceptor.ConnectAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket connect operation. - </summary> - <param name="socket">The socket which should asynchronously connect to the remote endpoint.</param> - <param name="remoteEndPoint">The remote endpoint to which the socket should connect.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - </member> - <member name="M:NetSharp.Deprecated.SocketAcceptor.DisconnectAsync(System.Net.Sockets.Socket,System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket disconnect operation. - </summary> - <param name="socket">The socket which should asynchronously disconnect from its remote endpoint.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - </member> - <member name="M:NetSharp.Deprecated.SocketClient.Finalize"> - <summary> - Destroys a socket client instance. - </summary> - </member> - <member name="M:NetSharp.Deprecated.SocketClient.Dispose(System.Boolean)"> - <summary> - Implementation of dispose pattern. - </summary> - <param name="disposing"> - Whether this method is being called by the object finalizer, or by the <see cref="M:NetSharp.Deprecated.SocketClient.Dispose"/> method. - </param> - </member> - <member name="M:NetSharp.Deprecated.SocketClient.Dispose"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.SocketOperations"> - <summary> - Provides helper awaitable functions for wrapping the <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> pattern. - </summary> - </member> - <member name="T:NetSharp.Deprecated.SocketOptions"> - <summary> - Allows for manipulation of socket options. - </summary> - </member> - <member name="F:NetSharp.Deprecated.SocketOptions.managedSocket"> - <summary> - The <see cref="T:System.Net.Sockets.Socket"/> instance whose settings are being managed. - </summary> - </member> - <member name="M:NetSharp.Deprecated.SocketOptions.#ctor(System.Net.Sockets.Socket@)"> - <summary> - Initialises a new instance of the <see cref="T:NetSharp.Deprecated.SocketOptions"/> class. - </summary> - <param name="socket">The <see cref="T:System.Net.Sockets.Socket"/> instance whose options should be managed.</param> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.DualMode"> - <summary> - Whether this <see cref="T:System.Net.Sockets.Socket"/> can operate in dual IPv4 / IPv6 mode. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.ForceFlush"> - <summary> - Whether sending a packet flushes underlying <see cref="T:System.Net.Sockets.NetworkStream"/>. - </summary> - <remarks> - This value is only used in a <see cref="T:System.Net.Sockets.TcpClient"/> instance, which uses a <see cref="T:System.Net.Sockets.NetworkStream"/> - to send and receive data. A <see cref="T:System.Net.Sockets.UdpClient"/> is unaffected by this value. - </remarks> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.Fragment"> - <summary> - Whether this <see cref="T:System.Net.Sockets.Socket"/> is allowed to fragment frames that are too large to send in one go. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.HopLimit"> - <summary> - The hop limit for packets sent by this <see cref="T:System.Net.Sockets.Socket"/>. Comparable to IPv4s TTL (Time To Live). - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.IsChecksumEnabled"> - <summary> - Whether a checksum should be created for each UDP packet sent. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.IsRoutingEnabled"> - <summary> - Whether the packet should be sent directly to its destination or allowed to be routed through multiple destinations - first. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.LocalEndPoint"> - <summary> - The local <see cref="T:System.Net.EndPoint"/> for the <see cref="F:NetSharp.Deprecated.SocketOptions.managedSocket"/>. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.LocalIPEndPoint"> - <summary> - The local <see cref="T:System.Net.IPEndPoint"/> for this <see cref="T:System.Net.Sockets.Socket"/> instance. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.RemoteEndPoint"> - <summary> - The remote <see cref="T:System.Net.EndPoint"/> for the <see cref="F:NetSharp.Deprecated.SocketOptions.managedSocket"/>. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.RemoteIPEndPoint"> - <summary> - The remote <see cref="T:System.Net.IPEndPoint"/> that this <see cref="T:System.Net.Sockets.Socket"/> instance communicates with. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.Ttl"> - <summary> - The 'Time To Live' for this <see cref="T:System.Net.Sockets.Socket"/>. - </summary> - </member> - <member name="P:NetSharp.Deprecated.SocketOptions.UseLoopback"> - <summary> - Whether this <see cref="T:System.Net.Sockets.Socket"/> should use a loopback address and bypass hardware. - </summary> - </member> - <member name="T:NetSharp.Deprecated.SocketReader"> - <summary> - Helper class providing awaitable wrappers around asynchronous Receive and ReceiveFrom operations. - </summary> - </member> - <member name="M:NetSharp.Deprecated.SocketReader.ReceiveFromAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Net.Sockets.SocketFlags,System.Memory{System.Byte},System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket receive operation. - </summary> - <param name="socket">The socket which should receive data from the remote endpoint.</param> - <param name="remoteEndPoint">The remove endpoint from which data should be received.</param> - <param name="socketFlags">The socket flags associated with the receive operation.</param> - <param name="inputBuffer">The memory buffer into which received data will be stored.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - <returns>The result of the receive operation.</returns> - </member> - <member name="M:NetSharp.Deprecated.SocketServer.Finalize"> - <summary> - Destroys a socket server instance. - </summary> - </member> - <member name="F:NetSharp.Deprecated.SocketServer.listenerSocket"> - <summary> - The socket which should be used to listen for incoming data and to send outgoing data. - </summary> - </member> - <member name="M:NetSharp.Deprecated.SocketServer.Dispose(System.Boolean)"> - <summary> - Implementation of dispose pattern. - </summary> - <param name="disposing"> - Whether this method is being called by the object finalizer, or by the <see cref="M:NetSharp.Deprecated.SocketServer.Dispose"/> method. - </param> - </member> - <member name="M:NetSharp.Deprecated.SocketServer.Dispose"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.SocketWriter"> - <summary> - Helper class providing awaitable wrappers around asynchronous Send and SendTo operations. - </summary> - </member> - <member name="M:NetSharp.Deprecated.SocketWriter.SendToAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Net.Sockets.SocketFlags,System.Memory{System.Byte},System.Threading.CancellationToken)"> - <summary> - Provides an awaitable wrapper around an asynchronous socket send operation. - </summary> - <param name="socket">The socket which should send the data to the remote endpoint.</param> - <param name="remoteEndPoint">The remote endpoint to which data should be written.</param> - <param name="socketFlags">The socket flags associated with the send operation.</param> - <param name="outputBuffer">The data buffer which should be sent.</param> - <param name="cancellationToken">The cancellation token to observe for the operation.</param> - <returns>The number of bytes of data which were written to the remote endpoint.</returns> - </member> - <member name="T:NetSharp.Deprecated.TcpClient"> - <summary> - Provides methods for TCP communication with a connected <see cref="T:NetSharp.Deprecated.TcpServer"/> instance. - </summary> - </member> - <member name="M:NetSharp.Deprecated.TcpClient.#ctor"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.TcpClient.SendBytesAsync(System.Byte[],System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.TcpClient.SendBytesWithResponseAsync(System.Byte[],System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.TcpClient.SendComplexAsync``2(``0,System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.TcpClient.SendSimpleAsync``1(``0,System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.TcpServer"> - <summary> - Provides methods for TCP communication with connected <see cref="T:NetSharp.Deprecated.TcpClient"/> instances. - </summary> - </member> - <member name="M:NetSharp.Deprecated.TcpServer.HandleClientAsync(NetSharp.Deprecated.Server.ClientHandlerArgs,System.Threading.CancellationToken)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.TcpServer.#ctor(System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.TcpServer.#ctor"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.TcpServer.RunAsync(System.Net.EndPoint)"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.TcpSocketOptions"> - <summary> - Allows for manipulation of TCP socket options. - </summary> - </member> - <member name="M:NetSharp.Deprecated.TcpSocketOptions.#ctor(System.Net.Sockets.Socket@)"> - <inheritdoc /> - </member> - <member name="P:NetSharp.Deprecated.TcpSocketOptions.HopLimit"> - <inheritdoc /> - </member> - <member name="P:NetSharp.Deprecated.TcpSocketOptions.IsRoutingEnabled"> - <inheritdoc /> - </member> - <member name="P:NetSharp.Deprecated.TcpSocketOptions.UseLoopback"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.UdpClient"> - <summary> - Provides methods for UDP communication with a connected <see cref="T:NetSharp.Deprecated.UdpServer"/> instance. - </summary> - </member> - <member name="M:NetSharp.Deprecated.UdpClient.#ctor"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.UdpClient.SendBytesAsync(System.Byte[],System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.UdpClient.SendBytesWithResponseAsync(System.Byte[],System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.UdpClient.SendComplexAsync``2(``0,System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.UdpClient.SendSimpleAsync``1(``0,System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.UdpServer"> - <summary> - Provides methods for UDP communication with connected <see cref="T:NetSharp.Deprecated.UdpClient"/> instances. - </summary> - </member> - <member name="F:NetSharp.Deprecated.UdpServer.clientChannelOptions"> - <summary> - The options that should be applied to every channel created to handle a client. - </summary> - </member> - <member name="F:NetSharp.Deprecated.UdpServer.activeClients"> + <member name="M:NetSharp.Packets.NetworkPacket.#ctor(NetSharp.Packets.NetworkPacket.NetworkPacketHeader,System.ReadOnlyMemory{System.Byte},NetSharp.Packets.NetworkPacket.NetworkPacketFooter)"> <summary> - Holds currently connected and active clients, as well as their current received packet queues. + Constructs a new instance of the <see cref="T:NetSharp.Packets.NetworkPacket"/> struct. </summary> + <param name="packetHeader">The header for this packet.</param> + <param name="packetDataBuffer">The data that should be stored in the packet.</param> + <param name="packetFooter">The footer for this packet.</param> + <exception cref="T:System.ArgumentException"> + Thrown when the given <paramref name="packetDataBuffer"/> exceeds <see cref="F:NetSharp.Packets.NetworkPacket.TotalSize"/> bytes in size. + </exception> </member> - <member name="M:NetSharp.Deprecated.UdpServer.HandleClientAsync(NetSharp.Deprecated.Server.ClientHandlerArgs,System.Threading.CancellationToken)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.UdpServer.#ctor(System.TimeSpan)"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.UdpServer.#ctor"> - <inheritdoc /> - </member> - <member name="M:NetSharp.Deprecated.UdpServer.RunAsync(System.Net.EndPoint)"> - <inheritdoc /> - </member> - <member name="T:NetSharp.Deprecated.UdpSocketOptions"> + <member name="M:NetSharp.Sockets.SocketAsyncOperations.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"> <summary> - Allows for manipulation of UDP socket options. + Event handler for the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed"/> event. </summary> - </member> - <member name="M:NetSharp.Deprecated.UdpSocketOptions.#ctor(System.Net.Sockets.Socket@)"> - <inheritdoc /> - </member> - <member name="P:NetSharp.Deprecated.UdpSocketOptions.HopLimit"> - <inheritdoc /> - </member> - <member name="P:NetSharp.Deprecated.UdpSocketOptions.IsRoutingEnabled"> - <inheritdoc /> - </member> - <member name="P:NetSharp.Deprecated.UdpSocketOptions.UseLoopback"> - <inheritdoc /> + <param name="sender">The object on which the event is raised.</param> + <param name="args">The event arguments.</param> </member> <member name="T:NetSharp.Deprecated.BiDictionary`2"> <summary> @@ -2326,35 +211,25 @@ <member name="M:NetSharp.Deprecated.Conversion.EndianAwareBitConverter.ToUInt64(System.Span{System.Byte},System.Boolean)"> <inheritdoc cref="M:System.BitConverter.ToUInt64(System.ReadOnlySpan{System.Byte})"/> </member> - <member name="M:NetSharp.Packets.NetworkPacket.#ctor(NetSharp.Packets.NetworkPacket.NetworkPacketHeader,System.ReadOnlyMemory{System.Byte},NetSharp.Packets.NetworkPacket.NetworkPacketFooter)"> - <summary> - Constructs a new instance of the <see cref="T:NetSharp.Packets.NetworkPacket"/> struct. - </summary> - <param name="packetHeader">The header for this packet.</param> - <param name="packetDataBuffer">The data that should be stored in the packet.</param> - <param name="packetFooter">The footer for this packet.</param> - <exception cref="T:System.ArgumentException"> - Thrown when the given <paramref name="packetDataBuffer"/> exceeds <see cref="F:NetSharp.Packets.NetworkPacket.TotalSize"/> bytes in size. - </exception> - </member> - <member name="M:NetSharp.Sockets.SocketAsyncOperations.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"> - <summary> - Event handler for the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed"/> event. - </summary> - <param name="sender">The object on which the event is raised.</param> - <param name="args">The event arguments.</param> - </member> <member name="T:NetSharp.Utils.TransmissionResult"> <summary> Represents the result of a socket transmission. </summary> </member> - <member name="M:NetSharp.Utils.TransmissionResult.#ctor(System.Net.Sockets.SocketAsyncEventArgs)"> + <member name="M:NetSharp.Utils.TransmissionResult.#ctor(System.Net.Sockets.SocketAsyncEventArgs@)"> <summary> Initialises a new instance of the <see cref="T:NetSharp.Utils.TransmissionResult"/> struct. </summary> <param name="args">The socket arguments associated with the transmission.</param> </member> + <member name="M:NetSharp.Utils.TransmissionResult.#ctor(System.Byte[]@,System.Int32@,System.Net.EndPoint@)"> + <summary> + Initialises a new instance of the <see cref="T:NetSharp.Utils.TransmissionResult"/> struct. + </summary> + <param name="buffer">The buffer associated with the transmission.</param> + <param name="count">The number of bytes written to or read from the buffer.</param> + <param name="remoteEndPoint">The remote end point associated with the transmission.</param> + </member> <member name="F:NetSharp.Utils.TransmissionResult.Buffer"> <summary> The byte buffer that was transmitted across the network. @@ -2370,10 +245,5 @@ The remote endpoint to which the buffer was transmitted. </summary> </member> - <member name="F:NetSharp.Utils.TransmissionResult.TransmissionArgs"> - <summary> - Socket arguments and other data associated with the transmission. - </summary> - </member> </members> </doc> diff --git a/NetSharp/NetSharp/Sockets/Datagram/DatagramSocketClient.cs b/NetSharp/NetSharp/Sockets/Datagram/DatagramSocketClient.cs @@ -1,12 +1,173 @@ -using System.Net.Sockets; +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using NetSharp.Utils; namespace NetSharp.Sockets.Datagram { - public class DatagramSocketClient : SocketClient + //TODO document class + public sealed class DatagramSocketClient : SocketClient { + private readonly struct SocketOperationToken + { + public readonly TaskCompletionSource<TransmissionResult> CompletionSource; + + public readonly CancellationToken CancellationToken; + + public SocketOperationToken(in TaskCompletionSource<TransmissionResult> completionSource, in CancellationToken cancellationToken) + { + CompletionSource = completionSource; + + CancellationToken = cancellationToken; + } + } + public DatagramSocketClient(in AddressFamily connectionAddressFamily, in ProtocolType connectionProtocolType) : base(in connectionAddressFamily, SocketType.Dgram, in connectionProtocolType) { } + + protected override SocketAsyncEventArgs CreateTransmissionArgs() + { + SocketAsyncEventArgs connectionArgs = new SocketAsyncEventArgs(); + + connectionArgs.Completed += HandleIoCompleted; + + return connectionArgs; + } + + protected override void ResetTransmissionArgs(SocketAsyncEventArgs args) + { + } + + protected override bool CanTransmissionArgsBeReused(in SocketAsyncEventArgs args) + { + return true; + } + + protected override void DestroyTransmissionArgs(SocketAsyncEventArgs remoteConnectionArgs) + { + remoteConnectionArgs.Completed -= HandleIoCompleted; + + remoteConnectionArgs.Dispose(); + } + + protected override void HandleIoCompleted(object sender, SocketAsyncEventArgs args) + { + switch (args.LastOperation) + { + case SocketAsyncOperation.SendTo: + SocketOperationToken sendToken = (SocketOperationToken) args.UserToken; + + if (sendToken.CancellationToken.IsCancellationRequested) + { + sendToken.CompletionSource.SetCanceled(); + } + else if (args.SocketError == SocketError.Success) + { + TransmissionResult result = new TransmissionResult(in args); + + sendToken.CompletionSource.SetResult(result); + + TransmissionArgsPool.Return(args); + } + else + { + sendToken.CompletionSource.SetException(new SocketException((int)args.SocketError)); + + TransmissionArgsPool.Return(args); + } + + break; + + case SocketAsyncOperation.ReceiveFrom: + SocketOperationToken receiveToken = (SocketOperationToken)args.UserToken; + + if (sendToken.CancellationToken.IsCancellationRequested) + { + receiveToken.CompletionSource.SetCanceled(); + } + else if (args.SocketError == SocketError.Success) + { + TransmissionResult result = new TransmissionResult(in args); + + receiveToken.CompletionSource.SetResult(result); + + TransmissionArgsPool.Return(args); + } + else + { + receiveToken.CompletionSource.SetException(new SocketException((int)args.SocketError)); + + TransmissionArgsPool.Return(args); + } + + break; + + default: + throw new NotSupportedException($"{nameof(HandleIoCompleted)} doesn't support {args.LastOperation}"); + } + } + + public TransmissionResult SendTo(EndPoint remoteEndPoint, byte[] sendBuffer, SocketFlags flags = SocketFlags.None) + { + int sentBytes = connection.SendTo(sendBuffer, flags, remoteEndPoint); + + return new TransmissionResult(in sendBuffer, in sentBytes, in remoteEndPoint); + } + + public ValueTask<TransmissionResult> SendToAsync(EndPoint remoteEndPoint, Memory<byte> sendBuffer, + SocketFlags flags = SocketFlags.None, CancellationToken cancellationToken = default) + { + TaskCompletionSource<TransmissionResult> tcs = new TaskCompletionSource<TransmissionResult>(); + + SocketAsyncEventArgs args = TransmissionArgsPool.Rent(); + + args.SetBuffer(sendBuffer); + + args.RemoteEndPoint = remoteEndPoint; + args.SocketFlags = flags; + args.UserToken = new SocketOperationToken(in tcs, in cancellationToken); + + if (connection.SendToAsync(args)) return new ValueTask<TransmissionResult>(tcs.Task); + + TransmissionResult result = new TransmissionResult(in args); + + TransmissionArgsPool.Return(args); + + return new ValueTask<TransmissionResult>(result); + + } + + public TransmissionResult ReceiveFrom(ref EndPoint remoteEndPoint, byte[] receiveBuffer, SocketFlags flags = SocketFlags.None) + { + int readBytes = connection.ReceiveFrom(receiveBuffer, flags, ref remoteEndPoint); + + return new TransmissionResult(in receiveBuffer, in readBytes, in remoteEndPoint); + } + + public ValueTask<TransmissionResult> ReceiveFromAsync(EndPoint remoteEndPoint, Memory<byte> receiveBuffer, + SocketFlags flags = SocketFlags.None, CancellationToken cancellationToken = default) + { + TaskCompletionSource<TransmissionResult> tcs = new TaskCompletionSource<TransmissionResult>(); + + SocketAsyncEventArgs args = TransmissionArgsPool.Rent(); + + args.SetBuffer(receiveBuffer); + + args.RemoteEndPoint = remoteEndPoint; + args.SocketFlags = flags; + args.UserToken = new SocketOperationToken(in tcs, in cancellationToken); + + if (connection.ReceiveFromAsync(args)) return new ValueTask<TransmissionResult>(tcs.Task); + + TransmissionResult result = new TransmissionResult(in args); + + TransmissionArgsPool.Return(args); + + return new ValueTask<TransmissionResult>(result); + } } } \ No newline at end of file diff --git a/NetSharp/NetSharp/Sockets/Datagram/DatagramSocketServer.cs b/NetSharp/NetSharp/Sockets/Datagram/DatagramSocketServer.cs @@ -1,226 +1,86 @@ using NetSharp.Utils; using System; -using System.Collections.Concurrent; -using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; -using System.Threading.Channels; using System.Threading.Tasks; -using Microsoft.Extensions.ObjectPool; -using NetSharp.Deprecated; + using NetworkPacket = NetSharp.Packets.NetworkPacket; namespace NetSharp.Sockets.Datagram { - public class DatagramSocketServer : SocketServer + //TODO document + public readonly struct DatagramSocketServerOptions { - private static readonly EndPoint AnyRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + public static readonly DatagramSocketServerOptions Defaults = + new DatagramSocketServerOptions(NetworkPacket.TotalSize, 8); - private readonly ConcurrentDictionary<EndPoint, RemoteDatagramClientToken> connectedClientTokens; + public readonly int PacketSize; - private readonly MyObjectPool<SocketAsyncEventArgs> ArgsPool; + public readonly int ConcurrentReceiveFromCalls; - private readonly struct RemoteDatagramClientToken + public DatagramSocketServerOptions(int packetSize, int concurrentReceiveFromCalls) { - private readonly Channel<NetworkPacket> PacketChannel; - - public readonly ChannelReader<NetworkPacket> PacketReader; - - public readonly ChannelWriter<NetworkPacket> PacketWriter; - - public RemoteDatagramClientToken(in Channel<NetworkPacket> packetChannel) - { - PacketChannel = packetChannel; - PacketReader = packetChannel.Reader; - PacketWriter = packetChannel.Writer; - } - } - - public DatagramSocketServer(in AddressFamily connectionAddressFamily, in ProtocolType connectionProtocolType) - : base(in connectionAddressFamily, SocketType.Dgram, in connectionProtocolType) - { - connectedClientTokens = new ConcurrentDictionary<EndPoint, RemoteDatagramClientToken>(); - - SocketAsyncEventArgs CreateArgs() - { - SocketAsyncEventArgs args = new SocketAsyncEventArgs(); - - args.Completed += HandleIoCompleted; - - return args; - } - - static void ResetArgs(SocketAsyncEventArgs args) - { - - } - - void DestroyArgs(SocketAsyncEventArgs args) - { - args.Completed -= HandleIoCompleted; - - args.Dispose(); - } - - static bool ReBufferArgsPredicate(in SocketAsyncEventArgs args) - { - return true; - } + PacketSize = packetSize; - ArgsPool = new MyObjectPool<SocketAsyncEventArgs>(CreateArgs, ResetArgs, DestroyArgs, ReBufferArgsPredicate); + ConcurrentReceiveFromCalls = concurrentReceiveFromCalls; } + } - protected override SocketAsyncEventArgs GenerateConnectionArgs(EndPoint remoteEndPoint) - { - SocketAsyncEventArgs connectionArgs = new SocketAsyncEventArgs { RemoteEndPoint = remoteEndPoint }; + //TODO address the need for a fixed packet size (NetworkPacket.TotalSize; lines 109 and 145) + //TODO address the need for a fixed number of initial ReceiveFrom method calls + //TODO address the need to handle series of network packets, not just single packets + public sealed class DatagramSocketServer : SocketServer + { + private static readonly EndPoint AnyRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - connectionArgs.Completed += SocketAsyncOperations.HandleIoCompleted; + public readonly DatagramSocketServerOptions ServerOptions; - return connectionArgs; - } - - protected override void DestroyConnectionArgs(SocketAsyncEventArgs remoteConnectionArgs) + public DatagramSocketServer(in AddressFamily connectionAddressFamily, in ProtocolType connectionProtocolType, + in DatagramSocketServerOptions serverOptions = default) : base(in connectionAddressFamily, SocketType.Dgram, + in connectionProtocolType) { - remoteConnectionArgs.Completed -= SocketAsyncOperations.HandleIoCompleted; - - remoteConnectionArgs.Dispose(); + ServerOptions = serverOptions.Equals(default) ? DatagramSocketServerOptions.Defaults : serverOptions; } - protected override async Task HandleClient(SocketAsyncEventArgs clientArgs, CancellationToken cancellationToken = default) + private readonly struct SocketOperationToken { - EndPoint clientEndPoint = clientArgs.RemoteEndPoint; - RemoteDatagramClientToken clientToken = connectedClientTokens[clientEndPoint]; - - byte[] responseBuffer = new byte[NetworkPacket.TotalSize]; - Memory<byte> responseBufferMemory = new Memory<byte>(responseBuffer); + public readonly byte[] RentedBuffer; - try + public SocketOperationToken(in byte[] rentedBuffer) { - while (!cancellationToken.IsCancellationRequested) - { - NetworkPacket request = await clientToken.PacketReader.ReadAsync(cancellationToken); - - // TODO implement actual request handling, besides just an echo - NetworkPacket response = request; - - NetworkPacket.Serialise(response, responseBufferMemory); - - TransmissionResult sendResult = - await SocketAsyncOperations - .SendToAsync(clientArgs, connection, clientEndPoint, SocketFlags.None, responseBufferMemory, - cancellationToken); - -#if DEBUG - lock (typeof(Console)) - { - Console.WriteLine($"[Server] Sent {sendResult.Count} bytes to {sendResult.RemoteEndPoint}"); - Console.WriteLine($"[Server] >>>> {Encoding.UTF8.GetString(sendResult.Buffer.Span)}"); - } -#endif - } - } - catch (OperationCanceledException) - { - Console.WriteLine($"Client task for {clientArgs.RemoteEndPoint} cancelled!"); - } - finally - { - DestroyConnectionArgs(clientArgs); + RentedBuffer = rentedBuffer; } } - private readonly struct ClientRequest + protected override SocketAsyncEventArgs CreateTransmissionArgs() { - public readonly NetworkPacket RequestPacket; - - public readonly EndPoint ClientEndPoint; + SocketAsyncEventArgs connectionArgs = new SocketAsyncEventArgs(); - public readonly CancellationToken CancellationToken; + connectionArgs.Completed += HandleIoCompleted; - public ClientRequest(in NetworkPacket requestPacket, in EndPoint clientEndPoint, in CancellationToken cancellationToken) - { - RequestPacket = requestPacket; - - ClientEndPoint = clientEndPoint; - - CancellationToken = cancellationToken; - } + return connectionArgs; } - private async Task HandleClientRequest(ClientRequest clientRequest) + protected override void ResetTransmissionArgs(SocketAsyncEventArgs args) { - SocketAsyncEventArgs clientArgs = TransmissionArgsPool.Get(); - - byte[] responseBuffer = BufferPool.Rent(NetworkPacket.TotalSize); - Memory<byte> responseBufferMemory = new Memory<byte>(responseBuffer); - - NetworkPacket request = clientRequest.RequestPacket; - EndPoint remoteEndPoint = clientRequest.ClientEndPoint; - CancellationToken cancellationToken = clientRequest.CancellationToken; - - // TODO implement actual request handling, besides just an echo - NetworkPacket response = request; - - NetworkPacket.Serialise(response, responseBufferMemory); - - TransmissionResult sendResult = - await SocketAsyncOperations - .SendToAsync(clientArgs, connection, remoteEndPoint, SocketFlags.None, responseBufferMemory, cancellationToken) - .ConfigureAwait(false); - -#if DEBUG - lock (typeof(Console)) - { - Console.WriteLine($"[Server] Sent {sendResult.Count} bytes to {sendResult.RemoteEndPoint}"); - Console.WriteLine($"[Server] >>>> {Encoding.UTF8.GetString(sendResult.Buffer.Span)}"); - } -#endif - - BufferPool.Return(responseBuffer, true); - - TransmissionArgsPool.Return(clientArgs); } - private readonly struct ClientPacket + protected override bool CanTransmissionArgsBeReused(in SocketAsyncEventArgs args) { - public readonly SocketAsyncEventArgs RentedArgs; - - public readonly byte[] RentedBuffer; - - public readonly Memory<byte> RentedBufferMemory; - - public readonly EndPoint RemoteEndPoint; - - public ClientPacket(in SocketAsyncEventArgs rentedArgs, in byte[] rentedBuffer, in Memory<byte> rentedBufferMemory, in EndPoint remoteEndPoint) - { - RentedArgs = rentedArgs; - - RentedBuffer = rentedBuffer; - - RentedBufferMemory = rentedBufferMemory; - - RemoteEndPoint = remoteEndPoint; - } + return true; } - private readonly struct SocketOperationToken + protected override void DestroyTransmissionArgs(SocketAsyncEventArgs remoteConnectionArgs) { - public readonly byte[] RentedBuffer; - - public readonly Memory<byte> RentedBufferMemory; - - public SocketOperationToken(in byte[] rentedBuffer, in Memory<byte> rentedBufferMemory) - { - RentedBuffer = rentedBuffer; + remoteConnectionArgs.Completed -= HandleIoCompleted; - RentedBufferMemory = rentedBufferMemory; - } + remoteConnectionArgs.Dispose(); } - private void HandleIoCompleted(object sender, SocketAsyncEventArgs args) + protected override void HandleIoCompleted(object sender, SocketAsyncEventArgs args) { switch (args.LastOperation) { @@ -229,7 +89,7 @@ namespace NetSharp.Sockets.Datagram break; case SocketAsyncOperation.ReceiveFrom: - DoReceiveFrom(AnyRemoteEndPoint); // start a new receive from operation immediately, to not drop any packets + ReceiveFrom(AnyRemoteEndPoint); // start a new receive from operation immediately, to not drop any packets CompleteReceiveFrom(args); break; @@ -239,11 +99,9 @@ namespace NetSharp.Sockets.Datagram } } - private void DoSendTo(SocketAsyncEventArgs sendArgs) + private void SendTo(SocketAsyncEventArgs sendArgs) { - bool completesAsync = connection.SendToAsync(sendArgs); - - if (!completesAsync) + if (!connection.SendToAsync(sendArgs)) { CompleteSendTo(sendArgs); } @@ -253,7 +111,7 @@ namespace NetSharp.Sockets.Datagram { SocketOperationToken sendToken = (SocketOperationToken) sendArgs.UserToken; - TransmissionResult sendResult = new TransmissionResult(sendArgs); + TransmissionResult sendResult = new TransmissionResult(in sendArgs); #if DEBUG lock (typeof(Console)) @@ -265,25 +123,23 @@ namespace NetSharp.Sockets.Datagram BufferPool.Return(sendToken.RentedBuffer, true); - ArgsPool.Return(sendArgs); + TransmissionArgsPool.Return(sendArgs); } - private void DoReceiveFrom(EndPoint remoteEndPoint) + private void ReceiveFrom(EndPoint remoteEndPoint) { - SocketAsyncEventArgs args = ArgsPool.Rent(); + SocketAsyncEventArgs args = TransmissionArgsPool.Rent(); byte[] receiveBuffer = BufferPool.Rent(NetworkPacket.TotalSize); Memory<byte> receiveBufferMemory = new Memory<byte>(receiveBuffer); args.SetBuffer(receiveBufferMemory); args.RemoteEndPoint = remoteEndPoint; - args.UserToken = new SocketOperationToken(in receiveBuffer, in receiveBufferMemory); - - bool completesAsync = connection.ReceiveFromAsync(args); + args.UserToken = new SocketOperationToken(in receiveBuffer); - if (!completesAsync) + if (!connection.ReceiveFromAsync(args)) { - DoReceiveFrom(AnyRemoteEndPoint); // start a new receive from operation immediately, to not drop any packets + ReceiveFrom(AnyRemoteEndPoint); // start a new receive from operation immediately, to not drop any packets CompleteReceiveFrom(args); } @@ -293,7 +149,7 @@ namespace NetSharp.Sockets.Datagram { SocketOperationToken receiveToken = (SocketOperationToken)receiveArgs.UserToken; - TransmissionResult receiveResult = new TransmissionResult(receiveArgs); + TransmissionResult receiveResult = new TransmissionResult(in receiveArgs); #if DEBUG lock (typeof(Console)) @@ -305,9 +161,10 @@ namespace NetSharp.Sockets.Datagram NetworkPacket request = NetworkPacket.Deserialise(receiveArgs.MemoryBuffer); + // TODO implement actual request processing, not just an echo server NetworkPacket response = request; - SocketAsyncEventArgs sendArgs = ArgsPool.Rent(); + SocketAsyncEventArgs sendArgs = TransmissionArgsPool.Rent(); byte[] sendBuffer = BufferPool.Rent(NetworkPacket.TotalSize); Memory<byte> sendBufferMemory = new Memory<byte>(sendBuffer); @@ -316,225 +173,23 @@ namespace NetSharp.Sockets.Datagram sendArgs.SetBuffer(sendBufferMemory); sendArgs.RemoteEndPoint = receiveResult.RemoteEndPoint; - sendArgs.UserToken = new SocketOperationToken(in sendBuffer, in sendBufferMemory); + sendArgs.UserToken = new SocketOperationToken(in sendBuffer); - DoSendTo(sendArgs); + SendTo(sendArgs); BufferPool.Return(receiveToken.RentedBuffer, true); - ArgsPool.Return(receiveArgs); + TransmissionArgsPool.Return(receiveArgs); } public override Task RunAsync(CancellationToken cancellationToken = default) { for (int i = 0; i < 10; i++) { - DoReceiveFrom(AnyRemoteEndPoint); + ReceiveFrom(AnyRemoteEndPoint); } return cancellationToken.WaitHandle.WaitOneAsync(); - /* - UnboundedChannelOptions requestChannelOptions = new UnboundedChannelOptions() - { - AllowSynchronousContinuations = true, - SingleReader = true, - SingleWriter = true, - }; - Channel<ClientPacket> requestChannel = Channel.CreateUnbounded<ClientPacket>(requestChannelOptions); - - UnboundedChannelOptions responseChannelOptions = new UnboundedChannelOptions() - { - AllowSynchronousContinuations = true, - SingleReader = true, - SingleWriter = true, - }; - Channel<ClientPacket> responseChannel = Channel.CreateUnbounded<ClientPacket>(responseChannelOptions); - - async Task ReceivePacketTask() - { - EndPoint anyRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - - while (!cancellationToken.IsCancellationRequested) - { - SocketAsyncEventArgs transmissionArgs = TransmissionArgsPool.Get(); - - byte[] requestBuffer = BufferPool.Rent(NetworkPacket.TotalSize); - Memory<byte> requestBufferMemory = new Memory<byte>(requestBuffer); - - TransmissionResult receiveResult = - await SocketAsyncOperations - .ReceiveFromAsync(transmissionArgs, connection, anyRemoteEndPoint, SocketFlags.None, requestBufferMemory, cancellationToken) - .ConfigureAwait(false); - -#if DEBUG - lock (typeof(Console)) - { - Console.WriteLine($"[Server] Received {receiveResult.Count} bytes from {receiveResult.RemoteEndPoint}"); - Console.WriteLine($"[Server] <<<< {Encoding.UTF8.GetString(receiveResult.Buffer.Span)}"); - } -#endif - ClientPacket request = new ClientPacket(in transmissionArgs, in requestBuffer, in requestBufferMemory, in receiveResult.RemoteEndPoint); - - await requestChannel.Writer.WriteAsync(request, cancellationToken); - } - } - - async Task HandleRequestTask() - { - while (!cancellationToken.IsCancellationRequested) - { - ClientPacket request = await requestChannel.Reader.ReadAsync(cancellationToken); - - NetworkPacket requestPacket = NetworkPacket.Deserialise(request.RentedBufferMemory); - - // TODO implement actual request handling, besides just an echo - NetworkPacket responsePacket = requestPacket; - - byte[] responseBuffer = BufferPool.Rent(NetworkPacket.TotalSize); - Memory<byte> responseBufferMemory = new Memory<byte>(responseBuffer); - - NetworkPacket.Serialise(responsePacket, responseBufferMemory); - - // after the response has been serialised to the response buffer, the request buffer is done with and can be freed - BufferPool.Return(request.RentedBuffer, true); - - ClientPacket response = new ClientPacket(in request.RentedArgs, in responseBuffer, in responseBufferMemory, in request.RemoteEndPoint); - - await responseChannel.Writer.WriteAsync(response, cancellationToken); - } - } - - async Task SendResponseTask() - { - while (!cancellationToken.IsCancellationRequested) - { - ClientPacket response = await responseChannel.Reader.ReadAsync(cancellationToken); - - EndPoint remoteEndPoint = response.RemoteEndPoint; - Memory<byte> responseBufferMemory = response.RentedBufferMemory; - - TransmissionResult sendResult = - await SocketAsyncOperations - .SendToAsync(response.RentedArgs, connection, remoteEndPoint, SocketFlags.None, responseBufferMemory, cancellationToken) - .ConfigureAwait(false); - -#if DEBUG - lock (typeof(Console)) - { - Console.WriteLine($"[Server] Sent {sendResult.Count} bytes to {sendResult.RemoteEndPoint}"); - Console.WriteLine($"[Server] >>>> {Encoding.UTF8.GetString(sendResult.Buffer.Span)}"); - } -#endif - - BufferPool.Return(response.RentedBuffer, true); - - TransmissionArgsPool.Return(response.RentedArgs); - } - } - - // TODO this still functions as the simple example below, in fact it performs worse, with a worse bandwidth :( - List<Task> completeTaskList = new List<Task>(); - - Task[] readRequestTasks = new Task[2]; - for (int i = 0; i < readRequestTasks.Length; i++) - { - readRequestTasks[i] = ReceivePacketTask(); - completeTaskList.Add(readRequestTasks[i]); - } - - Task[] handleRequestTasks = new Task[2]; - for (int i = 0; i < handleRequestTasks.Length; i++) - { - handleRequestTasks[i] = HandleRequestTask(); - completeTaskList.Add(handleRequestTasks[i]); - } - - Task[] writeResponseTasks = new Task[2]; - for (int i = 0; i < writeResponseTasks.Length; i++) - { - writeResponseTasks[i] = SendResponseTask(); - completeTaskList.Add(writeResponseTasks[i]); - } - - await Task.WhenAll(completeTaskList); - */ - - /* - EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - using SocketAsyncEventArgs remoteArgs = GenerateConnectionArgs(remoteEndPoint); - - byte[] requestBuffer = new byte[NetworkPacket.TotalSize]; - Memory<byte> requestBufferMemory = new Memory<byte>(requestBuffer); - - while (!cancellationToken.IsCancellationRequested) - { - TransmissionResult receiveResult = - await SocketAsyncOperations - .ReceiveFromAsync(remoteArgs, connection, remoteEndPoint, SocketFlags.None, requestBufferMemory, cancellationToken) - .ConfigureAwait(false); - - EndPoint clientEndPoint = receiveResult.RemoteEndPoint; - -#if DEBUG - lock (typeof(Console)) - { - Console.WriteLine($"[Server] Received {receiveResult.Count} bytes from {receiveResult.RemoteEndPoint}"); - Console.WriteLine($"[Server] <<<< {Encoding.UTF8.GetString(receiveResult.Buffer.Span)}"); - } -#endif - - NetworkPacket requestPacket = NetworkPacket.Deserialise(requestBufferMemory); - - ClientRequest request = new ClientRequest(in requestPacket, in clientEndPoint, in cancellationToken); - - Task _ = HandleClientRequest(request); - } - */ - - /* - EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - using SocketAsyncEventArgs remoteArgs = GenerateConnectionArgs(remoteEndPoint); - - byte[] requestBuffer = new byte[NetworkPacket.TotalSize]; - Memory<byte> requestBufferMemory = new Memory<byte>(requestBuffer); - - while (!cancellationToken.IsCancellationRequested) - { - remoteArgs.RemoteEndPoint = remoteEndPoint; - - TransmissionResult receiveResult = - await SocketAsyncOperations - .ReceiveFromAsync(remoteArgs, connection, remoteEndPoint, SocketFlags.None, requestBufferMemory, cancellationToken) - .ConfigureAwait(false); - - EndPoint clientEndPoint = receiveResult.RemoteEndPoint; - -#if DEBUG - lock (typeof(Console)) - { - Console.WriteLine($"[Server] Received {receiveResult.Count} bytes from {receiveResult.RemoteEndPoint}"); - Console.WriteLine($"[Server] <<<< {Encoding.UTF8.GetString(receiveResult.Buffer.Span)}"); - } -#endif - - if (!ConnectedClientHandlerTasks.ContainsKey(clientEndPoint)) - { - SocketAsyncEventArgs clientArgs = GenerateConnectionArgs(receiveResult.RemoteEndPoint); - - BoundedChannelOptions clientChannelOptions = new BoundedChannelOptions(60) - { FullMode = BoundedChannelFullMode.DropOldest, SingleReader = true, SingleWriter = true }; - Channel<NetworkPacket> clientChannel = Channel.CreateBounded<NetworkPacket>(clientChannelOptions); - - connectedClientTokens[clientEndPoint] = new RemoteDatagramClientToken(in clientChannel); - - ConnectedClientHandlerTasks[clientEndPoint] = HandleClient(clientArgs, cancellationToken); - } - - NetworkPacket request = NetworkPacket.Deserialise(requestBufferMemory); - - await connectedClientTokens[clientEndPoint].PacketWriter.WriteAsync(request, cancellationToken); - } - */ } } } \ No newline at end of file diff --git a/NetSharp/NetSharp/Sockets/SocketAsyncOperations.cs b/NetSharp/NetSharp/Sockets/SocketAsyncOperations.cs @@ -101,7 +101,7 @@ namespace NetSharp.Sockets } else if (args.BytesTransferred > 0) { - TransmissionResult result = new TransmissionResult(args); + TransmissionResult result = new TransmissionResult(in args); asyncReceiveToken.CompletionSource.SetResult(result); } @@ -130,7 +130,7 @@ namespace NetSharp.Sockets } else { - TransmissionResult result = new TransmissionResult(args); + TransmissionResult result = new TransmissionResult(in args); asyncReceiveFromToken.CompletionSource.SetResult(result); } @@ -154,7 +154,7 @@ namespace NetSharp.Sockets } else { - TransmissionResult result = new TransmissionResult(args); + TransmissionResult result = new TransmissionResult(in args); asyncSendToken.CompletionSource.SetResult(result); } @@ -178,7 +178,7 @@ namespace NetSharp.Sockets } else { - TransmissionResult result = new TransmissionResult(args); + TransmissionResult result = new TransmissionResult(in args); asyncSendToToken.CompletionSource.SetResult(result); } @@ -245,7 +245,7 @@ namespace NetSharp.Sockets // if the receive operation doesn't complete synchronously, returns the awaitable task if (socket.ReceiveAsync(socketArgs)) return new ValueTask<TransmissionResult>(tcs.Task); - TransmissionResult result = new TransmissionResult(socketArgs); + TransmissionResult result = new TransmissionResult(in socketArgs); return new ValueTask<TransmissionResult>(result); } @@ -263,7 +263,7 @@ namespace NetSharp.Sockets // if the receive operation doesn't complete synchronously, returns the awaitable task if (socket.ReceiveFromAsync(socketArgs)) return new ValueTask<TransmissionResult>(tcs.Task); - TransmissionResult result = new TransmissionResult(socketArgs); + TransmissionResult result = new TransmissionResult(in socketArgs); return new ValueTask<TransmissionResult>(result); } @@ -281,7 +281,7 @@ namespace NetSharp.Sockets // if the send operation doesn't complete synchronously, return the awaitable task if (socket.SendAsync(socketArgs)) return new ValueTask<TransmissionResult>(tcs.Task); - TransmissionResult result = new TransmissionResult(socketArgs); + TransmissionResult result = new TransmissionResult(in socketArgs); return new ValueTask<TransmissionResult>(result); } @@ -299,7 +299,7 @@ namespace NetSharp.Sockets // if the send operation doesn't complete synchronously, return the awaitable task if (socket.SendToAsync(socketArgs)) return new ValueTask<TransmissionResult>(tcs.Task); - TransmissionResult result = new TransmissionResult(socketArgs); + TransmissionResult result = new TransmissionResult(in socketArgs); return new ValueTask<TransmissionResult>(result); } diff --git a/NetSharp/NetSharp/Sockets/SocketClient.cs b/NetSharp/NetSharp/Sockets/SocketClient.cs @@ -11,15 +11,11 @@ namespace NetSharp.Sockets { public abstract class SocketClient : SocketConnection { - protected readonly ArrayPool<byte> BufferPool; - protected readonly SocketAsyncEventArgs Args; protected SocketClient(in AddressFamily connectionAddressFamily, in SocketType connectionSocketType, in ProtocolType connectionProtocolType) : base(in connectionAddressFamily, in connectionSocketType, in connectionProtocolType) { - BufferPool = ArrayPool<byte>.Create(NetworkPacket.TotalSize, 10); - Args = new SocketAsyncEventArgs(); Args.Completed += SocketAsyncOperations.HandleIoCompleted; } @@ -34,11 +30,6 @@ namespace NetSharp.Sockets return sentBytes; } - public ValueTask<TransmissionResult> SendBytesTo(Memory<byte> outgoingDataBuffer, EndPoint remoteEndPoint, SocketFlags flags = SocketFlags.None) - { - return SocketAsyncOperations.SendToAsync(Args, connection, remoteEndPoint, flags, outgoingDataBuffer); - } - public int ReceiveBytes(Memory<byte> incomingDataBuffer, SocketFlags flags = SocketFlags.None) { byte[] temporaryBuffer = BufferPool.Rent(NetworkPacket.TotalSize); @@ -48,10 +39,5 @@ namespace NetSharp.Sockets return receivedBytes; } - - public ValueTask<TransmissionResult> ReceiveBytesFrom(Memory<byte> incomingDataBuffer, ref EndPoint remoteEndPoint, SocketFlags flags = SocketFlags.None) - { - return SocketAsyncOperations.ReceiveFromAsync(Args, connection, remoteEndPoint, flags, incomingDataBuffer); - } } } \ No newline at end of file diff --git a/NetSharp/NetSharp/Sockets/SocketConnection.cs b/NetSharp/NetSharp/Sockets/SocketConnection.cs @@ -1,6 +1,9 @@ using System; +using System.Buffers; using System.Net; using System.Net.Sockets; +using NetSharp.Packets; +using NetSharp.Utils; namespace NetSharp.Sockets { @@ -8,11 +11,29 @@ namespace NetSharp.Sockets { protected readonly Socket connection; + protected readonly ArrayPool<byte> BufferPool; + + protected readonly SlimObjectPool<SocketAsyncEventArgs> TransmissionArgsPool; + protected SocketConnection(in AddressFamily connectionAddressFamily, in SocketType connectionSocketType, in ProtocolType connectionProtocolType) { connection = new Socket(connectionAddressFamily, connectionSocketType, connectionProtocolType); + + BufferPool = ArrayPool<byte>.Create(NetworkPacket.TotalSize, 1000); + + TransmissionArgsPool = new SlimObjectPool<SocketAsyncEventArgs>(CreateTransmissionArgs, ResetTransmissionArgs, DestroyTransmissionArgs, CanTransmissionArgsBeReused); } + protected abstract SocketAsyncEventArgs CreateTransmissionArgs(); + + protected abstract void ResetTransmissionArgs(SocketAsyncEventArgs args); + + protected abstract bool CanTransmissionArgsBeReused(in SocketAsyncEventArgs args); + + protected abstract void DestroyTransmissionArgs(SocketAsyncEventArgs remoteConnectionArgs); + + protected abstract void HandleIoCompleted(object sender, SocketAsyncEventArgs args); + public void Bind(in EndPoint localEndPoint) { connection.Bind(localEndPoint); diff --git a/NetSharp/NetSharp/Sockets/SocketServer.cs b/NetSharp/NetSharp/Sockets/SocketServer.cs @@ -1,12 +1,8 @@ -using NetSharp.Packets; - -using System.Buffers; -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.ObjectPool; namespace NetSharp.Sockets { @@ -14,44 +10,12 @@ namespace NetSharp.Sockets { protected readonly ConcurrentDictionary<EndPoint, Task> ConnectedClientHandlerTasks; - protected readonly ArrayPool<byte> BufferPool; - - protected readonly ObjectPool<SocketAsyncEventArgs> TransmissionArgsPool; - protected SocketServer(in AddressFamily connectionAddressFamily, in SocketType connectionSocketType, in ProtocolType connectionProtocolType) : base(in connectionAddressFamily, in connectionSocketType, in connectionProtocolType) { - BufferPool = ArrayPool<byte>.Create(NetworkPacket.TotalSize, 100); - - TransmissionArgsPool = new DefaultObjectPool<SocketAsyncEventArgs>(new PooledSocketAsyncEventArgsPolicy()); - ConnectedClientHandlerTasks = new ConcurrentDictionary<EndPoint, Task>(); } - protected abstract SocketAsyncEventArgs GenerateConnectionArgs(EndPoint remoteEndPoint); - - protected abstract void DestroyConnectionArgs(SocketAsyncEventArgs remoteConnectionArgs); - - protected abstract Task HandleClient(SocketAsyncEventArgs clientArgs, - CancellationToken cancellationToken = default); - public abstract Task RunAsync(CancellationToken cancellationToken = default); } - - public class PooledSocketAsyncEventArgsPolicy : IPooledObjectPolicy<SocketAsyncEventArgs> - { - public SocketAsyncEventArgs Create() - { - SocketAsyncEventArgs args = new SocketAsyncEventArgs(); - - args.Completed += SocketAsyncOperations.HandleIoCompleted; - - return args; - } - - public bool Return(SocketAsyncEventArgs obj) - { - return true; - } - } } \ No newline at end of file diff --git a/NetSharp/NetSharp/Sockets/Stream/StreamSocketClient.cs b/NetSharp/NetSharp/Sockets/Stream/StreamSocketClient.cs @@ -19,5 +19,30 @@ namespace NetSharp.Sockets.Stream { connection.Disconnect(true); } + + protected override SocketAsyncEventArgs CreateTransmissionArgs() + { + throw new System.NotImplementedException(); + } + + protected override void ResetTransmissionArgs(SocketAsyncEventArgs args) + { + throw new System.NotImplementedException(); + } + + protected override bool CanTransmissionArgsBeReused(in SocketAsyncEventArgs args) + { + throw new System.NotImplementedException(); + } + + protected override void DestroyTransmissionArgs(SocketAsyncEventArgs remoteConnectionArgs) + { + throw new System.NotImplementedException(); + } + + protected override void HandleIoCompleted(object sender, SocketAsyncEventArgs args) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/NetSharp/NetSharp/Sockets/Stream/StreamSocketServer.cs b/NetSharp/NetSharp/Sockets/Stream/StreamSocketServer.cs @@ -11,6 +11,23 @@ using NetSharp.Utils; namespace NetSharp.Sockets.Stream { + public readonly struct StreamSocketServerOptions + { + public static readonly StreamSocketServerOptions Defaults = + new StreamSocketServerOptions(NetworkPacket.TotalSize, 8); + + public readonly int PacketSize; + + public readonly int ConcurrentReceiveCalls; + + public StreamSocketServerOptions(int packetSize, int concurrentReceiveCalls) + { + PacketSize = packetSize; + + ConcurrentReceiveCalls = concurrentReceiveCalls; + } + } + public class StreamSocketServer : SocketServer { private readonly ConcurrentDictionary<EndPoint, RemoteStreamClientToken> connectedClientTokens; @@ -31,22 +48,37 @@ namespace NetSharp.Sockets.Stream } } - public StreamSocketServer(in AddressFamily connectionAddressFamily, in ProtocolType connectionProtocolType) - : base(in connectionAddressFamily, SocketType.Stream, in connectionProtocolType) + public readonly StreamSocketServerOptions ServerOptions; + + public StreamSocketServer(in AddressFamily connectionAddressFamily, in ProtocolType connectionProtocolType, + in StreamSocketServerOptions serverOptions = default) : base(in connectionAddressFamily, SocketType.Stream, + in connectionProtocolType) { connectedClientTokens = new ConcurrentDictionary<EndPoint, RemoteStreamClientToken>(); + + ServerOptions = serverOptions.Equals(default) ? StreamSocketServerOptions.Defaults : serverOptions; } - protected override SocketAsyncEventArgs GenerateConnectionArgs(EndPoint remoteEndPoint) + protected override SocketAsyncEventArgs CreateTransmissionArgs() { - SocketAsyncEventArgs connectionArgs = new SocketAsyncEventArgs { RemoteEndPoint = remoteEndPoint }; + SocketAsyncEventArgs connectionArgs = new SocketAsyncEventArgs(); - connectionArgs.Completed += SocketAsyncOperations.HandleIoCompleted; + connectionArgs.Completed += HandleIoCompleted; return connectionArgs; } - protected override void DestroyConnectionArgs(SocketAsyncEventArgs remoteConnectionArgs) + protected override void ResetTransmissionArgs(SocketAsyncEventArgs args) + { + + } + + protected override bool CanTransmissionArgsBeReused(in SocketAsyncEventArgs args) + { + return false; + } + + protected override void DestroyTransmissionArgs(SocketAsyncEventArgs remoteConnectionArgs) { remoteConnectionArgs.AcceptSocket.Shutdown(SocketShutdown.Both); remoteConnectionArgs.AcceptSocket.Close(); @@ -56,7 +88,12 @@ namespace NetSharp.Sockets.Stream remoteConnectionArgs.Dispose(); } - protected override async Task HandleClient(SocketAsyncEventArgs clientArgs, CancellationToken cancellationToken = default) + protected override void HandleIoCompleted(object sender, SocketAsyncEventArgs args) + { + throw new NotImplementedException(); + } + + protected async Task HandleClient(SocketAsyncEventArgs clientArgs, CancellationToken cancellationToken = default) { EndPoint clientEndPoint = clientArgs.AcceptSocket.RemoteEndPoint; RemoteStreamClientToken clientToken = connectedClientTokens[clientEndPoint]; @@ -119,7 +156,7 @@ namespace NetSharp.Sockets.Stream } finally { - DestroyConnectionArgs(clientArgs); + TransmissionArgsPool.Return(clientArgs); } } @@ -131,7 +168,7 @@ namespace NetSharp.Sockets.Stream while (!cancellationToken.IsCancellationRequested) { - SocketAsyncEventArgs clientArgs = GenerateConnectionArgs(remoteEndPoint); + SocketAsyncEventArgs clientArgs = TransmissionArgsPool.Rent(); await SocketAsyncOperations.AcceptAsync(clientArgs, connection, cancellationToken); diff --git a/NetSharp/NetSharp/Utils/MyObjectPool.cs b/NetSharp/NetSharp/Utils/MyObjectPool.cs @@ -1,54 +0,0 @@ -using System.Collections.Concurrent; - -namespace NetSharp.Utils -{ - internal class MyObjectPool<T> where T : class - { - internal delegate T CreateObjectDelegate(); - - internal delegate bool KeepObjectPredicate(in T instance); - - internal delegate void ResetObjectDelegate(T instance); - - internal delegate void DestroyObjectDelegate(T instance); - - private readonly CreateObjectDelegate createObjectDelegate; - private readonly KeepObjectPredicate rebufferObjectPredicate; - private readonly ResetObjectDelegate resetObjectDelegate; - private readonly DestroyObjectDelegate destroyObjectDelegate; - - private readonly ConcurrentBag<T> objectBuffer; - - internal MyObjectPool(in CreateObjectDelegate createDelegate, in ResetObjectDelegate resetDelegate, in DestroyObjectDelegate destroyDelegate, in KeepObjectPredicate keepObjectPredicate) - { - createObjectDelegate = createDelegate; - - resetObjectDelegate = resetDelegate; - - destroyObjectDelegate = destroyDelegate; - - rebufferObjectPredicate = keepObjectPredicate; - - objectBuffer = new ConcurrentBag<T>(); - } - - internal T Rent() - { - return objectBuffer.TryTake(out T result) ? result : createObjectDelegate(); - } - - internal void Return(T instance) - { - if (rebufferObjectPredicate(instance)) - { - resetObjectDelegate(instance); - - objectBuffer.Add(instance); - } - else - { - destroyObjectDelegate(instance); - } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Utils/SlimObjectPool.cs b/NetSharp/NetSharp/Utils/SlimObjectPool.cs @@ -0,0 +1,54 @@ +using System.Collections.Concurrent; + +namespace NetSharp.Utils +{ + public class SlimObjectPool<T> where T : class + { + public delegate T CreateObjectDelegate(); + + public delegate bool CanRebufferObjectPredicate(in T instance); + + public delegate void ResetObjectDelegate(T instance); + + public delegate void DestroyObjectDelegate(T instance); + + private readonly CreateObjectDelegate createObjectDelegate; + private readonly CanRebufferObjectPredicate canObjectBeRebufferedPredicate; + private readonly ResetObjectDelegate resetObjectDelegate; + private readonly DestroyObjectDelegate destroyObjectDelegate; + + private readonly ConcurrentQueue<T> objectBuffer; + + public SlimObjectPool(in CreateObjectDelegate createDelegate, in ResetObjectDelegate resetDelegate, in DestroyObjectDelegate destroyDelegate, in CanRebufferObjectPredicate rebufferPredicate) + { + createObjectDelegate = createDelegate; + + resetObjectDelegate = resetDelegate; + + destroyObjectDelegate = destroyDelegate; + + canObjectBeRebufferedPredicate = rebufferPredicate; + + objectBuffer = new ConcurrentQueue<T>(); + } + + public T Rent() + { + return objectBuffer.TryDequeue(out T result) ? result : createObjectDelegate(); + } + + public void Return(T instance) + { + if (canObjectBeRebufferedPredicate(instance)) + { + resetObjectDelegate(instance); + + objectBuffer.Enqueue(instance); + } + else + { + destroyObjectDelegate(instance); + } + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp/Utils/TransmissionResult.cs b/NetSharp/NetSharp/Utils/TransmissionResult.cs @@ -13,15 +13,27 @@ namespace NetSharp.Utils /// Initialises a new instance of the <see cref="TransmissionResult"/> struct. /// </summary> /// <param name="args">The socket arguments associated with the transmission.</param> - internal TransmissionResult(SocketAsyncEventArgs args) + internal TransmissionResult(in SocketAsyncEventArgs args) { - TransmissionArgs = args; Buffer = args.MemoryBuffer; Count = args.BytesTransferred; RemoteEndPoint = args.RemoteEndPoint; } /// <summary> + /// Initialises a new instance of the <see cref="TransmissionResult"/> struct. + /// </summary> + /// <param name="buffer">The buffer associated with the transmission.</param> + /// <param name="count">The number of bytes written to or read from the buffer.</param> + /// <param name="remoteEndPoint">The remote end point associated with the transmission.</param> + internal TransmissionResult(in byte[] buffer, in int count, in EndPoint remoteEndPoint) + { + Buffer = buffer; + Count = count; + RemoteEndPoint = remoteEndPoint; + } + + /// <summary> /// The byte buffer that was transmitted across the network. /// </summary> public readonly Memory<byte> Buffer; @@ -35,10 +47,5 @@ namespace NetSharp.Utils /// The remote endpoint to which the buffer was transmitted. /// </summary> public readonly EndPoint RemoteEndPoint; - - /// <summary> - /// Socket arguments and other data associated with the transmission. - /// </summary> - public readonly SocketAsyncEventArgs TransmissionArgs; } } \ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Program.cs b/NetSharp/NetSharpExamples/Program.cs @@ -44,8 +44,8 @@ namespace NetSharpExamples private static async Task TestSocketClient() { - const int clientCount = 24; - const long packetsToSend = 100_000; + const int clientCount = 10; + const long packetsToSend = 1_000_000; Task[] clientTasks = new Task[clientCount]; double[] clientBandwidths = new double[clientCount]; @@ -82,6 +82,8 @@ namespace NetSharpExamples client.Connect(in ServerEndPoint); #endif + EndPoint remoteEndPoint = ServerEndPoint; + byte[] requestBuffer = new byte[NetworkPacket.TotalSize]; Memory<byte> requestBufferMemory = new Memory<byte>(requestBuffer); @@ -96,14 +98,15 @@ namespace NetSharpExamples for (int i = 0; i < packetsToSend; i++) { - Encoding.UTF8.GetBytes($"Hello World! (Packet {i})").CopyTo(requestBufferMemory); + Encoding.UTF8.GetBytes($"[Client {id}] Hello World! (Packet {i})").CopyTo(requestBufferMemory); rttStopwatch.Start(); bandwidthStopwatch.Start(); + #if TCP int sendResult = client.SendBytes(requestBufferMemory); #else - TransmissionResult sendResult = await client.SendBytesTo(requestBufferMemory, ServerEndPoint); + TransmissionResult sendResult = client.SendTo(remoteEndPoint, requestBuffer); #endif bandwidthStopwatch.Stop(); @@ -117,15 +120,13 @@ namespace NetSharpExamples } #endif - EndPoint serverEndPoint = ServerEndPoint; - rttStopwatch.Start(); bandwidthStopwatch.Start(); #if TCP int receiveResult = client.ReceiveBytes(responseBufferMemory); #else - TransmissionResult receiveResult = await client.ReceiveBytesFrom(responseBufferMemory, ref serverEndPoint); + TransmissionResult receiveResult = client.ReceiveFrom(ref remoteEndPoint, responseBuffer); #endif bandwidthStopwatch.Stop(); @@ -200,7 +201,7 @@ namespace NetSharpExamples for (int clientId = 0; clientId < clientCount; clientId++) { - clientTasks[clientId] = Task.Factory.StartNew(ClientTask, clientId, TaskCreationOptions.LongRunning).Result; + clientTasks[clientId] = Task.Factory.StartNew(ClientTask, clientId, TaskCreationOptions.LongRunning); } await Task.WhenAll(clientTasks);