@ -15,7 +15,9 @@ 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.AspNetCore.HttpOverrides ;
using Microsoft.Extensions.Configuration ;
using Microsoft.Extensions.Logging ;
using Microsoft.Extensions.Logging ;
using static MediaBrowser . Controller . Extensions . ConfigurationExtensions ;
namespace Jellyfin.Networking.Manager
namespace Jellyfin.Networking.Manager
{
{
@ -33,12 +35,14 @@ namespace Jellyfin.Networking.Manager
private readonly IConfigurationManager _configurationManager ;
private readonly IConfigurationManager _configurationManager ;
private readonly IConfiguration _startupConfig ;
private readonly object _networkEventLock ;
private readonly object _networkEventLock ;
/// <summary>
/// <summary>
/// Holds the published server URLs and the IPs to use them on.
/// Holds the published server URLs and the IPs to use them on.
/// </summary>
/// </summary>
private IReadOnly Dictionary< IPData , string > _publishedServerUrls ;
private IReadOnly List< PublishedServerUriOverride > _publishedServerUrls ;
private IReadOnlyList < IPNetwork > _remoteAddressFilter ;
private IReadOnlyList < IPNetwork > _remoteAddressFilter ;
@ -76,20 +80,22 @@ namespace Jellyfin.Networking.Manager
/// <summary>
/// <summary>
/// Initializes a new instance of the <see cref="NetworkManager"/> class.
/// Initializes a new instance of the <see cref="NetworkManager"/> class.
/// </summary>
/// </summary>
/// <param name="configurationManager">IServerConfigurationManager instance.</param>
/// <param name="configurationManager">The <see cref="IConfigurationManager"/> instance.</param>
/// <param name="startupConfig">The <see cref="IConfiguration"/> instance holding startup parameters.</param>
/// <param name="logger">Logger to use for messages.</param>
/// <param name="logger">Logger to use for messages.</param>
#pragma warning disable CS8618 // Non-nullable field is uninitialized. : Values are set in UpdateSettings function. Compiler doesn't yet recognise this.
#pragma warning disable CS8618 // Non-nullable field is uninitialized. : Values are set in UpdateSettings function. Compiler doesn't yet recognise this.
public NetworkManager ( IConfigurationManager configurationManager , I Logger< NetworkManager > logger )
public NetworkManager ( IConfigurationManager configurationManager , I Configuration startupConfig , I Logger< NetworkManager > logger )
{
{
ArgumentNullException . ThrowIfNull ( logger ) ;
ArgumentNullException . ThrowIfNull ( logger ) ;
ArgumentNullException . ThrowIfNull ( configurationManager ) ;
ArgumentNullException . ThrowIfNull ( configurationManager ) ;
_logger = logger ;
_logger = logger ;
_configurationManager = configurationManager ;
_configurationManager = configurationManager ;
_startupConfig = startupConfig ;
_initLock = new ( ) ;
_initLock = new ( ) ;
_interfaces = new List < IPData > ( ) ;
_interfaces = new List < IPData > ( ) ;
_macAddresses = new List < PhysicalAddress > ( ) ;
_macAddresses = new List < PhysicalAddress > ( ) ;
_publishedServerUrls = new Dictionary< IPData , string > ( ) ;
_publishedServerUrls = new List< PublishedServerUriOverride > ( ) ;
_networkEventLock = new object ( ) ;
_networkEventLock = new object ( ) ;
_remoteAddressFilter = new List < IPNetwork > ( ) ;
_remoteAddressFilter = new List < IPNetwork > ( ) ;
@ -130,7 +136,7 @@ namespace Jellyfin.Networking.Manager
/// <summary>
/// <summary>
/// Gets the Published server override list.
/// Gets the Published server override list.
/// </summary>
/// </summary>
public IReadOnly Dictionary< IPData , string > PublishedServerUrls = > _publishedServerUrls ;
public IReadOnly List< PublishedServerUriOverride > PublishedServerUrls = > _publishedServerUrls ;
/// <inheritdoc/>
/// <inheritdoc/>
public void Dispose ( )
public void Dispose ( )
@ -170,7 +176,6 @@ namespace Jellyfin.Networking.Manager
{
{
if ( ! _eventfire )
if ( ! _eventfire )
{
{
_logger . LogDebug ( "Network Address Change Event." ) ;
// As network events tend to fire one after the other only fire once every second.
// As network events tend to fire one after the other only fire once every second.
_eventfire = true ;
_eventfire = true ;
OnNetworkChange ( ) ;
OnNetworkChange ( ) ;
@ -193,11 +198,12 @@ namespace Jellyfin.Networking.Manager
}
}
else
else
{
{
Initiali s eInterfaces( ) ;
Initiali z eInterfaces( ) ;
Initiali s eLan( networkConfig ) ;
Initiali z eLan( networkConfig ) ;
EnforceBindSettings ( networkConfig ) ;
EnforceBindSettings ( networkConfig ) ;
}
}
PrintNetworkInformation ( networkConfig ) ;
NetworkChanged ? . Invoke ( this , EventArgs . Empty ) ;
NetworkChanged ? . Invoke ( this , EventArgs . Empty ) ;
}
}
finally
finally
@ -210,7 +216,7 @@ namespace Jellyfin.Networking.Manager
/// Generate a list of all the interface ip addresses and submasks where that are in the active/unknown state.
/// Generate a list of all the interface ip addresses and submasks where that are in the active/unknown state.
/// Generate a list of all active mac addresses that aren't loopback addresses.
/// Generate a list of all active mac addresses that aren't loopback addresses.
/// </summary>
/// </summary>
private void Initiali s eInterfaces( )
private void Initiali z eInterfaces( )
{
{
lock ( _initLock )
lock ( _initLock )
{
{
@ -222,7 +228,7 @@ namespace Jellyfin.Networking.Manager
try
try
{
{
var nics = NetworkInterface . GetAllNetworkInterfaces ( )
var nics = NetworkInterface . GetAllNetworkInterfaces ( )
. Where ( i = > i . SupportsMulticast & & i . OperationalStatus = = OperationalStatus . Up ) ;
. Where ( i = > i . OperationalStatus = = OperationalStatus . Up ) ;
foreach ( NetworkInterface adapter in nics )
foreach ( NetworkInterface adapter in nics )
{
{
@ -242,34 +248,36 @@ namespace Jellyfin.Networking.Manager
{
{
if ( IsIPv4Enabled & & info . Address . AddressFamily = = AddressFamily . InterNetwork )
if ( IsIPv4Enabled & & info . Address . AddressFamily = = AddressFamily . InterNetwork )
{
{
var interfaceObject = new IPData ( info . Address , new IPNetwork ( info . Address , info . PrefixLength ) , adapter . Name ) ;
var interfaceObject = new IPData ( info . Address , new IPNetwork ( info . Address , info . PrefixLength ) , adapter . Name )
interfaceObject . Index = ipProperties . GetIPv4Properties ( ) . Index ;
{
interfaceObject . Name = adapter . Name ;
Index = ipProperties . GetIPv4Properties ( ) . Index ,
Name = adapter . Name ,
SupportsMulticast = adapter . SupportsMulticast
} ;
interfaces . Add ( interfaceObject ) ;
interfaces . Add ( interfaceObject ) ;
}
}
else if ( IsIPv6Enabled & & info . Address . AddressFamily = = AddressFamily . InterNetworkV6 )
else if ( IsIPv6Enabled & & info . Address . AddressFamily = = AddressFamily . InterNetworkV6 )
{
{
var interfaceObject = new IPData ( info . Address , new IPNetwork ( info . Address , info . PrefixLength ) , adapter . Name ) ;
var interfaceObject = new IPData ( info . Address , new IPNetwork ( info . Address , info . PrefixLength ) , adapter . Name )
interfaceObject . Index = ipProperties . GetIPv6Properties ( ) . Index ;
{
interfaceObject . Name = adapter . Name ;
Index = ipProperties . GetIPv6Properties ( ) . Index ,
Name = adapter . Name ,
SupportsMulticast = adapter . SupportsMulticast
} ;
interfaces . Add ( interfaceObject ) ;
interfaces . Add ( interfaceObject ) ;
}
}
}
}
}
}
#pragma warning disable CA1031 // Do not catch general exception types
catch ( Exception ex )
catch ( Exception ex )
#pragma warning restore CA1031 // Do not catch general exception types
{
{
// Ignore error, and attempt to continue.
// Ignore error, and attempt to continue.
_logger . LogError ( ex , "Error encountered parsing interfaces." ) ;
_logger . LogError ( ex , "Error encountered parsing interfaces." ) ;
}
}
}
}
}
}
#pragma warning disable CA1031 // Do not catch general exception types
catch ( Exception ex )
catch ( Exception ex )
#pragma warning restore CA1031 // Do not catch general exception types
{
{
_logger . LogError ( ex , "Error obtaining interfaces." ) ;
_logger . LogError ( ex , "Error obtaining interfaces." ) ;
}
}
@ -279,14 +287,14 @@ namespace Jellyfin.Networking.Manager
{
{
_logger . LogWarning ( "No interface information available. Using loopback interface(s)." ) ;
_logger . LogWarning ( "No interface information available. Using loopback interface(s)." ) ;
if ( IsIPv4Enabled & & ! IsIPv6Enabled )
if ( IsIPv4Enabled )
{
{
interfaces . Add ( new IPData ( IPAddress . Loopback , new IPNetwork ( IPAddress . Loopback , 8 ) , "lo" ) ) ;
interfaces . Add ( new IPData ( IPAddress . Loopback , Network . IPv4RFC5735Loopback , "lo" ) ) ;
}
}
if ( ! IsIPv4Enabled & & IsIPv6Enabled )
if ( IsIPv6Enabled )
{
{
interfaces . Add ( new IPData ( IPAddress . IPv6Loopback , new IP Network(IPAddress .IPv6 Loopback, 128 ) , "lo" ) ) ;
interfaces . Add ( new IPData ( IPAddress . IPv6Loopback , Network .IPv6 RFC4291 Loopback, "lo" ) ) ;
}
}
}
}
@ -299,9 +307,9 @@ namespace Jellyfin.Networking.Manager
}
}
/// <summary>
/// <summary>
/// Initiali s es internal LAN cache.
/// Initiali z es internal LAN cache.
/// </summary>
/// </summary>
private void Initiali s eLan( NetworkConfiguration config )
private void Initiali z eLan( NetworkConfiguration config )
{
{
lock ( _initLock )
lock ( _initLock )
{
{
@ -341,10 +349,6 @@ namespace Jellyfin.Networking.Manager
_excludedSubnets = NetworkExtensions . TryParseToSubnets ( subnets , out var excludedSubnets , true )
_excludedSubnets = NetworkExtensions . TryParseToSubnets ( subnets , out var excludedSubnets , true )
? excludedSubnets
? excludedSubnets
: new List < IPNetwork > ( ) ;
: new List < IPNetwork > ( ) ;
_logger . LogInformation ( "Defined LAN addresses: {0}" , _lanSubnets . Select ( s = > s . Prefix + "/" + s . PrefixLength ) ) ;
_logger . LogInformation ( "Defined LAN exclusions: {0}" , _excludedSubnets . Select ( s = > s . Prefix + "/" + s . PrefixLength ) ) ;
_logger . LogInformation ( "Using LAN addresses: {0}" , _lanSubnets . Where ( s = > ! _excludedSubnets . Contains ( s ) ) . Select ( s = > s . Prefix + "/" + s . PrefixLength ) ) ;
}
}
}
}
@ -369,12 +373,12 @@ namespace Jellyfin.Networking.Manager
. ToHashSet ( ) ;
. ToHashSet ( ) ;
interfaces = interfaces . Where ( x = > bindAddresses . Contains ( x . Address ) ) . ToList ( ) ;
interfaces = interfaces . Where ( x = > bindAddresses . Contains ( x . Address ) ) . ToList ( ) ;
if ( bindAddresses . Contains ( IPAddress . Loopback ) )
if ( bindAddresses . Contains ( IPAddress . Loopback ) & & ! interfaces . Any ( i = > i . Address . Equals ( IPAddress . Loopback ) ) )
{
{
interfaces . Add ( new IPData ( IPAddress . Loopback , Network . IPv4RFC5735Loopback , "lo" ) ) ;
interfaces . Add ( new IPData ( IPAddress . Loopback , Network . IPv4RFC5735Loopback , "lo" ) ) ;
}
}
if ( bindAddresses . Contains ( IPAddress . IPv6Loopback ) )
if ( bindAddresses . Contains ( IPAddress . IPv6Loopback ) & & ! interfaces . Any ( i = > i . Address . Equals ( IPAddress . IPv6Loopback ) ) )
{
{
interfaces . Add ( new IPData ( IPAddress . IPv6Loopback , Network . IPv6RFC4291Loopback , "lo" ) ) ;
interfaces . Add ( new IPData ( IPAddress . IPv6Loopback , Network . IPv6RFC4291Loopback , "lo" ) ) ;
}
}
@ -409,15 +413,14 @@ namespace Jellyfin.Networking.Manager
interfaces . RemoveAll ( x = > x . AddressFamily = = AddressFamily . InterNetworkV6 ) ;
interfaces . RemoveAll ( x = > x . AddressFamily = = AddressFamily . InterNetworkV6 ) ;
}
}
_logger . LogInformation ( "Using bind addresses: {0}" , interfaces . OrderByDescending ( x = > x . AddressFamily = = AddressFamily . InterNetwork ) . Select ( x = > x . Address ) ) ;
_interfaces = interfaces ;
_interfaces = interfaces ;
}
}
}
}
/// <summary>
/// <summary>
/// Initiali s es the remote address values.
/// Initiali z es the remote address values.
/// </summary>
/// </summary>
private void Initiali s eRemote( NetworkConfiguration config )
private void Initiali z eRemote( NetworkConfiguration config )
{
{
lock ( _initLock )
lock ( _initLock )
{
{
@ -455,13 +458,33 @@ namespace Jellyfin.Networking.Manager
/// format is subnet=ipaddress|host|uri
/// format is subnet=ipaddress|host|uri
/// when subnet = 0.0.0.0, any external address matches.
/// when subnet = 0.0.0.0, any external address matches.
/// </summary>
/// </summary>
private void Initiali s eOverrides( NetworkConfiguration config )
private void Initiali z eOverrides( NetworkConfiguration config )
{
{
lock ( _initLock )
lock ( _initLock )
{
{
var publishedServerUrls = new Dictionary < IPData , string > ( ) ;
var publishedServerUrls = new List < PublishedServerUriOverride > ( ) ;
var overrides = config . PublishedServerUriBySubnet ;
// Prefer startup configuration.
var startupOverrideKey = _startupConfig [ AddressOverrideKey ] ;
if ( ! string . IsNullOrEmpty ( startupOverrideKey ) )
{
publishedServerUrls . Add (
new PublishedServerUriOverride (
new IPData ( IPAddress . Any , Network . IPv4Any ) ,
startupOverrideKey ,
true ,
true ) ) ;
publishedServerUrls . Add (
new PublishedServerUriOverride (
new IPData ( IPAddress . IPv6Any , Network . IPv6Any ) ,
startupOverrideKey ,
true ,
true ) ) ;
_publishedServerUrls = publishedServerUrls ;
return ;
}
var overrides = config . PublishedServerUriBySubnet ;
foreach ( var entry in overrides )
foreach ( var entry in overrides )
{
{
var parts = entry . Split ( '=' ) ;
var parts = entry . Split ( '=' ) ;
@ -475,31 +498,70 @@ namespace Jellyfin.Networking.Manager
var identifier = parts [ 0 ] ;
var identifier = parts [ 0 ] ;
if ( string . Equals ( identifier , "all" , StringComparison . OrdinalIgnoreCase ) )
if ( string . Equals ( identifier , "all" , StringComparison . OrdinalIgnoreCase ) )
{
{
publishedServerUrls [ new IPData ( IPAddress . Broadcast , null ) ] = replacement ;
// Drop any other overrides in case an "all" override exists
publishedServerUrls . Clear ( ) ;
publishedServerUrls . Add (
new PublishedServerUriOverride (
new IPData ( IPAddress . Any , Network . IPv4Any ) ,
replacement ,
true ,
true ) ) ;
publishedServerUrls . Add (
new PublishedServerUriOverride (
new IPData ( IPAddress . IPv6Any , Network . IPv6Any ) ,
replacement ,
true ,
true ) ) ;
break ;
}
}
else if ( string . Equals ( identifier , "external" , StringComparison . OrdinalIgnoreCase ) )
else if ( string . Equals ( identifier , "external" , StringComparison . OrdinalIgnoreCase ) )
{
{
publishedServerUrls [ new IPData ( IPAddress . Any , Network . IPv4Any ) ] = replacement ;
publishedServerUrls . Add (
publishedServerUrls [ new IPData ( IPAddress . IPv6Any , Network . IPv6Any ) ] = replacement ;
new PublishedServerUriOverride (
new IPData ( IPAddress . Any , Network . IPv4Any ) ,
replacement ,
false ,
true ) ) ;
publishedServerUrls . Add (
new PublishedServerUriOverride (
new IPData ( IPAddress . IPv6Any , Network . IPv6Any ) ,
replacement ,
false ,
true ) ) ;
}
}
else if ( string . Equals ( identifier , "internal" , StringComparison . OrdinalIgnoreCase ) )
else if ( string . Equals ( identifier , "internal" , StringComparison . OrdinalIgnoreCase ) )
{
{
foreach ( var lan in _lanSubnets )
foreach ( var lan in _lanSubnets )
{
{
var lanPrefix = lan . Prefix ;
var lanPrefix = lan . Prefix ;
publishedServerUrls [ new IPData ( lanPrefix , new IPNetwork ( lanPrefix , lan . PrefixLength ) ) ] = replacement ;
publishedServerUrls . Add (
new PublishedServerUriOverride (
new IPData ( lanPrefix , new IPNetwork ( lanPrefix , lan . PrefixLength ) ) ,
replacement ,
true ,
false ) ) ;
}
}
}
}
else if ( NetworkExtensions . TryParseToSubnet ( identifier , out var result ) & & result is not null )
else if ( NetworkExtensions . TryParseToSubnet ( identifier , out var result ) & & result is not null )
{
{
var data = new IPData ( result . Prefix , result ) ;
var data = new IPData ( result . Prefix , result ) ;
publishedServerUrls [ data ] = replacement ;
publishedServerUrls . Add (
new PublishedServerUriOverride (
data ,
replacement ,
true ,
true ) ) ;
}
}
else if ( TryParseInterface ( identifier , out var ifaces ) )
else if ( TryParseInterface ( identifier , out var ifaces ) )
{
{
foreach ( var iface in ifaces )
foreach ( var iface in ifaces )
{
{
publishedServerUrls [ iface ] = replacement ;
publishedServerUrls . Add (
new PublishedServerUriOverride (
iface ,
replacement ,
true ,
true ) ) ;
}
}
}
}
else
else
@ -521,7 +583,7 @@ namespace Jellyfin.Networking.Manager
}
}
/// <summary>
/// <summary>
/// Reloads all settings and re- initialis es the instance.
/// Reloads all settings and re- Initializ es 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 ( object configuration )
public void UpdateSettings ( object configuration )
@ -531,12 +593,12 @@ namespace Jellyfin.Networking.Manager
var config = ( NetworkConfiguration ) configuration ;
var config = ( NetworkConfiguration ) configuration ;
HappyEyeballs . HttpClientExtension . UseIPv6 = config . EnableIPv6 ;
HappyEyeballs . HttpClientExtension . UseIPv6 = config . EnableIPv6 ;
Initiali s eLan( config ) ;
Initiali z eLan( config ) ;
Initiali s eRemote( config ) ;
Initiali z eRemote( config ) ;
if ( string . IsNullOrEmpty ( MockNetworkSettings ) )
if ( string . IsNullOrEmpty ( MockNetworkSettings ) )
{
{
Initiali s eInterfaces( ) ;
Initiali z eInterfaces( ) ;
}
}
else // Used in testing only.
else // Used in testing only.
{
{
@ -552,8 +614,10 @@ namespace Jellyfin.Networking.Manager
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 , parts [ 2 ] ) ;
var data = new IPData ( address , subnet , parts [ 2 ] )
data . Index = index ;
{
Index = index
} ;
interfaces . Add ( data ) ;
interfaces . Add ( data ) ;
}
}
}
}
@ -567,7 +631,9 @@ namespace Jellyfin.Networking.Manager
}
}
EnforceBindSettings ( config ) ;
EnforceBindSettings ( config ) ;
InitialiseOverrides ( config ) ;
InitializeOverrides ( config ) ;
PrintNetworkInformation ( config , false ) ;
}
}
/// <summary>
/// <summary>
@ -672,20 +738,13 @@ namespace Jellyfin.Networking.Manager
/// <inheritdoc/>
/// <inheritdoc/>
public IReadOnlyList < IPData > GetAllBindInterfaces ( bool individualInterfaces = false )
public IReadOnlyList < IPData > GetAllBindInterfaces ( bool individualInterfaces = false )
{
{
if ( _interfaces . Count != 0 )
if ( _interfaces . Count > 0 | | individualInterfaces )
{
{
return _interfaces ;
return _interfaces ;
}
}
// No bind address and no exclusions, so listen on all interfaces.
// No bind address and no exclusions, so listen on all interfaces.
var result = new List < IPData > ( ) ;
var result = new List < IPData > ( ) ;
if ( individualInterfaces )
{
result . AddRange ( _interfaces ) ;
return result ;
}
if ( IsIPv4Enabled & & IsIPv6Enabled )
if ( IsIPv4Enabled & & IsIPv6Enabled )
{
{
// Kestrel source code shows it uses Sockets.DualMode - so this also covers IPAddress.Any by default
// Kestrel source code shows it uses Sockets.DualMode - so this also covers IPAddress.Any by default
@ -892,31 +951,34 @@ namespace Jellyfin.Networking.Manager
bindPreference = string . Empty ;
bindPreference = string . Empty ;
int? port = null ;
int? port = null ;
var validPublishedServerUrls = _publishedServerUrls . Where ( x = > x . Key . Address . Equals ( IPAddress . Any )
// Only consider subnets including the source IP, prefering specific overrides
| | x . Key . Address . Equals ( IPAddress . IPv6Any )
List < PublishedServerUriOverride > validPublishedServerUrls ;
| | x . Key . Subnet . Contains ( source ) )
if ( ! isInExternalSubnet )
. DistinctBy ( x = > x . Key )
{
. OrderBy ( x = > x . Key . Address . Equals ( IPAddress . Any )
// Only use matching internal subnets
| | x . Key . Address . Equals ( IPAddress . IPv6Any ) )
// Prefer more specific (bigger subnet prefix) overrides
validPublishedServerUrls = _publishedServerUrls . Where ( x = > x . IsInternalOverride & & x . Data . Subnet . Contains ( source ) )
. OrderByDescending ( x = > x . Data . Subnet . PrefixLength )
. ToList ( ) ;
}
else
{
// Only use matching external subnets
// Prefer more specific (bigger subnet prefix) overrides
validPublishedServerUrls = _publishedServerUrls . Where ( x = > x . IsExternalOverride & & x . Data . Subnet . Contains ( source ) )
. OrderByDescending ( x = > x . Data . Subnet . PrefixLength )
. ToList ( ) ;
. ToList ( ) ;
}
// Check for user override.
foreach ( var data in validPublishedServerUrls )
foreach ( var data in validPublishedServerUrls )
{
{
if ( isInExternalSubnet & & ( data . Key . Address . Equals ( IPAddress . Any ) | | data . Key . Address . Equals ( IPAddress . IPv6Any ) ) )
// Get interface matching override subnet
{
var intf = _interfaces . OrderBy ( x = > x . Index ) . FirstOrDefault ( x = > data . Data . Subnet . Contains ( x . Address ) ) ;
// External.
bindPreference = data . Value ;
break ;
}
// Get address interface.
var intf = _interfaces . OrderBy ( x = > x . Index ) . FirstOrDefault ( x = > data . Key . Subnet . Contains ( x . Address ) ) ;
if ( intf ? . Address is not null )
if ( intf ? . Address is not null )
{
{
// Match IP address.
// If matching interface is found, use override
bindPreference = data . Value ;
bindPreference = data . OverrideUri ;
break ;
break ;
}
}
}
}
@ -927,7 +989,7 @@ namespace Jellyfin.Networking.Manager
return false ;
return false ;
}
}
// Ha s it got a port defined?
// Ha ndle override specifying port
var parts = bindPreference . Split ( ':' ) ;
var parts = bindPreference . Split ( ':' ) ;
if ( parts . Length > 1 )
if ( parts . Length > 1 )
{
{
@ -935,18 +997,12 @@ namespace Jellyfin.Networking.Manager
{
{
bindPreference = parts [ 0 ] ;
bindPreference = parts [ 0 ] ;
port = p ;
port = p ;
_logger . LogDebug ( "{Source}: Matching bind address override found: {Address}:{Port}" , source , bindPreference , port ) ;
return true ;
}
}
}
}
if ( port is not null )
_logger . LogDebug ( "{Source}: Matching bind address override found: {Address}" , source , bindPreference ) ;
{
_logger . LogDebug ( "{Source}: Matching bind address override found: {Address}:{Port}" , source , bindPreference , port ) ;
}
else
{
_logger . LogDebug ( "{Source}: Matching bind address override found: {Address}" , source , bindPreference ) ;
}
return true ;
return true ;
}
}
@ -1053,5 +1109,19 @@ namespace Jellyfin.Networking.Manager
_logger . LogDebug ( "{Source}: Using first external interface as bind address: {Result}" , source , result ) ;
_logger . LogDebug ( "{Source}: Using first external interface as bind address: {Result}" , source , result ) ;
return true ;
return true ;
}
}
private void PrintNetworkInformation ( NetworkConfiguration config , bool debug = true )
{
var logLevel = debug ? LogLevel . Debug : LogLevel . Information ;
if ( _logger . IsEnabled ( logLevel ) )
{
_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 . Prefix + "/" + 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 , "Remote IP filter is {0}" , config . IsRemoteIPFilterBlacklist ? "Blocklist" : "Allowlist" ) ;
_logger . Log ( logLevel , "Filter list: {0}" , _remoteAddressFilter . Select ( s = > s . Prefix + "/" + s . PrefixLength ) ) ;
}
}
}
}
}
}