Fix autodiscovery

This commit is contained in:
Shadowghost 2022-10-15 17:27:37 +02:00
parent 4aec41752f
commit 87d0158a4a
3 changed files with 67 additions and 33 deletions

View File

@ -79,6 +79,10 @@ namespace Emby.Server.Implementations.EntryPoints
{ {
if (_enableMultiSocketBinding) if (_enableMultiSocketBinding)
{ {
// Add global broadcast socket
_udpServers.Add(new UdpServer(_logger, _appHost, _config, System.Net.IPAddress.Broadcast, PortNumber));
// Add bind address specific broadcast sockets
foreach (var bindAddress in _networkManager.GetInternalBindAddresses()) foreach (var bindAddress in _networkManager.GetInternalBindAddresses())
{ {
if (bindAddress.AddressFamily == AddressFamily.InterNetworkV6) if (bindAddress.AddressFamily == AddressFamily.InterNetworkV6)
@ -87,7 +91,10 @@ namespace Emby.Server.Implementations.EntryPoints
continue; continue;
} }
_udpServers.Add(new UdpServer(_logger, _appHost, _config, bindAddress.Address, PortNumber)); var broadcastAddress = NetworkExtensions.GetBroadcastAddress(bindAddress.Subnet);
_logger.LogDebug("Binding UDP server to {Address}", broadcastAddress.ToString());
_udpServers.Add(new UdpServer(_logger, _appHost, _config, broadcastAddress, PortNumber));
} }
} }
else else

View File

@ -280,7 +280,7 @@ namespace Jellyfin.Networking.Manager
} }
_logger.LogDebug("Discovered {0} interfaces.", _interfaces.Count); _logger.LogDebug("Discovered {0} interfaces.", _interfaces.Count);
_logger.LogDebug("Interfaces addresses : {0}", _interfaces.Select(s => s.Address).ToString()); _logger.LogDebug("Interfaces addresses : {0}", _interfaces.Select(s => s.Address.ToString()));
} }
} }
@ -726,20 +726,11 @@ namespace Jellyfin.Networking.Manager
} }
bool isExternal = !_lanSubnets.Any(network => network.Contains(source)); bool isExternal = !_lanSubnets.Any(network => network.Contains(source));
_logger.LogDebug("GetBindInterface with source. External: {IsExternal}:", isExternal); _logger.LogDebug("GetBindInterface with source {Source}. External: {IsExternal}:", source, isExternal);
if (MatchesPublishedServerUrl(source, isExternal, out string res, out port)) if (MatchesPublishedServerUrl(source, isExternal, out result))
{ {
if (port != null) return result;
{
_logger.LogInformation("{Source}: Using BindAddress {Address}:{Port}", source, res, port);
}
else
{
_logger.LogInformation("{Source}: Using BindAddress {Address}", source, res);
}
return res;
} }
// No preference given, so move on to bind addresses. // No preference given, so move on to bind addresses.
@ -868,41 +859,37 @@ namespace Jellyfin.Networking.Manager
/// <param name="source">IP source address to use.</param> /// <param name="source">IP source address to use.</param>
/// <param name="isInExternalSubnet">True if the source is in an external subnet.</param> /// <param name="isInExternalSubnet">True if the source is in an 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>
/// <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(IPAddress source, bool isInExternalSubnet, out string bindPreference, out int? port) private bool MatchesPublishedServerUrl(IPAddress source, bool isInExternalSubnet, out string bindPreference)
{ {
bindPreference = string.Empty; bindPreference = string.Empty;
port = null; int? port = null;
var validPublishedServerUrls = _publishedServerUrls.Where(x => x.Key.Address.Equals(IPAddress.Any) var validPublishedServerUrls = _publishedServerUrls.Where(x => x.Key.Address.Equals(IPAddress.Any)
|| x.Key.Address.Equals(IPAddress.IPv6Any) || x.Key.Address.Equals(IPAddress.IPv6Any)
|| x.Key.Subnet.Contains(source)) || x.Key.Subnet.Contains(source))
.GroupBy(x => x.Key) .GroupBy(x => x.Key)
.Select(y => y.First()) .Select(x => x.First())
.OrderBy(x => x.Key.Address.Equals(IPAddress.Any)
|| x.Key.Address.Equals(IPAddress.IPv6Any))
.ToList(); .ToList();
// Check for user override. // Check for user override.
foreach (var data in validPublishedServerUrls) foreach (var data in validPublishedServerUrls)
{ {
// Get address interface // Get address interface.
var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(s => s.Subnet.Contains(data.Key.Address)); var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(x => data.Key.Subnet.Contains(x.Address));
// Remaining. Match anything. if (isInExternalSubnet && (data.Key.Address.Equals(IPAddress.Any) || data.Key.Address.Equals(IPAddress.IPv6Any)))
if (data.Key.Address.Equals(IPAddress.Broadcast))
{
bindPreference = data.Value;
break;
}
else if ((data.Key.Address.Equals(IPAddress.Any) || data.Key.Address.Equals(IPAddress.IPv6Any)) && isInExternalSubnet)
{ {
// External. // External.
bindPreference = data.Value; bindPreference = data.Value;
break; break;
} }
else if (intf?.Address != null)
if (intf?.Address != null)
{ {
// Match ip address. // Match IP address.
bindPreference = data.Value; bindPreference = data.Value;
break; break;
} }
@ -910,6 +897,7 @@ namespace Jellyfin.Networking.Manager
if (string.IsNullOrEmpty(bindPreference)) if (string.IsNullOrEmpty(bindPreference))
{ {
_logger.LogInformation("{Source}: No matching bind address override found", source);
return false; return false;
} }
@ -924,6 +912,15 @@ namespace Jellyfin.Networking.Manager
} }
} }
if (port != null)
{
_logger.LogInformation("{Source}: Matching bind address override found {Address}:{Port}", source, bindPreference, port);
}
else
{
_logger.LogInformation("{Source}: Matching bind address override found {Address}", source, bindPreference);
}
return true; return true;
} }
@ -967,12 +964,12 @@ namespace Jellyfin.Networking.Manager
if (bindAddress != null) if (bindAddress != null)
{ {
result = NetworkExtensions.FormatIpString(bindAddress); result = NetworkExtensions.FormatIpString(bindAddress);
_logger.LogDebug("{Source}: GetBindInterface: Has source, found a matching external bind interface: {Result}", source, result); _logger.LogDebug("{Source}: External request received, matching external bind interface found: {Result}", source, result);
return true; return true;
} }
} }
_logger.LogWarning("{Source}: External request received, no external interface bind found, trying internal interfaces.", source); _logger.LogWarning("{Source}: External request received, no matching external bind interface found, trying internal interfaces.", source);
} }
else else
{ {
@ -987,7 +984,7 @@ namespace Jellyfin.Networking.Manager
if (bindAddress != null) if (bindAddress != null)
{ {
result = NetworkExtensions.FormatIpString(bindAddress); result = NetworkExtensions.FormatIpString(bindAddress);
_logger.LogWarning("{Source}: Request received, matching internal interface bind found: {Result}", source, result); _logger.LogDebug("{Source}: Internal request received, matching internal bind interface found: {Result}", source, result);
return true; return true;
} }
} }

View File

@ -56,7 +56,23 @@ namespace MediaBrowser.Common.Net
/// <returns>String value of the subnet mask in dotted decimal notation.</returns> /// <returns>String value of the subnet mask in dotted decimal notation.</returns>
public static IPAddress CidrToMask(byte cidr, AddressFamily family) public static IPAddress CidrToMask(byte cidr, AddressFamily family)
{ {
uint addr = 0xFFFFFFFF << (family == AddressFamily.InterNetwork ? 32 : 128 - cidr); uint addr = 0xFFFFFFFF << ((family == AddressFamily.InterNetwork ? 32 : 128) - cidr);
addr = ((addr & 0xff000000) >> 24)
| ((addr & 0x00ff0000) >> 8)
| ((addr & 0x0000ff00) << 8)
| ((addr & 0x000000ff) << 24);
return new IPAddress(addr);
}
/// <summary>
/// Convert a subnet mask in CIDR notation to a dotted decimal string value. IPv4 only.
/// </summary>
/// <param name="cidr">Subnet mask in CIDR notation.</param>
/// <param name="family">IPv4 or IPv6 family.</param>
/// <returns>String value of the subnet mask in dotted decimal notation.</returns>
public static IPAddress CidrToMask(int cidr, AddressFamily family)
{
uint addr = 0xFFFFFFFF << ((family == AddressFamily.InterNetwork ? 32 : 128) - cidr);
addr = ((addr & 0xff000000) >> 24) addr = ((addr & 0xff000000) >> 24)
| ((addr & 0x00ff0000) >> 8) | ((addr & 0x00ff0000) >> 8)
| ((addr & 0x0000ff00) << 8) | ((addr & 0x0000ff00) << 8)
@ -319,5 +335,19 @@ namespace MediaBrowser.Common.Net
addresses = Array.Empty<IPAddress>(); addresses = Array.Empty<IPAddress>();
return false; return false;
} }
/// <summary>
/// Gets the broadcast address for a <see cref="IPNetwork"/>.
/// </summary>
/// <param name="network">The <see cref="IPNetwork"/>.</param>
/// <returns>The broadcast address.</returns>
public static IPAddress GetBroadcastAddress(IPNetwork network)
{
uint ipAddress = BitConverter.ToUInt32(network.Prefix.GetAddressBytes(), 0);
uint ipMaskV4 = BitConverter.ToUInt32(CidrToMask(network.PrefixLength, AddressFamily.InterNetwork).GetAddressBytes(), 0);
uint broadCastIpAddress = ipAddress | ~ipMaskV4;
return new IPAddress(BitConverter.GetBytes(broadCastIpAddress));
}
} }
} }