Updating to NetCollection 1.03
This commit is contained in:
parent
8c85cfd01d
commit
bbe2400b59
|
@ -28,8 +28,7 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.7" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.7" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.7" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.7" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.7" />
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.7" />
|
||||||
<PackageReference Include="Mono.Nat" Version="3.0.0" />
|
<PackageReference Include="NetworkCollection" Version="1.0.3" />
|
||||||
<PackageReference Include="NetworkCollection" Version="1.0.1" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -12,6 +12,7 @@ using MediaBrowser.Model.Configuration;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NetworkCollection;
|
using NetworkCollection;
|
||||||
|
using NetworkCollection.Udp;
|
||||||
|
|
||||||
namespace Jellyfin.Networking.Manager
|
namespace Jellyfin.Networking.Manager
|
||||||
{
|
{
|
||||||
|
@ -125,29 +126,19 @@ namespace Jellyfin.Networking.Manager
|
||||||
public event EventHandler? NetworkChanged;
|
public event EventHandler? NetworkChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the unique network location signature, which is updated on every network change.
|
/// Gets or sets a value indicating whether testing is taking place.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string NetworkLocationSignature { get; internal set; } = Guid.NewGuid().ToString();
|
public static string MockNetworkSettings { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether IP6 is enabled.
|
/// Gets or sets a value indicating whether IP6 is enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool IsIP6Enabled { get; internal set; }
|
public bool IsIP6Enabled { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether IP4 is enabled.
|
/// Gets or sets a value indicating whether IP4 is enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool IsIP4Enabled { get; internal set; } = true;
|
public bool IsIP4Enabled { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether is multi-socket binding available.
|
|
||||||
/// </summary>
|
|
||||||
public static bool EnableMultiSocketBinding { get; internal set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of times the network address has changed.
|
|
||||||
/// </summary>
|
|
||||||
public static int NetworkChangeCount { get; internal set; } = 1;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public NetCollection RemoteAddressFilter { get; private set; }
|
public NetCollection RemoteAddressFilter { get; private set; }
|
||||||
|
@ -271,7 +262,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public NetCollection GetAllBindInterfaces()
|
public NetCollection GetAllBindInterfaces(bool individualInterfaces = false)
|
||||||
{
|
{
|
||||||
lock (_intLock)
|
lock (_intLock)
|
||||||
{
|
{
|
||||||
|
@ -285,6 +276,11 @@ namespace Jellyfin.Networking.Manager
|
||||||
return _interfaceAddresses.Exclude(_bindExclusions);
|
return _interfaceAddresses.Exclude(_bindExclusions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (individualInterfaces)
|
||||||
|
{
|
||||||
|
return new NetCollection(_interfaceAddresses);
|
||||||
|
}
|
||||||
|
|
||||||
// No bind address and no exclusions, so listen on all interfaces.
|
// No bind address and no exclusions, so listen on all interfaces.
|
||||||
NetCollection result = new NetCollection();
|
NetCollection result = new NetCollection();
|
||||||
|
|
||||||
|
@ -311,12 +307,6 @@ namespace Jellyfin.Networking.Manager
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(source))
|
if (!string.IsNullOrEmpty(source))
|
||||||
{
|
{
|
||||||
if (string.Equals(source, "chromecast", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
// Just assign a variable so has source = true;
|
|
||||||
return GetBindInterface(IPNetAddress.IP4Loopback, out port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IPHost.TryParse(source, out IPHost host))
|
if (IPHost.TryParse(source, out IPHost host))
|
||||||
{
|
{
|
||||||
return GetBindInterface(host, out port);
|
return GetBindInterface(host, out port);
|
||||||
|
@ -572,16 +562,18 @@ namespace Jellyfin.Networking.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool TryParseInterface(string token, out IPNetAddress result)
|
public bool TryParseInterface(string token, out NetCollection? result)
|
||||||
{
|
{
|
||||||
|
result = null;
|
||||||
if (string.IsNullOrEmpty(token))
|
if (string.IsNullOrEmpty(token))
|
||||||
{
|
{
|
||||||
result = IPNetAddress.None;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_interfaceNames != null && _interfaceNames.TryGetValue(token.ToLower(CultureInfo.InvariantCulture), out int index))
|
if (_interfaceNames != null && _interfaceNames.TryGetValue(token.ToLower(CultureInfo.InvariantCulture), out int index))
|
||||||
{
|
{
|
||||||
|
result = new NetCollection();
|
||||||
|
|
||||||
_logger.LogInformation("Interface {0} used in settings. Using its interface addresses.", token);
|
_logger.LogInformation("Interface {0} used in settings. Using its interface addresses.", token);
|
||||||
|
|
||||||
// Replace interface tags with the interface IP's.
|
// Replace interface tags with the interface IP's.
|
||||||
|
@ -591,13 +583,14 @@ namespace Jellyfin.Networking.Manager
|
||||||
((IsIP4Enabled && iface.Address.AddressFamily == AddressFamily.InterNetwork) ||
|
((IsIP4Enabled && iface.Address.AddressFamily == AddressFamily.InterNetwork) ||
|
||||||
(IsIP6Enabled && iface.Address.AddressFamily == AddressFamily.InterNetworkV6)))
|
(IsIP6Enabled && iface.Address.AddressFamily == AddressFamily.InterNetworkV6)))
|
||||||
{
|
{
|
||||||
result = iface;
|
result.Add(iface);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return IPNetAddress.TryParse(token, out result);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -614,9 +607,27 @@ namespace Jellyfin.Networking.Manager
|
||||||
IsIP4Enabled = Socket.OSSupportsIPv6 && config.EnableIPV4;
|
IsIP4Enabled = Socket.OSSupportsIPv6 && config.EnableIPV4;
|
||||||
IsIP6Enabled = Socket.OSSupportsIPv6 && config.EnableIPV6;
|
IsIP6Enabled = Socket.OSSupportsIPv6 && config.EnableIPV6;
|
||||||
TrustAllIP6Interfaces = config.TrustAllIP6Interfaces;
|
TrustAllIP6Interfaces = config.TrustAllIP6Interfaces;
|
||||||
EnableMultiSocketBinding = config.EnableMultiSocketBinding;
|
UdpHelper.EnableMultiSocketBinding = config.EnableMultiSocketBinding;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(MockNetworkSettings))
|
||||||
|
{
|
||||||
|
InitialiseInterfaces();
|
||||||
|
}
|
||||||
|
else // Used in testing only.
|
||||||
|
{
|
||||||
|
// Format is <IPAddress>,<Index>,<Name>: <next interface>. Set index to -ve to simulate a gateway.
|
||||||
|
var interfaceList = MockNetworkSettings.Split(':');
|
||||||
|
foreach (var details in interfaceList)
|
||||||
|
{
|
||||||
|
var parts = details.Split(',');
|
||||||
|
var address = IPNetAddress.Parse(parts[0]);
|
||||||
|
var index = int.Parse(parts[1], CultureInfo.InvariantCulture);
|
||||||
|
address.Tag = index;
|
||||||
|
_interfaceAddresses.Add(address);
|
||||||
|
_interfaceNames.Add(parts[2], Math.Abs(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InitialiseInterfaces();
|
|
||||||
InitialiseLAN(config);
|
InitialiseLAN(config);
|
||||||
InitialiseBind(config);
|
InitialiseBind(config);
|
||||||
InitialiseRemote(config);
|
InitialiseRemote(config);
|
||||||
|
@ -671,6 +682,40 @@ namespace Jellyfin.Networking.Manager
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks the string to see if it matches any interface names.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token">String to check.</param>
|
||||||
|
/// <param name="index">Interface index number.</param>
|
||||||
|
/// <returns>True if an interface name matches the token.</returns>
|
||||||
|
private bool IsInterface(string token, out int index)
|
||||||
|
{
|
||||||
|
index = -1;
|
||||||
|
|
||||||
|
// Is it the name of an interface (windows) eg, Wireless LAN adapter Wireless Network Connection 1.
|
||||||
|
// Null check required here for automated testing.
|
||||||
|
if (_interfaceNames != null && token.Length > 1)
|
||||||
|
{
|
||||||
|
bool partial = token[^1] == '*';
|
||||||
|
if (partial)
|
||||||
|
{
|
||||||
|
token = token[0..^1];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ((string interfc, int interfcIndex) in _interfaceNames)
|
||||||
|
{
|
||||||
|
if ((!partial && string.Equals(interfc, token, StringComparison.OrdinalIgnoreCase)) ||
|
||||||
|
(partial && interfc.StartsWith(token, true, CultureInfo.InvariantCulture)))
|
||||||
|
{
|
||||||
|
index = interfcIndex;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses strings into the collection, replacing any interface references.
|
/// Parses strings into the collection, replacing any interface references.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -680,7 +725,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
{
|
{
|
||||||
// Is it the name of an interface (windows) eg, Wireless LAN adapter Wireless Network Connection 1.
|
// Is it the name of an interface (windows) eg, Wireless LAN adapter Wireless Network Connection 1.
|
||||||
// Null check required here for automated testing.
|
// Null check required here for automated testing.
|
||||||
if (_interfaceNames != null && _interfaceNames.TryGetValue(token.ToLower(CultureInfo.InvariantCulture), out int index))
|
if (IsInterface(token, out int index))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Interface {0} used in settings. Using its interface addresses.", token);
|
_logger.LogInformation("Interface {0} used in settings. Using its interface addresses.", token);
|
||||||
|
|
||||||
|
@ -774,14 +819,6 @@ namespace Jellyfin.Networking.Manager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnNetworkChanged()
|
private void OnNetworkChanged()
|
||||||
{
|
{
|
||||||
// As per UPnP Device Architecture v1.0 Annex A - IPv6 Support.
|
|
||||||
NetworkLocationSignature = Guid.NewGuid().ToString();
|
|
||||||
NetworkChangeCount++;
|
|
||||||
if (NetworkChangeCount > 99)
|
|
||||||
{
|
|
||||||
NetworkChangeCount = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_eventfire)
|
if (!_eventfire)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Network Address Change Event.");
|
_logger.LogDebug("Network Address Change Event.");
|
||||||
|
@ -800,20 +837,14 @@ namespace Jellyfin.Networking.Manager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitialiseOverrides(ServerConfiguration config)
|
private void InitialiseOverrides(ServerConfiguration config)
|
||||||
{
|
{
|
||||||
string[] overrides = config.PublishedServerUriBySubnet;
|
|
||||||
if (overrides == null)
|
|
||||||
{
|
|
||||||
lock (_intLock)
|
|
||||||
{
|
|
||||||
_publishedServerUrls.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_intLock)
|
lock (_intLock)
|
||||||
{
|
{
|
||||||
_publishedServerUrls.Clear();
|
_publishedServerUrls.Clear();
|
||||||
|
string[] overrides = config.PublishedServerUriBySubnet;
|
||||||
|
if (overrides == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var entry in overrides)
|
foreach (var entry in overrides)
|
||||||
{
|
{
|
||||||
|
@ -833,9 +864,16 @@ namespace Jellyfin.Networking.Manager
|
||||||
{
|
{
|
||||||
_publishedServerUrls[new IPNetAddress(IPAddress.Any)] = replacement;
|
_publishedServerUrls[new IPNetAddress(IPAddress.Any)] = replacement;
|
||||||
}
|
}
|
||||||
else if (TryParseInterface(parts[0], out IPNetAddress address))
|
else if (TryParseInterface(parts[0], out NetCollection? addresses) && addresses != null)
|
||||||
{
|
{
|
||||||
_publishedServerUrls[address] = replacement;
|
foreach (IPNetAddress na in addresses)
|
||||||
|
{
|
||||||
|
_publishedServerUrls[na] = replacement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IPNetAddress.TryParse(parts[0], out IPNetAddress result))
|
||||||
|
{
|
||||||
|
_publishedServerUrls[result] = replacement;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -859,6 +897,14 @@ namespace Jellyfin.Networking.Manager
|
||||||
|
|
||||||
// TODO: end fix.
|
// TODO: end fix.
|
||||||
|
|
||||||
|
// Add virtual machine interface names to the list of bind exclusions, so that they are auto-excluded.
|
||||||
|
if (config.IgnoreVirtualInterfaces)
|
||||||
|
{
|
||||||
|
var newList = ba.ToList();
|
||||||
|
newList.AddRange(config.VirtualInterfaceNames.Split(',').ToList());
|
||||||
|
ba = newList.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
// Read and parse bind addresses and exclusions, removing ones that don't exist.
|
// Read and parse bind addresses and exclusions, removing ones that don't exist.
|
||||||
_bindAddresses = CreateIPCollection(ba).Union(_interfaceAddresses);
|
_bindAddresses = CreateIPCollection(ba).Union(_interfaceAddresses);
|
||||||
_bindExclusions = CreateIPCollection(ba, true).Union(_interfaceAddresses);
|
_bindExclusions = CreateIPCollection(ba, true).Union(_interfaceAddresses);
|
||||||
|
|
|
@ -34,13 +34,24 @@ namespace MediaBrowser.Common.Net
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NetCollection RemoteAddressFilter { get; }
|
NetCollection RemoteAddressFilter { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether iP6 is enabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsIP6Enabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether iP4 is enabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsIP4Enabled { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the list of interfaces to use for Kestrel.
|
/// Calculates the list of interfaces to use for Kestrel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A NetCollection object containing all the interfaces to bind.
|
/// <returns>A NetCollection object containing all the interfaces to bind.
|
||||||
/// If all the interfaces are specified, and none are excluded, it returns zero items
|
/// If all the interfaces are specified, and none are excluded, it returns zero items
|
||||||
/// to represent any address.</returns>
|
/// to represent any address.</returns>
|
||||||
NetCollection GetAllBindInterfaces();
|
/// <param name="individualInterfaces">When false, return <see cref="IPAddress.Any"/> or <see cref="IPAddress.IPv6Any"/> for all interfaces.</param>
|
||||||
|
NetCollection GetAllBindInterfaces(bool individualInterfaces = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a collection containing the loopback interfaces.
|
/// Returns a collection containing the loopback interfaces.
|
||||||
|
@ -166,9 +177,9 @@ namespace MediaBrowser.Common.Net
|
||||||
/// eg. "eth1", or "TP-LINK Wireless USB Adapter".
|
/// eg. "eth1", or "TP-LINK Wireless USB Adapter".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="token">Token to parse.</param>
|
/// <param name="token">Token to parse.</param>
|
||||||
/// <param name="result">Resultant object if successful.</param>
|
/// <param name="result">Resultant object's ip addresses, if successful.</param>
|
||||||
/// <returns>Success of the operation.</returns>
|
/// <returns>Success of the operation.</returns>
|
||||||
bool TryParseInterface(string token, out IPNetAddress result);
|
bool TryParseInterface(string token, out NetCollection? result);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses an array of strings into a NetCollection.
|
/// Parses an array of strings into a NetCollection.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#nullable disable
|
#nullable enable
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable CA1819
|
#pragma warning disable CA1819
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether detailed ssdp logs are sent to the console/log.
|
/// Gets or sets a value indicating whether detailed ssdp logs are sent to the console/log.
|
||||||
/// If the setting "Emby.Dlna": "Debug" msut be set in logging.default.json for this property to work.
|
/// "Emby.Dlna": "Debug" must be set in logging.default.json for this property to work.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableSSDPTracing { get; set; } = false;
|
public bool EnableSSDPTracing { get; set; } = false;
|
||||||
|
|
||||||
|
@ -131,13 +131,23 @@ namespace MediaBrowser.Model.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int UDPSendDelay { get; set; } = 100;
|
public int UDPSendDelay { get; set; } = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether address names that match <see cref="VirtualInterfaceNames"/> should be Ignore for the purposes of binding.
|
||||||
|
/// </summary>
|
||||||
|
public bool IgnoreVirtualInterfaces { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating the interfaces that should be ignored. The list can be comma separated. <seealso cref="IgnoreVirtualInterfaces"/>.
|
||||||
|
/// </summary>
|
||||||
|
public string VirtualInterfaceNames { get; set; } = "vEthernet*";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the time (in seconds) between the pings of SSDP gateway monitor.
|
/// Gets or sets the time (in seconds) between the pings of SSDP gateway monitor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int GatewayMonitorPeriod { get; set; } = 60;
|
public int GatewayMonitorPeriod { get; set; } = 60;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether is multi-socket binding available.
|
/// Gets a value indicating whether multi-socket binding is available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableMultiSocketBinding { get; } = true;
|
public bool EnableMultiSocketBinding { get; } = true;
|
||||||
|
|
||||||
|
@ -158,7 +168,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public string[] PublishedServerUriBySubnet { get; set; } = Array.Empty<string>();
|
public string[] PublishedServerUriBySubnet { get; set; } = Array.Empty<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether gets or sets Autodiscovery tracing.
|
/// Gets or sets a value indicating whether Autodiscovery tracing is enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AutoDiscoveryTracing { get; set; } = false;
|
public bool AutoDiscoveryTracing { get; set; } = false;
|
||||||
|
|
||||||
|
@ -216,9 +226,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
/// Gets or sets a value indicating whether quick connect is available for use on this server.
|
/// Gets or sets a value indicating whether quick connect is available for use on this server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool QuickConnectAvailable { get; set; } = false;
|
public bool QuickConnectAvailable { get; set; } = false;
|
||||||
|
|
||||||
public bool AutoRunWebApp { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether access outside of the LAN is permitted.
|
/// Gets or sets a value indicating whether access outside of the LAN is permitted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -419,6 +427,5 @@ namespace MediaBrowser.Model.Configuration
|
||||||
/// Gets or sets the known proxies.
|
/// Gets or sets the known proxies.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] KnownProxies { get; set; } = Array.Empty<string>();
|
public string[] KnownProxies { get; set; } = Array.Empty<string>();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user