From 1b5999a1bc11ee386131e4bbce561896c0e1bced Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Tue, 25 Feb 2020 17:01:57 +0100 Subject: Open the Swagger API page on server start if not hosting the static web content --- Emby.Server.Implementations/EntryPoints/StartupWizard.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 5f2d629fea..6b7e2805bd 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -36,7 +36,11 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - if (!_config.Configuration.IsStartupWizardCompleted) + if (!_appHost.IsHostingContent) + { + BrowserLauncher.OpenSwaggerPage(_appHost); + } + else if (!_config.Configuration.IsStartupWizardCompleted) { BrowserLauncher.OpenWebApp(_appHost); } -- cgit v1.2.3 From 29bad073ebeb10813c6468b6159ce3bd06398134 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 28 Feb 2020 20:49:04 +0100 Subject: Use config setting to decide if web content should be hosted Also fail server startup if web content is expected but missing --- Emby.Server.Implementations/ApplicationHost.cs | 5 +---- .../EntryPoints/StartupWizard.cs | 4 +++- Jellyfin.Server/Program.cs | 25 ++++++++++++---------- MediaBrowser.Controller/IServerApplicationHost.cs | 5 ----- 4 files changed, 18 insertions(+), 21 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 789b8724c3..8ea188724a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -240,13 +240,10 @@ namespace Emby.Server.Implementations public int HttpsPort { get; private set; } /// - /// Gets the content root for the webhost. If the webhost is not serving static web content, this will be null. + /// Gets the content root for the webhost. /// public string ContentRoot { get; private set; } - /// - public bool IsHostingContent => ContentRoot != null; - /// /// Gets the server configuration manager. /// diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 6b7e2805bd..7c2b3cd5f2 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -2,7 +2,9 @@ using System.Threading.Tasks; using Emby.Server.Implementations.Browser; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Plugins; +using Microsoft.Extensions.Configuration; namespace Emby.Server.Implementations.EntryPoints { @@ -36,7 +38,7 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - if (!_appHost.IsHostingContent) + if (_appHost.Resolve().IsNoWebContent()) { BrowserLauncher.OpenSwaggerPage(_appHost); } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 7e03b0c9ca..843eb9ea94 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -19,7 +19,7 @@ using Emby.Server.Implementations.Networking; using Jellyfin.Drawing.Skia; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; -using MediaBrowser.Model.Globalization; +using MediaBrowser.Controller.Extensions; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -177,7 +177,7 @@ namespace Jellyfin.Server ServiceCollection serviceCollection = new ServiceCollection(); await appHost.InitAsync(serviceCollection).ConfigureAwait(false); - var host = CreateWebHostBuilder(appHost, serviceCollection).Build(); + var host = CreateWebHostBuilder(appHost, serviceCollection, appConfig).Build(); // A bit hacky to re-use service provider since ASP.NET doesn't allow a custom service collection. appHost.ServiceProvider = host.Services; @@ -221,7 +221,7 @@ namespace Jellyfin.Server } } - private static IWebHostBuilder CreateWebHostBuilder(ApplicationHost appHost, IServiceCollection serviceCollection) + private static IWebHostBuilder CreateWebHostBuilder(ApplicationHost appHost, IServiceCollection serviceCollection, IConfiguration appConfig) { var webhostBuilder = new WebHostBuilder() .UseKestrel(options => @@ -268,9 +268,18 @@ namespace Jellyfin.Server }) .UseStartup(); - // Set the root directory for static content, if one exists - if (appHost.IsHostingContent) + if (!appConfig.IsNoWebContent()) { + // Fail startup if the web content does not exist + if (!Directory.Exists(appHost.ContentRoot) || !Directory.GetFiles(appHost.ContentRoot).Any()) + { + throw new InvalidOperationException( + "The server is expected to host web content, but the provided content directory is either " + + $"invalid or empty: {appHost.ContentRoot}. If you do not want to host web content with the " + + $"server, you may set the '{MediaBrowser.Controller.Extensions.ConfigurationExtensions.NoWebContentKey}' flag."); + } + + // Configure the web host to host the static web content webhostBuilder.UseContentRoot(appHost.ContentRoot); } @@ -404,12 +413,6 @@ namespace Jellyfin.Server } } - // Reset webDir if the directory does not exist, or is empty - if (!Directory.Exists(webDir) || !Directory.GetFiles(webDir).Any()) - { - webDir = null; - } - // logDir // IF --logdir // ELSE IF $JELLYFIN_LOG_DIR diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 134ed110ba..25f0905eb8 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -16,11 +16,6 @@ namespace MediaBrowser.Controller { event EventHandler HasUpdateAvailableChanged; - /// - /// Gets a value indicating whether the server is hosting the static web content from jellyfin-web. - /// - bool IsHostingContent { get; } - /// /// Gets the system info. /// -- cgit v1.2.3 From 4102e3afd0a9df29faea598769db2212a00d64ce Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sun, 15 Mar 2020 13:00:14 +0100 Subject: Rename IsNoWebContent to NoWebContent --- Emby.Server.Implementations/EntryPoints/StartupWizard.cs | 2 +- Jellyfin.Server/Program.cs | 3 ++- MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 7c2b3cd5f2..bc6b8c956a 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -38,7 +38,7 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - if (_appHost.Resolve().IsNoWebContent()) + if (_appHost.Resolve().NoWebContent()) { BrowserLauncher.OpenSwaggerPage(_appHost); } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 9450fee705..6412db7518 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -287,7 +287,8 @@ namespace Jellyfin.Server }) .UseStartup(); - if (!startupConfig.IsNoWebContent()) + // Set up static content hosting unless it has been disabled via config + if (!startupConfig.NoWebContent()) { // Fail startup if the web content does not exist if (!Directory.Exists(appHost.ContentRoot) || !Directory.GetFiles(appHost.ContentRoot).Any()) diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs index 1a9ac09ee9..e802eeed2a 100644 --- a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs +++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs @@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Extensions /// The configuration to retrieve the value from. /// The parsed config value. /// The config value is not a valid bool string. See . - public static bool IsNoWebContent(this IConfiguration configuration) + public static bool NoWebContent(this IConfiguration configuration) => configuration.GetValue(NoWebContentKey); /// -- cgit v1.2.3 From 1a63c3f3644f8144ac7761724476891f4dc1d2cd Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 20 Mar 2020 13:13:20 +0100 Subject: Inject IConfiguration instead of resolving manually --- Emby.Server.Implementations/EntryPoints/StartupWizard.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index bc6b8c956a..9a41396ce0 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -13,10 +13,8 @@ namespace Emby.Server.Implementations.EntryPoints /// public sealed class StartupWizard : IServerEntryPoint { - /// - /// The app host. - /// private readonly IServerApplicationHost _appHost; + private readonly IConfiguration _appConfig; private readonly IServerConfigurationManager _config; /// @@ -24,9 +22,10 @@ namespace Emby.Server.Implementations.EntryPoints /// /// The application host. /// The configuration manager. - public StartupWizard(IServerApplicationHost appHost, IServerConfigurationManager config) + public StartupWizard(IServerApplicationHost appHost, IConfiguration appConfig, IServerConfigurationManager config) { _appHost = appHost; + _appConfig = appConfig; _config = config; } @@ -38,7 +37,7 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - if (_appHost.Resolve().NoWebContent()) + if (_appConfig.NoWebContent()) { BrowserLauncher.OpenSwaggerPage(_appHost); } -- cgit v1.2.3 From aa546dd36abb688cb3a5d10e589521ebf79ef610 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 21 Mar 2020 18:25:09 +0100 Subject: Rename command line option to --nowebclient and config setting to HostWebClient --- .../ConfigurationOptions.cs | 2 +- .../EntryPoints/StartupWizard.cs | 2 +- Jellyfin.Server/Program.cs | 4 ++-- Jellyfin.Server/Properties/launchSettings.json | 6 ++--- Jellyfin.Server/StartupOptions.cs | 10 ++++---- .../Extensions/ConfigurationExtensions.cs | 8 +++---- MediaBrowser.WebDashboard/Api/DashboardService.cs | 27 ++++++++++++---------- 7 files changed, 31 insertions(+), 28 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index 814d4b8b57..4574a64fdb 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -15,7 +15,7 @@ namespace Emby.Server.Implementations /// public static Dictionary DefaultConfiguration => new Dictionary { - { NoWebContentKey, bool.FalseString }, + { HostWebClientKey, bool.TrueString }, { HttpListenerHost.DefaultRedirectKey, "web/index.html" }, { FfmpegProbeSizeKey, "1G" }, { FfmpegAnalyzeDurationKey, "200M" }, diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 9a41396ce0..8e97719311 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - if (_appConfig.NoWebContent()) + if (!_appConfig.HostWebClient()) { BrowserLauncher.OpenSwaggerPage(_appHost); } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 67251eb249..d9ca141363 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -490,9 +490,9 @@ namespace Jellyfin.Server IApplicationPaths appPaths, IConfiguration? startupConfig = null) { - // Use the swagger API page as the default redirect path if not hosting the jellyfin-web content + // Use the swagger API page as the default redirect path if not hosting the web client var inMemoryDefaultConfig = ConfigurationOptions.DefaultConfiguration; - if (startupConfig != null && startupConfig.NoWebContent()) + if (startupConfig != null && !startupConfig.HostWebClient()) { inMemoryDefaultConfig[HttpListenerHost.DefaultRedirectKey] = "swagger/index.html"; } diff --git a/Jellyfin.Server/Properties/launchSettings.json b/Jellyfin.Server/Properties/launchSettings.json index d68a611c1b..53d9fe1656 100644 --- a/Jellyfin.Server/Properties/launchSettings.json +++ b/Jellyfin.Server/Properties/launchSettings.json @@ -3,9 +3,9 @@ "Jellyfin.Server": { "commandName": "Project" }, - "Jellyfin.Server (nowebcontent)": { + "Jellyfin.Server (nowebclient)": { "commandName": "Project", - "commandLineArgs": "--nowebcontent" + "commandLineArgs": "--nowebclient" } } -} \ No newline at end of file +} diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index 0abc0fd911..c93577d3ea 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -19,10 +19,10 @@ namespace Jellyfin.Server public string? DataDir { get; set; } /// - /// Gets or sets a value indicating whether the server should not host static web content. + /// Gets or sets a value indicating whether the server should not host the web client. /// - [Option(ConfigurationExtensions.NoWebContentKey, Required = false, HelpText = "Indicates that the web server should not host any static web content.")] - public bool NoWebContent { get; set; } + [Option("nowebclient", Required = false, HelpText = "Indicates that the web server should not host the web client.")] + public bool NoWebClient { get; set; } /// /// Gets or sets the path to the web directory. @@ -84,9 +84,9 @@ namespace Jellyfin.Server { var config = new Dictionary(); - if (NoWebContent) + if (NoWebClient) { - config.Add(ConfigurationExtensions.NoWebContentKey, bool.TrueString); + config.Add(ConfigurationExtensions.HostWebClientKey, bool.FalseString); } return config; diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs index 900cc6cb57..c951499847 100644 --- a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs +++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs @@ -9,9 +9,9 @@ namespace MediaBrowser.Controller.Extensions public static class ConfigurationExtensions { /// - /// The key for a setting that indicates whether the application should host static web content. + /// The key for a setting that indicates whether the application should host web client content. /// - public const string NoWebContentKey = "nowebcontent"; + public const string HostWebClientKey = "hostwebclient"; /// /// The key for the FFmpeg probe size option. @@ -34,8 +34,8 @@ namespace MediaBrowser.Controller.Extensions /// The configuration to retrieve the value from. /// The parsed config value. /// The config value is not a valid bool string. See . - public static bool NoWebContent(this IConfiguration configuration) - => configuration.GetValue(NoWebContentKey); + public static bool HostWebClient(this IConfiguration configuration) + => configuration.GetValue(HostWebClientKey); /// /// Gets the FFmpeg probe size from the . diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 3e47ce6829..a71d685fbb 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -136,15 +136,18 @@ namespace MediaBrowser.WebDashboard.Api _fileSystem = fileSystem; _resultFactory = resultFactory; - // Validate web content path - string webContentPath = DashboardUIPath; - bool webContentPathValid = appConfig.NoWebContent() || (Directory.Exists(webContentPath) && Directory.GetFiles(webContentPath).Any()); - if (!webContentPathValid) + // If hosting the web client, validate the client content path + if (appConfig.HostWebClient()) { - throw new InvalidOperationException( - "The server is expected to host web content, but the provided content directory is either " + - $"invalid or empty: {webContentPath}. If you do not want to host web content with the server, " + - $"you may set the '{Controller.Extensions.ConfigurationExtensions.NoWebContentKey}' flag."); + string webContentPath = DashboardUIPath; + if (!Directory.Exists(webContentPath) || !Directory.GetFiles(webContentPath).Any()) + { + throw new InvalidOperationException( + "The server is expected to host the web client, but the provided content directory is either " + + $"invalid or empty: {webContentPath}. If you do not want to host the web client with the " + + "server, you may set the '--nowebclient' command line flag, or set" + + $"'{Controller.Extensions.ConfigurationExtensions.HostWebClientKey}=false' in your config settings."); + } } } @@ -156,13 +159,13 @@ namespace MediaBrowser.WebDashboard.Api /// /// Gets the path of the directory containing the static web interface content, or null if the server is not - /// hosting the static web content. + /// hosting the web client. /// public string DashboardUIPath { get { - if (_appConfig.NoWebContent()) + if (!_appConfig.HostWebClient()) { return null; } @@ -329,7 +332,7 @@ namespace MediaBrowser.WebDashboard.Api /// System.Object. public async Task Get(GetDashboardResource request) { - if (_appConfig.NoWebContent() || DashboardUIPath == null) + if (!_appConfig.HostWebClient() || DashboardUIPath == null) { throw new ResourceNotFoundException(); } @@ -405,7 +408,7 @@ namespace MediaBrowser.WebDashboard.Api public async Task Get(GetDashboardPackage request) { - if (_appConfig.NoWebContent() || DashboardUIPath == null) + if (!_appConfig.HostWebClient() || DashboardUIPath == null) { throw new ResourceNotFoundException(); } -- cgit v1.2.3 From ca71ac72abf5d5ff31d50553283a43de298e0c73 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Thu, 2 Apr 2020 17:45:04 -0400 Subject: Replace EnableHttps and SupportsHttps with ListenWithHttps and CanConnectWithHttps --- Emby.Server.Implementations/ApplicationHost.cs | 15 ++++++++++----- .../EntryPoints/ExternalPortForwarding.cs | 2 +- .../HttpServer/HttpListenerHost.cs | 2 +- Jellyfin.Server/Program.cs | 4 ++-- MediaBrowser.Controller/IServerApplicationHost.cs | 5 ++--- MediaBrowser.Model/System/SystemInfo.cs | 4 ++-- 6 files changed, 18 insertions(+), 14 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c959cc974a..8158b45592 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1408,7 +1408,7 @@ namespace Emby.Server.Implementations InternalMetadataPath = ApplicationPaths.InternalMetadataPath, CachePath = ApplicationPaths.CachePath, HttpServerPortNumber = HttpPort, - SupportsHttps = SupportsHttps, + SupportsHttps = CanConnectWithHttps, HttpsPortNumber = HttpsPort, OperatingSystem = OperatingSystem.Id.ToString(), OperatingSystemDisplayName = OperatingSystem.Name, @@ -1446,9 +1446,14 @@ namespace Emby.Server.Implementations }; } - public bool EnableHttps => SupportsHttps && ServerConfigurationManager.Configuration.EnableHttps; + /// + public bool ListenWithHttps => Certificate != null && ServerConfigurationManager.Configuration.EnableHttps; - public bool SupportsHttps => Certificate != null || ServerConfigurationManager.Configuration.IsBehindProxy; + /// + /// Gets a value indicating whether a client can connect to the server over HTTPS, either directly or via a + /// reverse proxy. + /// + public bool CanConnectWithHttps => ListenWithHttps || ServerConfigurationManager.Configuration.IsBehindProxy; public async Task GetLocalApiUrl(CancellationToken cancellationToken) { @@ -1509,10 +1514,10 @@ namespace Emby.Server.Implementations public string GetLocalApiUrl(ReadOnlySpan host) { var url = new StringBuilder(64); - url.Append(EnableHttps ? "https://" : "http://") + url.Append(ListenWithHttps ? "https://" : "http://") .Append(host) .Append(':') - .Append(EnableHttps ? HttpsPort : HttpPort); + .Append(ListenWithHttps ? HttpsPort : HttpPort); string baseUrl = ServerConfigurationManager.Configuration.BaseUrl; if (baseUrl.Length != 0) diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index e290c62e16..2023c470a8 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.EntryPoints .Append(config.PublicPort).Append(Separator) .Append(_appHost.HttpPort).Append(Separator) .Append(_appHost.HttpsPort).Append(Separator) - .Append(_appHost.EnableHttps).Append(Separator) + .Append(_appHost.ListenWithHttps).Append(Separator) .Append(config.EnableRemoteAccess).Append(Separator) .ToString(); } diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 7a812f3201..e3f8ec0146 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.HttpServer private bool ValidateSsl(string remoteIp, string urlString) { - if (_config.Configuration.RequireHttps && _appHost.EnableHttps && !_config.Configuration.IsBehindProxy) + if (_config.Configuration.RequireHttps && _appHost.ListenWithHttps) { if (urlString.IndexOf("https://", StringComparison.OrdinalIgnoreCase) == -1) { diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 4abdd59aaf..ddd1054ad0 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -274,7 +274,7 @@ namespace Jellyfin.Server _logger.LogInformation("Kestrel listening on {IpAddress}", address); options.Listen(address, appHost.HttpPort); - if (appHost.EnableHttps && appHost.Certificate != null) + if (appHost.ListenWithHttps) { options.Listen(address, appHost.HttpsPort, listenOptions => { @@ -289,7 +289,7 @@ namespace Jellyfin.Server _logger.LogInformation("Kestrel listening on all interfaces"); options.ListenAnyIP(appHost.HttpPort); - if (appHost.EnableHttps && appHost.Certificate != null) + if (appHost.ListenWithHttps) { options.ListenAnyIP(appHost.HttpsPort, listenOptions => { diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 608ffc61c2..d999f76dbf 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -39,10 +39,9 @@ namespace MediaBrowser.Controller int HttpsPort { get; } /// - /// Gets a value indicating whether [supports HTTPS]. + /// Gets a value indicating whether the server should listen on an HTTPS port. /// - /// true if [supports HTTPS]; otherwise, false. - bool EnableHttps { get; } + bool ListenWithHttps { get; } /// /// Gets a value indicating whether this instance has update available. diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index cfa7684c91..83c60563e7 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -124,9 +124,9 @@ namespace MediaBrowser.Model.System public int HttpServerPortNumber { get; set; } /// - /// Gets or sets a value indicating whether [enable HTTPS]. + /// Gets or sets a value indicating whether a client can connect to the server over HTTPS, either directly or + /// via a reverse proxy. /// - /// true if [enable HTTPS]; otherwise, false. public bool SupportsHttps { get; set; } /// -- cgit v1.2.3 From 241d0ae65cca0ffdd92b7c366d692acaa71cd211 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 23:14:35 -0400 Subject: Inject IStartupOptions into StartupWizard --- Emby.Server.Implementations/ApplicationHost.cs | 2 ++ Emby.Server.Implementations/EntryPoints/StartupWizard.cs | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bae97c17ec..0620469c0f 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -557,6 +557,8 @@ namespace Emby.Server.Implementations : typeof(NullImageEncoder); serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); + serviceCollection.AddSingleton(_startupOptions); + serviceCollection.AddMemoryCache(); serviceCollection.AddSingleton(ConfigurationManager); diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 8e97719311..af1604aa6e 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -16,17 +16,25 @@ namespace Emby.Server.Implementations.EntryPoints private readonly IServerApplicationHost _appHost; private readonly IConfiguration _appConfig; private readonly IServerConfigurationManager _config; + private readonly IStartupOptions _startupOptions; /// /// Initializes a new instance of the class. /// /// The application host. + /// The application configuration. /// The configuration manager. - public StartupWizard(IServerApplicationHost appHost, IConfiguration appConfig, IServerConfigurationManager config) + /// The application startup options. + public StartupWizard( + IServerApplicationHost appHost, + IConfiguration appConfig, + IServerConfigurationManager config, + IStartupOptions startupOptions) { _appHost = appHost; _appConfig = appConfig; _config = config; + _startupOptions = startupOptions; } /// @@ -47,9 +55,7 @@ namespace Emby.Server.Implementations.EntryPoints } else if (_config.Configuration.AutoRunWebApp) { - var options = ((ApplicationHost)_appHost).StartupOptions; - - if (!options.NoAutoRunWebApp) + if (!_startupOptions.NoAutoRunWebApp) { BrowserLauncher.OpenWebApp(_appHost); } -- cgit v1.2.3 From 26afb42a72ec111675e079be7bdee13ea05c9713 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 6 Apr 2020 00:05:47 -0400 Subject: Cleanup port forwarding service - Use a concurrent collection instead of manually locking - Do not forward HTTPS port when it is not enabled - Created multiple rules (HTTP/HTTPS) in parallel instead of in sync --- .../EntryPoints/ExternalPortForwarding.cs | 79 +++++++++------------- 1 file changed, 33 insertions(+), 46 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index e290c62e16..5525401c5e 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Net; using System.Text; @@ -26,8 +27,8 @@ namespace Emby.Server.Implementations.EntryPoints private readonly IServerConfigurationManager _config; private readonly IDeviceDiscovery _deviceDiscovery; - private readonly object _createdRulesLock = new object(); - private List _createdRules = new List(); + private readonly ConcurrentDictionary _createdRules = new ConcurrentDictionary(); + private Timer _timer; private string _lastConfigIdentifier; @@ -98,7 +99,7 @@ namespace Emby.Server.Implementations.EntryPoints NatUtility.DeviceFound += OnNatUtilityDeviceFound; NatUtility.StartDiscovery(); - _timer = new Timer(ClearCreatedRules, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); + _timer = new Timer((_) => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); _deviceDiscovery.DeviceDiscovered += OnDeviceDiscoveryDeviceDiscovered; @@ -117,26 +118,16 @@ namespace Emby.Server.Implementations.EntryPoints _deviceDiscovery.DeviceDiscovered -= OnDeviceDiscoveryDeviceDiscovered; } - private void ClearCreatedRules(object state) - { - lock (_createdRulesLock) - { - _createdRules.Clear(); - } - } - private void OnDeviceDiscoveryDeviceDiscovered(object sender, GenericEventArgs e) { NatUtility.Search(e.Argument.LocalIpAddress, NatProtocol.Upnp); } - private void OnNatUtilityDeviceFound(object sender, DeviceEventArgs e) + private async void OnNatUtilityDeviceFound(object sender, DeviceEventArgs e) { try { - var device = e.Device; - - CreateRules(device); + await CreateRules(e.Device).ConfigureAwait(false); } catch (Exception ex) { @@ -144,7 +135,7 @@ namespace Emby.Server.Implementations.EntryPoints } } - private async void CreateRules(INatDevice device) + private Task CreateRules(INatDevice device) { if (_disposed) { @@ -153,50 +144,46 @@ 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.DeviceEndpoint; - - lock (_createdRulesLock) + if (!_createdRules.TryAdd(device.DeviceEndpoint, 0)) { - if (!_createdRules.Contains(address)) - { - _createdRules.Add(address); - } - else - { - return; - } + return Task.CompletedTask; } - try - { - await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error creating http port map"); - return; - } + return Task.WhenAll(CreatePortMaps(device)); + } - try - { - await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false); - } - catch (Exception ex) + private IEnumerable CreatePortMaps(INatDevice device) + { + yield return CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); + + if (_appHost.EnableHttps) { - _logger.LogError(ex, "Error creating https port map"); + yield return CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); } } - private Task CreatePortMap(INatDevice device, int privatePort, int publicPort) + private async Task CreatePortMap(INatDevice device, int privatePort, int publicPort) { _logger.LogDebug( - "Creating port map on local port {0} to public port {1} with device {2}", + "Creating port map on local port {LocalPort} to public port {PublicPort} with device {DeviceEndpoint}", privatePort, publicPort, device.DeviceEndpoint); - return device.CreatePortMapAsync( - new Mapping(Protocol.Tcp, privatePort, publicPort, 0, _appHost.Name)); + try + { + var mapping = new Mapping(Protocol.Tcp, privatePort, publicPort, 0, _appHost.Name); + await device.CreatePortMapAsync(mapping).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.LogError( + ex, + "Error creating port map on local port {LocalPort} to public port {PublicPort} with device {DeviceEndpoint}.", + privatePort, + publicPort, + device.DeviceEndpoint); + } } /// -- cgit v1.2.3 From 78d9b9894c5ad9478852196213b8585c37456128 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 6 Apr 2020 00:22:27 -0400 Subject: Respond to config changes correctly for external port forwarding --- .../EntryPoints/ExternalPortForwarding.cs | 13 +++++++------ 1 file changed, 7 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 5525401c5e..8dbc6494d5 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -30,7 +30,7 @@ namespace Emby.Server.Implementations.EntryPoints private readonly ConcurrentDictionary _createdRules = new ConcurrentDictionary(); private Timer _timer; - private string _lastConfigIdentifier; + private string _configIdentifier; private bool _disposed = false; @@ -70,7 +70,10 @@ namespace Emby.Server.Implementations.EntryPoints private void OnConfigurationUpdated(object sender, EventArgs e) { - if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) + var oldConfigIdentifier = _configIdentifier; + _configIdentifier = GetConfigIdentifier(); + + if (!string.Equals(_configIdentifier, oldConfigIdentifier, StringComparison.OrdinalIgnoreCase)) { Stop(); Start(); @@ -94,7 +97,7 @@ namespace Emby.Server.Implementations.EntryPoints return; } - _logger.LogDebug("Starting NAT discovery"); + _logger.LogInformation("Starting NAT discovery"); NatUtility.DeviceFound += OnNatUtilityDeviceFound; NatUtility.StartDiscovery(); @@ -102,13 +105,11 @@ namespace Emby.Server.Implementations.EntryPoints _timer = new Timer((_) => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); _deviceDiscovery.DeviceDiscovered += OnDeviceDiscoveryDeviceDiscovered; - - _lastConfigIdentifier = GetConfigIdentifier(); } private void Stop() { - _logger.LogDebug("Stopping NAT discovery"); + _logger.LogInformation("Stopping NAT discovery"); NatUtility.StopDiscovery(); NatUtility.DeviceFound -= OnNatUtilityDeviceFound; -- cgit v1.2.3 From 8a81bcd7425ebf93eb688bbc754179dfc20787ec Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Thu, 16 Apr 2020 22:49:23 -0400 Subject: Restart port forwarding when public https port changes --- Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 8dbc6494d5..37d7fd4799 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -61,6 +61,7 @@ namespace Emby.Server.Implementations.EntryPoints return new StringBuilder(32) .Append(config.EnableUPnP).Append(Separator) .Append(config.PublicPort).Append(Separator) + .Append(config.PublicHttpsPort).Append(Separator) .Append(_appHost.HttpPort).Append(Separator) .Append(_appHost.HttpsPort).Append(Separator) .Append(_appHost.EnableHttps).Append(Separator) -- cgit v1.2.3 From bd81825d2d2abba551d97d5c75890358d961fd27 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 20 Apr 2020 14:48:12 -0400 Subject: Respect AutoRunWebApp and NoAutoRunWebApp settings when HostWebClient is false --- .../EntryPoints/StartupWizard.cs | 36 ++++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 8e97719311..a0a653d753 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -31,31 +31,41 @@ namespace Emby.Server.Implementations.EntryPoints /// public Task RunAsync() + { + Run(); + return Task.CompletedTask; + } + + private void Run() { if (!_appHost.CanLaunchWebBrowser) { - return Task.CompletedTask; + return; } - if (!_appConfig.HostWebClient()) + // Always launch the startup wizard if possible when it has not been completed + if (!_config.Configuration.IsStartupWizardCompleted && _appConfig.HostWebClient()) { - BrowserLauncher.OpenSwaggerPage(_appHost); + BrowserLauncher.OpenWebApp(_appHost); + return; + } + + // Do nothing if the web app is configured to not run automatically + var options = ((ApplicationHost)_appHost).StartupOptions; + if (!_config.Configuration.AutoRunWebApp || options.NoAutoRunWebApp) + { + return; } - else if (!_config.Configuration.IsStartupWizardCompleted) + + // Launch the swagger page if the web client is not hosted, otherwise open the web client + if (_appConfig.HostWebClient()) { BrowserLauncher.OpenWebApp(_appHost); } - else if (_config.Configuration.AutoRunWebApp) + else { - var options = ((ApplicationHost)_appHost).StartupOptions; - - if (!options.NoAutoRunWebApp) - { - BrowserLauncher.OpenWebApp(_appHost); - } + BrowserLauncher.OpenSwaggerPage(_appHost); } - - return Task.CompletedTask; } /// -- cgit v1.2.3 From cabdec87e8e946bfa5de0dd0f97129f1a23e7d98 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sun, 26 Apr 2020 16:55:00 -0400 Subject: Fix merge with master --- Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/EntryPoints') diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index adec9dbe2c..878cee23c4 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -158,7 +158,7 @@ namespace Emby.Server.Implementations.EntryPoints { yield return CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); - if (_appHost.EnableHttps) + if (_appHost.ListenWithHttps) { yield return CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); } -- cgit v1.2.3