diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs
index 90c985a81..89119d31d 100644
--- a/Emby.Dlna/Main/DlnaEntryPoint.cs
+++ b/Emby.Dlna/Main/DlnaEntryPoint.cs
@@ -284,6 +284,7 @@ namespace Emby.Dlna.Main
var udn = CreateUuid(_appHost.SystemId);
var descriptorUri = "/dlna/" + udn + "/description.xml";
+ // Only get bind addresses in LAN
var bindAddresses = _networkManager
.GetInternalBindAddresses()
.Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork
@@ -304,12 +305,6 @@ namespace Emby.Dlna.Main
continue;
}
- // Limit to LAN addresses only
- if (!_networkManager.IsInLocalNetwork(address.Address))
- {
- continue;
- }
-
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
_logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address);
diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs
index 21795c8f8..a1baf3006 100644
--- a/Emby.Server.Implementations/Net/SocketFactory.cs
+++ b/Emby.Server.Implementations/Net/SocketFactory.cs
@@ -61,13 +61,18 @@ namespace Emby.Server.Implementations.Net
}
///
- public ISocket CreateUdpMulticastSocket(IPAddress ipAddress, int multicastTimeToLive, int localPort)
+ public ISocket CreateUdpMulticastSocket(IPAddress ipAddress, IPAddress bindIpAddress, int multicastTimeToLive, int localPort)
{
if (ipAddress == null)
{
throw new ArgumentNullException(nameof(ipAddress));
}
+ if (bindIpAddress == null)
+ {
+ bindIpAddress = IPAddress.Any;
+ }
+
if (multicastTimeToLive <= 0)
{
throw new ArgumentException("multicastTimeToLive cannot be zero or less.", nameof(multicastTimeToLive));
@@ -98,12 +103,10 @@ namespace Emby.Server.Implementations.Net
// retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive);
- var localIp = IPAddress.Any;
-
- retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ipAddress, localIp));
+ retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ipAddress, bindIpAddress));
retVal.MulticastLoopback = true;
- return new UdpSocket(retVal, localPort, localIp);
+ return new UdpSocket(retVal, localPort, bindIpAddress);
}
catch
{
diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs
index af2429cc2..b1112626c 100644
--- a/Jellyfin.Networking/Manager/NetworkManager.cs
+++ b/Jellyfin.Networking/Manager/NetworkManager.cs
@@ -298,20 +298,22 @@ namespace Jellyfin.Networking.Manager
if (_lanSubnets.Count == 0)
{
- // If no LAN addresses are specified, all private subnets are deemed to be the LAN
+ // If no LAN addresses are specified, all private subnets and Loopback are deemed to be the LAN
_logger.LogDebug("Using LAN interface addresses as user provided no LAN details.");
if (IsIpv6Enabled)
{
- _lanSubnets.Add(new IPNetwork(IPAddress.Parse("fc00::"), 7)); // ULA
- _lanSubnets.Add(new IPNetwork(IPAddress.Parse("fe80::"), 10)); // Site local
+ _lanSubnets.Add(new IPNetwork(IPAddress.IPv6Loopback, 128)); // RFC 4291 (Loopback)
+ _lanSubnets.Add(new IPNetwork(IPAddress.Parse("fe80::"), 10)); // RFC 4291 (Site local)
+ _lanSubnets.Add(new IPNetwork(IPAddress.Parse("fc00::"), 7)); // RFC 4193 (Unique local)
}
if (IsIpv4Enabled)
{
- _lanSubnets.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
- _lanSubnets.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12));
- _lanSubnets.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16));
+ _lanSubnets.Add(new IPNetwork(IPAddress.Loopback, 8)); // RFC 5735 (Loopback)
+ _lanSubnets.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8)); // RFC 1918 (private)
+ _lanSubnets.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12)); // RFC 1918 (private)
+ _lanSubnets.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16)); // RFC 1918 (private)
}
}
@@ -371,11 +373,13 @@ namespace Jellyfin.Networking.Manager
}
}
+ // Remove all IPv4 interfaces if IPv4 is disabled
if (!IsIpv4Enabled)
{
_interfaces.RemoveAll(x => x.AddressFamily == AddressFamily.InterNetwork);
}
+ // Remove all IPv6 interfaces if IPv6 is disabled
if (!IsIpv6Enabled)
{
_interfaces.RemoveAll(x => x.AddressFamily == AddressFamily.InterNetworkV6);
diff --git a/MediaBrowser.Model/Net/ISocketFactory.cs b/MediaBrowser.Model/Net/ISocketFactory.cs
index a2835b711..e5cf7adbc 100644
--- a/MediaBrowser.Model/Net/ISocketFactory.cs
+++ b/MediaBrowser.Model/Net/ISocketFactory.cs
@@ -1,5 +1,6 @@
#pragma warning disable CS1591
+using System.Collections.Generic;
using System.Net;
namespace MediaBrowser.Model.Net
@@ -23,9 +24,10 @@ namespace MediaBrowser.Model.Net
/// Creates a new multicast socket using the specified multicast IP address, multicast time to live and local port.
///
/// The multicast IP address to bind to.
+ /// The bind IP address.
/// The multicast time to live value. Actually a maximum number of network hops for UDP packets.
/// The local port to bind to.
/// A implementation.
- ISocket CreateUdpMulticastSocket(IPAddress ipAddress, int multicastTimeToLive, int localPort);
+ ISocket CreateUdpMulticastSocket(IPAddress ipAddress, IPAddress bindIpAddress, int multicastTimeToLive, int localPort);
}
}
diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs
index 53f872b60..e6c0a4403 100644
--- a/RSSDP/SsdpCommunicationsServer.cs
+++ b/RSSDP/SsdpCommunicationsServer.cs
@@ -33,7 +33,7 @@ namespace Rssdp.Infrastructure
*/
private object _BroadcastListenSocketSynchroniser = new object();
- private ISocket _BroadcastListenSocket;
+ private List _BroadcastListenSockets;
private object _SendSocketSynchroniser = new object();
private List _sendSockets;
@@ -111,24 +111,21 @@ namespace Rssdp.Infrastructure
{
ThrowIfDisposed();
- if (_BroadcastListenSocket == null)
+ lock (_BroadcastListenSocketSynchroniser)
{
- lock (_BroadcastListenSocketSynchroniser)
+ if (_BroadcastListenSockets == null)
{
- if (_BroadcastListenSocket == null)
+ try
{
- try
- {
- _BroadcastListenSocket = ListenForBroadcastsAsync();
- }
- catch (SocketException ex)
- {
- _logger.LogError("Failed to bind to port 1900: {Message}. DLNA will be unavailable", ex.Message);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error in BeginListeningForBroadcasts");
- }
+ _BroadcastListenSockets = ListenForBroadcastsAsync();
+ }
+ catch (SocketException ex)
+ {
+ _logger.LogError("Failed to bind to port 1900: {Message}. DLNA will be unavailable", ex.Message);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error in BeginListeningForBroadcasts");
}
}
}
@@ -142,11 +139,15 @@ namespace Rssdp.Infrastructure
{
lock (_BroadcastListenSocketSynchroniser)
{
- if (_BroadcastListenSocket != null)
+ if (_BroadcastListenSockets != null)
{
_logger.LogInformation("{0} disposing _BroadcastListenSocket", GetType().Name);
- _BroadcastListenSocket.Dispose();
- _BroadcastListenSocket = null;
+ foreach (var socket in _BroadcastListenSockets)
+ {
+ socket.Dispose();
+ }
+
+ _BroadcastListenSockets = null;
}
}
}
@@ -336,12 +337,40 @@ namespace Rssdp.Infrastructure
return Task.CompletedTask;
}
- private ISocket ListenForBroadcastsAsync()
+ private List ListenForBroadcastsAsync()
{
- var socket = _SocketFactory.CreateUdpMulticastSocket(IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress), _MulticastTtl, SsdpConstants.MulticastPort);
- _ = ListenToSocketInternal(socket);
+ var sockets = new List();
+ if (_enableMultiSocketBinding)
+ {
+ foreach (var address in _networkManager.GetInternalBindAddresses())
+ {
+ if (address.AddressFamily == AddressFamily.InterNetworkV6)
+ {
+ // Not support IPv6 right now
+ continue;
+ }
- return socket;
+ try
+ {
+ sockets.Add(_SocketFactory.CreateUdpMulticastSocket(IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress), address.Address, _MulticastTtl, SsdpConstants.MulticastPort));
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error in ListenForBroadcastsAsync. IPAddress: {0}", address);
+ }
+ }
+ }
+ else
+ {
+ sockets.Add(_SocketFactory.CreateUdpMulticastSocket(IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress), IPAddress.Any, _MulticastTtl, SsdpConstants.MulticastPort));
+ }
+
+ foreach (var socket in sockets)
+ {
+ _ = ListenToSocketInternal(socket);
+ }
+
+ return sockets;
}
private List CreateSocketAndListenForResponsesAsync()