Sky High 2 weeks ago committed by GitHub
commit e900683f27
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -878,7 +878,14 @@ namespace Emby.Server.Implementations
return GetLocalApiUrl(request.Host.Host, request.Scheme, requestPort);
}
return GetSmartApiUrl(request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback);
// Gets the server URL that can also be used by applications not on the server, for instance
// a cast receiver device. In case the request has a localhost url, LocalAddress will be set to a
// server Private network address (IPv4) or Unique Local Address (ULA, IPv6) which is valid for all
// devices on the LAN.
IPAddress localAddress = request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback;
return NetworkConstants.IPv4RFC5735Loopback.Contains(localAddress) || NetworkConstants.IPv6RFC4291Loopback.Contains(localAddress)
? GetSmartApiUrl(NetworkManager.ServerLanAddress)
: GetSmartApiUrl(localAddress);
}
/// <inheritdoc/>

@ -132,6 +132,11 @@ public class NetworkManager : INetworkManager, IDisposable
/// </summary>
public bool TrustAllIPv6Interfaces { get; private set; }
/// <summary>
/// Gets the IP LAN address of Jellyfin server usable for a Google cast receiver and such.
/// </summary>
public static string ServerLanAddress { get; private set; } = string.Empty;
/// <summary>
/// Gets the Published server override list.
/// </summary>
@ -633,6 +638,8 @@ public class NetworkManager : INetworkManager, IDisposable
InitializeOverrides(config);
PrintNetworkInformation(config, false);
InitializeServerLanAddress(config);
}
/// <summary>
@ -1122,4 +1129,80 @@ public class NetworkManager : INetworkManager, IDisposable
_logger.Log(logLevel, "Filter list: {0}", _remoteAddressFilter.Select(s => s.Prefix + "/" + s.PrefixLength));
}
}
/// <summary>
/// Initializes the LAN IP address that the server advertises for cast receivers.
/// A LAN device like a Chromecast receiver needs an unique LAN address of the Jellyfin server.
/// For IPv4, a Private network address (like 192.168.0.0/16 )serves this purpose, and for IPv6
/// the Unique Local Address (ULA, fd00::/8) does. An IPv6 global address (2000::/3) also works
/// as unique server address but is ranked as less desirable than a local address.
/// See e.g. https://en.wikipedia.org/wiki/Private_network
///
/// If multiple addresses are available:
/// - prefer Unique Local Addresses (ULA) or Site Local Addresses over other (global) addresses.
/// - all things equal, prefer IPv4 over IPv6 as the former in practice appears to be more stable.
/// </summary>
private void InitializeServerLanAddress(NetworkConfiguration config)
{
lock (_initLock)
{
int rank = 0; // ranks most preferable ip address
IPAddress ipSrv = IPAddress.None;
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (var adapter in adapters)
{
if (adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback)
{
continue;
}
// check if the network interface serves as IPv4 gateway
bool haveIP4GateWay = false;
foreach (var address in adapter.GetIPProperties().GatewayAddresses)
{
haveIP4GateWay = haveIP4GateWay || address.Address.AddressFamily == AddressFamily.InterNetwork;
}
// if the network interface is used as gateway, and has an acceptable IP address for this server,
// then this address is assumed to be accessible by other devices on the LAN.
foreach (var inf in _interfaces)
{
IPAddress ip = inf.Address;
if (!inf.Name.Equals(adapter.Name, StringComparison.OrdinalIgnoreCase) ||
ip.Equals(IPAddress.Loopback) || ip.Equals(IPAddress.IPv6Loopback))
{
continue;
}
if (ip.AddressFamily == AddressFamily.InterNetworkV6)
{
if (IsIPv6Enabled)
{
if (rank < 2 && (ip.IsIPv6SiteLocal || ip.IsIPv6UniqueLocal))
{
rank = 2;
ipSrv = ip;
}
else if (rank < 1)
{
rank = 1;
ipSrv = ip;
}
}
}
else if (haveIP4GateWay && IsIPv4Enabled && rank < 3)
{
rank = 3;
ipSrv = ip;
}
}
ServerLanAddress = ipSrv.ToString();
}
}
_logger.LogInformation("ServerLanAddress: {0} ", ServerLanAddress);
}
}

Loading…
Cancel
Save