< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.Session.WebSocketController
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/Session/WebSocketController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 31
Coverable lines: 31
Total lines: 122
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 8
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
get_HasOpenSockets()100%210%
get_SupportsMediaControl()100%210%
get_IsSessionActive()100%210%
GetActiveSockets()100%210%
AddWebSocket(...)100%210%
SendMessage(...)0%2040%
Dispose()0%2040%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/Session/WebSocketController.cs

#LineLine coverage
 1#pragma warning disable CS1591
 2
 3using System;
 4using System.Collections.Generic;
 5using System.Linq;
 6using System.Net.WebSockets;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using MediaBrowser.Controller.Net;
 10using MediaBrowser.Controller.Net.WebSocketMessages;
 11using MediaBrowser.Controller.Session;
 12using MediaBrowser.Model.Session;
 13using Microsoft.Extensions.Logging;
 14
 15namespace Emby.Server.Implementations.Session
 16{
 17    public sealed class WebSocketController : ISessionController, IAsyncDisposable, IDisposable
 18    {
 19        private readonly ILogger<WebSocketController> _logger;
 20        private readonly ISessionManager _sessionManager;
 21        private readonly SessionInfo _session;
 22
 23        private readonly List<IWebSocketConnection> _sockets;
 24        private bool _disposed = false;
 25
 26        public WebSocketController(
 27            ILogger<WebSocketController> logger,
 28            SessionInfo session,
 29            ISessionManager sessionManager)
 30        {
 031            _logger = logger;
 032            _session = session;
 033            _sessionManager = sessionManager;
 034            _sockets = new List<IWebSocketConnection>();
 035        }
 36
 037        private bool HasOpenSockets => GetActiveSockets().Any();
 38
 39        /// <inheritdoc />
 040        public bool SupportsMediaControl => HasOpenSockets;
 41
 42        /// <inheritdoc />
 043        public bool IsSessionActive => HasOpenSockets;
 44
 45        private IEnumerable<IWebSocketConnection> GetActiveSockets()
 046            => _sockets.Where(i => i.State == WebSocketState.Open);
 47
 48        public void AddWebSocket(IWebSocketConnection connection)
 49        {
 050            _logger.LogDebug("Adding websocket to session {Session}", _session.Id);
 051            _sockets.Add(connection);
 52
 053            connection.Closed += OnConnectionClosed;
 054        }
 55
 56        private async void OnConnectionClosed(object? sender, EventArgs e)
 57        {
 58            var connection = sender as IWebSocketConnection ?? throw new ArgumentException($"{nameof(sender)} is not of 
 59            _logger.LogDebug("Removing websocket from session {Session}", _session.Id);
 60            _sockets.Remove(connection);
 61            connection.Closed -= OnConnectionClosed;
 62            await _sessionManager.CloseIfNeededAsync(_session).ConfigureAwait(false);
 63        }
 64
 65        /// <inheritdoc />
 66        public Task SendMessage<T>(
 67            SessionMessageType name,
 68            Guid messageId,
 69            T data,
 70            CancellationToken cancellationToken)
 71        {
 072            var socket = GetActiveSockets().MaxBy(i => i.LastActivityDate);
 73
 074            if (socket is null)
 75            {
 076                return Task.CompletedTask;
 77            }
 78
 079            return socket.SendAsync(
 080                new OutboundWebSocketMessage<T>
 081                {
 082                    Data = data,
 083                    MessageType = name,
 084                    MessageId = messageId
 085                },
 086                cancellationToken);
 87        }
 88
 89        /// <inheritdoc />
 90        public void Dispose()
 91        {
 092            if (_disposed)
 93            {
 094                return;
 95            }
 96
 097            foreach (var socket in _sockets)
 98            {
 099                socket.Closed -= OnConnectionClosed;
 0100                socket.Dispose();
 101            }
 102
 0103            _disposed = true;
 0104        }
 105
 106        public async ValueTask DisposeAsync()
 107        {
 108            if (_disposed)
 109            {
 110                return;
 111            }
 112
 113            foreach (var socket in _sockets)
 114            {
 115                socket.Closed -= OnConnectionClosed;
 116                await socket.DisposeAsync().ConfigureAwait(false);
 117            }
 118
 119            _disposed = true;
 120        }
 121    }
 122}