From d9a03c9bb120cada54729d314a204a63fbf607b5 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 10 Sep 2019 22:37:53 +0200 Subject: Fix more warnings --- Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs index b2328121e3..3a7516dca9 100644 --- a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs +++ b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs @@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.EntryPoints { cancellationToken.ThrowIfCancellationRequested(); - await user.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_logger, _fileSystem)), cancellationToken).ConfigureAwait(false); + await user.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem)), cancellationToken).ConfigureAwait(false); } } -- cgit v1.2.3 From 3f7836d9eb16d90b890dc925d8f7a3e8f2cb6b71 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 23 Sep 2019 23:10:51 +0200 Subject: Update deps and add MultiThreading analyzer --- Emby.Naming/Emby.Naming.csproj | 3 +- .../AppBase/BaseConfigurationManager.cs | 25 +++++-- .../Emby.Server.Implementations.csproj | 16 ++--- .../EntryPoints/ExternalPortForwarding.cs | 17 +++-- .../Networking/NetworkManager.cs | 16 +++-- .../Updates/InstallationManager.cs | 84 +++++++++++----------- Jellyfin.Server/Jellyfin.Server.csproj | 9 ++- MediaBrowser.Common/MediaBrowser.Common.csproj | 2 +- .../MediaBrowser.MediaEncoding.csproj | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- .../MediaBrowser.Providers.csproj | 6 +- jellyfin.ruleset | 2 + 12 files changed, 106 insertions(+), 78 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index fca0aa1b38..a23fa3df79 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -24,8 +24,9 @@ - + + diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 4832c19c4e..7ec5252d07 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -35,7 +35,7 @@ namespace Emby.Server.Implementations.AppBase /// /// The _configuration sync lock. /// - private object _configurationSyncLock = new object(); + private readonly object _configurationSyncLock = new object(); /// /// The _configuration. @@ -98,16 +98,31 @@ namespace Emby.Server.Implementations.AppBase public IApplicationPaths CommonApplicationPaths { get; private set; } /// - /// Gets the system configuration + /// Gets the system configuration. /// /// The configuration. public BaseApplicationConfiguration CommonConfiguration { get { - // Lazy load - LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer)); - return _configuration; + if (_configurationLoaded) + { + return _configuration; + } + + lock (_configurationSyncLock) + { + if (_configurationLoaded) + { + return _configuration; + } + + _configuration = (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer); + + _configurationLoaded = true; + + return _configuration; + } } protected set { diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index ea44442687..d6ca19e3f4 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -1,4 +1,4 @@ - + @@ -29,9 +29,9 @@ - - - + + + @@ -47,16 +47,12 @@ true - - - latest - - - + + diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index f26a705867..d55dc2f18b 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -27,6 +27,11 @@ namespace Emby.Server.Implementations.EntryPoints private NatManager _natManager; + private readonly object _createdRulesLock = new object(); + private List _createdRules = new List(); + private readonly object _usnsHandledLock = new object(); + private List _usnsHandled = new List(); + public ExternalPortForwarding(ILoggerFactory loggerFactory, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient) { _logger = loggerFactory.CreateLogger("PortMapper"); @@ -127,12 +132,13 @@ namespace Emby.Server.Implementations.EntryPoints return; } - lock (_usnsHandled) + lock (_usnsHandledLock) { if (_usnsHandled.Contains(identifier)) { return; } + _usnsHandled.Add(identifier); } @@ -186,11 +192,12 @@ namespace Emby.Server.Implementations.EntryPoints private void ClearCreatedRules(object state) { - lock (_createdRules) + lock (_createdRulesLock) { _createdRules.Clear(); } - lock (_usnsHandled) + + lock (_usnsHandledLock) { _usnsHandled.Clear(); } @@ -216,8 +223,6 @@ namespace Emby.Server.Implementations.EntryPoints } } - private List _createdRules = new List(); - private List _usnsHandled = new List(); private async void CreateRules(INatDevice device) { if (_disposed) @@ -231,7 +236,7 @@ namespace Emby.Server.Implementations.EntryPoints var addressString = address.ToString(); - lock (_createdRules) + lock (_createdRulesLock) { if (!_createdRules.Contains(addressString)) { diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 7d85a0666a..d948dad688 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -20,6 +20,9 @@ namespace Emby.Server.Implementations.Networking private IPAddress[] _localIpAddresses; private readonly object _localIpAddressSyncLock = new object(); + private readonly object _subnetLookupLock = new object(); + private Dictionary> _subnetLookup = new Dictionary>(StringComparer.Ordinal); + public NetworkManager(ILogger logger) { _logger = logger; @@ -28,10 +31,10 @@ namespace Emby.Server.Implementations.Networking NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged; } - public Func LocalSubnetsFn { get; set; } - public event EventHandler NetworkChanged; + public Func LocalSubnetsFn { get; set; } + private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e) { _logger.LogDebug("NetworkAvailabilityChanged"); @@ -179,10 +182,9 @@ namespace Emby.Server.Implementations.Networking return false; } - private Dictionary> _subnetLookup = new Dictionary>(StringComparer.Ordinal); private List GetSubnets(string endpointFirstPart) { - lock (_subnetLookup) + lock (_subnetLookupLock) { if (_subnetLookup.TryGetValue(endpointFirstPart, out var subnets)) { @@ -200,7 +202,11 @@ namespace Emby.Server.Implementations.Networking int subnet_Test = 0; foreach (string part in unicastIPAddressInformation.IPv4Mask.ToString().Split('.')) { - if (part.Equals("0")) break; + if (part.Equals("0", StringComparison.Ordinal)) + { + break; + } + subnet_Test++; } diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 0c0c77cda1..1c36ba359d 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -28,43 +28,10 @@ namespace Emby.Server.Implementations.Updates /// public class InstallationManager : IInstallationManager { - public event EventHandler PackageInstalling; - public event EventHandler PackageInstallationCompleted; - public event EventHandler PackageInstallationFailed; - public event EventHandler PackageInstallationCancelled; - - /// - /// The current installations - /// - private List<(InstallationInfo info, CancellationTokenSource token)> _currentInstallations { get; set; } - - /// - /// The completed installations - /// - private ConcurrentBag _completedInstallationsInternal; - - public IEnumerable CompletedInstallations => _completedInstallationsInternal; - - /// - /// Occurs when [plugin uninstalled]. - /// - public event EventHandler> PluginUninstalled; - - /// - /// Occurs when [plugin updated]. - /// - public event EventHandler> PluginUpdated; - /// - /// Occurs when [plugin updated]. - /// - public event EventHandler> PluginInstalled; - - /// - /// The _logger + /// The _logger. /// private readonly ILogger _logger; - private readonly IApplicationPaths _appPaths; private readonly IHttpClient _httpClient; private readonly IJsonSerializer _jsonSerializer; @@ -79,6 +46,18 @@ namespace Emby.Server.Implementations.Updates private readonly IZipClient _zipClient; + private readonly object _currentInstallationsLock = new object(); + + /// + /// The current installations. + /// + private List<(InstallationInfo info, CancellationTokenSource token)> _currentInstallations; + + /// + /// The completed installations. + /// + private ConcurrentBag _completedInstallationsInternal; + public InstallationManager( ILogger logger, IApplicationHost appHost, @@ -107,6 +86,31 @@ namespace Emby.Server.Implementations.Updates _zipClient = zipClient; } + public event EventHandler PackageInstalling; + + public event EventHandler PackageInstallationCompleted; + + public event EventHandler PackageInstallationFailed; + + public event EventHandler PackageInstallationCancelled; + + /// + /// Occurs when [plugin uninstalled]. + /// + public event EventHandler> PluginUninstalled; + + /// + /// Occurs when [plugin updated]. + /// + public event EventHandler> PluginUpdated; + + /// + /// Occurs when [plugin updated]. + /// + public event EventHandler> PluginInstalled; + + public IEnumerable CompletedInstallations => _completedInstallationsInternal; + /// /// Gets all available packages. /// @@ -330,7 +334,7 @@ namespace Emby.Server.Implementations.Updates var tuple = (installationInfo, innerCancellationTokenSource); // Add it to the in-progress list - lock (_currentInstallations) + lock (_currentInstallationsLock) { _currentInstallations.Add(tuple); } @@ -349,7 +353,7 @@ namespace Emby.Server.Implementations.Updates { await InstallPackageInternal(package, linkedToken).ConfigureAwait(false); - lock (_currentInstallations) + lock (_currentInstallationsLock) { _currentInstallations.Remove(tuple); } @@ -360,7 +364,7 @@ namespace Emby.Server.Implementations.Updates } catch (OperationCanceledException) { - lock (_currentInstallations) + lock (_currentInstallationsLock) { _currentInstallations.Remove(tuple); } @@ -375,7 +379,7 @@ namespace Emby.Server.Implementations.Updates { _logger.LogError(ex, "Package installation failed"); - lock (_currentInstallations) + lock (_currentInstallationsLock) { _currentInstallations.Remove(tuple); } @@ -535,7 +539,7 @@ namespace Emby.Server.Implementations.Updates /// public bool CancelInstallation(Guid id) { - lock (_currentInstallations) + lock (_currentInstallationsLock) { var install = _currentInstallations.Find(x => x.Item1.Id == id); if (install == default((InstallationInfo, CancellationTokenSource))) @@ -563,7 +567,7 @@ namespace Emby.Server.Implementations.Updates { if (dispose) { - lock (_currentInstallations) + lock (_currentInstallationsLock) { foreach (var tuple in _currentInstallations) { diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index efdb75f980..4238d7fe3e 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -9,8 +9,6 @@ - - latest true @@ -25,8 +23,9 @@ - + + @@ -35,8 +34,8 @@ - - + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index cf3f6c2a44..ec98400c89 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -12,7 +12,7 @@ - + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 264f31f3c9..ad07fdd8e2 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -18,7 +18,7 @@ - + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 3ed319a0de..bd4eeea18d 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -15,7 +15,7 @@ - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index c7ecc59c9f..ec160a8484 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -11,8 +11,8 @@ - - + + @@ -28,5 +28,5 @@ latest - + diff --git a/jellyfin.ruleset b/jellyfin.ruleset index e259131b05..16d68567c1 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -10,6 +10,8 @@ + + -- cgit v1.2.3 From b0a25c4237c33ad961ed7805c9f6fd810997df36 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 1 Nov 2019 21:22:35 +0100 Subject: Use Mono.Nat Nuget package --- Emby.Dlna/Ssdp/DeviceDiscovery.cs | 23 +- Emby.Server.Implementations/ApplicationHost.cs | 5 +- .../Emby.Server.Implementations.csproj | 2 +- .../EntryPoints/ExternalPortForwarding.cs | 239 +++++------------- MediaBrowser.sln | 6 - Mono.Nat/AbstractNatDevice.cs | 55 ----- Mono.Nat/Enums/ProtocolType.cs | 36 --- Mono.Nat/EventArgs/DeviceEventArgs.cs | 45 ---- Mono.Nat/INatDevice.cs | 45 ---- Mono.Nat/ISearcher.cs | 46 ---- Mono.Nat/Mapping.cs | 121 ---------- Mono.Nat/Mono.Nat.csproj | 17 -- Mono.Nat/NatManager.cs | 86 ------- Mono.Nat/NatProtocol.cs | 8 - Mono.Nat/Pmp/PmpConstants.cs | 56 ----- Mono.Nat/Pmp/PmpNatDevice.cs | 217 ----------------- Mono.Nat/Pmp/PmpSearcher.cs | 235 ------------------ Mono.Nat/Properties/AssemblyInfo.cs | 21 -- Mono.Nat/Upnp/Messages/GetServicesMessage.cs | 64 ----- .../Messages/Requests/CreatePortMappingMessage.cs | 75 ------ Mono.Nat/Upnp/Messages/UpnpMessage.cs | 84 ------- Mono.Nat/Upnp/Searchers/UpnpSearcher.cs | 111 --------- Mono.Nat/Upnp/UpnpNatDevice.cs | 267 --------------------- 23 files changed, 78 insertions(+), 1786 deletions(-) delete mode 100644 Mono.Nat/AbstractNatDevice.cs delete mode 100644 Mono.Nat/Enums/ProtocolType.cs delete mode 100644 Mono.Nat/EventArgs/DeviceEventArgs.cs delete mode 100644 Mono.Nat/INatDevice.cs delete mode 100644 Mono.Nat/ISearcher.cs delete mode 100644 Mono.Nat/Mapping.cs delete mode 100644 Mono.Nat/Mono.Nat.csproj delete mode 100644 Mono.Nat/NatManager.cs delete mode 100644 Mono.Nat/NatProtocol.cs delete mode 100644 Mono.Nat/Pmp/PmpConstants.cs delete mode 100644 Mono.Nat/Pmp/PmpNatDevice.cs delete mode 100644 Mono.Nat/Pmp/PmpSearcher.cs delete mode 100644 Mono.Nat/Properties/AssemblyInfo.cs delete mode 100644 Mono.Nat/Upnp/Messages/GetServicesMessage.cs delete mode 100644 Mono.Nat/Upnp/Messages/Requests/CreatePortMappingMessage.cs delete mode 100644 Mono.Nat/Upnp/Messages/UpnpMessage.cs delete mode 100644 Mono.Nat/Upnp/Searchers/UpnpSearcher.cs delete mode 100644 Mono.Nat/Upnp/UpnpNatDevice.cs (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Dlna/Ssdp/DeviceDiscovery.cs b/Emby.Dlna/Ssdp/DeviceDiscovery.cs index 298f68a28e..c5f3593da8 100644 --- a/Emby.Dlna/Ssdp/DeviceDiscovery.cs +++ b/Emby.Dlna/Ssdp/DeviceDiscovery.cs @@ -4,8 +4,6 @@ using System.Linq; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Events; -using MediaBrowser.Model.Net; -using Microsoft.Extensions.Logging; using Rssdp; using Rssdp.Infrastructure; @@ -15,13 +13,14 @@ namespace Emby.Dlna.Ssdp { private bool _disposed; - private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private event EventHandler> DeviceDiscoveredInternal; private int _listenerCount; private object _syncLock = new object(); + + /// public event EventHandler> DeviceDiscovered { add @@ -31,6 +30,7 @@ namespace Emby.Dlna.Ssdp _listenerCount++; DeviceDiscoveredInternal += value; } + StartInternal(); } remove @@ -43,21 +43,16 @@ namespace Emby.Dlna.Ssdp } } + /// public event EventHandler> DeviceLeft; private SsdpDeviceLocator _deviceLocator; - private readonly ISocketFactory _socketFactory; private ISsdpCommunicationsServer _commsServer; - public DeviceDiscovery( - ILoggerFactory loggerFactory, - IServerConfigurationManager config, - ISocketFactory socketFactory) + public DeviceDiscovery(IServerConfigurationManager config) { - _logger = loggerFactory.CreateLogger(nameof(DeviceDiscovery)); _config = config; - _socketFactory = socketFactory; } // Call this method from somewhere in your code to start the search. @@ -82,8 +77,8 @@ namespace Emby.Dlna.Ssdp //_DeviceLocator.NotificationFilter = "upnp:rootdevice"; // Connect our event handler so we process devices as they are found - _deviceLocator.DeviceAvailable += deviceLocator_DeviceAvailable; - _deviceLocator.DeviceUnavailable += _DeviceLocator_DeviceUnavailable; + _deviceLocator.DeviceAvailable += OnDeviceLocatorDeviceAvailable; + _deviceLocator.DeviceUnavailable += OnDeviceLocatorDeviceUnavailable; var dueTime = TimeSpan.FromSeconds(5); var interval = TimeSpan.FromSeconds(_config.GetDlnaConfiguration().ClientDiscoveryIntervalSeconds); @@ -94,7 +89,7 @@ namespace Emby.Dlna.Ssdp } // Process each found device in the event handler - void deviceLocator_DeviceAvailable(object sender, DeviceAvailableEventArgs e) + private void OnDeviceLocatorDeviceAvailable(object sender, DeviceAvailableEventArgs e) { var originalHeaders = e.DiscoveredDevice.ResponseHeaders; @@ -115,7 +110,7 @@ namespace Emby.Dlna.Ssdp DeviceDiscoveredInternal?.Invoke(this, args); } - private void _DeviceLocator_DeviceUnavailable(object sender, DeviceUnavailableEventArgs e) + private void OnDeviceLocatorDeviceUnavailable(object sender, DeviceUnavailableEventArgs e) { var originalHeaders = e.DiscoveredDevice.ResponseHeaders; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index f7fe2bd638..7cb7aa7486 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -866,8 +866,7 @@ namespace Emby.Server.Implementations NotificationManager = new NotificationManager(LoggerFactory, UserManager, ServerConfigurationManager); serviceCollection.AddSingleton(NotificationManager); - serviceCollection.AddSingleton( - new DeviceDiscovery(LoggerFactory, ServerConfigurationManager, SocketFactory)); + serviceCollection.AddSingleton(new DeviceDiscovery(ServerConfigurationManager)); ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository); serviceCollection.AddSingleton(ChapterManager); @@ -1730,7 +1729,7 @@ namespace Emby.Server.Implementations /// dns is prefixed with a valid Uri prefix. /// /// The external dns prefix to get the hostname of. - /// The hostname in + /// The hostname in . private static string GetHostnameFromExternalDns(string externalDns) { if (string.IsNullOrEmpty(externalDns)) diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index d6ca19e3f4..45607dc098 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -10,7 +10,6 @@ - @@ -32,6 +31,7 @@ + diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index d55dc2f18b..2f3d2c2888 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; -using System.Globalization; 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 MediaBrowser.Controller.Plugins; @@ -19,57 +18,51 @@ namespace Emby.Server.Implementations.EntryPoints { private readonly IServerApplicationHost _appHost; private readonly ILogger _logger; - private readonly IHttpClient _httpClient; private readonly IServerConfigurationManager _config; private readonly IDeviceDiscovery _deviceDiscovery; private Timer _timer; - private NatManager _natManager; - private readonly object _createdRulesLock = new object(); - private List _createdRules = new List(); - private readonly object _usnsHandledLock = new object(); - private List _usnsHandled = new List(); + private List _createdRules = new List(); + private string _lastConfigIdentifier; + + private bool _disposed = false; - public ExternalPortForwarding(ILoggerFactory loggerFactory, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient) + public ExternalPortForwarding( + ILogger logger, + IServerApplicationHost appHost, + IServerConfigurationManager config, + IDeviceDiscovery deviceDiscovery) { - _logger = loggerFactory.CreateLogger("PortMapper"); + _logger = logger; _appHost = appHost; _config = config; _deviceDiscovery = deviceDiscovery; - _httpClient = httpClient; - _config.ConfigurationUpdated += _config_ConfigurationUpdated1; } - private void _config_ConfigurationUpdated1(object sender, EventArgs e) - { - _config_ConfigurationUpdated(sender, e); - } - - private string _lastConfigIdentifier; private string GetConfigIdentifier() { - var values = new List(); + const char Separator = '|'; var config = _config.Configuration; - values.Add(config.EnableUPnP.ToString()); - values.Add(config.PublicPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpsPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.EnableHttps.ToString()); - values.Add((config.EnableRemoteAccess).ToString()); - - return string.Join("|", values.ToArray()); + return new StringBuilder(32) + .Append(config.EnableUPnP).Append(Separator) + .Append(config.PublicPort).Append(Separator) + .Append(_appHost.HttpPort).Append(Separator) + .Append(_appHost.HttpsPort).Append(Separator) + .Append(_appHost.EnableHttps).Append(Separator) + .Append(config.EnableRemoteAccess).Append(Separator) + .ToString(); } - private async void _config_ConfigurationUpdated(object sender, EventArgs e) + private async void OnConfigurationUpdated(object sender, EventArgs e) { if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) { - DisposeNat(); + Stop(); - await RunAsync(); + await RunAsync().ConfigureAwait(false); } } @@ -80,8 +73,7 @@ namespace Emby.Server.Implementations.EntryPoints Start(); } - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - _config.ConfigurationUpdated += _config_ConfigurationUpdated; + _config.ConfigurationUpdated += OnConfigurationUpdated; return Task.CompletedTask; } @@ -89,105 +81,27 @@ namespace Emby.Server.Implementations.EntryPoints private void Start() { _logger.LogDebug("Starting NAT discovery"); - if (_natManager == null) - { - _natManager = new NatManager(_logger, _httpClient); - _natManager.DeviceFound += NatUtility_DeviceFound; - _natManager.StartDiscovery(); - } + + NatUtility.DeviceFound += OnNatUtilityDeviceFound; + NatUtility.StartDiscovery(); _timer = new Timer(ClearCreatedRules, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); - _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; + _deviceDiscovery.DeviceDiscovered += OnDeviceDiscoveryDeviceDiscovered; _lastConfigIdentifier = GetConfigIdentifier(); } - private async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs e) + private void Stop() { - if (_disposed) - { - return; - } - - var info = e.Argument; - - if (!info.Headers.TryGetValue("USN", out string usn)) usn = string.Empty; - - if (!info.Headers.TryGetValue("NT", out string nt)) nt = string.Empty; - - // Filter device type - if (usn.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - nt.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - usn.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - nt.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1) - { - return; - } - - var identifier = string.IsNullOrWhiteSpace(usn) ? nt : usn; - - if (info.Location == null) - { - return; - } - - lock (_usnsHandledLock) - { - if (_usnsHandled.Contains(identifier)) - { - return; - } - - _usnsHandled.Add(identifier); - } - - _logger.LogDebug("Found NAT device: " + identifier); - - if (IPAddress.TryParse(info.Location.Host, out var address)) - { - // The Handle method doesn't need the port - var endpoint = new IPEndPoint(address, info.Location.Port); - - IPAddress localAddress = null; - - try - { - var localAddressString = await _appHost.GetLocalApiUrl(CancellationToken.None).ConfigureAwait(false); + _logger.LogDebug("Stopping NAT discovery"); - if (Uri.TryCreate(localAddressString, UriKind.Absolute, out var uri)) - { - localAddressString = uri.Host; + NatUtility.StopDiscovery(); + NatUtility.DeviceFound -= OnNatUtilityDeviceFound; - if (!IPAddress.TryParse(localAddressString, out localAddress)) - { - return; - } - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error"); - return; - } + _timer?.Dispose(); - if (_disposed) - { - return; - } - - // This should never happen, but the Handle method will throw ArgumentNullException if it does - if (localAddress == null) - { - return; - } - - var natManager = _natManager; - if (natManager != null) - { - await natManager.Handle(localAddress, info, endpoint, NatProtocol.Upnp).ConfigureAwait(false); - } - } + _deviceDiscovery.DeviceDiscovered -= OnDeviceDiscoveryDeviceDiscovered; } private void ClearCreatedRules(object state) @@ -196,30 +110,24 @@ namespace Emby.Server.Implementations.EntryPoints { _createdRules.Clear(); } - - lock (_usnsHandledLock) - { - _usnsHandled.Clear(); - } } - void NatUtility_DeviceFound(object sender, DeviceEventArgs e) + private void OnDeviceDiscoveryDeviceDiscovered(object sender, GenericEventArgs e) { - if (_disposed) - { - return; - } + NatUtility.Search(e.Argument.LocalIpAddress, NatProtocol.Upnp); + } + private void OnNatUtilityDeviceFound(object sender, DeviceEventArgs e) + { try { var device = e.Device; CreateRules(device); } - catch + catch (Exception ex) { - // Commenting out because users are reporting problems out of our control - //_logger.LogError(ex, "Error creating port forwarding rules"); + _logger.LogError(ex, "Error creating port forwarding rules"); } } @@ -232,15 +140,13 @@ namespace Emby.Server.Implementations.EntryPoints // 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 - var address = device.LocalAddress; - - var addressString = address.ToString(); + var address = device.DeviceEndpoint; lock (_createdRulesLock) { - if (!_createdRules.Contains(addressString)) + if (!_createdRules.Contains(address)) { - _createdRules.Add(addressString); + _createdRules.Add(address); } else { @@ -268,54 +174,41 @@ namespace Emby.Server.Implementations.EntryPoints } } - private Task CreatePortMap(INatDevice device, int privatePort, int publicPort) + private Task CreatePortMap(INatDevice device, int privatePort, int publicPort) { - _logger.LogDebug("Creating port map on local port {0} to public port {1} with device {2}", privatePort, publicPort, device.LocalAddress.ToString()); - - return device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) - { - Description = _appHost.Name - }); + _logger.LogDebug( + "Creating port map on local port {0} to public port {1} with device {2}", + privatePort, + publicPort, + device.DeviceEndpoint); + + return device.CreatePortMapAsync( + new Mapping(Protocol.Tcp, privatePort, publicPort, 0, _appHost.Name)); } - private bool _disposed = false; + /// public void Dispose() { - _disposed = true; - DisposeNat(); + Dispose(true); + GC.SuppressFinalize(this); } - private void DisposeNat() + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool dispose) { - _logger.LogDebug("Stopping NAT discovery"); - - if (_timer != null) + if (_disposed) { - _timer.Dispose(); - _timer = null; + return; } - _deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered; - - var natManager = _natManager; + Stop(); - if (natManager != null) - { - _natManager = null; + _timer = null; - using (natManager) - { - try - { - natManager.StopDiscovery(); - natManager.DeviceFound -= NatUtility_DeviceFound; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error stopping NAT Discovery"); - } - } - } + _disposed = true; } } } diff --git a/MediaBrowser.sln b/MediaBrowser.sln index dd4e9f8a69..3b0353800d 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -33,8 +33,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSSDP", "RSSDP\RSSDP.csproj EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.csproj", "{805844AB-E92F-45E6-9D99-4F6D48D129A5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{CB7F2326-6497-4A3D-BA03-48513B17A7BE}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Notifications", "Emby.Notifications\Emby.Notifications.csproj", "{2E030C33-6923-4530-9E54-FA29FA6AD1A9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Naming", "Emby.Naming\Emby.Naming.csproj", "{E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}" @@ -129,10 +127,6 @@ Global {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.Build.0 = Debug|Any CPU {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.ActiveCfg = Release|Any CPU {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.Build.0 = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Any CPU.Build.0 = Release|Any CPU {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/Mono.Nat/AbstractNatDevice.cs b/Mono.Nat/AbstractNatDevice.cs deleted file mode 100644 index 1241170c1c..0000000000 --- a/Mono.Nat/AbstractNatDevice.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// Ben Motmans -// -// Copyright (C) 2006 Alan McGovern -// Copyright (C) 2007 Ben Motmans -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Text; -using System.Net; -using System.Threading.Tasks; - -namespace Mono.Nat -{ - public abstract class AbstractNatDevice : INatDevice - { - private DateTime lastSeen; - - protected AbstractNatDevice() - { - } - - public abstract IPAddress LocalAddress { get; } - - public DateTime LastSeen - { - get { return lastSeen; } - set { lastSeen = value; } - } - - public abstract Task CreatePortMap(Mapping mapping); - } -} diff --git a/Mono.Nat/Enums/ProtocolType.cs b/Mono.Nat/Enums/ProtocolType.cs deleted file mode 100644 index 54480598d2..0000000000 --- a/Mono.Nat/Enums/ProtocolType.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; - -namespace Mono.Nat -{ - public enum Protocol - { - Tcp, - Udp - } -} diff --git a/Mono.Nat/EventArgs/DeviceEventArgs.cs b/Mono.Nat/EventArgs/DeviceEventArgs.cs deleted file mode 100644 index 6358a0c29f..0000000000 --- a/Mono.Nat/EventArgs/DeviceEventArgs.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; - -namespace Mono.Nat -{ - public class DeviceEventArgs : EventArgs - { - private INatDevice device; - - public DeviceEventArgs(INatDevice device) - { - this.device = device; - } - - public INatDevice Device - { - get { return this.device; } - } - } -} diff --git a/Mono.Nat/INatDevice.cs b/Mono.Nat/INatDevice.cs deleted file mode 100644 index 6a15090710..0000000000 --- a/Mono.Nat/INatDevice.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// Ben Motmans -// -// Copyright (C) 2006 Alan McGovern -// Copyright (C) 2007 Ben Motmans -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Text; -using System.Net; -using System.Threading.Tasks; - -namespace Mono.Nat -{ - public interface INatDevice - { - Task CreatePortMap (Mapping mapping); - - IPAddress LocalAddress { get; } - - DateTime LastSeen { get; set; } - } -} diff --git a/Mono.Nat/ISearcher.cs b/Mono.Nat/ISearcher.cs deleted file mode 100644 index 95c2f2aa90..0000000000 --- a/Mono.Nat/ISearcher.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// Ben Motmans -// Nicholas Terry -// -// Copyright (C) 2006 Alan McGovern -// Copyright (C) 2007 Ben Motmans -// Copyright (C) 2014 Nicholas Terry -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Text; -using System.Net.Sockets; -using System.Net; - -namespace Mono.Nat -{ - internal interface ISearcher - { - event EventHandler DeviceFound; - - void Search(); - void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint); - } -} diff --git a/Mono.Nat/Mapping.cs b/Mono.Nat/Mapping.cs deleted file mode 100644 index 5b15d4e14f..0000000000 --- a/Mono.Nat/Mapping.cs +++ /dev/null @@ -1,121 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// Ben Motmans -// -// Copyright (C) 2006 Alan McGovern -// Copyright (C) 2007 Ben Motmans -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; - -namespace Mono.Nat -{ - public class Mapping - { - private string description; - private DateTime expiration; - private int lifetime; - private int privatePort; - private Protocol protocol; - private int publicPort; - - public Mapping(Protocol protocol, int privatePort, int publicPort) - : this (protocol, privatePort, publicPort, 0) - { - } - - public Mapping(Protocol protocol, int privatePort, int publicPort, int lifetime) - { - this.protocol = protocol; - this.privatePort = privatePort; - this.publicPort = publicPort; - this.lifetime = lifetime; - - if (lifetime == int.MaxValue) - this.expiration = DateTime.MaxValue; - else if (lifetime == 0) - this.expiration = DateTime.Now; - else - this.expiration = DateTime.Now.AddSeconds (lifetime); - } - - public string Description - { - get { return description; } - set { description = value; } - } - - public Protocol Protocol - { - get { return protocol; } - internal set { protocol = value; } - } - - public int PrivatePort - { - get { return privatePort; } - internal set { privatePort = value; } - } - - public int PublicPort - { - get { return publicPort; } - internal set { publicPort = value; } - } - - public int Lifetime - { - get { return lifetime; } - internal set { lifetime = value; } - } - - public DateTime Expiration - { - get { return expiration; } - internal set { expiration = value; } - } - - public bool IsExpired() - { - return expiration < DateTime.Now; - } - - public override bool Equals(object obj) - { - var other = obj as Mapping; - return other == null ? false : this.protocol == other.protocol && - this.privatePort == other.privatePort && this.publicPort == other.publicPort; - } - - public override int GetHashCode() - { - return this.protocol.GetHashCode() ^ this.privatePort.GetHashCode() ^ this.publicPort.GetHashCode(); - } - - public override string ToString() - { - return String.Format( "Protocol: {0}, Public Port: {1}, Private Port: {2}, Description: {3}, Expiration: {4}, Lifetime: {5}", - this.protocol, this.publicPort, this.privatePort, this.description, this.expiration, this.lifetime ); - } - } -} diff --git a/Mono.Nat/Mono.Nat.csproj b/Mono.Nat/Mono.Nat.csproj deleted file mode 100644 index c143000b37..0000000000 --- a/Mono.Nat/Mono.Nat.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - netstandard2.1 - false - - - diff --git a/Mono.Nat/NatManager.cs b/Mono.Nat/NatManager.cs deleted file mode 100644 index 3ed01a6b3c..0000000000 --- a/Mono.Nat/NatManager.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Net; -using System.Collections.Generic; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Dlna; -using Microsoft.Extensions.Logging; -using System.Linq; - -namespace Mono.Nat -{ - public class NatManager : IDisposable - { - public event EventHandler DeviceFound; - - private List controllers = new List(); - - private ILogger Logger; - private IHttpClient HttpClient; - - public NatManager(ILogger logger, IHttpClient httpClient) - { - Logger = logger; - HttpClient = httpClient; - } - - private object _runSyncLock = new object(); - public void StartDiscovery() - { - lock (_runSyncLock) - { - if (controllers.Count > 0) - { - return; - } - - controllers.Add(new PmpSearcher(Logger)); - - foreach (var searcher in controllers) - { - searcher.DeviceFound += Searcher_DeviceFound; - } - } - } - - public void StopDiscovery() - { - lock (_runSyncLock) - { - var disposables = controllers.OfType().ToList(); - controllers.Clear(); - - foreach (var disposable in disposables) - { - disposable.Dispose(); - } - } - } - - public void Dispose() - { - StopDiscovery(); - } - - public Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint, NatProtocol protocol) - { - switch (protocol) - { - case NatProtocol.Upnp: - var searcher = new UpnpSearcher(Logger, HttpClient); - searcher.DeviceFound += Searcher_DeviceFound; - return searcher.Handle(localAddress, deviceInfo, endpoint); - default: - throw new ArgumentException("Unexpected protocol: " + protocol); - } - } - - private void Searcher_DeviceFound(object sender, DeviceEventArgs e) - { - if (DeviceFound != null) - { - DeviceFound(sender, e); - } - } - } -} diff --git a/Mono.Nat/NatProtocol.cs b/Mono.Nat/NatProtocol.cs deleted file mode 100644 index 2768f133c5..0000000000 --- a/Mono.Nat/NatProtocol.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Mono.Nat -{ - public enum NatProtocol - { - Upnp = 0, - Pmp = 1 - } -} diff --git a/Mono.Nat/Pmp/PmpConstants.cs b/Mono.Nat/Pmp/PmpConstants.cs deleted file mode 100644 index 83fa8e07cd..0000000000 --- a/Mono.Nat/Pmp/PmpConstants.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// Authors: -// Ben Motmans -// -// Copyright (C) 2007 Ben Motmans -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; - -namespace Mono.Nat.Pmp -{ - internal static class PmpConstants - { - public const byte Version = (byte)0; - - public const byte OperationCode = (byte)0; - public const byte OperationCodeUdp = (byte)1; - public const byte OperationCodeTcp = (byte)2; - public const byte ServerNoop = (byte)128; - - public const int ClientPort = 5350; - public const int ServerPort = 5351; - - public const int RetryDelay = 250; - public const int RetryAttempts = 9; - - public const int RecommendedLeaseTime = 60 * 60; - public const int DefaultLeaseTime = RecommendedLeaseTime; - - public const short ResultCodeSuccess = 0; - public const short ResultCodeUnsupportedVersion = 1; - public const short ResultCodeNotAuthorized = 2; - public const short ResultCodeNetworkFailure = 3; - public const short ResultCodeOutOfResources = 4; - public const short ResultCodeUnsupportedOperationCode = 5; - } -} diff --git a/Mono.Nat/Pmp/PmpNatDevice.cs b/Mono.Nat/Pmp/PmpNatDevice.cs deleted file mode 100644 index 95bd72a6cc..0000000000 --- a/Mono.Nat/Pmp/PmpNatDevice.cs +++ /dev/null @@ -1,217 +0,0 @@ -// -// Authors: -// Ben Motmans -// -// Copyright (C) 2007 Ben Motmans -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Collections.Generic; -using System.Threading.Tasks; -using MediaBrowser.Model.Extensions; -using Microsoft.Extensions.Logging; - -namespace Mono.Nat.Pmp -{ - internal sealed class PmpNatDevice : AbstractNatDevice, IEquatable - { - private IPAddress localAddress; - private IPAddress publicAddress; - private ILogger _logger; - - internal PmpNatDevice(IPAddress localAddress, IPAddress publicAddress, ILogger logger) - { - if (localAddress == null) - { - throw new ArgumentNullException(nameof(localAddress)); - } - - this.localAddress = localAddress; - this.publicAddress = publicAddress; - _logger = logger; - } - - public override IPAddress LocalAddress - { - get { return localAddress; } - } - - public override Task CreatePortMap(Mapping mapping) - { - return InternalCreatePortMapAsync(mapping, true); - } - - public override bool Equals(object obj) - { - var device = obj as PmpNatDevice; - return (device == null) ? false : this.Equals(device); - } - - public override int GetHashCode() - { - return this.publicAddress.GetHashCode(); - } - - public bool Equals(PmpNatDevice other) - { - return (other == null) ? false : this.publicAddress.Equals(other.publicAddress); - } - - private async Task InternalCreatePortMapAsync(Mapping mapping, bool create) - { - var package = new List(); - - package.Add(PmpConstants.Version); - package.Add(mapping.Protocol == Protocol.Tcp ? PmpConstants.OperationCodeTcp : PmpConstants.OperationCodeUdp); - package.Add(0); //reserved - package.Add(0); //reserved - package.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)mapping.PrivatePort))); - package.AddRange( - BitConverter.GetBytes(create ? IPAddress.HostToNetworkOrder((short)mapping.PublicPort) : (short)0)); - package.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(mapping.Lifetime))); - - try - { - byte[] buffer = package.ToArray(); - int attempt = 0; - int delay = PmpConstants.RetryDelay; - - using (var udpClient = new UdpClient()) - { - var cancellationTokenSource = new CancellationTokenSource(); - - while (attempt < PmpConstants.RetryAttempts) - { - await udpClient.SendAsync(buffer, buffer.Length, new IPEndPoint(LocalAddress, PmpConstants.ServerPort)); - - if (attempt == 0) - { - await Task.Run(() => CreatePortMapListen(udpClient, mapping, cancellationTokenSource.Token)); - } - - attempt++; - delay *= 2; - await Task.Delay(delay).ConfigureAwait(false); - } - - cancellationTokenSource.Cancel(); - } - } - catch (OperationCanceledException) - { - - } - catch (Exception e) - { - string type = create ? "create" : "delete"; - string message = String.Format("Failed to {0} portmap (protocol={1}, private port={2}) {3}", - type, - mapping.Protocol, - mapping.PrivatePort, - e.Message); - _logger.LogDebug(message); - throw e; - } - - return mapping; - } - - private async void CreatePortMapListen(UdpClient udpClient, Mapping mapping, CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - try - { - var result = await udpClient.ReceiveAsync().ConfigureAwait(false); - var endPoint = result.RemoteEndPoint; - byte[] data = data = result.Buffer; - - if (data.Length < 16) - continue; - - if (data[0] != PmpConstants.Version) - continue; - - var opCode = (byte)(data[1] & 127); - - var protocol = Protocol.Tcp; - if (opCode == PmpConstants.OperationCodeUdp) - protocol = Protocol.Udp; - - short resultCode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 2)); - int epoch = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 4)); - - short privatePort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 8)); - short publicPort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 10)); - - var lifetime = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 12)); - - if (privatePort < 0 || publicPort < 0 || resultCode != PmpConstants.ResultCodeSuccess) - { - var errors = new[] - { - "Success", - "Unsupported Version", - "Not Authorized/Refused (e.g. box supports mapping, but user has turned feature off)" - , - "Network Failure (e.g. NAT box itself has not obtained a DHCP lease)", - "Out of resources (NAT box cannot create any more mappings at this time)", - "Unsupported opcode" - }; - - var errorMsg = errors[resultCode]; - _logger.LogDebug("Error in CreatePortMapListen: " + errorMsg); - return; - } - - if (lifetime == 0) return; //mapping was deleted - - //mapping was created - //TODO: verify that the private port+protocol are a match - mapping.PublicPort = publicPort; - mapping.Protocol = protocol; - mapping.Expiration = DateTime.Now.AddSeconds(lifetime); - return; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error in CreatePortMapListen"); - return; - } - } - } - - /// - /// Overridden. - /// - /// - public override string ToString() - { - return String.Format("PmpNatDevice - Local Address: {0}, Public IP: {1}, Last Seen: {2}", - this.localAddress, this.publicAddress, this.LastSeen); - } - } -} diff --git a/Mono.Nat/Pmp/PmpSearcher.cs b/Mono.Nat/Pmp/PmpSearcher.cs deleted file mode 100644 index 46c2e9d800..0000000000 --- a/Mono.Nat/Pmp/PmpSearcher.cs +++ /dev/null @@ -1,235 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// Ben Motmans -// Nicholas Terry -// -// Copyright (C) 2006 Alan McGovern -// Copyright (C) 2007 Ben Motmans -// Copyright (C) 2014 Nicholas Terry -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - - -using System; -using System.Collections.Generic; -using System.Text; -using System.Net; -using Mono.Nat.Pmp; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using System.Linq; - -namespace Mono.Nat -{ - internal class PmpSearcher : ISearcher, IDisposable - { - private ILogger _logger; - - private int timeout = 250; - private DateTime nextSearch; - public event EventHandler DeviceFound; - - public PmpSearcher(ILogger logger) - { - _logger = logger; - - CreateSocketsAndAddGateways(); - } - - public void Dispose() - { - var list = sockets.ToList(); - sockets.Clear(); - - foreach (var s in list) - { - using (s) - { - s.Close(); - } - } - } - - private List sockets; - private Dictionary> gatewayLists; - - private void CreateSocketsAndAddGateways() - { - sockets = new List(); - gatewayLists = new Dictionary>(); - - try - { - foreach (var n in NetworkInterface.GetAllNetworkInterfaces()) - { - if (n.OperationalStatus != OperationalStatus.Up && n.OperationalStatus != OperationalStatus.Unknown) - continue; - IPInterfaceProperties properties = n.GetIPProperties(); - var gatewayList = new List(); - - foreach (GatewayIPAddressInformation gateway in properties.GatewayAddresses) - { - if (gateway.Address.AddressFamily == AddressFamily.InterNetwork) - { - gatewayList.Add(new IPEndPoint(gateway.Address, PmpConstants.ServerPort)); - } - } - if (gatewayList.Count == 0) - { - /* Mono on OSX doesn't give any gateway addresses, so check DNS entries */ - foreach (var gw2 in properties.DnsAddresses) - { - if (gw2.AddressFamily == AddressFamily.InterNetwork) - { - gatewayList.Add(new IPEndPoint(gw2, PmpConstants.ServerPort)); - } - } - foreach (UnicastIPAddressInformation unicast in properties.UnicastAddresses) - { - if (/*unicast.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred - && unicast.AddressPreferredLifetime != UInt32.MaxValue - && */unicast.Address.AddressFamily == AddressFamily.InterNetwork) - { - var bytes = unicast.Address.GetAddressBytes(); - bytes[3] = 1; - gatewayList.Add(new IPEndPoint(new IPAddress(bytes), PmpConstants.ServerPort)); - } - } - } - - if (gatewayList.Count > 0) - { - foreach (var address in properties.UnicastAddresses) - { - if (address.Address.AddressFamily == AddressFamily.InterNetwork) - { - UdpClient client; - - try - { - client = new UdpClient(new IPEndPoint(address.Address, 0)); - } - catch (SocketException) - { - continue; // Move on to the next address. - } - - gatewayLists.Add(client, gatewayList); - sockets.Add(client); - } - } - } - } - } - catch (Exception) - { - // NAT-PMP does not use multicast, so there isn't really a good fallback. - } - } - - public async void Search() - { - foreach (UdpClient s in sockets) - { - try - { - await Search(s).ConfigureAwait(false); - } - catch - { - // Ignore any search errors - } - } - } - - async Task Search(UdpClient client) - { - // Sort out the time for the next search first. The spec says the - // timeout should double after each attempt. Once it reaches 64 seconds - // (and that attempt fails), assume no devices available - nextSearch = DateTime.Now.AddMilliseconds(timeout); - timeout *= 2; - - // We've tried 9 times as per spec, try searching again in 5 minutes - if (timeout == 128 * 1000) - { - timeout = 250; - nextSearch = DateTime.Now.AddMinutes(10); - return; - } - - // The nat-pmp search message. Must be sent to GatewayIP:53531 - byte[] buffer = new byte[] { PmpConstants.Version, PmpConstants.OperationCode }; - foreach (IPEndPoint gatewayEndpoint in gatewayLists[client]) - { - await client.SendAsync(buffer, buffer.Length, gatewayEndpoint).ConfigureAwait(false); - } - } - - bool IsSearchAddress(IPAddress address) - { - foreach (var gatewayList in gatewayLists.Values) - foreach (var gatewayEndpoint in gatewayList) - if (gatewayEndpoint.Address.Equals(address)) - return true; - return false; - } - - public void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint) - { - if (!IsSearchAddress(endpoint.Address)) - return; - if (response.Length != 12) - return; - if (response[0] != PmpConstants.Version) - return; - if (response[1] != PmpConstants.ServerNoop) - return; - int errorcode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(response, 2)); - if (errorcode != 0) - _logger.LogDebug("Non zero error: {0}", errorcode); - - var publicIp = new IPAddress(new byte[] { response[8], response[9], response[10], response[11] }); - nextSearch = DateTime.Now.AddMinutes(5); - timeout = 250; - - OnDeviceFound(new DeviceEventArgs(new PmpNatDevice(endpoint.Address, publicIp, _logger))); - } - - public DateTime NextSearch - { - get { return nextSearch; } - } - private void OnDeviceFound(DeviceEventArgs args) - { - if (DeviceFound != null) - DeviceFound(this, args); - } - - public NatProtocol Protocol - { - get { return NatProtocol.Pmp; } - } - } -} diff --git a/Mono.Nat/Properties/AssemblyInfo.cs b/Mono.Nat/Properties/AssemblyInfo.cs deleted file mode 100644 index dc47f2ffeb..0000000000 --- a/Mono.Nat/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Mono.Nat")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2006 Alan McGovern. Copyright © 2007 Ben Motmans. Code releases under the MIT license. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] diff --git a/Mono.Nat/Upnp/Messages/GetServicesMessage.cs b/Mono.Nat/Upnp/Messages/GetServicesMessage.cs deleted file mode 100644 index f619f5ca41..0000000000 --- a/Mono.Nat/Upnp/Messages/GetServicesMessage.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Net; -using MediaBrowser.Common.Net; - -namespace Mono.Nat.Upnp -{ - internal class GetServicesMessage : MessageBase - { - private string _servicesDescriptionUrl; - private EndPoint _hostAddress; - - public GetServicesMessage(string description, EndPoint hostAddress) - : base(null) - { - if (string.IsNullOrEmpty(description)) - { - throw new ArgumentException("Description is null/empty", nameof(description)); - } - - this._servicesDescriptionUrl = description; - this._hostAddress = hostAddress ?? throw new ArgumentNullException(nameof(hostAddress)); - } - - public override string Method => "GET"; - - public override HttpRequestOptions Encode() - { - var req = new HttpRequestOptions() - { - Url = $"http://{this._hostAddress}{this._servicesDescriptionUrl}" - }; - - req.RequestHeaders.Add("ACCEPT-LANGUAGE", "en"); - - return req; - } - } -} diff --git a/Mono.Nat/Upnp/Messages/Requests/CreatePortMappingMessage.cs b/Mono.Nat/Upnp/Messages/Requests/CreatePortMappingMessage.cs deleted file mode 100644 index 7d6844e32a..0000000000 --- a/Mono.Nat/Upnp/Messages/Requests/CreatePortMappingMessage.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Net; -using System.IO; -using System.Globalization; -using System.Text; -using System.Xml; -using MediaBrowser.Common.Net; - -namespace Mono.Nat.Upnp -{ - internal class CreatePortMappingMessage : MessageBase - { - #region Private Fields - - private IPAddress localIpAddress; - private Mapping mapping; - - #endregion - - - #region Constructors - public CreatePortMappingMessage(Mapping mapping, IPAddress localIpAddress, UpnpNatDevice device) - : base(device) - { - this.mapping = mapping; - this.localIpAddress = localIpAddress; - } - #endregion - - public override HttpRequestOptions Encode() - { - var culture = CultureInfo.InvariantCulture; - - var builder = new StringBuilder(256); - XmlWriter writer = CreateWriter(builder); - - WriteFullElement(writer, "NewRemoteHost", string.Empty); - WriteFullElement(writer, "NewExternalPort", this.mapping.PublicPort.ToString(culture)); - WriteFullElement(writer, "NewProtocol", this.mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP"); - WriteFullElement(writer, "NewInternalPort", this.mapping.PrivatePort.ToString(culture)); - WriteFullElement(writer, "NewInternalClient", this.localIpAddress.ToString()); - WriteFullElement(writer, "NewEnabled", "1"); - WriteFullElement(writer, "NewPortMappingDescription", string.IsNullOrEmpty(mapping.Description) ? "Mono.Nat" : mapping.Description); - WriteFullElement(writer, "NewLeaseDuration", mapping.Lifetime.ToString()); - - writer.Flush(); - return CreateRequest("AddPortMapping", builder.ToString()); - } - } -} diff --git a/Mono.Nat/Upnp/Messages/UpnpMessage.cs b/Mono.Nat/Upnp/Messages/UpnpMessage.cs deleted file mode 100644 index d47241d4a1..0000000000 --- a/Mono.Nat/Upnp/Messages/UpnpMessage.cs +++ /dev/null @@ -1,84 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Xml; -using System.Text; -using MediaBrowser.Common.Net; - -namespace Mono.Nat.Upnp -{ - internal abstract class MessageBase - { - protected UpnpNatDevice device; - - protected MessageBase(UpnpNatDevice device) - { - this.device = device; - } - - protected HttpRequestOptions CreateRequest(string upnpMethod, string methodParameters) - { - var req = new HttpRequestOptions() - { - Url = $"http://{this.device.HostEndPoint}{this.device.ControlUrl}", - EnableKeepAlive = false, - RequestContentType = "text/xml", - RequestContent = "" - + "" - + "" - + methodParameters - + "" - + "" - + "\r\n\r\n" - }; - - req.RequestHeaders.Add("SOAPACTION", "\"" + device.ServiceType + "#" + upnpMethod + "\""); - - return req; - } - - public abstract HttpRequestOptions Encode(); - - public virtual string Method => "POST"; - - protected void WriteFullElement(XmlWriter writer, string element, string value) - { - writer.WriteStartElement(element); - writer.WriteString(value); - writer.WriteEndElement(); - } - - protected XmlWriter CreateWriter(StringBuilder sb) - { - var settings = new XmlWriterSettings(); - settings.ConformanceLevel = ConformanceLevel.Fragment; - return XmlWriter.Create(sb, settings); - } - } -} diff --git a/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs b/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs deleted file mode 100644 index 3b54c4680e..0000000000 --- a/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs +++ /dev/null @@ -1,111 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// Ben Motmans -// Nicholas Terry -// -// Copyright (C) 2006 Alan McGovern -// Copyright (C) 2007 Ben Motmans -// Copyright (C) 2014 Nicholas Terry -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Text; -using System.Net; -using Mono.Nat.Upnp; -using System.Diagnostics; -using System.Net.Sockets; -using System.Net.NetworkInformation; -using MediaBrowser.Common.Net; -using Microsoft.Extensions.Logging; -using MediaBrowser.Model.Dlna; -using System.Threading.Tasks; - -namespace Mono.Nat -{ - internal class UpnpSearcher : ISearcher - { - public event EventHandler DeviceFound; - - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - - public UpnpSearcher(ILogger logger, IHttpClient httpClient) - { - _logger = logger; - _httpClient = httpClient; - } - - public void Search() - { - } - - public async Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint) - { - if (localAddress == null) - { - throw new ArgumentNullException(nameof(localAddress)); - } - - try - { - /* For UPnP Port Mapping we need ot find either WANPPPConnection or WANIPConnection. - * Any other device type is no good to us for this purpose. See the IGP overview paper - * page 5 for an overview of device types and their hierarchy. - * http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf */ - - /* TODO: Currently we are assuming version 1 of the protocol. We should figure out which - * version it is and apply the correct URN. */ - - /* Some routers don't correctly implement the version ID on the URN, so we only search for the type - * prefix. */ - - // We have an internet gateway device now - var d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty, _logger, _httpClient); - - await d.GetServicesList().ConfigureAwait(false); - - OnDeviceFound(new DeviceEventArgs(d)); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error decoding device response"); - } - } - - public void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint) - { - } - - private void OnDeviceFound(DeviceEventArgs args) - { - if (DeviceFound != null) - DeviceFound(this, args); - } - - public NatProtocol Protocol - { - get { return NatProtocol.Upnp; } - } - } -} diff --git a/Mono.Nat/Upnp/UpnpNatDevice.cs b/Mono.Nat/Upnp/UpnpNatDevice.cs deleted file mode 100644 index 3ff1eeb90e..0000000000 --- a/Mono.Nat/Upnp/UpnpNatDevice.cs +++ /dev/null @@ -1,267 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// Ben Motmans -// -// Copyright (C) 2006 Alan McGovern -// Copyright (C) 2007 Ben Motmans -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Net; -using System.Xml; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using Microsoft.Extensions.Logging; -using MediaBrowser.Model.Dlna; - -namespace Mono.Nat.Upnp -{ - public sealed class UpnpNatDevice : AbstractNatDevice, IEquatable - { - private EndPoint hostEndPoint; - private IPAddress localAddress; - private string serviceDescriptionUrl; - private string controlUrl; - private string serviceType; - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - - public override IPAddress LocalAddress - { - get { return localAddress; } - } - - internal UpnpNatDevice(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint hostEndPoint, string serviceType, ILogger logger, IHttpClient httpClient) - { - if (localAddress == null) - { - throw new ArgumentNullException(nameof(localAddress)); - } - - this.LastSeen = DateTime.Now; - this.localAddress = localAddress; - - // Split the string at the "location" section so i can extract the ipaddress and service description url - string locationDetails = deviceInfo.Location.ToString(); - this.serviceType = serviceType; - _logger = logger; - _httpClient = httpClient; - - // Make sure we have no excess whitespace - locationDetails = locationDetails.Trim(); - - // FIXME: Is this reliable enough. What if we get a hostname as opposed to a proper http address - // Are we going to get addresses with the "http://" attached? - if (locationDetails.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) - { - _logger.LogDebug("Found device at: {0}", locationDetails); - // This bit strings out the "http://" from the string - locationDetails = locationDetails.Substring(7); - - this.hostEndPoint = hostEndPoint; - - // The service description URL is the remainder of the "locationDetails" string. The bit that was originally after the ip - // and port information - this.serviceDescriptionUrl = locationDetails.Substring(locationDetails.IndexOf('/')); - } - else - { - _logger.LogDebug("Couldn't decode address. Please send following string to the developer: "); - } - } - - public async Task GetServicesList() - { - // Create a HTTPWebRequest to download the list of services the device offers - var message = new GetServicesMessage(this.serviceDescriptionUrl, this.hostEndPoint); - - using (var response = await _httpClient.SendAsync(message.Encode(), message.Method).ConfigureAwait(false)) - { - OnServicesReceived(response); - } - } - - private void OnServicesReceived(HttpResponseInfo response) - { - int abortCount = 0; - int bytesRead = 0; - byte[] buffer = new byte[10240]; - var servicesXml = new StringBuilder(); - var xmldoc = new XmlDocument(); - - using (var s = response.Content) - { - if (response.StatusCode != HttpStatusCode.OK) - { - _logger.LogDebug("{0}: Couldn't get services list: {1}", HostEndPoint, response.StatusCode); - return; // FIXME: This the best thing to do?? - } - - while (true) - { - bytesRead = s.Read(buffer, 0, buffer.Length); - servicesXml.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead)); - try - { - xmldoc.LoadXml(servicesXml.ToString()); - break; - } - catch (XmlException) - { - // If we can't receive the entire XML within 500ms, then drop the connection - // Unfortunately not all routers supply a valid ContentLength (mine doesn't) - // so this hack is needed to keep testing our recieved data until it gets successfully - // parsed by the xmldoc. Without this, the code will never pick up my router. - if (abortCount++ > 50) - { - return; - } - _logger.LogDebug("{0}: Couldn't parse services list", HostEndPoint); - System.Threading.Thread.Sleep(10); - } - } - - var ns = new XmlNamespaceManager(xmldoc.NameTable); - ns.AddNamespace("ns", "urn:schemas-upnp-org:device-1-0"); - XmlNodeList nodes = xmldoc.SelectNodes("//*/ns:serviceList", ns); - - foreach (XmlNode node in nodes) - { - //Go through each service there - foreach (XmlNode service in node.ChildNodes) - { - //If the service is a WANIPConnection, then we have what we want - string type = service["serviceType"].InnerText; - _logger.LogDebug("{0}: Found service: {1}", HostEndPoint, type); - - // TODO: Add support for version 2 of UPnP. - if (string.Equals(type, "urn:schemas-upnp-org:service:WANPPPConnection:1", StringComparison.OrdinalIgnoreCase) || - string.Equals(type, "urn:schemas-upnp-org:service:WANIPConnection:1", StringComparison.OrdinalIgnoreCase)) - { - this.controlUrl = service["controlURL"].InnerText; - _logger.LogDebug("{0}: Found upnp service at: {1}", HostEndPoint, controlUrl); - - Uri u; - if (Uri.TryCreate(controlUrl, UriKind.RelativeOrAbsolute, out u)) - { - if (u.IsAbsoluteUri) - { - var old = hostEndPoint; - IPAddress parsedHostIpAddress; - if (IPAddress.TryParse(u.Host, out parsedHostIpAddress)) - { - this.hostEndPoint = new IPEndPoint(parsedHostIpAddress, u.Port); - //_logger.LogDebug("{0}: Absolute URI detected. Host address is now: {1}", old, HostEndPoint); - this.controlUrl = controlUrl.Substring(u.GetLeftPart(UriPartial.Authority).Length); - //_logger.LogDebug("{0}: New control url: {1}", HostEndPoint, controlUrl); - } - } - } - else - { - _logger.LogDebug("{0}: Assuming control Uri is relative: {1}", HostEndPoint, controlUrl); - } - return; - } - } - } - - //If we get here, it means that we didn't get WANIPConnection service, which means no uPnP forwarding - //So we don't invoke the callback, so this device is never added to our lists - } - } - - /// - /// The EndPoint that the device is at - /// - internal EndPoint HostEndPoint - { - get { return this.hostEndPoint; } - } - - /// - /// The relative url of the xml file that describes the list of services is at - /// - internal string ServiceDescriptionUrl - { - get { return this.serviceDescriptionUrl; } - } - - /// - /// The relative url that we can use to control the port forwarding - /// - internal string ControlUrl - { - get { return this.controlUrl; } - } - - /// - /// The service type we're using on the device - /// - public string ServiceType - { - get { return serviceType; } - } - - public override async Task CreatePortMap(Mapping mapping) - { - var message = new CreatePortMappingMessage(mapping, localAddress, this); - using (await _httpClient.SendAsync(message.Encode(), message.Method).ConfigureAwait(false)) - { - - } - } - - public override bool Equals(object obj) - { - var device = obj as UpnpNatDevice; - return (device == null) ? false : this.Equals((device)); - } - - - public bool Equals(UpnpNatDevice other) - { - return (other == null) ? false : (this.hostEndPoint.Equals(other.hostEndPoint) - //&& this.controlUrl == other.controlUrl - && this.serviceDescriptionUrl == other.serviceDescriptionUrl); - } - - public override int GetHashCode() - { - return (this.hostEndPoint.GetHashCode() ^ this.controlUrl.GetHashCode() ^ this.serviceDescriptionUrl.GetHashCode()); - } - - /// - /// Overridden. - /// - /// - public override string ToString() - { - //GetExternalIP is blocking and can throw exceptions, can't use it here. - return String.Format( - "UpnpNatDevice - EndPoint: {0}, External IP: {1}, Control Url: {2}, Service Description Url: {3}, Service Type: {4}, Last Seen: {5}", - this.hostEndPoint, "Manually Check" /*this.GetExternalIP()*/, this.controlUrl, this.serviceDescriptionUrl, this.serviceType, this.LastSeen); - } - } -} -- cgit v1.2.3 From 558baeac48abfe6ee82b94cb2ee664160677c8c7 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 1 Nov 2019 21:25:37 +0100 Subject: Add docs --- .../EntryPoints/ExternalPortForwarding.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 2f3d2c2888..7cf850932f 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -14,6 +14,9 @@ using Mono.Nat; namespace Emby.Server.Implementations.EntryPoints { + /// + /// Server entrypoint handling external port forwarding. + /// public class ExternalPortForwarding : IServerEntryPoint { private readonly IServerApplicationHost _appHost; @@ -21,14 +24,20 @@ namespace Emby.Server.Implementations.EntryPoints private readonly IServerConfigurationManager _config; private readonly IDeviceDiscovery _deviceDiscovery; - private Timer _timer; - private readonly object _createdRulesLock = new object(); private List _createdRules = new List(); + private Timer _timer; private string _lastConfigIdentifier; private bool _disposed = false; + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The application host. + /// The configuration manager. + /// The device discovery. public ExternalPortForwarding( ILogger logger, IServerApplicationHost appHost, @@ -66,6 +75,7 @@ namespace Emby.Server.Implementations.EntryPoints } } + /// public Task RunAsync() { if (_config.Configuration.EnableUPnP && _config.Configuration.EnableRemoteAccess) -- cgit v1.2.3 From 210af0e73e6370b037105ed89776e86217fb873a Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 2 Nov 2019 10:31:14 +0100 Subject: Properly remove event handler --- .../EntryPoints/ExternalPortForwarding.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 7cf850932f..08041eb59f 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -65,23 +65,20 @@ namespace Emby.Server.Implementations.EntryPoints .ToString(); } - private async void OnConfigurationUpdated(object sender, EventArgs e) + private void OnConfigurationUpdated(object sender, EventArgs e) { if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) { Stop(); - await RunAsync().ConfigureAwait(false); + Start(); } } /// public Task RunAsync() { - if (_config.Configuration.EnableUPnP && _config.Configuration.EnableRemoteAccess) - { - Start(); - } + Start(); _config.ConfigurationUpdated += OnConfigurationUpdated; @@ -90,6 +87,11 @@ namespace Emby.Server.Implementations.EntryPoints private void Start() { + if (!_config.Configuration.EnableUPnP || !_config.Configuration.EnableRemoteAccess) + { + return; + } + _logger.LogDebug("Starting NAT discovery"); NatUtility.DeviceFound += OnNatUtilityDeviceFound; @@ -214,6 +216,8 @@ namespace Emby.Server.Implementations.EntryPoints return; } + _config.ConfigurationUpdated -= OnConfigurationUpdated; + Stop(); _timer = null; -- cgit v1.2.3 From 37eed8cf1f024b8de19c851fd353322d706c2b27 Mon Sep 17 00:00:00 2001 From: dkanada Date: Thu, 21 Nov 2019 21:51:17 +0900 Subject: revert settings to their old names --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../Configuration/ServerConfigurationManager.cs | 4 ++-- .../EntryPoints/LibraryChangedNotifier.cs | 13 ++++++++----- .../Configuration/EncodingConfigurationFactory.cs | 4 ++-- MediaBrowser.Model/Configuration/EncodingOptions.cs | 2 +- MediaBrowser.Model/System/SystemInfo.cs | 6 +++--- 6 files changed, 17 insertions(+), 14 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 9adbe90348..3a607aa54c 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1447,7 +1447,7 @@ namespace Emby.Server.Implementations CanSelfRestart = CanSelfRestart, CanLaunchWebBrowser = CanLaunchWebBrowser, HasUpdateAvailable = HasUpdateAvailable, - TranscodePath = ApplicationPaths.TranscodePath, + TranscodingTempPath = ApplicationPaths.TranscodePath, ServerName = FriendlyName, LocalAddress = localAddress, SupportsLibraryMonitor = true, diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index 2bd1b43619..fe705cbe27 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -91,9 +91,9 @@ namespace Emby.Server.Implementations.Configuration { var encodingConfig = this.GetConfiguration("encoding"); - ((ServerApplicationPaths)ApplicationPaths).TranscodePath = string.IsNullOrEmpty(encodingConfig.TranscodePath) ? + ((ServerApplicationPaths)ApplicationPaths).TranscodePath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ? null : - Path.Combine(encodingConfig.TranscodePath, "transcodes"); + Path.Combine(encodingConfig.TranscodingTempPath, "transcodes"); } protected override void OnNamedConfigurationUpdated(string key, object configuration) diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 9c0db2cf5e..7bef2ae581 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.EntryPoints public class LibraryChangedNotifier : IServerEntryPoint { /// - /// The _library manager + /// The library manager. /// private readonly ILibraryManager _libraryManager; @@ -30,7 +30,7 @@ namespace Emby.Server.Implementations.EntryPoints private readonly ILogger _logger; /// - /// The _library changed sync lock + /// The library changed sync lock. /// private readonly object _libraryChangedSyncLock = new object(); @@ -48,7 +48,7 @@ namespace Emby.Server.Implementations.EntryPoints private Timer LibraryUpdateTimer { get; set; } /// - /// The library update duration + /// The library update duration. /// private const int LibraryUpdateDuration = 30000; @@ -188,8 +188,11 @@ namespace Emby.Server.Implementations.EntryPoints { if (LibraryUpdateTimer == null) { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, - Timeout.Infinite); + LibraryUpdateTimer = new Timer( + LibraryUpdateTimerCallback, + null, + LibraryUpdateDuration, + Timeout.Infinite); } else { diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs index 857add4cb8..bb806ee55c 100644 --- a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs @@ -40,10 +40,10 @@ namespace MediaBrowser.MediaEncoding.Configuration var oldEncodingConfig = (EncodingOptions)oldConfig; var newEncodingConfig = (EncodingOptions)newConfig; - var newPath = newEncodingConfig.TranscodePath; + var newPath = newEncodingConfig.TranscodingTempPath; if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(oldEncodingConfig.TranscodePath ?? string.Empty, newPath)) + && !string.Equals(oldEncodingConfig.TranscodingTempPath ?? string.Empty, newPath)) { // Validate if (!Directory.Exists(newPath)) diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 795ef1736f..9ae10d9809 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -3,7 +3,7 @@ namespace MediaBrowser.Model.Configuration public class EncodingOptions { public int EncodingThreadCount { get; set; } - public string TranscodePath { get; set; } + public string TranscodingTempPath { get; set; } public double DownMixAudioBoost { get; set; } public bool EnableThrottling { get; set; } public int ThrottleDelaySeconds { get; set; } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 2e5e65690e..7014a5c87c 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -110,10 +110,10 @@ namespace MediaBrowser.Model.System public string InternalMetadataPath { get; set; } /// - /// Gets or sets the transcoding temporary path. + /// Gets or sets the transcode path. /// - /// The transcoding temporary path. - public string TranscodePath { get; set; } + /// The transcode path. + public string TranscodingTempPath { get; set; } /// /// Gets or sets the HTTP server port number. -- cgit v1.2.3 From b477b3874ef8d79a1e27f8bb298d38443c3ec425 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Fri, 25 Oct 2019 12:47:20 +0200 Subject: Fix some warnings --- Emby.Naming/AudioBook/AudioBookFileInfo.cs | 2 +- Emby.Naming/AudioBook/AudioBookInfo.cs | 2 +- Emby.Naming/TV/SeasonPathParser.cs | 4 +-- Emby.Naming/Video/CleanDateTimeParser.cs | 2 +- Emby.Naming/Video/VideoFileInfo.cs | 2 +- Emby.Naming/Video/VideoInfo.cs | 2 +- Emby.Naming/Video/VideoResolver.cs | 2 +- .../Activity/ActivityLogEntryPoint.cs | 4 +-- .../AppBase/BaseConfigurationManager.cs | 8 +++--- .../AppBase/ConfigurationHelper.cs | 4 +-- Emby.Server.Implementations/ApplicationHost.cs | 6 ++-- .../Channels/ChannelManager.cs | 4 +-- .../Collections/CollectionManager.cs | 2 +- .../Data/SqliteItemRepository.cs | 2 +- .../Devices/DeviceManager.cs | 1 - .../EntryPoints/ExternalPortForwarding.cs | 1 - .../EntryPoints/LibraryChangedNotifier.cs | 2 +- .../EntryPoints/ServerEventNotifier.cs | 2 +- .../HttpClientManager/HttpClientManager.cs | 2 +- .../HttpServer/HttpResultFactory.cs | 2 +- .../HttpServer/RangeRequestWriter.cs | 4 ++- .../Library/SearchEngine.cs | 2 +- .../Library/Validators/ArtistsValidator.cs | 3 +- .../Library/Validators/GenresPostScanTask.cs | 5 ++-- .../Library/Validators/MusicGenresPostScanTask.cs | 3 +- .../Library/Validators/StudiosPostScanTask.cs | 4 ++- .../LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 10 +++---- .../LiveTv/RefreshChannelsScheduledTask.cs | 4 +-- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 6 ++-- .../Localization/LocalizationManager.cs | 2 -- .../Middleware/WebSocketMiddleware.cs | 4 +-- .../Networking/NetworkManager.cs | 18 ++++++++---- .../Playlists/ManualPlaylistsFolder.cs | 1 - .../ScheduledTasks/ScheduledTaskWorker.cs | 9 +++--- .../ScheduledTasks/TaskManager.cs | 32 +++++++++++----------- .../ScheduledTasks/Triggers/DailyTrigger.cs | 5 ++-- .../Services/ServicePath.cs | 16 +++++++---- .../Services/SwaggerService.cs | 4 +-- .../Session/HttpSessionController.cs | 2 +- .../SocketSharp/SharpWebSocket.cs | 2 +- .../SocketSharp/WebSocketSharpListener.cs | 6 ++-- .../SocketSharp/WebSocketSharpRequest.cs | 3 +- .../Sorting/NameComparer.cs | 4 +++ .../Sorting/OfficialRatingComparer.cs | 4 +++ .../Sorting/StudioComparer.cs | 5 ++++ .../WebSockets/WebSocketManager.cs | 10 ++++--- MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 +- 48 files changed, 128 insertions(+), 100 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Naming/AudioBook/AudioBookFileInfo.cs b/Emby.Naming/AudioBook/AudioBookFileInfo.cs index 326ea05ef3..769e3d7fac 100644 --- a/Emby.Naming/AudioBook/AudioBookFileInfo.cs +++ b/Emby.Naming/AudioBook/AudioBookFileInfo.cs @@ -3,7 +3,7 @@ using System; namespace Emby.Naming.AudioBook { /// - /// Represents a single video file + /// Represents a single video file. /// public class AudioBookFileInfo : IComparable { diff --git a/Emby.Naming/AudioBook/AudioBookInfo.cs b/Emby.Naming/AudioBook/AudioBookInfo.cs index 600d3f05da..d53f53c528 100644 --- a/Emby.Naming/AudioBook/AudioBookInfo.cs +++ b/Emby.Naming/AudioBook/AudioBookInfo.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace Emby.Naming.AudioBook { /// - /// Represents a complete video, including all parts and subtitles + /// Represents a complete video, including all parts and subtitles. /// public class AudioBookInfo { diff --git a/Emby.Naming/TV/SeasonPathParser.cs b/Emby.Naming/TV/SeasonPathParser.cs index 9096ccaf5d..f34faf8e83 100644 --- a/Emby.Naming/TV/SeasonPathParser.cs +++ b/Emby.Naming/TV/SeasonPathParser.cs @@ -25,7 +25,7 @@ namespace Emby.Naming.TV } /// - /// A season folder must contain one of these somewhere in the name + /// A season folder must contain one of these somewhere in the name. /// private static readonly string[] _seasonFolderNames = { @@ -124,7 +124,7 @@ namespace Emby.Naming.TV } /// - /// Extracts the season number from the second half of the Season folder name (everything after "Season", or "Staffel") + /// Extracts the season number from the second half of the Season folder name (everything after "Season", or "Staffel"). /// /// The path. /// System.Nullable{System.Int32}. diff --git a/Emby.Naming/Video/CleanDateTimeParser.cs b/Emby.Naming/Video/CleanDateTimeParser.cs index 25fa09c488..c6b6039d4d 100644 --- a/Emby.Naming/Video/CleanDateTimeParser.cs +++ b/Emby.Naming/Video/CleanDateTimeParser.cs @@ -8,7 +8,7 @@ using Emby.Naming.Common; namespace Emby.Naming.Video { /// - /// http://kodi.wiki/view/Advancedsettings.xml#video + /// . /// public class CleanDateTimeParser { diff --git a/Emby.Naming/Video/VideoFileInfo.cs b/Emby.Naming/Video/VideoFileInfo.cs index 78f688ca8a..2f42f77845 100644 --- a/Emby.Naming/Video/VideoFileInfo.cs +++ b/Emby.Naming/Video/VideoFileInfo.cs @@ -1,7 +1,7 @@ namespace Emby.Naming.Video { /// - /// Represents a single video file + /// Represents a single video file. /// public class VideoFileInfo { diff --git a/Emby.Naming/Video/VideoInfo.cs b/Emby.Naming/Video/VideoInfo.cs index 2e456bda2b..f576b6ca28 100644 --- a/Emby.Naming/Video/VideoInfo.cs +++ b/Emby.Naming/Video/VideoInfo.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace Emby.Naming.Video { /// - /// Represents a complete video, including all parts and subtitles + /// Represents a complete video, including all parts and subtitles. /// public class VideoInfo { diff --git a/Emby.Naming/Video/VideoResolver.cs b/Emby.Naming/Video/VideoResolver.cs index 02a25c4b5b..91f443500f 100644 --- a/Emby.Naming/Video/VideoResolver.cs +++ b/Emby.Naming/Video/VideoResolver.cs @@ -41,7 +41,7 @@ namespace Emby.Naming.Video /// if set to true [is folder]. /// Whether or not the name should be parsed for info /// VideoFileInfo. - /// path + /// path is null. public VideoFileInfo Resolve(string path, bool isDirectory, bool parseName = true) { if (string.IsNullOrEmpty(path)) diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 1514402d68..efaaa116c6 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -616,8 +616,8 @@ namespace Emby.Server.Implementations.Activity /// /// Constructs a string description of a time-span value. /// - /// The value of this item - /// The name of this item (singular form) + /// The value of this item. + /// The name of this item (singular form). private static string CreateValueString(int value, string description) { return string.Format( diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 7ec5252d07..0b7c35f3e9 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -16,7 +16,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.AppBase { /// - /// Class BaseConfigurationManager + /// Class BaseConfigurationManager. /// public abstract class BaseConfigurationManager : IConfigurationManager { @@ -48,7 +48,7 @@ namespace Emby.Server.Implementations.AppBase /// The application paths. /// The logger factory. /// The XML serializer. - /// The file system + /// The file system. protected BaseConfigurationManager(IApplicationPaths applicationPaths, ILoggerFactory loggerFactory, IXmlSerializer xmlSerializer, IFileSystem fileSystem) { CommonApplicationPaths = applicationPaths; @@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.AppBase protected IXmlSerializer XmlSerializer { get; private set; } /// - /// Gets or sets the application paths. + /// Gets the application paths. /// /// The application paths. public IApplicationPaths CommonApplicationPaths { get; private set; } @@ -173,7 +173,7 @@ namespace Emby.Server.Implementations.AppBase /// Replaces the configuration. /// /// The new configuration. - /// newConfiguration + /// newConfiguration is null. public virtual void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration) { if (newConfiguration == null) diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 90b97061f3..854d7b4cbf 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -6,13 +6,13 @@ using MediaBrowser.Model.Serialization; namespace Emby.Server.Implementations.AppBase { /// - /// Class ConfigurationHelper + /// Class ConfigurationHelper. /// public static class ConfigurationHelper { /// /// Reads an xml configuration file from the file system - /// It will immediately re-serialize and save if new serialization data is available due to property changes + /// It will immediately re-serialize and save if new serialization data is available due to property changes. /// /// The type. /// The path. diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 120a5adc48..1bacd8aef2 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -321,7 +321,7 @@ namespace Emby.Server.Implementations private readonly IConfiguration _configuration; /// - /// Gets or sets the installation manager. + /// Gets the installation manager. /// /// The installation manager. protected IInstallationManager InstallationManager { get; private set; } @@ -500,7 +500,7 @@ namespace Emby.Server.Implementations /// /// Gets the export types. /// - /// The type + /// The type. /// IEnumerable{Type}. public IEnumerable GetExportTypes() { @@ -1022,7 +1022,7 @@ namespace Emby.Server.Implementations } /// - /// Dirty hacks + /// Dirty hacks. /// private void SetStaticProperties() { diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 22681fb499..151670074a 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -473,7 +473,7 @@ namespace Emby.Server.Implementations.Channels await item.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { ForceSave = !isNew && forceUpdate - }, cancellationToken); + }, cancellationToken).ConfigureAwait(false); return item; } @@ -636,7 +636,7 @@ namespace Emby.Server.Implementations.Channels private async Task RefreshLatestChannelItems(IChannel channel, CancellationToken cancellationToken) { - var internalChannel = await GetChannel(channel, cancellationToken); + var internalChannel = await GetChannel(channel, cancellationToken).ConfigureAwait(false); var query = new InternalItemsQuery(); query.Parent = internalChannel; diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 6d414be739..c5a77ce5b5 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -121,7 +121,7 @@ namespace Emby.Server.Implementations.Collections // This could cause it to get re-resolved as a plain folder var folderName = _fileSystem.GetValidFilename(name) + " [boxset]"; - var parentFolder = GetCollectionsFolder(true).Result; + var parentFolder = GetCollectionsFolder(true).GetAwaiter().GetResult(); if (parentFolder == null) { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 65f8a915f9..8d509f6888 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1177,7 +1177,7 @@ namespace Emby.Server.Implementations.Data { if (id == Guid.Empty) { - throw new ArgumentException(nameof(id), "Guid can't be empty"); + throw new ArgumentException("Guid can't be empty", nameof(id)); } CheckDisposed(); diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index d1704b3736..36d4418512 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -130,7 +130,6 @@ namespace Emby.Server.Implementations.Devices var session = _authRepo.Get(new AuthenticationInfoQuery { DeviceId = id - }).Items.FirstOrDefault(); var device = session == null ? null : ToDeviceInfo(session); diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 08041eb59f..a2619367d5 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -70,7 +70,6 @@ namespace Emby.Server.Implementations.EntryPoints if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) { Stop(); - Start(); } } diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 7bef2ae581..24906220d1 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -455,7 +455,7 @@ namespace Emby.Server.Implementations.EntryPoints return new[] { item }; } - return new T[] { }; + return Array.Empty(); } /// diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 141e729584..3ff8d99685 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -156,7 +156,7 @@ namespace Emby.Server.Implementations.EntryPoints { try { - await _sessionManager.SendMessageToAdminSessions(name, data, CancellationToken.None); + await _sessionManager.SendMessageToAdminSessions(name, data, CancellationToken.None).ConfigureAwait(false); } catch (Exception) { diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index 0e6083773d..810b46200d 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -325,7 +325,7 @@ namespace Emby.Server.Implementations.HttpClientManager if (options.LogErrorResponseBody) { - var msg = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + string msg = await response.Content.ReadAsStringAsync().ConfigureAwait(false); _logger.LogError("HTTP request failed with message: {Message}", msg); } diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index 0b2924a3ba..b5cfb6b09a 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -460,7 +460,7 @@ namespace Emby.Server.Implementations.HttpServer if (string.IsNullOrEmpty(path)) { - throw new ArgumentNullException(nameof(path)); + throw new ArgumentException("Path can't be empty.", nameof(options)); } if (fileShare != FileShareMode.Read && fileShare != FileShareMode.ReadWrite) diff --git a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs index e27f794ba6..320136d11a 100644 --- a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs @@ -48,12 +48,14 @@ namespace Emby.Server.Implementations.HttpServer public IDictionary Headers => _options; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The range header. + /// The content length. /// The source. /// Type of the content. /// if set to true [is head request]. + /// The logger instance. public RangeRequestWriter(string rangeHeader, long contentLength, Stream source, string contentType, bool isHeadRequest, ILogger logger) { if (string.IsNullOrEmpty(contentType)) diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 9c7f7dfcb1..6783b07eb8 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.Library if (string.IsNullOrEmpty(searchTerm)) { - throw new ArgumentNullException(nameof(searchTerm)); + throw new ArgumentNullException("SearchTerm can't be empty.", nameof(searchTerm)); } searchTerm = searchTerm.Trim().RemoveDiacritics(); diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs index b584cc649d..d06cda177f 100644 --- a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs @@ -28,10 +28,11 @@ namespace Emby.Server.Implementations.Library.Validators private readonly IItemRepository _itemRepo; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The library manager. /// The logger. + /// The item repository. public ArtistsValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs index 0568073005..3bc5c2fb2a 100644 --- a/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs @@ -10,17 +10,18 @@ namespace Emby.Server.Implementations.Library.Validators public class GenresPostScanTask : ILibraryPostScanTask { /// - /// The _library manager + /// The _library manager. /// private readonly ILibraryManager _libraryManager; private readonly ILogger _logger; private readonly IItemRepository _itemRepo; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The library manager. /// The logger. + /// The item repository. public GenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs index d7ab92d306..9ac4bf7618 100644 --- a/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs @@ -20,10 +20,11 @@ namespace Emby.Server.Implementations.Library.Validators private readonly IItemRepository _itemRepo; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The library manager. /// The logger. + /// The item repository. public MusicGenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs index 4aa5c7e72a..2efae0fe44 100644 --- a/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs @@ -21,9 +21,11 @@ namespace Emby.Server.Implementations.Library.Validators private readonly IItemRepository _itemRepo; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The library manager. + /// The logger. + /// Th item repository. public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 687a178a68..ef5928e480 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (requiresRefresh) { - await _libraryManager.ValidateMediaLibrary(new SimpleProgress(), CancellationToken.None); + await _libraryManager.ValidateMediaLibrary(new SimpleProgress(), CancellationToken.None).ConfigureAwait(false); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 9a4c91d0bd..838ac97d77 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -501,7 +501,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings public async Task> GetHeadends(ListingsProviderInfo info, string country, string location, CancellationToken cancellationToken) { - var token = await GetToken(info, cancellationToken); + var token = await GetToken(info, cancellationToken).ConfigureAwait(false); var lineups = new List(); @@ -713,7 +713,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken) { - var token = await GetToken(info, cancellationToken); + var token = await GetToken(info, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(token)) { @@ -738,7 +738,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings httpOptions.RequestHeaders["token"] = token; - using (await _httpClient.SendAsync(httpOptions, "PUT")) + using (await _httpClient.SendAsync(httpOptions, "PUT").ConfigureAwait(false)) { } } @@ -750,7 +750,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings throw new ArgumentException("Listings Id required"); } - var token = await GetToken(info, cancellationToken); + var token = await GetToken(info, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(token)) { @@ -833,7 +833,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings throw new Exception("ListingsId required"); } - var token = await GetToken(info, cancellationToken); + var token = await GetToken(info, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(token)) { diff --git a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs index 542951de4a..1056a33b9a 100644 --- a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs +++ b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs @@ -38,8 +38,8 @@ namespace Emby.Server.Implementations.LiveTv /// IEnumerable{BaseTaskTrigger}. public IEnumerable GetDefaultTriggers() { - return new[] { - + return new[] + { // Every so often new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} }; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index da98f3e58b..f834566605 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -185,7 +185,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Url = string.Format("{0}/tuners.html", GetApiUrl(info)), CancellationToken = cancellationToken, BufferContent = false - }, HttpMethod.Get)) + }, HttpMethod.Get).ConfigureAwait(false)) using (var stream = response.Content) using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) { @@ -259,7 +259,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun for (int i = 0; i < model.TunerCount; ++i) { var name = string.Format("Tuner {0}", i + 1); - var currentChannel = "none"; /// @todo Get current channel and map back to Station Id + var currentChannel = "none"; // @todo Get current channel and map back to Station Id var isAvailable = await manager.CheckTunerAvailability(ipInfo, i, cancellationToken).ConfigureAwait(false); var status = isAvailable ? LiveTvTunerStatus.Available : LiveTvTunerStatus.LiveTv; tuners.Add(new LiveTvTunerInfo @@ -298,7 +298,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public async Task> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) { // TODO Need faster way to determine UDP vs HTTP - var channels = await GetChannels(info, true, cancellationToken); + var channels = await GetChannels(info, true, cancellationToken).ConfigureAwait(false); var hdHomerunChannelInfo = channels.FirstOrDefault() as HdHomerunChannelInfo; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 13cdc50ca4..bda43e832a 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -5,11 +5,9 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; -using System.Text; using System.Threading.Tasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Middleware/WebSocketMiddleware.cs b/Emby.Server.Implementations/Middleware/WebSocketMiddleware.cs index 268bf4042d..fda32da5e8 100644 --- a/Emby.Server.Implementations/Middleware/WebSocketMiddleware.cs +++ b/Emby.Server.Implementations/Middleware/WebSocketMiddleware.cs @@ -27,12 +27,12 @@ namespace Emby.Server.Implementations.Middleware var webSocketContext = await httpContext.WebSockets.AcceptWebSocketAsync(null).ConfigureAwait(false); if (webSocketContext != null) { - await _webSocketManager.OnWebSocketConnected(webSocketContext); + await _webSocketManager.OnWebSocketConnected(webSocketContext).ConfigureAwait(false); } } else { - await _next.Invoke(httpContext); + await _next.Invoke(httpContext).ConfigureAwait(false); } } } diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index d948dad688..098bd518e3 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -490,23 +490,25 @@ namespace Emby.Server.Implementations.Networking IPAddress ipaddy; int port = -1; - //check if we have an IPv6 or ports + // check if we have an IPv6 or ports if (values.Length <= 2) // ipv4 or hostname { port = values.Length == 1 ? defaultport : GetPort(values[1]); - //try to use the address as IPv4, otherwise get hostname + // try to use the address as IPv4, otherwise get hostname if (!IPAddress.TryParse(values[0], out ipaddy)) + { ipaddy = await GetIPfromHost(values[0]).ConfigureAwait(false); + } } - else if (values.Length > 2) //ipv6 + else if (values.Length > 2) // ipv6 { - //could [a:b:c]:d + //ncould [a:b:c]:d if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]")) { string ipaddressstring = string.Join(":", values.Take(values.Length - 1).ToArray()); ipaddy = IPAddress.Parse(ipaddressstring); - port = GetPort(values[values.Length - 1]); + port = GetPort(values[^1]); } else //[a:b:c] or a:b:c { @@ -516,7 +518,11 @@ namespace Emby.Server.Implementations.Networking } else { - throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", endpointstring)); + throw new FormatException( + string.Format( + CultureInfo.InvariantCulture, + "Invalid endpoint ipaddress '{0}'", + endpointstring)); } if (port == -1) diff --git a/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs index de51a37ab7..cd9f7946e9 100644 --- a/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs +++ b/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs @@ -48,4 +48,3 @@ namespace Emby.Server.Implementations.Playlists } } } - diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 83226b07f1..5b188d9626 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.ScheduledTasks public event EventHandler> TaskProgress; /// - /// Gets or sets the scheduled task. + /// Gets the scheduled task. /// /// The scheduled task. public IScheduledTask ScheduledTask { get; private set; } @@ -215,11 +215,12 @@ namespace Emby.Server.Implementations.ScheduledTasks public double? CurrentProgress { get; private set; } /// - /// The _triggers + /// The _triggers. /// private Tuple[] _triggers; + /// - /// Gets the triggers that define when the task will run + /// Gets the triggers that define when the task will run. /// /// The triggers. private Tuple[] InternalTriggers @@ -245,7 +246,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Gets the triggers that define when the task will run + /// Gets the triggers that define when the task will run. /// /// The triggers. /// value diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index 595c3037d7..ecf58dbc0e 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -36,19 +36,19 @@ namespace Emby.Server.Implementations.ScheduledTasks /// Gets or sets the json serializer. /// /// The json serializer. - private IJsonSerializer JsonSerializer { get; set; } + private readonly IJsonSerializer _jsonSerializer; /// /// Gets or sets the application paths. /// /// The application paths. - private IApplicationPaths ApplicationPaths { get; set; } + private readonly IApplicationPaths _applicationPaths; /// /// Gets the logger. /// /// The logger. - private ILogger Logger { get; set; } + private readonly ILogger _logger; private readonly IFileSystem _fileSystem; /// @@ -57,19 +57,19 @@ namespace Emby.Server.Implementations.ScheduledTasks /// The application paths. /// The json serializer. /// The logger factory. - /// kernel + /// The filesystem manager. public TaskManager( IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory, IFileSystem fileSystem) { - ApplicationPaths = applicationPaths; - JsonSerializer = jsonSerializer; - Logger = loggerFactory.CreateLogger(nameof(TaskManager)); + _applicationPaths = applicationPaths; + _jsonSerializer = jsonSerializer; + _logger = loggerFactory.CreateLogger(nameof(TaskManager)); _fileSystem = fileSystem; - ScheduledTasks = new IScheduledTaskWorker[] { }; + ScheduledTasks = Array.Empty(); } /// @@ -78,7 +78,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// Task options. public void CancelIfRunningAndQueue(TaskOptions options) - where T : IScheduledTask + where T : IScheduledTask { var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T)); ((ScheduledTaskWorker)task).CancelIfRunning(); @@ -115,7 +115,7 @@ namespace Emby.Server.Implementations.ScheduledTasks if (scheduledTask == null) { - Logger.LogError("Unable to find scheduled task of type {0} in QueueScheduledTask.", typeof(T).Name); + _logger.LogError("Unable to find scheduled task of type {0} in QueueScheduledTask.", typeof(T).Name); } else { @@ -147,13 +147,13 @@ namespace Emby.Server.Implementations.ScheduledTasks if (scheduledTask == null) { - Logger.LogError("Unable to find scheduled task of type {0} in Execute.", typeof(T).Name); + _logger.LogError("Unable to find scheduled task of type {0} in Execute.", typeof(T).Name); } else { var type = scheduledTask.ScheduledTask.GetType(); - Logger.LogInformation("Queueing task {0}", type.Name); + _logger.LogInformation("Queueing task {0}", type.Name); lock (_taskQueue) { @@ -176,7 +176,7 @@ namespace Emby.Server.Implementations.ScheduledTasks if (scheduledTask == null) { - Logger.LogError("Unable to find scheduled task of type {0} in QueueScheduledTask.", task.GetType().Name); + _logger.LogError("Unable to find scheduled task of type {0} in QueueScheduledTask.", task.GetType().Name); } else { @@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { var type = task.ScheduledTask.GetType(); - Logger.LogInformation("Queueing task {0}", type.Name); + _logger.LogInformation("Queueing task {0}", type.Name); lock (_taskQueue) { @@ -213,7 +213,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// The tasks. public void AddTasks(IEnumerable tasks) { - var list = tasks.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem)); + var list = tasks.Select(t => new ScheduledTaskWorker(t, _applicationPaths, this, _jsonSerializer, _logger, _fileSystem)); ScheduledTasks = ScheduledTasks.Concat(list).ToArray(); } @@ -281,7 +281,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// private void ExecuteQueuedTasks() { - Logger.LogInformation("ExecuteQueuedTasks"); + _logger.LogInformation("ExecuteQueuedTasks"); // Execute queued tasks lock (_taskQueue) diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs index ec9466c4ab..ea278de0d9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using System.Threading; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; @@ -7,12 +6,12 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.ScheduledTasks { /// - /// Represents a task trigger that fires everyday + /// Represents a task trigger that fires everyday. /// public class DailyTrigger : ITaskTrigger { /// - /// Get the time of day to trigger the task to run + /// Get the time of day to trigger the task to run. /// /// The time of day. public TimeSpan TimeOfDay { get; set; } diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index 0b67669b94..27c4dcba07 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Reflection; @@ -45,8 +46,8 @@ namespace Emby.Server.Implementations.Services public int PathComponentsCount { get; set; } /// - /// The total number of segments after subparts have been exploded ('.') - /// e.g. /path/to/here.ext == 4 + /// Gets or sets the total number of segments after subparts have been exploded ('.') + /// e.g. /path/to/here.ext == 4. /// public int TotalComponentsCount { get; set; } @@ -279,7 +280,7 @@ namespace Emby.Server.Implementations.Services } /// - /// Provide for quick lookups based on hashes that can be determined from a request url + /// Provide for quick lookups based on hashes that can be determined from a request url. /// public string FirstMatchHashKey { get; private set; } @@ -436,9 +437,12 @@ namespace Emby.Server.Implementations.Services && requestComponents.Length >= this.TotalComponentsCount - this.wildcardCount; if (!isValidWildCardPath) - throw new ArgumentException(string.Format( - "Path Mismatch: Request Path '{0}' has invalid number of components compared to: '{1}'", - pathInfo, this.restPath)); + throw new ArgumentException( + string.Format( + CultureInfo.InvariantCulture, + "Path Mismatch: Request Path '{0}' has invalid number of components compared to: '{1}'", + pathInfo, + this.restPath)); } var requestKeyValuesMap = new Dictionary(); diff --git a/Emby.Server.Implementations/Services/SwaggerService.cs b/Emby.Server.Implementations/Services/SwaggerService.cs index d223864364..c30f32af94 100644 --- a/Emby.Server.Implementations/Services/SwaggerService.cs +++ b/Emby.Server.Implementations/Services/SwaggerService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using MediaBrowser.Controller.Net; @@ -175,7 +175,7 @@ namespace Emby.Server.Implementations.Services private SwaggerTag[] GetTags() { - return new SwaggerTag[] { }; + return Array.Empty(); } private Dictionary GetDefinitions() diff --git a/Emby.Server.Implementations/Session/HttpSessionController.cs b/Emby.Server.Implementations/Session/HttpSessionController.cs index 1104a7a85b..dfb81816c7 100644 --- a/Emby.Server.Implementations/Session/HttpSessionController.cs +++ b/Emby.Server.Implementations/Session/HttpSessionController.cs @@ -105,7 +105,7 @@ namespace Emby.Server.Implementations.Session return SendMessage(command.Command.ToString(), messageId, args, cancellationToken); } - private string[] _supportedMessages = new string[] { }; + private string[] _supportedMessages = Array.Empty(); public Task SendMessage(string name, string messageId, T data, ISessionController[] allControllers, CancellationToken cancellationToken) { if (!IsSessionActive) diff --git a/Emby.Server.Implementations/SocketSharp/SharpWebSocket.cs b/Emby.Server.Implementations/SocketSharp/SharpWebSocket.cs index 62b16ed8c8..67521d6c63 100644 --- a/Emby.Server.Implementations/SocketSharp/SharpWebSocket.cs +++ b/Emby.Server.Implementations/SocketSharp/SharpWebSocket.cs @@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.SocketSharp } /// - /// Gets or sets the state. + /// Gets the state. /// /// The state. public WebSocketState State => _webSocket.State; diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs index e93bff1244..ba5ba1904c 100644 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs +++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs @@ -81,8 +81,10 @@ namespace Emby.Server.Implementations.SocketSharp if (webSocketContext.State == WebSocketState.Open) { - await webSocketContext.CloseAsync(result.CloseStatus ?? WebSocketCloseStatus.NormalClosure, - result.CloseStatusDescription, _disposeCancellationToken); + await webSocketContext.CloseAsync( + result.CloseStatus ?? WebSocketCloseStatus.NormalClosure, + result.CloseStatusDescription, + _disposeCancellationToken).ConfigureAwait(false); } socket.Dispose(); diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs index 332ce39034..690ba0be4a 100644 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs +++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Net; -using System.Linq; using MediaBrowser.Common.Net; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; @@ -13,7 +12,7 @@ using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest; namespace Emby.Server.Implementations.SocketSharp { - public partial class WebSocketSharpRequest : IHttpRequest + public class WebSocketSharpRequest : IHttpRequest { public const string FormUrlEncoded = "application/x-www-form-urlencoded"; public const string MultiPartFormData = "multipart/form-data"; diff --git a/Emby.Server.Implementations/Sorting/NameComparer.cs b/Emby.Server.Implementations/Sorting/NameComparer.cs index 10fa4359aa..4eb1549f58 100644 --- a/Emby.Server.Implementations/Sorting/NameComparer.cs +++ b/Emby.Server.Implementations/Sorting/NameComparer.cs @@ -19,10 +19,14 @@ namespace Emby.Server.Implementations.Sorting public int Compare(BaseItem x, BaseItem y) { if (x == null) + { throw new ArgumentNullException(nameof(x)); + } if (y == null) + { throw new ArgumentNullException(nameof(y)); + } return string.Compare(x.Name, y.Name, StringComparison.CurrentCultureIgnoreCase); } diff --git a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs index e8fa8edc8e..7afbd9ff7d 100644 --- a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs @@ -24,10 +24,14 @@ namespace Emby.Server.Implementations.Sorting public int Compare(BaseItem x, BaseItem y) { if (x == null) + { throw new ArgumentNullException(nameof(x)); + } if (y == null) + { throw new ArgumentNullException(nameof(y)); + } var levelX = string.IsNullOrEmpty(x.OfficialRating) ? 0 : _localization.GetRatingLevel(x.OfficialRating) ?? 0; var levelY = string.IsNullOrEmpty(y.OfficialRating) ? 0 : _localization.GetRatingLevel(y.OfficialRating) ?? 0; diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index 617ed55d52..c9ac765c10 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -17,10 +17,15 @@ namespace Emby.Server.Implementations.Sorting public int Compare(BaseItem x, BaseItem y) { if (x == null) + { throw new ArgumentNullException(nameof(x)); + } if (y == null) + { throw new ArgumentNullException(nameof(y)); + } + return AlphanumComparator.CompareValues(x.Studios.FirstOrDefault() ?? string.Empty, y.Studios.FirstOrDefault() ?? string.Empty); } diff --git a/Emby.Server.Implementations/WebSockets/WebSocketManager.cs b/Emby.Server.Implementations/WebSockets/WebSocketManager.cs index 04c73ecea7..efd97e4ff1 100644 --- a/Emby.Server.Implementations/WebSockets/WebSocketManager.cs +++ b/Emby.Server.Implementations/WebSockets/WebSocketManager.cs @@ -39,12 +39,12 @@ namespace Emby.Server.Implementations.WebSockets do { var buffer = WebSocket.CreateServerBuffer(BufferSize); - result = await webSocket.ReceiveAsync(buffer, cancellationToken); + result = await webSocket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false); message.AddRange(buffer.Array.Take(result.Count)); if (result.EndOfMessage) { - await ProcessMessage(message.ToArray(), taskCompletionSource); + await ProcessMessage(message.ToArray(), taskCompletionSource).ConfigureAwait(false); message.Clear(); } } while (!taskCompletionSource.Task.IsCompleted && @@ -53,8 +53,10 @@ namespace Emby.Server.Implementations.WebSockets if (webSocket.State == WebSocketState.Open) { - await webSocket.CloseAsync(result.CloseStatus ?? WebSocketCloseStatus.NormalClosure, - result.CloseStatusDescription, cancellationToken); + await webSocket.CloseAsync( + result.CloseStatus ?? WebSocketCloseStatus.NormalClosure, + result.CloseStatusDescription, + cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index c7104c9507..833fcc54bc 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -588,7 +588,7 @@ namespace MediaBrowser.Api.Playback /// /// Parses query parameters as StreamOptions - /// + /// /// The stream request. private void ParseStreamOptions(StreamRequest request) { -- cgit v1.2.3