mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-06-01 04:34:26 -04:00
Revert "Use System.Net.IPNetwork"
This reverts commit 117d05d288da1d412159a29c0cb8d5c8259e48ae.
This commit is contained in:
parent
0fd36a5bf1
commit
635d67d458
@ -1,363 +0,0 @@
|
|||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Emby.Dlna.PlayTo;
|
|
||||||
using Emby.Dlna.Ssdp;
|
|
||||||
using Jellyfin.Networking.Configuration;
|
|
||||||
using Jellyfin.Networking.Extensions;
|
|
||||||
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.Plugins;
|
|
||||||
using MediaBrowser.Controller.Session;
|
|
||||||
using MediaBrowser.Model.Dlna;
|
|
||||||
using MediaBrowser.Model.Globalization;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Rssdp;
|
|
||||||
using Rssdp.Infrastructure;
|
|
||||||
|
|
||||||
namespace Emby.Dlna.Main
|
|
||||||
{
|
|
||||||
public sealed class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup
|
|
||||||
{
|
|
||||||
private readonly IServerConfigurationManager _config;
|
|
||||||
private readonly ILogger<DlnaEntryPoint> _logger;
|
|
||||||
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 readonly bool _disabled;
|
|
||||||
|
|
||||||
private PlayToManager _manager;
|
|
||||||
private SsdpDevicePublisher _publisher;
|
|
||||||
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
public DlnaEntryPoint(
|
|
||||||
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<DlnaEntryPoint>();
|
|
||||||
|
|
||||||
var netConfig = config.GetConfiguration<NetworkConfiguration>(NetworkConfigurationStore.StoreKey);
|
|
||||||
_disabled = appHost.ListenWithHttps && netConfig.RequireHttps;
|
|
||||||
|
|
||||||
if (_disabled && _config.GetDlnaConfiguration().EnableServer)
|
|
||||||
{
|
|
||||||
_logger.LogError("The DLNA specification does not support HTTPS.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (_disabled)
|
|
||||||
{
|
|
||||||
// No use starting as dlna won't work, as we're running purely on HTTPS.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReloadComponents();
|
|
||||||
|
|
||||||
_config.NamedConfigurationUpdated += OnNamedConfigurationUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 void StartDeviceDiscovery()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
((DeviceDiscovery)_deviceDiscovery).Start(_communicationsServer);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error starting device discovery");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public 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.Address is not null)
|
|
||||||
.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 = NetworkExtensions.MaskToCidr(intf.Subnet.BaseAddress),
|
|
||||||
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 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 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DisposeDevicePublisher()
|
|
||||||
{
|
|
||||||
if (_publisher is not null)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Disposing SsdpDevicePublisher");
|
|
||||||
_publisher.Dispose();
|
|
||||||
_publisher = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DisposeDevicePublisher();
|
|
||||||
DisposePlayToManager();
|
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -169,7 +169,7 @@ public class EnvironmentController : BaseJellyfinApiController
|
|||||||
// Check if unc share
|
// Check if unc share
|
||||||
var index = path.LastIndexOf(UncSeparator);
|
var index = path.LastIndexOf(UncSeparator);
|
||||||
|
|
||||||
if (index != -1 && path.IndexOf(UncSeparator, StringComparison.OrdinalIgnoreCase) == 0)
|
if (index != -1 && path[0] == UncSeparator)
|
||||||
{
|
{
|
||||||
parent = path.Substring(0, index);
|
parent = path.Substring(0, index);
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ public class HlsSegmentController : BaseJellyfinApiController
|
|||||||
var pathExtension = Path.GetExtension(path);
|
var pathExtension = Path.GetExtension(path);
|
||||||
if ((string.Equals(pathExtension, segmentContainer, StringComparison.OrdinalIgnoreCase)
|
if ((string.Equals(pathExtension, segmentContainer, StringComparison.OrdinalIgnoreCase)
|
||||||
|| string.Equals(pathExtension, ".m3u8", StringComparison.OrdinalIgnoreCase))
|
|| string.Equals(pathExtension, ".m3u8", StringComparison.OrdinalIgnoreCase))
|
||||||
&& path.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1)
|
&& path.Contains(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
playlistPath = path;
|
playlistPath = path;
|
||||||
break;
|
break;
|
||||||
|
@ -80,7 +80,7 @@ public class ImageController : BaseJellyfinApiController
|
|||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream GetFromBase64Stream(Stream inputStream)
|
private static CryptoStream GetFromBase64Stream(Stream inputStream)
|
||||||
=> new CryptoStream(inputStream, new FromBase64Transform(), CryptoStreamMode.Read);
|
=> new CryptoStream(inputStream, new FromBase64Transform(), CryptoStreamMode.Read);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -150,7 +150,7 @@ public class MusicGenresController : BaseJellyfinApiController
|
|||||||
|
|
||||||
MusicGenre? item;
|
MusicGenre? item;
|
||||||
|
|
||||||
if (genreName.IndexOf(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase) != -1)
|
if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
item = GetItemFromSlugName<MusicGenre>(_libraryManager, genreName, dtoOptions, BaseItemKind.MusicGenre);
|
item = GetItemFromSlugName<MusicGenre>(_libraryManager, genreName, dtoOptions, BaseItemKind.MusicGenre);
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,10 @@ public static class DtoExtensions
|
|||||||
|
|
||||||
if (!dtoOptions.ContainsField(ItemFields.RecursiveItemCount))
|
if (!dtoOptions.ContainsField(ItemFields.RecursiveItemCount))
|
||||||
{
|
{
|
||||||
if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 ||
|
if (client.Contains("kodi", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("wmc", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.Contains("wmc", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.Contains("media center", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1)
|
client.Contains("classic", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
int oldLen = dtoOptions.Fields.Count;
|
int oldLen = dtoOptions.Fields.Count;
|
||||||
var arr = new ItemFields[oldLen + 1];
|
var arr = new ItemFields[oldLen + 1];
|
||||||
@ -53,13 +53,13 @@ public static class DtoExtensions
|
|||||||
|
|
||||||
if (!dtoOptions.ContainsField(ItemFields.ChildCount))
|
if (!dtoOptions.ContainsField(ItemFields.ChildCount))
|
||||||
{
|
{
|
||||||
if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 ||
|
if (client.Contains("kodi", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("wmc", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.Contains("wmc", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.Contains("media center", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.Contains("classic", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("roku", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.Contains("roku", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("samsung", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.Contains("samsung", StringComparison.OrdinalIgnoreCase) ||
|
||||||
client.IndexOf("androidtv", StringComparison.OrdinalIgnoreCase) != -1)
|
client.Contains("androidtv", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
int oldLen = dtoOptions.Fields.Count;
|
int oldLen = dtoOptions.Fields.Count;
|
||||||
var arr = new ItemFields[oldLen + 1];
|
var arr = new ItemFields[oldLen + 1];
|
||||||
|
@ -53,7 +53,7 @@ public static class HlsHelpers
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1)
|
if (line.Contains("#EXTINF:", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if (count >= segmentCount)
|
if (count >= segmentCount)
|
||||||
|
@ -405,7 +405,7 @@ public class TranscodingJobHelper : IDisposable
|
|||||||
var name = Path.GetFileNameWithoutExtension(outputFilePath);
|
var name = Path.GetFileNameWithoutExtension(outputFilePath);
|
||||||
|
|
||||||
var filesToDelete = _fileSystem.GetFilePaths(directory)
|
var filesToDelete = _fileSystem.GetFilePaths(directory)
|
||||||
.Where(f => f.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1);
|
.Where(f => f.Contains(name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
List<Exception>? exs = null;
|
List<Exception>? exs = null;
|
||||||
foreach (var file in filesToDelete)
|
foreach (var file in filesToDelete)
|
||||||
|
@ -86,11 +86,11 @@ public class StreamState : EncodingJobInfo, IDisposable
|
|||||||
{
|
{
|
||||||
var userAgent = UserAgent ?? string.Empty;
|
var userAgent = UserAgent ?? string.Empty;
|
||||||
|
|
||||||
if (userAgent.IndexOf("AppleTV", StringComparison.OrdinalIgnoreCase) != -1
|
if (userAgent.Contains("AppleTV", StringComparison.OrdinalIgnoreCase)
|
||||||
|| userAgent.IndexOf("cfnetwork", StringComparison.OrdinalIgnoreCase) != -1
|
|| userAgent.Contains("cfnetwork", StringComparison.OrdinalIgnoreCase)
|
||||||
|| userAgent.IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1
|
|| userAgent.Contains("ipad", StringComparison.OrdinalIgnoreCase)
|
||||||
|| userAgent.IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1
|
|| userAgent.Contains("iphone", StringComparison.OrdinalIgnoreCase)
|
||||||
|| userAgent.IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
|
|| userAgent.Contains("ipod", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,12 @@ using MediaBrowser.Common.Configuration;
|
|||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
|
using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
|
||||||
using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager;
|
using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager;
|
||||||
|
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
|
||||||
|
|
||||||
namespace Jellyfin.Networking.Manager
|
namespace Jellyfin.Networking.Manager
|
||||||
{
|
{
|
||||||
@ -530,7 +532,7 @@ namespace Jellyfin.Networking.Manager
|
|||||||
{
|
{
|
||||||
foreach (var lan in _lanSubnets)
|
foreach (var lan in _lanSubnets)
|
||||||
{
|
{
|
||||||
var lanPrefix = lan.BaseAddress;
|
var lanPrefix = lan.Prefix;
|
||||||
publishedServerUrls.Add(
|
publishedServerUrls.Add(
|
||||||
new PublishedServerUriOverride(
|
new PublishedServerUriOverride(
|
||||||
new IPData(lanPrefix, new IPNetwork(lanPrefix, lan.PrefixLength)),
|
new IPData(lanPrefix, new IPNetwork(lanPrefix, lan.PrefixLength)),
|
||||||
@ -541,7 +543,7 @@ namespace Jellyfin.Networking.Manager
|
|||||||
}
|
}
|
||||||
else if (NetworkUtils.TryParseToSubnet(identifier, out var result) && result is not null)
|
else if (NetworkUtils.TryParseToSubnet(identifier, out var result) && result is not null)
|
||||||
{
|
{
|
||||||
var data = new IPData(result.Value.BaseAddress, result);
|
var data = new IPData(result.Prefix, result);
|
||||||
publishedServerUrls.Add(
|
publishedServerUrls.Add(
|
||||||
new PublishedServerUriOverride(
|
new PublishedServerUriOverride(
|
||||||
data,
|
data,
|
||||||
@ -607,11 +609,11 @@ namespace Jellyfin.Networking.Manager
|
|||||||
var parts = details.Split(',');
|
var parts = details.Split(',');
|
||||||
if (NetworkUtils.TryParseToSubnet(parts[0], out var subnet))
|
if (NetworkUtils.TryParseToSubnet(parts[0], out var subnet))
|
||||||
{
|
{
|
||||||
var address = subnet.Value.BaseAddress;
|
var address = subnet.Prefix;
|
||||||
var index = int.Parse(parts[1], CultureInfo.InvariantCulture);
|
var index = int.Parse(parts[1], CultureInfo.InvariantCulture);
|
||||||
if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6)
|
if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
var data = new IPData(address, subnet.Value, parts[2])
|
var data = new IPData(address, subnet, parts[2])
|
||||||
{
|
{
|
||||||
Index = index
|
Index = index
|
||||||
};
|
};
|
||||||
@ -881,7 +883,7 @@ namespace Jellyfin.Networking.Manager
|
|||||||
{
|
{
|
||||||
if (NetworkUtils.TryParseToSubnet(address, out var subnet))
|
if (NetworkUtils.TryParseToSubnet(address, out var subnet))
|
||||||
{
|
{
|
||||||
return IPAddress.IsLoopback(subnet.Value.BaseAddress) || (_lanSubnets.Any(x => x.Contains(subnet.Value.BaseAddress)) && !_excludedSubnets.Any(x => x.Contains(subnet.Value.BaseAddress)));
|
return IPAddress.IsLoopback(subnet.Prefix) || (_lanSubnets.Any(x => x.Contains(subnet.Prefix)) && !_excludedSubnets.Any(x => x.Contains(subnet.Prefix)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetworkUtils.TryParseHost(address, out var addresses, IsIPv4Enabled, IsIPv6Enabled))
|
if (NetworkUtils.TryParseHost(address, out var addresses, IsIPv4Enabled, IsIPv6Enabled))
|
||||||
@ -1112,12 +1114,12 @@ namespace Jellyfin.Networking.Manager
|
|||||||
var logLevel = debug ? LogLevel.Debug : LogLevel.Information;
|
var logLevel = debug ? LogLevel.Debug : LogLevel.Information;
|
||||||
if (_logger.IsEnabled(logLevel))
|
if (_logger.IsEnabled(logLevel))
|
||||||
{
|
{
|
||||||
_logger.Log(logLevel, "Defined LAN addresses: {0}", _lanSubnets.Select(s => s.BaseAddress + "/" + s.PrefixLength));
|
_logger.Log(logLevel, "Defined LAN addresses: {0}", _lanSubnets.Select(s => s.Prefix + "/" + s.PrefixLength));
|
||||||
_logger.Log(logLevel, "Defined LAN exclusions: {0}", _excludedSubnets.Select(s => s.BaseAddress + "/" + s.PrefixLength));
|
_logger.Log(logLevel, "Defined LAN exclusions: {0}", _excludedSubnets.Select(s => s.Prefix + "/" + s.PrefixLength));
|
||||||
_logger.Log(logLevel, "Using LAN addresses: {0}", _lanSubnets.Where(s => !_excludedSubnets.Contains(s)).Select(s => s.BaseAddress + "/" + s.PrefixLength));
|
_logger.Log(logLevel, "Using LAN addresses: {0}", _lanSubnets.Where(s => !_excludedSubnets.Contains(s)).Select(s => s.Prefix + "/" + s.PrefixLength));
|
||||||
_logger.Log(logLevel, "Using bind addresses: {0}", _interfaces.OrderByDescending(x => x.AddressFamily == AddressFamily.InterNetwork).Select(x => x.Address));
|
_logger.Log(logLevel, "Using bind addresses: {0}", _interfaces.OrderByDescending(x => x.AddressFamily == AddressFamily.InterNetwork).Select(x => x.Address));
|
||||||
_logger.Log(logLevel, "Remote IP filter is {0}", config.IsRemoteIPFilterBlacklist ? "Blocklist" : "Allowlist");
|
_logger.Log(logLevel, "Remote IP filter is {0}", config.IsRemoteIPFilterBlacklist ? "Blocklist" : "Allowlist");
|
||||||
_logger.Log(logLevel, "Filter list: {0}", _remoteAddressFilter.Select(s => s.BaseAddress + "/" + s.PrefixLength));
|
_logger.Log(logLevel, "Filter list: {0}", _remoteAddressFilter.Select(s => s.Prefix + "/" + s.PrefixLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,7 +748,7 @@ namespace Jellyfin.Server.Implementations.Users
|
|||||||
return GetPasswordResetProviders(user)[0];
|
return GetPasswordResetProviders(user)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private IList<IAuthenticationProvider> GetAuthenticationProviders(User? user)
|
private List<IAuthenticationProvider> GetAuthenticationProviders(User? user)
|
||||||
{
|
{
|
||||||
var authenticationProviderId = user?.AuthenticationProviderId;
|
var authenticationProviderId = user?.AuthenticationProviderId;
|
||||||
|
|
||||||
|
@ -279,9 +279,9 @@ namespace Jellyfin.Server.Extensions
|
|||||||
}
|
}
|
||||||
else if (NetworkUtils.TryParseToSubnet(allowedProxies[i], out var subnet))
|
else if (NetworkUtils.TryParseToSubnet(allowedProxies[i], out var subnet))
|
||||||
{
|
{
|
||||||
if (subnet.HasValue)
|
if (subnet is not null)
|
||||||
{
|
{
|
||||||
AddIPAddress(config, options, subnet.Value.BaseAddress, subnet.Value.PrefixLength);
|
AddIPAddress(config, options, subnet.Prefix, subnet.PrefixLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (NetworkUtils.TryParseHost(allowedProxies[i], out var addresses, config.EnableIPv4, config.EnableIPv6))
|
else if (NetworkUtils.TryParseHost(allowedProxies[i], out var addresses, config.EnableIPv4, config.EnableIPv6))
|
||||||
|
@ -40,7 +40,7 @@ namespace Jellyfin.Server
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string LoggingConfigFileSystem = "logging.json";
|
public const string LoggingConfigFileSystem = "logging.json";
|
||||||
|
|
||||||
private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
|
private static readonly SerilogLoggerFactory _loggerFactory = new SerilogLoggerFactory();
|
||||||
private static long _startTimestamp;
|
private static long _startTimestamp;
|
||||||
private static ILogger _logger = NullLogger.Instance;
|
private static ILogger _logger = NullLogger.Instance;
|
||||||
private static bool _restartOnShutdown;
|
private static bool _restartOnShutdown;
|
||||||
|
@ -35,7 +35,7 @@ namespace Jellyfin.Server
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
private readonly IServerApplicationHost _serverApplicationHost;
|
private readonly CoreAppHost _serverApplicationHost;
|
||||||
private readonly IServerConfigurationManager _serverConfigurationManager;
|
private readonly IServerConfigurationManager _serverConfigurationManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
|
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net;
|
namespace MediaBrowser.Common.Net;
|
||||||
|
|
||||||
|
@ -5,8 +5,7 @@ using System.Net;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Jellyfin.Extensions;
|
using Jellyfin.Extensions;
|
||||||
using Jellyfin.Networking.Constants;
|
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net;
|
namespace MediaBrowser.Common.Net;
|
||||||
|
|
||||||
@ -180,7 +179,7 @@ public static partial class NetworkUtils
|
|||||||
{
|
{
|
||||||
if (TryParseToSubnet(values[a], out var innerResult, negated))
|
if (TryParseToSubnet(values[a], out var innerResult, negated))
|
||||||
{
|
{
|
||||||
tmpResult.Add(innerResult.Value);
|
tmpResult.Add(innerResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +335,7 @@ public static partial class NetworkUtils
|
|||||||
/// <returns>The broadcast address.</returns>
|
/// <returns>The broadcast address.</returns>
|
||||||
public static IPAddress GetBroadcastAddress(IPNetwork network)
|
public static IPAddress GetBroadcastAddress(IPNetwork network)
|
||||||
{
|
{
|
||||||
var addressBytes = network.BaseAddress.GetAddressBytes();
|
var addressBytes = network.Prefix.GetAddressBytes();
|
||||||
uint ipAddress = BitConverter.ToUInt32(addressBytes, 0);
|
uint ipAddress = BitConverter.ToUInt32(addressBytes, 0);
|
||||||
uint ipMaskV4 = BitConverter.ToUInt32(CidrToMask(network.PrefixLength, AddressFamily.InterNetwork).GetAddressBytes(), 0);
|
uint ipMaskV4 = BitConverter.ToUInt32(CidrToMask(network.PrefixLength, AddressFamily.InterNetwork).GetAddressBytes(), 0);
|
||||||
uint broadCastIPAddress = ipAddress | ~ipMaskV4;
|
uint broadCastIPAddress = ipAddress | ~ipMaskV4;
|
||||||
|
@ -121,7 +121,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
"yadif_videotoolbox"
|
"yadif_videotoolbox"
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly IReadOnlyDictionary<int, string[]> _filterOptionsDict = new Dictionary<int, string[]>
|
private static readonly Dictionary<int, string[]> _filterOptionsDict = new Dictionary<int, string[]>
|
||||||
{
|
{
|
||||||
{ 0, new string[] { "scale_cuda", "Output format (default \"same\")" } },
|
{ 0, new string[] { "scale_cuda", "Output format (default \"same\")" } },
|
||||||
{ 1, new string[] { "tonemap_cuda", "GPU accelerated HDR to SDR tonemapping" } },
|
{ 1, new string[] { "tonemap_cuda", "GPU accelerated HDR to SDR tonemapping" } },
|
||||||
@ -132,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
};
|
};
|
||||||
|
|
||||||
// These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below
|
// These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below
|
||||||
private static readonly IReadOnlyDictionary<string, Version> _ffmpegMinimumLibraryVersions = new Dictionary<string, Version>
|
private static readonly Dictionary<string, Version> _ffmpegMinimumLibraryVersions = new Dictionary<string, Version>
|
||||||
{
|
{
|
||||||
{ "libavutil", new Version(56, 14) },
|
{ "libavutil", new Version(56, 14) },
|
||||||
{ "libavcodec", new Version(58, 18) },
|
{ "libavcodec", new Version(58, 18) },
|
||||||
@ -197,7 +197,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
internal bool ValidateVersionInternal(string versionOutput)
|
internal bool ValidateVersionInternal(string versionOutput)
|
||||||
{
|
{
|
||||||
if (versionOutput.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1)
|
if (versionOutput.Contains("Libav developers", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_logger.LogError("FFmpeg validation: avconv instead of ffmpeg is not supported");
|
_logger.LogError("FFmpeg validation: avconv instead of ffmpeg is not supported");
|
||||||
return false;
|
return false;
|
||||||
@ -333,7 +333,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="output">The 'ffmpeg -version' output.</param>
|
/// <param name="output">The 'ffmpeg -version' output.</param>
|
||||||
/// <returns>The library names and major.minor version numbers.</returns>
|
/// <returns>The library names and major.minor version numbers.</returns>
|
||||||
private static IReadOnlyDictionary<string, Version> GetFFmpegLibraryVersions(string output)
|
private static Dictionary<string, Version> GetFFmpegLibraryVersions(string output)
|
||||||
{
|
{
|
||||||
var map = new Dictionary<string, Version>();
|
var map = new Dictionary<string, Version>();
|
||||||
|
|
||||||
@ -537,9 +537,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IDictionary<int, bool> GetFFmpegFiltersWithOption()
|
private Dictionary<int, bool> GetFFmpegFiltersWithOption()
|
||||||
{
|
{
|
||||||
IDictionary<int, bool> dict = new Dictionary<int, bool>();
|
Dictionary<int, bool> dict = new Dictionary<int, bool>();
|
||||||
for (int i = 0; i < _filterOptionsDict.Count; i++)
|
for (int i = 0; i < _filterOptionsDict.Count; i++)
|
||||||
{
|
{
|
||||||
if (_filterOptionsDict.TryGetValue(i, out var val) && val.Length == 2)
|
if (_filterOptionsDict.TryGetValue(i, out var val) && val.Length == 2)
|
||||||
|
@ -59,7 +59,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
private static string GetFileInputArgument(string path, string inputPrefix)
|
private static string GetFileInputArgument(string path, string inputPrefix)
|
||||||
{
|
{
|
||||||
if (path.IndexOf("://", StringComparison.Ordinal) != -1)
|
if (path.Contains("://", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", path);
|
return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", path);
|
||||||
}
|
}
|
||||||
|
@ -612,11 +612,11 @@ namespace MediaBrowser.MediaEncoding.Probing
|
|||||||
{
|
{
|
||||||
codec = "dvbsub";
|
codec = "dvbsub";
|
||||||
}
|
}
|
||||||
else if ((codec ?? string.Empty).IndexOf("PGS", StringComparison.OrdinalIgnoreCase) != -1)
|
else if ((codec ?? string.Empty).Contains("PGS", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
codec = "PGSSUB";
|
codec = "PGSSUB";
|
||||||
}
|
}
|
||||||
else if ((codec ?? string.Empty).IndexOf("DVD", StringComparison.OrdinalIgnoreCase) != -1)
|
else if ((codec ?? string.Empty).Contains("DVD", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
codec = "DVDSUB";
|
codec = "DVDSUB";
|
||||||
}
|
}
|
||||||
@ -1339,7 +1339,7 @@ namespace MediaBrowser.MediaEncoding.Probing
|
|||||||
{
|
{
|
||||||
// Only use the comma as a delimiter if there are no slashes or pipes.
|
// Only use the comma as a delimiter if there are no slashes or pipes.
|
||||||
// We want to be careful not to split names that have commas in them
|
// We want to be careful not to split names that have commas in them
|
||||||
var delimiter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ?
|
var delimiter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.Contains(i, StringComparison.Ordinal)) ?
|
||||||
_nameDelimiters :
|
_nameDelimiters :
|
||||||
new[] { ',' };
|
new[] { ',' };
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
public bool SupportsFileExtension(string fileExtension)
|
public bool SupportsFileExtension(string fileExtension)
|
||||||
=> _subtitleFormats.ContainsKey(fileExtension);
|
=> _subtitleFormats.ContainsKey(fileExtension);
|
||||||
|
|
||||||
private IEnumerable<SubtitleFormat> GetSubtitleFormats()
|
private List<SubtitleFormat> GetSubtitleFormats()
|
||||||
{
|
{
|
||||||
var subtitleFormats = new List<SubtitleFormat>();
|
var subtitleFormats = new List<SubtitleFormat>();
|
||||||
var assembly = typeof(SubtitleFormat).Assembly;
|
var assembly = typeof(SubtitleFormat).Assembly;
|
||||||
|
@ -63,7 +63,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
|
|
||||||
private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles");
|
private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles");
|
||||||
|
|
||||||
private Stream ConvertSubtitles(
|
private MemoryStream ConvertSubtitles(
|
||||||
Stream stream,
|
Stream stream,
|
||||||
string inputFormat,
|
string inputFormat,
|
||||||
string outputFormat,
|
string outputFormat,
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.HttpOverrides" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||||
<PackageReference Include="MimeTypes">
|
<PackageReference Include="MimeTypes">
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Net;
|
namespace MediaBrowser.Model.Net;
|
||||||
|
|
||||||
@ -65,9 +66,9 @@ public class IPData
|
|||||||
{
|
{
|
||||||
if (Address.Equals(IPAddress.None))
|
if (Address.Equals(IPAddress.None))
|
||||||
{
|
{
|
||||||
return Subnet.BaseAddress.AddressFamily.Equals(IPAddress.None)
|
return Subnet.Prefix.AddressFamily.Equals(IPAddress.None)
|
||||||
? AddressFamily.Unspecified
|
? AddressFamily.Unspecified
|
||||||
: Subnet.BaseAddress.AddressFamily;
|
: Subnet.Prefix.AddressFamily;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@ using Microsoft.Extensions.Logging.Abstractions;
|
|||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager;
|
using IConfigurationManager = MediaBrowser.Common.Configuration.IConfigurationManager;
|
||||||
|
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
|
||||||
|
|
||||||
namespace Jellyfin.Server.Tests
|
namespace Jellyfin.Server.Tests
|
||||||
{
|
{
|
||||||
@ -99,7 +100,7 @@ namespace Jellyfin.Server.Tests
|
|||||||
Assert.Equal(knownNetworks.Length, options.KnownNetworks.Count);
|
Assert.Equal(knownNetworks.Length, options.KnownNetworks.Count);
|
||||||
foreach (var item in knownNetworks)
|
foreach (var item in knownNetworks)
|
||||||
{
|
{
|
||||||
Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.Prefix.Equals(item.BaseAddress) && x.PrefixLength == item.PrefixLength));
|
Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.Prefix.Equals(item.Prefix) && x.PrefixLength == item.PrefixLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user