jellyfin-server/Emby.Server.Implementations/Session/WebSocketController.cs
Cody Robibero b8722d02a3 Merge pull request #7781 from crobibero/live-tv-infinite
(cherry picked from commit 77c73e241fe1705528e3ffbb42f074c46240b9fb)
Signed-off-by: crobibero <cody@robibe.ro>
2022-06-06 09:16:11 -04:00

108 lines
3.3 KiB
C#

#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Session;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Session
{
public sealed class WebSocketController : ISessionController, IDisposable
{
private readonly ILogger<WebSocketController> _logger;
private readonly ISessionManager _sessionManager;
private readonly SessionInfo _session;
private readonly List<IWebSocketConnection> _sockets;
private bool _disposed = false;
public WebSocketController(
ILogger<WebSocketController> logger,
SessionInfo session,
ISessionManager sessionManager)
{
_logger = logger;
_session = session;
_sessionManager = sessionManager;
_sockets = new List<IWebSocketConnection>();
}
private bool HasOpenSockets => GetActiveSockets().Any();
/// <inheritdoc />
public bool SupportsMediaControl => HasOpenSockets;
/// <inheritdoc />
public bool IsSessionActive => HasOpenSockets;
private IEnumerable<IWebSocketConnection> GetActiveSockets()
=> _sockets.Where(i => i.State == WebSocketState.Open);
public void AddWebSocket(IWebSocketConnection connection)
{
_logger.LogDebug("Adding websocket to session {Session}", _session.Id);
_sockets.Add(connection);
connection.Closed += OnConnectionClosed;
}
private async void OnConnectionClosed(object? sender, EventArgs e)
{
var connection = sender as IWebSocketConnection ?? throw new ArgumentException($"{nameof(sender)} is not of type {nameof(IWebSocketConnection)}", nameof(sender));
_logger.LogDebug("Removing websocket from session {Session}", _session.Id);
_sockets.Remove(connection);
connection.Closed -= OnConnectionClosed;
await _sessionManager.CloseIfNeededAsync(_session).ConfigureAwait(false);
}
/// <inheritdoc />
public Task SendMessage<T>(
SessionMessageType name,
Guid messageId,
T data,
CancellationToken cancellationToken)
{
var socket = GetActiveSockets()
.OrderByDescending(i => i.LastActivityDate)
.FirstOrDefault();
if (socket == null)
{
return Task.CompletedTask;
}
return socket.SendAsync(
new WebSocketMessage<T>
{
Data = data,
MessageType = name,
MessageId = messageId
},
cancellationToken);
}
/// <inheritdoc />
public void Dispose()
{
if (_disposed)
{
return;
}
foreach (var socket in _sockets)
{
socket.Closed -= OnConnectionClosed;
}
_disposed = true;
}
}
}