diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs
index e27a8975b7..3d36a50454 100644
--- a/Emby.Dlna/PlayTo/PlayToController.cs
+++ b/Emby.Dlna/PlayTo/PlayToController.cs
@@ -889,6 +889,11 @@ namespace Emby.Dlna.PlayTo
return Task.CompletedTask;
}
+ public void CloseAllWebSockets(CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+
private class StreamParams
{
private MediaSourceInfo _mediaSource;
diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
index b87f1bc226..2c5ec81ada 100644
--- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
+++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
@@ -231,6 +231,15 @@ namespace Emby.Server.Implementations.HttpServer
CancellationToken.None);
}
+ ///
+ /// Gracefully closes the socket.
+ ///
+ /// The cancellation token.
+ public void CloseSocket(CancellationToken cancellationToken)
+ {
+ _socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "System Shutdown", cancellationToken);
+ }
+
///
public void Dispose()
{
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index e2fa93a380..0d2d0e5176 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -1363,9 +1363,26 @@ namespace Emby.Server.Implementations.Session
{
CheckDisposed();
+ CloseAllWebSockets(cancellationToken);
+
return SendMessageToSessions(Sessions, SessionMessageType.ServerShuttingDown, string.Empty, cancellationToken);
}
+ ///
+ /// Gracefully closes all web sockets in all sessions.
+ ///
+ /// The cancellation token.
+ private void CloseAllWebSockets(CancellationToken cancellationToken)
+ {
+ foreach (var session in Sessions)
+ {
+ foreach (var sessionController in session.SessionControllers)
+ {
+ sessionController.CloseAllWebSockets(cancellationToken);
+ }
+ }
+ }
+
///
/// Sends the server restart notification.
///
diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs
index 9fa92a53a1..16312ffb81 100644
--- a/Emby.Server.Implementations/Session/WebSocketController.cs
+++ b/Emby.Server.Implementations/Session/WebSocketController.cs
@@ -88,6 +88,18 @@ namespace Emby.Server.Implementations.Session
cancellationToken);
}
+ ///
+ /// Gracefully closes all web sockets.
+ ///
+ /// The cancellation token.
+ public void CloseAllWebSockets(CancellationToken cancellationToken)
+ {
+ foreach (var socket in _sockets)
+ {
+ socket.CloseSocket(cancellationToken);
+ }
+ }
+
///
public void Dispose()
{
diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
index 2c6483ae28..c53199de6b 100644
--- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
@@ -58,5 +58,11 @@ namespace MediaBrowser.Controller.Net
Task SendAsync(WebSocketMessage message, CancellationToken cancellationToken);
Task ProcessAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Gracefully closes the socket.
+ ///
+ /// The cancellation token.
+ void CloseSocket(CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs
index b38ee11462..3db79076da 100644
--- a/MediaBrowser.Controller/Session/ISessionController.cs
+++ b/MediaBrowser.Controller/Session/ISessionController.cs
@@ -33,5 +33,11 @@ namespace MediaBrowser.Controller.Session
/// CancellationToken for operation.
/// A task.
Task SendMessage(SessionMessageType name, Guid messageId, T data, CancellationToken cancellationToken);
+
+ ///
+ /// Gracefully closes all web sockets.
+ ///
+ /// The cancellation token.
+ void CloseAllWebSockets(CancellationToken cancellationToken);
}
}