Standardize bind IPs in ssdp and dlnahost (#82)

This commit is contained in:
disgustipated 2024-10-26 14:00:16 -04:00 committed by GitHub
parent 6907e25a18
commit b89cee0af3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 37 deletions

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
@ -245,8 +246,12 @@ public sealed class DlnaHost : IHostedService, IDisposable
// Only get bind addresses in LAN // Only get bind addresses in LAN
// IPv6 is currently unsupported // IPv6 is currently unsupported
var validInterfaces = _networkManager.GetInternalBindAddresses() var validInterfaces = _networkManager.GetInternalBindAddresses()
.Where(x => x.Address is not null)
.Where(x => x.AddressFamily != AddressFamily.InterNetworkV6) .Where(x => x.AddressFamily != AddressFamily.InterNetworkV6)
.Where(x => x.AddressFamily == AddressFamily.InterNetwork)
.Where(x => x.SupportsMulticast)
.Where(x => !x.Address.Equals(IPAddress.Loopback))
.ToList(); .ToList();
var httpBindPort = _appHost.HttpPort; var httpBindPort = _appHost.HttpPort;

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -233,6 +234,19 @@ namespace Rssdp.Infrastructure
} }
} }
public IEnumerable<IPData> GetBindIPs()
{
var iplist = _networkManager.GetInternalBindAddresses()
.Where(x => x.Address is not null)
.Where(x => x.AddressFamily != AddressFamily.InterNetworkV6)
.Where(x => x.AddressFamily == AddressFamily.InterNetwork)
.Where(x => x.SupportsMulticast)
.Where(x => !x.Address.Equals(IPAddress.Loopback))
.ToList();
return iplist;
}
public Task SendMulticastMessage(string message, IPAddress fromlocalIPAddress, CancellationToken cancellationToken) public Task SendMulticastMessage(string message, IPAddress fromlocalIPAddress, CancellationToken cancellationToken)
{ {
return SendMulticastMessage(message, SsdpConstants.UdpResendCount, fromlocalIPAddress, cancellationToken); return SendMulticastMessage(message, SsdpConstants.UdpResendCount, fromlocalIPAddress, cancellationToken);
@ -343,24 +357,19 @@ namespace Rssdp.Infrastructure
var sockets = new List<Socket>(); var sockets = new List<Socket>();
var multicastGroupAddress = IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress); var multicastGroupAddress = IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress);
// IPv6 is currently unsupported var validInterfaces = GetBindIPs();
var validInterfaces = _networkManager.GetInternalBindAddresses()
.Where(x => x.Address is not null)
.Where(x => x.SupportsMulticast)
.Where(x => x.AddressFamily == AddressFamily.InterNetwork)
.DistinctBy(x => x.Index);
foreach (var intf in validInterfaces) foreach (var intf in validInterfaces)
{ {
try try
{ {
var socket = CreateUdpMulticastSocket(multicastGroupAddress, intf, _MulticastTtl, SsdpConstants.MulticastPort); var socket = CreateUdpMulticastSocket(multicastGroupAddress, intf, _MulticastTtl, SsdpConstants.MulticastPort);
_ = ListenToSocketInternal(socket); _ = ListenToSocketInternal(socket, intf);
sockets.Add(socket); sockets.Add(socket);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Failed to create SSDP UDP multicast socket for {0} on interface {1} (index {2})", intf.Address, intf.Name, intf.Index); _logger.LogError(ex, "Failed to create SSDP UDP multicast socket for {0} on interface {1} (index {2})", intf, intf.Name, intf.Index);
} }
} }
@ -370,37 +379,26 @@ namespace Rssdp.Infrastructure
private List<Socket> CreateSendSockets() private List<Socket> CreateSendSockets()
{ {
var sockets = new List<Socket>(); var sockets = new List<Socket>();
var validInterfaces = GetBindIPs();
// IPv6 is currently unsupported
var validInterfaces = _networkManager.GetInternalBindAddresses()
.Where(x => x.Address is not null)
.Where(x => x.SupportsMulticast)
.Where(x => x.AddressFamily == AddressFamily.InterNetwork);
if (OperatingSystem.IsMacOS())
{
// Manually remove loopback on macOS due to https://github.com/dotnet/runtime/issues/24340
validInterfaces = validInterfaces.Where(x => !x.Address.Equals(IPAddress.Loopback));
}
foreach (var intf in validInterfaces) foreach (var intf in validInterfaces)
{ {
try try
{ {
var socket = CreateSsdpUdpSocket(intf, _LocalPort); var socket = CreateSsdpUdpSocket(intf, _LocalPort);
_ = ListenToSocketInternal(socket); _ = ListenToSocketInternal(socket, intf);
sockets.Add(socket); sockets.Add(socket);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Failed to create SSDP UDP sender socket for {0} on interface {1} (index {2})", intf.Address, intf.Name, intf.Index); _logger.LogError(ex, "Failed to create SSDP UDP sender socket for {0} on interface {1} (index {2})", intf, intf.Name, intf.Index);
} }
} }
return sockets; return sockets;
} }
private async Task ListenToSocketInternal(Socket socket) private async Task ListenToSocketInternal(Socket socket, IPData listenIP)
{ {
var cancelled = false; var cancelled = false;
var receiveBuffer = new byte[8192]; var receiveBuffer = new byte[8192];
@ -414,23 +412,11 @@ namespace Rssdp.Infrastructure
if (result.ReceivedBytes > 0) if (result.ReceivedBytes > 0)
{ {
var remoteEndpoint = (IPEndPoint)result.RemoteEndPoint; var remoteEndpoint = (IPEndPoint)result.RemoteEndPoint;
var allBindInterfaces = _networkManager.GetAllBindInterfaces();
IPData localEndpointAdapter;
if (allBindInterfaces.Count == 1
&& (allBindInterfaces[0].Address.Equals(IPAddress.Any)
|| allBindInterfaces[0].Address.Equals(IPAddress.IPv6Any)))
{
localEndpointAdapter = allBindInterfaces[0];
}
else
{
localEndpointAdapter = allBindInterfaces.First(a => a.Index == result.PacketInformation.Interface);
}
ProcessMessage( ProcessMessage(
Encoding.UTF8.GetString(receiveBuffer, 0, result.ReceivedBytes), Encoding.UTF8.GetString(receiveBuffer, 0, result.ReceivedBytes),
remoteEndpoint, remoteEndpoint,
localEndpointAdapter.Address); listenIP.Address);
} }
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)