fix: bind auto-discovery to multicast ip on macOS (#11368)

pull/11378/head
gnattu 4 weeks ago committed by GitHub
parent 658a454d81
commit 80fac82c2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -11,6 +11,7 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Model.ApiClient; using MediaBrowser.Model.ApiClient;
using MediaBrowser.Model.Net;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -50,6 +51,25 @@ public sealed class AutoDiscoveryHost : BackgroundService
_networkManager = networkManager; _networkManager = networkManager;
} }
private static IPAddress GetBindAddress(IPData intf)
{
if (intf.AddressFamily == AddressFamily.InterNetwork)
{
if (OperatingSystem.IsLinux())
{
return NetworkUtils.GetBroadcastAddress(intf.Subnet);
}
if (OperatingSystem.IsMacOS())
{
// macOS kernel does not allow bind to 127:255:255:255
return IPAddress.IsLoopback(intf.Address) ? intf.Address : NetworkUtils.GetBroadcastAddress(intf.Subnet);
}
}
return intf.Address;
}
/// <inheritdoc /> /// <inheritdoc />
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
@ -63,24 +83,23 @@ public sealed class AutoDiscoveryHost : BackgroundService
// Linux needs to bind to the broadcast addresses to receive broadcast traffic // Linux needs to bind to the broadcast addresses to receive broadcast traffic
if (OperatingSystem.IsLinux() && networkConfig.EnableIPv4) if (OperatingSystem.IsLinux() && networkConfig.EnableIPv4)
{ {
udpServers.Add(ListenForAutoDiscoveryMessage(IPAddress.Broadcast, stoppingToken)); udpServers.Add(ListenForAutoDiscoveryMessage(IPAddress.Broadcast, IPAddress.Broadcast, stoppingToken));
} }
udpServers.AddRange(_networkManager.GetInternalBindAddresses() udpServers.AddRange(_networkManager.GetInternalBindAddresses()
.Select(intf => ListenForAutoDiscoveryMessage( .Select(intf => ListenForAutoDiscoveryMessage(
OperatingSystem.IsLinux() && intf.AddressFamily == AddressFamily.InterNetwork GetBindAddress(intf),
? NetworkUtils.GetBroadcastAddress(intf.Subnet) intf.Address,
: intf.Address,
stoppingToken))); stoppingToken)));
await Task.WhenAll(udpServers).ConfigureAwait(false); await Task.WhenAll(udpServers).ConfigureAwait(false);
} }
private async Task ListenForAutoDiscoveryMessage(IPAddress address, CancellationToken cancellationToken) private async Task ListenForAutoDiscoveryMessage(IPAddress listenAddress, IPAddress respondAddress, CancellationToken cancellationToken)
{ {
try try
{ {
using var udpClient = new UdpClient(new IPEndPoint(address, PortNumber)); using var udpClient = new UdpClient(new IPEndPoint(listenAddress, PortNumber));
udpClient.MulticastLoopback = false; udpClient.MulticastLoopback = false;
while (!cancellationToken.IsCancellationRequested) while (!cancellationToken.IsCancellationRequested)
@ -91,7 +110,7 @@ public sealed class AutoDiscoveryHost : BackgroundService
var text = Encoding.UTF8.GetString(result.Buffer); var text = Encoding.UTF8.GetString(result.Buffer);
if (text.Contains("who is JellyfinServer?", StringComparison.OrdinalIgnoreCase)) if (text.Contains("who is JellyfinServer?", StringComparison.OrdinalIgnoreCase))
{ {
await RespondToV2Message(udpClient, result.RemoteEndPoint, cancellationToken).ConfigureAwait(false); await RespondToV2Message(respondAddress, result.RemoteEndPoint, cancellationToken).ConfigureAwait(false);
} }
} }
catch (SocketException ex) catch (SocketException ex)
@ -107,11 +126,11 @@ public sealed class AutoDiscoveryHost : BackgroundService
catch (Exception ex) catch (Exception ex)
{ {
// Exception in this function will prevent the background service from restarting in-process. // Exception in this function will prevent the background service from restarting in-process.
_logger.LogError(ex, "Unable to bind to {Address}:{Port}", address, PortNumber); _logger.LogError(ex, "Unable to bind to {Address}:{Port}", listenAddress, PortNumber);
} }
} }
private async Task RespondToV2Message(UdpClient udpClient, IPEndPoint endpoint, CancellationToken cancellationToken) private async Task RespondToV2Message(IPAddress responderIp, IPEndPoint endpoint, CancellationToken cancellationToken)
{ {
var localUrl = _appHost.GetSmartApiUrl(endpoint.Address); var localUrl = _appHost.GetSmartApiUrl(endpoint.Address);
if (string.IsNullOrEmpty(localUrl)) if (string.IsNullOrEmpty(localUrl))
@ -122,10 +141,11 @@ public sealed class AutoDiscoveryHost : BackgroundService
var response = new ServerDiscoveryInfo(localUrl, _appHost.SystemId, _appHost.FriendlyName); var response = new ServerDiscoveryInfo(localUrl, _appHost.SystemId, _appHost.FriendlyName);
using var responder = new UdpClient(new IPEndPoint(responderIp, PortNumber));
try try
{ {
_logger.LogDebug("Sending AutoDiscovery response"); _logger.LogDebug("Sending AutoDiscovery response");
await udpClient await responder
.SendAsync(JsonSerializer.SerializeToUtf8Bytes(response).AsMemory(), endpoint, cancellationToken) .SendAsync(JsonSerializer.SerializeToUtf8Bytes(response).AsMemory(), endpoint, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
} }

Loading…
Cancel
Save