aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Session
diff options
context:
space:
mode:
authorJPVenson <github@jpb.software>2025-02-21 11:08:09 +0000
committerJPVenson <github@jpb.software>2025-02-21 11:08:09 +0000
commit8c0b0d910229d7691b638d2aee5aa5a8aa07fe17 (patch)
tree2e4177bd57586f9e41747f582dddae9d70d78466 /Emby.Server.Implementations/Session
parent963f2357a966dd7a5a6ab248155cc52ce066753b (diff)
parent712908d53c7ca38d13e03ea7809e0c40e862a5fb (diff)
Merge remote-tracking branch 'jellyfinorigin/master' into feature/10.10/DetachedMigration
Diffstat (limited to 'Emby.Server.Implementations/Session')
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs10
-rw-r--r--Emby.Server.Implementations/Session/SessionWebSocketListener.cs8
-rw-r--r--Emby.Server.Implementations/Session/WebSocketController.cs98
3 files changed, 92 insertions, 24 deletions
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 6a8ad2bdc..030da6f73 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -1303,7 +1303,7 @@ namespace Emby.Server.Implementations.Session
if (item is null)
{
- _logger.LogError("A non-existent item Id {0} was passed into TranslateItemForPlayback", id);
+ _logger.LogError("A nonexistent item Id {0} was passed into TranslateItemForPlayback", id);
return Array.Empty<BaseItem>();
}
@@ -1356,7 +1356,7 @@ namespace Emby.Server.Implementations.Session
if (item is null)
{
- _logger.LogError("A non-existent item Id {0} was passed into TranslateItemForInstantMix", id);
+ _logger.LogError("A nonexistent item Id {0} was passed into TranslateItemForInstantMix", id);
return new List<BaseItem>();
}
@@ -1938,7 +1938,11 @@ namespace Emby.Server.Implementations.Session
// Don't report acceleration type for non-admin users.
result = result.Select(r =>
{
- r.TranscodingInfo.HardwareAccelerationType = HardwareAccelerationType.none;
+ if (r.TranscodingInfo is not null)
+ {
+ r.TranscodingInfo.HardwareAccelerationType = HardwareAccelerationType.none;
+ }
+
return r;
});
}
diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
index aba51de8f..d4606abd2 100644
--- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.Session
/// <summary>
/// Lock used for accessing the WebSockets watchlist.
/// </summary>
- private readonly object _webSocketsLock = new object();
+ private readonly Lock _webSocketsLock = new();
private readonly ISessionManager _sessionManager;
private readonly ILogger<SessionWebSocketListener> _logger;
@@ -276,11 +276,11 @@ namespace Emby.Server.Implementations.Session
/// </summary>
/// <param name="webSocket">The WebSocket.</param>
/// <returns>Task.</returns>
- private Task SendForceKeepAlive(IWebSocketConnection webSocket)
+ private async Task SendForceKeepAlive(IWebSocketConnection webSocket)
{
- return webSocket.SendAsync(
+ await webSocket.SendAsync(
new ForceKeepAliveMessage(WebSocketLostTimeout),
- CancellationToken.None);
+ CancellationToken.None).ConfigureAwait(false);
}
}
}
diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs
index cf8e0fb00..c45a4a60f 100644
--- a/Emby.Server.Implementations/Session/WebSocketController.cs
+++ b/Emby.Server.Implementations/Session/WebSocketController.cs
@@ -21,6 +21,7 @@ namespace Emby.Server.Implementations.Session
private readonly SessionInfo _session;
private readonly List<IWebSocketConnection> _sockets;
+ private readonly ReaderWriterLockSlim _socketsLock;
private bool _disposed = false;
public WebSocketController(
@@ -31,10 +32,26 @@ namespace Emby.Server.Implementations.Session
_logger = logger;
_session = session;
_sessionManager = sessionManager;
- _sockets = new List<IWebSocketConnection>();
+ _sockets = new();
+ _socketsLock = new();
}
- private bool HasOpenSockets => GetActiveSockets().Any();
+ private bool HasOpenSockets
+ {
+ get
+ {
+ ObjectDisposedException.ThrowIf(_disposed, this);
+ try
+ {
+ _socketsLock.EnterReadLock();
+ return _sockets.Any(i => i.State == WebSocketState.Open);
+ }
+ finally
+ {
+ _socketsLock.ExitReadLock();
+ }
+ }
+ }
/// <inheritdoc />
public bool SupportsMediaControl => HasOpenSockets;
@@ -42,23 +59,38 @@ namespace Emby.Server.Implementations.Session
/// <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;
+ ObjectDisposedException.ThrowIf(_disposed, this);
+ try
+ {
+ _socketsLock.EnterWriteLock();
+ _sockets.Add(connection);
+ connection.Closed += OnConnectionClosed;
+ }
+ finally
+ {
+ _socketsLock.ExitWriteLock();
+ }
}
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;
+ ObjectDisposedException.ThrowIf(_disposed, this);
+ try
+ {
+ _socketsLock.EnterWriteLock();
+ _sockets.Remove(connection);
+ connection.Closed -= OnConnectionClosed;
+ }
+ finally
+ {
+ _socketsLock.ExitWriteLock();
+ }
+
await _sessionManager.CloseIfNeededAsync(_session).ConfigureAwait(false);
}
@@ -69,7 +101,17 @@ namespace Emby.Server.Implementations.Session
T data,
CancellationToken cancellationToken)
{
- var socket = GetActiveSockets().MaxBy(i => i.LastActivityDate);
+ ObjectDisposedException.ThrowIf(_disposed, this);
+ IWebSocketConnection? socket;
+ try
+ {
+ _socketsLock.EnterReadLock();
+ socket = _sockets.Where(i => i.State == WebSocketState.Open).MaxBy(i => i.LastActivityDate);
+ }
+ finally
+ {
+ _socketsLock.ExitReadLock();
+ }
if (socket is null)
{
@@ -94,12 +136,23 @@ namespace Emby.Server.Implementations.Session
return;
}
- foreach (var socket in _sockets)
+ try
+ {
+ _socketsLock.EnterWriteLock();
+ foreach (var socket in _sockets)
+ {
+ socket.Closed -= OnConnectionClosed;
+ socket.Dispose();
+ }
+
+ _sockets.Clear();
+ }
+ finally
{
- socket.Closed -= OnConnectionClosed;
- socket.Dispose();
+ _socketsLock.ExitWriteLock();
}
+ _socketsLock.Dispose();
_disposed = true;
}
@@ -110,12 +163,23 @@ namespace Emby.Server.Implementations.Session
return;
}
- foreach (var socket in _sockets)
+ try
+ {
+ _socketsLock.EnterWriteLock();
+ foreach (var socket in _sockets)
+ {
+ socket.Closed -= OnConnectionClosed;
+ await socket.DisposeAsync().ConfigureAwait(false);
+ }
+
+ _sockets.Clear();
+ }
+ finally
{
- socket.Closed -= OnConnectionClosed;
- await socket.DisposeAsync().ConfigureAwait(false);
+ _socketsLock.ExitWriteLock();
}
+ _socketsLock.Dispose();
_disposed = true;
}
}