using System; using System.Globalization; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Jellyfin.Extensions.Json; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Session; /// /// Stands in for the websocket of a session another instance holds: messages are forwarded to that /// instance, which writes them to the connection it owns. /// public sealed class RemoteSessionController : ISessionController { private readonly IPodMessageBus _bus; private readonly ILogger _logger; private readonly string _ownerPod; private readonly string _sessionId; /// /// Initializes a new instance of the class. /// /// The cross-instance bus. /// The logger. /// The instance holding the connection. /// The session identifier. /// Whether the owner reported the session as controllable. public RemoteSessionController(IPodMessageBus bus, ILogger logger, string ownerPod, string sessionId, bool supportsMediaControl) { _bus = bus; _logger = logger; _ownerPod = ownerPod; _sessionId = sessionId; SupportsMediaControl = supportsMediaControl; } /// public bool IsSessionActive => true; /// public bool SupportsMediaControl { get; } /// public async Task SendMessage(SessionMessageType name, Guid messageId, T data, CancellationToken cancellationToken) { var routed = new RoutedSessionMessage { SessionId = _sessionId, MessageType = name, MessageId = messageId, Data = JsonSerializer.Serialize(data, JsonDefaults.Options) }; var delivered = await _bus.PublishAsync( _ownerPod, new PodMessage { Kind = RoutedSessionMessage.Kind, Payload = JsonSerializer.Serialize(routed, JsonDefaults.Options) }, cancellationToken).ConfigureAwait(false); if (delivered == 0) { _logger.LogWarning("Instance {OwnerPod} holds session {SessionId} but is not listening; the {MessageType} message was not delivered.", _ownerPod, _sessionId, name); throw new ResourceNotFoundException( string.Format(CultureInfo.InvariantCulture, "The instance holding session {0} is unreachable.", _sessionId)); } } }