WebSocketManager.cs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #pragma warning disable CS1591
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Net.WebSockets;
  5. using System.Threading.Tasks;
  6. using Jellyfin.Data.Events;
  7. using MediaBrowser.Controller.Net;
  8. using Microsoft.AspNetCore.Http;
  9. using Microsoft.Extensions.Logging;
  10. namespace Emby.Server.Implementations.HttpServer
  11. {
  12. public class WebSocketManager : IWebSocketManager
  13. {
  14. private readonly Lazy<IEnumerable<IWebSocketListener>> _webSocketListeners;
  15. private readonly ILogger<WebSocketManager> _logger;
  16. private readonly ILoggerFactory _loggerFactory;
  17. private bool _disposed = false;
  18. public WebSocketManager(
  19. Lazy<IEnumerable<IWebSocketListener>> webSocketListeners,
  20. ILogger<WebSocketManager> logger,
  21. ILoggerFactory loggerFactory)
  22. {
  23. _webSocketListeners = webSocketListeners;
  24. _logger = logger;
  25. _loggerFactory = loggerFactory;
  26. }
  27. public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
  28. /// <inheritdoc />
  29. public async Task WebSocketRequestHandler(HttpContext context)
  30. {
  31. if (_disposed)
  32. {
  33. return;
  34. }
  35. try
  36. {
  37. _logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress);
  38. WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false);
  39. using var connection = new WebSocketConnection(
  40. _loggerFactory.CreateLogger<WebSocketConnection>(),
  41. webSocket,
  42. context.Connection.RemoteIpAddress,
  43. context.Request.Query)
  44. {
  45. OnReceive = ProcessWebSocketMessageReceived
  46. };
  47. WebSocketConnected?.Invoke(this, new GenericEventArgs<IWebSocketConnection>(connection));
  48. await connection.ProcessAsync().ConfigureAwait(false);
  49. _logger.LogInformation("WS {IP} closed", context.Connection.RemoteIpAddress);
  50. }
  51. catch (Exception ex) // Otherwise ASP.Net will ignore the exception
  52. {
  53. _logger.LogError(ex, "WS {IP} WebSocketRequestHandler error", context.Connection.RemoteIpAddress);
  54. if (!context.Response.HasStarted)
  55. {
  56. context.Response.StatusCode = 500;
  57. }
  58. }
  59. }
  60. /// <summary>
  61. /// Processes the web socket message received.
  62. /// </summary>
  63. /// <param name="result">The result.</param>
  64. private Task ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
  65. {
  66. if (_disposed)
  67. {
  68. return Task.CompletedTask;
  69. }
  70. IEnumerable<Task> GetTasks()
  71. {
  72. var listeners = _webSocketListeners.Value;
  73. foreach (var x in listeners)
  74. {
  75. yield return x.ProcessMessageAsync(result);
  76. }
  77. }
  78. return Task.WhenAll(GetTasks());
  79. }
  80. }
  81. }