From 0f8b3c634708ce8e7b2e2ae6fed87b6b943b5bca Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 13 Dec 2018 14:18:25 +0100 Subject: Use Microsoft.Extensions.Logging abstraction --- MediaBrowser.Server.Mono/Program.cs | 54 ++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 887a9545f..21845d10e 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -1,4 +1,3 @@ -using MediaBrowser.Model.Logging; using MediaBrowser.Server.Mono.Native; using MediaBrowser.Server.Startup.Common; using System; @@ -15,16 +14,18 @@ using Emby.Drawing; using Emby.Server.Implementations; using Emby.Server.Implementations.EnvironmentInfo; using Emby.Server.Implementations.IO; -using Emby.Server.Implementations.Logging; using Emby.Server.Implementations.Networking; using MediaBrowser.Controller; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using Mono.Unix.Native; -using ILogger = MediaBrowser.Model.Logging.ILogger; using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate; using System.Threading; using InteropServices = System.Runtime.InteropServices; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; +using Serilog; +using Serilog.AspNetCore; namespace MediaBrowser.Server.Mono { @@ -33,7 +34,7 @@ namespace MediaBrowser.Server.Mono private static ILogger _logger; private static IFileSystem FileSystem; private static IServerApplicationPaths _appPaths; - private static ILogManager _logManager; + private static ILoggerFactory _loggerFactory; private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); private static bool _restartOnShutdown; @@ -52,23 +53,24 @@ namespace MediaBrowser.Server.Mono var appPaths = CreateApplicationPaths(applicationPath, customProgramDataPath); _appPaths = appPaths; - using (var logManager = new SimpleLogManager(appPaths.LogDirectoryPath, "server")) - { - _logManager = logManager; + var logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateLogger(); - var task = logManager.ReloadLogger(LogSeverity.Debug, CancellationToken.None); - Task.WaitAll(task); - logManager.AddConsoleOutput(); + using (var loggerFactory = new SerilogLoggerFactory(logger)) + { + _loggerFactory = loggerFactory; - var logger = _logger = logManager.GetLogger("Main"); + _logger = loggerFactory.CreateLogger("Main"); - ApplicationHost.LogEnvironmentInfo(logger, appPaths, true); + ApplicationHost.LogEnvironmentInfo(_logger, appPaths, true); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - RunApplication(appPaths, logManager, options); + RunApplication(appPaths, loggerFactory, options); - _logger.Info("Disposing app host"); + _logger.LogInformation("Disposing app host"); if (_restartOnShutdown) { @@ -109,27 +111,27 @@ namespace MediaBrowser.Server.Mono return new ServerApplicationPaths(programDataPath, appFolderPath, appFolderPath); } - private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, StartupOptions options) + private static void RunApplication(ServerApplicationPaths appPaths, ILoggerFactory loggerFactory, StartupOptions options) { // Allow all https requests ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); var environmentInfo = GetEnvironmentInfo(); - var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory, true); + var fileSystem = new ManagedFileSystem(loggerFactory.CreateLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory, true); FileSystem = fileSystem; using (var appHost = new MonoAppHost(appPaths, - logManager, + loggerFactory, options, fileSystem, new PowerManagement(), "embyserver-mono_{version}.zip", environmentInfo, new NullImageEncoder(), - new SystemEvents(logManager.GetLogger("SystemEvents")), - new NetworkManager(logManager.GetLogger("NetworkManager"), environmentInfo))) + new SystemEvents(loggerFactory.CreateLogger("SystemEvents")), + new NetworkManager(loggerFactory.CreateLogger("NetworkManager"), environmentInfo))) { if (options.ContainsOption("-v")) { @@ -141,7 +143,7 @@ namespace MediaBrowser.Server.Mono appHost.Init(); - appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); + appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); Console.WriteLine("Running startup tasks"); @@ -221,7 +223,7 @@ namespace MediaBrowser.Server.Mono } catch (Exception ex) { - _logger.ErrorException("Error getting unix name", ex); + _logger.LogError("Error getting unix name", ex); } _unixName = uname; } @@ -243,6 +245,8 @@ namespace MediaBrowser.Server.Mono { var exception = (Exception)e.ExceptionObject; + // TODO + /* new UnhandledExceptionWriter(_appPaths, _logger, _logManager, FileSystem, new ConsoleLogger()).Log(exception); if (!Debugger.IsAttached) @@ -254,7 +258,7 @@ namespace MediaBrowser.Server.Mono { Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(exception)); } - } + }*/ } public static void Shutdown() @@ -271,7 +275,7 @@ namespace MediaBrowser.Server.Mono private static void StartNewInstance(StartupOptions startupOptions) { - _logger.Info("Starting new instance"); + _logger.LogInformation("Starting new instance"); string module = startupOptions.GetOption("-restartpath"); string commandLineArgsString = startupOptions.GetOption("-restartargs") ?? string.Empty; @@ -290,8 +294,8 @@ namespace MediaBrowser.Server.Mono commandLineArgsString = string.Join(" ", args); } - _logger.Info("Executable: {0}", module); - _logger.Info("Arguments: {0}", commandLineArgsString); + _logger.LogInformation("Executable: {0}", module); + _logger.LogInformation("Arguments: {0}", commandLineArgsString); Process.Start(module, commandLineArgsString); } -- cgit v1.2.3 From 88f5471fe35657f410ddb8a58c84505301bda121 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 14 Dec 2018 20:44:24 +0100 Subject: Pls stop crashing --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- MediaBrowser.Server.Mono/Program.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 455e4c311..042e48e58 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -405,7 +405,7 @@ namespace Emby.Server.Implementations // hack alert, until common can target .net core BaseExtensions.CryptographyProvider = CryptographyProvider; - XmlSerializer = new MyXmlSerializer(fileSystem, LoggerFactory.CreateLogger("XmlSerializer")); + XmlSerializer = new MyXmlSerializer(fileSystem, loggerFactory.CreateLogger("XmlSerializer")); NetworkManager = networkManager; networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets; diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 21845d10e..0630df431 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -53,12 +53,12 @@ namespace MediaBrowser.Server.Mono var appPaths = CreateApplicationPaths(applicationPath, customProgramDataPath); _appPaths = appPaths; - var logger = new LoggerConfiguration() - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); - - using (var loggerFactory = new SerilogLoggerFactory(logger)) + using (var loggerFactory = new SerilogLoggerFactory( + new LoggerConfiguration() + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateLogger() + , true)) { _loggerFactory = loggerFactory; -- cgit v1.2.3 From a51798dd8d1fe71357c7926e9657f2c67cd40ed7 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 14 Dec 2018 22:07:28 +0100 Subject: Added logging.json file --- MediaBrowser.Server.Mono/EmbyServer.csproj | 10 ++++- MediaBrowser.Server.Mono/Program.cs | 51 +++++++++++++++++++--- .../Resources/Configuration/logging.json | 19 ++++++++ 3 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 MediaBrowser.Server.Mono/Resources/Configuration/logging.json (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/MediaBrowser.Server.Mono/EmbyServer.csproj b/MediaBrowser.Server.Mono/EmbyServer.csproj index 038a26f9d..da7883e6b 100644 --- a/MediaBrowser.Server.Mono/EmbyServer.csproj +++ b/MediaBrowser.Server.Mono/EmbyServer.csproj @@ -17,9 +17,13 @@ + - + + + + @@ -50,6 +54,10 @@ + + + + diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 0630df431..1e47322f1 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -23,6 +23,7 @@ using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certif using System.Threading; using InteropServices = System.Runtime.InteropServices; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Configuration; using ILogger = Microsoft.Extensions.Logging.ILogger; using Serilog; using Serilog.AspNetCore; @@ -53,12 +54,9 @@ namespace MediaBrowser.Server.Mono var appPaths = CreateApplicationPaths(applicationPath, customProgramDataPath); _appPaths = appPaths; - using (var loggerFactory = new SerilogLoggerFactory( - new LoggerConfiguration() - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger() - , true)) + createLogger(); + + using (var loggerFactory = new SerilogLoggerFactory()) { _loggerFactory = loggerFactory; @@ -156,6 +154,47 @@ namespace MediaBrowser.Server.Mono } } + private static async Task createLogger() + { + try + { + string path = Path.Combine(_appPaths.ProgramDataPath, "logging.json"); + + if (!File.Exists(path)) + { + var assembly = typeof(MainClass).Assembly; + // For some reason the csproj name is used instead of the assembly name + var resourcePath = "EmbyServer.Resources.Configuration.logging.json"; + using (Stream rscstr = assembly.GetManifestResourceStream(resourcePath)) + using (Stream fstr = File.Open(path, FileMode.CreateNew)) + { + await rscstr.CopyToAsync(fstr); + } + } + var configuration = new ConfigurationBuilder() + .AddJsonFile(path) + .Build(); + + Serilog.Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .Enrich.FromLogContext() + .CreateLogger(); + } + catch (Exception ex) + { + Serilog.Log.Logger = new LoggerConfiguration() + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}") + .WriteTo.File( + Path.Combine(AppContext.BaseDirectory, "logs", "log_.log"), + rollingInterval: RollingInterval.Day, + outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}") + .Enrich.FromLogContext() + .CreateLogger(); + + Serilog.Log.Logger.Fatal(ex, "Failed to read logger config"); + } + } + private static MonoEnvironmentInfo GetEnvironmentInfo() { var info = new MonoEnvironmentInfo(); diff --git a/MediaBrowser.Server.Mono/Resources/Configuration/logging.json b/MediaBrowser.Server.Mono/Resources/Configuration/logging.json new file mode 100644 index 000000000..68b57b276 --- /dev/null +++ b/MediaBrowser.Server.Mono/Resources/Configuration/logging.json @@ -0,0 +1,19 @@ +{ + "Serilog": { + "MinimumLevel": "Information", + "WriteTo": [ + { "Name": "Console", + "Args": { + "outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message}{NewLine}{Exception}" + } + }, + { "Name": "File", + "Args": { + "path": "logs//log_.log", + "rollingInterval": "Day", + "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}" + } + } + ] + } +} -- cgit v1.2.3 From 6d9ee138d6191ba33ec77b28cbc3543d59770e67 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 14 Dec 2018 23:34:53 +0100 Subject: More log dir configurable --- CONTRIBUTORS.md | 1 + MediaBrowser.Server.Mono/EmbyServer.csproj | 1 + MediaBrowser.Server.Mono/Program.cs | 15 +++++++++++---- .../Resources/Configuration/logging.json | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 467ba1522..3a2c229d1 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -7,6 +7,7 @@ - [EraYaN](https://github.com/EraYaN) - [flemse](https://github.com/flemse) - [bfayers](https://github.com/bfayers) + - [Bond_009](https://github.com/Bond-009) # Emby Contributors diff --git a/MediaBrowser.Server.Mono/EmbyServer.csproj b/MediaBrowser.Server.Mono/EmbyServer.csproj index da7883e6b..609af9674 100644 --- a/MediaBrowser.Server.Mono/EmbyServer.csproj +++ b/MediaBrowser.Server.Mono/EmbyServer.csproj @@ -17,6 +17,7 @@ + diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 1e47322f1..32953e89d 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -154,8 +154,13 @@ namespace MediaBrowser.Server.Mono } } - private static async Task createLogger() + private static void createLogger() { + var logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); + if (string.IsNullOrEmpty(logDir)){ + logDir = Path.Combine(_appPaths.ProgramDataPath, "logs"); + Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); + } try { string path = Path.Combine(_appPaths.ProgramDataPath, "logging.json"); @@ -168,11 +173,13 @@ namespace MediaBrowser.Server.Mono using (Stream rscstr = assembly.GetManifestResourceStream(resourcePath)) using (Stream fstr = File.Open(path, FileMode.CreateNew)) { - await rscstr.CopyToAsync(fstr); + rscstr.CopyTo(fstr); } } var configuration = new ConfigurationBuilder() - .AddJsonFile(path) + .SetBasePath(_appPaths.ProgramDataPath) + .AddJsonFile("logging.json") + .AddEnvironmentVariables("JELLYFIN_") .Build(); Serilog.Log.Logger = new LoggerConfiguration() @@ -185,7 +192,7 @@ namespace MediaBrowser.Server.Mono Serilog.Log.Logger = new LoggerConfiguration() .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}") .WriteTo.File( - Path.Combine(AppContext.BaseDirectory, "logs", "log_.log"), + Path.Combine(logDir, "logs", "log_.log"), rollingInterval: RollingInterval.Day, outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}") .Enrich.FromLogContext() diff --git a/MediaBrowser.Server.Mono/Resources/Configuration/logging.json b/MediaBrowser.Server.Mono/Resources/Configuration/logging.json index 68b57b276..78f99b2ad 100644 --- a/MediaBrowser.Server.Mono/Resources/Configuration/logging.json +++ b/MediaBrowser.Server.Mono/Resources/Configuration/logging.json @@ -4,12 +4,12 @@ "WriteTo": [ { "Name": "Console", "Args": { - "outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message}{NewLine}{Exception}" + "outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}" } }, { "Name": "File", "Args": { - "path": "logs//log_.log", + "path": "%JELLYFIN_LOG_DIR%//log_.log", "rollingInterval": "Day", "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}" } -- cgit v1.2.3 From a8fde5e89c106c4601e0535218d8fe858c6a3908 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 15 Dec 2018 00:06:57 +0100 Subject: Readded some stuff --- .../AppBase/BaseConfigurationManager.cs | 2 +- Emby.Server.Implementations/ApplicationHost.cs | 16 ++++++---------- .../Configuration/BaseApplicationConfiguration.cs | 2 ++ MediaBrowser.Server.Mono/Program.cs | 16 ++++++++++------ 4 files changed, 19 insertions(+), 17 deletions(-) (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index f55da91a8..fdf2a3b73 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.AppBase /// Initializes a new instance of the class. /// /// The application paths. - /// The log manager. + /// The logger factory. /// The XML serializer. protected BaseConfigurationManager(IApplicationPaths applicationPaths, ILoggerFactory loggerFactory, IXmlSerializer xmlSerializer, IFileSystem fileSystem) { diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 042e48e58..aa9b6e82a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -693,7 +693,7 @@ namespace Emby.Server.Implementations return parts; } - /*/ + /* private void SetBaseExceptionMessage() { var builder = GetBaseExceptionMessage(ApplicationPaths); @@ -799,13 +799,9 @@ namespace Emby.Server.Implementations } JsonSerializer = CreateJsonSerializer(); - /* - OnLoggerLoaded(true); - LoggerFactory.LoggerLoaded += (s, e) => OnLoggerLoaded(false); - LoggerFactory.LogSeverity = ConfigurationManager.CommonConfiguration.EnableDebugLevelLogging - ? LogSeverity.Debug - : LogSeverity.Info;*/ + OnLoggerLoaded(true); + //LoggerFactory.LoggerLoaded += (s, e) => OnLoggerLoaded(false); DiscoverTypes(); @@ -815,7 +811,7 @@ namespace Emby.Server.Implementations FindParts(); } - /* + protected virtual void OnLoggerLoaded(bool isFirstLoad) { Logger.LogInformation("Application version: {0}", ApplicationVersion); @@ -834,9 +830,9 @@ namespace Emby.Server.Implementations pluginBuilder.AppendLine(string.Format("{0} {1}", plugin.Name, plugin.Version)); } - Logger.LogMultiline("Plugins:", LogSeverity.Info, pluginBuilder); + Logger.LogInformation("Plugins: {plugins}", pluginBuilder.ToString()); } - }*/ + } protected virtual IHttpClient CreateHttpClient() { diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs index b5b0101cb..f84735bed 100644 --- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs +++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs @@ -9,6 +9,7 @@ namespace MediaBrowser.Model.Configuration /// public class BaseApplicationConfiguration { + // TODO: @bond Remove? /// /// Gets or sets a value indicating whether [enable debug level logging]. /// @@ -21,6 +22,7 @@ namespace MediaBrowser.Model.Configuration /// true if [enable auto update]; otherwise, false. public bool EnableAutoUpdate { get; set; } + // TODO: @bond Remove? /// /// The number of days we should retain log files /// diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 32953e89d..9c6ee4dd2 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -137,13 +137,14 @@ namespace MediaBrowser.Server.Mono return; } - Console.WriteLine("appHost.Init"); + //Console.WriteLine("appHost.Init"); appHost.Init(); appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); - Console.WriteLine("Running startup tasks"); + //Console.WriteLine("Running startup tasks"); + _logger.LogInformation("Running startup tasks"); var task = appHost.RunStartupTasks(); Task.WaitAll(task); @@ -291,10 +292,12 @@ namespace MediaBrowser.Server.Mono { var exception = (Exception)e.ExceptionObject; - // TODO - /* - new UnhandledExceptionWriter(_appPaths, _logger, _logManager, FileSystem, new ConsoleLogger()).Log(exception); + //new UnhandledExceptionWriter(_appPaths, _logger, _logManager, FileSystem, new ConsoleLogger()).Log(exception); + + _logger.LogCritical(exception, "Unhandled Exception"); + // TODO: @bond + /* if (!Debugger.IsAttached) { var message = LogHelper.GetLogMessage(exception).ToString(); @@ -304,7 +307,8 @@ namespace MediaBrowser.Server.Mono { Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(exception)); } - }*/ + } + */ } public static void Shutdown() -- cgit v1.2.3 From ea4c914123ba8279b9d9fcf7d5318e11f7a3da4c Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 20 Dec 2018 13:11:26 +0100 Subject: Fix exception logging --- Emby.Dlna/Didl/DidlBuilder.cs | 8 +- Emby.Dlna/DlnaManager.cs | 6 +- Emby.Dlna/Main/DlnaEntryPoint.cs | 12 +- Emby.Dlna/PlayTo/Device.cs | 6 +- Emby.Dlna/PlayTo/PlayToController.cs | 10 +- Emby.Dlna/PlayTo/PlayToManager.cs | 2 +- Emby.Dlna/Service/BaseControlHandler.cs | 2 +- Emby.Drawing.ImageMagick/ImageMagickEncoder.cs | 4 +- Emby.Drawing.Net/GDIImageEncoder.cs | 2 +- Emby.Drawing.Skia/SkiaEncoder.cs | 2 +- Emby.Drawing/ImageProcessor.cs | 10 +- Emby.Notifications/NotificationManager.cs | 6 +- Emby.Notifications/Notifications.cs | 2 +- Emby.Photos/PhotoProvider.cs | 4 +- .../Activity/ActivityRepository.cs | 228 ++++++++++----------- .../AppBase/BaseConfigurationManager.cs | 2 +- Emby.Server.Implementations/ApplicationHost.cs | 58 +++--- .../Channels/ChannelManager.cs | 6 +- .../Collections/CollectionManager.cs | 2 +- .../Data/BaseSqliteRepository.cs | 2 +- .../Data/SqliteDisplayPreferencesRepository.cs | 2 +- .../Data/SqliteItemRepository.cs | 2 +- .../Data/SqliteUserRepository.cs | 2 +- Emby.Server.Implementations/Devices/DeviceId.cs | 4 +- .../Devices/DeviceManager.cs | 2 +- Emby.Server.Implementations/Dto/DtoService.cs | 12 +- .../EntryPoints/AutomaticRestartEntryPoint.cs | 4 +- .../EntryPoints/ExternalPortForwarding.cs | 6 +- .../EntryPoints/KeepServerAwake.cs | 2 +- .../EntryPoints/LibraryChangedNotifier.cs | 4 +- .../EntryPoints/RecordingNotifier.cs | 2 +- .../EntryPoints/ServerEventNotifier.cs | 12 +- .../EntryPoints/UdpServerEntryPoint.cs | 2 +- .../EntryPoints/UsageEntryPoint.cs | 4 +- .../HttpClientManager/HttpClientManager.cs | 4 +- .../HttpServer/HttpListenerHost.cs | 14 +- .../HttpServer/ResponseFilter.cs | 2 +- .../HttpServer/WebSocketConnection.cs | 4 +- Emby.Server.Implementations/IO/FileRefresher.cs | 8 +- Emby.Server.Implementations/IO/LibraryMonitor.cs | 16 +- .../IO/ManagedFileSystem.cs | 6 +- .../Library/LibraryManager.cs | 33 ++- .../Library/MediaSourceManager.cs | 4 +- Emby.Server.Implementations/Library/UserManager.cs | 14 +- .../Library/Validators/ArtistsValidator.cs | 2 +- .../Library/Validators/GameGenresValidator.cs | 2 +- .../Library/Validators/GenresValidator.cs | 2 +- .../Library/Validators/MusicGenresValidator.cs | 2 +- .../Library/Validators/PeopleValidator.cs | 2 +- .../Library/Validators/StudiosValidator.cs | 2 +- .../LiveTv/EmbyTV/EmbyTV.cs | 52 ++--- .../LiveTv/EmbyTV/EncodedRecorder.cs | 24 +-- .../LiveTv/EmbyTV/ItemDataProvider.cs | 2 +- .../LiveTv/EmbyTV/TimerManager.cs | 6 +- .../LiveTv/Listings/SchedulesDirect.cs | 34 ++- .../LiveTv/LiveTvDtoService.cs | 9 +- .../LiveTv/LiveTvManager.cs | 16 +- .../LiveTv/TunerHosts/BaseTunerHost.cs | 8 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 84 ++++---- .../LiveTv/TunerHosts/LiveStream.cs | 6 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 +- .../MediaEncoder/EncodingManager.cs | 6 +- .../Networking/NetworkManager.cs | 10 +- Emby.Server.Implementations/News/NewsEntryPoint.cs | 2 +- Emby.Server.Implementations/ResourceFileManager.cs | 2 +- .../ScheduledTasks/PluginUpdateTask.cs | 4 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 10 +- .../ScheduledTasks/Tasks/DeleteCacheFileTask.cs | 8 +- .../Security/AuthenticationRepository.cs | 2 +- .../Security/PluginSecurityManager.cs | 11 +- Emby.Server.Implementations/Udp/UdpServer.cs | 12 +- .../Updates/InstallationManager.cs | 10 +- Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs | 4 +- MediaBrowser.Api/ApiEntryPoint.cs | 20 +- MediaBrowser.Api/Images/ImageService.cs | 2 +- MediaBrowser.Api/Library/LibraryService.cs | 2 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 4 +- MediaBrowser.Api/Playback/StreamState.cs | 6 +- MediaBrowser.Api/Playback/TranscodingThrottler.cs | 20 +- MediaBrowser.Api/PluginService.cs | 6 +- MediaBrowser.Api/Subtitles/SubtitleService.cs | 2 +- MediaBrowser.Common/Events/EventHelper.cs | 8 +- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../Entities/CollectionFolder.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 2 +- .../Entities/UserViewBuilder.cs | 10 +- MediaBrowser.Controller/IO/FileData.cs | 2 +- .../MediaEncoding/EncodingJobInfo.cs | 1 - .../Net/BasePeriodicWebSocketListener.cs | 2 +- MediaBrowser.Controller/Session/SessionInfo.cs | 4 +- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 6 +- .../Encoder/EncoderValidator.cs | 14 +- MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs | 4 +- .../Encoder/FontConfigLoader.cs | 12 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 34 +-- .../Probing/ProbeResultNormalizer.cs | 4 +- .../Subtitles/SubtitleEncoder.cs | 12 +- MediaBrowser.Providers/Manager/ImageSaver.cs | 4 +- .../Manager/ItemImageProvider.cs | 8 +- MediaBrowser.Providers/Manager/MetadataService.cs | 14 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 20 +- .../MediaInfo/FFProbeVideoInfo.cs | 2 +- .../MediaInfo/SubtitleDownloader.cs | 2 +- .../MediaInfo/SubtitleScheduledTask.cs | 2 +- .../Music/MusicBrainzAlbumProvider.cs | 2 +- .../Subtitles/SubtitleManager.cs | 4 +- MediaBrowser.Providers/TV/SeriesMetadataService.cs | 2 +- .../TV/TheMovieDb/MovieDbSeasonProvider.cs | 2 +- .../TV/TheTVDB/TvdbPrescanTask.cs | 2 +- MediaBrowser.Server.Mono/Program.cs | 2 +- .../SocketSharp/WebSocketSharpListener.cs | 6 +- .../SocketSharp/WebSocketSharpResponse.cs | 2 +- MediaBrowser.WebDashboard/Api/DashboardService.cs | 2 +- MediaBrowser.XbmcMetadata/EntryPoint.cs | 2 +- .../Parsers/MovieNfoParser.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 6 +- Mono.Nat/Pmp/PmpNatDevice.cs | 2 +- Mono.Nat/Upnp/Searchers/UpnpSearcher.cs | 2 +- RSSDP/SsdpCommunicationsServer.cs | 6 +- SocketHttpListener/Net/HttpEndPointListener.cs | 4 +- 123 files changed, 561 insertions(+), 603 deletions(-) (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 2cde379ea..6de35b842 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -913,9 +913,9 @@ namespace Emby.Dlna.Didl writer.WriteFullEndElement(); } - catch (XmlException) + catch (XmlException ex) { - _logger.LogError("Error adding xml value: {value}", name); + _logger.LogError(ex, "Error adding xml value: {value}", name); } } @@ -925,9 +925,9 @@ namespace Emby.Dlna.Didl { writer.WriteElementString(prefix, name, namespaceUri, value); } - catch (XmlException) + catch (XmlException ex) { - _logger.LogError("Error adding xml value: {value}", value); + _logger.LogError(ex, "Error adding xml value: {value}", value); } } diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 4c5bde6cd..eae4f3271 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -58,7 +58,7 @@ namespace Emby.Dlna } catch (Exception ex) { - _logger.LogError("Error extracting DLNA profiles.", ex); + _logger.LogError(ex, "Error extracting DLNA profiles."); } } @@ -198,7 +198,7 @@ namespace Emby.Dlna } catch (ArgumentException ex) { - _logger.LogError("Error evaluating regex pattern {0}", ex, pattern); + _logger.LogError(ex, "Error evaluating regex pattern {0}", pattern); return false; } } @@ -324,7 +324,7 @@ namespace Emby.Dlna } catch (Exception ex) { - _logger.LogError("Error parsing profile file: {0}", ex, path); + _logger.LogError(ex, "Error parsing profile file: {0}", path); return null; } diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 4697287e9..6ab0767a5 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -185,7 +185,7 @@ namespace Emby.Dlna.Main } catch (Exception ex) { - _logger.LogError("Error starting ssdp handlers", ex); + _logger.LogError(ex, "Error starting ssdp handlers"); } } @@ -202,7 +202,7 @@ namespace Emby.Dlna.Main } catch (Exception ex) { - _logger.LogError("Error starting device discovery", ex); + _logger.LogError(ex, "Error starting device discovery"); } } @@ -215,7 +215,7 @@ namespace Emby.Dlna.Main } catch (Exception ex) { - _logger.LogError("Error stopping device discovery", ex); + _logger.LogError(ex, "Error stopping device discovery"); } } @@ -243,7 +243,7 @@ namespace Emby.Dlna.Main } catch (Exception ex) { - _logger.LogError("Error registering endpoint", ex); + _logger.LogError(ex, "Error registering endpoint"); } } @@ -361,7 +361,7 @@ namespace Emby.Dlna.Main } catch (Exception ex) { - _logger.LogError("Error starting PlayTo manager", ex); + _logger.LogError(ex, "Error starting PlayTo manager"); } } } @@ -379,7 +379,7 @@ namespace Emby.Dlna.Main } catch (Exception ex) { - _logger.LogError("Error disposing PlayTo manager", ex); + _logger.LogError(ex, "Error disposing PlayTo manager"); } _manager = null; } diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 1cbb69d1d..a1df90ec0 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -140,7 +140,7 @@ namespace Emby.Dlna.PlayTo } catch (Exception ex) { - _logger.LogError("Error updating device volume info for {0}", ex, Properties.Name); + _logger.LogError(ex, "Error updating device volume info for {0}", Properties.Name); } } @@ -507,7 +507,7 @@ namespace Emby.Dlna.PlayTo if (_disposed) return; - //_logger.LogError("Error updating device info for {0}", ex, Properties.Name); + //_logger.LogError(ex, "Error updating device info for {0}", Properties.Name); _connectFailureCount++; @@ -767,7 +767,7 @@ namespace Emby.Dlna.PlayTo } catch (Exception ex) { - _logger.LogError("Unable to parse xml {0}", ex, trackString); + _logger.LogError(ex, "Unable to parse xml {0}", trackString); return new Tuple(true, null); } } diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index e722f83d8..c51f220ef 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -156,7 +156,7 @@ namespace Emby.Dlna.PlayTo } catch (Exception ex) { - _logger.LogError("Error reporting progress", ex); + _logger.LogError(ex, "Error reporting progress"); } } @@ -204,7 +204,7 @@ namespace Emby.Dlna.PlayTo } catch (Exception ex) { - _logger.LogError("Error reporting playback stopped", ex); + _logger.LogError(ex, "Error reporting playback stopped"); } } @@ -223,7 +223,7 @@ namespace Emby.Dlna.PlayTo } catch (Exception ex) { - _logger.LogError("Error reporting progress", ex); + _logger.LogError(ex, "Error reporting progress"); } } @@ -247,7 +247,7 @@ namespace Emby.Dlna.PlayTo } catch (Exception ex) { - _logger.LogError("Error reporting progress", ex); + _logger.LogError(ex, "Error reporting progress"); } } @@ -278,7 +278,7 @@ namespace Emby.Dlna.PlayTo } catch (Exception ex) { - _logger.LogError("Error reporting progress", ex); + _logger.LogError(ex, "Error reporting progress"); } } diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 0384d8f11..47d00aad5 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -121,7 +121,7 @@ namespace Emby.Dlna.PlayTo } catch (Exception ex) { - _logger.LogError("Error creating PlayTo device.", ex); + _logger.LogError(ex, "Error creating PlayTo device."); } finally { diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs index 55fe7fb80..ae094cc2f 100644 --- a/Emby.Dlna/Service/BaseControlHandler.cs +++ b/Emby.Dlna/Service/BaseControlHandler.cs @@ -52,7 +52,7 @@ namespace Emby.Dlna.Service } catch (Exception ex) { - _logger.LogError("Error processing control request", ex); + _logger.LogError(ex, "Error processing control request"); return new ControlErrorHandler().GetResponse(ex); } diff --git a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs index f5de730a1..6aac77cf4 100644 --- a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs @@ -103,7 +103,7 @@ namespace Emby.Drawing.ImageMagick } catch { - //_logger.LogError("Error loading webp: ", ex); + //_logger.LogError(ex, "Error loading webp: "); _webpAvailable = false; } } @@ -295,7 +295,7 @@ namespace Emby.Drawing.ImageMagick } catch (Exception ex) { - _logger.LogError("Error drawing indicator overlay", ex); + _logger.LogError(ex, "Error drawing indicator overlay"); } } diff --git a/Emby.Drawing.Net/GDIImageEncoder.cs b/Emby.Drawing.Net/GDIImageEncoder.cs index 4391cc618..1639125d3 100644 --- a/Emby.Drawing.Net/GDIImageEncoder.cs +++ b/Emby.Drawing.Net/GDIImageEncoder.cs @@ -214,7 +214,7 @@ namespace Emby.Drawing.Net } catch (Exception ex) { - _logger.LogError("Error drawing indicator overlay", ex); + _logger.LogError(ex, "Error drawing indicator overlay"); } } diff --git a/Emby.Drawing.Skia/SkiaEncoder.cs b/Emby.Drawing.Skia/SkiaEncoder.cs index 185b11f45..7a445a09c 100644 --- a/Emby.Drawing.Skia/SkiaEncoder.cs +++ b/Emby.Drawing.Skia/SkiaEncoder.cs @@ -660,7 +660,7 @@ namespace Emby.Drawing.Skia } catch (Exception ex) { - _logger.LogError("Error drawing indicator overlay", ex); + _logger.LogError(ex, "Error drawing indicator overlay"); } } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 8cbe5f96a..c417f3785 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -302,7 +302,7 @@ namespace Emby.Drawing { // Decoder failed to decode it #if DEBUG - _logger.LogError("Error encoding image", ex); + _logger.LogError(ex, "Error encoding image"); #endif // Just spit out the original file if all the options are default return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); @@ -310,7 +310,7 @@ namespace Emby.Drawing catch (Exception ex) { // If it fails for whatever reason, return the original image - _logger.LogError("Error encoding image", ex); + _logger.LogError(ex, "Error encoding image"); // Just spit out the original file if all the options are default return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); @@ -603,7 +603,7 @@ namespace Emby.Drawing } catch (Exception ex) { - _logger.LogError("Image conversion failed for {0}", ex, originalImagePath); + _logger.LogError(ex, "Image conversion failed for {originalImagePath}", originalImagePath); } } @@ -660,7 +660,7 @@ namespace Emby.Drawing } catch (Exception ex) { - _logger.LogError("Error enhancing image", ex); + _logger.LogError(ex, "Error enhancing image"); } return new ValueTuple(originalImagePath, dateModified, inputImageSupportsTransparency); @@ -853,7 +853,7 @@ namespace Emby.Drawing } catch (Exception ex) { - _logger.LogError("Error in image enhancer: {0}", ex, i.GetType().Name); + _logger.LogError(ex, "Error in image enhancer: {0}", i.GetType().Name); } } diff --git a/Emby.Notifications/NotificationManager.cs b/Emby.Notifications/NotificationManager.cs index 209bc82aa..fa8fdd9c1 100644 --- a/Emby.Notifications/NotificationManager.cs +++ b/Emby.Notifications/NotificationManager.cs @@ -134,7 +134,7 @@ namespace Emby.Notifications } catch (Exception ex) { - _logger.LogError("Error sending notification to {0}", ex, service.Name); + _logger.LogError(ex, "Error sending notification to {0}", service.Name); } } @@ -146,7 +146,7 @@ namespace Emby.Notifications } catch (Exception ex) { - _logger.LogError("Error in IsEnabledForUser", ex); + _logger.LogError(ex, "Error in IsEnabledForUser"); return false; } } @@ -177,7 +177,7 @@ namespace Emby.Notifications } catch (Exception ex) { - _logger.LogError("Error in GetNotificationTypes", ex); + _logger.LogError(ex, "Error in GetNotificationTypes"); return new List(); } diff --git a/Emby.Notifications/Notifications.cs b/Emby.Notifications/Notifications.cs index ab78f9f91..c09c4d449 100644 --- a/Emby.Notifications/Notifications.cs +++ b/Emby.Notifications/Notifications.cs @@ -273,7 +273,7 @@ namespace Emby.Notifications } catch (Exception ex) { - _logger.LogError("Error sending notification", ex); + _logger.LogError(ex, "Error sending notification"); } } diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index ace3b2afb..726fd1d79 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -170,9 +170,9 @@ namespace Emby.Photos } } } - catch (Exception e) + catch (Exception ex) { - _logger.LogError("Image Provider - Error reading image tag for {0}", e, item.Path); + _logger.LogError(ex, "Image Provider - Error reading image tag for {0}", item.Path); } } diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs index a84d6d45f..fcdcb0c2c 100644 --- a/Emby.Server.Implementations/Activity/ActivityRepository.cs +++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Activity } catch (Exception ex) { - Logger.LogError("Error loading database file. Will reset and retry.", ex); + Logger.LogError(ex, "Error loading database file. Will reset and retry."); FileSystem.DeleteFile(DbFilePath); @@ -73,7 +73,7 @@ namespace Emby.Server.Implementations.Activity } catch (Exception ex) { - Logger.LogError("Error migrating activity log database", ex); + Logger.LogError(ex, "Error migrating activity log database"); } } @@ -87,36 +87,34 @@ namespace Emby.Server.Implementations.Activity } using (WriteLock.Write()) + using (var connection = CreateConnection()) { - using (var connection = CreateConnection()) + connection.RunInTransaction(db => { - connection.RunInTransaction(db => + using (var statement = db.PrepareStatement("insert into ActivityLog (Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)")) { - using (var statement = db.PrepareStatement("insert into ActivityLog (Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)")) + statement.TryBind("@Name", entry.Name); + + statement.TryBind("@Overview", entry.Overview); + statement.TryBind("@ShortOverview", entry.ShortOverview); + statement.TryBind("@Type", entry.Type); + statement.TryBind("@ItemId", entry.ItemId); + + if (entry.UserId.Equals(Guid.Empty)) { - statement.TryBind("@Name", entry.Name); - - statement.TryBind("@Overview", entry.Overview); - statement.TryBind("@ShortOverview", entry.ShortOverview); - statement.TryBind("@Type", entry.Type); - statement.TryBind("@ItemId", entry.ItemId); - - if (entry.UserId.Equals(Guid.Empty)) - { - statement.TryBindNull("@UserId"); - } - else - { - statement.TryBind("@UserId", entry.UserId.ToString("N")); - } - - statement.TryBind("@DateCreated", entry.Date.ToDateTimeParamValue()); - statement.TryBind("@LogSeverity", entry.Severity.ToString()); - - statement.MoveNext(); + statement.TryBindNull("@UserId"); } - }, TransactionMode); - } + else + { + statement.TryBind("@UserId", entry.UserId.ToString("N")); + } + + statement.TryBind("@DateCreated", entry.Date.ToDateTimeParamValue()); + statement.TryBind("@LogSeverity", entry.Severity.ToString()); + + statement.MoveNext(); + } + }, TransactionMode); } } @@ -128,132 +126,128 @@ namespace Emby.Server.Implementations.Activity } using (WriteLock.Write()) + using (var connection = CreateConnection()) { - using (var connection = CreateConnection()) + connection.RunInTransaction(db => { - connection.RunInTransaction(db => + using (var statement = db.PrepareStatement("Update ActivityLog set Name=@Name,Overview=@Overview,ShortOverview=@ShortOverview,Type=@Type,ItemId=@ItemId,UserId=@UserId,DateCreated=@DateCreated,LogSeverity=@LogSeverity where Id=@Id")) { - using (var statement = db.PrepareStatement("Update ActivityLog set Name=@Name,Overview=@Overview,ShortOverview=@ShortOverview,Type=@Type,ItemId=@ItemId,UserId=@UserId,DateCreated=@DateCreated,LogSeverity=@LogSeverity where Id=@Id")) + statement.TryBind("@Id", entry.Id); + + statement.TryBind("@Name", entry.Name); + statement.TryBind("@Overview", entry.Overview); + statement.TryBind("@ShortOverview", entry.ShortOverview); + statement.TryBind("@Type", entry.Type); + statement.TryBind("@ItemId", entry.ItemId); + + if (entry.UserId.Equals(Guid.Empty)) { - statement.TryBind("@Id", entry.Id); - - statement.TryBind("@Name", entry.Name); - statement.TryBind("@Overview", entry.Overview); - statement.TryBind("@ShortOverview", entry.ShortOverview); - statement.TryBind("@Type", entry.Type); - statement.TryBind("@ItemId", entry.ItemId); - - if (entry.UserId.Equals(Guid.Empty)) - { - statement.TryBindNull("@UserId"); - } - else - { - statement.TryBind("@UserId", entry.UserId.ToString("N")); - } - - statement.TryBind("@DateCreated", entry.Date.ToDateTimeParamValue()); - statement.TryBind("@LogSeverity", entry.Severity.ToString()); - - statement.MoveNext(); + statement.TryBindNull("@UserId"); } - }, TransactionMode); - } + else + { + statement.TryBind("@UserId", entry.UserId.ToString("N")); + } + + statement.TryBind("@DateCreated", entry.Date.ToDateTimeParamValue()); + statement.TryBind("@LogSeverity", entry.Severity.ToString()); + + statement.MoveNext(); + } + }, TransactionMode); } } public QueryResult GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? startIndex, int? limit) { using (WriteLock.Read()) + using (var connection = CreateConnection(true)) { - using (var connection = CreateConnection(true)) - { - var commandText = BaseActivitySelectText; - var whereClauses = new List(); + var commandText = BaseActivitySelectText; + var whereClauses = new List(); - if (minDate.HasValue) + if (minDate.HasValue) + { + whereClauses.Add("DateCreated>=@DateCreated"); + } + if (hasUserId.HasValue) + { + if (hasUserId.Value) { - whereClauses.Add("DateCreated>=@DateCreated"); + whereClauses.Add("UserId not null"); } - if (hasUserId.HasValue) + else { - if (hasUserId.Value) - { - whereClauses.Add("UserId not null"); - } - else - { - whereClauses.Add("UserId is null"); - } + whereClauses.Add("UserId is null"); } + } - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - if (startIndex.HasValue && startIndex.Value > 0) - { - var pagingWhereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); - whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLog {0} ORDER BY DateCreated DESC LIMIT {1})", - pagingWhereText, - startIndex.Value.ToString(_usCulture))); - } - - var whereText = whereClauses.Count == 0 ? + if (startIndex.HasValue && startIndex.Value > 0) + { + var pagingWhereText = whereClauses.Count == 0 ? string.Empty : " where " + string.Join(" AND ", whereClauses.ToArray()); - commandText += whereText; + whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLog {0} ORDER BY DateCreated DESC LIMIT {1})", + pagingWhereText, + startIndex.Value.ToString(_usCulture))); + } - commandText += " ORDER BY DateCreated DESC"; + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); - if (limit.HasValue) - { - commandText += " LIMIT " + limit.Value.ToString(_usCulture); - } + commandText += whereText; - var statementTexts = new List(); - statementTexts.Add(commandText); - statementTexts.Add("select count (Id) from ActivityLog" + whereTextWithoutPaging); + commandText += " ORDER BY DateCreated DESC"; - return connection.RunInTransaction(db => - { - var list = new List(); - var result = new QueryResult(); + if (limit.HasValue) + { + commandText += " LIMIT " + limit.Value.ToString(_usCulture); + } - var statements = PrepareAllSafe(db, statementTexts).ToList(); + var statementTexts = new List(); + statementTexts.Add(commandText); + statementTexts.Add("select count (Id) from ActivityLog" + whereTextWithoutPaging); + + return connection.RunInTransaction(db => + { + var list = new List(); + var result = new QueryResult(); - using (var statement = statements[0]) + var statements = PrepareAllSafe(db, statementTexts).ToList(); + + using (var statement = statements[0]) + { + if (minDate.HasValue) { - if (minDate.HasValue) - { - statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); - } - - foreach (var row in statement.ExecuteQuery()) - { - list.Add(GetEntry(row)); - } + statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); } - using (var statement = statements[1]) + foreach (var row in statement.ExecuteQuery()) { - if (minDate.HasValue) - { - statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); - } + list.Add(GetEntry(row)); + } + } - result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); + using (var statement = statements[1]) + { + if (minDate.HasValue) + { + statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); } - result.Items = list.ToArray(); - return result; + result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); + } - }, ReadTransactionMode); - } + result.Items = list.ToArray(list.Count); + return result; + + }, ReadTransactionMode); } } diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index fdf2a3b73..fddf19893 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -259,7 +259,7 @@ namespace Emby.Server.Implementations.AppBase } catch (Exception ex) { - Logger.LogError("Error loading configuration file: {0}", ex, path); + Logger.LogError(ex, "Error loading configuration file: {path}", path); return Activator.CreateInstance(configurationType); } diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index aa9b6e82a..888635c9d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -545,7 +545,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error creating {0}", ex, type.FullName); + Logger.LogError(ex, "Error creating {type}", type.FullName); // Don't blow up in release mode return null; } @@ -625,7 +625,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error loading assembly {0}", ex, file); + Logger.LogError(ex, "Error loading assembly {file}", file); return null; } } @@ -648,7 +648,7 @@ namespace Emby.Server.Implementations /// /// if set to true [manage liftime]. /// IEnumerable{``0}. - public IEnumerable GetExports(bool manageLiftime = true) + public IEnumerable GetExports(bool manageLifetime = true) { var parts = GetExportTypes() .Select(CreateInstanceSafe) @@ -656,7 +656,7 @@ namespace Emby.Server.Implementations .Cast() .ToList(); - if (manageLiftime) + if (manageLifetime) { lock (DisposableParts) { @@ -667,7 +667,7 @@ namespace Emby.Server.Implementations return parts; } - public List> GetExportsWithInfo(bool manageLiftime = true) + public List> GetExportsWithInfo(bool manageLifetime = true) { var parts = GetExportTypes() .Select(i => @@ -683,7 +683,7 @@ namespace Emby.Server.Implementations .Where(i => i != null) .ToList(); - if (manageLiftime) + if (manageLifetime) { lock (DisposableParts) { @@ -693,6 +693,8 @@ namespace Emby.Server.Implementations return parts; } + + // TODO: @bond /* private void SetBaseExceptionMessage() { @@ -760,7 +762,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error in {0}", ex, name); + Logger.LogError(ex, "Error in {name}", name); } Logger.LogInformation("Entry point completed: {0}. Duration: {1} seconds", name, (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture), "ImageInfos"); } @@ -777,7 +779,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error configuring autorun", ex); + Logger.LogError(ex, "Error configuring autorun"); } } @@ -1119,7 +1121,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error setting http limit", ex); + Logger.LogError(ex, "Error setting http limit"); } } @@ -1186,7 +1188,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error loading cert from {0}", ex, certificateLocation); + Logger.LogError(ex, "Error loading cert from {certificateLocation}", certificateLocation); return null; } } @@ -1415,7 +1417,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error getting plugin Id from {0}.", ex, plugin.GetType().FullName); + Logger.LogError(ex, "Error getting plugin Id from {pluginName}.", plugin.GetType().FullName); } } @@ -1427,7 +1429,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error loading plugin {0}", ex, plugin.GetType().FullName); + Logger.LogError(ex, "Error loading plugin {pluginName}", plugin.GetType().FullName); return null; } @@ -1450,11 +1452,11 @@ namespace Emby.Server.Implementations if (path == null) { - Logger.LogInformation("Loading {0}", assembly.FullName); + Logger.LogInformation("Loading {assemblyName}", assembly.FullName); } else { - Logger.LogInformation("Loading {0} from {1}", assembly.FullName, path); + Logger.LogInformation("Loading {assemblyName} from {path}", assembly.FullName, path); } } @@ -1507,7 +1509,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error loading types from assembly", ex); + Logger.LogError(ex, "Error loading types from assembly"); return new List>(); } @@ -1554,7 +1556,7 @@ namespace Emby.Server.Implementations ? "The http server is unable to start due to a Socket error. This can occasionally happen when the operating system takes longer than usual to release the IP bindings from the previous session. This can take up to five minutes. Please try waiting or rebooting the system." : "Error starting Http Server"; - Logger.LogError(msg, ex); + Logger.LogError(ex, msg); if (HttpPort == ServerConfiguration.DefaultHttpPort) { @@ -1570,7 +1572,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error starting http server", ex); + Logger.LogError(ex, "Error starting http server"); throw; } @@ -1605,7 +1607,7 @@ namespace Emby.Server.Implementations // } // catch (Exception ex) // { - // Logger.LogError("Error creating ssl cert", ex); + // Logger.LogError(ex, "Error creating ssl cert"); // return null; // } // } @@ -1710,7 +1712,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error sending server restart notification", ex); + Logger.LogError(ex, "Error sending server restart notification"); } Logger.LogInformation("Calling RestartInternal"); @@ -1845,7 +1847,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error getting version number from {0}", ex, path); + Logger.LogError(ex, "Error getting version number from {path}", path); return new Version(1, 0); } @@ -1930,13 +1932,13 @@ namespace Emby.Server.Implementations if (version < minRequiredVersion) { - Logger.LogInformation("Not loading {0} {1} because the minimum supported version is {2}. Please update to the newer version", filename, version, minRequiredVersion); + Logger.LogInformation("Not loading {filename} {version} because the minimum supported version is {minRequiredVersion}. Please update to the newer version", filename, version, minRequiredVersion); return false; } } catch (Exception ex) { - Logger.LogError("Error getting version number from {0}", ex, path); + Logger.LogError(ex, "Error getting version number from {path}", path); return false; } @@ -2043,7 +2045,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error getting local Ip address information", ex); + Logger.LogError(ex, "Error getting local Ip address information"); } return null; @@ -2251,7 +2253,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error sending server shutdown notification", ex); + Logger.LogError(ex, "Error sending server shutdown notification"); } ShutdownInternal(); @@ -2276,7 +2278,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error authorizing server", ex); + Logger.LogError(ex, "Error authorizing server"); } } @@ -2443,9 +2445,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Console.WriteLine("Error launching url: {0}", url); - Logger.LogError("Error launching url: {0}", ex, url); - + Logger.LogError(ex, "Error launching url: {url}", url); throw; } } @@ -2516,7 +2516,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError("Error disposing {0}", ex, part.GetType().Name); + Logger.LogError(ex, "Error disposing {0}", part.GetType().Name); } } } diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 88dfbd7c1..00da46f30 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -300,7 +300,7 @@ namespace Emby.Server.Implementations.Channels } catch (Exception ex) { - _logger.LogError("Error getting channel information for {0}", ex, channelInfo.Name); + _logger.LogError(ex, "Error getting channel information for {0}", channelInfo.Name); } numComplete++; @@ -848,7 +848,7 @@ namespace Emby.Server.Implementations.Channels } catch (Exception ex) { - _logger.LogError("Error writing to channel cache file: {0}", ex, path); + _logger.LogError(ex, "Error writing to channel cache file: {path}", path); } } @@ -911,7 +911,7 @@ namespace Emby.Server.Implementations.Channels } catch (Exception ex) { - _logger.LogError("Error retrieving channel item from database", ex); + _logger.LogError(ex, "Error retrieving channel item from database"); } if (item == null) diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index af7c70d7d..d1afb0712 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -365,7 +365,7 @@ namespace Emby.Server.Implementations.Collections } catch (Exception ex) { - _logger.LogError("Error creating camera uploads library", ex); + _logger.LogError(ex, "Error creating camera uploads library"); } _config.Configuration.CollectionsUpgraded = true; diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 8e59596dd..59776c373 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -323,7 +323,7 @@ namespace Emby.Server.Implementations.Data } catch (Exception ex) { - Logger.LogError("Error disposing database", ex); + Logger.LogError(ex, "Error disposing database"); } } diff --git a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs index 307342135..00e1956cf 100644 --- a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs @@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.Data } catch (Exception ex) { - Logger.LogError("Error loading database file. Will reset and retry.", ex); + Logger.LogError(ex, "Error loading database file. Will reset and retry."); FileSystem.DeleteFile(DbFilePath); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 7239eec93..0f9770e8f 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1364,7 +1364,7 @@ namespace Emby.Server.Implementations.Data } catch (SerializationException ex) { - Logger.LogError("Error deserializing item", ex); + Logger.LogError(ex, "Error deserializing item"); } } } diff --git a/Emby.Server.Implementations/Data/SqliteUserRepository.cs b/Emby.Server.Implementations/Data/SqliteUserRepository.cs index 9ac255ec4..d490a481e 100644 --- a/Emby.Server.Implementations/Data/SqliteUserRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserRepository.cs @@ -74,7 +74,7 @@ namespace Emby.Server.Implementations.Data } catch (Exception ex) { - Logger.LogError("Error migrating users database", ex); + Logger.LogError(ex, "Error migrating users database"); } } diff --git a/Emby.Server.Implementations/Devices/DeviceId.cs b/Emby.Server.Implementations/Devices/DeviceId.cs index fe953bfb9..90cef5d06 100644 --- a/Emby.Server.Implementations/Devices/DeviceId.cs +++ b/Emby.Server.Implementations/Devices/DeviceId.cs @@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.Devices } catch (Exception ex) { - _logger.LogError("Error reading file", ex); + _logger.LogError(ex, "Error reading file"); } return null; @@ -66,7 +66,7 @@ namespace Emby.Server.Implementations.Devices } catch (Exception ex) { - _logger.LogError("Error writing to file", ex); + _logger.LogError(ex, "Error writing to file"); } } diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index c5c86f5b9..250316211 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -434,7 +434,7 @@ namespace Emby.Server.Implementations.Devices } catch (Exception ex) { - _logger.LogError("Error creating camera uploads library", ex); + _logger.LogError(ex, "Error creating camera uploads library"); } _config.Configuration.CameraUploadUpgraded = true; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 424309995..e8d06ec00 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -225,7 +225,7 @@ namespace Emby.Server.Implementations.Dto catch (Exception ex) { // Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions - _logger.LogError("Error generating PrimaryImageAspectRatio for {0}", ex, item.Name); + _logger.LogError(ex, "Error generating PrimaryImageAspectRatio for {itemName}", item.Name); } } @@ -547,7 +547,7 @@ namespace Emby.Server.Implementations.Dto } catch (Exception ex) { - _logger.LogError("Error getting {0} image info", ex, type); + _logger.LogError(ex, "Error getting {type} image info", type); return null; } } @@ -560,7 +560,7 @@ namespace Emby.Server.Implementations.Dto } catch (Exception ex) { - _logger.LogError("Error getting {0} image info for {1}", ex, image.Type, image.Path); + _logger.LogError(ex, "Error getting {imageType} image info for {path}", image.Type, image.Path); return null; } } @@ -619,7 +619,7 @@ namespace Emby.Server.Implementations.Dto } catch (Exception ex) { - _logger.LogError("Error getting person {0}", ex, c); + _logger.LogError(ex, "Error getting person {0}", c); return null; } @@ -1451,7 +1451,7 @@ namespace Emby.Server.Implementations.Dto } catch (Exception ex) { - //_logger.LogError("Failed to determine primary image aspect ratio for {0}", ex, imageInfo.Path); + _logger.LogError(ex, "Failed to determine primary image aspect ratio for {0}", imageInfo.Path); return null; } } @@ -1464,7 +1464,7 @@ namespace Emby.Server.Implementations.Dto } catch (Exception ex) { - _logger.LogError("Error in image enhancer: {0}", ex, enhancer.GetType().Name); + _logger.LogError(ex, "Error in image enhancer: {0}", enhancer.GetType().Name); } } diff --git a/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs index cd5fca40d..a0947c87d 100644 --- a/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs @@ -73,7 +73,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.LogError("Error restarting server", ex); + _logger.LogError(ex, "Error restarting server"); } } } @@ -98,7 +98,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.LogError("Error getting timers", ex); + _logger.LogError(ex, "Error getting timers"); } } diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 46fbc94fd..a95e21e1c 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -216,7 +216,7 @@ namespace Emby.Server.Implementations.EntryPoints catch { // Commenting out because users are reporting problems out of our control - //_logger.LogError("Error creating port forwarding rules", ex); + //_logger.LogError(ex, "Error creating port forwarding rules"); } } @@ -253,6 +253,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { + _logger.LogError(ex, "Error creating http port map"); return; } @@ -262,6 +263,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { + _logger.LogError(ex, "Error creating https port map"); } } @@ -309,7 +311,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.LogError("Error stopping NAT Discovery", ex); + _logger.LogError(ex, "Error stopping NAT Discovery"); } } } diff --git a/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs b/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs index a9121ba32..a6dadcef0 100644 --- a/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs +++ b/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs @@ -49,7 +49,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.LogError("Error resetting system standby timer", ex); + _logger.LogError(ex, "Error resetting system standby timer"); } } diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index ff283667b..bb8ef52f1 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -331,7 +331,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.LogError("Error in GetLibraryUpdateInfo", ex); + _logger.LogError(ex, "Error in GetLibraryUpdateInfo"); return; } @@ -346,7 +346,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.LogError("Error sending LibraryChanged message", ex); + _logger.LogError(ex, "Error sending LibraryChanged message"); } } } diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs index 24cd659e1..0b377dc68 100644 --- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs @@ -66,7 +66,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.LogError("Error sending message", ex); + _logger.LogError(ex, "Error sending message"); } } diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index f6a74c4ec..72dcabab3 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -156,14 +156,10 @@ namespace Emby.Server.Implementations.EntryPoints try { await _sessionManager.SendMessageToAdminSessions(name, data, CancellationToken.None); - } - catch (ObjectDisposedException) - { - } catch (Exception) { - //Logger.LogError("Error sending message", ex); + } } @@ -172,14 +168,10 @@ namespace Emby.Server.Implementations.EntryPoints try { await _sessionManager.SendMessageToUserSessions(new List { user.Id }, name, data, CancellationToken.None); - } - catch (ObjectDisposedException) - { - } catch (Exception) { - //Logger.LogError("Error sending message", ex); + } } diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index 1bb11ce40..f8e2d32dd 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.LogError("Failed to start UDP Server", ex); + _logger.LogError(ex, "Failed to start UDP Server"); } } diff --git a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs index ca79262b0..f7542a5e9 100644 --- a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs @@ -91,7 +91,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - //_logger.LogError("Error sending anonymous usage statistics.", ex); + _logger.LogError(ex, "Error sending anonymous usage statistics."); } } @@ -119,7 +119,7 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception ex) { - //_logger.LogError("Error sending anonymous usage statistics.", ex); + _logger.LogError(ex, "Error sending anonymous usage statistics."); } } diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index b3f8ef884..23dd55b18 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -685,7 +685,7 @@ namespace Emby.Server.Implementations.HttpClientManager { if (options.LogErrors) { - _logger.LogError("Error " + webException.Status + " getting response from " + options.Url, webException); + _logger.LogError(webException, "Error {status} getting response from {url}", webException.Status, options.Url); } var exception = new HttpException(webException.Message, webException); @@ -723,7 +723,7 @@ namespace Emby.Server.Implementations.HttpClientManager if (options.LogErrors) { - _logger.LogError("Error getting response from " + options.Url, ex); + _logger.LogError(ex, "Error getting response from {url}", options.Url); } return ex; diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 1d87d0e44..704b7f8a6 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -252,7 +252,7 @@ namespace Emby.Server.Implementations.HttpServer if (logExceptionStackTrace) { - _logger.LogError("Error processing request", ex); + _logger.LogError(ex, "Error processing request"); } else if (logExceptionMessage) { @@ -272,9 +272,9 @@ namespace Emby.Server.Implementations.HttpServer httpRes.ContentType = "text/html"; await Write(httpRes, NormalizeExceptionMessage(ex.Message)).ConfigureAwait(false); } - catch + catch (Exception errorEx) { - //_logger.LogError("Error this.ProcessRequest(context)(Exception while writing error to the response)", errorEx); + _logger.LogError(errorEx, "Error this.ProcessRequest(context)(Exception while writing error to the response)"); } } @@ -713,7 +713,7 @@ namespace Emby.Server.Implementations.HttpServer var pathParts = pathInfo.TrimStart('/').Split('/'); if (pathParts.Length == 0) { - _logger.LogError("Path parts empty for PathInfo: {0}, Url: {1}", pathInfo, httpReq.RawUrl); + _logger.LogError("Path parts empty for PathInfo: {pathInfo}, Url: {RawUrl}", pathInfo, httpReq.RawUrl); return null; } @@ -729,7 +729,7 @@ namespace Emby.Server.Implementations.HttpServer }; } - _logger.LogError("Could not find handler for {0}", pathInfo); + _logger.LogError("Could not find handler for {pathInfo}", pathInfo); return null; } @@ -919,7 +919,7 @@ namespace Emby.Server.Implementations.HttpServer return Task.CompletedTask; } - //_logger.LogDebug("Websocket message received: {0}", result.MessageType); + _logger.LogDebug("Websocket message received: {0}", result.MessageType); var tasks = _webSocketListeners.Select(i => Task.Run(async () => { @@ -929,7 +929,7 @@ namespace Emby.Server.Implementations.HttpServer } catch (Exception ex) { - _logger.LogError("{0} failed processing WebSocket message {1}", ex, i.GetType().Name, result.MessageType ?? string.Empty); + _logger.LogError(ex, "{0} failed processing WebSocket message {1}", i.GetType().Name, result.MessageType ?? string.Empty); } })); diff --git a/Emby.Server.Implementations/HttpServer/ResponseFilter.cs b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs index b1759069c..f38aa5ea0 100644 --- a/Emby.Server.Implementations/HttpServer/ResponseFilter.cs +++ b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.HttpServer if (exception != null) { - _logger.LogError("Error processing request for {0}", exception, req.RawUrl); + _logger.LogError(exception, "Error processing request for {RawUrl}", req.RawUrl); if (!string.IsNullOrEmpty(exception.Message)) { diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 037bdde77..8b5dfd444 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -180,7 +180,7 @@ namespace Emby.Server.Implementations.HttpServer if (!message.StartsWith("{", StringComparison.OrdinalIgnoreCase)) { // This info is useful sometimes but also clogs up the log - //_lLogError("Received web socket message that is not a json structure: " + message); + _logger.LogDebug("Received web socket message that is not a json structure: {message}", message); return; } @@ -204,7 +204,7 @@ namespace Emby.Server.Implementations.HttpServer } catch (Exception ex) { - _logger.LogError("Error processing web socket message", ex); + _logger.LogError(ex, "Error processing web socket message"); } } diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index 6087f3cf2..df484d04c 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -141,7 +141,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError("Error processing directory changes", ex); + Logger.LogError(ex, "Error processing directory changes"); } } @@ -161,7 +161,7 @@ namespace Emby.Server.Implementations.IO continue; } - Logger.LogInformation(item.Name + " (" + item.Path + ") will be refreshed."); + Logger.LogInformation("{name} ({path}}) will be refreshed.", item.Name, item.Path); try { @@ -172,11 +172,11 @@ namespace Emby.Server.Implementations.IO // For now swallow and log. // Research item: If an IOException occurs, the item may be in a disconnected state (media unavailable) // Should we remove it from it's parent? - Logger.LogError("Error refreshing {0}", ex, item.Name); + Logger.LogError(ex, "Error refreshing {name}", item.Name); } catch (Exception ex) { - Logger.LogError("Error refreshing {0}", ex, item.Name); + Logger.LogError(ex, "Error refreshing {name}", item.Name); } } } diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 22d1783ed..ca5810fd6 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError("Error in ReportFileSystemChanged for {0}", ex, path); + Logger.LogError(ex, "Error in ReportFileSystemChanged for {path}", path); } } } @@ -354,7 +354,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError("Error watching path: {0}", ex, path); + Logger.LogError(ex, "Error watching path: {path}", path); } }); } @@ -382,7 +382,7 @@ namespace Emby.Server.Implementations.IO { using (watcher) { - Logger.LogInformation("Stopping directory watching for path {0}", watcher.Path); + Logger.LogInformation("Stopping directory watching for path {path}", watcher.Path); watcher.Created -= watcher_Changed; watcher.Deleted -= watcher_Changed; @@ -439,7 +439,7 @@ namespace Emby.Server.Implementations.IO var ex = e.GetException(); var dw = (FileSystemWatcher)sender; - Logger.LogError("Error in Directory watcher for: " + dw.Path, ex); + Logger.LogError(ex, "Error in Directory watcher for: {path}", dw.Path); DisposeWatcher(dw, true); } @@ -461,7 +461,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError("Exception in ReportFileSystemChanged. Path: {0}", ex, e.FullPath); + Logger.LogError(ex, "Exception in ReportFileSystemChanged. Path: {FullPath}", e.FullPath); } } @@ -487,13 +487,13 @@ namespace Emby.Server.Implementations.IO { if (_fileSystem.AreEqual(i, path)) { - //logger.LogDebug("Ignoring change to {0}", path); + Logger.LogDebug("Ignoring change to {path}", path); return true; } if (_fileSystem.ContainsSubPath(i, path)) { - //logger.LogDebug("Ignoring change to {0}", path); + Logger.LogDebug("Ignoring change to {path}", path); return true; } @@ -503,7 +503,7 @@ namespace Emby.Server.Implementations.IO { if (_fileSystem.AreEqual(parent, path)) { - //logger.LogDebug("Ignoring change to {0}", path); + Logger.LogDebug("Ignoring change to {path}", path); return true; } } diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 42b9ae23b..8819449b5 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -175,7 +175,7 @@ namespace Emby.Server.Implementations.IO path = System.IO.Path.GetFullPath(path); return path; } - catch (ArgumentException ex) + catch (ArgumentException) { return filePath; } @@ -395,7 +395,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError("Error determining CreationTimeUtc for {0}", ex, info.FullName); + Logger.LogError(ex, "Error determining CreationTimeUtc for {FullName}", info.FullName); return DateTime.MinValue; } } @@ -434,7 +434,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError("Error determining LastAccessTimeUtc for {0}", ex, info.FullName); + Logger.LogError(ex, "Error determining LastAccessTimeUtc for {FullName}", info.FullName); return DateTime.MinValue; } } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index e1a725c93..451f16bef 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -384,7 +384,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error deleting {0}", ex, metadataPath); + _logger.LogError(ex, "Error deleting {metadataPath}", metadataPath); } } @@ -398,14 +398,13 @@ namespace Emby.Server.Implementations.Library { try { + _logger.LogDebug("Deleting path {path}", fileSystemInfo.FullName); if (fileSystemInfo.IsDirectory) { - _logger.LogDebug("Deleting path {0}", fileSystemInfo.FullName); _fileSystem.DeleteDirectory(fileSystemInfo.FullName, true); } else { - _logger.LogDebug("Deleting path {0}", fileSystemInfo.FullName); _fileSystem.DeleteFile(fileSystemInfo.FullName); } } @@ -489,7 +488,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error in {0} resolving {1}", ex, resolver.GetType().Name, args.Path); + _logger.LogError(ex, "Error in {resolver} resolving {path}", resolver.GetType().Name, args.Path); return null; } } @@ -587,7 +586,7 @@ namespace Emby.Server.Implementations.Library { if (parent != null && parent.IsPhysicalRoot) { - _logger.LogError("Error in GetFilteredFileSystemEntries isPhysicalRoot: {0} IsVf: {1}", ex, isPhysicalRoot, isVf); + _logger.LogError(ex, "Error in GetFilteredFileSystemEntries isPhysicalRoot: {0} IsVf: {1}", isPhysicalRoot, isVf); files = new FileSystemMetadata[] { }; } @@ -713,7 +712,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error resolving path {0}", ex, f.FullName); + _logger.LogError(ex, "Error resolving path {path}", f.FullName); return null; } }).Where(i => i != null); @@ -1148,7 +1147,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error running postscan task", ex); + _logger.LogError(ex, "Error running postscan task"); } numComplete++; @@ -1199,7 +1198,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error resolving shortcut file {0}", ex, i); + _logger.LogError(ex, "Error resolving shortcut file {file}", i); return null; } }) @@ -1650,7 +1649,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error getting intros", ex); + _logger.LogError(ex, "Error getting intros"); return new List(); } @@ -1670,7 +1669,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error getting intro files", ex); + _logger.LogError(ex, "Error getting intro files"); return new List(); } @@ -1693,7 +1692,7 @@ namespace Emby.Server.Implementations.Library if (video == null) { - _logger.LogError("Unable to locate item with Id {0}.", info.ItemId.Value); + _logger.LogError("Unable to locate item with Id {ID}.", info.ItemId.Value); } } else if (!string.IsNullOrEmpty(info.Path)) @@ -1705,7 +1704,7 @@ namespace Emby.Server.Implementations.Library if (video == null) { - _logger.LogError("Intro resolver returned null for {0}.", info.Path); + _logger.LogError("Intro resolver returned null for {path}.", info.Path); } else { @@ -1724,7 +1723,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error resolving path {0}.", ex, info.Path); + _logger.LogError(ex, "Error resolving path {path}.", info.Path); } } else @@ -1873,7 +1872,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error in ItemAdded event handler", ex); + _logger.LogError(ex, "Error in ItemAdded event handler"); } } } @@ -1929,7 +1928,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error in ItemUpdated event handler", ex); + _logger.LogError(ex, "Error in ItemUpdated event handler"); } } } @@ -1965,7 +1964,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error in ItemRemoved event handler", ex); + _logger.LogError(ex, "Error in ItemRemoved event handler"); } } } @@ -2808,7 +2807,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error getting person", ex); + _logger.LogError(ex, "Error getting person"); return null; } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 15673d25d..e5fd28997 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -256,7 +256,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error getting media sources", ex); + _logger.LogError(ex, "Error getting media sources"); return new List(); } } @@ -477,7 +477,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error probing live tv stream", ex); + _logger.LogError(ex, "Error probing live tv stream"); AddMediaInfo(mediaSource, isAudio); } diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 35b0ca304..ae3577b7d 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -392,7 +392,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error authenticating with provider {0}", ex, provider.Name); + _logger.LogError(ex, "Error authenticating with provider {provider}", provider.Name); return false; } @@ -575,7 +575,7 @@ namespace Emby.Server.Implementations.Library catch (Exception ex) { // Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions - _logger.LogError("Error generating PrimaryImageAspectRatio for {0}", ex, user.Name); + _logger.LogError(ex, "Error generating PrimaryImageAspectRatio for {user}", user.Name); } } @@ -599,7 +599,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error getting {0} image info for {1}", ex, image.Type, image.Path); + _logger.LogError(ex, "Error getting {imageType} image info for {imagePath}", image.Type, image.Path); return null; } } @@ -775,7 +775,7 @@ namespace Emby.Server.Implementations.Library } catch (IOException ex) { - _logger.LogError("Error deleting file {0}", ex, configPath); + _logger.LogError(ex, "Error deleting file {path}", configPath); } DeleteUserPolicy(user); @@ -1045,7 +1045,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error reading policy file: {0}", ex, path); + _logger.LogError(ex, "Error reading policy file: {path}", path); return GetDefaultPolicy(user); } @@ -1109,7 +1109,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error deleting policy file", ex); + _logger.LogError(ex, "Error deleting policy file"); } } @@ -1144,7 +1144,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError("Error reading policy file: {0}", ex, path); + _logger.LogError(ex, "Error reading policy file: {path}", path); return new UserConfiguration(); } diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs index 593a9a1ef..1686dc23c 100644 --- a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs @@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.LogError("Error refreshing {0}", ex, name); + _logger.LogError(ex, "Error refreshing {ArtistName}", name); } numComplete++; diff --git a/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs b/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs index ffa5608dd..070777475 100644 --- a/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs @@ -57,7 +57,7 @@ namespace Emby.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.LogError("Error refreshing {0}", ex, name); + _logger.LogError(ex, "Error refreshing {GenreName}", name); } numComplete++; diff --git a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs index e59b747de..775cde299 100644 --- a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs @@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.LogError("Error refreshing {0}", ex, name); + _logger.LogError(ex, "Error refreshing {GenreName}", name); } numComplete++; diff --git a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs index ec8568afc..b5ed1c0e6 100644 --- a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs @@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.LogError("Error refreshing {0}", ex, name); + _logger.LogError(ex, "Error refreshing {GenreName}", name); } numComplete++; diff --git a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs index 80e396583..50c7cfbc6 100644 --- a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs @@ -78,7 +78,7 @@ namespace Emby.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.LogError("Error validating IBN entry {0}", ex, person); + _logger.LogError(ex, "Error validating IBN entry {person}", person); } // Update progress diff --git a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs index fec989032..1a5ebac54 100644 --- a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs @@ -57,7 +57,7 @@ namespace Emby.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.LogError("Error refreshing {0}", ex, name); + _logger.LogError(ex, "Error refreshing {StudioName}", name); } numComplete++; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index b9b8802a8..ef96510bd 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -170,7 +170,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error creating virtual folder", ex); + _logger.LogError(ex, "Error creating virtual folder"); } pathsAdded.AddRange(pathsToCreate); @@ -196,7 +196,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error creating recording folders", ex); + _logger.LogError(ex, "Error creating recording folders"); } } @@ -224,7 +224,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error removing virtual folder", ex); + _logger.LogError(ex, "Error removing virtual folder"); } } else @@ -236,14 +236,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error removing media path", ex); + _logger.LogError(ex, "Error removing media path"); } } } if (requiresRefresh) { - _libraryManager.ValidateMediaLibrary(new SimpleProgress(), CancellationToken.None); + await _libraryManager.ValidateMediaLibrary(new SimpleProgress(), CancellationToken.None); } } @@ -342,7 +342,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error getting channels", ex); + _logger.LogError(ex, "Error getting channels"); } } @@ -364,7 +364,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error adding metadata", ex); + _logger.LogError(ex, "Error adding metadata"); } } } @@ -595,7 +595,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error getting channels", ex); + _logger.LogError(ex, "Error getting channels"); } } @@ -1217,7 +1217,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error recording stream", ex); + _logger.LogError(ex, "Error recording stream"); } } @@ -1414,16 +1414,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV await recorder.Record(directStreamProvider, mediaStreamInfo, recordPath, duration, onStarted, activeRecordingInfo.CancellationTokenSource.Token).ConfigureAwait(false); recordingStatus = RecordingStatus.Completed; - _logger.LogInformation("Recording completed: {0}", recordPath); + _logger.LogInformation("Recording completed: {recordPath}", recordPath); } catch (OperationCanceledException) { - _logger.LogInformation("Recording stopped: {0}", recordPath); + _logger.LogInformation("Recording stopped: {recordPath}", recordPath); recordingStatus = RecordingStatus.Completed; } catch (Exception ex) { - _logger.LogError("Error recording to {0}", ex, recordPath); + _logger.LogError(ex, "Error recording to {recordPath}", recordPath); recordingStatus = RecordingStatus.Error; } @@ -1435,7 +1435,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error closing live stream", ex); + _logger.LogError(ex, "Error closing live stream"); } } @@ -1511,20 +1511,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error deleting 0-byte failed recording file {0}", ex, path); + _logger.LogError(ex, "Error deleting 0-byte failed recording file {path}", path); } } } private void TriggerRefresh(string path) { - _logger.LogInformation("Triggering refresh on {0}", path); + _logger.LogInformation("Triggering refresh on {path}", path); var item = GetAffectedBaseItem(_fileSystem.GetDirectoryName(path)); if (item != null) { - _logger.LogInformation("Refreshing recording parent {0}", item.Path); + _logger.LogInformation("Refreshing recording parent {path}", item.Path); _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_logger, _fileSystem)) { @@ -1642,7 +1642,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error deleting item", ex); + _logger.LogError(ex, "Error deleting item"); } } } @@ -1668,7 +1668,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error deleting recording", ex); + _logger.LogError(ex, "Error deleting recording"); } } } @@ -1780,7 +1780,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error running recording post processor", ex); + _logger.LogError(ex, "Error running recording post processor"); } } @@ -1794,7 +1794,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var process = (IProcess)sender; try { - _logger.LogInformation("Recording post-processing script completed with exit code {0}", process.ExitCode); + _logger.LogInformation("Recording post-processing script completed with exit code {ExitCode}", process.ExitCode); } catch { @@ -1875,7 +1875,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error saving recording image", ex); + _logger.LogError(ex, "Error saving recording image"); } } @@ -1890,7 +1890,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error saving recording image", ex); + _logger.LogError(ex, "Error saving recording image"); } } @@ -1903,7 +1903,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error saving recording image", ex); + _logger.LogError(ex, "Error saving recording image"); } } @@ -1916,7 +1916,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error saving recording image", ex); + _logger.LogError(ex, "Error saving recording image"); } } } @@ -1984,7 +1984,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error saving nfo", ex); + _logger.LogError(ex, "Error saving nfo"); } } @@ -2814,7 +2814,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error discovering tuner devices", ex); + _logger.LogError(ex, "Error discovering tuner devices"); return new List(); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index af5e96c05..4ea83b7ac 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -269,14 +269,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { try { - _logger.LogInformation("Stopping ffmpeg recording process for {0}", _targetPath); + _logger.LogInformation("Stopping ffmpeg recording process for {path}", _targetPath); //process.Kill(); _process.StandardInput.WriteLine("q"); } catch (Exception ex) { - _logger.LogError("Error stopping recording transcoding job for {0}", ex, _targetPath); + _logger.LogError(ex, "Error stopping recording transcoding job for {path}", _targetPath); } if (_hasExited) @@ -286,7 +286,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - _logger.LogInformation("Calling recording process.WaitForExit for {0}", _targetPath); + _logger.LogInformation("Calling recording process.WaitForExit for {path}", _targetPath); if (_process.WaitForExit(10000)) { @@ -295,7 +295,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error waiting for recording process to exit for {0}", ex, _targetPath); + _logger.LogError(ex, "Error waiting for recording process to exit for {path}", _targetPath); } if (_hasExited) @@ -305,13 +305,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - _logger.LogInformation("Killing ffmpeg recording process for {0}", _targetPath); + _logger.LogInformation("Killing ffmpeg recording process for {path}", _targetPath); _process.Kill(); } catch (Exception ex) { - _logger.LogError("Error killing recording transcoding job for {0}", ex, _targetPath); + _logger.LogError(ex, "Error killing recording transcoding job for {path}", _targetPath); } } } @@ -329,7 +329,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var exitCode = process.ExitCode; - _logger.LogInformation("FFMpeg recording exited with code {0} for {1}", exitCode, _targetPath); + _logger.LogInformation("FFMpeg recording exited with code {ExitCode} for {path}", exitCode, _targetPath); if (exitCode == 0) { @@ -337,13 +337,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } else { - _taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {0} failed. Exit code {1}", _targetPath, exitCode))); + _taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {path} failed. Exit code {ExitCode}", _targetPath, exitCode))); } } catch { - _logger.LogError("FFMpeg recording exited with an error for {0}.", _targetPath); - _taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {0} failed", _targetPath))); + _logger.LogError("FFMpeg recording exited with an error for {path}.", _targetPath); + _taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {path} failed", _targetPath))); } } @@ -357,7 +357,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error disposing recording log stream", ex); + _logger.LogError(ex, "Error disposing recording log stream"); } _logFileStream = null; @@ -387,7 +387,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error reading ffmpeg recording log", ex); + _logger.LogError(ex, "Error reading ffmpeg recording log"); } } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 813a7a5f9..9f179dc2c 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - Logger.LogError("Error deserializing {0}", ex, jsonFile); + Logger.LogError(ex, "Error deserializing {jsonFile}", jsonFile); } return new List(); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index f00a54c7f..5618579f6 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -143,7 +143,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError("Error scheduling wake timer", ex); + _logger.LogError(ex, "Error scheduling wake timer"); } } @@ -153,12 +153,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (_timers.TryAdd(item.Id, timer)) { - _logger.LogInformation("Creating recording timer for {0}, {1}. Timer will fire in {2} minutes", item.Id, item.Name, dueTime.TotalMinutes.ToString(CultureInfo.InvariantCulture)); + _logger.LogInformation("Creating recording timer for {id}, {name}. Timer will fire in {minutes} minutes", item.Id, item.Name, dueTime.TotalMinutes.ToString(CultureInfo.InvariantCulture)); } else { timer.Dispose(); - _logger.LogWarning("Timer already exists for item {0}", item.Id); + _logger.LogWarning("Timer already exists for item {id}", item.Id); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 48b4e5833..8fb3af211 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -527,7 +527,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings } catch (Exception ex) { - _logger.LogError("Error getting image info from schedules direct", ex); + _logger.LogError(ex, "Error getting image info from schedules direct"); return new List(); } @@ -557,35 +557,33 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { using (var httpResponse = await Get(options, false, info).ConfigureAwait(false)) + using (Stream responce = httpResponse.Content) { - using (Stream responce = httpResponse.Content) - { - var root = await _jsonSerializer.DeserializeFromStreamAsync>(responce).ConfigureAwait(false); + var root = await _jsonSerializer.DeserializeFromStreamAsync>(responce).ConfigureAwait(false); - if (root != null) + if (root != null) + { + foreach (ScheduleDirect.Headends headend in root) { - foreach (ScheduleDirect.Headends headend in root) + foreach (ScheduleDirect.Lineup lineup in headend.lineups) { - foreach (ScheduleDirect.Lineup lineup in headend.lineups) + lineups.Add(new NameIdPair { - lineups.Add(new NameIdPair - { - Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name, - Id = lineup.uri.Substring(18) - }); - } + Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name, + Id = lineup.uri.Substring(18) + }); } } - else - { - _logger.LogInformation("No lineups available"); - } + } + else + { + _logger.LogInformation("No lineups available"); } } } catch (Exception ex) { - _logger.LogError("Error getting headends", ex); + _logger.LogError(ex, "Error getting headends"); } return lineups; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index cc8840e14..6fe578715 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -170,6 +170,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + _logger.LogError(ex, "Error"); } } image = librarySeries.GetImageInfo(ImageType.Backdrop, 0); @@ -185,6 +186,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + _logger.LogError(ex, "Error"); } } } @@ -212,6 +214,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + _logger.LogError(ex, "Error"); } } @@ -230,6 +233,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + _logger.LogError(ex, "Error"); } } } @@ -260,6 +264,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + _logger.LogError(ex, "Error"); } } image = librarySeries.GetImageInfo(ImageType.Backdrop, 0); @@ -275,6 +280,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + _logger.LogError(ex, "Error"); } } } @@ -333,6 +339,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + _logger.LogError(ex, "Error"); } } } @@ -376,7 +383,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError("Error getting image info for {0}", ex, info.Name); + _logger.LogError(ex, "Error getting image info for {name}", info.Name); } return null; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 679f8668b..ee2a9fe4b 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1089,7 +1089,7 @@ namespace Emby.Server.Implementations.LiveTv { cancellationToken.ThrowIfCancellationRequested(); - _logger.LogDebug("Refreshing guide from {0}", service.Name); + _logger.LogDebug("Refreshing guide from {name}", service.Name); try { @@ -1108,7 +1108,7 @@ namespace Emby.Server.Implementations.LiveTv catch (Exception ex) { cleanDatabase = false; - _logger.LogError("Error refreshing channels for service", ex); + _logger.LogError(ex, "Error refreshing channels for service"); } numComplete++; @@ -1171,7 +1171,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError("Error getting channel information for {0}", ex, channelInfo.Item2.Name); + _logger.LogError(ex, "Error getting channel information for {name}", channelInfo.Item2.Name); } numComplete++; @@ -1300,7 +1300,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError("Error getting programs for channel {0}", ex, currentChannel.Name); + _logger.LogError(ex, "Error getting programs for channel {name}", currentChannel.Name); } numComplete++; @@ -1645,7 +1645,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError("Error getting recordings", ex); + _logger.LogError(ex, "Error getting recordings"); return new List>(); } }); @@ -1721,7 +1721,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError("Error getting recordings", ex); + _logger.LogError(ex, "Error getting recordings"); return new List>(); } }); @@ -1876,7 +1876,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError("Error getting recordings", ex); + _logger.LogError(ex, "Error getting recordings"); return new List>(); } }); @@ -1922,7 +1922,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError("Error getting recordings", ex); + _logger.LogError(ex, "Error getting recordings"); return new List>(); } }); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 97c33f1fa..ef2010ba6 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (Exception ex) { - Logger.LogError("Error getting channel list", ex); + Logger.LogError(ex, "Error getting channel list"); if (enableCache) { @@ -161,7 +161,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (Exception ex) { - Logger.LogError("Error getting channels", ex); + Logger.LogError(ex, "Error getting channels"); } } } @@ -201,7 +201,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (Exception ex) { - Logger.LogError("Error getting channels", ex); + Logger.LogError(ex, "Error getting channels"); } } @@ -221,7 +221,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (Exception ex) { - Logger.LogError("Error opening tuner", ex); + Logger.LogError(ex, "Error opening tuner"); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index a8d1dcaa3..be090df0c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -303,7 +303,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } catch (Exception ex) { - Logger.LogError("Error getting tuner info", ex); + Logger.LogError(ex, "Error getting tuner info"); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 933c34124..c781bccbb 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath)); - Logger.LogInformation("Opening HDHR UDP Live stream from {0}", uri.Host); + Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host); var remoteAddress = IPAddress.Parse(uri.Host); var embyRemoteAddress = _networkManager.ParseIpAddress(uri.Host); @@ -69,9 +69,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun localAddress = ((IPEndPoint)tcpSocket.LocalEndPoint).Address; tcpSocket.Close(); } - catch (Exception) + catch (Exception ex) { - Logger.LogError("Unable to determine local ip address for Legacy HDHomerun stream."); + Logger.LogError(ex, "Unable to determine local ip address for Legacy HDHomerun stream."); return; } } @@ -87,21 +87,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun catch (Exception ex) { using (udpClient) + using (hdHomerunManager) { - using (hdHomerunManager) + if (!(ex is OperationCanceledException)) { - if (!(ex is OperationCanceledException)) - { - Logger.LogError("Error opening live stream:", ex); - } - throw; + Logger.LogError(ex, "Error opening live stream:"); } + throw; } } var taskCompletionSource = new TaskCompletionSource(); - StartStreaming(udpClient, hdHomerunManager, remoteAddress, taskCompletionSource, LiveStreamCancellationTokenSource.Token); + await StartStreaming(udpClient, hdHomerunManager, remoteAddress, taskCompletionSource, LiveStreamCancellationTokenSource.Token); //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Path = tempFile; @@ -122,26 +120,24 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return Task.Run(async () => { using (udpClient) + using (hdHomerunManager) { - using (hdHomerunManager) + try { - try - { - await CopyTo(udpClient, TempFilePath, openTaskCompletionSource, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException ex) - { - Logger.LogInformation("HDHR UDP stream cancelled or timed out from {0}", remoteAddress); - openTaskCompletionSource.TrySetException(ex); - } - catch (Exception ex) - { - Logger.LogError("Error opening live stream:", ex); - openTaskCompletionSource.TrySetException(ex); - } - - EnableStreamSharing = false; + await CopyTo(udpClient, TempFilePath, openTaskCompletionSource, cancellationToken).ConfigureAwait(false); } + catch (OperationCanceledException ex) + { + Logger.LogInformation("HDHR UDP stream cancelled or timed out from {0}", remoteAddress); + openTaskCompletionSource.TrySetException(ex); + } + catch (Exception ex) + { + Logger.LogError(ex, "Error opening live stream:"); + openTaskCompletionSource.TrySetException(ex); + } + + EnableStreamSharing = false; } await DeleteTempFiles(new List { TempFilePath }).ConfigureAwait(false); @@ -166,30 +162,28 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var resolved = false; using (var source = _socketFactory.CreateNetworkStream(udpClient, false)) + using (var fileStream = FileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) { - using (var fileStream = FileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) - { - var currentCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token).Token; + var currentCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token).Token; - while ((read = await source.ReadAsync(buffer, 0, buffer.Length, currentCancellationToken).ConfigureAwait(false)) != 0) - { - cancellationToken.ThrowIfCancellationRequested(); + while ((read = await source.ReadAsync(buffer, 0, buffer.Length, currentCancellationToken).ConfigureAwait(false)) != 0) + { + cancellationToken.ThrowIfCancellationRequested(); - currentCancellationToken = cancellationToken; + currentCancellationToken = cancellationToken; - read -= RtpHeaderBytes; + read -= RtpHeaderBytes; - if (read > 0) - { - fileStream.Write(buffer, RtpHeaderBytes, read); - } + if (read > 0) + { + fileStream.Write(buffer, RtpHeaderBytes, read); + } - if (!resolved) - { - resolved = true; - DateOpened = DateTime.UtcNow; - Resolve(openTaskCompletionSource); - } + if (!resolved) + { + resolved = true; + DateOpened = DateTime.UtcNow; + Resolve(openTaskCompletionSource); } } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index b1eda3b7f..4a2b4ebb2 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (Exception ex) { - Logger.LogError("Error closing live stream", ex); + Logger.LogError(ex, "Error closing live stream"); } } @@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (Exception ex) { - //Logger.LogError("Error deleting file {0}", ex, path); + Logger.LogError(ex, "Error deleting file {path}", path); failedFiles.Add(path); } } @@ -242,7 +242,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (Exception ex) { - Logger.LogError("Error seeking stream", ex); + Logger.LogError(ex, "Error seeking stream"); } } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index ca53036a4..9b10daba0 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -138,7 +138,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (Exception ex) { - Logger.LogError("Error copying live stream.", ex); + Logger.LogError(ex, "Error copying live stream."); } EnableStreamSharing = false; await DeleteTempFiles(new List { TempFilePath }).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 3c7263581..792ffb3c4 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -166,7 +166,7 @@ namespace Emby.Server.Implementations.MediaEncoder } catch (Exception ex) { - _logger.LogError("Error extracting chapter images for {0}", ex, string.Join(",", video.Path)); + _logger.LogError(ex, "Error extracting chapter images for {0}", string.Join(",", video.Path)); success = false; break; } @@ -226,7 +226,7 @@ namespace Emby.Server.Implementations.MediaEncoder foreach (var image in deadImages) { - _logger.LogDebug("Deleting dead chapter image {0}", image); + _logger.LogDebug("Deleting dead chapter image {path}", image); try { @@ -234,7 +234,7 @@ namespace Emby.Server.Implementations.MediaEncoder } catch (IOException ex) { - _logger.LogError("Error deleting {0}.", ex, image); + _logger.LogError(ex, "Error deleting {path}.", image); } } } diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 7945680b3..260d20e35 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.Networking } catch (Exception ex) { - Logger.LogError("Error binding to NetworkAddressChanged event", ex); + Logger.LogError(ex, "Error binding to NetworkAddressChanged event"); } try @@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.Networking } catch (Exception ex) { - Logger.LogError("Error binding to NetworkChange_NetworkAvailabilityChanged event", ex); + Logger.LogError(ex, "Error binding to NetworkChange_NetworkAvailabilityChanged event"); } } } @@ -372,7 +372,7 @@ namespace Emby.Server.Implementations.Networking } catch (Exception ex) { - Logger.LogError("Error resovling hostname", ex); + Logger.LogError(ex, "Error resolving hostname"); } } } @@ -399,7 +399,7 @@ namespace Emby.Server.Implementations.Networking } catch (Exception ex) { - Logger.LogError("Error in GetAllNetworkInterfaces", ex); + Logger.LogError(ex, "Error in GetAllNetworkInterfaces"); return new List(); } @@ -428,7 +428,7 @@ namespace Emby.Server.Implementations.Networking } catch (Exception ex) { - Logger.LogError("Error querying network interface", ex); + Logger.LogError(ex, "Error querying network interface"); return new List(); } diff --git a/Emby.Server.Implementations/News/NewsEntryPoint.cs b/Emby.Server.Implementations/News/NewsEntryPoint.cs index 95ec2a672..ce6fe6630 100644 --- a/Emby.Server.Implementations/News/NewsEntryPoint.cs +++ b/Emby.Server.Implementations/News/NewsEntryPoint.cs @@ -67,7 +67,7 @@ namespace Emby.Server.Implementations.News } catch (Exception ex) { - _logger.LogError("Error downloading news", ex); + _logger.LogError(ex, "Error downloading news"); } } diff --git a/Emby.Server.Implementations/ResourceFileManager.cs b/Emby.Server.Implementations/ResourceFileManager.cs index b268e00db..04cf0632c 100644 --- a/Emby.Server.Implementations/ResourceFileManager.cs +++ b/Emby.Server.Implementations/ResourceFileManager.cs @@ -59,7 +59,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - _logger.LogError("Error in Path.GetFullPath", ex); + _logger.LogError(ex, "Error in Path.GetFullPath"); } // Don't allow file system access outside of the source folder diff --git a/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs index c77efb5cd..46a7f1f27 100644 --- a/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs @@ -89,11 +89,11 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (HttpException ex) { - _logger.LogError("Error downloading {0}", ex, package.name); + _logger.LogError(ex, "Error downloading {name}", package.name); } catch (IOException ex) { - _logger.LogError("Error updating {0}", ex, package.name); + _logger.LogError(ex, "Error updating {name}", package.name); } // Update progress diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 93e02063b..7c2ce4af3 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -146,7 +146,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (Exception ex) { - Logger.LogError("Error deserializing {0}", ex, path); + Logger.LogError(ex, "Error deserializing {path}", path); } _readFromFile = true; } @@ -436,7 +436,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (Exception ex) { - Logger.LogError("Error", ex); + Logger.LogError(ex, "Error"); failureException = ex; @@ -669,7 +669,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (Exception ex) { - Logger.LogError("Error calling CancellationToken.Cancel();", ex); + Logger.LogError(ex, "Error calling CancellationToken.Cancel();"); } } var task = _currentTask; @@ -691,7 +691,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (Exception ex) { - Logger.LogError("Error calling Task.WaitAll();", ex); + Logger.LogError(ex, "Error calling Task.WaitAll();"); } } @@ -704,7 +704,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (Exception ex) { - Logger.LogError("Error calling CancellationToken.Dispose();", ex); + Logger.LogError(ex, "Error calling CancellationToken.Dispose();"); } } if (wassRunning) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index efadd7111..c60f59ce4 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -132,11 +132,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError("Error deleting directory {0}", ex, directory); + _logger.LogError(ex, "Error deleting directory {path}", directory); } catch (IOException ex) { - _logger.LogError("Error deleting directory {0}", ex, directory); + _logger.LogError(ex, "Error deleting directory {path}", directory); } } } @@ -150,11 +150,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError("Error deleting file {0}", ex, path); + _logger.LogError(ex, "Error deleting file {path}", path); } catch (IOException ex) { - _logger.LogError("Error deleting file {0}", ex, path); + _logger.LogError(ex, "Error deleting file {path}", path); } } diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs index d2c6ed33b..228d511ce 100644 --- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs +++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs @@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.Security } catch (Exception ex) { - Logger.LogError("Error migrating authentication database", ex); + Logger.LogError(ex, "Error migrating authentication database"); } } diff --git a/Emby.Server.Implementations/Security/PluginSecurityManager.cs b/Emby.Server.Implementations/Security/PluginSecurityManager.cs index aa0f39030..2b1494c39 100644 --- a/Emby.Server.Implementations/Security/PluginSecurityManager.cs +++ b/Emby.Server.Implementations/Security/PluginSecurityManager.cs @@ -150,18 +150,15 @@ namespace Emby.Server.Implementations.Security SaveAppStoreInfo(parameters); throw; } - catch (HttpException e) + catch (HttpException ex) { - _logger.LogError("Error registering appstore purchase {0}", e, parameters ?? "NO PARMS SENT"); + _logger.LogError(ex, "Error registering appstore purchase {parameters}", parameters ?? "NO PARMS SENT"); - if (e.StatusCode.HasValue && e.StatusCode.Value == HttpStatusCode.PaymentRequired) - { - } throw new Exception("Error registering store sale"); } - catch (Exception e) + catch (Exception ex) { - _logger.LogError("Error registering appstore purchase {0}", e, parameters ?? "NO PARMS SENT"); + _logger.LogError(ex, "Error registering appstore purchase {parameters}", parameters ?? "NO PARMS SENT"); SaveAppStoreInfo(parameters); //TODO - could create a re-try routine on start-up if this file is there. For now we can handle manually. throw new Exception("Error registering store sale"); diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index 222ec7dd0..8cacc1124 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Udp } catch (Exception ex) { - _logger.LogError("Error in OnMessageReceived", ex); + _logger.LogError(ex, "Error in OnMessageReceived"); } } } @@ -171,7 +171,7 @@ namespace Emby.Server.Implementations.Udp } catch (Exception ex) { - _logger.LogError("Error receiving udp message", ex); + _logger.LogError(ex, "Error receiving udp message"); } } @@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.Udp } catch (Exception ex) { - _logger.LogError("Error receiving udp message", ex); + _logger.LogError(ex, "Error receiving udp message"); } BeginReceive(); @@ -224,7 +224,7 @@ namespace Emby.Server.Implementations.Udp } catch (Exception ex) { - _logger.LogError("Error handling UDP message", ex); + _logger.LogError(ex, "Error handling UDP message"); } } @@ -274,7 +274,7 @@ namespace Emby.Server.Implementations.Udp { await _udpClient.SendToAsync(bytes, 0, bytes.Length, remoteEndPoint, cancellationToken).ConfigureAwait(false); - _logger.LogInformation("Udp message sent to {0}", remoteEndPoint); + _logger.LogInformation("Udp message sent to {remoteEndPoint}", remoteEndPoint); } catch (OperationCanceledException) { @@ -282,7 +282,7 @@ namespace Emby.Server.Implementations.Udp } catch (Exception ex) { - _logger.LogError("Error sending message to {0}", ex, remoteEndPoint); + _logger.LogError(ex, "Error sending message to {remoteEndPoint}", remoteEndPoint); } } } diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index f864b079a..b4d18b69c 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.Updates } catch (Exception ex) { - _logger.LogError("Package installation failed", ex); + _logger.LogError(ex, "Package installation failed"); lock (CurrentInstallations) { @@ -610,9 +610,9 @@ namespace Emby.Server.Implementations.Updates _fileSystem.WriteAllText(target + ".ver", package.versionStr); } } - catch (IOException e) + catch (IOException ex) { - _logger.LogError("Error attempting to move file from {0} to {1}", e, tempFile, target); + _logger.LogError(ex, "Error attempting to move file from {TempFile} to {TargetFile}", tempFile, target); throw; } @@ -620,10 +620,10 @@ namespace Emby.Server.Implementations.Updates { _fileSystem.DeleteFile(tempFile); } - catch (IOException e) + catch (IOException ex) { // Don't fail because of this - _logger.LogError("Error deleting temp file {0]", e, tempFile); + _logger.LogError(ex, "Error deleting temp file {TempFile}", tempFile); } } diff --git a/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs b/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs index bbcd1eed3..d96c391fb 100644 --- a/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs +++ b/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs @@ -87,7 +87,7 @@ namespace Emby.XmlTv.Classes if (string.IsNullOrEmpty(id)) { - //LLogError("No id found for channel row"); + // LogError("No id found for channel row"); // Log.Error(" channel#{0} doesnt contain an id", iChannel); return null; } @@ -130,7 +130,7 @@ namespace Emby.XmlTv.Classes if (string.IsNullOrEmpty(result.DisplayName)) { - //LLogError("No display-name found for channel {0}", id); + // LogError("No display-name found for channel {0}", id); return null; } diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index b51bdf6fd..ed0a0c81a 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -147,7 +147,7 @@ namespace MediaBrowser.Api } catch (Exception ex) { - Logger.LogError("Error deleting encoded media cache", ex); + Logger.LogError(ex, "Error deleting encoded media cache"); } } @@ -557,7 +557,7 @@ namespace MediaBrowser.Api { try { - Logger.LogInformation("Stopping ffmpeg process with q command for {0}", job.Path); + Logger.LogInformation("Stopping ffmpeg process with q command for {path}", job.Path); //process.Kill(); process.StandardInput.WriteLine("q"); @@ -565,13 +565,13 @@ namespace MediaBrowser.Api // Need to wait because killing is asynchronous if (!process.WaitForExit(5000)) { - Logger.LogInformation("Killing ffmpeg process for {0}", job.Path); + Logger.LogInformation("Killing ffmpeg process for {path}", job.Path); process.Kill(); } } catch (Exception ex) { - Logger.LogError("Error killing transcoding job for {0}", ex, job.Path); + Logger.LogError(ex, "Error killing transcoding job for {path}", job.Path); } } } @@ -589,7 +589,7 @@ namespace MediaBrowser.Api } catch (Exception ex) { - Logger.LogError("Error closing live stream for {0}", ex, job.Path); + Logger.LogError(ex, "Error closing live stream for {path}", job.Path); } } } @@ -620,15 +620,15 @@ namespace MediaBrowser.Api { } - catch (IOException) + catch (IOException ex) { - //Logger.LogError("Error deleting partial stream file(s) {0}", ex, path); + Logger.LogError(ex, "Error deleting partial stream file(s) {path}", path); DeletePartialStreamFiles(path, jobType, retryCount + 1, 500); } - catch + catch (Exception ex) { - //Logger.LogError("Error deleting partial stream file(s) {0}", ex, path); + Logger.LogError(ex, "Error deleting partial stream file(s) {path}", path); } } @@ -670,7 +670,7 @@ namespace MediaBrowser.Api catch (IOException ex) { e = ex; - //Logger.LogError("Error deleting HLS file {0}", ex, file); + Logger.LogError(ex, "Error deleting HLS file {path}", file); } } diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 28a424512..17c6d5dc5 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -362,7 +362,7 @@ namespace MediaBrowser.Api.Images } catch (Exception ex) { - Logger.LogError("Error getting image information for {0}", ex, info.Path); + Logger.LogError(ex, "Error getting image information for {path}", info.Path); return null; } diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index cf5014328..ecf3eb7db 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -1001,7 +1001,7 @@ namespace MediaBrowser.Api.Library } catch (Exception ex) { - Logger.LogError("Error refreshing library", ex); + Logger.LogError(ex, "Error refreshing library"); } }); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 37cc8d2d7..af56f6382 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -278,7 +278,7 @@ namespace MediaBrowser.Api.Playback } catch (Exception ex) { - Logger.LogError("Error starting ffmpeg", ex); + Logger.LogError(ex, "Error starting ffmpeg"); ApiEntryPoint.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType, state); @@ -372,7 +372,7 @@ namespace MediaBrowser.Api.Playback //} //catch (Exception ex) //{ - // Logger.LogError("Error disposing ffmpeg.", ex); + // Logger.LogError(ex, "Error disposing ffmpeg."); //} } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 7dda91e5a..5361e313c 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -367,7 +367,7 @@ namespace MediaBrowser.Api.Playback.Hls } catch (IOException ex) { - Logger.LogError("Error deleting partial stream file(s) {0}", ex, path); + Logger.LogError(ex, "Error deleting partial stream file(s) {path}", path); var task = Task.Delay(100); Task.WaitAll(task); @@ -375,7 +375,7 @@ namespace MediaBrowser.Api.Playback.Hls } catch (Exception ex) { - Logger.LogError("Error deleting partial stream file(s) {0}", ex, path); + Logger.LogError(ex, "Error deleting partial stream file(s) {path}", path); } } diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 981a4725d..67fb04d0c 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -162,7 +162,7 @@ namespace MediaBrowser.Api.Playback } catch (Exception ex) { - _logger.LogError("Error disposing log stream", ex); + _logger.LogError(ex, "Error disposing log stream"); } LogFileStream = null; @@ -179,7 +179,7 @@ namespace MediaBrowser.Api.Playback } catch (Exception ex) { - _logger.LogError("Error disposing TranscodingThrottler", ex); + _logger.LogError(ex, "Error disposing TranscodingThrottler"); } TranscodingThrottler = null; @@ -196,7 +196,7 @@ namespace MediaBrowser.Api.Playback } catch (Exception ex) { - _logger.LogError("Error closing media source", ex); + _logger.LogError(ex, "Error closing media source"); } } } diff --git a/MediaBrowser.Api/Playback/TranscodingThrottler.cs b/MediaBrowser.Api/Playback/TranscodingThrottler.cs index 47f1f777a..5852852f6 100644 --- a/MediaBrowser.Api/Playback/TranscodingThrottler.cs +++ b/MediaBrowser.Api/Playback/TranscodingThrottler.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Api.Playback } catch (Exception ex) { - _logger.LogError("Error pausing transcoding", ex); + _logger.LogError(ex, "Error pausing transcoding"); } } } @@ -78,7 +78,7 @@ namespace MediaBrowser.Api.Playback { if (_isPaused) { - _logger.LogDebug("Sending unpause command to ffmpeg"); + _logger.LogDebug("Sending resume command to ffmpeg"); try { @@ -87,7 +87,7 @@ namespace MediaBrowser.Api.Playback } catch (Exception ex) { - _logger.LogError("Error unpausing transcoding", ex); + _logger.LogError(ex, "Error resuming transcoding"); } } } @@ -110,11 +110,11 @@ namespace MediaBrowser.Api.Playback if (gap < targetGap) { - //_logger.LogDebug("Not throttling transcoder gap {0} target gap {1}", gap, targetGap); + _logger.LogDebug("Not throttling transcoder gap {0} target gap {1}", gap, targetGap); return false; } - //_logger.LogDebug("Throttling transcoder gap {0} target gap {1}", gap, targetGap); + _logger.LogDebug("Throttling transcoder gap {0} target gap {1}", gap, targetGap); return true; } @@ -135,21 +135,21 @@ namespace MediaBrowser.Api.Playback if (gap < targetGap) { - //_logger.LogDebug("Not throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); + _logger.LogDebug("Not throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); return false; } - //_logger.LogDebug("Throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); + _logger.LogDebug("Throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); return true; } - catch + catch (Exception ex) { - //_logger.LogError("Error getting output size"); + _logger.LogError(ex, "Error getting output size"); return false; } } - //_logger.LogDebug("No throttle data for " + path); + _logger.LogDebug("No throttle data for " + path); return false; } diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index 33e6b2020..1f1bb3614 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -8,13 +8,13 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Services; using MediaBrowser.Common.Plugins; +using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { @@ -230,9 +230,9 @@ namespace MediaBrowser.Api .ToArray(); } } - catch + catch (Exception ex) { - //Logger.LogError("Error getting plugin list", ex); + Logger.LogError(ex, "Error getting plugin list"); // Play it safe here if (requireAppStoreEnabled) { diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index 9a149dc92..0e5b0a964 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -278,7 +278,7 @@ namespace MediaBrowser.Api.Subtitles } catch (Exception ex) { - Logger.LogError("Error downloading subtitles", ex); + Logger.LogError(ex, "Error downloading subtitles"); } }); diff --git a/MediaBrowser.Common/Events/EventHelper.cs b/MediaBrowser.Common/Events/EventHelper.cs index 96d0fcae8..04a2270e3 100644 --- a/MediaBrowser.Common/Events/EventHelper.cs +++ b/MediaBrowser.Common/Events/EventHelper.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Common.Events } catch (Exception ex) { - logger.LogError("Error in event handler", ex); + logger.LogError(ex, "Error in event handler"); } }); } @@ -54,7 +54,7 @@ namespace MediaBrowser.Common.Events } catch (Exception ex) { - logger.LogError("Error in event handler", ex); + logger.LogError(ex, "Error in event handler"); } }); } @@ -77,7 +77,7 @@ namespace MediaBrowser.Common.Events } catch (Exception ex) { - logger.LogError("Error in event handler", ex); + logger.LogError(ex, "Error in event handler"); } } } @@ -100,7 +100,7 @@ namespace MediaBrowser.Common.Events } catch (Exception ex) { - logger.LogError("Error in event handler", ex); + logger.LogError(ex, "Error in event handler"); } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 9ba80da69..6393a9f19 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1414,7 +1414,7 @@ namespace MediaBrowser.Controller.Entities } catch (Exception ex) { - Logger.LogError("Error refreshing owned items for {0}", ex, Path ?? Name); + Logger.LogError(ex, "Error refreshing owned items for {path}", Path ?? Name); } } diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index dbec03a21..7292b166a 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities } catch (Exception ex) { - Logger.LogError("Error loading library options", ex); + Logger.LogError(ex, "Error loading library options"); return new LibraryOptions(); } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index e9352ce40..dbe30f9a5 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -303,7 +303,7 @@ namespace MediaBrowser.Controller.Entities var id = child.Id; if (dictionary.ContainsKey(id)) { - Logger.LogError("Found folder containing items with duplicate id. Path: {0}, Child Name: {1}", + Logger.LogError("Found folder containing items with duplicate id. Path: {path}, Child Name: {ChildName}", Path ?? Name, child.Path ?? child.Name); } diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 6d5126a44..b50a12d52 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -259,10 +259,9 @@ namespace MediaBrowser.Controller.Entities { return _libraryManager.GetGenre(i); } - catch + catch (Exception ex) { - // Full exception logged at lower levels - _logger.LogError("Error getting genre"); + _logger.LogError(ex, "Error getting genre"); return null; } @@ -383,10 +382,9 @@ namespace MediaBrowser.Controller.Entities { return _libraryManager.GetGenre(i); } - catch + catch (Exception ex) { - // Full exception logged at lower levels - _logger.LogError("Error getting genre"); + _logger.LogError(ex, "Error getting genre"); return null; } diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index 37d507753..c0cf51ab2 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Controller.IO } catch (Exception ex) { - logger.LogError("Error resolving shortcut from {0}", ex, fullName); + logger.LogError(ex, "Error resolving shortcut from {path}", fullName); } } else if (flattenFolderDepth > 0 && isDirectory) diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 3ec4e3bb7..c8c2367e6 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -727,7 +727,6 @@ namespace MediaBrowser.Controller.MediaEncoding return count; } - protected void DisposeIsoMount() { if (IsoMount != null) diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index bac7e0184..5abbadcc7 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -232,7 +232,7 @@ namespace MediaBrowser.Controller.Net } catch (Exception ex) { - Logger.LogError("Error sending web socket message {0}", ex, Name); + Logger.LogError(ex, "Error sending web socket message {Name}", Name); DisposeConnection(tuple); } } diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 65ff43cf9..98848a440 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -337,7 +337,7 @@ namespace MediaBrowser.Controller.Session } catch (Exception ex) { - _logger.LogError("Error reporting playback progress", ex); + _logger.LogError(ex, "Error reporting playback progress"); } } @@ -379,7 +379,7 @@ namespace MediaBrowser.Controller.Session } catch (Exception ex) { - _logger.LogError("Error disposing session controller", ex); + _logger.LogError(ex, "Error disposing session controller"); } } } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 4e7a7a168..9666c8266 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -135,7 +135,7 @@ namespace MediaBrowser.LocalMetadata.Savers } catch (Exception ex) { - Logger.LogError("Error setting hidden attribute on {0} - {1}", path, ex.Message); + Logger.LogError(ex, "Error setting hidden attribute on {path}", path); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 1fd34c8fd..187f350b8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex) { - Logger.LogError("Error starting ffmpeg", ex); + Logger.LogError(ex, "Error starting ffmpeg"); OnTranscodeFailedToStart(encodingJob.OutputFilePath, encodingJob); @@ -179,9 +179,9 @@ namespace MediaBrowser.MediaEncoding.Encoder isSuccesful = exitCode == 0; } - catch + catch (Exception ex) { - Logger.LogError("FFMpeg exited with an error."); + Logger.LogError(ex, "FFMpeg exited with an error."); } if (isSuccesful && !job.IsCancelled) diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 9653e561c..fb131f304 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (logOutput) { - _logger.LogError("Error validating encoder", ex); + _logger.LogError(ex, "Error validating encoder"); } } @@ -78,9 +78,9 @@ namespace MediaBrowser.MediaEncoding.Encoder { output = GetProcessOutput(encoderAppPath, "-decoders"); } - catch (Exception ) + catch (Exception ex) { - //_logger.LogError("Error detecting available decoders", ex); + _logger.LogError(ex, "Error detecting available decoders"); } var found = new List(); @@ -187,7 +187,7 @@ namespace MediaBrowser.MediaEncoding.Encoder RedirectStandardOutput = true }); - _logger.LogInformation("Running {0} {1}", path, arguments); + _logger.LogInformation("Running {path} {arguments}", path, arguments); using (process) { @@ -199,16 +199,16 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch { - _logger.LogInformation("Killing process {0} {1}", path, arguments); + _logger.LogInformation("Killing process {path} {arguments}", path, arguments); // Hate having to do this try { process.Kill(); } - catch (Exception ex1) + catch (Exception ex) { - _logger.LogError("Error killing process", ex1); + _logger.LogError(ex, "Error killing process"); } throw; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index dcaf4a2b1..e97898ac5 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -81,7 +81,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex) { - _logger.LogError("Error disposing log stream", ex); + _logger.LogError(ex, "Error disposing log stream"); } LogFileStream = null; @@ -98,7 +98,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex) { - _logger.LogError("Error closing media source", ex); + _logger.LogError(ex, "Error closing media source"); } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/FontConfigLoader.cs b/MediaBrowser.MediaEncoding/Encoder/FontConfigLoader.cs index 2f0161962..d2cf7f395 100644 --- a/MediaBrowser.MediaEncoding/Encoder/FontConfigLoader.cs +++ b/MediaBrowser.MediaEncoding/Encoder/FontConfigLoader.cs @@ -72,12 +72,12 @@ namespace MediaBrowser.MediaEncoding.Encoder catch (HttpException ex) { // Don't let the server crash because of this - _logger.LogError("Error downloading ffmpeg font files", ex); + _logger.LogError(ex, "Error downloading ffmpeg font files"); } catch (Exception ex) { // Don't let the server crash because of this - _logger.LogError("Error writing ffmpeg font files", ex); + _logger.LogError(ex, "Error writing ffmpeg font files"); } } @@ -103,7 +103,7 @@ namespace MediaBrowser.MediaEncoding.Encoder catch (IOException ex) { // Log this, but don't let it fail the operation - _logger.LogError("Error copying file", ex); + _logger.LogError(ex, "Error copying file"); } } @@ -127,7 +127,7 @@ namespace MediaBrowser.MediaEncoding.Encoder catch (Exception ex) { // The core can function without the font file, so handle this - _logger.LogError("Failed to download ffmpeg font file from {0}", ex, url); + _logger.LogError(ex, "Failed to download ffmpeg font file from {url}", url); } } @@ -145,12 +145,12 @@ namespace MediaBrowser.MediaEncoding.Encoder catch (IOException ex) { // Log this, but don't let it fail the operation - _logger.LogError("Error deleting temp file {0}", ex, tempFile); + _logger.LogError(ex, "Error deleting temp file {path}", tempFile); } } private void Extract7zArchive(string archivePath, string targetPath) { - _logger.LogInformation("Extracting {0} to {1}", archivePath, targetPath); + _logger.LogInformation("Extracting {ArchivePath} to {TargetPath}", archivePath, targetPath); _zipClient.ExtractAllFrom7z(archivePath, targetPath, true); } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4cd66e5ce..a661d7691 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -102,8 +102,6 @@ namespace MediaBrowser.MediaEncoding.Encoder _originalFFMpegPath = ffMpegPath; _hasExternalEncoder = hasExternalEncoder; - - SetEnvironmentVariable(); } private readonly object _logLock = new object(); @@ -117,7 +115,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex) { - _logger.LogError("Error setting FFREPORT environment variable", ex); + _logger.LogError(ex, "Error setting FFREPORT environment variable"); } } } @@ -132,31 +130,11 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex) { - //_logger.LogError("Error setting FFREPORT environment variable", ex); + _logger.LogError(ex, "Error setting FFREPORT environment variable"); } } } - private void SetEnvironmentVariable() - { - try - { - //_environmentInfo.SetProcessEnvironmentVariable("FFREPORT", "file=program-YYYYMMDD-HHMMSS.txt:level=32"); - } - catch (Exception ex) - { - _logger.LogError("Error setting FFREPORT environment variable", ex); - } - try - { - //_environmentInfo.SetUserEnvironmentVariable("FFREPORT", "file=program-YYYYMMDD-HHMMSS.txt:level=32"); - } - catch (Exception ex) - { - _logger.LogError("Error setting FFREPORT environment variable", ex); - } - } - public string EncoderLocationType { get @@ -649,9 +627,9 @@ namespace MediaBrowser.MediaEncoding.Encoder { throw; } - catch + catch (Exception ex) { - _logger.LogError("I-frame image extraction failed, will attempt standard way. Input: {0}", inputArgument); + _logger.LogError(ex, "I-frame image extraction failed, will attempt standard way. Input: {arguments}", inputArgument); } } @@ -999,7 +977,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex) { - _logger.LogError("Error in WaitForExit", ex); + _logger.LogError(ex, "Error in WaitForExit"); } try @@ -1010,7 +988,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex) { - _logger.LogError("Error killing process", ex); + _logger.LogError(ex, "Error killing process"); } } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c3cf61dc1..d0ccef2f8 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1351,11 +1351,11 @@ namespace MediaBrowser.MediaEncoding.Probing { video.Timestamp = GetMpegTimestamp(video.Path); - _logger.LogDebug("Video has {0} timestamp", video.Timestamp); + _logger.LogDebug("Video has {timestamp} timestamp", video.Timestamp); } catch (Exception ex) { - _logger.LogError("Error extracting timestamp info from {0}", ex, video.Path); + _logger.LogError(ex, "Error extracting timestamp info from {path}", video.Path); video.Timestamp = null; } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index a3e0f89a9..43f775392 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -431,7 +431,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } catch (Exception ex) { - _logger.LogError("Error starting ffmpeg", ex); + _logger.LogError(ex, "Error starting ffmpeg"); throw; } @@ -448,7 +448,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } catch (Exception ex) { - _logger.LogError("Error killing subtitle conversion process", ex); + _logger.LogError(ex, "Error killing subtitle conversion process"); } } @@ -471,7 +471,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } catch (IOException ex) { - _logger.LogError("Error deleting converted subtitle {0}", ex, outputPath); + _logger.LogError(ex, "Error deleting converted subtitle {0}", outputPath); } } } @@ -561,7 +561,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } catch (Exception ex) { - _logger.LogError("Error starting ffmpeg", ex); + _logger.LogError(ex, "Error starting ffmpeg"); throw; } @@ -578,7 +578,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } catch (Exception ex) { - _logger.LogError("Error killing subtitle extraction process", ex); + _logger.LogError(ex, "Error killing subtitle extraction process"); } } @@ -603,7 +603,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } catch (IOException ex) { - _logger.LogError("Error deleting extracted subtitle {0}", ex, outputPath); + _logger.LogError(ex, "Error deleting extracted subtitle {0}", outputPath); } } else if (!_fileSystem.FileExists(outputPath)) diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index c1cb07a0e..6790f9b33 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -211,7 +211,7 @@ namespace MediaBrowser.Providers.Manager if (retry) { - _logger.LogError("IOException saving to {0}. {2}. Will retry saving to {1}", path, retryPath, ex.Message); + _logger.LogError(ex, "IOException saving to {0}. Will retry saving to {1}", path, retryPath); } else { @@ -271,7 +271,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("Error setting hidden attribute on {0} - {1}", path, ex.Message); + _logger.LogError(ex, "Error setting hidden attribute on {0}", path); } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index a11ccd6d6..fc30374b3 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { result.ErrorMessage = ex.Message; - _logger.LogError("Error in {0}", ex, provider.Name); + _logger.LogError(ex, "Error in {provider}", provider.Name); } } @@ -310,7 +310,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { result.ErrorMessage = ex.Message; - _logger.LogError("Error in {0}", ex, provider.Name); + _logger.LogError(ex, "Error in {provider}", provider.Name); } } @@ -577,7 +577,7 @@ namespace MediaBrowser.Providers.Manager } catch (IOException ex) { - _logger.LogError("Error examining images", ex); + _logger.LogError(ex, "Error examining images"); } } @@ -586,7 +586,7 @@ namespace MediaBrowser.Providers.Manager } catch (HttpException ex) { - // Sometimes providers send back bad url's. Just move onto the next image + // Sometimes providers send back bad urls. Just move onto the next image if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) { continue; diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 5d607f5d6..e26004923 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - Logger.LogError("Error getting file {0}", ex, path); + Logger.LogError(ex, "Error getting file {path}", path); return null; } } @@ -96,7 +96,7 @@ namespace MediaBrowser.Providers.Manager localImagesFailed = true; if (!(item is IItemByName)) { - Logger.LogError("Error validating images for {0}", ex, item.Path ?? item.Name ?? "Unknown name"); + Logger.LogError(ex, "Error validating images for {0}", item.Path ?? item.Name ?? "Unknown name"); } } @@ -268,7 +268,7 @@ namespace MediaBrowser.Providers.Manager // } // catch (Exception ex) // { - // Logger.LogError("Error in AddPersonImage", ex); + // Logger.LogError(ex, "Error in AddPersonImage"); // } //} @@ -767,7 +767,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - Logger.LogError("Error in {0}", ex, provider.Name); + Logger.LogError(ex, "Error in {provider}", provider.Name); // If a local provider fails, consider that a failure refreshResult.ErrorMessage = ex.Message; @@ -839,7 +839,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { refreshResult.ErrorMessage = ex.Message; - Logger.LogError("Error in {0}", ex, provider.Name); + Logger.LogError(ex, "Error in {provider}", provider.Name); } } @@ -891,7 +891,7 @@ namespace MediaBrowser.Providers.Manager { refreshResult.Failures++; refreshResult.ErrorMessage = ex.Message; - Logger.LogError("Error in {0}", ex, provider.Name); + Logger.LogError(ex, "Error in {provider}", provider.Name); } } @@ -951,7 +951,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - Logger.LogError("Error in {0}.HasChanged", ex, changeMonitor.GetType().Name); + Logger.LogError(ex, "Error in {0}.HasChanged", changeMonitor.GetType().Name); return false; } } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index e3b23ce33..8a9aae117 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -144,7 +144,7 @@ namespace MediaBrowser.Providers.Manager return service.RefreshMetadata(item, options, cancellationToken); } - _logger.LogError("Unable to find a metadata service for item of type " + item.GetType().Name); + _logger.LogError("Unable to find a metadata service for item of type {TypeName}", item.GetType().Name); return Task.FromResult(ItemUpdateType.None); } @@ -250,7 +250,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("{0} failed in GetImageInfos for type {1}", ex, provider.GetType().Name, item.GetType().Name); + _logger.LogError(ex, "{0} failed in GetImageInfos for type {1}", provider.GetType().Name, item.GetType().Name); return new List(); } } @@ -400,7 +400,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("{0} failed in Supports for type {1}", ex, provider.GetType().Name, item.GetType().Name); + _logger.LogError(ex, "{0} failed in Supports for type {1}", provider.GetType().Name, item.GetType().Name); return false; } } @@ -642,7 +642,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("Error in {0} GetSavePath", ex, saver.Name); + _logger.LogError(ex, "Error in {0} GetSavePath", saver.Name); continue; } @@ -653,7 +653,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("Error in metadata saver", ex); + _logger.LogError(ex, "Error in metadata saver"); } finally { @@ -668,7 +668,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("Error in metadata saver", ex); + _logger.LogError(ex, "Error in metadata saver"); } } } @@ -731,7 +731,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("Error in {0}.IsEnabledFor", ex, saver.Name); + _logger.LogError(ex, "Error in {0}.IsEnabledFor", saver.Name); return false; } } @@ -876,7 +876,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("Error in {0}.Suports", ex, i.GetType().Name); + _logger.LogError(ex, "Error in {0}.Suports", i.GetType().Name); return false; } }); @@ -1070,7 +1070,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("Error refreshing item", ex); + _logger.LogError(ex, "Error refreshing item"); } } @@ -1147,7 +1147,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError("Error refreshing library", ex); + _logger.LogError(ex, "Error refreshing library"); } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 4dc3849d9..c2fe392ab 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -342,7 +342,7 @@ namespace MediaBrowser.Providers.MediaInfo } catch (Exception ex) { - _logger.LogError("Error getting BDInfo", ex); + _logger.LogError(ex, "Error getting BDInfo"); return null; } } diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs index 8d5f20317..4c66f2b0a 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs @@ -176,7 +176,7 @@ namespace MediaBrowser.Providers.MediaInfo } catch (Exception ex) { - _logger.LogError("Error downloading subtitles", ex); + _logger.LogError(ex, "Error downloading subtitles"); } return false; diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 4fa6a0521..81abedeb9 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -148,7 +148,7 @@ namespace MediaBrowser.Providers.MediaInfo } catch (Exception ex) { - _logger.LogError("Error downloading subtitles for {0}", ex, video.Path); + _logger.LogError(ex, "Error downloading subtitles for {Path}", video.Path); } // Update progress diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index da0f40a5a..0dbc43313 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -774,7 +774,7 @@ namespace MediaBrowser.Providers.Music } catch (Exception ex) { - _logger.LogError("Error getting music brainz info", ex); + _logger.LogError(ex, "Error getting music brainz info"); } } } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 2006067b3..2cf737511 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -101,7 +101,7 @@ namespace MediaBrowser.Providers.Subtitles } catch (Exception ex) { - _logger.LogError("Error downloading subtitles from {0}", ex, provider.Name); + _logger.LogError(ex, "Error downloading subtitles from {Provider}", provider.Name); } } return new RemoteSubtitleInfo[] { }; @@ -119,7 +119,7 @@ namespace MediaBrowser.Providers.Subtitles } catch (Exception ex) { - _logger.LogError("Error downloading subtitles from {0}", ex, i.Name); + _logger.LogError(ex, "Error downloading subtitles from {0}", i.Name); return new RemoteSubtitleInfo[] { }; } }); diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index a943e49c0..1cb06efdf 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.TV } catch (Exception ex) { - Logger.LogError("Error in DummySeasonProvider", ex); + Logger.LogError(ex, "Error in DummySeasonProvider"); } } diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs index 8b09ee2fc..217dab663 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Providers.TV } catch (HttpException ex) { - _logger.LogError("No metadata found for {0}", seasonNumber.Value); + _logger.LogError(ex, "No metadata found for {0}", seasonNumber.Value); if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) { diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs index 6bad5b925..8bab59595 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs @@ -358,7 +358,7 @@ namespace MediaBrowser.Providers.TV } catch (HttpException ex) { - _logger.LogError("Error updating tvdb series id {0}, language {1}", ex, seriesId, language); + _logger.LogError(ex, "Error updating tvdb series id {ID}, language {Language}", seriesId, language); // Already logged at lower levels, but don't fail the whole operation, unless timed out // We have to fail this to make it run again otherwise new episode data could potentially be missing diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 9c6ee4dd2..cf61b79fe 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -270,7 +270,7 @@ namespace MediaBrowser.Server.Mono } catch (Exception ex) { - _logger.LogError("Error getting unix name", ex); + _logger.LogError(ex, "Error getting unix name"); } _unixName = uname; } diff --git a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpListener.cs index e8557d1f9..993863e8c 100644 --- a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpListener.cs @@ -114,7 +114,7 @@ namespace EmbyServer.SocketSharp } catch (Exception ex) { - _logger.LogError("Error processing request", ex); + _logger.LogError(ex, "Error processing request"); httpReq = httpReq ?? GetRequest(context); return ErrorHandler(ex, httpReq, true, true); @@ -176,7 +176,7 @@ namespace EmbyServer.SocketSharp } catch (Exception ex) { - _logger.LogError("AcceptWebSocketAsync error", ex); + _logger.LogError(ex, "AcceptWebSocketAsync error"); ctx.Response.StatusCode = 500; ctx.Response.Close(); } @@ -206,7 +206,7 @@ namespace EmbyServer.SocketSharp } catch (Exception ex) { - _logger.LogError("Error closing web socket response", ex); + _logger.LogError(ex, "Error closing web socket response"); } } diff --git a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpResponse.cs b/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpResponse.cs index d299c64ef..08fa4cbd6 100644 --- a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpResponse.cs +++ b/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpResponse.cs @@ -112,7 +112,7 @@ namespace EmbyServer.SocketSharp } catch (Exception ex) { - _logger.LogError("Error in HttpListenerResponseWrapper: " + ex.Message, ex); + _logger.LogError(ex, "Error in HttpListenerResponseWrapper"); } } } diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 0327929a9..58d02ef04 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -245,7 +245,7 @@ namespace MediaBrowser.WebDashboard.Api } catch (Exception ex) { - _logger.LogError("Error getting plugin information from {0}", ex, p.GetType().Name); + _logger.LogError(ex, "Error getting plugin information from {Plugin}", p.GetType().Name); return null; } }) diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs index 7461e952d..dac3f4967 100644 --- a/MediaBrowser.XbmcMetadata/EntryPoint.cs +++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs @@ -72,7 +72,7 @@ namespace MediaBrowser.XbmcMetadata } catch (Exception ex) { - _logger.LogError("Error saving metadata for {0}", ex, item.Path ?? item.Name); + _logger.LogError(ex, "Error saving metadata for {path}", item.Path ?? item.Name); } } } diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs index 27f128fce..e6b4eea1c 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -81,7 +81,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers } catch (Exception ex) { - Logger.LogError("Error parsing set node", ex); + Logger.LogError(ex, "Error parsing set node"); } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 74e714362..131ce80d5 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -230,7 +230,7 @@ namespace MediaBrowser.XbmcMetadata.Savers } catch (Exception ex) { - Logger.LogError("Error setting hidden attribute on {path} - {ex}", path, ex.Message); + Logger.LogError(ex, "Error setting hidden attribute on {path}", path); } } @@ -283,7 +283,7 @@ namespace MediaBrowser.XbmcMetadata.Savers } catch (XmlException ex) { - Logger.LogError("Error reading existng nfo", ex); + Logger.LogError(ex, "Error reading existing nfo"); } writer.WriteEndElement(); @@ -1000,7 +1000,7 @@ namespace MediaBrowser.XbmcMetadata.Savers } catch (Exception ex) { - logger.LogError("Error reading existing xml tags from {0}.", ex, path); + logger.LogError(ex, "Error reading existing xml tags from {path}.", path); return; } diff --git a/Mono.Nat/Pmp/PmpNatDevice.cs b/Mono.Nat/Pmp/PmpNatDevice.cs index 99d030207..fbf3032d4 100644 --- a/Mono.Nat/Pmp/PmpNatDevice.cs +++ b/Mono.Nat/Pmp/PmpNatDevice.cs @@ -198,7 +198,7 @@ namespace Mono.Nat.Pmp } catch (Exception ex) { - _logger.LogError("Error in CreatePortMapListen", ex); + _logger.LogError(ex, "Error in CreatePortMapListen"); return; } } diff --git a/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs b/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs index e9e47a91e..bcf358d1c 100644 --- a/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs +++ b/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs @@ -90,7 +90,7 @@ namespace Mono.Nat } catch (Exception ex) { - _logger.LogError("Error decoding device response", ex); + _logger.LogError(ex, "Error decoding device response"); } } diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 921ef3e51..65ec0ca71 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -131,7 +131,7 @@ namespace Rssdp.Infrastructure } catch (Exception ex) { - _logger.LogError("Error in BeginListeningForBroadcasts", ex); + _logger.LogError(ex, "Error in BeginListeningForBroadcasts"); } } } @@ -197,7 +197,7 @@ namespace Rssdp.Infrastructure } catch (Exception ex) { - _logger.LogError("Error sending socket message from {0} to {1}", ex, socket.LocalIPAddress.ToString(), destination.ToString()); + _logger.LogError(ex, "Error sending socket message from {0} to {1}", socket.LocalIPAddress.ToString(), destination.ToString()); } } @@ -376,7 +376,7 @@ namespace Rssdp.Infrastructure } catch (Exception ex) { - _logger.LogError("Error in CreateSsdpUdpSocket. IPAddress: {0}", ex, address); + _logger.LogError(ex, "Error in CreateSsdpUdpSocket. IPAddress: {0}", address); } } } diff --git a/SocketHttpListener/Net/HttpEndPointListener.cs b/SocketHttpListener/Net/HttpEndPointListener.cs index 867012d05..fb093314c 100644 --- a/SocketHttpListener/Net/HttpEndPointListener.cs +++ b/SocketHttpListener/Net/HttpEndPointListener.cs @@ -173,7 +173,7 @@ namespace SocketHttpListener.Net { HttpEndPointListener epl = (HttpEndPointListener)acceptEventArg.UserToken; - epl._logger.LogError("Error in socket.AcceptAsync", ex); + epl._logger.LogError(ex, "Error in socket.AcceptAsync"); } } @@ -238,7 +238,7 @@ namespace SocketHttpListener.Net } catch (Exception ex) { - epl._logger.LogError("Error in ProcessAccept", ex); + epl._logger.LogError(ex, "Error in ProcessAccept"); TryClose(accepted); epl.Accept(); -- cgit v1.2.3 From cd251799a4f5d0d2ab811563227dc638c035d766 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 30 Dec 2018 23:31:19 +0100 Subject: Change location of logging.json from to /config --- MediaBrowser.Server.Mono/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index cf61b79fe..b8c29796d 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -164,7 +164,7 @@ namespace MediaBrowser.Server.Mono } try { - string path = Path.Combine(_appPaths.ProgramDataPath, "logging.json"); + string path = Path.Combine(_appPaths.ConfigurationDirectoryPath, "logging.json"); if (!File.Exists(path)) { @@ -178,7 +178,7 @@ namespace MediaBrowser.Server.Mono } } var configuration = new ConfigurationBuilder() - .SetBasePath(_appPaths.ProgramDataPath) + .SetBasePath(_appPaths.ConfigurationDirectoryPath) .AddJsonFile("logging.json") .AddEnvironmentVariables("JELLYFIN_") .Build(); -- cgit v1.2.3 From 7d0ae2bca2a50518d8b3eacae8dac5fd9856f781 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Mon, 31 Dec 2018 15:34:27 +0100 Subject: Fix location log dir when failed to read configuration --- MediaBrowser.Server.Mono/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index b8c29796d..f512fc98e 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -193,7 +193,7 @@ namespace MediaBrowser.Server.Mono Serilog.Log.Logger = new LoggerConfiguration() .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}") .WriteTo.File( - Path.Combine(logDir, "logs", "log_.log"), + Path.Combine(logDir, "log_.log"), rollingInterval: RollingInterval.Day, outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}") .Enrich.FromLogContext() -- cgit v1.2.3 From 75efe9cf0a15b6871726a4c2e8802e2af88cf1d1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 1 Jan 2019 16:27:11 +0100 Subject: Rename and rework entry point --- Emby.Server.Implementations/ApplicationHost.cs | 5 +- .../EnvironmentInfo/EnvironmentInfo.cs | 19 +- Emby.Server.Implementations/StartupOptions.cs | 17 +- Jellyfin.Server/CoreAppHost.cs | 57 ++ Jellyfin.Server/Jellyfin.Server.csproj | 39 + Jellyfin.Server/PowerManagement.cs | 23 + Jellyfin.Server/Program.cs | 302 ++++++++ Jellyfin.Server/SocketSharp/HttpFile.cs | 14 + Jellyfin.Server/SocketSharp/RequestMono.cs | 805 ++++++++++++++++++++ Jellyfin.Server/SocketSharp/SharpWebSocket.cs | 159 ++++ .../SocketSharp/WebSocketSharpListener.cs | 260 +++++++ .../SocketSharp/WebSocketSharpRequest.cs | 554 ++++++++++++++ .../SocketSharp/WebSocketSharpResponse.cs | 197 +++++ MediaBrowser.Model/System/Architecture.cs | 10 - MediaBrowser.Model/System/IEnvironmentInfo.cs | 3 +- MediaBrowser.Model/System/SystemInfo.cs | 3 +- MediaBrowser.Server.Mono/EmbyServer.csproj | 66 -- MediaBrowser.Server.Mono/ImageEncoderHelper.cs | 50 -- MediaBrowser.Server.Mono/MonoAppHost.cs | 104 --- MediaBrowser.Server.Mono/Native/MonoFileSystem.cs | 23 - MediaBrowser.Server.Mono/Native/PowerManagement.cs | 21 - MediaBrowser.Server.Mono/Program.cs | 380 ---------- .../Properties/AssemblyInfo.cs | 15 - .../Properties/launchSettings.json | 7 - .../Resources/Configuration/logging.json | 19 - MediaBrowser.Server.Mono/SocketSharp/HttpFile.cs | 14 - .../SocketSharp/RequestMono.cs | 807 --------------------- .../SocketSharp/SharpWebSocket.cs | 159 ---- .../SocketSharp/WebSocketSharpListener.cs | 262 ------- .../SocketSharp/WebSocketSharpRequest.cs | 556 -------------- .../SocketSharp/WebSocketSharpResponse.cs | 196 ----- MediaBrowser.sln | 41 +- 32 files changed, 2446 insertions(+), 2741 deletions(-) create mode 100644 Jellyfin.Server/CoreAppHost.cs create mode 100644 Jellyfin.Server/Jellyfin.Server.csproj create mode 100644 Jellyfin.Server/PowerManagement.cs create mode 100644 Jellyfin.Server/Program.cs create mode 100644 Jellyfin.Server/SocketSharp/HttpFile.cs create mode 100644 Jellyfin.Server/SocketSharp/RequestMono.cs create mode 100644 Jellyfin.Server/SocketSharp/SharpWebSocket.cs create mode 100644 Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs create mode 100644 Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs create mode 100644 Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs delete mode 100644 MediaBrowser.Model/System/Architecture.cs delete mode 100644 MediaBrowser.Server.Mono/EmbyServer.csproj delete mode 100644 MediaBrowser.Server.Mono/ImageEncoderHelper.cs delete mode 100644 MediaBrowser.Server.Mono/MonoAppHost.cs delete mode 100644 MediaBrowser.Server.Mono/Native/MonoFileSystem.cs delete mode 100644 MediaBrowser.Server.Mono/Native/PowerManagement.cs delete mode 100644 MediaBrowser.Server.Mono/Program.cs delete mode 100644 MediaBrowser.Server.Mono/Properties/AssemblyInfo.cs delete mode 100644 MediaBrowser.Server.Mono/Properties/launchSettings.json delete mode 100644 MediaBrowser.Server.Mono/Resources/Configuration/logging.json delete mode 100644 MediaBrowser.Server.Mono/SocketSharp/HttpFile.cs delete mode 100644 MediaBrowser.Server.Mono/SocketSharp/RequestMono.cs delete mode 100644 MediaBrowser.Server.Mono/SocketSharp/SharpWebSocket.cs delete mode 100644 MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpListener.cs delete mode 100644 MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpRequest.cs delete mode 100644 MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpResponse.cs (limited to 'MediaBrowser.Server.Mono/Program.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index a4a24dda0..060898684 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -416,7 +416,6 @@ namespace Emby.Server.Implementations ConfigurationManager = GetConfigurationManager(); - // Initialize this early in case the -v command line option is used Logger = LoggerFactory.CreateLogger("App"); StartupOptions = options; @@ -467,7 +466,7 @@ namespace Emby.Server.Implementations { get { - return _version ?? (_version = GetType().GetTypeInfo().Assembly.GetName().Version); + return _version ?? (_version = typeof(ApplicationHost).Assembly.GetName().Version); } } @@ -1772,7 +1771,7 @@ namespace Emby.Server.Implementations return list.ToList(); } - protected abstract List GetAssembliesWithPartsInternal(); + protected abstract IEnumerable GetAssembliesWithPartsInternal(); /// /// Gets the plugin assemblies. diff --git a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs index 765505109..ad941de55 100644 --- a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs +++ b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -1,12 +1,12 @@ using System; using System.IO; using MediaBrowser.Model.System; +using System.Runtime.InteropServices; namespace Emby.Server.Implementations.EnvironmentInfo { public class EnvironmentInfo : IEnvironmentInfo { - private Architecture? _customArchitecture; private MediaBrowser.Model.System.OperatingSystem? _customOperatingSystem; public virtual MediaBrowser.Model.System.OperatingSystem OperatingSystem @@ -60,22 +60,7 @@ namespace Emby.Server.Implementations.EnvironmentInfo } } - public Architecture SystemArchitecture - { - get - { - if (_customArchitecture.HasValue) - { - return _customArchitecture.Value; - } - - return Environment.Is64BitOperatingSystem ? MediaBrowser.Model.System.Architecture.X64 : MediaBrowser.Model.System.Architecture.X86; - } - set - { - _customArchitecture = value; - } - } + public Architecture SystemArchitecture { get; set; } public string GetEnvironmentVariable(string name) { diff --git a/Emby.Server.Implementations/StartupOptions.cs b/Emby.Server.Implementations/StartupOptions.cs index 159c36248..2114d85bf 100644 --- a/Emby.Server.Implementations/StartupOptions.cs +++ b/Emby.Server.Implementations/StartupOptions.cs @@ -1,33 +1,30 @@ using System; -using System.Collections.Generic; using System.Linq; namespace Emby.Server.Implementations { public class StartupOptions { - private readonly List _options; + private readonly string[] _options; public StartupOptions(string[] commandLineArgs) { - _options = commandLineArgs.ToList(); + _options = commandLineArgs; } public bool ContainsOption(string option) - { - return _options.Contains(option, StringComparer.OrdinalIgnoreCase); - } + => _options.Contains(option, StringComparer.OrdinalIgnoreCase); public string GetOption(string name) { - var index = _options.IndexOf(name); + int index = Array.IndexOf(_options, name); - if (index != -1) + if (index == -1) { - return _options.ElementAtOrDefault(index + 1); + return null; } - return null; + return _options.ElementAtOrDefault(index + 1); } } } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs new file mode 100644 index 000000000..2fb106b3c --- /dev/null +++ b/Jellyfin.Server/CoreAppHost.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Reflection; +using Emby.Server.Implementations; +using Emby.Server.Implementations.HttpServer; +using Jellyfin.SocketSharp; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.System; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server +{ + public class CoreAppHost : ApplicationHost + { + public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) + : base(applicationPaths, loggerFactory, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, networkManager) + { + } + + public override bool CanSelfRestart + { + get + { + // A restart script must be provided + return StartupOptions.ContainsOption("-restartpath"); + } + } + + protected override void RestartInternal() => Program.Restart(); + + protected override IEnumerable GetAssembliesWithPartsInternal() + => new [] { typeof(CoreAppHost).Assembly }; + + protected override void ShutdownInternal() => Program.Shutdown(); + + protected override bool SupportsDualModeSockets + { + get + { + return true; + } + } + + protected override IHttpListener CreateHttpListener() + => new WebSocketSharpListener( + Logger, + Certificate, + StreamHelper, + TextEncoding, + NetworkManager, + SocketFactory, + CryptographyProvider, + SupportsDualModeSockets, + FileSystemManager, + EnvironmentInfo + ); + } +} diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj new file mode 100644 index 000000000..cf8396785 --- /dev/null +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -0,0 +1,39 @@ + + + + Exe + netcoreapp2.1 + false + + + + + latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Jellyfin.Server/PowerManagement.cs b/Jellyfin.Server/PowerManagement.cs new file mode 100644 index 000000000..c27c51893 --- /dev/null +++ b/Jellyfin.Server/PowerManagement.cs @@ -0,0 +1,23 @@ +using System; +using MediaBrowser.Model.System; + +namespace Jellyfin.Server.Native +{ + public class PowerManagement : IPowerManagement + { + public void PreventSystemStandby() + { + + } + + public void AllowSystemStandby() + { + + } + + public void ScheduleWake(DateTime wakeTimeUtc, string displayName) + { + + } + } +} diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs new file mode 100644 index 000000000..b768e1032 --- /dev/null +++ b/Jellyfin.Server/Program.cs @@ -0,0 +1,302 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Emby.Drawing; +using Emby.Drawing.ImageMagick; +using Emby.Drawing.Skia; +using Emby.Server.Implementations; +using Emby.Server.Implementations.EnvironmentInfo; +using Emby.Server.Implementations.IO; +using Emby.Server.Implementations.Networking; +using Jellyfin.Server.Native; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.AspNetCore; +using ILogger = Microsoft.Extensions.Logging.ILogger; + +namespace Jellyfin.Server +{ + public static class Program + { + private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); + private static ILoggerFactory _loggerFactory; + private static ILogger _logger; + private static bool _restartOnShutdown; + + public static async Task Main(string[] args) + { + StartupOptions options = new StartupOptions(args); + + Assembly entryAssembly = Assembly.GetEntryAssembly(); + + if (options.ContainsOption("-v") || options.ContainsOption("--version")) + { + Console.WriteLine(entryAssembly.GetName().Version.ToString()); + return 0; + } + + string dataPath = options.GetOption("-programdata"); + string binPath = entryAssembly.Location; + ServerApplicationPaths appPaths = CreateApplicationPaths(binPath, dataPath); + + await createLogger(appPaths); + _loggerFactory = new SerilogLoggerFactory(); + _logger = _loggerFactory.CreateLogger("Main"); + + AppDomain.CurrentDomain.UnhandledException += (sender, e) + => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");; + + ApplicationHost.LogEnvironmentInfo(_logger, appPaths, true); + + SQLitePCL.Batteries_V2.Init(); + + // Allow all https requests + ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); + + EnvironmentInfo environmentInfo = getEnvironmentInfo(); + var fileSystem = new ManagedFileSystem(_loggerFactory.CreateLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory, true); + + using (var appHost = new CoreAppHost( + appPaths, + _loggerFactory, + options, + fileSystem, + new PowerManagement(), + "embyserver-mono_{version}.zip", + environmentInfo, + new NullImageEncoder(), + new SystemEvents(_loggerFactory.CreateLogger("SystemEvents")), + new NetworkManager(_loggerFactory.CreateLogger("NetworkManager"), environmentInfo))) + { + appHost.Init(); + + appHost.ImageProcessor.ImageEncoder = GetImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); + + _logger.LogInformation("Running startup tasks"); + + await appHost.RunStartupTasks(); + + // TODO: read input for a stop command + // Block main thread until shutdown + await ApplicationTaskCompletionSource.Task; + + _logger.LogInformation("Disposing app host"); + } + + if (_restartOnShutdown) + { + StartNewInstance(options); + } + + return 0; + } + + private static ServerApplicationPaths CreateApplicationPaths(string applicationPath, string programDataPath) + { + if (string.IsNullOrEmpty(programDataPath)) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + } + else + { + // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. + programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); + // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used. + if (string.IsNullOrEmpty(programDataPath)){ + programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); + } + } + programDataPath = Path.Combine(programDataPath, "jellyfin"); + } + + string appFolderPath = Path.GetDirectoryName(applicationPath); + + return new ServerApplicationPaths(programDataPath, appFolderPath, appFolderPath); + } + + private static async Task createLogger(IApplicationPaths appPaths) + { + string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); + if (string.IsNullOrEmpty(logDir)){ + logDir = Path.Combine(appPaths.ProgramDataPath, "logs"); + Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); + } + try + { + string path = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json"); + + if (!File.Exists(path)) + { + // For some reason the csproj name is used instead of the assembly name + using (Stream rscstr = typeof(Program).Assembly + .GetManifestResourceStream("EmbyServer.Resources.Configuration.logging.json")) + using (Stream fstr = File.Open(path, FileMode.CreateNew)) + { + await rscstr.CopyToAsync(fstr); + } + } + var configuration = new ConfigurationBuilder() + .SetBasePath(appPaths.ConfigurationDirectoryPath) + .AddJsonFile("logging.json") + .AddEnvironmentVariables("JELLYFIN_") + .Build(); + + // Serilog.Log is used by SerilogLoggerFactory when no logger is specified + Serilog.Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .Enrich.FromLogContext() + .CreateLogger(); + } + catch (Exception ex) + { + Serilog.Log.Logger = new LoggerConfiguration() + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}") + .WriteTo.File( + Path.Combine(logDir, "log_.log"), + rollingInterval: RollingInterval.Day, + outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}") + .Enrich.FromLogContext() + .CreateLogger(); + + Serilog.Log.Logger.Fatal(ex, "Failed to create/read logger configuration"); + } + } + + public static IImageEncoder GetImageEncoder( + ILogger logger, + IFileSystem fileSystem, + StartupOptions startupOptions, + Func httpClient, + IApplicationPaths appPaths, + IEnvironmentInfo environment, + ILocalizationManager localizationManager) + { + if (!startupOptions.ContainsOption("-enablegdi")) + { + try + { + return new SkiaEncoder(logger, appPaths, httpClient, fileSystem, localizationManager); + } + catch (Exception ex) + { + logger.LogInformation("Skia not available. Will try next image processor. {0}", ex.Message); + } + + try + { + return new ImageMagickEncoder(logger, appPaths, httpClient, fileSystem, environment); + } + catch + { + logger.LogInformation("ImageMagick not available. Will try next image processor."); + } + } + + return new NullImageEncoder(); + } + + private static EnvironmentInfo getEnvironmentInfo() + => new EnvironmentInfo() + { + SystemArchitecture = RuntimeInformation.OSArchitecture, + OperatingSystem = getOperatingSystem() + }; + + private static MediaBrowser.Model.System.OperatingSystem getOperatingSystem() { + switch (Environment.OSVersion.Platform) + { + case PlatformID.MacOSX: + return MediaBrowser.Model.System.OperatingSystem.OSX; + case PlatformID.Win32NT: + return MediaBrowser.Model.System.OperatingSystem.Windows; + case PlatformID.Unix: + { + string osDescription = RuntimeInformation.OSDescription; + if (osDescription.Contains("linux", StringComparison.OrdinalIgnoreCase)) + { + return MediaBrowser.Model.System.OperatingSystem.Linux; + } + else if (osDescription.Contains("darwin", StringComparison.OrdinalIgnoreCase)) + { + return MediaBrowser.Model.System.OperatingSystem.OSX; + } + else if (osDescription.Contains("bsd", StringComparison.OrdinalIgnoreCase)) + { + return MediaBrowser.Model.System.OperatingSystem.BSD; + } + throw new Exception($"Can't resolve OS with description: {Environment.OSVersion.Platform}"); + } + default: throw new Exception($"Can't resolve OS with description: {Environment.OSVersion.Platform}"); + } + } + + public static void Shutdown() + { + ApplicationTaskCompletionSource.SetResult(true); + } + + public static void Restart() + { + _restartOnShutdown = true; + + Shutdown(); + } + + private static void StartNewInstance(StartupOptions startupOptions) + { + _logger.LogInformation("Starting new instance"); + + string module = startupOptions.GetOption("-restartpath"); + + if (string.IsNullOrWhiteSpace(module)) + { + module = Environment.GetCommandLineArgs().First(); + } + + string commandLineArgsString; + + if (startupOptions.ContainsOption("-restartargs")) + { + commandLineArgsString = startupOptions.GetOption("-restartargs") ?? string.Empty; + } + else + { + commandLineArgsString = string .Join(" ", + Environment.GetCommandLineArgs() + .Skip(1) + .Select(NormalizeCommandLineArgument) + ); + } + + _logger.LogInformation("Executable: {0}", module); + _logger.LogInformation("Arguments: {0}", commandLineArgsString); + + Process.Start(module, commandLineArgsString); + } + + private static string NormalizeCommandLineArgument(string arg) + { + if (!arg.Contains(" ", StringComparison.OrdinalIgnoreCase)) + { + return arg; + } + + return "\"" + arg + "\""; + } + } +} diff --git a/Jellyfin.Server/SocketSharp/HttpFile.cs b/Jellyfin.Server/SocketSharp/HttpFile.cs new file mode 100644 index 000000000..4a798062d --- /dev/null +++ b/Jellyfin.Server/SocketSharp/HttpFile.cs @@ -0,0 +1,14 @@ +using System.IO; +using MediaBrowser.Model.Services; + +namespace Jellyfin.SocketSharp +{ + public class HttpFile : IHttpFile + { + public string Name { get; set; } + public string FileName { get; set; } + public long ContentLength { get; set; } + public string ContentType { get; set; } + public Stream InputStream { get; set; } + } +} diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs new file mode 100644 index 000000000..31f289497 --- /dev/null +++ b/Jellyfin.Server/SocketSharp/RequestMono.cs @@ -0,0 +1,805 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using MediaBrowser.Model.Services; + +namespace Jellyfin.SocketSharp +{ + public partial class WebSocketSharpRequest : IHttpRequest + { + static internal string GetParameter(string header, string attr) + { + int ap = header.IndexOf(attr); + if (ap == -1) + return null; + + ap += attr.Length; + if (ap >= header.Length) + return null; + + char ending = header[ap]; + if (ending != '"') + ending = ' '; + + int end = header.IndexOf(ending, ap + 1); + if (end == -1) + return ending == '"' ? null : header.Substring(ap); + + return header.Substring(ap + 1, end - ap - 1); + } + + async Task LoadMultiPart(WebROCollection form) + { + string boundary = GetParameter(ContentType, "; boundary="); + if (boundary == null) + return; + + using (var requestStream = InputStream) + { + //DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request + //Not ending with \r\n? + var ms = new MemoryStream(32 * 1024); + await requestStream.CopyToAsync(ms).ConfigureAwait(false); + + var input = ms; + ms.WriteByte((byte)'\r'); + ms.WriteByte((byte)'\n'); + + input.Position = 0; + + // Uncomment to debug + //var content = new StreamReader(ms).ReadToEnd(); + //Console.WriteLine(boundary + "::" + content); + //input.Position = 0; + + var multi_part = new HttpMultipart(input, boundary, ContentEncoding); + + HttpMultipart.Element e; + while ((e = multi_part.ReadNextElement()) != null) + { + if (e.Filename == null) + { + byte[] copy = new byte[e.Length]; + + input.Position = e.Start; + input.Read(copy, 0, (int)e.Length); + + form.Add(e.Name, (e.Encoding ?? ContentEncoding).GetString(copy, 0, copy.Length)); + } + else + { + // + // We use a substream, as in 2.x we will support large uploads streamed to disk, + // + HttpPostedFile sub = new HttpPostedFile(e.Filename, e.ContentType, input, e.Start, e.Length); + files[e.Name] = sub; + } + } + } + } + + public async Task GetFormData() + { + var form = new WebROCollection(); + files = new Dictionary(); + + if (IsContentType("multipart/form-data", true)) + { + await LoadMultiPart(form).ConfigureAwait(false); + } + else if (IsContentType("application/x-www-form-urlencoded", true)) + { + await LoadWwwForm(form).ConfigureAwait(false); + } + +#if NET_4_0 + if (validateRequestNewMode && !checked_form) { + // Setting this before calling the validator prevents + // possible endless recursion + checked_form = true; + ValidateNameValueCollection ("Form", query_string_nvc, RequestValidationSource.Form); + } else +#endif + if (validate_form && !checked_form) + { + checked_form = true; + ValidateNameValueCollection("Form", form); + } + + return form; + } + + public string Accept + { + get + { + return string.IsNullOrEmpty(request.Headers["Accept"]) ? null : request.Headers["Accept"]; + } + } + + public string Authorization + { + get + { + return string.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"]; + } + } + + protected bool validate_cookies, validate_query_string, validate_form; + protected bool checked_cookies, checked_query_string, checked_form; + + static void ThrowValidationException(string name, string key, string value) + { + string v = "\"" + value + "\""; + if (v.Length > 20) + v = v.Substring(0, 16) + "...\""; + + string msg = String.Format("A potentially dangerous Request.{0} value was " + + "detected from the client ({1}={2}).", name, key, v); + + throw new Exception(msg); + } + + static void ValidateNameValueCollection(string name, QueryParamCollection coll) + { + if (coll == null) + return; + + foreach (var pair in coll) + { + var key = pair.Name; + var val = pair.Value; + if (val != null && val.Length > 0 && IsInvalidString(val)) + ThrowValidationException(name, key, val); + } + } + + internal static bool IsInvalidString(string val) + { + int validationFailureIndex; + + return IsInvalidString(val, out validationFailureIndex); + } + + internal static bool IsInvalidString(string val, out int validationFailureIndex) + { + validationFailureIndex = 0; + + int len = val.Length; + if (len < 2) + return false; + + char current = val[0]; + for (int idx = 1; idx < len; idx++) + { + char next = val[idx]; + // See http://secunia.com/advisories/14325 + if (current == '<' || current == '\xff1c') + { + if (next == '!' || next < ' ' + || (next >= 'a' && next <= 'z') + || (next >= 'A' && next <= 'Z')) + { + validationFailureIndex = idx - 1; + return true; + } + } + else if (current == '&' && next == '#') + { + validationFailureIndex = idx - 1; + return true; + } + + current = next; + } + + return false; + } + + public void ValidateInput() + { + validate_cookies = true; + validate_query_string = true; + validate_form = true; + } + + bool IsContentType(string ct, bool starts_with) + { + if (ct == null || ContentType == null) return false; + + if (starts_with) + return StrUtils.StartsWith(ContentType, ct, true); + + return string.Equals(ContentType, ct, StringComparison.OrdinalIgnoreCase); + } + + async Task LoadWwwForm(WebROCollection form) + { + using (Stream input = InputStream) + { + using (var ms = new MemoryStream()) + { + await input.CopyToAsync(ms).ConfigureAwait(false); + ms.Position = 0; + + using (StreamReader s = new StreamReader(ms, ContentEncoding)) + { + StringBuilder key = new StringBuilder(); + StringBuilder value = new StringBuilder(); + int c; + + while ((c = s.Read()) != -1) + { + if (c == '=') + { + value.Length = 0; + while ((c = s.Read()) != -1) + { + if (c == '&') + { + AddRawKeyValue(form, key, value); + break; + } + else + value.Append((char)c); + } + if (c == -1) + { + AddRawKeyValue(form, key, value); + return; + } + } + else if (c == '&') + AddRawKeyValue(form, key, value); + else + key.Append((char)c); + } + if (c == -1) + AddRawKeyValue(form, key, value); + } + } + } + } + + void AddRawKeyValue(WebROCollection form, StringBuilder key, StringBuilder value) + { + string decodedKey = WebUtility.UrlDecode(key.ToString()); + form.Add(decodedKey, + WebUtility.UrlDecode(value.ToString())); + + key.Length = 0; + value.Length = 0; + } + + Dictionary files; + + class WebROCollection : QueryParamCollection + { + public override string ToString() + { + StringBuilder result = new StringBuilder(); + foreach (var pair in this) + { + if (result.Length > 0) + result.Append('&'); + + var key = pair.Name; + if (key != null && key.Length > 0) + { + result.Append(key); + result.Append('='); + } + result.Append(pair.Value); + } + + return result.ToString(); + } + } + + public sealed class HttpPostedFile + { + string name; + string content_type; + Stream stream; + + class ReadSubStream : Stream + { + Stream s; + long offset; + long end; + long position; + + public ReadSubStream(Stream s, long offset, long length) + { + this.s = s; + this.offset = offset; + this.end = offset + length; + position = offset; + } + + public override void Flush() + { + } + + public override int Read(byte[] buffer, int dest_offset, int count) + { + if (buffer == null) + throw new ArgumentNullException("buffer"); + + if (dest_offset < 0) + throw new ArgumentOutOfRangeException("dest_offset", "< 0"); + + if (count < 0) + throw new ArgumentOutOfRangeException("count", "< 0"); + + int len = buffer.Length; + if (dest_offset > len) + throw new ArgumentException("destination offset is beyond array size"); + // reordered to avoid possible integer overflow + if (dest_offset > len - count) + throw new ArgumentException("Reading would overrun buffer"); + + if (count > end - position) + count = (int)(end - position); + + if (count <= 0) + return 0; + + s.Position = position; + int result = s.Read(buffer, dest_offset, count); + if (result > 0) + position += result; + else + position = end; + + return result; + } + + public override int ReadByte() + { + if (position >= end) + return -1; + + s.Position = position; + int result = s.ReadByte(); + if (result < 0) + position = end; + else + position++; + + return result; + } + + public override long Seek(long d, SeekOrigin origin) + { + long real; + switch (origin) + { + case SeekOrigin.Begin: + real = offset + d; + break; + case SeekOrigin.End: + real = end + d; + break; + case SeekOrigin.Current: + real = position + d; + break; + default: + throw new ArgumentException(); + } + + long virt = real - offset; + if (virt < 0 || virt > Length) + throw new ArgumentException(); + + position = s.Seek(real, SeekOrigin.Begin); + return position; + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + public override bool CanRead + { + get { return true; } + } + public override bool CanSeek + { + get { return true; } + } + public override bool CanWrite + { + get { return false; } + } + + public override long Length + { + get { return end - offset; } + } + + public override long Position + { + get + { + return position - offset; + } + set + { + if (value > Length) + throw new ArgumentOutOfRangeException(); + + position = Seek(value, SeekOrigin.Begin); + } + } + } + + internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length) + { + this.name = name; + this.content_type = content_type; + this.stream = new ReadSubStream(base_stream, offset, length); + } + + public string ContentType + { + get + { + return content_type; + } + } + + public int ContentLength + { + get + { + return (int)stream.Length; + } + } + + public string FileName + { + get + { + return name; + } + } + + public Stream InputStream + { + get + { + return stream; + } + } + } + + class Helpers + { + public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture; + } + + internal sealed class StrUtils + { + public static bool StartsWith(string str1, string str2, bool ignore_case) + { + if (string.IsNullOrEmpty(str1)) + { + return false; + } + + var comparison = ignore_case ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + return str1.IndexOf(str2, comparison) == 0; + } + + public static bool EndsWith(string str1, string str2, bool ignore_case) + { + int l2 = str2.Length; + if (l2 == 0) + return true; + + int l1 = str1.Length; + if (l2 > l1) + return false; + + var comparison = ignore_case ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + return str1.IndexOf(str2, comparison) == str1.Length - str2.Length - 1; + } + } + + class HttpMultipart + { + + public class Element + { + public string ContentType; + public string Name; + public string Filename; + public Encoding Encoding; + public long Start; + public long Length; + + public override string ToString() + { + return "ContentType " + ContentType + ", Name " + Name + ", Filename " + Filename + ", Start " + + Start.ToString() + ", Length " + Length.ToString(); + } + } + + Stream data; + string boundary; + byte[] boundary_bytes; + byte[] buffer; + bool at_eof; + Encoding encoding; + StringBuilder sb; + + const byte HYPHEN = (byte)'-', LF = (byte)'\n', CR = (byte)'\r'; + + // See RFC 2046 + // In the case of multipart entities, in which one or more different + // sets of data are combined in a single body, a "multipart" media type + // field must appear in the entity's header. The body must then contain + // one or more body parts, each preceded by a boundary delimiter line, + // and the last one followed by a closing boundary delimiter line. + // After its boundary delimiter line, each body part then consists of a + // header area, a blank line, and a body area. Thus a body part is + // similar to an RFC 822 message in syntax, but different in meaning. + + public HttpMultipart(Stream data, string b, Encoding encoding) + { + this.data = data; + //DB: 30/01/11: cannot set or read the Position in HttpListener in Win.NET + //var ms = new MemoryStream(32 * 1024); + //data.CopyTo(ms); + //this.data = ms; + + boundary = b; + boundary_bytes = encoding.GetBytes(b); + buffer = new byte[boundary_bytes.Length + 2]; // CRLF or '--' + this.encoding = encoding; + sb = new StringBuilder(); + } + + string ReadLine() + { + // CRLF or LF are ok as line endings. + bool got_cr = false; + int b = 0; + sb.Length = 0; + while (true) + { + b = data.ReadByte(); + if (b == -1) + { + return null; + } + + if (b == LF) + { + break; + } + got_cr = b == CR; + sb.Append((char)b); + } + + if (got_cr) + sb.Length--; + + return sb.ToString(); + + } + + static string GetContentDispositionAttribute(string l, string name) + { + int idx = l.IndexOf(name + "=\""); + if (idx < 0) + return null; + int begin = idx + name.Length + "=\"".Length; + int end = l.IndexOf('"', begin); + if (end < 0) + return null; + if (begin == end) + return ""; + return l.Substring(begin, end - begin); + } + + string GetContentDispositionAttributeWithEncoding(string l, string name) + { + int idx = l.IndexOf(name + "=\""); + if (idx < 0) + return null; + int begin = idx + name.Length + "=\"".Length; + int end = l.IndexOf('"', begin); + if (end < 0) + return null; + if (begin == end) + return ""; + + string temp = l.Substring(begin, end - begin); + byte[] source = new byte[temp.Length]; + for (int i = temp.Length - 1; i >= 0; i--) + source[i] = (byte)temp[i]; + + return encoding.GetString(source, 0, source.Length); + } + + bool ReadBoundary() + { + try + { + string line = ReadLine(); + while (line == "") + line = ReadLine(); + if (line[0] != '-' || line[1] != '-') + return false; + + if (!StrUtils.EndsWith(line, boundary, false)) + return true; + } + catch + { + } + + return false; + } + + string ReadHeaders() + { + string s = ReadLine(); + if (s == "") + return null; + + return s; + } + + bool CompareBytes(byte[] orig, byte[] other) + { + for (int i = orig.Length - 1; i >= 0; i--) + if (orig[i] != other[i]) + return false; + + return true; + } + + long MoveToNextBoundary() + { + long retval = 0; + bool got_cr = false; + + int state = 0; + int c = data.ReadByte(); + while (true) + { + if (c == -1) + return -1; + + if (state == 0 && c == LF) + { + retval = data.Position - 1; + if (got_cr) + retval--; + state = 1; + c = data.ReadByte(); + } + else if (state == 0) + { + got_cr = c == CR; + c = data.ReadByte(); + } + else if (state == 1 && c == '-') + { + c = data.ReadByte(); + if (c == -1) + return -1; + + if (c != '-') + { + state = 0; + got_cr = false; + continue; // no ReadByte() here + } + + int nread = data.Read(buffer, 0, buffer.Length); + int bl = buffer.Length; + if (nread != bl) + return -1; + + if (!CompareBytes(boundary_bytes, buffer)) + { + state = 0; + data.Position = retval + 2; + if (got_cr) + { + data.Position++; + got_cr = false; + } + c = data.ReadByte(); + continue; + } + + if (buffer[bl - 2] == '-' && buffer[bl - 1] == '-') + { + at_eof = true; + } + else if (buffer[bl - 2] != CR || buffer[bl - 1] != LF) + { + state = 0; + data.Position = retval + 2; + if (got_cr) + { + data.Position++; + got_cr = false; + } + c = data.ReadByte(); + continue; + } + data.Position = retval + 2; + if (got_cr) + data.Position++; + break; + } + else + { + // state == 1 + state = 0; // no ReadByte() here + } + } + + return retval; + } + + public Element ReadNextElement() + { + if (at_eof || ReadBoundary()) + return null; + + Element elem = new Element(); + string header; + while ((header = ReadHeaders()) != null) + { + if (StrUtils.StartsWith(header, "Content-Disposition:", true)) + { + elem.Name = GetContentDispositionAttribute(header, "name"); + elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename")); + } + else if (StrUtils.StartsWith(header, "Content-Type:", true)) + { + elem.ContentType = header.Substring("Content-Type:".Length).Trim(); + elem.Encoding = GetEncoding(elem.ContentType); + } + } + + long start = 0; + start = data.Position; + elem.Start = start; + long pos = MoveToNextBoundary(); + if (pos == -1) + return null; + + elem.Length = pos - start; + return elem; + } + + static string StripPath(string path) + { + if (path == null || path.Length == 0) + return path; + + if (path.IndexOf(":\\") != 1 && !path.StartsWith("\\\\")) + return path; + return path.Substring(path.LastIndexOf('\\') + 1); + } + } + } +} diff --git a/Jellyfin.Server/SocketSharp/SharpWebSocket.cs b/Jellyfin.Server/SocketSharp/SharpWebSocket.cs new file mode 100644 index 000000000..1c72035a5 --- /dev/null +++ b/Jellyfin.Server/SocketSharp/SharpWebSocket.cs @@ -0,0 +1,159 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Net.WebSockets; +using Emby.Server.Implementations.Net; +using MediaBrowser.Common.Events; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.SocketSharp +{ + public class SharpWebSocket : IWebSocket + { + /// + /// The logger + /// + private readonly ILogger _logger; + + public event EventHandler Closed; + + /// + /// Gets or sets the web socket. + /// + /// The web socket. + private SocketHttpListener.WebSocket WebSocket { get; set; } + + private TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); + private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); + + public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger) + { + if (socket == null) + { + throw new ArgumentNullException("socket"); + } + + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + + _logger = logger; + WebSocket = socket; + + socket.OnMessage += socket_OnMessage; + socket.OnClose += socket_OnClose; + socket.OnError += socket_OnError; + + WebSocket.ConnectAsServer(); + } + + public Task StartReceive() + { + return _taskCompletionSource.Task; + } + + void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e) + { + _logger.LogError("Error in SharpWebSocket: {0}", e.Message ?? string.Empty); + //EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); + } + + void socket_OnClose(object sender, SocketHttpListener.CloseEventArgs e) + { + _taskCompletionSource.TrySetResult(true); + + EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); + } + + void socket_OnMessage(object sender, SocketHttpListener.MessageEventArgs e) + { + //if (!string.IsNullOrEmpty(e.Data)) + //{ + // if (OnReceive != null) + // { + // OnReceive(e.Data); + // } + // return; + //} + if (OnReceiveBytes != null) + { + OnReceiveBytes(e.RawData); + } + } + + /// + /// Gets or sets the state. + /// + /// The state. + public WebSocketState State + { + get + { + return WebSocket.ReadyState; + } + } + + /// + /// Sends the async. + /// + /// The bytes. + /// if set to true [end of message]. + /// The cancellation token. + /// Task. + public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken) + { + return WebSocket.SendAsync(bytes); + } + + /// + /// Sends the asynchronous. + /// + /// The text. + /// if set to true [end of message]. + /// The cancellation token. + /// Task. + public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken) + { + return WebSocket.SendAsync(text); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// 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) + { + if (dispose) + { + WebSocket.OnMessage -= socket_OnMessage; + WebSocket.OnClose -= socket_OnClose; + WebSocket.OnError -= socket_OnError; + + _cancellationTokenSource.Cancel(); + + WebSocket.Close(); + } + } + + /// + /// Gets or sets the receive action. + /// + /// The receive action. + public Action OnReceiveBytes { get; set; } + + /// + /// Gets or sets the on receive. + /// + /// The on receive. + public Action OnReceive { get; set; } + } +} diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs new file mode 100644 index 000000000..c360a8fce --- /dev/null +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Emby.Server.Implementations.Net; +using Emby.Server.Implementations.HttpServer; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Cryptography; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Services; +using MediaBrowser.Model.System; +using MediaBrowser.Model.Text; +using Microsoft.Extensions.Logging; +using SocketHttpListener.Net; + +namespace Jellyfin.SocketSharp +{ + public class WebSocketSharpListener : IHttpListener + { + private HttpListener _listener; + + private readonly ILogger _logger; + private readonly X509Certificate _certificate; + private readonly IStreamHelper _streamHelper; + private readonly ITextEncoding _textEncoding; + private readonly INetworkManager _networkManager; + private readonly ISocketFactory _socketFactory; + private readonly ICryptoProvider _cryptoProvider; + private readonly IFileSystem _fileSystem; + private readonly bool _enableDualMode; + private readonly IEnvironmentInfo _environment; + + private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); + private CancellationToken _disposeCancellationToken; + + public WebSocketSharpListener(ILogger logger, X509Certificate certificate, IStreamHelper streamHelper, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, bool enableDualMode, IFileSystem fileSystem, IEnvironmentInfo environment) + { + _logger = logger; + _certificate = certificate; + _streamHelper = streamHelper; + _textEncoding = textEncoding; + _networkManager = networkManager; + _socketFactory = socketFactory; + _cryptoProvider = cryptoProvider; + _enableDualMode = enableDualMode; + _fileSystem = fileSystem; + _environment = environment; + + _disposeCancellationToken = _disposeCancellationTokenSource.Token; + } + + public Func ErrorHandler { get; set; } + public Func RequestHandler { get; set; } + + public Action WebSocketConnecting { get; set; } + + public Action WebSocketConnected { get; set; } + + public void Start(IEnumerable urlPrefixes) + { + if (_listener == null) + _listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _networkManager, _textEncoding, _streamHelper, _fileSystem, _environment); + + _listener.EnableDualMode = _enableDualMode; + + if (_certificate != null) + { + _listener.LoadCert(_certificate); + } + + foreach (var prefix in urlPrefixes) + { + _logger.LogInformation("Adding HttpListener prefix " + prefix); + _listener.Prefixes.Add(prefix); + } + + _listener.OnContext = ProcessContext; + + _listener.Start(); + } + + private void ProcessContext(HttpListenerContext context) + { + //InitTask(context, _disposeCancellationToken); + Task.Run(() => InitTask(context, _disposeCancellationToken)); + } + + private void LogRequest(ILogger logger, HttpListenerRequest request) + { + var url = request.Url.ToString(); + + logger.LogInformation("{0} {1}. UserAgent: {2}", request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, url, request.UserAgent ?? string.Empty); + } + + private Task InitTask(HttpListenerContext context, CancellationToken cancellationToken) + { + IHttpRequest httpReq = null; + var request = context.Request; + + try + { + if (request.IsWebSocketRequest) + { + LogRequest(_logger, request); + + return ProcessWebSocketRequest(context); + } + + httpReq = GetRequest(context); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error processing request"); + + httpReq = httpReq ?? GetRequest(context); + return ErrorHandler(ex, httpReq, true, true); + } + + var uri = request.Url; + + return RequestHandler(httpReq, uri.OriginalString, uri.Host, uri.LocalPath, cancellationToken); + } + + private async Task ProcessWebSocketRequest(HttpListenerContext ctx) + { + try + { + var endpoint = ctx.Request.RemoteEndPoint.ToString(); + var url = ctx.Request.RawUrl; + + var queryString = ctx.Request.QueryString; + + var connectingArgs = new WebSocketConnectingEventArgs + { + Url = url, + QueryString = queryString, + Endpoint = endpoint + }; + + if (WebSocketConnecting != null) + { + WebSocketConnecting(connectingArgs); + } + + if (connectingArgs.AllowConnection) + { + _logger.LogDebug("Web socket connection allowed"); + + var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false); + + if (WebSocketConnected != null) + { + var socket = new SharpWebSocket(webSocketContext.WebSocket, _logger); + + WebSocketConnected(new WebSocketConnectEventArgs + { + Url = url, + QueryString = queryString, + WebSocket = socket, + Endpoint = endpoint + }); + + await ReceiveWebSocket(ctx, socket).ConfigureAwait(false); + } + } + else + { + _logger.LogWarning("Web socket connection not allowed"); + ctx.Response.StatusCode = 401; + ctx.Response.Close(); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "AcceptWebSocketAsync error"); + ctx.Response.StatusCode = 500; + ctx.Response.Close(); + } + } + + private async Task ReceiveWebSocket(HttpListenerContext ctx, SharpWebSocket socket) + { + try + { + await socket.StartReceive().ConfigureAwait(false); + } + finally + { + TryClose(ctx, 200); + } + } + + private void TryClose(HttpListenerContext ctx, int statusCode) + { + try + { + ctx.Response.StatusCode = 200; + ctx.Response.Close(); + } + catch (ObjectDisposedException) + { + } + catch (Exception ex) + { + _logger.LogError(ex, "Error closing web socket response"); + } + } + + private IHttpRequest GetRequest(HttpListenerContext httpContext) + { + var urlSegments = httpContext.Request.Url.Segments; + + var operationName = urlSegments[urlSegments.Length - 1]; + + var req = new WebSocketSharpRequest(httpContext, operationName, _logger); + + return req; + } + + public Task Stop() + { + _disposeCancellationTokenSource.Cancel(); + + if (_listener != null) + { + _listener.Close(); + } + + return Task.CompletedTask; + } + + public void Dispose() + { + Dispose(true); + } + + private bool _disposed; + private readonly object _disposeLock = new object(); + protected virtual void Dispose(bool disposing) + { + if (_disposed) return; + + lock (_disposeLock) + { + if (_disposed) return; + + if (disposing) + { + Stop(); + } + + //release unmanaged resources here... + _disposed = true; + } + } + } +} diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs new file mode 100644 index 000000000..7c9dc8f88 --- /dev/null +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -0,0 +1,554 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Emby.Server.Implementations.HttpServer; +using MediaBrowser.Model.Services; +using Microsoft.Extensions.Logging; +using SocketHttpListener.Net; +using IHttpFile = MediaBrowser.Model.Services.IHttpFile; +using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest; +using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse; +using IResponse = MediaBrowser.Model.Services.IResponse; + +namespace Jellyfin.SocketSharp +{ + public partial class WebSocketSharpRequest : IHttpRequest + { + private readonly HttpListenerRequest request; + private readonly IHttpResponse response; + + public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, ILogger logger) + { + this.OperationName = operationName; + this.request = httpContext.Request; + this.response = new WebSocketSharpResponse(logger, httpContext.Response, this); + + //HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]); + } + + private static string GetHandlerPathIfAny(string listenerUrl) + { + if (listenerUrl == null) return null; + var pos = listenerUrl.IndexOf("://", StringComparison.OrdinalIgnoreCase); + if (pos == -1) return null; + var startHostUrl = listenerUrl.Substring(pos + "://".Length); + var endPos = startHostUrl.IndexOf('/'); + if (endPos == -1) return null; + var endHostUrl = startHostUrl.Substring(endPos + 1); + return string.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/'); + } + + public HttpListenerRequest HttpRequest + { + get { return request; } + } + + public object OriginalRequest + { + get { return request; } + } + + public IResponse Response + { + get { return response; } + } + + public IHttpResponse HttpResponse + { + get { return response; } + } + + public string OperationName { get; set; } + + public object Dto { get; set; } + + public string RawUrl + { + get { return request.RawUrl; } + } + + public string AbsoluteUri + { + get { return request.Url.AbsoluteUri.TrimEnd('/'); } + } + + public string UserHostAddress + { + get { return request.UserHostAddress; } + } + + public string XForwardedFor + { + get + { + return String.IsNullOrEmpty(request.Headers["X-Forwarded-For"]) ? null : request.Headers["X-Forwarded-For"]; + } + } + + public int? XForwardedPort + { + get + { + return string.IsNullOrEmpty(request.Headers["X-Forwarded-Port"]) ? (int?)null : int.Parse(request.Headers["X-Forwarded-Port"]); + } + } + + public string XForwardedProtocol + { + get + { + return string.IsNullOrEmpty(request.Headers["X-Forwarded-Proto"]) ? null : request.Headers["X-Forwarded-Proto"]; + } + } + + public string XRealIp + { + get + { + return String.IsNullOrEmpty(request.Headers["X-Real-IP"]) ? null : request.Headers["X-Real-IP"]; + } + } + + private string remoteIp; + public string RemoteIp + { + get + { + return remoteIp ?? + (remoteIp = (CheckBadChars(XForwardedFor)) ?? + (NormalizeIp(CheckBadChars(XRealIp)) ?? + (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null))); + } + } + + private static readonly char[] HttpTrimCharacters = new char[] { (char)0x09, (char)0xA, (char)0xB, (char)0xC, (char)0xD, (char)0x20 }; + + // + // CheckBadChars - throws on invalid chars to be not found in header name/value + // + internal static string CheckBadChars(string name) + { + if (name == null || name.Length == 0) + { + return name; + } + + // VALUE check + //Trim spaces from both ends + name = name.Trim(HttpTrimCharacters); + + //First, check for correctly formed multi-line value + //Second, check for absenece of CTL characters + int crlf = 0; + for (int i = 0; i < name.Length; ++i) + { + char c = (char)(0x000000ff & (uint)name[i]); + switch (crlf) + { + case 0: + if (c == '\r') + { + crlf = 1; + } + else if (c == '\n') + { + // Technically this is bad HTTP. But it would be a breaking change to throw here. + // Is there an exploit? + crlf = 2; + } + else if (c == 127 || (c < ' ' && c != '\t')) + { + throw new ArgumentException("net_WebHeaderInvalidControlChars"); + } + break; + + case 1: + if (c == '\n') + { + crlf = 2; + break; + } + throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); + + case 2: + if (c == ' ' || c == '\t') + { + crlf = 0; + break; + } + throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); + } + } + if (crlf != 0) + { + throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); + } + return name; + } + + internal static bool ContainsNonAsciiChars(string token) + { + for (int i = 0; i < token.Length; ++i) + { + if ((token[i] < 0x20) || (token[i] > 0x7e)) + { + return true; + } + } + return false; + } + + private string NormalizeIp(string ip) + { + if (!string.IsNullOrWhiteSpace(ip)) + { + // Handle ipv4 mapped to ipv6 + const string srch = "::ffff:"; + var index = ip.IndexOf(srch, StringComparison.OrdinalIgnoreCase); + if (index == 0) + { + ip = ip.Substring(srch.Length); + } + } + + return ip; + } + + public bool IsSecureConnection + { + get { return request.IsSecureConnection || XForwardedProtocol == "https"; } + } + + public string[] AcceptTypes + { + get { return request.AcceptTypes; } + } + + private Dictionary items; + public Dictionary Items + { + get { return items ?? (items = new Dictionary()); } + } + + private string responseContentType; + public string ResponseContentType + { + get + { + return responseContentType + ?? (responseContentType = GetResponseContentType(this)); + } + set + { + this.responseContentType = value; + } + } + + public const string FormUrlEncoded = "application/x-www-form-urlencoded"; + public const string MultiPartFormData = "multipart/form-data"; + public static string GetResponseContentType(IRequest httpReq) + { + var specifiedContentType = GetQueryStringContentType(httpReq); + if (!string.IsNullOrEmpty(specifiedContentType)) return specifiedContentType; + + var serverDefaultContentType = "application/json"; + + var acceptContentTypes = httpReq.AcceptTypes; + string defaultContentType = null; + if (HasAnyOfContentTypes(httpReq, FormUrlEncoded, MultiPartFormData)) + { + defaultContentType = serverDefaultContentType; + } + + var acceptsAnything = false; + var hasDefaultContentType = !string.IsNullOrEmpty(defaultContentType); + if (acceptContentTypes != null) + { + foreach (var acceptsType in acceptContentTypes) + { + var contentType = HttpResultFactory.GetRealContentType(acceptsType); + acceptsAnything = acceptsAnything || contentType == "*/*"; + } + + if (acceptsAnything) + { + if (hasDefaultContentType) + return defaultContentType; + if (serverDefaultContentType != null) + return serverDefaultContentType; + } + } + + if (acceptContentTypes == null && httpReq.ContentType == Soap11) + { + return Soap11; + } + + //We could also send a '406 Not Acceptable', but this is allowed also + return serverDefaultContentType; + } + + public const string Soap11 = "text/xml; charset=utf-8"; + + public static bool HasAnyOfContentTypes(IRequest request, params string[] contentTypes) + { + if (contentTypes == null || request.ContentType == null) return false; + foreach (var contentType in contentTypes) + { + if (IsContentType(request, contentType)) return true; + } + return false; + } + + public static bool IsContentType(IRequest request, string contentType) + { + return request.ContentType.StartsWith(contentType, StringComparison.OrdinalIgnoreCase); + } + + public const string Xml = "application/xml"; + private static string GetQueryStringContentType(IRequest httpReq) + { + var format = httpReq.QueryString["format"]; + if (format == null) + { + const int formatMaxLength = 4; + var pi = httpReq.PathInfo; + if (pi == null || pi.Length <= formatMaxLength) return null; + if (pi[0] == '/') pi = pi.Substring(1); + format = LeftPart(pi, '/'); + if (format.Length > formatMaxLength) return null; + } + + format = LeftPart(format, '.').ToLower(); + if (format.Contains("json")) return "application/json"; + if (format.Contains("xml")) return Xml; + + return null; + } + + public static string LeftPart(string strVal, char needle) + { + if (strVal == null) return null; + var pos = strVal.IndexOf(needle); + return pos == -1 + ? strVal + : strVal.Substring(0, pos); + } + + public static string HandlerFactoryPath; + + private string pathInfo; + public string PathInfo + { + get + { + if (this.pathInfo == null) + { + var mode = HandlerFactoryPath; + + var pos = request.RawUrl.IndexOf("?"); + if (pos != -1) + { + var path = request.RawUrl.Substring(0, pos); + this.pathInfo = GetPathInfo( + path, + mode, + mode ?? ""); + } + else + { + this.pathInfo = request.RawUrl; + } + + this.pathInfo = System.Net.WebUtility.UrlDecode(pathInfo); + this.pathInfo = NormalizePathInfo(pathInfo, mode); + } + return this.pathInfo; + } + } + + private static string GetPathInfo(string fullPath, string mode, string appPath) + { + var pathInfo = ResolvePathInfoFromMappedPath(fullPath, mode); + if (!string.IsNullOrEmpty(pathInfo)) return pathInfo; + + //Wildcard mode relies on this to work out the handlerPath + pathInfo = ResolvePathInfoFromMappedPath(fullPath, appPath); + if (!string.IsNullOrEmpty(pathInfo)) return pathInfo; + + return fullPath; + } + + private static string ResolvePathInfoFromMappedPath(string fullPath, string mappedPathRoot) + { + if (mappedPathRoot == null) return null; + + var sbPathInfo = new StringBuilder(); + var fullPathParts = fullPath.Split('/'); + var mappedPathRootParts = mappedPathRoot.Split('/'); + var fullPathIndexOffset = mappedPathRootParts.Length - 1; + var pathRootFound = false; + + for (var fullPathIndex = 0; fullPathIndex < fullPathParts.Length; fullPathIndex++) + { + if (pathRootFound) + { + sbPathInfo.Append("/" + fullPathParts[fullPathIndex]); + } + else if (fullPathIndex - fullPathIndexOffset >= 0) + { + pathRootFound = true; + for (var mappedPathRootIndex = 0; mappedPathRootIndex < mappedPathRootParts.Length; mappedPathRootIndex++) + { + if (!string.Equals(fullPathParts[fullPathIndex - fullPathIndexOffset + mappedPathRootIndex], mappedPathRootParts[mappedPathRootIndex], StringComparison.OrdinalIgnoreCase)) + { + pathRootFound = false; + break; + } + } + } + } + if (!pathRootFound) return null; + + var path = sbPathInfo.ToString(); + return path.Length > 1 ? path.TrimEnd('/') : "/"; + } + + private Dictionary cookies; + public IDictionary Cookies + { + get + { + if (cookies == null) + { + cookies = new Dictionary(); + foreach (var cookie in this.request.Cookies) + { + var httpCookie = (System.Net.Cookie) cookie; + cookies[httpCookie.Name] = new System.Net.Cookie(httpCookie.Name, httpCookie.Value, httpCookie.Path, httpCookie.Domain); + } + } + + return cookies; + } + } + + public string UserAgent + { + get { return request.UserAgent; } + } + + public QueryParamCollection Headers + { + get { return request.Headers; } + } + + private QueryParamCollection queryString; + public QueryParamCollection QueryString + { + get { return queryString ?? (queryString = MyHttpUtility.ParseQueryString(request.Url.Query)); } + } + + public bool IsLocal + { + get { return request.IsLocal; } + } + + private string httpMethod; + public string HttpMethod + { + get + { + return httpMethod + ?? (httpMethod = request.HttpMethod); + } + } + + public string Verb + { + get { return HttpMethod; } + } + + public string ContentType + { + get { return request.ContentType; } + } + + public Encoding contentEncoding; + public Encoding ContentEncoding + { + get { return contentEncoding ?? request.ContentEncoding; } + set { contentEncoding = value; } + } + + public Uri UrlReferrer + { + get { return request.UrlReferrer; } + } + + public static Encoding GetEncoding(string contentTypeHeader) + { + var param = GetParameter(contentTypeHeader, "charset="); + if (param == null) return null; + try + { + return Encoding.GetEncoding(param); + } + catch (ArgumentException) + { + return null; + } + } + + public Stream InputStream + { + get { return request.InputStream; } + } + + public long ContentLength + { + get { return request.ContentLength64; } + } + + private IHttpFile[] httpFiles; + public IHttpFile[] Files + { + get + { + if (httpFiles == null) + { + if (files == null) + return httpFiles = new IHttpFile[0]; + + httpFiles = new IHttpFile[files.Count]; + var i = 0; + foreach (var pair in files) + { + var reqFile = pair.Value; + httpFiles[i] = new HttpFile + { + ContentType = reqFile.ContentType, + ContentLength = reqFile.ContentLength, + FileName = reqFile.FileName, + InputStream = reqFile.InputStream, + }; + i++; + } + } + return httpFiles; + } + } + + public static string NormalizePathInfo(string pathInfo, string handlerPath) + { + if (handlerPath != null && pathInfo.TrimStart('/').StartsWith( + handlerPath, StringComparison.OrdinalIgnoreCase)) + { + return pathInfo.TrimStart('/').Substring(handlerPath.Length); + } + + return pathInfo; + } + } +} diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs new file mode 100644 index 000000000..c7437c825 --- /dev/null +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Services; +using Microsoft.Extensions.Logging; +using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse; +using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse; +using IRequest = MediaBrowser.Model.Services.IRequest; + + +namespace Jellyfin.SocketSharp +{ + public class WebSocketSharpResponse : IHttpResponse + { + private readonly ILogger _logger; + private readonly HttpListenerResponse _response; + + public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response, IRequest request) + { + _logger = logger; + this._response = response; + Items = new Dictionary(); + Request = request; + } + + public IRequest Request { get; private set; } + public Dictionary Items { get; private set; } + public object OriginalResponse + { + get { return _response; } + } + + public int StatusCode + { + get { return this._response.StatusCode; } + set { this._response.StatusCode = value; } + } + + public string StatusDescription + { + get { return this._response.StatusDescription; } + set { this._response.StatusDescription = value; } + } + + public string ContentType + { + get { return _response.ContentType; } + set { _response.ContentType = value; } + } + + //public ICookies Cookies { get; set; } + + public void AddHeader(string name, string value) + { + if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase)) + { + ContentType = value; + return; + } + + _response.AddHeader(name, value); + } + + public QueryParamCollection Headers + { + get + { + return _response.Headers; + } + } + + public string GetHeader(string name) + { + return _response.Headers[name]; + } + + public void Redirect(string url) + { + _response.Redirect(url); + } + + public Stream OutputStream + { + get { return _response.OutputStream; } + } + + public void Close() + { + if (!this.IsClosed) + { + this.IsClosed = true; + + try + { + var response = this._response; + + var outputStream = response.OutputStream; + + // This is needed with compression + outputStream.Flush(); + outputStream.Dispose(); + + response.Close(); + } + catch (SocketException) + { + } + catch (Exception ex) + { + _logger.LogError(ex, "Error in HttpListenerResponseWrapper"); + } + } + } + + public bool IsClosed + { + get; + private set; + } + + public void SetContentLength(long contentLength) + { + //you can happily set the Content-Length header in Asp.Net + //but HttpListener will complain if you do - you have to set ContentLength64 on the response. + //workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header + _response.ContentLength64 = contentLength; + } + + public void SetCookie(Cookie cookie) + { + var cookieStr = AsHeaderValue(cookie); + _response.Headers.Add("Set-Cookie", cookieStr); + } + + public static string AsHeaderValue(Cookie cookie) + { + var defaultExpires = DateTime.MinValue; + + var path = cookie.Expires == defaultExpires + ? "/" + : cookie.Path ?? "/"; + + var sb = new StringBuilder(); + + sb.Append($"{cookie.Name}={cookie.Value};path={path}"); + + if (cookie.Expires != defaultExpires) + { + sb.Append($";expires={cookie.Expires:R}"); + } + + if (!string.IsNullOrEmpty(cookie.Domain)) + { + sb.Append($";domain={cookie.Domain}"); + } + //else if (restrictAllCookiesToDomain != null) + //{ + // sb.Append($";domain={restrictAllCookiesToDomain}"); + //} + + if (cookie.Secure) + { + sb.Append(";Secure"); + } + if (cookie.HttpOnly) + { + sb.Append(";HttpOnly"); + } + + return sb.ToString(); + } + + + public bool SendChunked + { + get { return _response.SendChunked; } + set { _response.SendChunked = value; } + } + + public bool KeepAlive { get; set; } + + public void ClearCookies() + { + } + + public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) + { + return _response.TransmitFile(path, offset, count, fileShareMode, cancellationToken); + } + } +} diff --git a/MediaBrowser.Model/System/Architecture.cs b/MediaBrowser.Model/System/Architecture.cs deleted file mode 100644 index 73f78cd58..000000000 --- a/MediaBrowser.Model/System/Architecture.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace MediaBrowser.Model.System -{ - public enum Architecture - { - X86 = 0, - X64 = 1, - Arm = 2, - Arm64 = 3 - } -} diff --git a/MediaBrowser.Model/System/IEnvironmentInfo.cs b/MediaBrowser.Model/System/IEnvironmentInfo.cs index 8cf25a365..6af514dc8 100644 --- a/MediaBrowser.Model/System/IEnvironmentInfo.cs +++ b/MediaBrowser.Model/System/IEnvironmentInfo.cs @@ -1,4 +1,5 @@ - +using System.Runtime.InteropServices; + namespace MediaBrowser.Model.System { public interface IEnvironmentInfo diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index c790731c6..031222b75 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Updates; -using System.Collections.Generic; -using System; +using System.Runtime.InteropServices; namespace MediaBrowser.Model.System { diff --git a/MediaBrowser.Server.Mono/EmbyServer.csproj b/MediaBrowser.Server.Mono/EmbyServer.csproj deleted file mode 100644 index 609af9674..000000000 --- a/MediaBrowser.Server.Mono/EmbyServer.csproj +++ /dev/null @@ -1,66 +0,0 @@ - - - - Exe - jellyfin - netcoreapp2.1 - false - - - - None - ubuntu.16.04-x64 - - - - AnyCPU - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MediaBrowser.Server.Mono/ImageEncoderHelper.cs b/MediaBrowser.Server.Mono/ImageEncoderHelper.cs deleted file mode 100644 index 29760ec55..000000000 --- a/MediaBrowser.Server.Mono/ImageEncoderHelper.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using Emby.Drawing; -using Emby.Drawing.ImageMagick; -using Emby.Server.Implementations; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; -using Emby.Drawing.Skia; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Globalization; - -namespace MediaBrowser.Server.Startup.Common -{ - public class ImageEncoderHelper - { - public static IImageEncoder GetImageEncoder(ILogger logger, - IFileSystem fileSystem, - StartupOptions startupOptions, - Func httpClient, - IApplicationPaths appPaths, - IEnvironmentInfo environment, - ILocalizationManager localizationManager) - { - if (!startupOptions.ContainsOption("-enablegdi")) - { - try - { - return new SkiaEncoder(logger, appPaths, httpClient, fileSystem, localizationManager); - } - catch (Exception ex) - { - logger.LogInformation("Skia not available. Will try next image processor. {0}", ex.Message); - } - - try - { - return new ImageMagickEncoder(logger, appPaths, httpClient, fileSystem, environment); - } - catch - { - logger.LogInformation("ImageMagick not available. Will try next image processor."); - } - } - - return new NullImageEncoder(); - } - } -} diff --git a/MediaBrowser.Server.Mono/MonoAppHost.cs b/MediaBrowser.Server.Mono/MonoAppHost.cs deleted file mode 100644 index c2ec423f8..000000000 --- a/MediaBrowser.Server.Mono/MonoAppHost.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -//using Emby.Server.CinemaMode; -using Emby.Server.Implementations; -using Emby.Server.Implementations.Library; -using Emby.Server.Implementations.HttpServer; -using Emby.Server.Implementations.Net; -using MediaBrowser.Controller.Connect; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Sync; -using IsoMounter; -using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; -using MediaBrowser.Model.Services; -using MediaBrowser.Model.System; - -namespace MediaBrowser.Server.Mono -{ - public class MonoAppHost : ApplicationHost - { - public MonoAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) - : base(applicationPaths, loggerFactory, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, networkManager) - { - } - - public override bool CanSelfRestart - { - get - { - // A restart script must be provided - return StartupOptions.ContainsOption("-restartpath"); - } - } - - //protected override ISyncManager CreateSyncManager() - //{ - // return new SyncManager(); - //} - - protected override void RestartInternal() - { - MainClass.Restart(); - } - - protected override List GetAssembliesWithPartsInternal() - { - var list = new List(); - - list.Add(GetType().Assembly); - - return list; - } - - protected override void ShutdownInternal() - { - MainClass.Shutdown(); - } - - protected override bool SupportsDualModeSockets - { - get - { - return GetMonoVersion() >= new Version(4, 6); - } - } - - private static Version GetMonoVersion() - { - Type type = Type.GetType("Mono.Runtime"); - if (type != null) - { - MethodInfo displayName = type.GetTypeInfo().GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static); - var displayNameValue = displayName.Invoke(null, null).ToString().Trim().Split(' ')[0]; - - Version version; - if (Version.TryParse(displayNameValue, out version)) - { - return version; - } - } - - return new Version(1, 0); - } - - protected override IHttpListener CreateHttpListener() - { - return new EmbyServer.SocketSharp.WebSocketSharpListener( - Logger, - Certificate, - StreamHelper, - TextEncoding, - NetworkManager, - SocketFactory, - CryptographyProvider, - SupportsDualModeSockets, - FileSystemManager, - EnvironmentInfo); - } - - } -} diff --git a/MediaBrowser.Server.Mono/Native/MonoFileSystem.cs b/MediaBrowser.Server.Mono/Native/MonoFileSystem.cs deleted file mode 100644 index 2499d8bb5..000000000 --- a/MediaBrowser.Server.Mono/Native/MonoFileSystem.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Emby.Server.Implementations.IO; -using Microsoft.Extensions.Logging; -using MediaBrowser.Model.System; -using Mono.Unix.Native; - -namespace MediaBrowser.Server.Mono.Native -{ - public class MonoFileSystem : ManagedFileSystem - { - public MonoFileSystem(ILogger logger, IEnvironmentInfo environment, string defaultDirectory, string tempPath, bool enableSeperateFileAndDirectoryQueries) - : base(logger, environment,defaultDirectory, tempPath, enableSeperateFileAndDirectoryQueries) - { - } - - public override void SetExecutable(string path) - { - // Linux: File permission to 666, and user's execute bit - Logger.LogInformation("Syscall.chmod {0} FilePermissions.DEFFILEMODE | FilePermissions.S_IRWXU | FilePermissions.S_IXGRP | FilePermissions.S_IXOTH", path); - - Syscall.chmod(path, FilePermissions.DEFFILEMODE | FilePermissions.S_IRWXU | FilePermissions.S_IXGRP | FilePermissions.S_IXOTH); - } - } -} diff --git a/MediaBrowser.Server.Mono/Native/PowerManagement.cs b/MediaBrowser.Server.Mono/Native/PowerManagement.cs deleted file mode 100644 index 219a69d65..000000000 --- a/MediaBrowser.Server.Mono/Native/PowerManagement.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using MediaBrowser.Model.System; - -namespace MediaBrowser.Server.Mono.Native -{ - public class PowerManagement : IPowerManagement - { - public void PreventSystemStandby() - { - } - - public void AllowSystemStandby() - { - } - - public void ScheduleWake(DateTime wakeTimeUtc, string displayName) - { - // nothing to Do - } - } -} diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs deleted file mode 100644 index f512fc98e..000000000 --- a/MediaBrowser.Server.Mono/Program.cs +++ /dev/null @@ -1,380 +0,0 @@ -using MediaBrowser.Server.Mono.Native; -using MediaBrowser.Server.Startup.Common; -using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Security; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Emby.Drawing; -using Emby.Server.Implementations; -using Emby.Server.Implementations.EnvironmentInfo; -using Emby.Server.Implementations.IO; -using Emby.Server.Implementations.Networking; -using MediaBrowser.Controller; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.System; -using Mono.Unix.Native; -using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate; -using System.Threading; -using InteropServices = System.Runtime.InteropServices; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Configuration; -using ILogger = Microsoft.Extensions.Logging.ILogger; -using Serilog; -using Serilog.AspNetCore; - -namespace MediaBrowser.Server.Mono -{ - public class MainClass - { - private static ILogger _logger; - private static IFileSystem FileSystem; - private static IServerApplicationPaths _appPaths; - private static ILoggerFactory _loggerFactory; - - private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); - private static bool _restartOnShutdown; - - public static void Main(string[] args) - { - var applicationPath = Assembly.GetEntryAssembly().Location; - - SetSqliteProvider(); - - var options = new StartupOptions(Environment.GetCommandLineArgs()); - - // Allow this to be specified on the command line. - var customProgramDataPath = options.GetOption("-programdata"); - - var appPaths = CreateApplicationPaths(applicationPath, customProgramDataPath); - _appPaths = appPaths; - - createLogger(); - - using (var loggerFactory = new SerilogLoggerFactory()) - { - _loggerFactory = loggerFactory; - - _logger = loggerFactory.CreateLogger("Main"); - - ApplicationHost.LogEnvironmentInfo(_logger, appPaths, true); - - AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - - RunApplication(appPaths, loggerFactory, options); - - _logger.LogInformation("Disposing app host"); - - if (_restartOnShutdown) - { - StartNewInstance(options); - } - } - } - - private static void SetSqliteProvider() - { - // SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); - //SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); - SQLitePCL.Batteries_V2.Init(); - } - - private static ServerApplicationPaths CreateApplicationPaths(string applicationPath, string programDataPath) - { - if (string.IsNullOrEmpty(programDataPath)) - { - if (InteropServices.RuntimeInformation.IsOSPlatform(InteropServices.OSPlatform.Windows)) - { - programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - } - else - { - // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. - programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); - // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used. - if (string.IsNullOrEmpty(programDataPath)){ - programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); - } - } - programDataPath = Path.Combine(programDataPath, "jellyfin"); - } - - var appFolderPath = Path.GetDirectoryName(applicationPath); - - return new ServerApplicationPaths(programDataPath, appFolderPath, appFolderPath); - } - - private static void RunApplication(ServerApplicationPaths appPaths, ILoggerFactory loggerFactory, StartupOptions options) - { - // Allow all https requests - ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); - - var environmentInfo = GetEnvironmentInfo(); - - var fileSystem = new ManagedFileSystem(loggerFactory.CreateLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory, true); - - FileSystem = fileSystem; - - using (var appHost = new MonoAppHost(appPaths, - loggerFactory, - options, - fileSystem, - new PowerManagement(), - "embyserver-mono_{version}.zip", - environmentInfo, - new NullImageEncoder(), - new SystemEvents(loggerFactory.CreateLogger("SystemEvents")), - new NetworkManager(loggerFactory.CreateLogger("NetworkManager"), environmentInfo))) - { - if (options.ContainsOption("-v")) - { - Console.WriteLine(appHost.ApplicationVersion.ToString()); - return; - } - - //Console.WriteLine("appHost.Init"); - - appHost.Init(); - - appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); - - //Console.WriteLine("Running startup tasks"); - _logger.LogInformation("Running startup tasks"); - - var task = appHost.RunStartupTasks(); - Task.WaitAll(task); - - task = ApplicationTaskCompletionSource.Task; - - Task.WaitAll(task); - } - } - - private static void createLogger() - { - var logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); - if (string.IsNullOrEmpty(logDir)){ - logDir = Path.Combine(_appPaths.ProgramDataPath, "logs"); - Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); - } - try - { - string path = Path.Combine(_appPaths.ConfigurationDirectoryPath, "logging.json"); - - if (!File.Exists(path)) - { - var assembly = typeof(MainClass).Assembly; - // For some reason the csproj name is used instead of the assembly name - var resourcePath = "EmbyServer.Resources.Configuration.logging.json"; - using (Stream rscstr = assembly.GetManifestResourceStream(resourcePath)) - using (Stream fstr = File.Open(path, FileMode.CreateNew)) - { - rscstr.CopyTo(fstr); - } - } - var configuration = new ConfigurationBuilder() - .SetBasePath(_appPaths.ConfigurationDirectoryPath) - .AddJsonFile("logging.json") - .AddEnvironmentVariables("JELLYFIN_") - .Build(); - - Serilog.Log.Logger = new LoggerConfiguration() - .ReadFrom.Configuration(configuration) - .Enrich.FromLogContext() - .CreateLogger(); - } - catch (Exception ex) - { - Serilog.Log.Logger = new LoggerConfiguration() - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}") - .WriteTo.File( - Path.Combine(logDir, "log_.log"), - rollingInterval: RollingInterval.Day, - outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}") - .Enrich.FromLogContext() - .CreateLogger(); - - Serilog.Log.Logger.Fatal(ex, "Failed to read logger config"); - } - } - - private static MonoEnvironmentInfo GetEnvironmentInfo() - { - var info = new MonoEnvironmentInfo(); - - var uname = GetUnixName(); - - var sysName = uname.sysname ?? string.Empty; - - if (string.Equals(sysName, "Darwin", StringComparison.OrdinalIgnoreCase)) - { - info.OperatingSystem = Model.System.OperatingSystem.OSX; - } - else if (string.Equals(sysName, "Linux", StringComparison.OrdinalIgnoreCase)) - { - info.OperatingSystem = Model.System.OperatingSystem.Linux; - } - else if (string.Equals(sysName, "BSD", StringComparison.OrdinalIgnoreCase)) - { - info.OperatingSystem = Model.System.OperatingSystem.BSD; - } - - var archX86 = new Regex("(i|I)[3-6]86"); - - if (archX86.IsMatch(uname.machine)) - { - info.SystemArchitecture = Architecture.X86; - } - else if (string.Equals(uname.machine, "x86_64", StringComparison.OrdinalIgnoreCase)) - { - info.SystemArchitecture = Architecture.X64; - } - else if (uname.machine.StartsWith("arm", StringComparison.OrdinalIgnoreCase)) - { - info.SystemArchitecture = Architecture.Arm; - } - else if (System.Environment.Is64BitOperatingSystem) - { - info.SystemArchitecture = Architecture.X64; - } - else - { - info.SystemArchitecture = Architecture.X86; - } - - return info; - } - - private static Uname _unixName; - - private static Uname GetUnixName() - { - if (_unixName == null) - { - var uname = new Uname(); - try - { - Utsname utsname; - var callResult = Syscall.uname(out utsname); - if (callResult == 0) - { - uname.sysname = utsname.sysname ?? string.Empty; - uname.machine = utsname.machine ?? string.Empty; - } - - } - catch (Exception ex) - { - _logger.LogError(ex, "Error getting unix name"); - } - _unixName = uname; - } - return _unixName; - } - - public class Uname - { - public string sysname = string.Empty; - public string machine = string.Empty; - } - - /// - /// Handles the UnhandledException event of the CurrentDomain control. - /// - /// The source of the event. - /// The instance containing the event data. - static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - var exception = (Exception)e.ExceptionObject; - - //new UnhandledExceptionWriter(_appPaths, _logger, _logManager, FileSystem, new ConsoleLogger()).Log(exception); - - _logger.LogCritical(exception, "Unhandled Exception"); - - // TODO: @bond - /* - if (!Debugger.IsAttached) - { - var message = LogHelper.GetLogMessage(exception).ToString(); - - if (message.IndexOf("InotifyWatcher", StringComparison.OrdinalIgnoreCase) == -1 && - message.IndexOf("_IOCompletionCallback", StringComparison.OrdinalIgnoreCase) == -1) - { - Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(exception)); - } - } - */ - } - - public static void Shutdown() - { - ApplicationTaskCompletionSource.SetResult(true); - } - - public static void Restart() - { - _restartOnShutdown = true; - - Shutdown(); - } - - private static void StartNewInstance(StartupOptions startupOptions) - { - _logger.LogInformation("Starting new instance"); - - string module = startupOptions.GetOption("-restartpath"); - string commandLineArgsString = startupOptions.GetOption("-restartargs") ?? string.Empty; - - if (string.IsNullOrWhiteSpace(module)) - { - module = Environment.GetCommandLineArgs().First(); - } - if (!startupOptions.ContainsOption("-restartargs")) - { - var args = Environment.GetCommandLineArgs() - .Skip(1) - .Select(NormalizeCommandLineArgument) - .ToArray(); - - commandLineArgsString = string.Join(" ", args); - } - - _logger.LogInformation("Executable: {0}", module); - _logger.LogInformation("Arguments: {0}", commandLineArgsString); - - Process.Start(module, commandLineArgsString); - } - - private static string NormalizeCommandLineArgument(string arg) - { - if (arg.IndexOf(" ", StringComparison.OrdinalIgnoreCase) == -1) - { - return arg; - } - - return "\"" + arg + "\""; - } - } - - // class NoCheckCertificatePolicy : ICertificatePolicy - // { - // public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) - // { - // return true; - // } - // } - - public class MonoEnvironmentInfo : EnvironmentInfo - { - - //public override string GetUserId() - //{ - // return Syscall.getuid().ToString(CultureInfo.InvariantCulture); - //} - } -} diff --git a/MediaBrowser.Server.Mono/Properties/AssemblyInfo.cs b/MediaBrowser.Server.Mono/Properties/AssemblyInfo.cs deleted file mode 100644 index eda3bcf97..000000000 --- a/MediaBrowser.Server.Mono/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Reflection; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. -[assembly: AssemblyTitle ("MediaBrowser.Server.Mono")] -[assembly: AssemblyDescription ("")] -[assembly: AssemblyConfiguration ("")] -[assembly: AssemblyCompany ("")] -[assembly: AssemblyProduct ("")] -[assembly: AssemblyCopyright ("Emby")] -[assembly: AssemblyTrademark ("")] -[assembly: AssemblyCulture ("")] -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. \ No newline at end of file diff --git a/MediaBrowser.Server.Mono/Properties/launchSettings.json b/MediaBrowser.Server.Mono/Properties/launchSettings.json deleted file mode 100644 index 058ad7adc..000000000 --- a/MediaBrowser.Server.Mono/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "EmbyServer": { - "commandName": "Project" - } - } -} diff --git a/MediaBrowser.Server.Mono/Resources/Configuration/logging.json b/MediaBrowser.Server.Mono/Resources/Configuration/logging.json deleted file mode 100644 index 78f99b2ad..000000000 --- a/MediaBrowser.Server.Mono/Resources/Configuration/logging.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "Serilog": { - "MinimumLevel": "Information", - "WriteTo": [ - { "Name": "Console", - "Args": { - "outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}" - } - }, - { "Name": "File", - "Args": { - "path": "%JELLYFIN_LOG_DIR%//log_.log", - "rollingInterval": "Day", - "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}" - } - } - ] - } -} diff --git a/MediaBrowser.Server.Mono/SocketSharp/HttpFile.cs b/MediaBrowser.Server.Mono/SocketSharp/HttpFile.cs deleted file mode 100644 index 1e7c93deb..000000000 --- a/MediaBrowser.Server.Mono/SocketSharp/HttpFile.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediaBrowser.Model.Services; -using System.IO; - -namespace EmbyServer.SocketSharp -{ - public class HttpFile : IHttpFile - { - public string Name { get; set; } - public string FileName { get; set; } - public long ContentLength { get; set; } - public string ContentType { get; set; } - public Stream InputStream { get; set; } - } -} diff --git a/MediaBrowser.Server.Mono/SocketSharp/RequestMono.cs b/MediaBrowser.Server.Mono/SocketSharp/RequestMono.cs deleted file mode 100644 index 9d2354316..000000000 --- a/MediaBrowser.Server.Mono/SocketSharp/RequestMono.cs +++ /dev/null @@ -1,807 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Globalization; -using System.IO; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Model.Services; - -namespace EmbyServer.SocketSharp -{ - public partial class WebSocketSharpRequest : IHttpRequest - { - static internal string GetParameter(string header, string attr) - { - int ap = header.IndexOf(attr); - if (ap == -1) - return null; - - ap += attr.Length; - if (ap >= header.Length) - return null; - - char ending = header[ap]; - if (ending != '"') - ending = ' '; - - int end = header.IndexOf(ending, ap + 1); - if (end == -1) - return ending == '"' ? null : header.Substring(ap); - - return header.Substring(ap + 1, end - ap - 1); - } - - async Task LoadMultiPart(WebROCollection form) - { - string boundary = GetParameter(ContentType, "; boundary="); - if (boundary == null) - return; - - using (var requestStream = InputStream) - { - //DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request - //Not ending with \r\n? - var ms = new MemoryStream(32 * 1024); - await requestStream.CopyToAsync(ms).ConfigureAwait(false); - - var input = ms; - ms.WriteByte((byte)'\r'); - ms.WriteByte((byte)'\n'); - - input.Position = 0; - - //Uncomment to debug - //var content = new StreamReader(ms).ReadToEnd(); - //Console.WriteLine(boundary + "::" + content); - //input.Position = 0; - - var multi_part = new HttpMultipart(input, boundary, ContentEncoding); - - HttpMultipart.Element e; - while ((e = multi_part.ReadNextElement()) != null) - { - if (e.Filename == null) - { - byte[] copy = new byte[e.Length]; - - input.Position = e.Start; - input.Read(copy, 0, (int)e.Length); - - form.Add(e.Name, (e.Encoding ?? ContentEncoding).GetString(copy, 0, copy.Length)); - } - else - { - // - // We use a substream, as in 2.x we will support large uploads streamed to disk, - // - HttpPostedFile sub = new HttpPostedFile(e.Filename, e.ContentType, input, e.Start, e.Length); - files[e.Name] = sub; - } - } - } - } - - public async Task GetFormData() - { - var form = new WebROCollection(); - files = new Dictionary(); - - if (IsContentType("multipart/form-data", true)) - { - await LoadMultiPart(form).ConfigureAwait(false); - } - else if (IsContentType("application/x-www-form-urlencoded", true)) - { - await LoadWwwForm(form).ConfigureAwait(false); - } - -#if NET_4_0 - if (validateRequestNewMode && !checked_form) { - // Setting this before calling the validator prevents - // possible endless recursion - checked_form = true; - ValidateNameValueCollection ("Form", query_string_nvc, RequestValidationSource.Form); - } else -#endif - if (validate_form && !checked_form) - { - checked_form = true; - ValidateNameValueCollection("Form", form); - } - - return form; - } - - public string Accept - { - get - { - return string.IsNullOrEmpty(request.Headers["Accept"]) ? null : request.Headers["Accept"]; - } - } - - public string Authorization - { - get - { - return string.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"]; - } - } - - protected bool validate_cookies, validate_query_string, validate_form; - protected bool checked_cookies, checked_query_string, checked_form; - - static void ThrowValidationException(string name, string key, string value) - { - string v = "\"" + value + "\""; - if (v.Length > 20) - v = v.Substring(0, 16) + "...\""; - - string msg = String.Format("A potentially dangerous Request.{0} value was " + - "detected from the client ({1}={2}).", name, key, v); - - throw new Exception(msg); - } - - static void ValidateNameValueCollection(string name, QueryParamCollection coll) - { - if (coll == null) - return; - - foreach (var pair in coll) - { - var key = pair.Name; - var val = pair.Value; - if (val != null && val.Length > 0 && IsInvalidString(val)) - ThrowValidationException(name, key, val); - } - } - - internal static bool IsInvalidString(string val) - { - int validationFailureIndex; - - return IsInvalidString(val, out validationFailureIndex); - } - - internal static bool IsInvalidString(string val, out int validationFailureIndex) - { - validationFailureIndex = 0; - - int len = val.Length; - if (len < 2) - return false; - - char current = val[0]; - for (int idx = 1; idx < len; idx++) - { - char next = val[idx]; - // See http://secunia.com/advisories/14325 - if (current == '<' || current == '\xff1c') - { - if (next == '!' || next < ' ' - || (next >= 'a' && next <= 'z') - || (next >= 'A' && next <= 'Z')) - { - validationFailureIndex = idx - 1; - return true; - } - } - else if (current == '&' && next == '#') - { - validationFailureIndex = idx - 1; - return true; - } - - current = next; - } - - return false; - } - - public void ValidateInput() - { - validate_cookies = true; - validate_query_string = true; - validate_form = true; - } - - bool IsContentType(string ct, bool starts_with) - { - if (ct == null || ContentType == null) return false; - - if (starts_with) - return StrUtils.StartsWith(ContentType, ct, true); - - return string.Equals(ContentType, ct, StringComparison.OrdinalIgnoreCase); - } - - async Task LoadWwwForm(WebROCollection form) - { - using (Stream input = InputStream) - { - using (var ms = new MemoryStream()) - { - await input.CopyToAsync(ms).ConfigureAwait(false); - ms.Position = 0; - - using (StreamReader s = new StreamReader(ms, ContentEncoding)) - { - StringBuilder key = new StringBuilder(); - StringBuilder value = new StringBuilder(); - int c; - - while ((c = s.Read()) != -1) - { - if (c == '=') - { - value.Length = 0; - while ((c = s.Read()) != -1) - { - if (c == '&') - { - AddRawKeyValue(form, key, value); - break; - } - else - value.Append((char)c); - } - if (c == -1) - { - AddRawKeyValue(form, key, value); - return; - } - } - else if (c == '&') - AddRawKeyValue(form, key, value); - else - key.Append((char)c); - } - if (c == -1) - AddRawKeyValue(form, key, value); - } - } - } - } - - void AddRawKeyValue(WebROCollection form, StringBuilder key, StringBuilder value) - { - string decodedKey = WebUtility.UrlDecode(key.ToString()); - form.Add(decodedKey, - WebUtility.UrlDecode(value.ToString())); - - key.Length = 0; - value.Length = 0; - } - - Dictionary files; - - class WebROCollection : QueryParamCollection - { - public override string ToString() - { - StringBuilder result = new StringBuilder(); - foreach (var pair in this) - { - if (result.Length > 0) - result.Append('&'); - - var key = pair.Name; - if (key != null && key.Length > 0) - { - result.Append(key); - result.Append('='); - } - result.Append(pair.Value); - } - - return result.ToString(); - } - } - - public sealed class HttpPostedFile - { - string name; - string content_type; - Stream stream; - - class ReadSubStream : Stream - { - Stream s; - long offset; - long end; - long position; - - public ReadSubStream(Stream s, long offset, long length) - { - this.s = s; - this.offset = offset; - this.end = offset + length; - position = offset; - } - - public override void Flush() - { - } - - public override int Read(byte[] buffer, int dest_offset, int count) - { - if (buffer == null) - throw new ArgumentNullException("buffer"); - - if (dest_offset < 0) - throw new ArgumentOutOfRangeException("dest_offset", "< 0"); - - if (count < 0) - throw new ArgumentOutOfRangeException("count", "< 0"); - - int len = buffer.Length; - if (dest_offset > len) - throw new ArgumentException("destination offset is beyond array size"); - // reordered to avoid possible integer overflow - if (dest_offset > len - count) - throw new ArgumentException("Reading would overrun buffer"); - - if (count > end - position) - count = (int)(end - position); - - if (count <= 0) - return 0; - - s.Position = position; - int result = s.Read(buffer, dest_offset, count); - if (result > 0) - position += result; - else - position = end; - - return result; - } - - public override int ReadByte() - { - if (position >= end) - return -1; - - s.Position = position; - int result = s.ReadByte(); - if (result < 0) - position = end; - else - position++; - - return result; - } - - public override long Seek(long d, SeekOrigin origin) - { - long real; - switch (origin) - { - case SeekOrigin.Begin: - real = offset + d; - break; - case SeekOrigin.End: - real = end + d; - break; - case SeekOrigin.Current: - real = position + d; - break; - default: - throw new ArgumentException(); - } - - long virt = real - offset; - if (virt < 0 || virt > Length) - throw new ArgumentException(); - - position = s.Seek(real, SeekOrigin.Begin); - return position; - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - public override bool CanRead - { - get { return true; } - } - public override bool CanSeek - { - get { return true; } - } - public override bool CanWrite - { - get { return false; } - } - - public override long Length - { - get { return end - offset; } - } - - public override long Position - { - get - { - return position - offset; - } - set - { - if (value > Length) - throw new ArgumentOutOfRangeException(); - - position = Seek(value, SeekOrigin.Begin); - } - } - } - - internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length) - { - this.name = name; - this.content_type = content_type; - this.stream = new ReadSubStream(base_stream, offset, length); - } - - public string ContentType - { - get - { - return content_type; - } - } - - public int ContentLength - { - get - { - return (int)stream.Length; - } - } - - public string FileName - { - get - { - return name; - } - } - - public Stream InputStream - { - get - { - return stream; - } - } - } - - class Helpers - { - public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture; - } - - internal sealed class StrUtils - { - public static bool StartsWith(string str1, string str2, bool ignore_case) - { - if (string.IsNullOrEmpty(str1)) - { - return false; - } - - var comparison = ignore_case ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - return str1.IndexOf(str2, comparison) == 0; - } - - public static bool EndsWith(string str1, string str2, bool ignore_case) - { - int l2 = str2.Length; - if (l2 == 0) - return true; - - int l1 = str1.Length; - if (l2 > l1) - return false; - - var comparison = ignore_case ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - return str1.IndexOf(str2, comparison) == str1.Length - str2.Length - 1; - } - } - - class HttpMultipart - { - - public class Element - { - public string ContentType; - public string Name; - public string Filename; - public Encoding Encoding; - public long Start; - public long Length; - - public override string ToString() - { - return "ContentType " + ContentType + ", Name " + Name + ", Filename " + Filename + ", Start " + - Start.ToString() + ", Length " + Length.ToString(); - } - } - - Stream data; - string boundary; - byte[] boundary_bytes; - byte[] buffer; - bool at_eof; - Encoding encoding; - StringBuilder sb; - - const byte HYPHEN = (byte)'-', LF = (byte)'\n', CR = (byte)'\r'; - - // See RFC 2046 - // In the case of multipart entities, in which one or more different - // sets of data are combined in a single body, a "multipart" media type - // field must appear in the entity's header. The body must then contain - // one or more body parts, each preceded by a boundary delimiter line, - // and the last one followed by a closing boundary delimiter line. - // After its boundary delimiter line, each body part then consists of a - // header area, a blank line, and a body area. Thus a body part is - // similar to an RFC 822 message in syntax, but different in meaning. - - public HttpMultipart(Stream data, string b, Encoding encoding) - { - this.data = data; - //DB: 30/01/11: cannot set or read the Position in HttpListener in Win.NET - //var ms = new MemoryStream(32 * 1024); - //data.CopyTo(ms); - //this.data = ms; - - boundary = b; - boundary_bytes = encoding.GetBytes(b); - buffer = new byte[boundary_bytes.Length + 2]; // CRLF or '--' - this.encoding = encoding; - sb = new StringBuilder(); - } - - string ReadLine() - { - // CRLF or LF are ok as line endings. - bool got_cr = false; - int b = 0; - sb.Length = 0; - while (true) - { - b = data.ReadByte(); - if (b == -1) - { - return null; - } - - if (b == LF) - { - break; - } - got_cr = b == CR; - sb.Append((char)b); - } - - if (got_cr) - sb.Length--; - - return sb.ToString(); - - } - - static string GetContentDispositionAttribute(string l, string name) - { - int idx = l.IndexOf(name + "=\""); - if (idx < 0) - return null; - int begin = idx + name.Length + "=\"".Length; - int end = l.IndexOf('"', begin); - if (end < 0) - return null; - if (begin == end) - return ""; - return l.Substring(begin, end - begin); - } - - string GetContentDispositionAttributeWithEncoding(string l, string name) - { - int idx = l.IndexOf(name + "=\""); - if (idx < 0) - return null; - int begin = idx + name.Length + "=\"".Length; - int end = l.IndexOf('"', begin); - if (end < 0) - return null; - if (begin == end) - return ""; - - string temp = l.Substring(begin, end - begin); - byte[] source = new byte[temp.Length]; - for (int i = temp.Length - 1; i >= 0; i--) - source[i] = (byte)temp[i]; - - return encoding.GetString(source, 0, source.Length); - } - - bool ReadBoundary() - { - try - { - string line = ReadLine(); - while (line == "") - line = ReadLine(); - if (line[0] != '-' || line[1] != '-') - return false; - - if (!StrUtils.EndsWith(line, boundary, false)) - return true; - } - catch - { - } - - return false; - } - - string ReadHeaders() - { - string s = ReadLine(); - if (s == "") - return null; - - return s; - } - - bool CompareBytes(byte[] orig, byte[] other) - { - for (int i = orig.Length - 1; i >= 0; i--) - if (orig[i] != other[i]) - return false; - - return true; - } - - long MoveToNextBoundary() - { - long retval = 0; - bool got_cr = false; - - int state = 0; - int c = data.ReadByte(); - while (true) - { - if (c == -1) - return -1; - - if (state == 0 && c == LF) - { - retval = data.Position - 1; - if (got_cr) - retval--; - state = 1; - c = data.ReadByte(); - } - else if (state == 0) - { - got_cr = c == CR; - c = data.ReadByte(); - } - else if (state == 1 && c == '-') - { - c = data.ReadByte(); - if (c == -1) - return -1; - - if (c != '-') - { - state = 0; - got_cr = false; - continue; // no ReadByte() here - } - - int nread = data.Read(buffer, 0, buffer.Length); - int bl = buffer.Length; - if (nread != bl) - return -1; - - if (!CompareBytes(boundary_bytes, buffer)) - { - state = 0; - data.Position = retval + 2; - if (got_cr) - { - data.Position++; - got_cr = false; - } - c = data.ReadByte(); - continue; - } - - if (buffer[bl - 2] == '-' && buffer[bl - 1] == '-') - { - at_eof = true; - } - else if (buffer[bl - 2] != CR || buffer[bl - 1] != LF) - { - state = 0; - data.Position = retval + 2; - if (got_cr) - { - data.Position++; - got_cr = false; - } - c = data.ReadByte(); - continue; - } - data.Position = retval + 2; - if (got_cr) - data.Position++; - break; - } - else - { - // state == 1 - state = 0; // no ReadByte() here - } - } - - return retval; - } - - public Element ReadNextElement() - { - if (at_eof || ReadBoundary()) - return null; - - Element elem = new Element(); - string header; - while ((header = ReadHeaders()) != null) - { - if (StrUtils.StartsWith(header, "Content-Disposition:", true)) - { - elem.Name = GetContentDispositionAttribute(header, "name"); - elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename")); - } - else if (StrUtils.StartsWith(header, "Content-Type:", true)) - { - elem.ContentType = header.Substring("Content-Type:".Length).Trim(); - elem.Encoding = GetEncoding(elem.ContentType); - } - } - - long start = 0; - start = data.Position; - elem.Start = start; - long pos = MoveToNextBoundary(); - if (pos == -1) - return null; - - elem.Length = pos - start; - return elem; - } - - static string StripPath(string path) - { - if (path == null || path.Length == 0) - return path; - - if (path.IndexOf(":\\") != 1 && !path.StartsWith("\\\\")) - return path; - return path.Substring(path.LastIndexOf('\\') + 1); - } - } - - } -} diff --git a/MediaBrowser.Server.Mono/SocketSharp/SharpWebSocket.cs b/MediaBrowser.Server.Mono/SocketSharp/SharpWebSocket.cs deleted file mode 100644 index fd32640a2..000000000 --- a/MediaBrowser.Server.Mono/SocketSharp/SharpWebSocket.cs +++ /dev/null @@ -1,159 +0,0 @@ -using MediaBrowser.Common.Events; -using Microsoft.Extensions.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; -using System.Net.WebSockets; -using Emby.Server.Implementations.Net; - -namespace EmbyServer.SocketSharp -{ - public class SharpWebSocket : IWebSocket - { - /// - /// The logger - /// - private readonly ILogger _logger; - - public event EventHandler Closed; - - /// - /// Gets or sets the web socket. - /// - /// The web socket. - private SocketHttpListener.WebSocket WebSocket { get; set; } - - private TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); - private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - - public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger) - { - if (socket == null) - { - throw new ArgumentNullException("socket"); - } - - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - _logger = logger; - WebSocket = socket; - - socket.OnMessage += socket_OnMessage; - socket.OnClose += socket_OnClose; - socket.OnError += socket_OnError; - - WebSocket.ConnectAsServer(); - } - - public Task StartReceive() - { - return _taskCompletionSource.Task; - } - - void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e) - { - _logger.LogError("Error in SharpWebSocket: {0}", e.Message ?? string.Empty); - //EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); - } - - void socket_OnClose(object sender, SocketHttpListener.CloseEventArgs e) - { - _taskCompletionSource.TrySetResult(true); - - EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); - } - - void socket_OnMessage(object sender, SocketHttpListener.MessageEventArgs e) - { - //if (!string.IsNullOrEmpty(e.Data)) - //{ - // if (OnReceive != null) - // { - // OnReceive(e.Data); - // } - // return; - //} - if (OnReceiveBytes != null) - { - OnReceiveBytes(e.RawData); - } - } - - /// - /// Gets or sets the state. - /// - /// The state. - public WebSocketState State - { - get - { - return WebSocket.ReadyState; - } - } - - /// - /// Sends the async. - /// - /// The bytes. - /// if set to true [end of message]. - /// The cancellation token. - /// Task. - public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken) - { - return WebSocket.SendAsync(bytes); - } - - /// - /// Sends the asynchronous. - /// - /// The text. - /// if set to true [end of message]. - /// The cancellation token. - /// Task. - public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken) - { - return WebSocket.SendAsync(text); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// 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) - { - if (dispose) - { - WebSocket.OnMessage -= socket_OnMessage; - WebSocket.OnClose -= socket_OnClose; - WebSocket.OnError -= socket_OnError; - - _cancellationTokenSource.Cancel(); - - WebSocket.Close(); - } - } - - /// - /// Gets or sets the receive action. - /// - /// The receive action. - public Action OnReceiveBytes { get; set; } - - /// - /// Gets or sets the on receive. - /// - /// The on receive. - public Action OnReceive { get; set; } - } -} diff --git a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpListener.cs deleted file mode 100644 index 993863e8c..000000000 --- a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpListener.cs +++ /dev/null @@ -1,262 +0,0 @@ -using MediaBrowser.Controller.Net; -using Microsoft.Extensions.Logging; -using SocketHttpListener.Net; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Cryptography; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Services; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Text; -using Emby.Server.Implementations.Net; -using Emby.Server.Implementations.HttpServer; - -namespace EmbyServer.SocketSharp -{ - public class WebSocketSharpListener : IHttpListener - { - private HttpListener _listener; - - private readonly ILogger _logger; - private readonly X509Certificate _certificate; - private readonly IStreamHelper _streamHelper; - private readonly ITextEncoding _textEncoding; - private readonly INetworkManager _networkManager; - private readonly ISocketFactory _socketFactory; - private readonly ICryptoProvider _cryptoProvider; - private readonly IFileSystem _fileSystem; - private readonly bool _enableDualMode; - private readonly IEnvironmentInfo _environment; - - private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); - private CancellationToken _disposeCancellationToken; - - public WebSocketSharpListener(ILogger logger, X509Certificate certificate, IStreamHelper streamHelper, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, bool enableDualMode, IFileSystem fileSystem, IEnvironmentInfo environment) - { - _logger = logger; - _certificate = certificate; - _streamHelper = streamHelper; - _textEncoding = textEncoding; - _networkManager = networkManager; - _socketFactory = socketFactory; - _cryptoProvider = cryptoProvider; - _enableDualMode = enableDualMode; - _fileSystem = fileSystem; - _environment = environment; - - _disposeCancellationToken = _disposeCancellationTokenSource.Token; - } - - public Func ErrorHandler { get; set; } - public Func RequestHandler { get; set; } - - public Action WebSocketConnecting { get; set; } - - public Action WebSocketConnected { get; set; } - - public void Start(IEnumerable urlPrefixes) - { - if (_listener == null) - _listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _networkManager, _textEncoding, _streamHelper, _fileSystem, _environment); - - _listener.EnableDualMode = _enableDualMode; - - if (_certificate != null) - { - _listener.LoadCert(_certificate); - } - - foreach (var prefix in urlPrefixes) - { - _logger.LogInformation("Adding HttpListener prefix " + prefix); - _listener.Prefixes.Add(prefix); - } - - _listener.OnContext = ProcessContext; - - _listener.Start(); - } - - private void ProcessContext(HttpListenerContext context) - { - //InitTask(context, _disposeCancellationToken); - Task.Run(() => InitTask(context, _disposeCancellationToken)); - } - - private void LogRequest(ILogger logger, HttpListenerRequest request) - { - var url = request.Url.ToString(); - - logger.LogInformation("{0} {1}. UserAgent: {2}", request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, url, request.UserAgent ?? string.Empty); - } - - private Task InitTask(HttpListenerContext context, CancellationToken cancellationToken) - { - IHttpRequest httpReq = null; - var request = context.Request; - - try - { - if (request.IsWebSocketRequest) - { - LogRequest(_logger, request); - - return ProcessWebSocketRequest(context); - } - - httpReq = GetRequest(context); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error processing request"); - - httpReq = httpReq ?? GetRequest(context); - return ErrorHandler(ex, httpReq, true, true); - } - - var uri = request.Url; - - return RequestHandler(httpReq, uri.OriginalString, uri.Host, uri.LocalPath, cancellationToken); - } - - private async Task ProcessWebSocketRequest(HttpListenerContext ctx) - { - try - { - var endpoint = ctx.Request.RemoteEndPoint.ToString(); - var url = ctx.Request.RawUrl; - - var queryString = ctx.Request.QueryString; - - var connectingArgs = new WebSocketConnectingEventArgs - { - Url = url, - QueryString = queryString, - Endpoint = endpoint - }; - - if (WebSocketConnecting != null) - { - WebSocketConnecting(connectingArgs); - } - - if (connectingArgs.AllowConnection) - { - _logger.LogDebug("Web socket connection allowed"); - - var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false); - - if (WebSocketConnected != null) - { - var socket = new SharpWebSocket(webSocketContext.WebSocket, _logger); - - WebSocketConnected(new WebSocketConnectEventArgs - { - Url = url, - QueryString = queryString, - WebSocket = socket, - Endpoint = endpoint - }); - - await ReceiveWebSocket(ctx, socket).ConfigureAwait(false); - } - } - else - { - _logger.LogWarning("Web socket connection not allowed"); - ctx.Response.StatusCode = 401; - ctx.Response.Close(); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "AcceptWebSocketAsync error"); - ctx.Response.StatusCode = 500; - ctx.Response.Close(); - } - } - - private async Task ReceiveWebSocket(HttpListenerContext ctx, SharpWebSocket socket) - { - try - { - await socket.StartReceive().ConfigureAwait(false); - } - finally - { - TryClose(ctx, 200); - } - } - - private void TryClose(HttpListenerContext ctx, int statusCode) - { - try - { - ctx.Response.StatusCode = 200; - ctx.Response.Close(); - } - catch (ObjectDisposedException) - { - } - catch (Exception ex) - { - _logger.LogError(ex, "Error closing web socket response"); - } - } - - private IHttpRequest GetRequest(HttpListenerContext httpContext) - { - var urlSegments = httpContext.Request.Url.Segments; - - var operationName = urlSegments[urlSegments.Length - 1]; - - var req = new WebSocketSharpRequest(httpContext, operationName, _logger); - - return req; - } - - public Task Stop() - { - _disposeCancellationTokenSource.Cancel(); - - if (_listener != null) - { - _listener.Close(); - } - - return Task.CompletedTask; - } - - public void Dispose() - { - Dispose(true); - } - - private bool _disposed; - private readonly object _disposeLock = new object(); - protected virtual void Dispose(bool disposing) - { - if (_disposed) return; - - lock (_disposeLock) - { - if (_disposed) return; - - if (disposing) - { - Stop(); - } - - //release unmanaged resources here... - _disposed = true; - } - } - } - -} diff --git a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpRequest.cs b/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpRequest.cs deleted file mode 100644 index 1e1c3db7c..000000000 --- a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpRequest.cs +++ /dev/null @@ -1,556 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using Emby.Server.Implementations.HttpServer; -using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; -using MediaBrowser.Model.Services; -using SocketHttpListener.Net; -using IHttpFile = MediaBrowser.Model.Services.IHttpFile; -using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest; -using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse; -using IResponse = MediaBrowser.Model.Services.IResponse; -using System.Threading.Tasks; - -namespace EmbyServer.SocketSharp -{ - public partial class WebSocketSharpRequest : IHttpRequest - { - private readonly HttpListenerRequest request; - private readonly IHttpResponse response; - - public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, ILogger logger) - { - this.OperationName = operationName; - this.request = httpContext.Request; - this.response = new WebSocketSharpResponse(logger, httpContext.Response, this); - - //HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]); - } - - private static string GetHandlerPathIfAny(string listenerUrl) - { - if (listenerUrl == null) return null; - var pos = listenerUrl.IndexOf("://", StringComparison.OrdinalIgnoreCase); - if (pos == -1) return null; - var startHostUrl = listenerUrl.Substring(pos + "://".Length); - var endPos = startHostUrl.IndexOf('/'); - if (endPos == -1) return null; - var endHostUrl = startHostUrl.Substring(endPos + 1); - return string.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/'); - } - - public HttpListenerRequest HttpRequest - { - get { return request; } - } - - public object OriginalRequest - { - get { return request; } - } - - public IResponse Response - { - get { return response; } - } - - public IHttpResponse HttpResponse - { - get { return response; } - } - - public string OperationName { get; set; } - - public object Dto { get; set; } - - public string RawUrl - { - get { return request.RawUrl; } - } - - public string AbsoluteUri - { - get { return request.Url.AbsoluteUri.TrimEnd('/'); } - } - - public string UserHostAddress - { - get { return request.UserHostAddress; } - } - - public string XForwardedFor - { - get - { - return String.IsNullOrEmpty(request.Headers["X-Forwarded-For"]) ? null : request.Headers["X-Forwarded-For"]; - } - } - - public int? XForwardedPort - { - get - { - return string.IsNullOrEmpty(request.Headers["X-Forwarded-Port"]) ? (int?)null : int.Parse(request.Headers["X-Forwarded-Port"]); - } - } - - public string XForwardedProtocol - { - get - { - return string.IsNullOrEmpty(request.Headers["X-Forwarded-Proto"]) ? null : request.Headers["X-Forwarded-Proto"]; - } - } - - public string XRealIp - { - get - { - return String.IsNullOrEmpty(request.Headers["X-Real-IP"]) ? null : request.Headers["X-Real-IP"]; - } - } - - private string remoteIp; - public string RemoteIp - { - get - { - return remoteIp ?? - (remoteIp = (CheckBadChars(XForwardedFor)) ?? - (NormalizeIp(CheckBadChars(XRealIp)) ?? - (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null))); - } - } - - private static readonly char[] HttpTrimCharacters = new char[] { (char)0x09, (char)0xA, (char)0xB, (char)0xC, (char)0xD, (char)0x20 }; - - // - // CheckBadChars - throws on invalid chars to be not found in header name/value - // - internal static string CheckBadChars(string name) - { - if (name == null || name.Length == 0) - { - return name; - } - - // VALUE check - //Trim spaces from both ends - name = name.Trim(HttpTrimCharacters); - - //First, check for correctly formed multi-line value - //Second, check for absenece of CTL characters - int crlf = 0; - for (int i = 0; i < name.Length; ++i) - { - char c = (char)(0x000000ff & (uint)name[i]); - switch (crlf) - { - case 0: - if (c == '\r') - { - crlf = 1; - } - else if (c == '\n') - { - // Technically this is bad HTTP. But it would be a breaking change to throw here. - // Is there an exploit? - crlf = 2; - } - else if (c == 127 || (c < ' ' && c != '\t')) - { - throw new ArgumentException("net_WebHeaderInvalidControlChars"); - } - break; - - case 1: - if (c == '\n') - { - crlf = 2; - break; - } - throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); - - case 2: - if (c == ' ' || c == '\t') - { - crlf = 0; - break; - } - throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); - } - } - if (crlf != 0) - { - throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); - } - return name; - } - - internal static bool ContainsNonAsciiChars(string token) - { - for (int i = 0; i < token.Length; ++i) - { - if ((token[i] < 0x20) || (token[i] > 0x7e)) - { - return true; - } - } - return false; - } - - private string NormalizeIp(string ip) - { - if (!string.IsNullOrWhiteSpace(ip)) - { - // Handle ipv4 mapped to ipv6 - const string srch = "::ffff:"; - var index = ip.IndexOf(srch, StringComparison.OrdinalIgnoreCase); - if (index == 0) - { - ip = ip.Substring(srch.Length); - } - } - - return ip; - } - - public bool IsSecureConnection - { - get { return request.IsSecureConnection || XForwardedProtocol == "https"; } - } - - public string[] AcceptTypes - { - get { return request.AcceptTypes; } - } - - private Dictionary items; - public Dictionary Items - { - get { return items ?? (items = new Dictionary()); } - } - - private string responseContentType; - public string ResponseContentType - { - get - { - return responseContentType - ?? (responseContentType = GetResponseContentType(this)); - } - set - { - this.responseContentType = value; - } - } - - public const string FormUrlEncoded = "application/x-www-form-urlencoded"; - public const string MultiPartFormData = "multipart/form-data"; - public static string GetResponseContentType(IRequest httpReq) - { - var specifiedContentType = GetQueryStringContentType(httpReq); - if (!string.IsNullOrEmpty(specifiedContentType)) return specifiedContentType; - - var serverDefaultContentType = "application/json"; - - var acceptContentTypes = httpReq.AcceptTypes; - string defaultContentType = null; - if (HasAnyOfContentTypes(httpReq, FormUrlEncoded, MultiPartFormData)) - { - defaultContentType = serverDefaultContentType; - } - - var acceptsAnything = false; - var hasDefaultContentType = !string.IsNullOrEmpty(defaultContentType); - if (acceptContentTypes != null) - { - foreach (var acceptsType in acceptContentTypes) - { - var contentType = HttpResultFactory.GetRealContentType(acceptsType); - acceptsAnything = acceptsAnything || contentType == "*/*"; - } - - if (acceptsAnything) - { - if (hasDefaultContentType) - return defaultContentType; - if (serverDefaultContentType != null) - return serverDefaultContentType; - } - } - - if (acceptContentTypes == null && httpReq.ContentType == Soap11) - { - return Soap11; - } - - //We could also send a '406 Not Acceptable', but this is allowed also - return serverDefaultContentType; - } - - public const string Soap11 = "text/xml; charset=utf-8"; - - public static bool HasAnyOfContentTypes(IRequest request, params string[] contentTypes) - { - if (contentTypes == null || request.ContentType == null) return false; - foreach (var contentType in contentTypes) - { - if (IsContentType(request, contentType)) return true; - } - return false; - } - - public static bool IsContentType(IRequest request, string contentType) - { - return request.ContentType.StartsWith(contentType, StringComparison.OrdinalIgnoreCase); - } - - public const string Xml = "application/xml"; - private static string GetQueryStringContentType(IRequest httpReq) - { - var format = httpReq.QueryString["format"]; - if (format == null) - { - const int formatMaxLength = 4; - var pi = httpReq.PathInfo; - if (pi == null || pi.Length <= formatMaxLength) return null; - if (pi[0] == '/') pi = pi.Substring(1); - format = LeftPart(pi, '/'); - if (format.Length > formatMaxLength) return null; - } - - format = LeftPart(format, '.').ToLower(); - if (format.Contains("json")) return "application/json"; - if (format.Contains("xml")) return Xml; - - return null; - } - - public static string LeftPart(string strVal, char needle) - { - if (strVal == null) return null; - var pos = strVal.IndexOf(needle); - return pos == -1 - ? strVal - : strVal.Substring(0, pos); - } - - public static string HandlerFactoryPath; - - private string pathInfo; - public string PathInfo - { - get - { - if (this.pathInfo == null) - { - var mode = HandlerFactoryPath; - - var pos = request.RawUrl.IndexOf("?"); - if (pos != -1) - { - var path = request.RawUrl.Substring(0, pos); - this.pathInfo = GetPathInfo( - path, - mode, - mode ?? ""); - } - else - { - this.pathInfo = request.RawUrl; - } - - this.pathInfo = System.Net.WebUtility.UrlDecode(pathInfo); - this.pathInfo = NormalizePathInfo(pathInfo, mode); - } - return this.pathInfo; - } - } - - private static string GetPathInfo(string fullPath, string mode, string appPath) - { - var pathInfo = ResolvePathInfoFromMappedPath(fullPath, mode); - if (!string.IsNullOrEmpty(pathInfo)) return pathInfo; - - //Wildcard mode relies on this to work out the handlerPath - pathInfo = ResolvePathInfoFromMappedPath(fullPath, appPath); - if (!string.IsNullOrEmpty(pathInfo)) return pathInfo; - - return fullPath; - } - - private static string ResolvePathInfoFromMappedPath(string fullPath, string mappedPathRoot) - { - if (mappedPathRoot == null) return null; - - var sbPathInfo = new StringBuilder(); - var fullPathParts = fullPath.Split('/'); - var mappedPathRootParts = mappedPathRoot.Split('/'); - var fullPathIndexOffset = mappedPathRootParts.Length - 1; - var pathRootFound = false; - - for (var fullPathIndex = 0; fullPathIndex < fullPathParts.Length; fullPathIndex++) - { - if (pathRootFound) - { - sbPathInfo.Append("/" + fullPathParts[fullPathIndex]); - } - else if (fullPathIndex - fullPathIndexOffset >= 0) - { - pathRootFound = true; - for (var mappedPathRootIndex = 0; mappedPathRootIndex < mappedPathRootParts.Length; mappedPathRootIndex++) - { - if (!string.Equals(fullPathParts[fullPathIndex - fullPathIndexOffset + mappedPathRootIndex], mappedPathRootParts[mappedPathRootIndex], StringComparison.OrdinalIgnoreCase)) - { - pathRootFound = false; - break; - } - } - } - } - if (!pathRootFound) return null; - - var path = sbPathInfo.ToString(); - return path.Length > 1 ? path.TrimEnd('/') : "/"; - } - - private Dictionary cookies; - public IDictionary Cookies - { - get - { - if (cookies == null) - { - cookies = new Dictionary(); - foreach (var cookie in this.request.Cookies) - { - var httpCookie = (System.Net.Cookie) cookie; - cookies[httpCookie.Name] = new System.Net.Cookie(httpCookie.Name, httpCookie.Value, httpCookie.Path, httpCookie.Domain); - } - } - - return cookies; - } - } - - public string UserAgent - { - get { return request.UserAgent; } - } - - public QueryParamCollection Headers - { - get { return request.Headers; } - } - - private QueryParamCollection queryString; - public QueryParamCollection QueryString - { - get { return queryString ?? (queryString = MyHttpUtility.ParseQueryString(request.Url.Query)); } - } - - public bool IsLocal - { - get { return request.IsLocal; } - } - - private string httpMethod; - public string HttpMethod - { - get - { - return httpMethod - ?? (httpMethod = request.HttpMethod); - } - } - - public string Verb - { - get { return HttpMethod; } - } - - public string ContentType - { - get { return request.ContentType; } - } - - public Encoding contentEncoding; - public Encoding ContentEncoding - { - get { return contentEncoding ?? request.ContentEncoding; } - set { contentEncoding = value; } - } - - public Uri UrlReferrer - { - get { return request.UrlReferrer; } - } - - public static Encoding GetEncoding(string contentTypeHeader) - { - var param = GetParameter(contentTypeHeader, "charset="); - if (param == null) return null; - try - { - return Encoding.GetEncoding(param); - } - catch (ArgumentException) - { - return null; - } - } - - public Stream InputStream - { - get { return request.InputStream; } - } - - public long ContentLength - { - get { return request.ContentLength64; } - } - - private IHttpFile[] httpFiles; - public IHttpFile[] Files - { - get - { - if (httpFiles == null) - { - if (files == null) - return httpFiles = new IHttpFile[0]; - - httpFiles = new IHttpFile[files.Count]; - var i = 0; - foreach (var pair in files) - { - var reqFile = pair.Value; - httpFiles[i] = new HttpFile - { - ContentType = reqFile.ContentType, - ContentLength = reqFile.ContentLength, - FileName = reqFile.FileName, - InputStream = reqFile.InputStream, - }; - i++; - } - } - return httpFiles; - } - } - - public static string NormalizePathInfo(string pathInfo, string handlerPath) - { - if (handlerPath != null && pathInfo.TrimStart('/').StartsWith( - handlerPath, StringComparison.OrdinalIgnoreCase)) - { - return pathInfo.TrimStart('/').Substring(handlerPath.Length); - } - - return pathInfo; - } - } -} diff --git a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpResponse.cs b/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpResponse.cs deleted file mode 100644 index 08fa4cbd6..000000000 --- a/MediaBrowser.Server.Mono/SocketSharp/WebSocketSharpResponse.cs +++ /dev/null @@ -1,196 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; -using MediaBrowser.Model.Services; -using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse; -using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse; -using IRequest = MediaBrowser.Model.Services.IRequest; -using System.Net.Sockets; - -namespace EmbyServer.SocketSharp -{ - public class WebSocketSharpResponse : IHttpResponse - { - private readonly ILogger _logger; - private readonly HttpListenerResponse _response; - - public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response, IRequest request) - { - _logger = logger; - this._response = response; - Items = new Dictionary(); - Request = request; - } - - public IRequest Request { get; private set; } - public Dictionary Items { get; private set; } - public object OriginalResponse - { - get { return _response; } - } - - public int StatusCode - { - get { return this._response.StatusCode; } - set { this._response.StatusCode = value; } - } - - public string StatusDescription - { - get { return this._response.StatusDescription; } - set { this._response.StatusDescription = value; } - } - - public string ContentType - { - get { return _response.ContentType; } - set { _response.ContentType = value; } - } - - //public ICookies Cookies { get; set; } - - public void AddHeader(string name, string value) - { - if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase)) - { - ContentType = value; - return; - } - - _response.AddHeader(name, value); - } - - public QueryParamCollection Headers - { - get - { - return _response.Headers; - } - } - - public string GetHeader(string name) - { - return _response.Headers[name]; - } - - public void Redirect(string url) - { - _response.Redirect(url); - } - - public Stream OutputStream - { - get { return _response.OutputStream; } - } - - public void Close() - { - if (!this.IsClosed) - { - this.IsClosed = true; - - try - { - var response = this._response; - - var outputStream = response.OutputStream; - - // This is needed with compression - outputStream.Flush(); - outputStream.Dispose(); - - response.Close(); - } - catch (SocketException) - { - } - catch (Exception ex) - { - _logger.LogError(ex, "Error in HttpListenerResponseWrapper"); - } - } - } - - public bool IsClosed - { - get; - private set; - } - - public void SetContentLength(long contentLength) - { - //you can happily set the Content-Length header in Asp.Net - //but HttpListener will complain if you do - you have to set ContentLength64 on the response. - //workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header - _response.ContentLength64 = contentLength; - } - - public void SetCookie(Cookie cookie) - { - var cookieStr = AsHeaderValue(cookie); - _response.Headers.Add("Set-Cookie", cookieStr); - } - - public static string AsHeaderValue(Cookie cookie) - { - var defaultExpires = DateTime.MinValue; - - var path = cookie.Expires == defaultExpires - ? "/" - : cookie.Path ?? "/"; - - var sb = new StringBuilder(); - - sb.Append($"{cookie.Name}={cookie.Value};path={path}"); - - if (cookie.Expires != defaultExpires) - { - sb.Append($";expires={cookie.Expires:R}"); - } - - if (!string.IsNullOrEmpty(cookie.Domain)) - { - sb.Append($";domain={cookie.Domain}"); - } - //else if (restrictAllCookiesToDomain != null) - //{ - // sb.Append($";domain={restrictAllCookiesToDomain}"); - //} - - if (cookie.Secure) - { - sb.Append(";Secure"); - } - if (cookie.HttpOnly) - { - sb.Append(";HttpOnly"); - } - - return sb.ToString(); - } - - - public bool SendChunked - { - get { return _response.SendChunked; } - set { _response.SendChunked = value; } - } - - public bool KeepAlive { get; set; } - - public void ClearCookies() - { - } - - public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) - { - return _response.TransmitFile(path, offset, count, fileShareMode, cancellationToken); - } - } -} diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 1f4b01b31..07b9fc4c8 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -28,8 +28,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.XbmcMetadata", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EmbyServer", "MediaBrowser.Server.Mono\EmbyServer.csproj", "{175A9388-F352-4586-A6B4-070DED62B644}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Drawing", "Emby.Drawing\Emby.Drawing.csproj", "{08FFF49B-F175-4807-A2B5-73B0EBD9F716}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Photos", "Emby.Photos\Emby.Photos.csproj", "{89AB4548-770D-41FD-A891-8DAFF44F452C}" @@ -66,6 +64,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IsoMounter", "Emby.IsoMount EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{960295EE-4AF4-4440-A525-B4C295B01A61}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -216,23 +216,6 @@ Global {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Win32.ActiveCfg = Release|Any CPU {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x64.ActiveCfg = Release|Any CPU {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.ActiveCfg = Release|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Any CPU.Build.0 = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Win32.ActiveCfg = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Win32.Build.0 = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|x64.ActiveCfg = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|x86.ActiveCfg = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Debug|x86.Build.0 = Debug|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Release|Any CPU.ActiveCfg = Release|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Release|Win32.ActiveCfg = Release|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Release|Win32.Build.0 = Release|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Release|x64.ActiveCfg = Release|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Release|x86.ActiveCfg = Release|Any CPU - {175A9388-F352-4586-A6B4-070DED62B644}.Release|x86.Build.0 = Release|Any CPU {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.Build.0 = Debug|Any CPU {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -567,6 +550,26 @@ Global {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|x64.Build.0 = Release|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|x86.ActiveCfg = Release|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|x86.Build.0 = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Win32.ActiveCfg = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Win32.Build.0 = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|x64.ActiveCfg = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|x64.Build.0 = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|x86.ActiveCfg = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|x86.Build.0 = Debug|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.Build.0 = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Win32.ActiveCfg = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Win32.Build.0 = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|x64.ActiveCfg = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|x64.Build.0 = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|x86.ActiveCfg = Release|Any CPU + {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- cgit v1.2.3