Advertisement
Guest User

Untitled

a guest
Apr 9th, 2020
13
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.11 KB | None | 0 0
  1. using NetSharp.Packets;
  2. using NetSharp.Utils;
  3.  
  4. using System;
  5. using System.Collections.Concurrent;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Channels;
  11. using System.Threading.Tasks;
  12.  
  13. namespace NetSharp.Sockets.Datagram
  14. {
  15. public class DatagramSocketServer : SocketServer
  16. {
  17. private readonly ConcurrentDictionary<EndPoint, RemoteDatagramClientToken> connectedClientTokens;
  18.  
  19. private readonly struct RemoteDatagramClientToken
  20. {
  21. private readonly Channel<NetworkPacket> PacketChannel;
  22.  
  23. public readonly ChannelReader<NetworkPacket> PacketReader;
  24.  
  25. public readonly ChannelWriter<NetworkPacket> PacketWriter;
  26.  
  27. public RemoteDatagramClientToken(in Channel<NetworkPacket> packetChannel)
  28. {
  29. PacketChannel = packetChannel;
  30. PacketReader = packetChannel.Reader;
  31. PacketWriter = packetChannel.Writer;
  32. }
  33. }
  34.  
  35. public DatagramSocketServer(in AddressFamily connectionAddressFamily, in ProtocolType connectionProtocolType)
  36. : base(in connectionAddressFamily, SocketType.Dgram, in connectionProtocolType)
  37. {
  38. connectedClientTokens = new ConcurrentDictionary<EndPoint, RemoteDatagramClientToken>();
  39. }
  40.  
  41. protected override SocketAsyncEventArgs GenerateConnectionArgs(EndPoint remoteEndPoint)
  42. {
  43. SocketAsyncEventArgs connectionArgs = new SocketAsyncEventArgs { RemoteEndPoint = remoteEndPoint };
  44.  
  45. connectionArgs.Completed += SocketAsyncOperations.HandleIoCompleted;
  46.  
  47. return connectionArgs;
  48. }
  49.  
  50. protected override void DestroyConnectionArgs(SocketAsyncEventArgs remoteConnectionArgs)
  51. {
  52. remoteConnectionArgs.Completed -= SocketAsyncOperations.HandleIoCompleted;
  53.  
  54. remoteConnectionArgs.Dispose();
  55. }
  56.  
  57. protected override async Task HandleClient(SocketAsyncEventArgs clientArgs, CancellationToken cancellationToken = default)
  58. {
  59. EndPoint clientEndPoint = clientArgs.RemoteEndPoint;
  60. RemoteDatagramClientToken clientToken = connectedClientTokens[clientEndPoint];
  61.  
  62. byte[] responseBuffer = new byte[NetworkPacket.TotalSize];
  63. Memory<byte> responseBufferMemory = new Memory<byte>(responseBuffer);
  64.  
  65. try
  66. {
  67. while (!cancellationToken.IsCancellationRequested)
  68. {
  69. NetworkPacket request = await clientToken.PacketReader.ReadAsync(cancellationToken);
  70.  
  71. // TODO implement actual request handling, besides just an echo
  72. NetworkPacket response = NetworkPacket.Duplicate(in request);
  73.  
  74. NetworkPacket.Serialise(response, responseBufferMemory);
  75.  
  76. TransmissionResult sendResult =
  77. await SocketAsyncOperations
  78. .SendToAsync(clientArgs, connection, clientEndPoint, SocketFlags.None, responseBufferMemory,
  79. cancellationToken);
  80.  
  81. #if DEBUG
  82. lock (typeof(Console))
  83. {
  84. Console.WriteLine($"[Server] Sent {sendResult.Count} bytes to {sendResult.RemoteEndPoint}");
  85. Console.WriteLine($"[Server] >>>> {Encoding.UTF8.GetString(sendResult.Buffer.Span)}");
  86. }
  87. #endif
  88. }
  89. }
  90. catch (OperationCanceledException)
  91. {
  92. Console.WriteLine($"Client task for {clientArgs.RemoteEndPoint} cancelled!");
  93. }
  94. finally
  95. {
  96. DestroyConnectionArgs(clientArgs);
  97. }
  98. }
  99.  
  100. public override async Task RunAsync(CancellationToken cancellationToken = default)
  101. {
  102. byte[] requestBuffer = new byte[NetworkPacket.TotalSize];
  103. Memory<byte> requestBufferMemory = new Memory<byte>(requestBuffer);
  104.  
  105. EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
  106. using SocketAsyncEventArgs remoteArgs = GenerateConnectionArgs(remoteEndPoint);
  107.  
  108. while (!cancellationToken.IsCancellationRequested)
  109. {
  110. remoteArgs.RemoteEndPoint = remoteEndPoint;
  111.  
  112. TransmissionResult receiveResult =
  113. await SocketAsyncOperations
  114. .ReceiveFromAsync(remoteArgs, connection, remoteEndPoint, SocketFlags.None, requestBufferMemory, cancellationToken)
  115. .ConfigureAwait(false);
  116.  
  117. EndPoint clientEndPoint = receiveResult.RemoteEndPoint;
  118.  
  119. #if DEBUG
  120. lock (typeof(Console))
  121. {
  122. Console.WriteLine($"[Server] Received {receiveResult.Count} bytes from {receiveResult.RemoteEndPoint}");
  123. Console.WriteLine($"[Server] <<<< {Encoding.UTF8.GetString(receiveResult.Buffer.Span)}");
  124. }
  125. #endif
  126.  
  127. if (!ConnectedClientHandlerTasks.ContainsKey(clientEndPoint))
  128. {
  129. SocketAsyncEventArgs clientArgs = GenerateConnectionArgs(receiveResult.RemoteEndPoint);
  130.  
  131. BoundedChannelOptions clientChannelOptions = new BoundedChannelOptions(60)
  132. { FullMode = BoundedChannelFullMode.DropOldest, SingleReader = true, SingleWriter = true };
  133. Channel<NetworkPacket> clientChannel = Channel.CreateBounded<NetworkPacket>(clientChannelOptions);
  134.  
  135. connectedClientTokens[clientEndPoint] = new RemoteDatagramClientToken(in clientChannel);
  136.  
  137. ConnectedClientHandlerTasks[clientEndPoint] = HandleClient(clientArgs, cancellationToken);
  138. }
  139.  
  140. NetworkPacket requestPacket = NetworkPacket.Deserialise(requestBufferMemory);
  141.  
  142. await connectedClientTokens[clientEndPoint].PacketWriter.WriteAsync(requestPacket, cancellationToken);
  143. }
  144.  
  145. /*
  146. while (true)
  147. {
  148. TransmissionResult receiveResult =
  149. await SocketAsyncEventArgs.ReceiveAsync(remoteEndPoint, SocketFlags.None, requestBufferMemory);
  150.  
  151. #if DEBUG
  152. lock (typeof(Console))
  153. {
  154. Console.WriteLine($"[Server] Received {receiveResult.Count} bytes from {receiveResult.RemoteEndPoint}");
  155. Console.WriteLine($"[Server] <<<< {Encoding.UTF8.GetString(receiveResult.Buffer.Span)}");
  156. }
  157. #endif
  158.  
  159. TransmissionResult sendResult =
  160. await SocketAsyncOperations.SendAsync(receiveResult.RemoteEndPoint, SocketFlags.None, requestBuffer);
  161.  
  162. #if DEBUG
  163. lock (typeof(Console))
  164. {
  165. Console.WriteLine($"[Server] Sent {sendResult.Count} bytes to {sendResult.RemoteEndPoint}");
  166. Console.WriteLine($"[Server] >>>> {Encoding.UTF8.GetString(sendResult.Buffer.Span)}");
  167. }
  168. #endif
  169. }
  170. */
  171. }
  172. }
  173. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement