< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.HttpServer.WebSocketManager
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/HttpServer/WebSocketManager.cs
Line coverage
19%
Covered lines: 8
Uncovered lines: 34
Coverable lines: 42
Total lines: 103
Line coverage: 19%
Branch coverage
20%
Covered branches: 2
Total branches: 10
Branch coverage: 20%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 2/13/2026 - 12:11:21 AM Line coverage: 100% (5/5) Total lines: 984/19/2026 - 12:14:27 AM Line coverage: 21.6% (8/37) Branch coverage: 20% (2/10) Total lines: 985/15/2026 - 12:15:55 AM Line coverage: 19% (8/42) Branch coverage: 20% (2/10) Total lines: 103 4/19/2026 - 12:14:27 AM Line coverage: 21.6% (8/37) Branch coverage: 20% (2/10) Total lines: 985/15/2026 - 12:15:55 AM Line coverage: 19% (8/42) Branch coverage: 20% (2/10) Total lines: 103

Coverage delta

Coverage delta 79 -79

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
WebSocketRequestHandler()25%5689.37%
ProcessWebSocketMessageReceived()0%620%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/HttpServer/WebSocketManager.cs

#LineLine coverage
 1#nullable disable
 2
 3#pragma warning disable CS1591
 4
 5using System;
 6using System.Collections.Generic;
 7using System.Globalization;
 8using System.Linq;
 9using System.Net.WebSockets;
 10using System.Threading.Tasks;
 11using MediaBrowser.Common.Extensions;
 12using MediaBrowser.Controller.Net;
 13using Microsoft.AspNetCore.Http;
 14using Microsoft.Extensions.Logging;
 15
 16namespace Emby.Server.Implementations.HttpServer
 17{
 18    public class WebSocketManager : IWebSocketManager
 19    {
 20        private readonly IWebSocketListener[] _webSocketListeners;
 21        private readonly IAuthService _authService;
 22        private readonly ILogger<WebSocketManager> _logger;
 23        private readonly ILoggerFactory _loggerFactory;
 24
 25        public WebSocketManager(
 26            IAuthService authService,
 27            IEnumerable<IWebSocketListener> webSocketListeners,
 28            ILogger<WebSocketManager> logger,
 29            ILoggerFactory loggerFactory)
 30        {
 1931            _webSocketListeners = webSocketListeners.ToArray();
 1932            _authService = authService;
 1933            _logger = logger;
 1934            _loggerFactory = loggerFactory;
 1935        }
 36
 37        /// <inheritdoc />
 38        public async Task WebSocketRequestHandler(HttpContext context)
 39        {
 140            var authorizationInfo = await _authService.Authenticate(context.Request).ConfigureAwait(false);
 141            if (!authorizationInfo.IsAuthenticated)
 42            {
 143                throw new SecurityException("Token is required");
 44            }
 45
 46            try
 47            {
 048                _logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress);
 49
 050                WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false);
 051                var connection = new WebSocketConnection(
 052                    _loggerFactory.CreateLogger<WebSocketConnection>(),
 053                    webSocket,
 054                    authorizationInfo,
 055                    context.GetNormalizedRemoteIP())
 056                {
 057                    RequestUICulture = CultureInfo.CurrentUICulture
 058                };
 059                connection.OnReceive = result =>
 060                {
 061                    connection.ApplyRequestCulture();
 062                    return ProcessWebSocketMessageReceived(result);
 063                };
 064                await using (connection.ConfigureAwait(false))
 65                {
 066                    var tasks = new Task[_webSocketListeners.Length];
 067                    for (var i = 0; i < _webSocketListeners.Length; ++i)
 68                    {
 069                        tasks[i] = _webSocketListeners[i].ProcessWebSocketConnectedAsync(connection, context);
 70                    }
 71
 072                    await Task.WhenAll(tasks).ConfigureAwait(false);
 73
 074                    await connection.ReceiveAsync().ConfigureAwait(false);
 075                    _logger.LogInformation("WS {IP} closed", context.Connection.RemoteIpAddress);
 76                }
 077            }
 078            catch (Exception ex) // Otherwise ASP.Net will ignore the exception
 79            {
 080                _logger.LogError(ex, "WS {IP} WebSocketRequestHandler error", context.Connection.RemoteIpAddress);
 081                if (!context.Response.HasStarted)
 82                {
 083                    context.Response.StatusCode = 500;
 84                }
 085            }
 086        }
 87
 88        /// <summary>
 89        /// Processes the web socket message received.
 90        /// </summary>
 91        /// <param name="result">The result.</param>
 92        private async Task ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
 93        {
 094            var tasks = new Task[_webSocketListeners.Length];
 095            for (var i = 0; i < _webSocketListeners.Length; ++i)
 96            {
 097                tasks[i] = _webSocketListeners[i].ProcessMessageAsync(result);
 98            }
 99
 0100            await Task.WhenAll(tasks).ConfigureAwait(false);
 0101        }
 102    }
 103}