WebSocketManager.cs 3.3 KB

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