Updated to the latest
This commit is contained in:
parent
084d21cade
commit
9a9b2bfb2e
|
@ -99,8 +99,7 @@ namespace Jellyfin.Networking.Configuration
|
||||||
public bool UPnPCreateHttpPortMap { get; set; }
|
public bool UPnPCreateHttpPortMap { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the UDPPortRange
|
/// Gets or sets the UDPPortRange.
|
||||||
/// Gets or sets client udp port range.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string UDPPortRange { get; set; } = string.Empty;
|
public string UDPPortRange { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
@ -115,8 +114,8 @@ namespace Jellyfin.Networking.Configuration
|
||||||
public bool EnableIPV4 { get; set; } = true;
|
public bool EnableIPV4 { get; set; } = true;
|
||||||
|
|
||||||
/// <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.
|
||||||
/// "Emby.Dlna": "Debug" must 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 have any effect.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableSSDPTracing { get; set; }
|
public bool EnableSSDPTracing { get; set; }
|
||||||
|
|
||||||
|
@ -143,7 +142,6 @@ namespace Jellyfin.Networking.Configuration
|
||||||
public bool IgnoreVirtualInterfaces { get; set; } = true;
|
public bool IgnoreVirtualInterfaces { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the VirtualInterfaceNames
|
|
||||||
/// Gets or sets a value indicating the interfaces that should be ignored. The list can be comma separated. <seealso cref="IgnoreVirtualInterfaces"/>.
|
/// Gets or sets a value indicating the interfaces that should be ignored. The list can be comma separated. <seealso cref="IgnoreVirtualInterfaces"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string VirtualInterfaceNames { get; set; } = "vEthernet*";
|
public string VirtualInterfaceNames { get; set; } = "vEthernet*";
|
||||||
|
|
|
@ -182,7 +182,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
public IReadOnlyCollection<PhysicalAddress> GetMacAddresses()
|
public IReadOnlyCollection<PhysicalAddress> GetMacAddresses()
|
||||||
{
|
{
|
||||||
// Populated in construction - so always has values.
|
// Populated in construction - so always has values.
|
||||||
return _macAddresses.AsReadOnly();
|
return _macAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@ -378,7 +378,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("GetBindInterface: Source: {0}, External: {1}:", haveSource, isExternal);
|
_logger.LogDebug("GetBindInterface: Source: {HaveSource}, External: {IsExternal}:", haveSource, isExternal);
|
||||||
|
|
||||||
// No preference given, so move on to bind addresses.
|
// No preference given, so move on to bind addresses.
|
||||||
if (MatchesBindInterface(source, isExternal, out string result))
|
if (MatchesBindInterface(source, isExternal, out string result))
|
||||||
|
@ -408,20 +408,20 @@ namespace Jellyfin.Networking.Manager
|
||||||
if (intf.Contains(source))
|
if (intf.Contains(source))
|
||||||
{
|
{
|
||||||
result = FormatIP6String(intf.Address);
|
result = FormatIP6String(intf.Address);
|
||||||
_logger.LogDebug("{0}: GetBindInterface: Has source, matched best internal interface on range. {1}", source, result);
|
_logger.LogDebug("{Source}: GetBindInterface: Has source, matched best internal interface on range. {Result}", source, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FormatIP6String(interfaces.First().Address);
|
result = FormatIP6String(interfaces.First().Address);
|
||||||
_logger.LogDebug("{0}: GetBindInterface: Matched first internal interface. {1}", source, result);
|
_logger.LogDebug("{Source}: GetBindInterface: Matched first internal interface. {Result}", source, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There isn't any others, so we'll use the loopback.
|
// There isn't any others, so we'll use the loopback.
|
||||||
result = IsIP6Enabled ? "::" : "127.0.0.1";
|
result = IsIP6Enabled ? "::" : "127.0.0.1";
|
||||||
_logger.LogWarning("{0}: GetBindInterface: Loopback return.", source, result);
|
_logger.LogWarning("{Source}: GetBindInterface: Loopback {Result} returned.", source, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,7 +552,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
{
|
{
|
||||||
result = new Collection<IPObject>();
|
result = new Collection<IPObject>();
|
||||||
|
|
||||||
_logger.LogInformation("Interface {0} used in settings. Using its interface addresses.", token);
|
_logger.LogInformation("Interface {Token} used in settings. Using its interface addresses.", token);
|
||||||
|
|
||||||
// Replace interface tags with the interface IP's.
|
// Replace interface tags with the interface IP's.
|
||||||
foreach (IPNetAddress iface in _interfaceAddresses)
|
foreach (IPNetAddress iface in _interfaceAddresses)
|
||||||
|
@ -575,7 +575,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
/// Reloads all settings and re-initialises the instance.
|
/// Reloads all settings and re-initialises the instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="configuration">The <see cref="NetworkConfiguration"/> to use.</param>
|
/// <param name="configuration">The <see cref="NetworkConfiguration"/> to use.</param>
|
||||||
public void UpdateSettings(NetworkConfiguration configuration)
|
public void UpdateSettings(object configuration)
|
||||||
{
|
{
|
||||||
NetworkConfiguration config = (NetworkConfiguration)configuration ?? throw new ArgumentNullException(nameof(configuration));
|
NetworkConfiguration config = (NetworkConfiguration)configuration ?? throw new ArgumentNullException(nameof(configuration));
|
||||||
|
|
||||||
|
@ -740,7 +740,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
// Null check required here for automated testing.
|
// Null check required here for automated testing.
|
||||||
if (IsInterface(token, out int index))
|
if (IsInterface(token, out int index))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Interface {0} used in settings. Using its interface addresses.", token);
|
_logger.LogInformation("Interface {Token} used in settings. Using its interface addresses.", token);
|
||||||
|
|
||||||
// Replace interface tags with the interface IP's.
|
// Replace interface tags with the interface IP's.
|
||||||
foreach (IPNetAddress iface in _interfaceAddresses)
|
foreach (IPNetAddress iface in _interfaceAddresses)
|
||||||
|
@ -780,7 +780,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Invalid or unknown network {0}.", token);
|
_logger.LogDebug("Invalid or unknown network {Token}.", token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,7 +867,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
var parts = entry.Split('=');
|
var parts = entry.Split('=');
|
||||||
if (parts.Length != 2)
|
if (parts.Length != 2)
|
||||||
{
|
{
|
||||||
_logger.LogError("Unable to parse bind override. {0}", entry);
|
_logger.LogError("Unable to parse bind override: {Entry}", entry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -893,7 +893,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Unable to parse bind ip address. {0}", parts[1]);
|
_logger.LogError("Unable to parse bind ip address. {Parts}", parts[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -904,6 +904,8 @@ namespace Jellyfin.Networking.Manager
|
||||||
/// Initialises the network bind addresses.
|
/// Initialises the network bind addresses.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitialiseBind(NetworkConfiguration config)
|
private void InitialiseBind(NetworkConfiguration config)
|
||||||
|
{
|
||||||
|
lock (_intLock)
|
||||||
{
|
{
|
||||||
string[] lanAddresses = config.LocalNetworkAddresses;
|
string[] lanAddresses = config.LocalNetworkAddresses;
|
||||||
|
|
||||||
|
@ -919,9 +921,11 @@ namespace Jellyfin.Networking.Manager
|
||||||
// Add virtual machine interface names to the list of bind exclusions, so that they are auto-excluded.
|
// Add virtual machine interface names to the list of bind exclusions, so that they are auto-excluded.
|
||||||
if (config.IgnoreVirtualInterfaces)
|
if (config.IgnoreVirtualInterfaces)
|
||||||
{
|
{
|
||||||
var newList = lanAddresses.ToList();
|
var virtualInterfaceNames = config.VirtualInterfaceNames.Split(',');
|
||||||
newList.AddRange(config.VirtualInterfaceNames.Split(',').ToList());
|
var newList = new string[lanAddresses.Length + virtualInterfaceNames.Length];
|
||||||
lanAddresses = newList.ToArray();
|
Array.Copy(lanAddresses, newList, lanAddresses.Length);
|
||||||
|
Array.Copy(virtualInterfaceNames, 0, newList, lanAddresses.Length, virtualInterfaceNames.Length);
|
||||||
|
lanAddresses = newList;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -930,14 +934,18 @@ namespace Jellyfin.Networking.Manager
|
||||||
_logger.LogInformation("Using bind addresses: {0}", _bindAddresses.AsString());
|
_logger.LogInformation("Using bind addresses: {0}", _bindAddresses.AsString());
|
||||||
_logger.LogInformation("Using bind exclusions: {0}", _bindExclusions.AsString());
|
_logger.LogInformation("Using bind exclusions: {0}", _bindExclusions.AsString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialises the remote address values.
|
/// Initialises the remote address values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitialiseRemote(NetworkConfiguration config)
|
private void InitialiseRemote(NetworkConfiguration config)
|
||||||
|
{
|
||||||
|
lock (_intLock)
|
||||||
{
|
{
|
||||||
RemoteAddressFilter = CreateIPCollection(config.RemoteIPFilter);
|
RemoteAddressFilter = CreateIPCollection(config.RemoteIPFilter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialises internal LAN cache settings.
|
/// Initialises internal LAN cache settings.
|
||||||
|
@ -959,7 +967,8 @@ namespace Jellyfin.Networking.Manager
|
||||||
// If no LAN addresses are specified - all private subnets are deemed to be the LAN
|
// If no LAN addresses are specified - all private subnets are deemed to be the LAN
|
||||||
_usingPrivateAddresses = _lanSubnets.Count == 0;
|
_usingPrivateAddresses = _lanSubnets.Count == 0;
|
||||||
|
|
||||||
// NOTE: The order of the commands in this statement matters.
|
// NOTE: The order of the commands generating the collection in this statement matters.
|
||||||
|
// Altering the order will cause the collections to be created incorrectly.
|
||||||
if (_usingPrivateAddresses)
|
if (_usingPrivateAddresses)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Using LAN interface addresses as user provided no LAN details.");
|
_logger.LogDebug("Using LAN interface addresses as user provided no LAN details.");
|
||||||
|
@ -1020,6 +1029,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
|
|
||||||
_interfaceNames.Clear();
|
_interfaceNames.Clear();
|
||||||
_interfaceAddresses.Clear();
|
_interfaceAddresses.Clear();
|
||||||
|
_macAddresses.Clear();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -1051,7 +1061,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
};
|
};
|
||||||
|
|
||||||
int tag = nw.Tag;
|
int tag = nw.Tag;
|
||||||
if ((ipProperties.GatewayAddresses.Count > 0) && !nw.IsLoopback())
|
if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback())
|
||||||
{
|
{
|
||||||
// -ve Tags signify the interface has a gateway.
|
// -ve Tags signify the interface has a gateway.
|
||||||
nw.Tag *= -1;
|
nw.Tag *= -1;
|
||||||
|
@ -1072,7 +1082,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
};
|
};
|
||||||
|
|
||||||
int tag = nw.Tag;
|
int tag = nw.Tag;
|
||||||
if ((ipProperties.GatewayAddresses.Count > 0) && !nw.IsLoopback())
|
if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback())
|
||||||
{
|
{
|
||||||
// -ve Tags signify the interface has a gateway.
|
// -ve Tags signify the interface has a gateway.
|
||||||
nw.Tag *= -1;
|
nw.Tag *= -1;
|
||||||
|
@ -1087,9 +1097,10 @@ namespace Jellyfin.Networking.Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning disable CA1031 // Do not catch general exception types
|
#pragma warning disable CA1031 // Do not catch general exception types
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Ignore error, and attempt to continue.
|
// Ignore error, and attempt to continue.
|
||||||
|
_logger.LogError(ex, "Error encountered parsing interfaces.");
|
||||||
}
|
}
|
||||||
#pragma warning restore CA1031 // Do not catch general exception types
|
#pragma warning restore CA1031 // Do not catch general exception types
|
||||||
}
|
}
|
||||||
|
@ -1100,8 +1111,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
// If for some reason we don't have an interface info, resolve our DNS name.
|
// If for some reason we don't have an interface info, resolve our DNS name.
|
||||||
if (_interfaceAddresses.Count == 0)
|
if (_interfaceAddresses.Count == 0)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("No interfaces information available. Using loopback.");
|
_logger.LogError("No interfaces information available. Resolving DNS name.");
|
||||||
|
|
||||||
IPHost host = new IPHost(Dns.GetHostName());
|
IPHost host = new IPHost(Dns.GetHostName());
|
||||||
foreach (var a in host.GetAddresses())
|
foreach (var a in host.GetAddresses())
|
||||||
{
|
{
|
||||||
|
@ -1110,7 +1120,7 @@ namespace Jellyfin.Networking.Manager
|
||||||
|
|
||||||
if (_interfaceAddresses.Count == 0)
|
if (_interfaceAddresses.Count == 0)
|
||||||
{
|
{
|
||||||
_logger.LogError("No interfaces information available. Resolving DNS name.");
|
_logger.LogWarning("No interfaces information available. Using loopback.");
|
||||||
// Last ditch attempt - use loopback address.
|
// Last ditch attempt - use loopback address.
|
||||||
_interfaceAddresses.AddItem(IPNetAddress.IP4Loopback);
|
_interfaceAddresses.AddItem(IPNetAddress.IP4Loopback);
|
||||||
if (IsIP6Enabled)
|
if (IsIP6Enabled)
|
||||||
|
@ -1131,11 +1141,11 @@ namespace Jellyfin.Networking.Manager
|
||||||
/// Attempts to match the source against a user defined bind interface.
|
/// Attempts to match the source against a user defined bind interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source">IP source address to use.</param>
|
/// <param name="source">IP source address to use.</param>
|
||||||
/// <param name="isExternal">True if the source is in the external subnet.</param>
|
/// <param name="isInExternalSubnet">True if the source is in the external subnet.</param>
|
||||||
/// <param name="bindPreference">The published server url that matches the source address.</param>
|
/// <param name="bindPreference">The published server url that matches the source address.</param>
|
||||||
/// <param name="port">The resultant port, if one exists.</param>
|
/// <param name="port">The resultant port, if one exists.</param>
|
||||||
/// <returns><c>true</c> if a match is found, <c>false</c> otherwise.</returns>
|
/// <returns><c>true</c> if a match is found, <c>false</c> otherwise.</returns>
|
||||||
private bool MatchesPublishedServerUrl(IPObject source, bool isExternal, out string bindPreference, out int? port)
|
private bool MatchesPublishedServerUrl(IPObject source, bool isInExternalSubnet, out string bindPreference, out int? port)
|
||||||
{
|
{
|
||||||
bindPreference = string.Empty;
|
bindPreference = string.Empty;
|
||||||
port = null;
|
port = null;
|
||||||
|
@ -1144,12 +1154,12 @@ namespace Jellyfin.Networking.Manager
|
||||||
foreach (var addr in _publishedServerUrls)
|
foreach (var addr in _publishedServerUrls)
|
||||||
{
|
{
|
||||||
// Remaining. Match anything.
|
// Remaining. Match anything.
|
||||||
if (addr.Key.Equals(IPAddress.Broadcast))
|
if (addr.Key.Address.Equals(IPAddress.Broadcast))
|
||||||
{
|
{
|
||||||
bindPreference = addr.Value;
|
bindPreference = addr.Value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ((addr.Key.Equals(IPAddress.Any) || addr.Key.Equals(IPAddress.IPv6Any)) && isExternal)
|
else if ((addr.Key.Address.Equals(IPAddress.Any) || addr.Key.Address.Equals(IPAddress.IPv6Any)) && isInExternalSubnet)
|
||||||
{
|
{
|
||||||
// External.
|
// External.
|
||||||
bindPreference = addr.Value;
|
bindPreference = addr.Value;
|
||||||
|
@ -1163,8 +1173,11 @@ namespace Jellyfin.Networking.Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(bindPreference))
|
if (string.IsNullOrEmpty(bindPreference))
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Has it got a port defined?
|
// Has it got a port defined?
|
||||||
var parts = bindPreference.Split(':');
|
var parts = bindPreference.Split(':');
|
||||||
if (parts.Length > 1)
|
if (parts.Length > 1)
|
||||||
|
@ -1179,22 +1192,19 @@ namespace Jellyfin.Networking.Manager
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to match the source against a user defined bind interface.
|
/// Attempts to match the source against a user defined bind interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source">IP source address to use.</param>
|
/// <param name="source">IP source address to use.</param>
|
||||||
/// <param name="isExternal">True if the source is in the external subnet.</param>
|
/// <param name="isInExternalSubnet">True if the source is in the external subnet.</param>
|
||||||
/// <param name="result">The result, if a match is found.</param>
|
/// <param name="result">The result, if a match is found.</param>
|
||||||
/// <returns><c>true</c> if a match is found, <c>false</c> otherwise.</returns>
|
/// <returns><c>true</c> if a match is found, <c>false</c> otherwise.</returns>
|
||||||
private bool MatchesBindInterface(IPObject source, bool isExternal, out string result)
|
private bool MatchesBindInterface(IPObject source, bool isInExternalSubnet, out string result)
|
||||||
{
|
{
|
||||||
result = string.Empty;
|
result = string.Empty;
|
||||||
var nc = _bindAddresses.Exclude(_bindExclusions);
|
var addresses = _bindAddresses.Exclude(_bindExclusions);
|
||||||
|
|
||||||
int count = nc.Count;
|
int count = addresses.Count;
|
||||||
if (count == 1 && (_bindAddresses[0].Equals(IPAddress.Any) || _bindAddresses[0].Equals(IPAddress.IPv6Any)))
|
if (count == 1 && (_bindAddresses[0].Equals(IPAddress.Any) || _bindAddresses[0].Equals(IPAddress.IPv6Any)))
|
||||||
{
|
{
|
||||||
// Ignore IPAny addresses.
|
// Ignore IPAny addresses.
|
||||||
|
@ -1205,26 +1215,34 @@ namespace Jellyfin.Networking.Manager
|
||||||
{
|
{
|
||||||
// Check to see if any of the bind interfaces are in the same subnet.
|
// Check to see if any of the bind interfaces are in the same subnet.
|
||||||
|
|
||||||
Collection<IPObject> bindResult;
|
|
||||||
IPAddress? defaultGateway = null;
|
IPAddress? defaultGateway = null;
|
||||||
IPAddress? bindAddress;
|
IPAddress? bindAddress = null;
|
||||||
|
|
||||||
if (isExternal)
|
if (isInExternalSubnet)
|
||||||
{
|
{
|
||||||
// Find all external bind addresses. Store the default gateway, but check to see if there is a better match first.
|
// Find all external bind addresses. Store the default gateway, but check to see if there is a better match first.
|
||||||
bindResult = CreateCollection(nc
|
foreach (var addr in addresses.OrderBy(p => p.Tag))
|
||||||
.Where(p => !IsInLocalNetwork(p))
|
{
|
||||||
.OrderBy(p => p.Tag));
|
if (defaultGateway == null && !IsInLocalNetwork(addr))
|
||||||
defaultGateway = bindResult.FirstOrDefault()?.Address;
|
{
|
||||||
bindAddress = bindResult
|
defaultGateway = addr.Address;
|
||||||
.Where(p => p.Contains(source))
|
}
|
||||||
.OrderBy(p => p.Tag)
|
|
||||||
.FirstOrDefault()?.Address;
|
if (bindAddress == null && addr.Contains(source))
|
||||||
|
{
|
||||||
|
bindAddress = addr.Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultGateway != null && bindAddress != null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Look for the best internal address.
|
// Look for the best internal address.
|
||||||
bindAddress = nc
|
bindAddress = addresses
|
||||||
.Where(p => IsInLocalNetwork(p) && (p.Contains(source) || p.Equals(IPAddress.None)))
|
.Where(p => IsInLocalNetwork(p) && (p.Contains(source) || p.Equals(IPAddress.None)))
|
||||||
.OrderBy(p => p.Tag)
|
.OrderBy(p => p.Tag)
|
||||||
.FirstOrDefault()?.Address;
|
.FirstOrDefault()?.Address;
|
||||||
|
@ -1233,23 +1251,23 @@ namespace Jellyfin.Networking.Manager
|
||||||
if (bindAddress != null)
|
if (bindAddress != null)
|
||||||
{
|
{
|
||||||
result = FormatIP6String(bindAddress);
|
result = FormatIP6String(bindAddress);
|
||||||
_logger.LogDebug("{0}: GetBindInterface: Has source, found a match bind interface subnets. {1}", source, result);
|
_logger.LogDebug("{Source}: GetBindInterface: Has source, found a match bind interface subnets. {Result}", source, result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isExternal && defaultGateway != null)
|
if (isInExternalSubnet && defaultGateway != null)
|
||||||
{
|
{
|
||||||
result = FormatIP6String(defaultGateway);
|
result = FormatIP6String(defaultGateway);
|
||||||
_logger.LogDebug("{0}: GetBindInterface: Using first user defined external interface. {1}", source, result);
|
_logger.LogDebug("{Source}: GetBindInterface: Using first user defined external interface. {Result}", source, result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FormatIP6String(nc.First().Address);
|
result = FormatIP6String(addresses[0].Address);
|
||||||
_logger.LogDebug("{0}: GetBindInterface: Selected first user defined interface. {1}", source, result);
|
_logger.LogDebug("{Source}: GetBindInterface: Selected first user defined interface. {Result}", source, result);
|
||||||
|
|
||||||
if (isExternal)
|
if (isInExternalSubnet)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("{0}: External request received, however, only an internal interface bind found.", source);
|
_logger.LogWarning("{Source}: External request received, however, only an internal interface bind found.", source);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1268,12 +1286,12 @@ namespace Jellyfin.Networking.Manager
|
||||||
{
|
{
|
||||||
result = string.Empty;
|
result = string.Empty;
|
||||||
// Get the first WAN interface address that isn't a loopback.
|
// Get the first WAN interface address that isn't a loopback.
|
||||||
var extResult = CreateCollection(_interfaceAddresses
|
var extResult = _interfaceAddresses
|
||||||
.Exclude(_bindExclusions)
|
.Exclude(_bindExclusions)
|
||||||
.Where(p => !IsInLocalNetwork(p))
|
.Where(p => !IsInLocalNetwork(p))
|
||||||
.OrderBy(p => p.Tag));
|
.OrderBy(p => p.Tag);
|
||||||
|
|
||||||
if (extResult.Count > 0)
|
if (extResult.Any())
|
||||||
{
|
{
|
||||||
// Does the request originate in one of the interface subnets?
|
// Does the request originate in one of the interface subnets?
|
||||||
// (For systems with multiple internal network cards, and multiple subnets)
|
// (For systems with multiple internal network cards, and multiple subnets)
|
||||||
|
@ -1282,19 +1300,19 @@ namespace Jellyfin.Networking.Manager
|
||||||
if (!IsInLocalNetwork(intf) && intf.Contains(source))
|
if (!IsInLocalNetwork(intf) && intf.Contains(source))
|
||||||
{
|
{
|
||||||
result = FormatIP6String(intf.Address);
|
result = FormatIP6String(intf.Address);
|
||||||
_logger.LogDebug("{0}: GetBindInterface: Selected best external on interface on range. {1}", source, result);
|
_logger.LogDebug("{Source}: GetBindInterface: Selected best external on interface on range. {Result}", source, result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FormatIP6String(extResult.First().Address);
|
result = FormatIP6String(extResult.First().Address);
|
||||||
_logger.LogDebug("{0}: GetBindInterface: Selected first external interface. {0}", source, result);
|
_logger.LogDebug("{Source}: GetBindInterface: Selected first external interface. {Result}", source, result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to return something, so return an internal address
|
// Have to return something, so return an internal address
|
||||||
|
|
||||||
_logger.LogWarning("{0}: External request received, however, no WAN interface found.", source);
|
_logger.LogWarning("{Source}: External request received, however, no WAN interface found.", source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
@ -13,6 +14,11 @@ namespace MediaBrowser.Common.Net
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class IPHost : IPObject
|
public class IPHost : IPObject
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets timeout value before resolve required, in minutes.
|
||||||
|
/// </summary>
|
||||||
|
public const int Timeout = 30;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an IPHost that has no value.
|
/// Represents an IPHost that has no value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -21,7 +27,7 @@ namespace MediaBrowser.Common.Net
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Time when last resolved in ticks.
|
/// Time when last resolved in ticks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private long _lastResolved;
|
private DateTime? _lastResolved = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the IP Addresses, attempting to resolve the name, if there are none.
|
/// Gets the IP Addresses, attempting to resolve the name, if there are none.
|
||||||
|
@ -83,15 +89,9 @@ namespace MediaBrowser.Common.Net
|
||||||
{
|
{
|
||||||
// Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length,
|
// Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length,
|
||||||
// which is automatically determined by it's IP type. Anything else is meaningless.
|
// which is automatically determined by it's IP type. Anything else is meaningless.
|
||||||
throw new NotImplementedException("The prefix length on a host cannot be set.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets timeout value before resolve required, in minutes.
|
|
||||||
/// </summary>
|
|
||||||
public byte Timeout { get; set; } = 30;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether the address has a value.
|
/// Gets a value indicating whether the address has a value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -395,15 +395,15 @@ namespace MediaBrowser.Common.Net
|
||||||
private bool ResolveHost()
|
private bool ResolveHost()
|
||||||
{
|
{
|
||||||
// When was the last time we resolved?
|
// When was the last time we resolved?
|
||||||
if (_lastResolved == 0)
|
if (_lastResolved == null)
|
||||||
{
|
{
|
||||||
_lastResolved = DateTime.UtcNow.Ticks;
|
_lastResolved = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we haven't resolved before, or out timer has run out...
|
// If we haven't resolved before, or our timer has run out...
|
||||||
if ((_addresses.Length == 0 && !Resolved) || (TimeSpan.FromTicks(DateTime.UtcNow.Ticks - _lastResolved).TotalMinutes > Timeout))
|
if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved?.AddMinutes(Timeout)))
|
||||||
{
|
{
|
||||||
_lastResolved = DateTime.UtcNow.Ticks;
|
_lastResolved = DateTime.UtcNow;
|
||||||
ResolveHostInternal().GetAwaiter().GetResult();
|
ResolveHostInternal().GetAwaiter().GetResult();
|
||||||
Resolved = true;
|
Resolved = true;
|
||||||
}
|
}
|
||||||
|
@ -433,9 +433,10 @@ namespace MediaBrowser.Common.Net
|
||||||
IPHostEntry ip = await Dns.GetHostEntryAsync(HostName).ConfigureAwait(false);
|
IPHostEntry ip = await Dns.GetHostEntryAsync(HostName).ConfigureAwait(false);
|
||||||
_addresses = ip.AddressList;
|
_addresses = ip.AddressList;
|
||||||
}
|
}
|
||||||
catch (SocketException)
|
catch (SocketException ex)
|
||||||
{
|
{
|
||||||
// Ignore socket errors, as the result value will just be an empty array.
|
// Log and then ignore socket errors, as the result value will just be an empty array.
|
||||||
|
Debug.WriteLine("GetHostEntryAsync failed with {Message}.", ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,17 @@ namespace MediaBrowser.Common.Net
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IPv4 multicast address.
|
/// IPv4 multicast address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly IPAddress MulticastIPv4 = IPAddress.Parse("239.255.255.250");
|
public static readonly IPAddress SSDPMulticastIPv4 = IPAddress.Parse("239.255.255.250");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IPv6 local link multicast address.
|
/// IPv6 local link multicast address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly IPAddress MulticastIPv6LinkLocal = IPAddress.Parse("ff02::C");
|
public static readonly IPAddress SSDPMulticastIPv6LinkLocal = IPAddress.Parse("ff02::C");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IPv6 site local multicast address.
|
/// IPv6 site local multicast address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly IPAddress MulticastIPv6SiteLocal = IPAddress.Parse("ff05::C");
|
public static readonly IPAddress SSDPMulticastIPv6SiteLocal = IPAddress.Parse("ff05::C");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IP4Loopback address host.
|
/// IP4Loopback address host.
|
||||||
|
@ -235,7 +235,7 @@ namespace MediaBrowser.Common.Net
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a textual representation of this object.
|
/// Returns a textual representation of this object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shortVersion">Set to true, if the subnet is to be included as part of the address.</param>
|
/// <param name="shortVersion">Set to true, if the subnet is to be excluded as part of the address.</param>
|
||||||
/// <returns>String representation of this object.</returns>
|
/// <returns>String representation of this object.</returns>
|
||||||
public string ToString(bool shortVersion)
|
public string ToString(bool shortVersion)
|
||||||
{
|
{
|
||||||
|
|
|
@ -86,7 +86,9 @@ namespace MediaBrowser.Common.Net
|
||||||
// prefix length value. eg. /16 on a 4 octet ip4 address (192.168.2.240) will result in the 2 and the 240 being zeroed out.
|
// prefix length value. eg. /16 on a 4 octet ip4 address (192.168.2.240) will result in the 2 and the 240 being zeroed out.
|
||||||
// Where there is not an exact boundary (eg /23), mod is used to calculate how many bits of this value are to be kept.
|
// Where there is not an exact boundary (eg /23), mod is used to calculate how many bits of this value are to be kept.
|
||||||
|
|
||||||
byte[] addressBytes = address.GetAddressBytes();
|
// GetAddressBytes
|
||||||
|
Span<byte> addressBytes = stackalloc byte[address.AddressFamily == AddressFamily.InterNetwork ? 4 : 16];
|
||||||
|
address.TryWriteBytes(addressBytes, out _);
|
||||||
|
|
||||||
int div = prefixLength / 8;
|
int div = prefixLength / 8;
|
||||||
int mod = prefixLength % 8;
|
int mod = prefixLength % 8;
|
||||||
|
@ -169,15 +171,17 @@ namespace MediaBrowser.Common.Net
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!address.Equals(IPAddress.None))
|
if (!address.Equals(IPAddress.None))
|
||||||
{
|
|
||||||
if (address.AddressFamily == AddressFamily.InterNetwork)
|
|
||||||
{
|
{
|
||||||
if (address.IsIPv4MappedToIPv6)
|
if (address.IsIPv4MappedToIPv6)
|
||||||
{
|
{
|
||||||
address = address.MapToIPv4();
|
address = address.MapToIPv4();
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] octet = address.GetAddressBytes();
|
if (address.AddressFamily == AddressFamily.InterNetwork)
|
||||||
|
{
|
||||||
|
// GetAddressBytes
|
||||||
|
Span<byte> octet = stackalloc byte[4];
|
||||||
|
address.TryWriteBytes(octet, out _);
|
||||||
|
|
||||||
return (octet[0] == 10)
|
return (octet[0] == 10)
|
||||||
|| (octet[0] == 172 && octet[1] >= 16 && octet[1] <= 31) // RFC1918
|
|| (octet[0] == 172 && octet[1] >= 16 && octet[1] <= 31) // RFC1918
|
||||||
|
@ -186,7 +190,10 @@ namespace MediaBrowser.Common.Net
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byte[] octet = address.GetAddressBytes();
|
// GetAddressBytes
|
||||||
|
Span<byte> octet = stackalloc byte[16];
|
||||||
|
address.TryWriteBytes(octet, out _);
|
||||||
|
|
||||||
uint word = (uint)(octet[0] << 8) + octet[1];
|
uint word = (uint)(octet[0] << 8) + octet[1];
|
||||||
|
|
||||||
return (word >= 0xfe80 && word <= 0xfebf) // fe80::/10 :Local link.
|
return (word >= 0xfe80 && word <= 0xfebf) // fe80::/10 :Local link.
|
||||||
|
@ -223,7 +230,9 @@ namespace MediaBrowser.Common.Net
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] octet = address.GetAddressBytes();
|
// GetAddressBytes
|
||||||
|
Span<byte> octet = stackalloc byte[16];
|
||||||
|
address.TryWriteBytes(octet, out _);
|
||||||
uint word = (uint)(octet[0] << 8) + octet[1];
|
uint word = (uint)(octet[0] << 8) + octet[1];
|
||||||
|
|
||||||
return word >= 0xfe80 && word <= 0xfebf; // fe80::/10 :Local link.
|
return word >= 0xfe80 && word <= 0xfebf; // fe80::/10 :Local link.
|
||||||
|
@ -261,7 +270,9 @@ namespace MediaBrowser.Common.Net
|
||||||
byte cidrnet = 0;
|
byte cidrnet = 0;
|
||||||
if (!mask.Equals(IPAddress.Any))
|
if (!mask.Equals(IPAddress.Any))
|
||||||
{
|
{
|
||||||
byte[] bytes = mask.GetAddressBytes();
|
// GetAddressBytes
|
||||||
|
Span<byte> bytes = stackalloc byte[mask.AddressFamily == AddressFamily.InterNetwork ? 4 : 16];
|
||||||
|
mask.TryWriteBytes(bytes, out _);
|
||||||
|
|
||||||
var zeroed = false;
|
var zeroed = false;
|
||||||
for (var i = 0; i < bytes.Length; i++)
|
for (var i = 0; i < bytes.Length; i++)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user