Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardize bind IPs in ssdp and dlnahost #82

Merged
merged 7 commits into from
Oct 26, 2024
7 changes: 6 additions & 1 deletion src/Jellyfin.Plugin.Dlna/Main/DlnaHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Threading;
Expand Down Expand Up @@ -243,8 +244,12 @@ private void RegisterServerEndpoints()

// Only get bind addresses in LAN
// 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.InterNetwork)
.Where(x => x.SupportsMulticast)
.Where(x => !x.Address.Equals(IPAddress.Loopback))
.ToList();

var httpBindPort = _appHost.HttpPort;
Expand Down
58 changes: 22 additions & 36 deletions src/Rssdp/SsdpCommunicationsServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
Expand Down Expand Up @@ -233,6 +234,19 @@ private List<Socket> GetSendSockets(IPAddress fromlocalIPAddress, IPEndPoint des
}
}

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)
{
return SendMulticastMessage(message, SsdpConstants.UdpResendCount, fromlocalIPAddress, cancellationToken);
Expand Down Expand Up @@ -343,24 +357,19 @@ private List<Socket> CreateMulticastSocketsAndListen()
var sockets = new List<Socket>();
var multicastGroupAddress = IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress);

// 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)
.DistinctBy(x => x.Index);
var validInterfaces = GetBindIPs();

foreach (var intf in validInterfaces)
{
try
{
var socket = CreateUdpMulticastSocket(multicastGroupAddress, intf, _MulticastTtl, SsdpConstants.MulticastPort);
_ = ListenToSocketInternal(socket);
_ = ListenToSocketInternal(socket, intf);
sockets.Add(socket);
}
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);
}
}

Expand All @@ -370,37 +379,26 @@ private List<Socket> CreateMulticastSocketsAndListen()
private List<Socket> CreateSendSockets()
{
var sockets = new List<Socket>();

// 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));
}
var validInterfaces = GetBindIPs();

foreach (var intf in validInterfaces)
{
try
{
var socket = CreateSsdpUdpSocket(intf, _LocalPort);
_ = ListenToSocketInternal(socket);
_ = ListenToSocketInternal(socket, intf);
sockets.Add(socket);
}
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;
}

private async Task ListenToSocketInternal(Socket socket)
private async Task ListenToSocketInternal(Socket socket, IPData listenIP)
{
var cancelled = false;
var receiveBuffer = new byte[8192];
Expand All @@ -414,23 +412,11 @@ private async Task ListenToSocketInternal(Socket socket)
if (result.ReceivedBytes > 0)
{
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(
Encoding.UTF8.GetString(receiveBuffer, 0, result.ReceivedBytes),
remoteEndpoint,
localEndpointAdapter.Address);
listenIP.Address);
}
}
catch (ObjectDisposedException)
Expand Down
Loading