From 7df6e0b16f8e6b3026955e31417906b3bcbba290 Mon Sep 17 00:00:00 2001 From: JPVenson Date: Sat, 19 Apr 2025 22:08:24 +0300 Subject: Add port awareness to startup server (#13913) --- Jellyfin.Server/ServerSetupApp/SetupServer.cs | 74 ++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 13 deletions(-) (limited to 'Jellyfin.Server/ServerSetupApp') diff --git a/Jellyfin.Server/ServerSetupApp/SetupServer.cs b/Jellyfin.Server/ServerSetupApp/SetupServer.cs index 9e2cf5bc8..3d4810bd7 100644 --- a/Jellyfin.Server/ServerSetupApp/SetupServer.cs +++ b/Jellyfin.Server/ServerSetupApp/SetupServer.cs @@ -4,6 +4,9 @@ using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; +using Emby.Server.Implementations.Configuration; +using Emby.Server.Implementations.Serialization; +using Jellyfin.Networking.Manager; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller; @@ -11,9 +14,12 @@ using MediaBrowser.Model.System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Primitives; namespace Jellyfin.Server.ServerSetupApp; @@ -22,20 +28,45 @@ namespace Jellyfin.Server.ServerSetupApp; /// public sealed class SetupServer : IDisposable { + private readonly Func _networkManagerFactory; + private readonly IApplicationPaths _applicationPaths; + private readonly Func _serverFactory; + private readonly ILoggerFactory _loggerFactory; + private readonly IConfiguration _startupConfiguration; + private readonly ServerConfigurationManager _configurationManager; private IHost? _startupServer; private bool _disposed; /// - /// Starts the Bind-All Setup aspcore server to provide a reflection on the current core setup. + /// Initializes a new instance of the class. /// /// The networkmanager. /// The application paths. - /// The servers application host. - /// A Task. - public async Task RunAsync( + /// The servers application host. + /// The logger factory. + /// The startup configuration. + public SetupServer( Func networkManagerFactory, IApplicationPaths applicationPaths, - Func serverApplicationHost) + Func serverApplicationHostFactory, + ILoggerFactory loggerFactory, + IConfiguration startupConfiguration) + { + _networkManagerFactory = networkManagerFactory; + _applicationPaths = applicationPaths; + _serverFactory = serverApplicationHostFactory; + _loggerFactory = loggerFactory; + _startupConfiguration = startupConfiguration; + var xmlSerializer = new MyXmlSerializer(); + _configurationManager = new ServerConfigurationManager(_applicationPaths, loggerFactory, xmlSerializer); + _configurationManager.RegisterConfiguration(); + } + + /// + /// Starts the Bind-All Setup aspcore server to provide a reflection on the current core setup. + /// + /// A Task. + public async Task RunAsync() { ThrowIfDisposed(); _startupServer = Host.CreateDefaultBuilder() @@ -48,7 +79,23 @@ public sealed class SetupServer : IDisposable .ConfigureWebHostDefaults(webHostBuilder => { webHostBuilder - .UseKestrel() + .UseKestrel((builderContext, options) => + { + var config = _configurationManager.GetNetworkConfiguration()!; + var knownBindInterfaces = NetworkManager.GetInterfacesCore(_loggerFactory.CreateLogger(), config.EnableIPv4, config.EnableIPv6); + knownBindInterfaces = NetworkManager.FilterBindSettings(config, knownBindInterfaces.ToList(), config.EnableIPv4, config.EnableIPv6); + var bindInterfaces = NetworkManager.GetAllBindInterfaces(false, _configurationManager, knownBindInterfaces, config.EnableIPv4, config.EnableIPv6); + Extensions.WebHostBuilderExtensions.SetupJellyfinWebServer( + bindInterfaces, + config.InternalHttpPort, + null, + null, + _startupConfiguration, + _applicationPaths, + _loggerFactory.CreateLogger(), + builderContext, + options); + }) .Configure(app => { app.UseHealthChecks("/health"); @@ -57,14 +104,14 @@ public sealed class SetupServer : IDisposable { loggerRoute.Run(async context => { - var networkManager = networkManagerFactory(); + var networkManager = _networkManagerFactory(); if (context.Connection.RemoteIpAddress is null || networkManager is null || !networkManager.IsInLocalNetwork(context.Connection.RemoteIpAddress)) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; return; } - var logFilePath = new DirectoryInfo(applicationPaths.LogDirectoryPath) + var logFilePath = new DirectoryInfo(_applicationPaths.LogDirectoryPath) .EnumerateFiles() .OrderBy(f => f.CreationTimeUtc) .FirstOrDefault() @@ -80,20 +127,20 @@ public sealed class SetupServer : IDisposable { systemRoute.Run(async context => { - var jfApplicationHost = serverApplicationHost(); + var jfApplicationHost = _serverFactory(); var retryCounter = 0; while (jfApplicationHost is null && retryCounter < 5) { await Task.Delay(500).ConfigureAwait(false); - jfApplicationHost = serverApplicationHost(); + jfApplicationHost = _serverFactory(); retryCounter++; } if (jfApplicationHost is null) { context.Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable; - context.Response.Headers.RetryAfter = new Microsoft.Extensions.Primitives.StringValues("60"); + context.Response.Headers.RetryAfter = new StringValues("5"); return; } @@ -114,9 +161,10 @@ public sealed class SetupServer : IDisposable app.Run((context) => { context.Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable; - context.Response.Headers.RetryAfter = new Microsoft.Extensions.Primitives.StringValues("60"); + context.Response.Headers.RetryAfter = new StringValues("5"); + context.Response.Headers.ContentType = new StringValues("text/html"); context.Response.WriteAsync("

Jellyfin Server still starting. Please wait.

"); - var networkManager = networkManagerFactory(); + var networkManager = _networkManagerFactory(); if (networkManager is not null && context.Connection.RemoteIpAddress is not null && networkManager.IsInLocalNetwork(context.Connection.RemoteIpAddress)) { context.Response.WriteAsync("

You can download the current logfiles here.

"); -- cgit v1.2.3