You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

RelayConnection.cs 2.9 KiB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using Discord.API;
  2. using Discord.API.Gateway;
  3. using Discord.Logging;
  4. using System;
  5. using System.Net.WebSockets;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using WebSocketClient = System.Net.WebSockets.WebSocket;
  9. namespace Discord.Relay
  10. {
  11. public class RelayConnection
  12. {
  13. private readonly RelayServer _server;
  14. private readonly WebSocketClient _socket;
  15. private readonly CancellationTokenSource _cancelToken;
  16. private readonly byte[] _inBuffer, _outBuffer;
  17. private readonly Logger _logger;
  18. internal RelayConnection(RelayServer server, WebSocketClient socket, int id)
  19. {
  20. _server = server;
  21. _socket = socket;
  22. _cancelToken = new CancellationTokenSource();
  23. _inBuffer = new byte[4000];
  24. _outBuffer = new byte[4000];
  25. _logger = server.LogManager.CreateLogger($"Client #{id}");
  26. }
  27. internal async Task RunAsync()
  28. {
  29. await _logger.InfoAsync($"Connected");
  30. var token = _cancelToken.Token;
  31. try
  32. {
  33. var segment = new ArraySegment<byte>(_inBuffer);
  34. //Send HELLO
  35. await SendAsync(GatewayOpCode.Hello, new HelloEvent { HeartbeatInterval = 15000 }).ConfigureAwait(false);
  36. while (_socket.State == WebSocketState.Open)
  37. {
  38. var result = await _socket.ReceiveAsync(segment, token).ConfigureAwait(false);
  39. if (result.MessageType == WebSocketMessageType.Close)
  40. await _logger.WarningAsync($"Received Close {result.CloseStatus} ({result.CloseStatusDescription ?? "No Reason"})").ConfigureAwait(false);
  41. else
  42. await _logger.InfoAsync($"Received {result.Count} bytes");
  43. }
  44. }
  45. catch (OperationCanceledException)
  46. {
  47. try { await _socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None).ConfigureAwait(false); }
  48. catch { }
  49. }
  50. catch (Exception ex)
  51. {
  52. try { await _socket.CloseAsync(WebSocketCloseStatus.InternalServerError, ex.Message, CancellationToken.None).ConfigureAwait(false); }
  53. catch { }
  54. }
  55. finally
  56. {
  57. await _logger.InfoAsync($"Disconnected");
  58. }
  59. }
  60. internal void Stop()
  61. {
  62. _cancelToken.Cancel();
  63. }
  64. private async Task SendAsync(GatewayOpCode opCode, object payload)
  65. {
  66. var frame = new SocketFrame { Operation = (int)opCode, Payload = payload };
  67. var bytes = _server.Serialize(frame, _outBuffer);
  68. var segment = new ArraySegment<byte>(_outBuffer, 0, bytes);
  69. await _socket.SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None).ConfigureAwait(false);
  70. }
  71. }
  72. }