diff options
Diffstat (limited to 'src/Jellyfin.Networking/ExternalPortForwarding.cs')
| -rw-r--r-- | src/Jellyfin.Networking/ExternalPortForwarding.cs | 269 |
1 files changed, 134 insertions, 135 deletions
diff --git a/src/Jellyfin.Networking/ExternalPortForwarding.cs b/src/Jellyfin.Networking/ExternalPortForwarding.cs index f90da7ae4..df9e43ca9 100644 --- a/src/Jellyfin.Networking/ExternalPortForwarding.cs +++ b/src/Jellyfin.Networking/ExternalPortForwarding.cs @@ -16,181 +16,180 @@ using MediaBrowser.Controller.Plugins; using Microsoft.Extensions.Logging; using Mono.Nat; -namespace Jellyfin.Networking +namespace Jellyfin.Networking; + +/// <summary> +/// Server entrypoint handling external port forwarding. +/// </summary> +public sealed class ExternalPortForwarding : IServerEntryPoint { + private readonly IServerApplicationHost _appHost; + private readonly ILogger<ExternalPortForwarding> _logger; + private readonly IServerConfigurationManager _config; + + private readonly ConcurrentDictionary<IPEndPoint, byte> _createdRules = new ConcurrentDictionary<IPEndPoint, byte>(); + + private Timer _timer; + private string _configIdentifier; + + private bool _disposed; + /// <summary> - /// Server entrypoint handling external port forwarding. + /// Initializes a new instance of the <see cref="ExternalPortForwarding"/> class. /// </summary> - public sealed class ExternalPortForwarding : IServerEntryPoint + /// <param name="logger">The logger.</param> + /// <param name="appHost">The application host.</param> + /// <param name="config">The configuration manager.</param> + public ExternalPortForwarding( + ILogger<ExternalPortForwarding> logger, + IServerApplicationHost appHost, + IServerConfigurationManager config) { - private readonly IServerApplicationHost _appHost; - private readonly ILogger<ExternalPortForwarding> _logger; - private readonly IServerConfigurationManager _config; - - private readonly ConcurrentDictionary<IPEndPoint, byte> _createdRules = new ConcurrentDictionary<IPEndPoint, byte>(); - - private Timer _timer; - private string _configIdentifier; - - private bool _disposed; - - /// <summary> - /// Initializes a new instance of the <see cref="ExternalPortForwarding"/> class. - /// </summary> - /// <param name="logger">The logger.</param> - /// <param name="appHost">The application host.</param> - /// <param name="config">The configuration manager.</param> - public ExternalPortForwarding( - ILogger<ExternalPortForwarding> logger, - IServerApplicationHost appHost, - IServerConfigurationManager config) - { - _logger = logger; - _appHost = appHost; - _config = 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 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(); - } - } + private void OnConfigurationUpdated(object sender, EventArgs e) + { + var oldConfigIdentifier = _configIdentifier; + _configIdentifier = GetConfigIdentifier(); - /// <inheritdoc /> - public Task RunAsync() + if (!string.Equals(_configIdentifier, oldConfigIdentifier, StringComparison.OrdinalIgnoreCase)) { + Stop(); Start(); + } + } - _config.ConfigurationUpdated += OnConfigurationUpdated; + /// <inheritdoc /> + public Task RunAsync() + { + Start(); - return Task.CompletedTask; - } + _config.ConfigurationUpdated += OnConfigurationUpdated; - private void Start() + return Task.CompletedTask; + } + + private void Start() + { + var config = _config.GetNetworkConfiguration(); + if (!config.EnableUPnP || !config.EnableRemoteAccess) { - var config = _config.GetNetworkConfiguration(); - if (!config.EnableUPnP || !config.EnableRemoteAccess) - { - return; - } + return; + } - _logger.LogInformation("Starting NAT discovery"); + _logger.LogInformation("Starting NAT discovery"); - NatUtility.DeviceFound += OnNatUtilityDeviceFound; - NatUtility.StartDiscovery(); + NatUtility.DeviceFound += OnNatUtilityDeviceFound; + NatUtility.StartDiscovery(); - _timer = new Timer((_) => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); - } + _timer = new Timer((_) => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); + } - private void Stop() - { - _logger.LogInformation("Stopping NAT discovery"); + private void Stop() + { + _logger.LogInformation("Stopping NAT discovery"); - NatUtility.StopDiscovery(); - NatUtility.DeviceFound -= OnNatUtilityDeviceFound; + NatUtility.StopDiscovery(); + NatUtility.DeviceFound -= OnNatUtilityDeviceFound; - _timer?.Dispose(); - } + _timer?.Dispose(); + } - private async void OnNatUtilityDeviceFound(object sender, DeviceEventArgs e) + private async void OnNatUtilityDeviceFound(object sender, DeviceEventArgs e) + { + try { - try - { - await CreateRules(e.Device).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error creating port forwarding rules"); - } + await CreateRules(e.Device).ConfigureAwait(false); } - - private Task CreateRules(INatDevice device) + catch (Exception ex) { - ObjectDisposedException.ThrowIf(_disposed, this); + _logger.LogError(ex, "Error creating port forwarding rules"); + } + } - // 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(device.DeviceEndpoint, 0)) - { - return Task.CompletedTask; - } + private Task CreateRules(INatDevice device) + { + ObjectDisposedException.ThrowIf(_disposed, this); - return Task.WhenAll(CreatePortMaps(device)); + // 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(device.DeviceEndpoint, 0)) + { + return Task.CompletedTask; } - private IEnumerable<Task> CreatePortMaps(INatDevice device) - { - var config = _config.GetNetworkConfiguration(); - yield return CreatePortMap(device, _appHost.HttpPort, config.PublicHttpPort); + return Task.WhenAll(CreatePortMaps(device)); + } - if (_appHost.ListenWithHttps) - { - yield return CreatePortMap(device, _appHost.HttpsPort, config.PublicHttpsPort); - } + 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) + 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.LogDebug( - "Creating port map on local port {LocalPort} to public port {PublicPort} with device {DeviceEndpoint}", + _logger.LogError( + ex, + "Error 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() + /// <inheritdoc /> + public void Dispose() + { + if (_disposed) { - if (_disposed) - { - return; - } + return; + } - _config.ConfigurationUpdated -= OnConfigurationUpdated; + _config.ConfigurationUpdated -= OnConfigurationUpdated; - Stop(); + Stop(); - _timer?.Dispose(); - _timer = null; + _timer?.Dispose(); + _timer = null; - _disposed = true; - } + _disposed = true; } } |
