2020-01-13 20:03:49 +01:00
#pragma warning disable CS1591
#pragma warning disable SA1600
#nullable enable
2019-01-13 20:54:44 +01:00
using System ;
2013-10-03 03:22:50 +02:00
using System.Collections.Generic ;
2013-09-24 17:42:30 +02:00
using System.Linq ;
2019-01-13 20:22:24 +01:00
using System.Net.WebSockets ;
2013-09-24 17:42:30 +02:00
using System.Threading ;
using System.Threading.Tasks ;
2020-11-13 19:14:44 +01:00
using MediaBrowser.Common.Extensions ;
2019-01-13 20:22:24 +01:00
using MediaBrowser.Controller.Net ;
using MediaBrowser.Controller.Session ;
using MediaBrowser.Model.Net ;
2020-09-25 09:25:59 +02:00
using MediaBrowser.Model.Session ;
2019-01-13 20:22:24 +01:00
using Microsoft.Extensions.Logging ;
2013-09-24 17:42:30 +02:00
2016-11-04 00:35:19 +01:00
namespace Emby.Server.Implementations.Session
2013-09-24 17:42:30 +02:00
{
2019-12-17 23:15:02 +01:00
public sealed class WebSocketController : ISessionController , IDisposable
2013-09-24 17:42:30 +02:00
{
2020-06-06 02:15:56 +02:00
private readonly ILogger < WebSocketController > _logger ;
2014-05-17 20:37:40 +02:00
private readonly ISessionManager _sessionManager ;
2019-12-17 23:15:02 +01:00
private readonly SessionInfo _session ;
2014-05-17 20:37:40 +02:00
2020-05-02 01:30:04 +02:00
private readonly List < IWebSocketConnection > _sockets ;
2019-12-17 23:15:02 +01:00
private bool _disposed = false ;
public WebSocketController (
ILogger < WebSocketController > logger ,
SessionInfo session ,
ISessionManager sessionManager )
2013-09-24 17:42:30 +02:00
{
2014-05-17 06:24:10 +02:00
_logger = logger ;
2019-12-17 23:15:02 +01:00
_session = session ;
2014-05-17 20:37:40 +02:00
_sessionManager = sessionManager ;
2019-12-17 23:15:02 +01:00
_sockets = new List < IWebSocketConnection > ( ) ;
2013-09-24 17:42:30 +02:00
}
2019-01-06 21:50:43 +01:00
private bool HasOpenSockets = > GetActiveSockets ( ) . Any ( ) ;
2015-03-21 17:10:02 +01:00
2019-12-17 23:15:02 +01:00
/// <inheritdoc />
2019-01-06 21:50:43 +01:00
public bool SupportsMediaControl = > HasOpenSockets ;
2015-03-21 17:10:02 +01:00
2019-12-17 23:15:02 +01:00
/// <inheritdoc />
2019-01-06 21:50:43 +01:00
public bool IsSessionActive = > HasOpenSockets ;
2013-10-03 03:22:50 +02:00
2014-05-17 06:24:10 +02:00
private IEnumerable < IWebSocketConnection > GetActiveSockets ( )
2019-12-17 23:15:02 +01:00
= > _sockets . Where ( i = > i . State = = WebSocketState . Open ) ;
2014-05-17 06:24:10 +02:00
2014-05-17 20:37:40 +02:00
public void AddWebSocket ( IWebSocketConnection connection )
{
2019-12-17 23:15:02 +01:00
_logger . LogDebug ( "Adding websocket to session {Session}" , _session . Id ) ;
_sockets . Add ( connection ) ;
2014-05-17 20:37:40 +02:00
2019-12-17 23:15:02 +01:00
connection . Closed + = OnConnectionClosed ;
2014-05-17 20:37:40 +02:00
}
2020-11-13 17:41:18 +01:00
private void OnConnectionClosed ( object? sender , EventArgs e )
2014-05-17 20:37:40 +02:00
{
2020-11-14 02:04:06 +01:00
var connection = sender as IWebSocketConnection ? ? throw new ArgumentException ( $"{nameof(sender)} is not of type {nameof(IWebSocketConnection)}" , nameof ( sender ) ) ;
2019-12-26 20:57:46 +01:00
_logger . LogDebug ( "Removing websocket from session {Session}" , _session . Id ) ;
2019-12-17 23:15:02 +01:00
_sockets . Remove ( connection ) ;
2019-12-26 20:57:46 +01:00
connection . Closed - = OnConnectionClosed ;
_sessionManager . CloseIfNeeded ( _session ) ;
2014-05-17 20:37:40 +02:00
}
2019-12-17 23:15:02 +01:00
/// <inheritdoc />
public Task SendMessage < T > (
2020-09-25 09:25:59 +02:00
SessionMessageType name ,
2019-12-17 23:15:02 +01:00
Guid messageId ,
T data ,
CancellationToken cancellationToken )
2014-05-17 06:24:10 +02:00
{
var socket = GetActiveSockets ( )
2019-12-17 23:15:02 +01:00
. OrderByDescending ( i = > i . LastActivityDate )
2014-05-17 06:24:10 +02:00
. FirstOrDefault ( ) ;
2013-09-24 21:54:42 +02:00
if ( socket = = null )
2013-09-24 17:42:30 +02:00
{
2018-09-12 19:26:21 +02:00
return Task . CompletedTask ;
2013-09-24 17:42:30 +02:00
}
2013-09-24 21:54:42 +02:00
2020-01-13 20:03:49 +01:00
return socket . SendAsync (
new WebSocketMessage < T >
{
Data = data ,
MessageType = name ,
MessageId = messageId
} ,
cancellationToken ) ;
2015-01-13 04:46:44 +01:00
}
2019-12-17 23:15:02 +01:00
/// <inheritdoc />
2014-05-17 23:23:48 +02:00
public void Dispose ( )
{
2019-12-17 23:15:02 +01:00
if ( _disposed )
2014-05-17 23:23:48 +02:00
{
2019-12-17 23:15:02 +01:00
return ;
2014-05-17 23:23:48 +02:00
}
2019-12-17 23:15:02 +01:00
foreach ( var socket in _sockets )
{
socket . Closed - = OnConnectionClosed ;
}
_disposed = true ;
2014-05-17 23:23:48 +02:00
}
2013-09-24 17:42:30 +02:00
}
}