diff options
Diffstat (limited to 'Emby.Dlna/Main/DlnaHost.cs')
| -rw-r--r-- | Emby.Dlna/Main/DlnaHost.cs | 387 |
1 files changed, 0 insertions, 387 deletions
diff --git a/Emby.Dlna/Main/DlnaHost.cs b/Emby.Dlna/Main/DlnaHost.cs deleted file mode 100644 index 58db7c26f..000000000 --- a/Emby.Dlna/Main/DlnaHost.cs +++ /dev/null @@ -1,387 +0,0 @@ -#pragma warning disable CA1031 // Do not catch general exception types. - -using System; -using System.Globalization; -using System.Linq; -using System.Net.Http; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using Emby.Dlna.PlayTo; -using Emby.Dlna.Ssdp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Globalization; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Rssdp; -using Rssdp.Infrastructure; - -namespace Emby.Dlna.Main; - -/// <summary> -/// A <see cref="IHostedService"/> that manages a DLNA server. -/// </summary> -public sealed class DlnaHost : IHostedService, IDisposable -{ - private readonly ILogger<DlnaHost> _logger; - private readonly IServerConfigurationManager _config; - private readonly IServerApplicationHost _appHost; - private readonly ISessionManager _sessionManager; - private readonly IHttpClientFactory _httpClientFactory; - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IDlnaManager _dlnaManager; - private readonly IImageProcessor _imageProcessor; - private readonly IUserDataManager _userDataManager; - private readonly ILocalizationManager _localization; - private readonly IMediaSourceManager _mediaSourceManager; - private readonly IMediaEncoder _mediaEncoder; - private readonly IDeviceDiscovery _deviceDiscovery; - private readonly ISsdpCommunicationsServer _communicationsServer; - private readonly INetworkManager _networkManager; - private readonly object _syncLock = new(); - - private SsdpDevicePublisher? _publisher; - private PlayToManager? _manager; - private bool _disposed; - - /// <summary> - /// Initializes a new instance of the <see cref="DlnaHost"/> class. - /// </summary> - /// <param name="config">The <see cref="IServerConfigurationManager"/>.</param> - /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param> - /// <param name="appHost">The <see cref="IServerApplicationHost"/>.</param> - /// <param name="sessionManager">The <see cref="ISessionManager"/>.</param> - /// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/>.</param> - /// <param name="libraryManager">The <see cref="ILibraryManager"/>.</param> - /// <param name="userManager">The <see cref="IUserManager"/>.</param> - /// <param name="dlnaManager">The <see cref="IDlnaManager"/>.</param> - /// <param name="imageProcessor">The <see cref="IImageProcessor"/>.</param> - /// <param name="userDataManager">The <see cref="IUserDataManager"/>.</param> - /// <param name="localizationManager">The <see cref="ILocalizationManager"/>.</param> - /// <param name="mediaSourceManager">The <see cref="IMediaSourceManager"/>.</param> - /// <param name="deviceDiscovery">The <see cref="IDeviceDiscovery"/>.</param> - /// <param name="mediaEncoder">The <see cref="IMediaEncoder"/>.</param> - /// <param name="communicationsServer">The <see cref="ISsdpCommunicationsServer"/>.</param> - /// <param name="networkManager">The <see cref="INetworkManager"/>.</param> - public DlnaHost( - IServerConfigurationManager config, - ILoggerFactory loggerFactory, - IServerApplicationHost appHost, - ISessionManager sessionManager, - IHttpClientFactory httpClientFactory, - ILibraryManager libraryManager, - IUserManager userManager, - IDlnaManager dlnaManager, - IImageProcessor imageProcessor, - IUserDataManager userDataManager, - ILocalizationManager localizationManager, - IMediaSourceManager mediaSourceManager, - IDeviceDiscovery deviceDiscovery, - IMediaEncoder mediaEncoder, - ISsdpCommunicationsServer communicationsServer, - INetworkManager networkManager) - { - _config = config; - _appHost = appHost; - _sessionManager = sessionManager; - _httpClientFactory = httpClientFactory; - _libraryManager = libraryManager; - _userManager = userManager; - _dlnaManager = dlnaManager; - _imageProcessor = imageProcessor; - _userDataManager = userDataManager; - _localization = localizationManager; - _mediaSourceManager = mediaSourceManager; - _deviceDiscovery = deviceDiscovery; - _mediaEncoder = mediaEncoder; - _communicationsServer = communicationsServer; - _networkManager = networkManager; - _logger = loggerFactory.CreateLogger<DlnaHost>(); - } - - /// <inheritdoc /> - public async Task StartAsync(CancellationToken cancellationToken) - { - var netConfig = _config.GetConfiguration<NetworkConfiguration>(NetworkConfigurationStore.StoreKey); - if (_appHost.ListenWithHttps && netConfig.RequireHttps) - { - if (_config.GetDlnaConfiguration().EnableServer) - { - _logger.LogError("The DLNA specification does not support HTTPS."); - } - - // No use starting as dlna won't work, as we're running purely on HTTPS. - return; - } - - await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false); - ReloadComponents(); - - _config.NamedConfigurationUpdated += OnNamedConfigurationUpdated; - } - - /// <inheritdoc /> - public Task StopAsync(CancellationToken cancellationToken) - { - Stop(); - - return Task.CompletedTask; - } - - /// <inheritdoc /> - public void Dispose() - { - if (!_disposed) - { - Stop(); - _disposed = true; - } - } - - private void OnNamedConfigurationUpdated(object? sender, ConfigurationUpdateEventArgs e) - { - if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase)) - { - ReloadComponents(); - } - } - - private void ReloadComponents() - { - var options = _config.GetDlnaConfiguration(); - StartDeviceDiscovery(); - - if (options.EnableServer) - { - StartDevicePublisher(options); - } - else - { - DisposeDevicePublisher(); - } - - if (options.EnablePlayTo) - { - StartPlayToManager(); - } - else - { - DisposePlayToManager(); - } - } - - private static string CreateUuid(string text) - { - if (!Guid.TryParse(text, out var guid)) - { - guid = text.GetMD5(); - } - - return guid.ToString("D", CultureInfo.InvariantCulture); - } - - private static void SetProperties(SsdpDevice device, string fullDeviceType) - { - var serviceParts = fullDeviceType - .Replace("urn:", string.Empty, StringComparison.OrdinalIgnoreCase) - .Replace(":1", string.Empty, StringComparison.OrdinalIgnoreCase) - .Split(':'); - - device.DeviceTypeNamespace = serviceParts[0].Replace('.', '-'); - device.DeviceClass = serviceParts[1]; - device.DeviceType = serviceParts[2]; - } - - private void StartDeviceDiscovery() - { - try - { - ((DeviceDiscovery)_deviceDiscovery).Start(_communicationsServer); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error starting device discovery"); - } - } - - private void StartDevicePublisher(Configuration.DlnaOptions options) - { - if (_publisher is not null) - { - return; - } - - try - { - _publisher = new SsdpDevicePublisher( - _communicationsServer, - Environment.OSVersion.Platform.ToString(), - // Can not use VersionString here since that includes OS and version - Environment.OSVersion.Version.ToString(), - _config.GetDlnaConfiguration().SendOnlyMatchedHost) - { - LogFunction = msg => _logger.LogDebug("{Msg}", msg), - SupportPnpRootDevice = false - }; - - RegisterServerEndpoints(); - - if (options.BlastAliveMessages) - { - _publisher.StartSendingAliveNotifications(TimeSpan.FromSeconds(options.BlastAliveMessageIntervalSeconds)); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error registering endpoint"); - } - } - - private void RegisterServerEndpoints() - { - var udn = CreateUuid(_appHost.SystemId); - var descriptorUri = "/dlna/" + udn + "/description.xml"; - - // Only get bind addresses in LAN - // IPv6 is currently unsupported - var validInterfaces = _networkManager.GetInternalBindAddresses() - .Where(x => x.AddressFamily != AddressFamily.InterNetworkV6) - .ToList(); - - if (validInterfaces.Count == 0) - { - // No interfaces returned, fall back to loopback - validInterfaces = _networkManager.GetLoopbacks().ToList(); - } - - foreach (var intf in validInterfaces) - { - var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; - - _logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, intf.Address); - - var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(intf.Address, false) + descriptorUri); - - var device = new SsdpRootDevice - { - CacheLifetime = TimeSpan.FromSeconds(1800), // How long SSDP clients can cache this info. - Location = uri.Uri, // Must point to the URL that serves your devices UPnP description document. - Address = intf.Address, - PrefixLength = NetworkUtils.MaskToCidr(intf.Subnet.Prefix), - FriendlyName = "Jellyfin", - Manufacturer = "Jellyfin", - ModelName = "Jellyfin Server", - Uuid = udn - // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. - }; - - SetProperties(device, fullService); - _publisher!.AddDevice(device); - - var embeddedDevices = new[] - { - "urn:schemas-upnp-org:service:ContentDirectory:1", - "urn:schemas-upnp-org:service:ConnectionManager:1", - // "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1" - }; - - foreach (var subDevice in embeddedDevices) - { - var embeddedDevice = new SsdpEmbeddedDevice - { - FriendlyName = device.FriendlyName, - Manufacturer = device.Manufacturer, - ModelName = device.ModelName, - Uuid = udn - // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. - }; - - SetProperties(embeddedDevice, subDevice); - device.AddDevice(embeddedDevice); - } - } - } - - private void StartPlayToManager() - { - lock (_syncLock) - { - if (_manager is not null) - { - return; - } - - try - { - _manager = new PlayToManager( - _logger, - _sessionManager, - _libraryManager, - _userManager, - _dlnaManager, - _appHost, - _imageProcessor, - _deviceDiscovery, - _httpClientFactory, - _userDataManager, - _localization, - _mediaSourceManager, - _mediaEncoder); - - _manager.Start(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error starting PlayTo manager"); - } - } - } - - private void DisposePlayToManager() - { - lock (_syncLock) - { - if (_manager is not null) - { - try - { - _logger.LogInformation("Disposing PlayToManager"); - _manager.Dispose(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error disposing PlayTo manager"); - } - - _manager = null; - } - } - } - - private void DisposeDevicePublisher() - { - if (_publisher is not null) - { - _logger.LogInformation("Disposing SsdpDevicePublisher"); - _publisher.Dispose(); - _publisher = null; - } - } - - private void Stop() - { - DisposeDevicePublisher(); - DisposePlayToManager(); - } -} |
