Move away from using Collection, simplify code, add proper ordering

This commit is contained in:
Shadowghost 2022-07-20 14:29:30 +02:00
parent a492082f4e
commit 2281b8c997
7 changed files with 42 additions and 47 deletions

View File

@ -293,7 +293,7 @@ namespace Emby.Dlna.Main
if (bindAddresses.Count == 0) if (bindAddresses.Count == 0)
{ {
// No interfaces returned, so use loopback. // No interfaces returned, so use loopback.
bindAddresses = _networkManager.GetLoopbacks(); bindAddresses = _networkManager.GetLoopbacks().ToList();
} }
foreach (var address in bindAddresses) foreach (var address in bindAddresses)

View File

@ -151,9 +151,9 @@ namespace Jellyfin.Networking.Configuration
public bool IgnoreVirtualInterfaces { get; set; } = true; public bool IgnoreVirtualInterfaces { get; set; } = true;
/// <summary> /// <summary>
/// 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 interface name prefixes that should be ignored. The list can be comma separated and values are case-insensitive. <seealso cref="IgnoreVirtualInterfaces"/>.
/// </summary> /// </summary>
public string VirtualInterfaceNames { get; set; } = "vEthernet*"; public string VirtualInterfaceNames { get; set; } = "veth";
/// <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.

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@ -47,7 +46,7 @@ namespace Jellyfin.Networking.Manager
/// </summary> /// </summary>
private readonly Dictionary<IPData, string> _publishedServerUrls; private readonly Dictionary<IPData, string> _publishedServerUrls;
private Collection<IPNetwork> _remoteAddressFilter; private List<IPNetwork> _remoteAddressFilter;
/// <summary> /// <summary>
/// Used to stop "event-racing conditions". /// Used to stop "event-racing conditions".
@ -58,12 +57,12 @@ namespace Jellyfin.Networking.Manager
/// Unfiltered user defined LAN subnets (<see cref="NetworkConfiguration.LocalNetworkSubnets"/>) /// Unfiltered user defined LAN subnets (<see cref="NetworkConfiguration.LocalNetworkSubnets"/>)
/// or internal interface network subnets if undefined by user. /// or internal interface network subnets if undefined by user.
/// </summary> /// </summary>
private Collection<IPNetwork> _lanSubnets; private List<IPNetwork> _lanSubnets;
/// <summary> /// <summary>
/// User defined list of subnets to excluded from the LAN. /// User defined list of subnets to excluded from the LAN.
/// </summary> /// </summary>
private Collection<IPNetwork> _excludedSubnets; private List<IPNetwork> _excludedSubnets;
/// <summary> /// <summary>
/// List of interfaces to bind to. /// List of interfaces to bind to.
@ -95,7 +94,7 @@ namespace Jellyfin.Networking.Manager
_macAddresses = new List<PhysicalAddress>(); _macAddresses = new List<PhysicalAddress>();
_publishedServerUrls = new Dictionary<IPData, string>(); _publishedServerUrls = new Dictionary<IPData, string>();
_eventFireLock = new object(); _eventFireLock = new object();
_remoteAddressFilter = new Collection<IPNetwork>(); _remoteAddressFilter = new List<IPNetwork>();
UpdateSettings(_configurationManager.GetNetworkConfiguration()); UpdateSettings(_configurationManager.GetNetworkConfiguration());
@ -225,8 +224,8 @@ namespace Jellyfin.Networking.Manager
{ {
try try
{ {
IPInterfaceProperties ipProperties = adapter.GetIPProperties(); var ipProperties = adapter.GetIPProperties();
PhysicalAddress mac = adapter.GetPhysicalAddress(); var mac = adapter.GetPhysicalAddress();
// Populate MAC list // Populate MAC list
if (adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback && PhysicalAddress.None.Equals(mac)) if (adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback && PhysicalAddress.None.Equals(mac))
@ -235,7 +234,7 @@ namespace Jellyfin.Networking.Manager
} }
// Populate interface list // Populate interface list
foreach (UnicastIPAddressInformation info in ipProperties.UnicastAddresses) foreach (var info in ipProperties.UnicastAddresses)
{ {
if (IsIpv4Enabled && info.Address.AddressFamily == AddressFamily.InterNetwork) if (IsIpv4Enabled && info.Address.AddressFamily == AddressFamily.InterNetwork)
{ {
@ -364,8 +363,8 @@ namespace Jellyfin.Networking.Manager
// Use explicit bind addresses // Use explicit bind addresses
if (config.LocalNetworkAddresses.Length > 0) if (config.LocalNetworkAddresses.Length > 0)
{ {
_bindAddresses = config.LocalNetworkAddresses.Select(p => IPAddress.TryParse(p, out var address) _bindAddresses = config.LocalNetworkAddresses.Select(p => IPAddress.TryParse(p, out var addresses)
? address ? addresses
: (_interfaces.Where(x => x.Name.Equals(p, StringComparison.OrdinalIgnoreCase)).Select(x => x.Address).FirstOrDefault() ?? IPAddress.None)).ToList(); : (_interfaces.Where(x => x.Name.Equals(p, StringComparison.OrdinalIgnoreCase)).Select(x => x.Address).FirstOrDefault() ?? IPAddress.None)).ToList();
_bindAddresses.RemoveAll(x => x == IPAddress.None); _bindAddresses.RemoveAll(x => x == IPAddress.None);
} }
@ -525,13 +524,11 @@ namespace Jellyfin.Networking.Manager
var address = IPAddress.Parse(split[0]); var address = IPAddress.Parse(split[0]);
var network = new IPNetwork(address, int.Parse(split[1], CultureInfo.InvariantCulture)); var network = new IPNetwork(address, int.Parse(split[1], CultureInfo.InvariantCulture));
var index = int.Parse(parts[1], CultureInfo.InvariantCulture); var index = int.Parse(parts[1], CultureInfo.InvariantCulture);
if (address.AddressFamily == AddressFamily.InterNetwork) if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6)
{ {
_interfaces.Add(new IPData(address, network, parts[2])); var data = new IPData(address, network, parts[2]);
} data.Index = index;
else if (address.AddressFamily == AddressFamily.InterNetworkV6) _interfaces.Add(data);
{
_interfaces.Add(new IPData(address, network, parts[2]));
} }
} }
} }
@ -562,9 +559,9 @@ namespace Jellyfin.Networking.Manager
} }
/// <inheritdoc/> /// <inheritdoc/>
public bool TryParseInterface(string intf, out Collection<IPData> result) public bool TryParseInterface(string intf, out List<IPData> result)
{ {
result = new Collection<IPData>(); result = new List<IPData>();
if (string.IsNullOrEmpty(intf)) if (string.IsNullOrEmpty(intf))
{ {
return false; return false;
@ -573,7 +570,7 @@ namespace Jellyfin.Networking.Manager
if (_interfaces != null) if (_interfaces != null)
{ {
// Match all interfaces starting with names starting with token // Match all interfaces starting with names starting with token
var matchedInterfaces = _interfaces.Where(s => s.Name.Equals(intf.ToLowerInvariant(), StringComparison.OrdinalIgnoreCase)); var matchedInterfaces = _interfaces.Where(s => s.Name.Equals(intf.ToLowerInvariant(), StringComparison.OrdinalIgnoreCase)).OrderBy(x => x.Index);
if (matchedInterfaces.Any()) if (matchedInterfaces.Any())
{ {
_logger.LogInformation("Interface {Token} used in settings. Using its interface addresses.", intf); _logger.LogInformation("Interface {Token} used in settings. Using its interface addresses.", intf);
@ -626,14 +623,14 @@ namespace Jellyfin.Networking.Manager
} }
/// <inheritdoc/> /// <inheritdoc/>
public IReadOnlyCollection<PhysicalAddress> GetMacAddresses() public IReadOnlyList<PhysicalAddress> GetMacAddresses()
{ {
// Populated in construction - so always has values. // Populated in construction - so always has values.
return _macAddresses; return _macAddresses;
} }
/// <inheritdoc/> /// <inheritdoc/>
public List<IPData> GetLoopbacks() public IReadOnlyList<IPData> GetLoopbacks()
{ {
var loopbackNetworks = new List<IPData>(); var loopbackNetworks = new List<IPData>();
if (IsIpv4Enabled) if (IsIpv4Enabled)
@ -650,7 +647,7 @@ namespace Jellyfin.Networking.Manager
} }
/// <inheritdoc/> /// <inheritdoc/>
public List<IPData> GetAllBindInterfaces(bool individualInterfaces = false) public IReadOnlyList<IPData> GetAllBindInterfaces(bool individualInterfaces = false)
{ {
if (_bindAddresses.Count == 0) if (_bindAddresses.Count == 0)
{ {
@ -816,7 +813,7 @@ namespace Jellyfin.Networking.Manager
} }
/// <inheritdoc/> /// <inheritdoc/>
public List<IPData> GetInternalBindAddresses() public IReadOnlyList<IPData> GetInternalBindAddresses()
{ {
if (_bindAddresses.Count == 0) if (_bindAddresses.Count == 0)
{ {
@ -833,7 +830,8 @@ namespace Jellyfin.Networking.Manager
// Select all local bind addresses // Select all local bind addresses
return _interfaces.Where(x => _bindAddresses.Contains(x.Address)) return _interfaces.Where(x => _bindAddresses.Contains(x.Address))
.Where(x => IsInLocalNetwork(x.Address)) .Where(x => IsInLocalNetwork(x.Address))
.OrderBy(x => x.Index).ToList(); .OrderBy(x => x.Index)
.ToList();
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -892,7 +890,7 @@ namespace Jellyfin.Networking.Manager
interfaces = interfaces.Where(x => IsInLocalNetwork(x.Address)).ToList(); interfaces = interfaces.Where(x => IsInLocalNetwork(x.Address)).ToList();
} }
foreach (var intf in _interfaces) foreach (var intf in interfaces)
{ {
if (intf.Subnet.Contains(address)) if (intf.Subnet.Contains(address))
{ {
@ -942,7 +940,7 @@ namespace Jellyfin.Networking.Manager
foreach (var data in validPublishedServerUrls) foreach (var data in validPublishedServerUrls)
{ {
// Get address interface // Get address interface
var intf = _interfaces.FirstOrDefault(s => s.Subnet.Contains(data.Key.Address)); var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(s => s.Subnet.Contains(data.Key.Address));
// Remaining. Match anything. // Remaining. Match anything.
if (data.Key.Address.Equals(IPAddress.Broadcast)) if (data.Key.Address.Equals(IPAddress.Broadcast))
@ -1017,7 +1015,7 @@ namespace Jellyfin.Networking.Manager
defaultGateway = addr; defaultGateway = addr;
} }
var intf = _interfaces.Where(x => x.Subnet.Contains(addr)).FirstOrDefault(); var intf = _interfaces.Where(x => x.Subnet.Contains(addr)).OrderBy(x => x.Index).FirstOrDefault();
if (bindAddress == null && intf != null && intf.Subnet.Contains(source)) if (bindAddress == null && intf != null && intf.Subnet.Contains(source))
{ {
@ -1082,7 +1080,7 @@ 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 = _interfaces.Where(p => !IsInLocalNetwork(p.Address)); var extResult = _interfaces.Where(p => !IsInLocalNetwork(p.Address)).OrderBy(x => x.Index);
IPAddress? hasResult = null; IPAddress? hasResult = null;
// Does the request originate in one of the interface subnets? // Does the request originate in one of the interface subnets?

View File

@ -114,7 +114,7 @@ public class CreateNetworkConfiguration : IMigrationRoutine
public bool IgnoreVirtualInterfaces { get; set; } = true; public bool IgnoreVirtualInterfaces { get; set; } = true;
public string VirtualInterfaceNames { get; set; } = "veth*"; public string VirtualInterfaceNames { get; set; } = "veth";
public string[] PublishedServerUriBySubnet { get; set; } = Array.Empty<string>(); public string[] PublishedServerUriBySubnet { get; set; } = Array.Empty<string>();

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net; using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -34,13 +33,13 @@ namespace MediaBrowser.Common.Net
/// 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>
/// <param name="individualInterfaces">When false, return <see cref="IPAddress.Any"/> or <see cref="IPAddress.IPv6Any"/> for all interfaces.</param> /// <param name="individualInterfaces">When false, return <see cref="IPAddress.Any"/> or <see cref="IPAddress.IPv6Any"/> for all interfaces.</param>
List<IPData> GetAllBindInterfaces(bool individualInterfaces = false); IReadOnlyList<IPData> GetAllBindInterfaces(bool individualInterfaces = false);
/// <summary> /// <summary>
/// Returns a collection containing the loopback interfaces. /// Returns a list containing the loopback interfaces.
/// </summary> /// </summary>
/// <returns>List{IPData}.</returns> /// <returns>List{IPData}.</returns>
List<IPData> GetLoopbacks(); IReadOnlyList<IPData> GetLoopbacks();
/// <summary> /// <summary>
/// Retrieves the bind address to use in system url's. (Server Discovery, PlayTo, LiveTV, SystemInfo) /// Retrieves the bind address to use in system url's. (Server Discovery, PlayTo, LiveTV, SystemInfo)
@ -97,7 +96,7 @@ namespace MediaBrowser.Common.Net
/// Get a list of all the MAC addresses associated with active interfaces. /// Get a list of all the MAC addresses associated with active interfaces.
/// </summary> /// </summary>
/// <returns>List of MAC addresses.</returns> /// <returns>List of MAC addresses.</returns>
IReadOnlyCollection<PhysicalAddress> GetMacAddresses(); IReadOnlyList<PhysicalAddress> GetMacAddresses();
/// <summary> /// <summary>
/// Returns true if the address is part of the user defined LAN. /// Returns true if the address is part of the user defined LAN.
@ -122,13 +121,13 @@ namespace MediaBrowser.Common.Net
/// <param name="intf">Interface name.</param> /// <param name="intf">Interface name.</param>
/// <param name="result">Resultant object's ip addresses, 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 intf, out Collection<IPData>? result); bool TryParseInterface(string intf, out List<IPData>? result);
/// <summary> /// <summary>
/// Returns all the internal Bind interface addresses. /// Returns all the internal Bind interface addresses.
/// </summary> /// </summary>
/// <returns>An internal list of interfaces addresses.</returns> /// <returns>An internal list of interfaces addresses.</returns>
List<IPData> GetInternalBindAddresses(); IReadOnlyList<IPData> GetInternalBindAddresses();
/// <summary> /// <summary>
/// Checks to see if <paramref name="remoteIp"/> has access. /// Checks to see if <paramref name="remoteIp"/> has access.

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using System; using System;
using System.Collections.ObjectModel; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@ -148,9 +148,9 @@ namespace MediaBrowser.Common.Net
/// <param name="result">Collection of <see cref="IPNetwork"/>.</param> /// <param name="result">Collection of <see cref="IPNetwork"/>.</param>
/// <param name="negated">Boolean signaling if negated or not negated values should be parsed.</param> /// <param name="negated">Boolean signaling if negated or not negated values should be parsed.</param>
/// <returns><c>True</c> if parsing was successful.</returns> /// <returns><c>True</c> if parsing was successful.</returns>
public static bool TryParseSubnets(string[] values, out Collection<IPNetwork> result, bool negated = false) public static bool TryParseSubnets(string[] values, out List<IPNetwork> result, bool negated = false)
{ {
result = new Collection<IPNetwork>(); result = new List<IPNetwork>();
if (values == null || values.Length == 0) if (values == null || values.Length == 0)
{ {

View File

@ -1,5 +1,5 @@
using System; using System;
using System.Collections.ObjectModel; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@ -49,8 +49,6 @@ namespace Jellyfin.Networking.Tests
{ {
EnableIPV6 = true, EnableIPV6 = true,
EnableIPV4 = true, EnableIPV4 = true,
IgnoreVirtualInterfaces = true,
VirtualInterfaceNames = "veth",
LocalNetworkSubnets = lan?.Split(';') ?? throw new ArgumentNullException(nameof(lan)) LocalNetworkSubnets = lan?.Split(';') ?? throw new ArgumentNullException(nameof(lan))
}; };
@ -208,7 +206,7 @@ namespace Jellyfin.Networking.Tests
using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
NetworkManager.MockNetworkSettings = string.Empty; NetworkManager.MockNetworkSettings = string.Empty;
_ = nm.TryParseInterface(result, out Collection<IPData>? resultObj); _ = nm.TryParseInterface(result, out List<IPData>? resultObj);
// Check to see if dns resolution is working. If not, skip test. // Check to see if dns resolution is working. If not, skip test.
_ = NetworkExtensions.TryParseHost(source, out var host); _ = NetworkExtensions.TryParseHost(source, out var host);
@ -277,7 +275,7 @@ namespace Jellyfin.Networking.Tests
using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
NetworkManager.MockNetworkSettings = string.Empty; NetworkManager.MockNetworkSettings = string.Empty;
if (nm.TryParseInterface(result, out Collection<IPData>? resultObj) && resultObj != null) if (nm.TryParseInterface(result, out List<IPData>? resultObj) && resultObj != null)
{ {
// Parse out IPAddresses so we can do a string comparison. (Ignore subnet masks). // Parse out IPAddresses so we can do a string comparison. (Ignore subnet masks).
result = resultObj.First().Address.ToString(); result = resultObj.First().Address.ToString();