aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs11
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs2
-rw-r--r--Jellyfin.Networking/Manager/NetworkManager.cs30
-rw-r--r--MediaBrowser.Controller/IServerApplicationHost.cs5
-rw-r--r--tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs2
-rw-r--r--tests/Jellyfin.Networking.Tests/NetworkParseTests.cs50
9 files changed, 63 insertions, 43 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 3a504d2f4..c244e7cfa 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -1186,14 +1186,13 @@ namespace Emby.Server.Implementations
}
/// <inheritdoc/>
- public string GetLoopbackHttpApiUrl()
+ public string GetUrlForUseByHttpApi()
{
- if (NetManager.IsIP6Enabled)
- {
- return GetLocalApiUrl("::1", Uri.UriSchemeHttp, HttpPort);
- }
+ // GetBindInterfaces will return an interface.
+ var bind = NetManager.GetInternalBindAddresses().FirstOrDefault() ??
+ NetManager.GetAllBindInterfaces(true).First();
- return GetLocalApiUrl("127.0.0.1", Uri.UriSchemeHttp, HttpPort);
+ return GetLocalApiUrl(bind.Address.ToString(), Uri.UriSchemeHttp);
}
/// <inheritdoc/>
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 026b6bc0b..0205ed9e5 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -1027,7 +1027,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var stream = new MediaSourceInfo
{
- EncoderPath = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveRecordings/" + info.Id + "/stream",
+ EncoderPath = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveRecordings/" + info.Id + "/stream",
EncoderProtocol = MediaProtocol.Http,
Path = info.Path,
Protocol = MediaProtocol.File,
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index ecd28097d..1af9396d7 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -104,7 +104,7 @@ namespace Emby.Server.Implementations.LiveTv
// Dummy this up so that direct play checks can still run
if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http)
{
- source.Path = _appHost.GetSmartApiUrl(string.Empty);
+ source.Path = _appHost.GetUrlForUseByHttpApi();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index 58e0c7448..a8a8ac729 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -146,7 +146,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
// OpenedMediaSource.Path = tempFile;
// OpenedMediaSource.ReadAtNativeFramerate = true;
- MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
+ MediaSource.Path = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
MediaSource.Protocol = MediaProtocol.Http;
// OpenedMediaSource.SupportsDirectPlay = false;
// OpenedMediaSource.SupportsDirectStream = true;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
index f572151b8..b3e554139 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
@@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
// OpenedMediaSource.Path = tempFile;
// OpenedMediaSource.ReadAtNativeFramerate = true;
- MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
+ MediaSource.Path = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
MediaSource.Protocol = MediaProtocol.Http;
// OpenedMediaSource.Path = TempFilePath;
diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs
index 4078fd126..b654535e6 100644
--- a/Jellyfin.Networking/Manager/NetworkManager.cs
+++ b/Jellyfin.Networking/Manager/NetworkManager.cs
@@ -455,10 +455,10 @@ namespace Jellyfin.Networking.Manager
}
// No bind address, so return all internal interfaces.
- return CreateCollection(_internalInterfaces.Where(p => !p.IsLoopback()));
+ return CreateCollection(_internalInterfaces);
}
- return new Collection<IPObject>(_bindAddresses);
+ return new Collection<IPObject>(_bindAddresses.Where(IsInLocalNetwork).ToArray());
}
/// <inheritdoc/>
@@ -481,7 +481,7 @@ namespace Jellyfin.Networking.Manager
}
// As private addresses can be redefined by Configuration.LocalNetworkAddresses
- return _lanSubnets.ContainsAddress(address) && !_excludedSubnets.ContainsAddress(address);
+ return address.IsLoopback() || (_lanSubnets.ContainsAddress(address) && !_excludedSubnets.ContainsAddress(address));
}
/// <inheritdoc/>
@@ -647,16 +647,6 @@ namespace Jellyfin.Networking.Manager
_interfaceAddresses.AddItem(address, false);
_interfaceNames[parts[2]] = Math.Abs(index);
}
-
- if (IsIP4Enabled)
- {
- _interfaceAddresses.AddItem(IPNetAddress.IP4Loopback);
- }
-
- if (IsIP6Enabled)
- {
- _interfaceAddresses.AddItem(IPNetAddress.IP6Loopback);
- }
}
InitialiseLAN(config);
@@ -1037,17 +1027,14 @@ namespace Jellyfin.Networking.Manager
// Subnets are the same as the calculated internal interface.
_lanSubnets = new Collection<IPObject>();
- // We must listen on loopback for LiveTV to function regardless of the settings.
if (IsIP6Enabled)
{
- _lanSubnets.AddItem(IPNetAddress.IP6Loopback);
_lanSubnets.AddItem(IPNetAddress.Parse("fc00::/7")); // ULA
_lanSubnets.AddItem(IPNetAddress.Parse("fe80::/10")); // Site local
}
if (IsIP4Enabled)
{
- _lanSubnets.AddItem(IPNetAddress.IP4Loopback);
_lanSubnets.AddItem(IPNetAddress.Parse("10.0.0.0/8"));
_lanSubnets.AddItem(IPNetAddress.Parse("172.16.0.0/12"));
_lanSubnets.AddItem(IPNetAddress.Parse("192.168.0.0/16"));
@@ -1055,17 +1042,6 @@ namespace Jellyfin.Networking.Manager
}
else
{
- // We must listen on loopback for LiveTV to function regardless of the settings.
- if (IsIP6Enabled)
- {
- _lanSubnets.AddItem(IPNetAddress.IP6Loopback);
- }
-
- if (IsIP4Enabled)
- {
- _lanSubnets.AddItem(IPNetAddress.IP4Loopback);
- }
-
// Internal interfaces must be private, not excluded and part of the LocalNetworkSubnet.
_internalInterfaces = CreateCollection(_interfaceAddresses.Where(IsInLocalNetwork));
}
diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs
index b0abca367..52a7ff204 100644
--- a/MediaBrowser.Controller/IServerApplicationHost.cs
+++ b/MediaBrowser.Controller/IServerApplicationHost.cs
@@ -82,11 +82,10 @@ namespace MediaBrowser.Controller
string GetSmartApiUrl(string hostname, int? port = null);
/// <summary>
- /// Gets a localhost URL that can be used to access the API using the loop-back IP address.
- /// over HTTP (not HTTPS).
+ /// Gets an URL that can be used to access the API over HTTP (not HTTPS).
/// </summary>
/// <returns>The API URL.</returns>
- string GetLoopbackHttpApiUrl();
+ string GetUrlForUseByHttpApi();
/// <summary>
/// Gets a local (LAN) URL that can be used to access the API.
diff --git a/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs b/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs
index 1cad625b7..61f913252 100644
--- a/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs
+++ b/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs
@@ -34,7 +34,7 @@ namespace Jellyfin.Networking.Tests
}
/// <summary>
- /// Checks that thge given IP address is not in the network provided.
+ /// Checks that the given IP address is not in the network provided.
/// </summary>
/// <param name="network">Network address(es).</param>
/// <param name="value">The IP to check.</param>
diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
index 97c14d463..170f0279f 100644
--- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
+++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
@@ -35,9 +35,9 @@ namespace Jellyfin.Networking.Tests
// eth16 only
[InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.208/24]")]
// All interfaces excluded. (including loopbacks)
- [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[127.0.0.1/8,::1/128]")]
+ [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[]")]
// vEthernet1 and vEthernet212 should be excluded.
- [InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24,127.0.0.1/8,::1/128]")]
+ [InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24]")]
// Overlapping interface,
[InlineData("192.168.1.110/24,-20,br0|192.168.1.10/24,-16,br0|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.110/24,192.168.1.10/24]")]
public void IgnoreVirtualInterfaces(string interfaces, string lan, string value)
@@ -476,5 +476,51 @@ namespace Jellyfin.Networking.Tests
Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIp)), denied);
}
+
+ [Theory]
+ [InlineData("192.168.1.209/24,-16,eth16", "192.168.1.0/24", "", "192.168.1.209")] // Only 1 address so use it.
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "192.168.1.208")] // LAN address is specified by default.
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "10.0.0.1")] // return bind address
+
+ public void Get_Appropriate_Interface_NoSource(string interfaces, string lan, string bind, string result)
+ {
+ var conf = new NetworkConfiguration()
+ {
+ EnableIPV4 = true,
+ LocalNetworkSubnets = lan.Split(','),
+ LocalNetworkAddresses = bind.Split(',')
+ };
+
+ NetworkManager.MockNetworkSettings = interfaces;
+ using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
+
+ var interfaceToUse = nm.GetBindInterface(string.Empty, out _);
+
+ Assert.Equal(result, interfaceToUse);
+ }
+
+ [Theory]
+ [InlineData("192.168.1.209/24,-16,eth16", "192.168.1.0/24", "", "192.168.1.210", "192.168.1.209")] // Source on LAN
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "192.168.1.209", "192.168.1.208")] // Source on LAN
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "8.8.8.8", "10.0.0.1")] // Source external.
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "192.168.1.209", "10.0.0.1")] // LAN not bound, so return external.
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "8.8.8.8", "10.0.0.1")] // return external bind address
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "192.168.1.210", "192.168.1.208")] // return LAN bind address
+ public void Get_Appropriate_Interface_ForSource(string interfaces, string lan, string bind, string source, string result)
+ {
+ var conf = new NetworkConfiguration()
+ {
+ EnableIPV4 = true,
+ LocalNetworkSubnets = lan.Split(','),
+ LocalNetworkAddresses = bind.Split(',')
+ };
+
+ NetworkManager.MockNetworkSettings = interfaces;
+ using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
+
+ var interfaceToUse = nm.GetBindInterface(source, out _);
+
+ Assert.Equal(result, interfaceToUse);
+ }
}
}