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