PlayerConnectionHandler.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net.WebSockets;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using BubbleSocketCore.Simulation;
  8. using BubbleSocketCore.Websocket;
  9. using Microsoft.AspNetCore.Http;
  10. using Microsoft.Extensions.Configuration;
  11. using Microsoft.Extensions.Logging;
  12. namespace BubbleSocketCore.Handlers
  13. {
  14. class PlayerConnectionHandler : IHandler
  15. {
  16. private readonly IConfiguration Configuration;
  17. private readonly ILoggerFactory LoggerFactory;
  18. private readonly ILogger Logger;
  19. public SimulationActionFactory simulationActionFactory { get; private set; }
  20. public ConnectionManager connectionManager { get; private set; }
  21. public Simulation.Simulation simulation { get; private set; }
  22. public PlayerConnectionHandler(IConfiguration configuration, ILoggerFactory loggerFactory)
  23. {
  24. Configuration = configuration;
  25. LoggerFactory = loggerFactory;
  26. Logger = LoggerFactory.CreateLogger("PlayerConnectionHandler");
  27. simulationActionFactory = new SimulationActionFactory(Configuration, LoggerFactory);
  28. connectionManager = ConnectionManager.GetInstance();
  29. simulation = Simulation.Simulation.GetInstance();
  30. }
  31. public void AddSocket(WebSocket webSocket)
  32. {
  33. connectionManager.Add(webSocket);
  34. }
  35. public bool IsListening(HttpRequest request)
  36. {
  37. return request.Path == "/game";
  38. }
  39. public async Task Listen(HttpContext context, WebSocket selfSocket, CancellationToken cancellationToken)
  40. {
  41. try
  42. {
  43. var buffer = WebSocket.CreateClientBuffer(1024 * 4, 1024 * 4);
  44. WebSocketReceiveResult result = await selfSocket.ReceiveAsync(buffer, cancellationToken);
  45. while (!result.CloseStatus.HasValue)
  46. {
  47. var allBytes = new List<byte>();
  48. for (int i = 0; i < result.Count; i++)
  49. {
  50. allBytes.Add(buffer.Array[i]);
  51. }
  52. while (!result.EndOfMessage)
  53. {
  54. result = await selfSocket.ReceiveAsync(buffer, cancellationToken);
  55. for (int i = 0; i < result.Count; i++)
  56. {
  57. allBytes.Add(buffer.Array[i]);
  58. }
  59. }
  60. var rawString = Encoding.UTF8.GetString(allBytes.ToArray(), 0, allBytes.Count);
  61. var rawMessageType = rawString.Substring(0, 2);
  62. var messageData = rawString.Substring(2, rawString.Length - 2);
  63. var messageType = SimulationActionType.UNKNOWN;
  64. ISimulationAction simulationAction = new NoOpSimulationActionType();
  65. try
  66. {
  67. messageType = SimulationActionFactory.ParseActionType(rawMessageType);
  68. simulationAction = simulationActionFactory.Create(messageType);
  69. }
  70. catch (Exception e)
  71. {
  72. Logger.LogWarning($"Invalid Message Type: {messageType}: {e.Message}");
  73. }
  74. try
  75. {
  76. simulationAction.Run(selfSocket, simulationAction.ParseMessageData(messageData));
  77. }
  78. catch (System.Text.Json.JsonException e)
  79. {
  80. Logger.LogWarning($"Data received was not json: {e.Message}");
  81. }
  82. //wait for next input message
  83. //this is what's failing on server shutdown; the cancellation token isn't right
  84. result = await selfSocket.ReceiveAsync(buffer, cancellationToken);
  85. }
  86. await selfSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, cancellationToken);
  87. simulationActionFactory.Create(SimulationActionType.Disconnect).Run(selfSocket, "{}");
  88. }
  89. catch (WebSocketException e)
  90. {
  91. Logger.LogWarning($"Websocket exception: {e.Message}");
  92. simulationActionFactory.Create(SimulationActionType.Disconnect).Run(selfSocket, "{}");
  93. }
  94. catch (OperationCanceledException)
  95. {
  96. Logger.LogInformation("Server shutdown request");
  97. simulationActionFactory.Create(SimulationActionType.Disconnect).Run(selfSocket, "{}");
  98. }
  99. catch (Exception e)
  100. {
  101. Logger.LogWarning($"Unexpected Exception: {e.ToString()}{e.Message}");
  102. }
  103. }
  104. private async Task Send(WebSocket socket, ArraySegment<byte> data, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
  105. {
  106. await socket.SendAsync(data, messageType, endOfMessage, cancellationToken);
  107. }
  108. }
  109. }