diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj
index 454dd9b7df..06d387dc87 100644
--- a/Jellyfin.Networking/Jellyfin.Networking.csproj
+++ b/Jellyfin.Networking/Jellyfin.Networking.csproj
@@ -28,8 +28,7 @@
-
-
+
diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs
index 83661d6b31..6f2970ef89 100644
--- a/Jellyfin.Networking/Manager/NetworkManager.cs
+++ b/Jellyfin.Networking/Manager/NetworkManager.cs
@@ -12,6 +12,7 @@ using MediaBrowser.Model.Configuration;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using NetworkCollection;
+using NetworkCollection.Udp;
namespace Jellyfin.Networking.Manager
{
@@ -125,29 +126,19 @@ namespace Jellyfin.Networking.Manager
public event EventHandler? NetworkChanged;
///
- /// Gets the unique network location signature, which is updated on every network change.
+ /// Gets or sets a value indicating whether testing is taking place.
///
- public static string NetworkLocationSignature { get; internal set; } = Guid.NewGuid().ToString();
+ public static string MockNetworkSettings { get; set; } = string.Empty;
///
- /// Gets a value indicating whether IP6 is enabled.
+ /// Gets or sets a value indicating whether IP6 is enabled.
///
- public static bool IsIP6Enabled { get; internal set; }
+ public bool IsIP6Enabled { get; set; }
///
- /// Gets a value indicating whether IP4 is enabled.
+ /// Gets or sets a value indicating whether IP4 is enabled.
///
- public static bool IsIP4Enabled { get; internal set; } = true;
-
- ///
- /// Gets a value indicating whether is multi-socket binding available.
- ///
- public static bool EnableMultiSocketBinding { get; internal set; } = true;
-
- ///
- /// Gets the number of times the network address has changed.
- ///
- public static int NetworkChangeCount { get; internal set; } = 1;
+ public bool IsIP4Enabled { get; set; }
///
public NetCollection RemoteAddressFilter { get; private set; }
@@ -271,7 +262,7 @@ namespace Jellyfin.Networking.Manager
}
///
- public NetCollection GetAllBindInterfaces()
+ public NetCollection GetAllBindInterfaces(bool individualInterfaces = false)
{
lock (_intLock)
{
@@ -285,6 +276,11 @@ namespace Jellyfin.Networking.Manager
return _interfaceAddresses.Exclude(_bindExclusions);
}
+ if (individualInterfaces)
+ {
+ return new NetCollection(_interfaceAddresses);
+ }
+
// No bind address and no exclusions, so listen on all interfaces.
NetCollection result = new NetCollection();
@@ -311,12 +307,6 @@ namespace Jellyfin.Networking.Manager
{
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))
{
return GetBindInterface(host, out port);
@@ -572,16 +562,18 @@ namespace Jellyfin.Networking.Manager
}
///
- public bool TryParseInterface(string token, out IPNetAddress result)
+ public bool TryParseInterface(string token, out NetCollection? result)
{
+ result = null;
if (string.IsNullOrEmpty(token))
{
- result = IPNetAddress.None;
return false;
}
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);
// Replace interface tags with the interface IP's.
@@ -591,13 +583,14 @@ namespace Jellyfin.Networking.Manager
((IsIP4Enabled && iface.Address.AddressFamily == AddressFamily.InterNetwork) ||
(IsIP6Enabled && iface.Address.AddressFamily == AddressFamily.InterNetworkV6)))
{
- result = iface;
- return true;
+ result.Add(iface);
}
}
+
+ return true;
}
- return IPNetAddress.TryParse(token, out result);
+ return false;
}
///
@@ -614,9 +607,27 @@ namespace Jellyfin.Networking.Manager
IsIP4Enabled = Socket.OSSupportsIPv6 && config.EnableIPV4;
IsIP6Enabled = Socket.OSSupportsIPv6 && config.EnableIPV6;
TrustAllIP6Interfaces = config.TrustAllIP6Interfaces;
- EnableMultiSocketBinding = config.EnableMultiSocketBinding;
+ UdpHelper.EnableMultiSocketBinding = config.EnableMultiSocketBinding;
+
+ if (string.IsNullOrEmpty(MockNetworkSettings))
+ {
+ InitialiseInterfaces();
+ }
+ else // Used in testing only.
+ {
+ // Format is ,,: . 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);
InitialiseBind(config);
InitialiseRemote(config);
@@ -671,6 +682,40 @@ namespace Jellyfin.Networking.Manager
return str;
}
+ ///
+ /// Checks the string to see if it matches any interface names.
+ ///
+ /// String to check.
+ /// Interface index number.
+ /// True if an interface name matches the token.
+ 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;
+ }
+
///
/// Parses strings into the collection, replacing any interface references.
///
@@ -680,7 +725,7 @@ namespace Jellyfin.Networking.Manager
{
// 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 && _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);
@@ -774,14 +819,6 @@ namespace Jellyfin.Networking.Manager
///
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)
{
_logger.LogDebug("Network Address Change Event.");
@@ -800,20 +837,14 @@ namespace Jellyfin.Networking.Manager
///
private void InitialiseOverrides(ServerConfiguration config)
{
- string[] overrides = config.PublishedServerUriBySubnet;
- if (overrides == null)
- {
- lock (_intLock)
- {
- _publishedServerUrls.Clear();
- }
-
- return;
- }
-
lock (_intLock)
{
_publishedServerUrls.Clear();
+ string[] overrides = config.PublishedServerUriBySubnet;
+ if (overrides == null)
+ {
+ return;
+ }
foreach (var entry in overrides)
{
@@ -833,9 +864,16 @@ namespace Jellyfin.Networking.Manager
{
_publishedServerUrls[new IPNetAddress(IPAddress.Any)] = replacement;
}
- else if (TryParseInterface(parts[0], out IPNetAddress address))
+ else if (TryParseInterface(parts[0], out NetCollection? addresses) && addresses != null)
+ {
+ foreach (IPNetAddress na in addresses)
+ {
+ _publishedServerUrls[na] = replacement;
+ }
+ }
+ else if (IPNetAddress.TryParse(parts[0], out IPNetAddress result))
{
- _publishedServerUrls[address] = replacement;
+ _publishedServerUrls[result] = replacement;
}
else
{
@@ -859,6 +897,14 @@ namespace Jellyfin.Networking.Manager
// 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.
_bindAddresses = CreateIPCollection(ba).Union(_interfaceAddresses);
_bindExclusions = CreateIPCollection(ba, true).Union(_interfaceAddresses);
diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs
index 32c017aee6..8789cd9d81 100644
--- a/MediaBrowser.Common/Net/INetworkManager.cs
+++ b/MediaBrowser.Common/Net/INetworkManager.cs
@@ -34,13 +34,24 @@ namespace MediaBrowser.Common.Net
///
NetCollection RemoteAddressFilter { get; }
+ ///
+ /// Gets or sets a value indicating whether iP6 is enabled.
+ ///
+ public bool IsIP6Enabled { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether iP4 is enabled.
+ ///
+ public bool IsIP4Enabled { get; set; }
+
///
/// Calculates the list of interfaces to use for Kestrel.
///
/// A NetCollection object containing all the interfaces to bind.
/// If all the interfaces are specified, and none are excluded, it returns zero items
/// to represent any address.
- NetCollection GetAllBindInterfaces();
+ /// When false, return or for all interfaces.
+ NetCollection GetAllBindInterfaces(bool individualInterfaces = false);
///
/// Returns a collection containing the loopback interfaces.
@@ -166,9 +177,9 @@ namespace MediaBrowser.Common.Net
/// eg. "eth1", or "TP-LINK Wireless USB Adapter".
///
/// Token to parse.
- /// Resultant object if successful.
+ /// Resultant object's ip addresses, if successful.
/// Success of the operation.
- bool TryParseInterface(string token, out IPNetAddress result);
+ bool TryParseInterface(string token, out NetCollection? result);
///
/// Parses an array of strings into a NetCollection.
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 073a629829..dbfab1fad4 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -1,4 +1,4 @@
-#nullable disable
+#nullable enable
#pragma warning disable CS1591
#pragma warning disable CA1819
@@ -111,7 +111,7 @@ namespace MediaBrowser.Model.Configuration
///
/// 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.
///
public bool EnableSSDPTracing { get; set; } = false;
@@ -131,13 +131,23 @@ namespace MediaBrowser.Model.Configuration
///
public int UDPSendDelay { get; set; } = 100;
+ ///
+ /// Gets or sets a value indicating whether address names that match should be Ignore for the purposes of binding.
+ ///
+ public bool IgnoreVirtualInterfaces { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating the interfaces that should be ignored. The list can be comma separated. .
+ ///
+ public string VirtualInterfaceNames { get; set; } = "vEthernet*";
+
///
/// Gets or sets the time (in seconds) between the pings of SSDP gateway monitor.
///
public int GatewayMonitorPeriod { get; set; } = 60;
///
- /// Gets a value indicating whether is multi-socket binding available.
+ /// Gets a value indicating whether multi-socket binding is available.
///
public bool EnableMultiSocketBinding { get; } = true;
@@ -158,7 +168,7 @@ namespace MediaBrowser.Model.Configuration
public string[] PublishedServerUriBySubnet { get; set; } = Array.Empty();
///
- /// Gets or sets a value indicating whether gets or sets Autodiscovery tracing.
+ /// Gets or sets a value indicating whether Autodiscovery tracing is enabled.
///
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.
///
public bool QuickConnectAvailable { get; set; } = false;
-
- public bool AutoRunWebApp { get; set; } = true;
-
+
///
/// Gets or sets a value indicating whether access outside of the LAN is permitted.
///
@@ -419,6 +427,5 @@ namespace MediaBrowser.Model.Configuration
/// Gets or sets the known proxies.
///
public string[] KnownProxies { get; set; } = Array.Empty();
-
}
}