mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-04-18 19:25:00 -04:00
Remove the ability to auto port forward (#13222)
This commit is contained in:
parent
cc284afb47
commit
b318f33599
9 changed files with 7 additions and 200 deletions
|
@ -49,7 +49,6 @@
|
||||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.1" />
|
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.1" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
<PackageVersion Include="MimeTypes" Version="2.5.2" />
|
<PackageVersion Include="MimeTypes" Version="2.5.2" />
|
||||||
<PackageVersion Include="Mono.Nat" Version="3.0.4" />
|
|
||||||
<PackageVersion Include="Moq" Version="4.18.4" />
|
<PackageVersion Include="Moq" Version="4.18.4" />
|
||||||
<PackageVersion Include="NEbml" Version="0.11.0" />
|
<PackageVersion Include="NEbml" Version="0.11.0" />
|
||||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
@ -88,4 +87,4 @@
|
||||||
<PackageVersion Include="Xunit.SkippableFact" Version="1.5.23" />
|
<PackageVersion Include="Xunit.SkippableFact" Version="1.5.23" />
|
||||||
<PackageVersion Include="xunit" Version="2.9.3" />
|
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -93,7 +93,6 @@ public class StartupController : BaseJellyfinApiController
|
||||||
{
|
{
|
||||||
NetworkConfiguration settings = _config.GetNetworkConfiguration();
|
NetworkConfiguration settings = _config.GetNetworkConfiguration();
|
||||||
settings.EnableRemoteAccess = startupRemoteAccessDto.EnableRemoteAccess;
|
settings.EnableRemoteAccess = startupRemoteAccessDto.EnableRemoteAccess;
|
||||||
settings.EnableUPnP = startupRemoteAccessDto.EnableAutomaticPortMapping;
|
|
||||||
_config.SaveConfiguration(NetworkConfigurationStore.StoreKey, settings);
|
_config.SaveConfiguration(NetworkConfigurationStore.StoreKey, settings);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Jellyfin.Api.Models.StartupDtos;
|
namespace Jellyfin.Api.Models.StartupDtos;
|
||||||
|
@ -17,5 +18,6 @@ public class StartupRemoteAccessDto
|
||||||
/// Gets or sets a value indicating whether enable automatic port mapping.
|
/// Gets or sets a value indicating whether enable automatic port mapping.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
[Required]
|
||||||
|
[Obsolete("No longer supported")]
|
||||||
public bool EnableAutomaticPortMapping { get; set; }
|
public bool EnableAutomaticPortMapping { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma warning disable CS0618 // obsolete
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
|
|
@ -129,7 +129,6 @@ namespace Jellyfin.Server
|
||||||
|
|
||||||
services.AddHostedService<RecordingsHost>();
|
services.AddHostedService<RecordingsHost>();
|
||||||
services.AddHostedService<AutoDiscoveryHost>();
|
services.AddHostedService<AutoDiscoveryHost>();
|
||||||
services.AddHostedService<PortForwardingHost>();
|
|
||||||
services.AddHostedService<NfoUserDataSaver>();
|
services.AddHostedService<NfoUserDataSaver>();
|
||||||
services.AddHostedService<LibraryChangedNotifier>();
|
services.AddHostedService<LibraryChangedNotifier>();
|
||||||
services.AddHostedService<UserDataChangeNotifier>();
|
services.AddHostedService<UserDataChangeNotifier>();
|
||||||
|
|
|
@ -110,6 +110,7 @@ public class NetworkConfiguration
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether to enable automatic port forwarding.
|
/// Gets or sets a value indicating whether to enable automatic port forwarding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("No longer supported")]
|
||||||
public bool EnableUPnP { get; set; }
|
public bool EnableUPnP { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -12,6 +12,6 @@
|
||||||
"**/jellyfin-web": true,
|
"**/jellyfin-web": true,
|
||||||
"**/obj": true
|
"**/obj": true
|
||||||
},
|
},
|
||||||
"formatFiles.excludePattern": "**/node_modules,**/.vscode,**/dist/**,**/.chrome,ThirdParty,RSSDP,Mono.Nat,unRaid,debian"
|
"formatFiles.excludePattern": "**/node_modules,**/.vscode,**/dist/**,**/.chrome,ThirdParty,unRaid,debian"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,4 @@
|
||||||
<ProjectReference Include="..\..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
<ProjectReference Include="..\..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Mono.Nat" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Controller;
|
|
||||||
using MediaBrowser.Controller.Configuration;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Mono.Nat;
|
|
||||||
|
|
||||||
namespace Jellyfin.Networking;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="IHostedService"/> responsible for UPnP port forwarding.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class PortForwardingHost : IHostedService, IDisposable
|
|
||||||
{
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
|
||||||
private readonly ILogger<PortForwardingHost> _logger;
|
|
||||||
private readonly IServerConfigurationManager _config;
|
|
||||||
private readonly ConcurrentDictionary<IPEndPoint, byte> _createdRules = new();
|
|
||||||
|
|
||||||
private Timer? _timer;
|
|
||||||
private string? _configIdentifier;
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="PortForwardingHost"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="logger">The logger.</param>
|
|
||||||
/// <param name="appHost">The application host.</param>
|
|
||||||
/// <param name="config">The configuration manager.</param>
|
|
||||||
public PortForwardingHost(
|
|
||||||
ILogger<PortForwardingHost> logger,
|
|
||||||
IServerApplicationHost appHost,
|
|
||||||
IServerConfigurationManager config)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
_appHost = appHost;
|
|
||||||
_config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetConfigIdentifier()
|
|
||||||
{
|
|
||||||
const char Separator = '|';
|
|
||||||
var config = _config.GetNetworkConfiguration();
|
|
||||||
|
|
||||||
return new StringBuilder(32)
|
|
||||||
.Append(config.EnableUPnP).Append(Separator)
|
|
||||||
.Append(config.PublicHttpPort).Append(Separator)
|
|
||||||
.Append(config.PublicHttpsPort).Append(Separator)
|
|
||||||
.Append(_appHost.HttpPort).Append(Separator)
|
|
||||||
.Append(_appHost.HttpsPort).Append(Separator)
|
|
||||||
.Append(_appHost.ListenWithHttps).Append(Separator)
|
|
||||||
.Append(config.EnableRemoteAccess).Append(Separator)
|
|
||||||
.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnConfigurationUpdated(object? sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var oldConfigIdentifier = _configIdentifier;
|
|
||||||
_configIdentifier = GetConfigIdentifier();
|
|
||||||
|
|
||||||
if (!string.Equals(_configIdentifier, oldConfigIdentifier, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Start();
|
|
||||||
|
|
||||||
_config.ConfigurationUpdated += OnConfigurationUpdated;
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Start()
|
|
||||||
{
|
|
||||||
var config = _config.GetNetworkConfiguration();
|
|
||||||
if (!config.EnableUPnP || !config.EnableRemoteAccess)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("Starting NAT discovery");
|
|
||||||
|
|
||||||
NatUtility.DeviceFound += OnNatUtilityDeviceFound;
|
|
||||||
NatUtility.StartDiscovery();
|
|
||||||
|
|
||||||
_timer?.Dispose();
|
|
||||||
_timer = new Timer(_ => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Stop()
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Stopping NAT discovery");
|
|
||||||
|
|
||||||
NatUtility.StopDiscovery();
|
|
||||||
NatUtility.DeviceFound -= OnNatUtilityDeviceFound;
|
|
||||||
|
|
||||||
_timer?.Dispose();
|
|
||||||
_timer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnNatUtilityDeviceFound(object? sender, DeviceEventArgs e)
|
|
||||||
{
|
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// On some systems the device discovered event seems to fire repeatedly
|
|
||||||
// This check will help ensure we're not trying to port map the same device over and over
|
|
||||||
if (!_createdRules.TryAdd(e.Device.DeviceEndpoint, 0))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.WhenAll(CreatePortMaps(e.Device)).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error creating port forwarding rules");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<Task> CreatePortMaps(INatDevice device)
|
|
||||||
{
|
|
||||||
var config = _config.GetNetworkConfiguration();
|
|
||||||
yield return CreatePortMap(device, _appHost.HttpPort, config.PublicHttpPort);
|
|
||||||
|
|
||||||
if (_appHost.ListenWithHttps)
|
|
||||||
{
|
|
||||||
yield return CreatePortMap(device, _appHost.HttpsPort, config.PublicHttpsPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task CreatePortMap(INatDevice device, int privatePort, int publicPort)
|
|
||||||
{
|
|
||||||
_logger.LogDebug(
|
|
||||||
"Creating port map on local port {LocalPort} to public port {PublicPort} with device {DeviceEndpoint}",
|
|
||||||
privatePort,
|
|
||||||
publicPort,
|
|
||||||
device.DeviceEndpoint);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var mapping = new Mapping(Protocol.Tcp, privatePort, publicPort, 0, _appHost.Name);
|
|
||||||
await device.CreatePortMapAsync(mapping).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(
|
|
||||||
ex,
|
|
||||||
"Error creating port map on local port {LocalPort} to public port {PublicPort} with device {DeviceEndpoint}.",
|
|
||||||
privatePort,
|
|
||||||
publicPort,
|
|
||||||
device.DeviceEndpoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_config.ConfigurationUpdated -= OnConfigurationUpdated;
|
|
||||||
|
|
||||||
_timer?.Dispose();
|
|
||||||
_timer = null;
|
|
||||||
|
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue