aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server/Program.cs
diff options
context:
space:
mode:
authorBond_009 <bond.009@outlook.com>2019-12-10 23:00:59 +0100
committerBond_009 <bond.009@outlook.com>2019-12-10 23:00:59 +0100
commit0bf8bfbb0cfd67b387a574148022f3c554ff5173 (patch)
tree34f12fcce7b688fc50d377f90dbccc343e03b310 /Jellyfin.Server/Program.cs
parentc6d48f51f608601775d98fc7866eefc367bfd63b (diff)
parent67922dff50967c02e8c0c10f43884fd4e788b012 (diff)
Merge branch 'master' into mediaencoding
Diffstat (limited to 'Jellyfin.Server/Program.cs')
-rw-r--r--Jellyfin.Server/Program.cs104
1 files changed, 95 insertions, 9 deletions
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index c9ca79a2b..712990a1e 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
@@ -19,9 +20,12 @@ using Jellyfin.Drawing.Skia;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.Globalization;
+using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
using Serilog;
using Serilog.Extensions.Logging;
using SQLitePCL;
@@ -36,7 +40,7 @@ namespace Jellyfin.Server
{
private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
- private static ILogger _logger;
+ private static ILogger _logger = NullLogger.Instance;
private static bool _restartOnShutdown;
/// <summary>
@@ -87,6 +91,12 @@ namespace Jellyfin.Server
{
var stopWatch = new Stopwatch();
stopWatch.Start();
+
+ // Log all uncaught exceptions to std error
+ static void UnhandledExceptionToConsole(object sender, UnhandledExceptionEventArgs e) =>
+ Console.Error.WriteLine("Unhandled Exception\n" + e.ExceptionObject.ToString());
+ AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionToConsole;
+
ServerApplicationPaths appPaths = CreateApplicationPaths(options);
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
@@ -98,6 +108,8 @@ namespace Jellyfin.Server
_logger = _loggerFactory.CreateLogger("Main");
+ // Log uncaught exceptions to the logging instead of std error
+ AppDomain.CurrentDomain.UnhandledException -= UnhandledExceptionToConsole;
AppDomain.CurrentDomain.UnhandledException += (sender, e)
=> _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");
@@ -130,7 +142,7 @@ namespace Jellyfin.Server
_logger.LogInformation(
"Jellyfin version: {Version}",
- Assembly.GetEntryAssembly().GetName().Version.ToString(3));
+ Assembly.GetEntryAssembly()!.GetName().Version!.ToString(3));
ApplicationHost.LogEnvironmentInfo(_logger, appPaths);
@@ -162,7 +174,24 @@ namespace Jellyfin.Server
appConfig);
try
{
- await appHost.InitAsync(new ServiceCollection()).ConfigureAwait(false);
+ ServiceCollection serviceCollection = new ServiceCollection();
+ await appHost.InitAsync(serviceCollection).ConfigureAwait(false);
+
+ var host = CreateWebHostBuilder(appHost, serviceCollection).Build();
+
+ // A bit hacky to re-use service provider since ASP.NET doesn't allow a custom service collection.
+ appHost.ServiceProvider = host.Services;
+ appHost.FindParts();
+
+ try
+ {
+ await host.StartAsync().ConfigureAwait(false);
+ }
+ catch
+ {
+ _logger.LogError("Kestrel failed to start! This is most likely due to an invalid address or port bind - correct your bind configuration in system.xml and try again.");
+ throw;
+ }
appHost.ImageProcessor.ImageEncoder = GetImageEncoder(appPaths, appHost.LocalizationManager);
@@ -194,6 +223,55 @@ namespace Jellyfin.Server
}
}
+ private static IWebHostBuilder CreateWebHostBuilder(ApplicationHost appHost, IServiceCollection serviceCollection)
+ {
+ return new WebHostBuilder()
+ .UseKestrel(options =>
+ {
+ var addresses = appHost.ServerConfigurationManager
+ .Configuration
+ .LocalNetworkAddresses
+ .Select(appHost.NormalizeConfiguredLocalAddress)
+ .Where(i => i != null)
+ .ToList();
+ if (addresses.Any())
+ {
+ foreach (var address in addresses)
+ {
+ _logger.LogInformation("Kestrel listening on {ipaddr}", address);
+ options.Listen(address, appHost.HttpPort);
+
+ if (appHost.EnableHttps && appHost.Certificate != null)
+ {
+ options.Listen(
+ address,
+ appHost.HttpsPort,
+ listenOptions => listenOptions.UseHttps(appHost.Certificate));
+ }
+ }
+ }
+ else
+ {
+ _logger.LogInformation("Kestrel listening on all interfaces");
+ options.ListenAnyIP(appHost.HttpPort);
+
+ if (appHost.EnableHttps && appHost.Certificate != null)
+ {
+ options.ListenAnyIP(
+ appHost.HttpsPort,
+ listenOptions => listenOptions.UseHttps(appHost.Certificate));
+ }
+ }
+ })
+ .UseContentRoot(appHost.ContentRoot)
+ .ConfigureServices(services =>
+ {
+ // Merge the external ServiceCollection into ASP.NET DI
+ services.TryAdd(serviceCollection);
+ })
+ .UseStartup<Startup>();
+ }
+
/// <summary>
/// Create the data, config and log paths from the variety of inputs(command line args,
/// environment variables) or decide on what default to use. For Windows it's %AppPath%
@@ -359,16 +437,25 @@ namespace Jellyfin.Server
private static async Task<IConfiguration> CreateConfiguration(IApplicationPaths appPaths)
{
+ const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json");
if (!File.Exists(configPath))
{
// For some reason the csproj name is used instead of the assembly name
- using (Stream rscstr = typeof(Program).Assembly
- .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json"))
- using (Stream fstr = File.Open(configPath, FileMode.CreateNew))
+ using (Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath))
{
- await rscstr.CopyToAsync(fstr).ConfigureAwait(false);
+ if (resource == null)
+ {
+ throw new InvalidOperationException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "Invalid resource path: '{0}'",
+ ResourcePath));
+ }
+
+ using Stream dst = File.Open(configPath, FileMode.CreateNew);
+ await resource.CopyToAsync(dst).ConfigureAwait(false);
}
}
@@ -431,7 +518,7 @@ namespace Jellyfin.Server
{
_logger.LogInformation("Starting new instance");
- string module = options.RestartPath;
+ var module = options.RestartPath;
if (string.IsNullOrWhiteSpace(module))
{
@@ -439,7 +526,6 @@ namespace Jellyfin.Server
}
string commandLineArgsString;
-
if (options.RestartArgs != null)
{
commandLineArgsString = options.RestartArgs ?? string.Empty;