2019-10-09 17:10:16 +02:00
#pragma warning disable CS1591
2019-01-13 20:23:38 +01:00
using System ;
using System.Collections.Concurrent ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.Globalization ;
using System.IO ;
using System.Linq ;
using System.Net ;
2019-03-08 20:32:14 +01:00
using System.Net.Http ;
2019-07-07 21:03:26 +02:00
using System.Net.Sockets ;
2019-01-13 20:23:38 +01:00
using System.Reflection ;
using System.Runtime.InteropServices ;
using System.Security.Cryptography.X509Certificates ;
using System.Text ;
using System.Threading ;
using System.Threading.Tasks ;
2017-08-09 21:56:38 +02:00
using Emby.Dlna ;
using Emby.Dlna.Main ;
using Emby.Dlna.Ssdp ;
2019-01-13 20:23:38 +01:00
using Emby.Drawing ;
using Emby.Notifications ;
using Emby.Photos ;
2017-08-09 21:56:38 +02:00
using Emby.Server.Implementations.Activity ;
2017-09-09 20:51:24 +02:00
using Emby.Server.Implementations.Archiving ;
2017-08-09 21:56:38 +02:00
using Emby.Server.Implementations.Channels ;
using Emby.Server.Implementations.Collections ;
using Emby.Server.Implementations.Configuration ;
2017-09-09 20:51:24 +02:00
using Emby.Server.Implementations.Cryptography ;
2017-08-09 21:56:38 +02:00
using Emby.Server.Implementations.Data ;
using Emby.Server.Implementations.Devices ;
2017-09-09 20:51:24 +02:00
using Emby.Server.Implementations.Diagnostics ;
2017-08-09 21:56:38 +02:00
using Emby.Server.Implementations.Dto ;
using Emby.Server.Implementations.HttpServer ;
using Emby.Server.Implementations.HttpServer.Security ;
using Emby.Server.Implementations.IO ;
using Emby.Server.Implementations.Library ;
using Emby.Server.Implementations.LiveTv ;
using Emby.Server.Implementations.Localization ;
2017-09-09 20:51:24 +02:00
using Emby.Server.Implementations.Net ;
2017-08-09 21:56:38 +02:00
using Emby.Server.Implementations.Playlists ;
2017-09-09 20:51:24 +02:00
using Emby.Server.Implementations.ScheduledTasks ;
2017-08-09 21:56:38 +02:00
using Emby.Server.Implementations.Security ;
2017-09-09 20:51:24 +02:00
using Emby.Server.Implementations.Serialization ;
2017-08-09 21:56:38 +02:00
using Emby.Server.Implementations.Session ;
2019-02-25 23:34:32 +01:00
using Emby.Server.Implementations.SocketSharp ;
2017-08-09 21:56:38 +02:00
using Emby.Server.Implementations.TV ;
using Emby.Server.Implementations.Updates ;
using MediaBrowser.Api ;
2013-03-04 06:43:06 +01:00
using MediaBrowser.Common ;
using MediaBrowser.Common.Configuration ;
2014-04-26 04:55:07 +02:00
using MediaBrowser.Common.Events ;
2013-03-07 06:34:00 +01:00
using MediaBrowser.Common.Net ;
2017-08-09 21:56:38 +02:00
using MediaBrowser.Common.Plugins ;
using MediaBrowser.Common.Updates ;
2013-02-24 22:53:54 +01:00
using MediaBrowser.Controller ;
2019-01-13 20:23:38 +01:00
using MediaBrowser.Controller.Authentication ;
2014-03-18 02:45:41 +01:00
using MediaBrowser.Controller.Channels ;
2014-06-09 21:16:14 +02:00
using MediaBrowser.Controller.Chapters ;
2014-03-07 16:53:23 +01:00
using MediaBrowser.Controller.Collections ;
2013-03-04 06:43:06 +01:00
using MediaBrowser.Controller.Configuration ;
2014-10-11 22:38:13 +02:00
using MediaBrowser.Controller.Devices ;
2014-03-13 20:08:02 +01:00
using MediaBrowser.Controller.Dlna ;
2013-03-08 06:08:27 +01:00
using MediaBrowser.Controller.Drawing ;
2013-09-04 19:02:19 +02:00
using MediaBrowser.Controller.Dto ;
2013-03-01 22:22:34 +01:00
using MediaBrowser.Controller.Entities ;
2013-02-27 21:25:45 +01:00
using MediaBrowser.Controller.Library ;
2013-09-26 17:48:14 +02:00
using MediaBrowser.Controller.LiveTv ;
2014-02-20 17:37:41 +01:00
using MediaBrowser.Controller.MediaEncoding ;
2013-12-07 16:52:38 +01:00
using MediaBrowser.Controller.Net ;
2013-07-06 23:23:32 +02:00
using MediaBrowser.Controller.Notifications ;
2013-03-08 06:08:27 +01:00
using MediaBrowser.Controller.Persistence ;
2014-08-02 04:34:45 +02:00
using MediaBrowser.Controller.Playlists ;
2013-03-08 06:08:27 +01:00
using MediaBrowser.Controller.Plugins ;
using MediaBrowser.Controller.Providers ;
2013-03-03 17:53:58 +01:00
using MediaBrowser.Controller.Resolvers ;
2014-05-07 20:38:50 +02:00
using MediaBrowser.Controller.Security ;
2013-05-09 19:38:02 +02:00
using MediaBrowser.Controller.Session ;
2013-03-10 05:22:36 +01:00
using MediaBrowser.Controller.Sorting ;
2014-05-07 04:28:19 +02:00
using MediaBrowser.Controller.Subtitles ;
2014-09-01 22:10:54 +02:00
using MediaBrowser.Controller.TV ;
2015-05-31 20:22:51 +02:00
using MediaBrowser.LocalMetadata.Savers ;
2017-09-09 20:51:24 +02:00
using MediaBrowser.MediaEncoding.BdInfo ;
2017-08-09 21:56:38 +02:00
using MediaBrowser.Model.Activity ;
using MediaBrowser.Model.Configuration ;
2017-09-09 20:51:24 +02:00
using MediaBrowser.Model.Cryptography ;
2017-08-09 21:56:38 +02:00
using MediaBrowser.Model.Diagnostics ;
using MediaBrowser.Model.Dlna ;
2017-09-09 20:51:24 +02:00
using MediaBrowser.Model.Events ;
2019-01-13 20:23:38 +01:00
using MediaBrowser.Model.Extensions ;
2017-08-09 21:56:38 +02:00
using MediaBrowser.Model.Globalization ;
using MediaBrowser.Model.IO ;
2013-02-24 22:53:54 +01:00
using MediaBrowser.Model.MediaInfo ;
2017-08-09 21:56:38 +02:00
using MediaBrowser.Model.Net ;
using MediaBrowser.Model.Serialization ;
using MediaBrowser.Model.Services ;
2013-02-24 22:53:54 +01:00
using MediaBrowser.Model.System ;
2017-09-09 20:51:24 +02:00
using MediaBrowser.Model.Tasks ;
2013-09-14 03:56:03 +02:00
using MediaBrowser.Model.Updates ;
2014-06-09 21:16:14 +02:00
using MediaBrowser.Providers.Chapters ;
2014-01-28 19:37:01 +01:00
using MediaBrowser.Providers.Manager ;
2014-05-07 04:28:19 +02:00
using MediaBrowser.Providers.Subtitles ;
2019-02-15 20:11:27 +01:00
using MediaBrowser.Providers.TV.TheTVDB ;
2013-02-28 20:32:41 +01:00
using MediaBrowser.WebDashboard.Api ;
2014-06-30 05:04:50 +02:00
using MediaBrowser.XbmcMetadata.Providers ;
2019-02-25 23:34:32 +01:00
using Microsoft.AspNetCore.Builder ;
using Microsoft.AspNetCore.Hosting ;
using Microsoft.AspNetCore.Http ;
2019-02-26 07:22:49 +01:00
using Microsoft.AspNetCore.Http.Extensions ;
2019-02-17 11:54:47 +01:00
using Microsoft.Extensions.Configuration ;
2019-02-03 17:09:12 +01:00
using Microsoft.Extensions.DependencyInjection ;
2019-02-26 08:09:42 +01:00
using Microsoft.Extensions.DependencyInjection.Extensions ;
2019-08-09 23:16:24 +02:00
using Microsoft.Extensions.Logging ;
2017-08-09 21:56:38 +02:00
using ServiceStack ;
2019-03-07 17:39:40 +01:00
using OperatingSystem = MediaBrowser . Common . System . OperatingSystem ;
2013-02-24 22:53:54 +01:00
2017-08-09 21:56:38 +02:00
namespace Emby.Server.Implementations
2013-02-24 22:53:54 +01:00
{
/// <summary>
2019-10-09 17:10:16 +02:00
/// Class CompositionRoot.
2013-02-24 22:53:54 +01:00
/// </summary>
2018-09-12 19:26:21 +02:00
public abstract class ApplicationHost : IServerApplicationHost , IDisposable
2013-02-24 22:53:54 +01:00
{
2019-08-14 20:24:44 +02:00
private SqliteUserRepository _userRepository ;
2019-08-14 20:35:36 +02:00
private SqliteDisplayPreferencesRepository _displayPreferencesRepository ;
2017-08-16 08:43:41 +02:00
/// <summary>
/// Gets a value indicating whether this instance can self restart.
/// </summary>
/// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
public abstract bool CanSelfRestart { get ; }
2017-12-03 23:14:35 +01:00
public virtual bool CanLaunchWebBrowser
{
get
{
if ( ! Environment . UserInteractive )
{
return false ;
}
2019-01-28 21:58:47 +01:00
if ( StartupOptions . IsService )
2017-12-03 23:14:35 +01:00
{
return false ;
}
2019-03-07 17:39:40 +01:00
if ( OperatingSystem . Id = = OperatingSystemId . Windows
| | OperatingSystem . Id = = OperatingSystemId . Darwin )
2017-12-03 23:14:35 +01:00
{
return true ;
}
return false ;
}
}
2017-08-16 08:43:41 +02:00
/// <summary>
/// Occurs when [has pending restart changed].
/// </summary>
public event EventHandler HasPendingRestartChanged ;
/// <summary>
2019-03-13 22:32:52 +01:00
/// Gets a value indicating whether this instance has changes that require the entire application to restart.
2017-08-16 08:43:41 +02:00
/// </summary>
/// <value><c>true</c> if this instance has pending application restart; otherwise, <c>false</c>.</value>
public bool HasPendingRestart { get ; private set ; }
2019-10-09 17:10:16 +02:00
/// <inheritdoc />
2017-09-09 20:51:24 +02:00
public bool IsShuttingDown { get ; private set ; }
2017-08-16 08:43:41 +02:00
/// <summary>
/// Gets or sets the logger.
/// </summary>
/// <value>The logger.</value>
protected ILogger Logger { get ; set ; }
2019-02-18 22:47:02 +01:00
private IPlugin [ ] _plugins ;
2017-08-16 08:43:41 +02:00
/// <summary>
2019-03-13 22:32:52 +01:00
/// Gets the plugins.
2017-08-16 08:43:41 +02:00
/// </summary>
/// <value>The plugins.</value>
2019-02-18 22:47:02 +01:00
public IPlugin [ ] Plugins
{
get = > _plugins ;
protected set = > _plugins = value ;
}
2017-08-16 08:43:41 +02:00
/// <summary>
2018-12-13 14:18:25 +01:00
/// Gets or sets the logger factory.
2017-08-16 08:43:41 +02:00
/// </summary>
2018-12-13 14:18:25 +01:00
/// <value>The logger factory.</value>
public ILoggerFactory LoggerFactory { get ; protected set ; }
2017-08-16 08:43:41 +02:00
/// <summary>
2019-03-13 22:32:52 +01:00
/// Gets or sets the application paths.
2017-08-16 08:43:41 +02:00
/// </summary>
/// <value>The application paths.</value>
protected ServerApplicationPaths ApplicationPaths { get ; set ; }
/// <summary>
2019-03-13 22:32:52 +01:00
/// Gets or sets all concrete types.
2017-08-16 08:43:41 +02:00
/// </summary>
/// <value>All concrete types.</value>
2019-08-29 23:11:55 +02:00
private Type [ ] _allConcreteTypes ;
2017-08-16 08:43:41 +02:00
/// <summary>
2019-08-29 23:11:55 +02:00
/// The disposable parts.
2017-08-16 08:43:41 +02:00
/// </summary>
2019-03-25 22:25:32 +01:00
private readonly List < IDisposable > _disposableParts = new List < IDisposable > ( ) ;
2017-08-16 08:43:41 +02:00
/// <summary>
/// Gets the configuration manager.
/// </summary>
/// <value>The configuration manager.</value>
protected IConfigurationManager ConfigurationManager { get ; set ; }
public IFileSystem FileSystemManager { get ; set ; }
2019-10-09 17:10:16 +02:00
/// <inheritdoc />
2017-08-16 08:43:41 +02:00
public PackageVersionClass SystemUpdateLevel
{
get
{
#if BETA
return PackageVersionClass . Beta ;
2019-03-25 22:25:32 +01:00
#else
2017-08-16 08:43:41 +02:00
return PackageVersionClass . Release ;
2019-03-25 22:25:32 +01:00
#endif
2017-08-16 08:43:41 +02:00
}
}
2019-02-03 17:09:12 +01:00
protected IServiceProvider _serviceProvider ;
2017-08-16 08:43:41 +02:00
2013-02-24 22:53:54 +01:00
/// <summary>
2013-03-04 06:43:06 +01:00
/// Gets the server configuration manager.
2013-02-24 22:53:54 +01:00
/// </summary>
2013-03-04 06:43:06 +01:00
/// <value>The server configuration manager.</value>
2019-01-06 21:50:43 +01:00
public IServerConfigurationManager ServerConfigurationManager = > ( IServerConfigurationManager ) ConfigurationManager ;
2013-03-03 08:27:40 +01:00
2013-03-08 06:08:27 +01:00
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2013-03-08 06:08:27 +01:00
/// <summary>
/// Gets or sets the library manager.
/// </summary>
/// <value>The library manager.</value>
internal ILibraryManager LibraryManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2013-03-08 06:08:27 +01:00
/// <summary>
/// Gets or sets the directory watchers.
/// </summary>
/// <value>The directory watchers.</value>
2014-01-28 22:25:10 +01:00
private ILibraryMonitor LibraryMonitor { get ; set ; }
2019-03-13 22:32:52 +01:00
2013-03-08 06:08:27 +01:00
/// <summary>
/// Gets or sets the provider manager.
/// </summary>
/// <value>The provider manager.</value>
private IProviderManager ProviderManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2013-03-08 06:08:27 +01:00
/// <summary>
/// Gets or sets the HTTP server.
/// </summary>
/// <value>The HTTP server.</value>
private IHttpServer HttpServer { get ; set ; }
2019-03-13 22:32:52 +01:00
2013-09-04 19:02:19 +02:00
private IDtoService DtoService { get ; set ; }
2019-03-13 22:32:52 +01:00
2017-05-12 20:09:42 +02:00
public IImageProcessor ImageProcessor { get ; set ; }
2013-03-10 07:45:16 +01:00
2013-04-08 17:55:53 +02:00
/// <summary>
/// Gets or sets the media encoder.
/// </summary>
/// <value>The media encoder.</value>
2013-04-07 22:55:05 +02:00
private IMediaEncoder MediaEncoder { get ; set ; }
2019-03-13 22:32:52 +01:00
2015-01-02 07:12:58 +01:00
private ISubtitleEncoder SubtitleEncoder { get ; set ; }
2013-04-08 17:55:53 +02:00
2013-09-24 17:42:30 +02:00
private ISessionManager SessionManager { get ; set ; }
2013-08-10 03:40:52 +02:00
2013-09-26 17:48:14 +02:00
private ILiveTvManager LiveTvManager { get ; set ; }
2013-09-26 23:20:26 +02:00
2019-01-27 10:20:05 +01:00
public LocalizationManager LocalizationManager { get ; set ; }
2013-06-10 19:46:11 +02:00
2014-02-20 17:37:41 +01:00
private IEncodingManager EncodingManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2014-03-18 18:05:57 +01:00
private IChannelManager ChannelManager { get ; set ; }
2014-02-28 05:49:02 +01:00
2013-04-13 20:02:30 +02:00
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
2013-10-02 18:08:58 +02:00
private IUserDataManager UserDataManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2019-01-26 18:27:57 +01:00
internal SqliteItemRepository ItemRepository { get ; set ; }
2013-04-13 20:02:30 +02:00
2014-04-25 22:15:50 +02:00
private INotificationManager NotificationManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2014-05-07 04:28:19 +02:00
private ISubtitleManager SubtitleManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2014-06-09 21:16:14 +02:00
private IChapterManager ChapterManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2014-10-11 22:38:13 +02:00
private IDeviceManager DeviceManager { get ; set ; }
2014-04-25 22:15:50 +02:00
2014-09-01 22:10:54 +02:00
internal IUserViewManager UserViewManager { get ; set ; }
2014-06-07 21:46:24 +02:00
2014-07-08 03:41:03 +02:00
private IAuthenticationRepository AuthenticationRepository { get ; set ; }
2019-03-13 22:32:52 +01:00
2014-09-01 22:10:54 +02:00
private ITVSeriesManager TVSeriesManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2014-10-08 03:37:45 +02:00
private ICollectionManager CollectionManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2015-02-07 22:03:09 +01:00
private IMediaSourceManager MediaSourceManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2019-02-17 11:54:47 +01:00
private readonly IConfiguration _configuration ;
2016-10-29 07:40:15 +02:00
/// <summary>
/// Gets or sets the installation manager.
/// </summary>
/// <value>The installation manager.</value>
protected IInstallationManager InstallationManager { get ; private set ; }
2016-11-08 19:44:23 +01:00
protected IAuthService AuthService { get ; private set ; }
2019-03-13 22:32:52 +01:00
public IStartupOptions StartupOptions { get ; }
2014-09-14 17:26:33 +02:00
2016-11-11 18:33:10 +01:00
internal IImageEncoder ImageEncoder { get ; private set ; }
2017-08-16 08:43:41 +02:00
protected IProcessFactory ProcessFactory { get ; private set ; }
2019-03-13 22:32:52 +01:00
2017-08-16 08:43:41 +02:00
protected readonly IXmlSerializer XmlSerializer ;
protected ISocketFactory SocketFactory { get ; private set ; }
2019-03-13 22:32:52 +01:00
2017-08-16 08:43:41 +02:00
protected ITaskManager TaskManager { get ; private set ; }
2019-03-13 22:32:52 +01:00
2017-08-16 08:43:41 +02:00
public IHttpClient HttpClient { get ; private set ; }
2019-03-13 22:32:52 +01:00
2017-08-16 08:43:41 +02:00
protected INetworkManager NetworkManager { get ; set ; }
2019-03-13 22:32:52 +01:00
2017-08-16 08:43:41 +02:00
public IJsonSerializer JsonSerializer { get ; private set ; }
2019-03-13 22:32:52 +01:00
2017-08-16 08:43:41 +02:00
protected IIsoManager IsoManager { get ; private set ; }
2016-11-09 05:58:58 +01:00
2013-09-21 03:04:14 +02:00
/// <summary>
2014-07-20 06:46:29 +02:00
/// Initializes a new instance of the <see cref="ApplicationHost" /> class.
2013-09-21 03:04:14 +02:00
/// </summary>
2019-03-13 22:32:52 +01:00
public ApplicationHost (
ServerApplicationPaths applicationPaths ,
2018-12-13 14:18:25 +01:00
ILoggerFactory loggerFactory ,
2019-01-28 21:58:47 +01:00
IStartupOptions options ,
2014-10-07 01:58:46 +02:00
IFileSystem fileSystem ,
2016-11-11 18:33:10 +01:00
IImageEncoder imageEncoder ,
2019-02-17 11:54:47 +01:00
INetworkManager networkManager ,
IConfiguration configuration )
2013-09-20 19:32:10 +02:00
{
2019-02-17 11:54:47 +01:00
_configuration = configuration ;
2017-11-29 21:50:18 +01:00
2019-09-25 13:24:39 +02:00
XmlSerializer = new MyXmlSerializer ( ) ;
2017-08-16 08:43:41 +02:00
NetworkManager = networkManager ;
2018-09-12 19:26:21 +02:00
networkManager . LocalSubnetsFn = GetConfiguredLocalSubnets ;
2017-08-16 08:43:41 +02:00
ApplicationPaths = applicationPaths ;
2018-12-13 14:18:25 +01:00
LoggerFactory = loggerFactory ;
2017-08-16 08:43:41 +02:00
FileSystemManager = fileSystem ;
2019-03-07 17:39:40 +01:00
ConfigurationManager = new ServerConfigurationManager ( ApplicationPaths , LoggerFactory , XmlSerializer , FileSystemManager ) ;
2017-08-16 08:43:41 +02:00
2018-12-13 14:18:25 +01:00
Logger = LoggerFactory . CreateLogger ( "App" ) ;
2017-08-16 08:43:41 +02:00
2016-11-13 05:33:51 +01:00
StartupOptions = options ;
2014-12-17 23:39:17 +01:00
2016-11-11 18:33:10 +01:00
ImageEncoder = imageEncoder ;
2017-03-10 20:51:29 +01:00
fileSystem . AddShortcutHandler ( new MbLinkShortcutHandler ( fileSystem ) ) ;
2017-11-29 21:50:18 +01:00
2019-08-09 23:16:24 +02:00
NetworkManager . NetworkChanged + = OnNetworkChanged ;
2017-11-29 21:50:18 +01:00
}
2018-09-12 19:26:21 +02:00
public string ExpandVirtualPath ( string path )
{
var appPaths = ApplicationPaths ;
return path . Replace ( appPaths . VirtualDataPath , appPaths . DataPath , StringComparison . OrdinalIgnoreCase )
. Replace ( appPaths . VirtualInternalMetadataPath , appPaths . InternalMetadataPath , StringComparison . OrdinalIgnoreCase ) ;
}
public string ReverseVirtualPath ( string path )
{
var appPaths = ApplicationPaths ;
return path . Replace ( appPaths . DataPath , appPaths . VirtualDataPath , StringComparison . OrdinalIgnoreCase )
. Replace ( appPaths . InternalMetadataPath , appPaths . VirtualInternalMetadataPath , StringComparison . OrdinalIgnoreCase ) ;
}
private string [ ] GetConfiguredLocalSubnets ( )
{
return ServerConfigurationManager . Configuration . LocalNetworkSubnets ;
}
2019-08-09 23:16:24 +02:00
private void OnNetworkChanged ( object sender , EventArgs e )
2017-11-29 21:50:18 +01:00
{
_validAddressResults . Clear ( ) ;
2014-01-30 01:18:05 +01:00
}
2013-09-21 03:04:14 +02:00
2019-10-08 20:51:11 +02:00
/// <inheritdoc />
public Version ApplicationVersion { get ; } = typeof ( ApplicationHost ) . Assembly . GetName ( ) . Version ;
/// <inheritdoc />
public string ApplicationVersionString { get ; } = typeof ( ApplicationHost ) . Assembly . GetName ( ) . Version . ToString ( 3 ) ;
2019-01-08 01:57:01 +01:00
/// <summary>
2019-08-09 23:50:40 +02:00
/// Gets the current application user agent.
2019-01-08 01:57:01 +01:00
/// </summary>
2019-01-20 03:41:48 +01:00
/// <value>The application user agent.</value>
2019-10-08 20:51:11 +02:00
public string ApplicationUserAgent = > Name . Replace ( ' ' , '-' ) + "/" + ApplicationVersionString ;
2019-01-08 01:57:01 +01:00
2019-03-14 22:32:27 +01:00
/// <summary>
/// Gets the email address for use within a comment section of a user agent field.
/// Presently used to provide contact information to MusicBrainz service.
/// </summary>
public string ApplicationUserAgentAddress { get ; } = "team@jellyfin.org" ;
2019-01-08 01:57:01 +01:00
/// <summary>
2019-08-09 23:16:24 +02:00
/// Gets the current application name.
2019-01-08 01:57:01 +01:00
/// </summary>
/// <value>The application name.</value>
2019-08-09 23:16:24 +02:00
public string ApplicationProductName { get ; } = FileVersionInfo . GetVersionInfo ( Assembly . GetEntryAssembly ( ) . Location ) . ProductName ;
2014-11-14 07:27:10 +01:00
2017-08-16 08:43:41 +02:00
private DeviceId _deviceId ;
2019-03-13 22:32:52 +01:00
2017-08-16 08:43:41 +02:00
public string SystemId
{
get
{
if ( _deviceId = = null )
{
2019-02-06 20:38:42 +01:00
_deviceId = new DeviceId ( ApplicationPaths , LoggerFactory ) ;
2017-08-16 08:43:41 +02:00
}
return _deviceId . Value ;
}
}
2014-01-25 22:07:19 +01:00
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
2019-01-20 05:52:40 +01:00
public string Name = > ApplicationProductName ;
2014-01-25 22:07:19 +01:00
2017-08-16 08:43:41 +02:00
/// <summary>
2019-02-03 17:09:12 +01:00
/// Creates an instance of type and resolves all constructor dependencies
2017-08-16 08:43:41 +02:00
/// </summary>
/// <param name="type">The type.</param>
/// <returns>System.Object.</returns>
public object CreateInstance ( Type type )
2019-02-03 17:09:12 +01:00
= > ActivatorUtilities . CreateInstance ( _serviceProvider , type ) ;
/// <summary>
/// Creates an instance of type and resolves all constructor dependencies
/// </summary>
2019-08-09 23:50:40 +02:00
/// /// <typeparam name="T">The type.</typeparam>
/// <returns>T.</returns>
2019-02-03 17:09:12 +01:00
public T CreateInstance < T > ( )
= > ActivatorUtilities . CreateInstance < T > ( _serviceProvider ) ;
2017-08-16 08:43:41 +02:00
/// <summary>
/// Creates the instance safe.
/// </summary>
2019-03-13 22:32:52 +01:00
/// <param name="type">The type.</param>
2017-08-16 08:43:41 +02:00
/// <returns>System.Object.</returns>
2019-02-03 17:09:12 +01:00
protected object CreateInstanceSafe ( Type type )
2017-08-16 08:43:41 +02:00
{
try
{
2019-02-16 11:41:48 +01:00
Logger . LogDebug ( "Creating instance of {Type}" , type ) ;
2019-02-03 17:09:12 +01:00
return ActivatorUtilities . CreateInstance ( _serviceProvider , type ) ;
2017-08-16 08:43:41 +02:00
}
catch ( Exception ex )
{
2019-02-03 17:09:12 +01:00
Logger . LogError ( ex , "Error creating {Type}" , type ) ;
2017-08-16 08:43:41 +02:00
return null ;
}
}
/// <summary>
/// Resolves this instance.
/// </summary>
2019-03-13 22:32:52 +01:00
/// <typeparam name="T">The type</typeparam>
2017-08-16 08:43:41 +02:00
/// <returns>``0.</returns>
2019-02-03 17:09:12 +01:00
public T Resolve < T > ( ) = > _serviceProvider . GetService < T > ( ) ;
2017-08-16 08:43:41 +02:00
/// <summary>
/// Gets the export types.
/// </summary>
2019-03-13 22:32:52 +01:00
/// <typeparam name="T">The type</typeparam>
2017-08-16 08:43:41 +02:00
/// <returns>IEnumerable{Type}.</returns>
2019-02-03 17:09:12 +01:00
public IEnumerable < Type > GetExportTypes < T > ( )
2017-08-16 08:43:41 +02:00
{
var currentType = typeof ( T ) ;
2019-08-29 23:11:55 +02:00
return _allConcreteTypes . Where ( i = > currentType . IsAssignableFrom ( i ) ) ;
2017-08-16 08:43:41 +02:00
}
2019-08-11 16:52:37 +02:00
/// <inheritdoc />
public IReadOnlyCollection < T > GetExports < T > ( bool manageLifetime = true )
2017-08-16 08:43:41 +02:00
{
var parts = GetExportTypes < T > ( )
2019-03-13 22:32:52 +01:00
. Select ( CreateInstanceSafe )
2017-08-16 08:43:41 +02:00
. Where ( i = > i ! = null )
2019-02-06 17:41:38 +01:00
. Cast < T > ( )
. ToList ( ) ; // Convert to list so this isn't executed for each iteration
2017-08-16 08:43:41 +02:00
2018-12-20 13:11:26 +01:00
if ( manageLifetime )
2017-08-16 08:43:41 +02:00
{
2019-03-13 22:32:52 +01:00
lock ( _disposableParts )
2017-08-16 08:43:41 +02:00
{
2019-03-13 22:32:52 +01:00
_disposableParts . AddRange ( parts . OfType < IDisposable > ( ) ) ;
2017-08-16 08:43:41 +02:00
}
}
return parts ;
}
2013-03-08 06:08:27 +01:00
/// <summary>
2013-03-10 07:45:16 +01:00
/// Runs the startup tasks.
2013-03-08 06:08:27 +01:00
/// </summary>
2019-08-11 16:52:37 +02:00
/// <returns><see cref="Task" />.</returns>
2019-03-07 17:39:40 +01:00
public async Task RunStartupTasksAsync ( )
2013-03-07 06:34:00 +01:00
{
2019-01-27 15:40:37 +01:00
Logger . LogInformation ( "Running startup tasks" ) ;
2017-08-16 08:43:41 +02:00
Resolve < ITaskManager > ( ) . AddTasks ( GetExports < IScheduledTask > ( false ) ) ;
ConfigurationManager . ConfigurationUpdated + = OnConfigurationUpdated ;
2013-03-08 06:08:27 +01:00
2019-02-28 23:47:56 +01:00
MediaEncoder . SetFFmpegPath ( ) ;
2016-09-09 18:58:08 +02:00
2018-12-13 14:18:25 +01:00
Logger . LogInformation ( "ServerId: {0}" , SystemId ) ;
2018-09-12 19:26:21 +02:00
2019-08-11 16:52:37 +02:00
var entryPoints = GetExports < IServerEntryPoint > ( ) ;
2019-01-27 15:40:37 +01:00
2019-02-25 18:26:17 +01:00
var stopWatch = new Stopwatch ( ) ;
stopWatch . Start ( ) ;
2019-03-13 22:32:52 +01:00
await Task . WhenAll ( StartEntryPoints ( entryPoints , true ) ) . ConfigureAwait ( false ) ;
2019-02-26 19:37:39 +01:00
Logger . LogInformation ( "Executed all pre-startup entry points in {Elapsed:g}" , stopWatch . Elapsed ) ;
2018-09-12 19:26:21 +02:00
2018-12-13 14:18:25 +01:00
Logger . LogInformation ( "Core startup complete" ) ;
2015-09-14 01:07:54 +02:00
HttpServer . GlobalResponse = null ;
2013-04-08 17:55:53 +02:00
2019-02-25 18:26:17 +01:00
stopWatch . Restart ( ) ;
2019-03-13 22:32:52 +01:00
await Task . WhenAll ( StartEntryPoints ( entryPoints , false ) ) . ConfigureAwait ( false ) ;
2019-02-26 19:37:39 +01:00
Logger . LogInformation ( "Executed all post-startup entry points in {Elapsed:g}" , stopWatch . Elapsed ) ;
2019-02-25 18:26:17 +01:00
stopWatch . Stop ( ) ;
2018-09-12 19:26:21 +02:00
}
2019-01-27 15:40:37 +01:00
private IEnumerable < Task > StartEntryPoints ( IEnumerable < IServerEntryPoint > entryPoints , bool isBeforeStartup )
2018-09-12 19:26:21 +02:00
{
foreach ( var entryPoint in entryPoints )
2013-06-22 01:38:19 +02:00
{
2018-09-12 19:26:21 +02:00
if ( isBeforeStartup ! = ( entryPoint is IRunBeforeStartup ) )
{
continue ;
}
2019-01-27 15:40:37 +01:00
Logger . LogDebug ( "Starting entry point {Type}" , entryPoint . GetType ( ) ) ;
yield return entryPoint . RunAsync ( ) ;
2016-06-30 00:01:35 +02:00
}
2013-03-07 06:34:00 +01:00
}
2019-03-07 17:39:40 +01:00
public async Task InitAsync ( IServiceCollection serviceCollection )
2014-02-13 06:11:54 +01:00
{
2015-01-19 05:29:57 +01:00
HttpPort = ServerConfigurationManager . Configuration . HttpServerPortNumber ;
HttpsPort = ServerConfigurationManager . Configuration . HttpsPortNumber ;
2016-11-09 05:58:58 +01:00
// Safeguard against invalid configuration
if ( HttpPort = = HttpsPort )
{
HttpPort = ServerConfiguration . DefaultHttpPort ;
HttpsPort = ServerConfiguration . DefaultHttpsPort ;
}
2019-01-17 23:55:05 +01:00
JsonSerializer = new JsonSerializer ( FileSystemManager ) ;
2017-08-16 08:43:41 +02:00
if ( Plugins ! = null )
{
var pluginBuilder = new StringBuilder ( ) ;
foreach ( var plugin in Plugins )
{
2019-08-09 23:16:24 +02:00
pluginBuilder . AppendLine (
string . Format (
CultureInfo . InvariantCulture ,
"{0} {1}" ,
plugin . Name ,
plugin . Version ) ) ;
2017-08-16 08:43:41 +02:00
}
2019-08-09 23:16:24 +02:00
Logger . LogInformation ( "Plugins: {Plugins}" , pluginBuilder . ToString ( ) ) ;
2017-08-16 08:43:41 +02:00
}
2019-01-01 18:41:02 +01:00
DiscoverTypes ( ) ;
2019-03-13 22:32:52 +01:00
await RegisterResources ( serviceCollection ) . ConfigureAwait ( false ) ;
2019-01-01 18:41:02 +01:00
FindParts ( ) ;
2019-02-25 23:34:32 +01:00
2019-03-05 07:55:29 +01:00
string contentRoot = ServerConfigurationManager . Configuration . DashboardSourcePath ;
if ( string . IsNullOrEmpty ( contentRoot ) )
{
2019-03-12 14:18:45 +01:00
contentRoot = ServerConfigurationManager . ApplicationPaths . WebPath ;
2019-03-05 07:55:29 +01:00
}
2019-03-06 19:27:05 +01:00
var host = new WebHostBuilder ( )
2019-02-26 20:40:05 +01:00
. UseKestrel ( options = >
{
2019-09-29 06:07:44 +02:00
var addresses = ServerConfigurationManager
. Configuration
. LocalNetworkAddresses
. Select ( NormalizeConfiguredLocalAddress )
. Where ( i = > i ! = null )
. ToList ( ) ;
if ( addresses . Any ( ) )
{
foreach ( var address in addresses )
{
Logger . LogInformation ( "Kestrel listening on {ipaddr}" , address ) ;
options . Listen ( address , HttpPort ) ;
if ( EnableHttps & & Certificate ! = null )
{
options . Listen ( address , HttpsPort , listenOptions = > listenOptions . UseHttps ( Certificate ) ) ;
}
}
}
else
2019-03-03 08:29:23 +01:00
{
2019-09-29 06:07:44 +02:00
Logger . LogInformation ( "Kestrel listening on all interfaces" ) ;
options . ListenAnyIP ( HttpPort ) ;
if ( EnableHttps & & Certificate ! = null )
{
options . ListenAnyIP ( HttpsPort , listenOptions = > listenOptions . UseHttps ( Certificate ) ) ;
}
2019-03-03 08:29:23 +01:00
}
2019-02-26 20:40:05 +01:00
} )
2019-03-05 07:55:29 +01:00
. UseContentRoot ( contentRoot )
2019-02-26 08:09:42 +01:00
. ConfigureServices ( services = >
{
2019-02-26 10:30:51 +01:00
services . AddResponseCompression ( ) ;
2019-02-26 08:09:42 +01:00
services . AddHttpContextAccessor ( ) ;
} )
2019-02-26 20:40:05 +01:00
. Configure ( app = >
2019-02-25 23:34:32 +01:00
{
2019-02-26 20:40:05 +01:00
app . UseWebSockets ( ) ;
2019-02-25 23:34:32 +01:00
2019-02-26 10:30:51 +01:00
app . UseResponseCompression ( ) ;
2019-08-09 23:16:24 +02:00
2019-02-27 23:22:55 +01:00
// TODO app.UseMiddleware<WebSocketMiddleware>();
2019-02-26 10:23:58 +01:00
app . Use ( ExecuteWebsocketHandlerAsync ) ;
app . Use ( ExecuteHttpHandlerAsync ) ;
2019-02-25 23:34:32 +01:00
} )
. Build ( ) ;
2019-03-03 14:30:41 +01:00
2019-09-29 23:17:19 +02:00
try
{
await host . StartAsync ( ) . ConfigureAwait ( false ) ;
}
2019-10-04 18:53:26 +02:00
catch
2019-09-29 23:17:19 +02:00
{
Logger . LogError ( "Kestrel failed to start! This is most likely due to an invalid address or port bind - correct your bind configuration in system.xml and try again." ) ;
throw ;
}
2019-02-25 23:34:32 +01:00
}
2019-03-06 19:27:05 +01:00
private async Task ExecuteWebsocketHandlerAsync ( HttpContext context , Func < Task > next )
2019-02-25 23:34:32 +01:00
{
2019-02-26 10:23:58 +01:00
if ( ! context . WebSockets . IsWebSocketRequest )
2019-02-25 23:34:32 +01:00
{
2019-03-05 07:55:29 +01:00
await next ( ) . ConfigureAwait ( false ) ;
2019-02-26 10:23:58 +01:00
return ;
2019-02-25 23:34:32 +01:00
}
2019-02-26 21:27:02 +01:00
await HttpServer . ProcessWebSocketRequest ( context ) . ConfigureAwait ( false ) ;
2019-02-26 10:23:58 +01:00
}
2019-03-06 19:27:05 +01:00
private async Task ExecuteHttpHandlerAsync ( HttpContext context , Func < Task > next )
2019-02-26 10:23:58 +01:00
{
if ( context . WebSockets . IsWebSocketRequest )
{
2019-03-05 07:55:29 +01:00
await next ( ) . ConfigureAwait ( false ) ;
2019-02-26 10:23:58 +01:00
return ;
}
var request = context . Request ;
var response = context . Response ;
2019-02-26 15:13:06 +01:00
var localPath = context . Request . Path . ToString ( ) ;
2019-02-26 10:23:58 +01:00
2019-02-25 23:34:32 +01:00
var req = new WebSocketSharpRequest ( request , response , request . Path , Logger ) ;
2019-07-28 23:53:19 +02:00
await HttpServer . RequestHandler ( req , request . GetDisplayUrl ( ) , request . Host . ToString ( ) , localPath , context . RequestAborted ) . ConfigureAwait ( false ) ;
2018-12-15 00:06:57 +01:00
}
2014-02-13 06:11:54 +01:00
2013-02-24 22:53:54 +01:00
/// <summary>
/// Registers resources that classes will depend on
/// </summary>
2019-02-03 17:09:12 +01:00
protected async Task RegisterResources ( IServiceCollection serviceCollection )
2013-02-24 22:53:54 +01:00
{
2019-02-15 22:02:17 +01:00
serviceCollection . AddMemoryCache ( ) ;
2019-02-15 20:11:27 +01:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( ConfigurationManager ) ;
serviceCollection . AddSingleton < IApplicationHost > ( this ) ;
serviceCollection . AddSingleton < IApplicationPaths > ( ApplicationPaths ) ;
2017-08-16 08:43:41 +02:00
2019-03-11 23:13:01 +01:00
serviceCollection . AddSingleton < IConfiguration > ( _configuration ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( JsonSerializer ) ;
2017-08-16 08:43:41 +02:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( LoggerFactory ) ;
serviceCollection . AddLogging ( ) ;
serviceCollection . AddSingleton ( Logger ) ;
2017-08-16 08:43:41 +02:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( FileSystemManager ) ;
2019-02-15 20:11:27 +01:00
serviceCollection . AddSingleton < TvDbClientManager > ( ) ;
2017-08-16 08:43:41 +02:00
2019-06-14 16:32:37 +02:00
HttpClient = new HttpClientManager . HttpClientManager (
ApplicationPaths ,
LoggerFactory . CreateLogger < HttpClientManager . HttpClientManager > ( ) ,
FileSystemManager ,
( ) = > ApplicationUserAgent ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( HttpClient ) ;
2017-08-16 08:43:41 +02:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( NetworkManager ) ;
2017-08-16 08:43:41 +02:00
IsoManager = new IsoManager ( ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( IsoManager ) ;
2017-08-16 08:43:41 +02:00
2019-01-25 22:41:43 +01:00
TaskManager = new TaskManager ( ApplicationPaths , JsonSerializer , LoggerFactory , FileSystemManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( TaskManager ) ;
2017-08-16 08:43:41 +02:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( XmlSerializer ) ;
2017-08-16 08:43:41 +02:00
ProcessFactory = new ProcessFactory ( ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( ProcessFactory ) ;
2017-08-16 08:43:41 +02:00
2019-07-07 16:39:35 +02:00
serviceCollection . AddSingleton ( typeof ( IStreamHelper ) , typeof ( StreamHelper ) ) ;
2018-09-12 19:26:21 +02:00
2019-03-25 22:25:32 +01:00
serviceCollection . AddSingleton ( typeof ( ICryptoProvider ) , typeof ( CryptographyProvider ) ) ;
2017-08-16 08:43:41 +02:00
2019-01-17 23:55:05 +01:00
SocketFactory = new SocketFactory ( ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( SocketFactory ) ;
2013-02-26 04:43:04 +01:00
2019-03-25 22:25:32 +01:00
serviceCollection . AddSingleton ( typeof ( IInstallationManager ) , typeof ( InstallationManager ) ) ;
2016-10-29 07:40:15 +02:00
2019-07-07 16:39:35 +02:00
serviceCollection . AddSingleton ( typeof ( IZipClient ) , typeof ( ZipClient ) ) ;
2016-10-28 20:35:17 +02:00
2019-07-07 16:39:35 +02:00
serviceCollection . AddSingleton ( typeof ( IHttpResultFactory ) , typeof ( HttpResultFactory ) ) ;
2013-03-15 05:23:07 +01:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton < IServerApplicationHost > ( this ) ;
serviceCollection . AddSingleton < IServerApplicationPaths > ( ApplicationPaths ) ;
2013-03-07 06:34:00 +01:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( ServerConfigurationManager ) ;
2015-02-28 19:47:05 +01:00
2019-08-16 17:31:47 +02:00
LocalizationManager = new LocalizationManager ( ServerConfigurationManager , JsonSerializer , LoggerFactory . CreateLogger < LocalizationManager > ( ) ) ;
2019-03-13 22:32:52 +01:00
await LocalizationManager . LoadAll ( ) . ConfigureAwait ( false ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton < ILocalizationManager > ( LocalizationManager ) ;
2014-03-31 03:00:47 +02:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton < IBlurayExaminer > ( new BdInfoExaminer ( FileSystemManager ) ) ;
2013-03-08 06:08:27 +01:00
2018-12-13 14:18:25 +01:00
UserDataManager = new UserDataManager ( LoggerFactory , ServerConfigurationManager , ( ) = > UserManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( UserDataManager ) ;
2013-04-13 20:02:30 +02:00
2019-08-14 20:35:36 +02:00
_displayPreferencesRepository = new SqliteDisplayPreferencesRepository (
LoggerFactory . CreateLogger < SqliteDisplayPreferencesRepository > ( ) ,
ApplicationPaths ,
FileSystemManager ) ;
serviceCollection . AddSingleton < IDisplayPreferencesRepository > ( _displayPreferencesRepository ) ;
2013-04-19 22:27:02 +02:00
2019-09-25 17:43:20 +02:00
ItemRepository = new SqliteItemRepository ( ServerConfigurationManager , this , LoggerFactory . CreateLogger < SqliteItemRepository > ( ) , LocalizationManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton < IItemRepository > ( ItemRepository ) ;
2013-04-19 22:27:02 +02:00
2017-05-26 08:48:54 +02:00
AuthenticationRepository = GetAuthenticationRepository ( ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( AuthenticationRepository ) ;
2014-07-08 03:41:03 +02:00
2019-08-14 20:24:44 +02:00
_userRepository = GetUserRepository ( ) ;
2019-04-03 14:22:17 +02:00
2019-06-09 22:08:01 +02:00
UserManager = new UserManager ( LoggerFactory . CreateLogger < UserManager > ( ) , _userRepository , XmlSerializer , NetworkManager , ( ) = > ImageProcessor , ( ) = > DtoService , this , JsonSerializer , FileSystemManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( UserManager ) ;
2013-04-14 05:05:19 +02:00
2019-01-17 23:55:05 +01:00
LibraryManager = new LibraryManager ( this , LoggerFactory , TaskManager , UserManager , ServerConfigurationManager , UserDataManager , ( ) = > LibraryMonitor , FileSystemManager , ( ) = > ProviderManager , ( ) = > UserViewManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( LibraryManager ) ;
2013-03-05 05:25:27 +01:00
2019-01-17 23:55:05 +01:00
// TODO wtaylor: investigate use of second music manager
2014-04-02 23:55:19 +02:00
var musicManager = new MusicManager ( LibraryManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton < IMusicManager > ( new MusicManager ( LibraryManager ) ) ;
2014-03-30 18:49:40 +02:00
2019-03-07 17:39:40 +01:00
LibraryMonitor = new LibraryMonitor ( LoggerFactory , LibraryManager , ServerConfigurationManager , FileSystemManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( LibraryMonitor ) ;
2013-03-08 06:08:27 +01:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton < ISearchEngine > ( new SearchEngine ( LoggerFactory , LibraryManager , UserManager ) ) ;
2013-04-05 21:34:33 +02:00
2017-05-01 04:22:13 +02:00
CertificateInfo = GetCertificateInfo ( true ) ;
Certificate = GetCertificate ( CertificateInfo ) ;
2016-11-12 07:58:50 +01:00
2019-03-13 22:32:52 +01:00
HttpServer = new HttpListenerHost (
this ,
2019-07-28 23:53:19 +02:00
LoggerFactory . CreateLogger < HttpListenerHost > ( ) ,
2018-09-12 19:26:21 +02:00
ServerConfigurationManager ,
2019-02-17 11:54:47 +01:00
_configuration ,
2018-09-12 19:26:21 +02:00
NetworkManager ,
JsonSerializer ,
2019-02-26 20:22:40 +01:00
XmlSerializer ,
2019-03-13 22:32:52 +01:00
CreateHttpListener ( ) )
{
GlobalResponse = LocalizationManager . GetLocalizedString ( "StartupEmbyServerIsLoading" )
} ;
2013-04-08 17:55:53 +02:00
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( HttpServer ) ;
2014-03-28 04:32:43 +01:00
2019-08-11 16:52:37 +02:00
ImageProcessor = new ImageProcessor ( LoggerFactory . CreateLogger < ImageProcessor > ( ) , ServerConfigurationManager . ApplicationPaths , FileSystemManager , ImageEncoder , ( ) = > LibraryManager , ( ) = > MediaEncoder ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( ImageProcessor ) ;
2013-09-18 20:49:06 +02:00
2016-07-01 17:51:35 +02:00
TVSeriesManager = new TVSeriesManager ( UserManager , UserDataManager , LibraryManager , ServerConfigurationManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( TVSeriesManager ) ;
2014-12-30 17:36:49 +01:00
2019-02-06 20:38:42 +01:00
DeviceManager = new DeviceManager ( AuthenticationRepository , JsonSerializer , LibraryManager , LocalizationManager , UserManager , FileSystemManager , LibraryMonitor , ServerConfigurationManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( DeviceManager ) ;
2014-10-11 22:38:13 +02:00
2019-02-05 09:49:46 +01:00
MediaSourceManager = new MediaSourceManager ( ItemRepository , ApplicationPaths , LocalizationManager , UserManager , LibraryManager , LoggerFactory , JsonSerializer , FileSystemManager , UserDataManager , ( ) = > MediaEncoder ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( MediaSourceManager ) ;
2018-09-12 19:26:21 +02:00
2019-01-25 23:05:01 +01:00
SubtitleManager = new SubtitleManager ( LoggerFactory , FileSystemManager , LibraryMonitor , MediaSourceManager , LocalizationManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( SubtitleManager ) ;
2018-09-12 19:26:21 +02:00
2018-12-13 14:18:25 +01:00
ProviderManager = new ProviderManager ( HttpClient , SubtitleManager , ServerConfigurationManager , LibraryMonitor , LoggerFactory , FileSystemManager , ApplicationPaths , ( ) = > LibraryManager , JsonSerializer ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( ProviderManager ) ;
2018-09-12 19:26:21 +02:00
2019-02-06 20:38:42 +01:00
DtoService = new DtoService ( LoggerFactory , LibraryManager , UserDataManager , ItemRepository , ImageProcessor , ProviderManager , this , ( ) = > MediaSourceManager , ( ) = > LiveTvManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( DtoService ) ;
2013-12-13 16:48:35 +01:00
2019-03-25 21:27:03 +01:00
ChannelManager = new ChannelManager ( UserManager , DtoService , LibraryManager , LoggerFactory , ServerConfigurationManager , FileSystemManager , UserDataManager , JsonSerializer , ProviderManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( ChannelManager ) ;
2014-03-18 02:45:41 +01:00
2019-03-25 21:27:03 +01:00
SessionManager = new SessionManager ( UserDataManager , LoggerFactory , LibraryManager , UserManager , musicManager , DtoService , ImageProcessor , this , AuthenticationRepository , DeviceManager , MediaSourceManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( SessionManager ) ;
2015-03-08 19:11:53 +01:00
2019-02-12 20:50:47 +01:00
serviceCollection . AddSingleton < IDlnaManager > (
2019-03-01 17:12:22 +01:00
new DlnaManager ( XmlSerializer , FileSystemManager , ApplicationPaths , LoggerFactory , JsonSerializer , this ) ) ;
2014-03-13 20:08:02 +01:00
2019-01-17 23:55:05 +01:00
CollectionManager = new CollectionManager ( LibraryManager , ApplicationPaths , LocalizationManager , FileSystemManager , LibraryMonitor , LoggerFactory , ProviderManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( CollectionManager ) ;
2014-03-07 16:53:23 +01:00
2019-07-07 16:39:35 +02:00
serviceCollection . AddSingleton ( typeof ( IPlaylistManager ) , typeof ( PlaylistManager ) ) ;
2014-08-02 04:34:45 +02:00
2019-02-02 12:19:02 +01:00
LiveTvManager = new LiveTvManager ( this , ServerConfigurationManager , LoggerFactory , ItemRepository , ImageProcessor , UserDataManager , DtoService , UserManager , LibraryManager , TaskManager , LocalizationManager , JsonSerializer , FileSystemManager , ( ) = > ChannelManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( LiveTvManager ) ;
2014-01-12 07:31:21 +01:00
2015-10-05 00:04:56 +02:00
UserViewManager = new UserViewManager ( LibraryManager , LocalizationManager , UserManager , ChannelManager , LiveTvManager , ServerConfigurationManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( UserViewManager ) ;
2014-06-07 21:46:24 +02:00
2018-12-13 14:18:25 +01:00
NotificationManager = new NotificationManager ( LoggerFactory , UserManager , ServerConfigurationManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( NotificationManager ) ;
2014-04-25 22:15:50 +02:00
2019-11-01 21:22:35 +01:00
serviceCollection . AddSingleton < IDeviceDiscovery > ( new DeviceDiscovery ( ServerConfigurationManager ) ) ;
2015-07-23 18:32:34 +02:00
2019-01-17 23:55:05 +01:00
ChapterManager = new ChapterManager ( LibraryManager , LoggerFactory , ServerConfigurationManager , ItemRepository ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( ChapterManager ) ;
2014-06-09 21:16:14 +02:00
2019-02-12 23:05:42 +01:00
MediaEncoder = new MediaBrowser . MediaEncoding . Encoder . MediaEncoder (
LoggerFactory ,
JsonSerializer ,
StartupOptions . FFmpegPath ,
ServerConfigurationManager ,
FileSystemManager ,
( ) = > SubtitleEncoder ,
( ) = > MediaSourceManager ,
ProcessFactory ,
2019-03-16 17:54:57 +01:00
5000 ,
LocalizationManager ) ;
2019-02-08 14:35:26 +01:00
serviceCollection . AddSingleton ( MediaEncoder ) ;
2015-01-02 06:36:27 +01:00
2019-01-17 23:55:05 +01:00
EncodingManager = new MediaEncoder . EncodingManager ( FileSystemManager , LoggerFactory , MediaEncoder , ChapterManager , LibraryManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( EncodingManager ) ;
2014-06-10 19:36:06 +02:00
2019-01-25 21:33:58 +01:00
var activityLogRepo = GetActivityLogRepository ( ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( activityLogRepo ) ;
serviceCollection . AddSingleton < IActivityManager > ( new ActivityManager ( LoggerFactory , activityLogRepo , UserManager ) ) ;
2014-08-11 00:13:17 +02:00
2018-12-28 00:27:57 +01:00
var authContext = new AuthorizationContext ( AuthenticationRepository , UserManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton < IAuthorizationContext > ( authContext ) ;
serviceCollection . AddSingleton < ISessionContext > ( new SessionContext ( UserManager , authContext , SessionManager ) ) ;
2016-11-08 19:44:23 +01:00
2019-07-28 23:53:19 +02:00
AuthService = new AuthService ( authContext , ServerConfigurationManager , SessionManager , NetworkManager ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( AuthService ) ;
2014-07-02 06:57:18 +02:00
2019-01-17 23:55:05 +01:00
SubtitleEncoder = new MediaBrowser . MediaEncoding . Subtitles . SubtitleEncoder ( LibraryManager , LoggerFactory , ApplicationPaths , FileSystemManager , MediaEncoder , JsonSerializer , HttpClient , MediaSourceManager , ProcessFactory ) ;
2019-02-03 17:09:12 +01:00
serviceCollection . AddSingleton ( SubtitleEncoder ) ;
2016-06-04 07:51:33 +02:00
2019-06-10 00:53:16 +02:00
serviceCollection . AddSingleton ( typeof ( IResourceFileManager ) , typeof ( ResourceFileManager ) ) ;
2018-09-12 19:26:21 +02:00
2019-08-14 20:35:36 +02:00
_displayPreferencesRepository . Initialize ( ) ;
2016-06-24 08:32:51 +02:00
2019-09-25 13:24:39 +02:00
var userDataRepo = new SqliteUserDataRepository ( LoggerFactory . CreateLogger < SqliteUserDataRepository > ( ) , ApplicationPaths ) ;
2016-06-24 08:32:51 +02:00
2018-09-12 19:26:21 +02:00
SetStaticProperties ( ) ;
( ( UserManager ) UserManager ) . Initialize ( ) ;
2016-06-24 08:32:51 +02:00
( ( UserDataManager ) UserDataManager ) . Repository = userDataRepo ;
2019-01-26 18:27:57 +01:00
ItemRepository . Initialize ( userDataRepo , UserManager ) ;
2016-05-01 23:48:37 +02:00
( ( LibraryManager ) LibraryManager ) . ItemRepository = ItemRepository ;
2019-02-03 17:09:12 +01:00
_serviceProvider = serviceCollection . BuildServiceProvider ( ) ;
2018-09-12 19:26:21 +02:00
}
2013-04-08 17:55:53 +02:00
2019-03-07 17:39:40 +01:00
public static void LogEnvironmentInfo ( ILogger logger , IApplicationPaths appPaths )
2017-08-16 08:43:41 +02:00
{
2018-09-12 19:26:21 +02:00
// Distinct these to prevent users from reporting problems that aren't actually problems
var commandLineArgs = Environment
. GetCommandLineArgs ( )
2019-01-01 18:41:02 +01:00
. Distinct ( ) ;
logger . LogInformation ( "Arguments: {Args}" , commandLineArgs ) ;
2019-03-26 19:20:40 +01:00
logger . LogInformation ( "Operating system: {OS}" , OperatingSystem . Name ) ;
2019-03-07 17:39:40 +01:00
logger . LogInformation ( "Architecture: {Architecture}" , RuntimeInformation . OSArchitecture ) ;
2019-01-01 18:51:55 +01:00
logger . LogInformation ( "64-Bit Process: {Is64Bit}" , Environment . Is64BitProcess ) ;
logger . LogInformation ( "User Interactive: {IsUserInteractive}" , Environment . UserInteractive ) ;
logger . LogInformation ( "Processor count: {ProcessorCount}" , Environment . ProcessorCount ) ;
logger . LogInformation ( "Program data path: {ProgramDataPath}" , appPaths . ProgramDataPath ) ;
2019-03-10 22:04:18 +01:00
logger . LogInformation ( "Web resources path: {WebPath}" , appPaths . WebPath ) ;
2019-01-01 18:51:55 +01:00
logger . LogInformation ( "Application directory: {ApplicationPath}" , appPaths . ProgramSystemPath ) ;
2017-08-16 08:43:41 +02:00
}
2019-03-03 08:29:23 +01:00
private X509Certificate2 GetCertificate ( CertificateInfo info )
2016-11-11 04:29:51 +01:00
{
2019-03-03 08:29:23 +01:00
var certificateLocation = info ? . Path ;
2017-05-01 04:22:13 +02:00
2016-11-11 04:29:51 +01:00
if ( string . IsNullOrWhiteSpace ( certificateLocation ) )
{
return null ;
}
try
{
2019-01-26 22:59:53 +01:00
if ( ! File . Exists ( certificateLocation ) )
2016-11-13 22:04:21 +01:00
{
return null ;
}
2017-05-10 21:12:03 +02:00
// Don't use an empty string password
var password = string . IsNullOrWhiteSpace ( info . Password ) ? null : info . Password ;
2019-01-13 21:37:13 +01:00
var localCert = new X509Certificate2 ( certificateLocation , password ) ;
2019-03-13 22:32:52 +01:00
// localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
2016-11-11 18:33:10 +01:00
if ( ! localCert . HasPrivateKey )
2016-11-11 04:29:51 +01:00
{
2019-01-01 18:51:55 +01:00
Logger . LogError ( "No private key included in SSL cert {CertificateLocation}." , certificateLocation ) ;
2016-11-11 04:29:51 +01:00
return null ;
}
2017-09-03 04:42:13 +02:00
return localCert ;
2016-11-11 04:29:51 +01:00
}
catch ( Exception ex )
{
2019-01-01 18:51:55 +01:00
Logger . LogError ( ex , "Error loading cert from {CertificateLocation}" , certificateLocation ) ;
2016-11-11 04:29:51 +01:00
return null ;
}
}
2013-10-01 00:18:44 +02:00
/// <summary>
/// Gets the user repository.
/// </summary>
2019-08-14 20:24:44 +02:00
/// <returns><see cref="Task{SqliteUserRepository}" />.</returns>
private SqliteUserRepository GetUserRepository ( )
2013-08-10 02:46:34 +02:00
{
2019-08-14 20:35:36 +02:00
var repo = new SqliteUserRepository (
LoggerFactory . CreateLogger < SqliteUserRepository > ( ) ,
2019-09-25 17:43:20 +02:00
ApplicationPaths ) ;
2013-08-10 02:46:34 +02:00
2016-11-18 19:28:45 +01:00
repo . Initialize ( ) ;
2013-08-18 21:44:38 +02:00
2016-10-07 17:08:13 +02:00
return repo ;
2014-01-20 17:09:53 +01:00
}
2017-05-26 08:48:54 +02:00
private IAuthenticationRepository GetAuthenticationRepository ( )
2014-07-08 03:41:03 +02:00
{
2019-01-17 23:55:05 +01:00
var repo = new AuthenticationRepository ( LoggerFactory , ServerConfigurationManager ) ;
2014-07-08 03:41:03 +02:00
2016-11-18 10:28:39 +01:00
repo . Initialize ( ) ;
2014-07-08 03:41:03 +02:00
return repo ;
}
2019-01-25 21:33:58 +01:00
private IActivityRepository GetActivityLogRepository ( )
2014-08-11 00:13:17 +02:00
{
2019-01-25 21:33:58 +01:00
var repo = new ActivityRepository ( LoggerFactory , ServerConfigurationManager . ApplicationPaths , FileSystemManager ) ;
2019-01-14 18:28:29 +01:00
2019-01-25 21:33:58 +01:00
repo . Initialize ( ) ;
2019-01-14 18:28:29 +01:00
return repo ;
2014-08-11 00:13:17 +02:00
}
2013-03-08 06:08:27 +01:00
/// <summary>
/// Dirty hacks
/// </summary>
private void SetStaticProperties ( )
{
2019-03-03 08:29:23 +01:00
ItemRepository . ImageProcessor = ImageProcessor ;
2018-09-12 19:26:21 +02:00
2013-03-08 06:08:27 +01:00
// For now there's no real way to inject these properly
2018-12-13 14:18:25 +01:00
BaseItem . Logger = LoggerFactory . CreateLogger ( "BaseItem" ) ;
2013-03-08 06:08:27 +01:00
BaseItem . ConfigurationManager = ServerConfigurationManager ;
BaseItem . LibraryManager = LibraryManager ;
BaseItem . ProviderManager = ProviderManager ;
2013-06-10 19:46:11 +02:00
BaseItem . LocalizationManager = LocalizationManager ;
2013-06-20 18:44:24 +02:00
BaseItem . ItemRepository = ItemRepository ;
2013-03-08 06:08:27 +01:00
User . UserManager = UserManager ;
2013-10-30 16:07:30 +01:00
BaseItem . FileSystem = FileSystemManager ;
2014-01-16 18:23:30 +01:00
BaseItem . UserDataManager = UserDataManager ;
2014-09-01 22:10:54 +02:00
BaseItem . ChannelManager = ChannelManager ;
2018-09-12 19:26:21 +02:00
Video . LiveTvManager = LiveTvManager ;
2014-09-01 22:10:54 +02:00
Folder . UserViewManager = UserViewManager ;
UserView . TVSeriesManager = TVSeriesManager ;
2018-09-12 19:26:21 +02:00
UserView . CollectionManager = CollectionManager ;
2015-02-07 22:03:09 +01:00
BaseItem . MediaSourceManager = MediaSourceManager ;
2016-08-13 07:49:00 +02:00
CollectionFolder . XmlSerializer = XmlSerializer ;
2018-09-12 19:26:21 +02:00
CollectionFolder . JsonSerializer = JsonSerializer ;
CollectionFolder . ApplicationHost = this ;
2016-11-08 19:44:23 +01:00
AuthenticatedAttribute . AuthService = AuthService ;
2019-02-18 22:47:02 +01:00
}
private async void PluginInstalled ( object sender , GenericEventArgs < PackageVersionInfo > args )
{
2019-04-04 01:43:02 +02:00
string dir = Path . Combine ( ApplicationPaths . PluginsPath , args . Argument . name ) ;
2019-04-03 00:19:19 +02:00
var types = Directory . EnumerateFiles ( dir , "*.dll" , SearchOption . AllDirectories )
2019-02-18 22:47:02 +01:00
. Select ( x = > Assembly . LoadFrom ( x ) )
. SelectMany ( x = > x . ExportedTypes )
. Where ( x = > x . IsClass & & ! x . IsAbstract & & ! x . IsInterface & & ! x . IsGenericType )
2019-08-29 23:11:55 +02:00
. ToArray ( ) ;
2019-02-18 22:47:02 +01:00
2019-08-29 23:11:55 +02:00
int oldLen = _allConcreteTypes . Length ;
Array . Resize ( ref _allConcreteTypes , oldLen + types . Length ) ;
types . CopyTo ( _allConcreteTypes , oldLen ) ;
2019-02-18 22:47:02 +01:00
var plugins = types . Where ( x = > x . IsAssignableFrom ( typeof ( IPlugin ) ) )
. Select ( CreateInstanceSafe )
. Where ( x = > x ! = null )
. Cast < IPlugin > ( )
. Select ( LoadPlugin )
. Where ( x = > x ! = null )
. ToArray ( ) ;
2019-08-29 23:11:55 +02:00
oldLen = _plugins . Length ;
Array . Resize ( ref _plugins , oldLen + plugins . Length ) ;
2019-02-18 22:47:02 +01:00
plugins . CopyTo ( _plugins , oldLen ) ;
var entries = types . Where ( x = > x . IsAssignableFrom ( typeof ( IServerEntryPoint ) ) )
. Select ( CreateInstanceSafe )
. Where ( x = > x ! = null )
. Cast < IServerEntryPoint > ( )
. ToList ( ) ;
2019-08-09 23:16:24 +02:00
await Task . WhenAll ( StartEntryPoints ( entries , true ) ) . ConfigureAwait ( false ) ;
await Task . WhenAll ( StartEntryPoints ( entries , false ) ) . ConfigureAwait ( false ) ;
2013-02-24 22:53:54 +01:00
}
2013-03-01 22:22:34 +01:00
/// <summary>
/// Finds the parts.
/// </summary>
2017-08-16 08:43:41 +02:00
protected void FindParts ( )
2013-03-01 22:22:34 +01:00
{
2019-03-25 22:25:32 +01:00
InstallationManager = _serviceProvider . GetService < IInstallationManager > ( ) ;
2019-03-28 19:11:05 +01:00
InstallationManager . PluginInstalled + = PluginInstalled ;
2019-03-25 22:25:32 +01:00
2016-10-10 20:18:28 +02:00
if ( ! ServerConfigurationManager . Configuration . IsPortAuthorized )
2013-03-27 23:13:46 +01:00
{
2015-01-12 06:07:19 +01:00
ServerConfigurationManager . Configuration . IsPortAuthorized = true ;
ConfigurationManager . SaveConfiguration ( ) ;
2013-03-27 23:13:46 +01:00
}
2017-08-16 08:43:41 +02:00
ConfigurationManager . AddParts ( GetExports < IConfigurationFactory > ( ) ) ;
2019-02-06 14:04:32 +01:00
Plugins = GetExports < IPlugin > ( )
. Select ( LoadPlugin )
. Where ( i = > i ! = null )
. ToArray ( ) ;
2013-03-15 05:23:07 +01:00
2019-03-07 22:49:41 +01:00
HttpServer . Init ( GetExports < IService > ( false ) , GetExports < IWebSocketListener > ( ) , GetUrlPrefixes ( ) ) ;
2013-03-08 06:08:27 +01:00
2019-03-13 22:32:52 +01:00
LibraryManager . AddParts (
GetExports < IResolverIgnoreRule > ( ) ,
2017-08-17 22:19:02 +02:00
GetExports < IItemResolver > ( ) ,
GetExports < IIntroProvider > ( ) ,
GetExports < IBaseItemComparer > ( ) ,
GetExports < ILibraryPostScanTask > ( ) ) ;
2013-06-25 03:22:21 +02:00
2019-03-13 22:32:52 +01:00
ProviderManager . AddParts (
GetExports < IImageProvider > ( ) ,
2017-08-17 22:19:02 +02:00
GetExports < IMetadataService > ( ) ,
GetExports < IMetadataProvider > ( ) ,
GetExports < IMetadataSaver > ( ) ,
GetExports < IExternalId > ( ) ) ;
2013-08-10 03:40:52 +02:00
2019-08-11 16:52:37 +02:00
ImageProcessor . ImageEnhancers = GetExports < IImageEnhancer > ( ) ;
2013-09-26 18:17:36 +02:00
2015-07-23 15:23:22 +02:00
LiveTvManager . AddParts ( GetExports < ILiveTvService > ( ) , GetExports < ITunerHost > ( ) , GetExports < IListingsProvider > ( ) ) ;
2013-12-25 15:39:46 +01:00
2014-05-07 04:28:19 +02:00
SubtitleManager . AddParts ( GetExports < ISubtitleProvider > ( ) ) ;
2014-06-11 16:42:03 +02:00
2015-09-16 05:55:26 +02:00
ChannelManager . AddParts ( GetExports < IChannel > ( ) ) ;
2014-04-25 22:15:50 +02:00
2015-03-07 23:43:53 +01:00
MediaSourceManager . AddParts ( GetExports < IMediaSourceProvider > ( ) ) ;
2015-04-04 02:41:16 +02:00
2014-04-27 05:42:05 +02:00
NotificationManager . AddParts ( GetExports < INotificationService > ( ) , GetExports < INotificationTypeFactory > ( ) ) ;
2019-03-22 08:01:23 +01:00
UserManager . AddParts ( GetExports < IAuthenticationProvider > ( ) , GetExports < IPasswordResetProvider > ( ) ) ;
2018-09-12 19:26:21 +02:00
IsoManager . AddParts ( GetExports < IIsoMounter > ( ) ) ;
2013-03-01 22:22:34 +01:00
}
2019-02-06 14:04:32 +01:00
private IPlugin LoadPlugin ( IPlugin plugin )
2017-08-16 08:43:41 +02:00
{
try
{
2019-02-06 14:04:32 +01:00
if ( plugin is IPluginAssembly assemblyPlugin )
2017-08-16 08:43:41 +02:00
{
var assembly = plugin . GetType ( ) . Assembly ;
var assemblyName = assembly . GetName ( ) ;
2019-02-06 14:04:32 +01:00
var assemblyFilePath = assembly . Location ;
2017-08-16 08:43:41 +02:00
2018-09-12 19:26:21 +02:00
var dataFolderPath = Path . Combine ( ApplicationPaths . PluginsPath , Path . GetFileNameWithoutExtension ( assemblyFilePath ) ) ;
2017-08-16 08:43:41 +02:00
2018-09-12 19:26:21 +02:00
assemblyPlugin . SetAttributes ( assemblyFilePath , dataFolderPath , assemblyName . Version ) ;
2017-08-28 18:41:32 +02:00
try
{
var idAttributes = assembly . GetCustomAttributes ( typeof ( GuidAttribute ) , true ) ;
if ( idAttributes . Length > 0 )
{
var attribute = ( GuidAttribute ) idAttributes [ 0 ] ;
var assemblyId = new Guid ( attribute . Value ) ;
assemblyPlugin . SetId ( assemblyId ) ;
}
}
catch ( Exception ex )
{
2019-01-03 21:25:39 +01:00
Logger . LogError ( ex , "Error getting plugin Id from {PluginName}." , plugin . GetType ( ) . FullName ) ;
2017-08-28 18:41:32 +02:00
}
2017-08-16 08:43:41 +02:00
}
2019-01-03 21:25:39 +01:00
if ( plugin is IHasPluginConfiguration hasPluginConfiguration )
2018-09-12 19:26:21 +02:00
{
hasPluginConfiguration . SetStartupInfo ( s = > Directory . CreateDirectory ( s ) ) ;
}
2017-08-16 08:43:41 +02:00
}
catch ( Exception ex )
{
2019-04-20 12:18:44 +02:00
Logger . LogError ( ex , "Error loading plugin {PluginName}" , plugin . GetType ( ) . FullName ) ;
2017-08-16 08:43:41 +02:00
return null ;
}
return plugin ;
}
/// <summary>
/// Discovers the types.
/// </summary>
protected void DiscoverTypes ( )
{
2018-12-13 14:18:25 +01:00
Logger . LogInformation ( "Loading assemblies" ) ;
2017-08-16 08:43:41 +02:00
2019-08-29 23:11:55 +02:00
_allConcreteTypes = GetTypes ( GetComposablePartAssemblies ( ) ) . ToArray ( ) ;
2019-04-20 14:02:00 +02:00
}
private IEnumerable < Type > GetTypes ( IEnumerable < Assembly > assemblies )
{
foreach ( var ass in assemblies )
{
Type [ ] exportedTypes ;
try
{
exportedTypes = ass . GetExportedTypes ( ) ;
}
catch ( TypeLoadException ex )
{
Logger . LogError ( ex , "Error getting exported types from {Assembly}" , ass . FullName ) ;
continue ;
}
foreach ( Type type in exportedTypes )
{
if ( type . IsClass & & ! type . IsAbstract & & ! type . IsInterface & & ! type . IsGenericType )
{
yield return type ;
}
}
}
2017-08-16 08:43:41 +02:00
}
2017-05-01 04:22:13 +02:00
private CertificateInfo CertificateInfo { get ; set ; }
2019-03-13 22:32:52 +01:00
2019-03-03 08:29:23 +01:00
protected X509Certificate2 Certificate { get ; private set ; }
2015-01-19 07:42:31 +01:00
2015-01-19 05:29:57 +01:00
private IEnumerable < string > GetUrlPrefixes ( )
{
2018-09-12 19:26:21 +02:00
var hosts = new [ ] { "+" } ;
2015-01-19 05:29:57 +01:00
2016-06-07 18:21:46 +02:00
return hosts . SelectMany ( i = >
{
var prefixes = new List < string >
{
2019-03-13 22:32:52 +01:00
"http://" + i + ":" + HttpPort + "/"
2016-06-07 18:21:46 +02:00
} ;
2017-05-01 04:22:13 +02:00
if ( CertificateInfo ! = null )
2016-06-07 18:21:46 +02:00
{
2016-09-21 20:28:33 +02:00
prefixes . Add ( "https://" + i + ":" + HttpsPort + "/" ) ;
2016-06-07 18:21:46 +02:00
}
return prefixes ;
} ) ;
2015-01-19 05:29:57 +01:00
}
2019-02-26 20:22:40 +01:00
protected IHttpListener CreateHttpListener ( ) = > new WebSocketSharpListener ( Logger ) ;
2015-01-19 08:12:01 +01:00
2017-05-01 04:22:13 +02:00
private CertificateInfo GetCertificateInfo ( bool generateCertificate )
2013-05-07 20:49:42 +02:00
{
2019-09-19 21:56:54 +02:00
// Custom cert
2017-05-01 04:22:13 +02:00
return new CertificateInfo
{
2019-09-19 21:56:54 +02:00
Path = ServerConfigurationManager . Configuration . CertificatePath ,
Password = ServerConfigurationManager . Configuration . CertificatePassword
2017-05-01 04:22:13 +02:00
} ;
2013-05-07 20:49:42 +02:00
}
2013-05-07 21:07:51 +02:00
/// <summary>
/// Called when [configuration updated].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
2017-08-16 08:43:41 +02:00
protected void OnConfigurationUpdated ( object sender , EventArgs e )
2013-05-07 21:07:51 +02:00
{
2015-01-19 05:29:57 +01:00
var requiresRestart = false ;
// Don't do anything if these haven't been set yet
if ( HttpPort ! = 0 & & HttpsPort ! = 0 )
{
// Need to restart if ports have changed
if ( ServerConfigurationManager . Configuration . HttpServerPortNumber ! = HttpPort | |
ServerConfigurationManager . Configuration . HttpsPortNumber ! = HttpsPort )
{
2015-02-11 05:05:58 +01:00
if ( ServerConfigurationManager . Configuration . IsPortAuthorized )
{
ServerConfigurationManager . Configuration . IsPortAuthorized = false ;
ServerConfigurationManager . SaveConfiguration ( ) ;
2015-01-19 05:29:57 +01:00
2015-02-11 05:05:58 +01:00
requiresRestart = true ;
}
2015-01-19 05:29:57 +01:00
}
}
if ( ! HttpServer . UrlPrefixes . SequenceEqual ( GetUrlPrefixes ( ) , StringComparer . OrdinalIgnoreCase ) )
2013-05-07 21:07:51 +02:00
{
2015-01-19 05:29:57 +01:00
requiresRestart = true ;
}
2015-01-04 06:55:34 +01:00
2019-03-13 22:32:52 +01:00
var currentCertPath = CertificateInfo ? . Path ;
2017-05-01 04:22:13 +02:00
var newCertInfo = GetCertificateInfo ( false ) ;
2019-03-13 22:32:52 +01:00
var newCertPath = newCertInfo ? . Path ;
2017-05-01 04:22:13 +02:00
if ( ! string . Equals ( currentCertPath , newCertPath , StringComparison . OrdinalIgnoreCase ) )
2015-01-19 07:42:31 +01:00
{
requiresRestart = true ;
}
2015-01-19 05:29:57 +01:00
if ( requiresRestart )
{
2018-12-13 14:18:25 +01:00
Logger . LogInformation ( "App needs to be restarted due to configuration change." ) ;
2016-12-26 18:38:12 +01:00
2013-05-07 21:07:51 +02:00
NotifyPendingRestart ( ) ;
}
}
2017-08-16 08:43:41 +02:00
/// <summary>
/// Notifies that the kernel that a change has been made that requires a restart
/// </summary>
public void NotifyPendingRestart ( )
{
2018-12-13 14:18:25 +01:00
Logger . LogInformation ( "App needs to be restarted." ) ;
2017-08-16 08:43:41 +02:00
var changed = ! HasPendingRestart ;
HasPendingRestart = true ;
if ( changed )
{
EventHelper . QueueEventIfNotNull ( HasPendingRestartChanged , this , EventArgs . Empty , Logger ) ;
}
}
2013-02-24 22:53:54 +01:00
/// <summary>
/// Restarts this instance.
/// </summary>
2017-09-09 20:51:24 +02:00
public void Restart ( )
2013-02-24 22:53:54 +01:00
{
2013-10-07 16:38:31 +02:00
if ( ! CanSelfRestart )
{
2016-08-31 21:17:11 +02:00
throw new PlatformNotSupportedException ( "The server is unable to self-restart. Please restart manually." ) ;
2013-10-07 16:38:31 +02:00
}
2017-09-09 20:51:24 +02:00
if ( IsShuttingDown )
2013-09-05 19:26:03 +02:00
{
2017-09-09 20:51:24 +02:00
return ;
2013-09-05 19:26:03 +02:00
}
2017-09-09 20:51:24 +02:00
IsShuttingDown = true ;
Task . Run ( async ( ) = >
2013-09-05 19:26:03 +02:00
{
2017-09-09 20:51:24 +02:00
try
{
await SessionManager . SendServerRestartNotification ( CancellationToken . None ) . ConfigureAwait ( false ) ;
}
catch ( Exception ex )
{
2018-12-20 13:11:26 +01:00
Logger . LogError ( ex , "Error sending server restart notification" ) ;
2017-09-09 20:51:24 +02:00
}
2013-09-05 19:26:03 +02:00
2018-12-13 14:18:25 +01:00
Logger . LogInformation ( "Calling RestartInternal" ) ;
2014-06-04 18:15:44 +02:00
2017-09-09 20:51:24 +02:00
RestartInternal ( ) ;
} ) ;
2013-02-24 22:53:54 +01:00
}
2016-11-13 05:33:51 +01:00
protected abstract void RestartInternal ( ) ;
2013-02-24 22:53:54 +01:00
/// <summary>
/// Gets the composable part assemblies.
/// </summary>
/// <returns>IEnumerable{Assembly}.</returns>
2019-02-03 17:09:12 +01:00
protected IEnumerable < Assembly > GetComposablePartAssemblies ( )
2013-02-24 22:53:54 +01:00
{
2019-02-03 17:09:12 +01:00
if ( Directory . Exists ( ApplicationPaths . PluginsPath ) )
{
2019-04-03 00:19:19 +02:00
foreach ( var file in Directory . EnumerateFiles ( ApplicationPaths . PluginsPath , "*.dll" , SearchOption . AllDirectories ) )
2019-02-03 17:09:12 +01:00
{
2019-04-20 12:18:44 +02:00
Assembly plugAss ;
try
{
plugAss = Assembly . LoadFrom ( file ) ;
}
2019-04-20 14:02:00 +02:00
catch ( FileLoadException ex )
2019-04-20 12:18:44 +02:00
{
Logger . LogError ( ex , "Failed to load assembly {Path}" , file ) ;
continue ;
}
Logger . LogInformation ( "Loaded assembly {Assembly} from {Path}" , plugAss . FullName , file ) ;
yield return plugAss ;
2019-02-03 17:09:12 +01:00
}
}
2013-09-26 23:20:26 +02:00
2019-01-08 17:29:34 +01:00
// Include composable parts in the Api assembly
2019-02-03 17:09:12 +01:00
yield return typeof ( ApiEntryPoint ) . Assembly ;
2013-02-24 22:53:54 +01:00
2019-01-08 17:29:34 +01:00
// Include composable parts in the Dashboard assembly
2019-02-03 17:09:12 +01:00
yield return typeof ( DashboardService ) . Assembly ;
2013-02-24 22:53:54 +01:00
2019-01-08 17:29:34 +01:00
// Include composable parts in the Model assembly
2019-02-03 17:09:12 +01:00
yield return typeof ( SystemInfo ) . Assembly ;
2013-02-24 22:53:54 +01:00
2019-01-08 17:29:34 +01:00
// Include composable parts in the Common assembly
2019-02-03 17:09:12 +01:00
yield return typeof ( IApplicationHost ) . Assembly ;
2013-02-24 22:53:54 +01:00
2019-01-08 17:29:34 +01:00
// Include composable parts in the Controller assembly
2019-02-03 17:09:12 +01:00
yield return typeof ( IServerApplicationHost ) . Assembly ;
2013-02-24 22:53:54 +01:00
2019-01-08 17:29:34 +01:00
// Include composable parts in the Providers assembly
2019-02-03 17:09:12 +01:00
yield return typeof ( ProviderUtils ) . Assembly ;
2013-06-20 18:44:24 +02:00
2019-01-08 17:29:34 +01:00
// Include composable parts in the Photos assembly
2019-02-03 17:09:12 +01:00
yield return typeof ( PhotoProvider ) . Assembly ;
2016-10-26 20:25:03 +02:00
2016-11-02 21:53:50 +01:00
// Emby.Server implementations
2019-02-03 17:09:12 +01:00
yield return typeof ( InstallationManager ) . Assembly ;
2016-11-02 21:53:50 +01:00
2014-03-27 20:30:21 +01:00
// MediaEncoding
2019-02-03 17:09:12 +01:00
yield return typeof ( MediaBrowser . MediaEncoding . Encoder . MediaEncoder ) . Assembly ;
2014-03-27 20:30:21 +01:00
2019-01-08 17:29:34 +01:00
// Dlna
2019-02-03 17:09:12 +01:00
yield return typeof ( DlnaEntryPoint ) . Assembly ;
2014-02-28 05:49:02 +01:00
2019-01-08 17:29:34 +01:00
// Local metadata
2019-02-03 17:09:12 +01:00
yield return typeof ( BoxSetXmlSaver ) . Assembly ;
2014-06-30 05:04:50 +02:00
2018-09-12 19:26:21 +02:00
// Notifications
2019-02-03 17:09:12 +01:00
yield return typeof ( NotificationManager ) . Assembly ;
2018-09-12 19:26:21 +02:00
2019-01-08 17:29:34 +01:00
// Xbmc
2019-02-03 17:09:12 +01:00
yield return typeof ( ArtistNfoProvider ) . Assembly ;
2013-09-05 19:26:03 +02:00
2019-02-03 17:09:12 +01:00
foreach ( var i in GetAssembliesWithPartsInternal ( ) )
2013-12-29 15:12:29 +01:00
{
2019-02-03 17:09:12 +01:00
yield return i ;
2013-12-29 15:12:29 +01:00
}
}
2019-02-03 17:09:12 +01:00
protected abstract IEnumerable < Assembly > GetAssembliesWithPartsInternal ( ) ;
2016-10-28 05:16:38 +02:00
2013-03-07 06:34:00 +01:00
/// <summary>
/// Gets the system status.
/// </summary>
2019-03-13 22:32:52 +01:00
/// <param name="cancellationToken">The cancellation token</param>
2013-03-07 06:34:00 +01:00
/// <returns>SystemInfo.</returns>
2017-11-23 16:46:16 +01:00
public async Task < SystemInfo > GetSystemInfo ( CancellationToken cancellationToken )
2013-03-07 06:34:00 +01:00
{
2017-11-23 16:46:16 +01:00
var localAddress = await GetLocalApiUrl ( cancellationToken ) . ConfigureAwait ( false ) ;
2019-04-18 13:19:16 +02:00
2013-03-07 06:34:00 +01:00
return new SystemInfo
{
HasPendingRestart = HasPendingRestart ,
2017-09-09 20:51:24 +02:00
IsShuttingDown = IsShuttingDown ,
2019-10-08 20:51:11 +02:00
Version = ApplicationVersionString ,
2015-01-19 05:29:57 +01:00
WebSocketPortNumber = HttpPort ,
2017-08-19 21:43:35 +02:00
CompletedInstallations = InstallationManager . CompletedInstallations . ToArray ( ) ,
2014-09-06 19:46:09 +02:00
Id = SystemId ,
2013-08-16 16:18:09 +02:00
ProgramDataPath = ApplicationPaths . ProgramDataPath ,
2019-03-10 22:04:18 +01:00
WebPath = ApplicationPaths . WebPath ,
2013-11-30 19:32:39 +01:00
LogPath = ApplicationPaths . LogDirectoryPath ,
2018-09-12 19:26:21 +02:00
ItemsByNamePath = ApplicationPaths . InternalMetadataPath ,
2014-03-31 23:04:22 +02:00
InternalMetadataPath = ApplicationPaths . InternalMetadataPath ,
2013-12-15 02:17:57 +01:00
CachePath = ApplicationPaths . CachePath ,
2015-01-19 05:29:57 +01:00
HttpServerPortNumber = HttpPort ,
2015-01-19 22:08:58 +01:00
SupportsHttps = SupportsHttps ,
2015-01-19 05:29:57 +01:00
HttpsPortNumber = HttpsPort ,
2019-03-07 17:39:40 +01:00
OperatingSystem = OperatingSystem . Id . ToString ( ) ,
OperatingSystemDisplayName = OperatingSystem . Name ,
2013-10-07 18:22:19 +02:00
CanSelfRestart = CanSelfRestart ,
2017-12-03 23:14:35 +01:00
CanLaunchWebBrowser = CanLaunchWebBrowser ,
2014-04-26 04:55:07 +02:00
HasUpdateAvailable = HasUpdateAvailable ,
2014-01-30 01:18:05 +01:00
TranscodingTempPath = ApplicationPaths . TranscodingTempPath ,
2014-08-20 00:28:35 +02:00
ServerName = FriendlyName ,
2016-06-19 18:53:43 +02:00
LocalAddress = localAddress ,
2016-11-11 09:13:11 +01:00
SupportsLibraryMonitor = true ,
2019-02-12 23:05:42 +01:00
EncoderLocation = MediaEncoder . EncoderLocation ,
2019-03-07 17:39:40 +01:00
SystemArchitecture = RuntimeInformation . OSArchitecture ,
2017-04-10 03:51:36 +02:00
SystemUpdateLevel = SystemUpdateLevel ,
2019-01-28 14:41:37 +01:00
PackageName = StartupOptions . PackageName
2013-03-07 06:34:00 +01:00
} ;
}
2019-08-09 23:16:24 +02:00
public IEnumerable < WakeOnLanInfo > GetWakeOnLanInfo ( )
= > NetworkManager . GetMacAddresses ( )
. Select ( i = > new WakeOnLanInfo ( i ) )
. ToList ( ) ;
2018-09-12 19:26:21 +02:00
2017-12-01 18:03:40 +01:00
public async Task < PublicSystemInfo > GetPublicSystemInfo ( CancellationToken cancellationToken )
{
2019-04-18 13:19:16 +02:00
var localAddress = await GetLocalApiUrl ( cancellationToken ) . ConfigureAwait ( false ) ;
2017-12-01 18:03:40 +01:00
return new PublicSystemInfo
{
2019-10-08 20:51:11 +02:00
Version = ApplicationVersionString ,
2019-04-16 07:16:02 +02:00
ProductName = ApplicationProductName ,
2017-12-01 18:03:40 +01:00
Id = SystemId ,
2019-03-07 17:39:40 +01:00
OperatingSystem = OperatingSystem . Id . ToString ( ) ,
2017-12-01 18:03:40 +01:00
ServerName = FriendlyName ,
LocalAddress = localAddress
} ;
}
2019-01-06 21:50:43 +01:00
public bool EnableHttps = > SupportsHttps & & ServerConfigurationManager . Configuration . EnableHttps ;
2015-01-19 05:29:57 +01:00
2019-01-06 21:50:43 +01:00
public bool SupportsHttps = > Certificate ! = null | | ServerConfigurationManager . Configuration . IsBehindProxy ;
2015-01-19 05:29:57 +01:00
2017-11-23 16:46:16 +01:00
public async Task < string > GetLocalApiUrl ( CancellationToken cancellationToken )
2014-08-20 00:28:35 +02:00
{
2016-06-19 08:18:29 +02:00
try
2014-08-20 00:28:35 +02:00
{
2016-06-19 08:18:29 +02:00
// Return the first matched address, if found, or the first known local address
2017-11-29 21:50:18 +01:00
var addresses = await GetLocalIpAddressesInternal ( false , 1 , cancellationToken ) . ConfigureAwait ( false ) ;
2015-01-24 20:03:55 +01:00
2017-11-29 21:50:18 +01:00
foreach ( var address in addresses )
2015-01-24 20:03:55 +01:00
{
2016-06-19 08:18:29 +02:00
return GetLocalApiUrl ( address ) ;
2015-01-24 20:03:55 +01:00
}
2015-08-10 19:37:50 +02:00
return null ;
2014-08-20 00:28:35 +02:00
}
2016-06-19 08:18:29 +02:00
catch ( Exception ex )
{
2018-12-20 13:11:26 +01:00
Logger . LogError ( ex , "Error getting local Ip address information" ) ;
2016-06-19 08:18:29 +02:00
}
return null ;
2015-01-24 20:03:55 +01:00
}
2014-08-20 00:28:35 +02:00
2019-07-25 00:23:56 +02:00
/// <summary>
/// Removes the scope id from IPv6 addresses.
/// </summary>
/// <param name="address">The IPv6 address.</param>
/// <returns>The IPv6 address without the scope id.</returns>
private string RemoveScopeId ( string address )
{
var index = address . IndexOf ( '%' ) ;
if ( index = = - 1 )
{
return address ;
}
return address . Substring ( 0 , index ) ;
}
2019-07-07 21:03:26 +02:00
public string GetLocalApiUrl ( IPAddress ipAddress )
2016-10-26 03:57:58 +02:00
{
2019-07-07 21:03:26 +02:00
if ( ipAddress . AddressFamily = = AddressFamily . InterNetworkV6 )
2016-03-09 18:40:29 +01:00
{
2019-07-25 00:23:56 +02:00
var str = RemoveScopeId ( ipAddress . ToString ( ) ) ;
2019-07-07 21:03:26 +02:00
return GetLocalApiUrl ( "[" + str + "]" ) ;
2016-03-09 18:40:29 +01:00
}
2019-07-07 21:03:26 +02:00
return GetLocalApiUrl ( ipAddress . ToString ( ) ) ;
2016-03-09 18:40:29 +01:00
}
2015-02-10 06:54:58 +01:00
public string GetLocalApiUrl ( string host )
{
2019-03-24 11:59:40 +01:00
if ( EnableHttps )
{
2019-03-24 16:47:48 +01:00
return string . Format ( "https://{0}:{1}" ,
2019-03-24 11:59:40 +01:00
host ,
HttpsPort . ToString ( CultureInfo . InvariantCulture ) ) ;
}
2019-07-07 21:03:26 +02:00
2015-02-10 06:54:58 +01:00
return string . Format ( "http://{0}:{1}" ,
2019-03-24 11:59:40 +01:00
host ,
2019-03-25 21:34:55 +01:00
HttpPort . ToString ( CultureInfo . InvariantCulture ) ) ;
2015-02-10 06:54:58 +01:00
}
2019-07-07 21:03:26 +02:00
public Task < List < IPAddress > > GetLocalIpAddresses ( CancellationToken cancellationToken )
2017-11-29 21:50:18 +01:00
{
return GetLocalIpAddressesInternal ( true , 0 , cancellationToken ) ;
}
2019-07-07 21:03:26 +02:00
private async Task < List < IPAddress > > GetLocalIpAddressesInternal ( bool allowLoopback , int limit , CancellationToken cancellationToken )
2016-10-26 03:57:58 +02:00
{
2016-12-07 21:02:34 +01:00
var addresses = ServerConfigurationManager
. Configuration
. LocalNetworkAddresses
. Select ( NormalizeConfiguredLocalAddress )
. Where ( i = > i ! = null )
. ToList ( ) ;
2015-12-29 04:39:38 +01:00
2016-12-07 21:02:34 +01:00
if ( addresses . Count = = 0 )
2016-09-12 21:38:38 +02:00
{
2019-02-21 15:35:31 +01:00
addresses . AddRange ( NetworkManager . GetLocalIpAddresses ( ServerConfigurationManager . Configuration . IgnoreVirtualInterfaces ) ) ;
2017-11-29 21:50:18 +01:00
}
2016-12-07 21:02:34 +01:00
2019-07-07 21:03:26 +02:00
var resultList = new List < IPAddress > ( ) ;
2016-12-07 21:02:34 +01:00
2017-11-29 21:50:18 +01:00
foreach ( var address in addresses )
{
if ( ! allowLoopback )
2016-09-12 21:38:38 +02:00
{
2019-07-07 21:03:26 +02:00
if ( address . Equals ( IPAddress . Loopback ) | | address . Equals ( IPAddress . IPv6Loopback ) )
2016-12-07 21:02:34 +01:00
{
2017-11-29 21:50:18 +01:00
continue ;
2016-12-07 21:02:34 +01:00
}
2016-09-12 21:38:38 +02:00
}
2016-12-07 21:02:34 +01:00
2017-11-29 21:50:18 +01:00
var valid = await IsIpAddressValidAsync ( address , cancellationToken ) . ConfigureAwait ( false ) ;
if ( valid )
{
resultList . Add ( address ) ;
if ( limit > 0 & & resultList . Count > = limit )
{
return resultList ;
}
}
2016-09-12 21:38:38 +02:00
}
2017-11-29 21:50:18 +01:00
return resultList ;
2016-12-07 21:02:34 +01:00
}
2019-07-07 21:03:26 +02:00
private IPAddress NormalizeConfiguredLocalAddress ( string address )
2016-12-07 21:02:34 +01:00
{
var index = address . Trim ( '/' ) . IndexOf ( '/' ) ;
if ( index ! = - 1 )
{
address = address . Substring ( index + 1 ) ;
}
2019-07-07 21:03:26 +02:00
if ( IPAddress . TryParse ( address . Trim ( '/' ) , out IPAddress result ) )
2016-12-07 21:02:34 +01:00
{
return result ;
}
2019-03-13 22:32:52 +01:00
2016-12-07 21:02:34 +01:00
return null ;
2014-08-20 00:28:35 +02:00
}
2015-12-29 04:39:38 +01:00
private readonly ConcurrentDictionary < string , bool > _validAddressResults = new ConcurrentDictionary < string , bool > ( StringComparer . OrdinalIgnoreCase ) ;
2019-03-13 22:32:52 +01:00
2019-07-07 21:03:26 +02:00
private async Task < bool > IsIpAddressValidAsync ( IPAddress address , CancellationToken cancellationToken )
2014-09-17 05:04:10 +02:00
{
2019-07-29 23:47:25 +02:00
if ( address . Equals ( IPAddress . Loopback )
| | address . Equals ( IPAddress . IPv6Loopback ) )
2014-09-17 05:04:10 +02:00
{
2015-12-29 04:39:38 +01:00
return true ;
}
2014-09-17 05:04:10 +02:00
2016-03-09 18:40:29 +01:00
var apiUrl = GetLocalApiUrl ( address ) ;
2015-12-29 04:39:38 +01:00
apiUrl + = "/system/ping" ;
2014-09-17 05:04:10 +02:00
2019-01-13 21:48:18 +01:00
if ( _validAddressResults . TryGetValue ( apiUrl , out var cachedResult ) )
2015-12-29 04:39:38 +01:00
{
return cachedResult ;
}
2014-09-17 05:04:10 +02:00
2015-12-29 04:39:38 +01:00
try
{
2019-03-13 22:32:52 +01:00
using ( var response = await HttpClient . SendAsync (
new HttpRequestOptions
{
Url = apiUrl ,
LogErrorResponseBody = false ,
BufferContent = false ,
CancellationToken = cancellationToken
2019-03-08 20:32:14 +01:00
} , HttpMethod . Post ) . ConfigureAwait ( false ) )
2015-12-29 04:39:38 +01:00
{
2015-12-29 20:06:32 +01:00
using ( var reader = new StreamReader ( response . Content ) )
{
2019-03-08 20:32:14 +01:00
var result = await reader . ReadToEndAsync ( ) . ConfigureAwait ( false ) ;
2015-12-29 20:06:32 +01:00
var valid = string . Equals ( Name , result , StringComparison . OrdinalIgnoreCase ) ;
_validAddressResults . AddOrUpdate ( apiUrl , valid , ( k , v ) = > valid ) ;
2018-12-13 14:18:25 +01:00
Logger . LogDebug ( "Ping test result to {0}. Success: {1}" , apiUrl , valid ) ;
2015-12-29 20:06:32 +01:00
return valid ;
}
2015-12-29 04:39:38 +01:00
}
2014-09-17 05:04:10 +02:00
}
2017-11-23 16:46:16 +01:00
catch ( OperationCanceledException )
{
2018-12-13 14:18:25 +01:00
Logger . LogDebug ( "Ping test result to {0}. Success: {1}" , apiUrl , "Cancelled" ) ;
2017-11-23 16:46:16 +01:00
throw ;
}
2018-09-12 19:26:21 +02:00
catch ( Exception ex )
2015-12-29 04:39:38 +01:00
{
2018-12-20 13:39:58 +01:00
Logger . LogDebug ( ex , "Ping test result to {0}. Success: {1}" , apiUrl , false ) ;
2015-12-29 20:06:32 +01:00
_validAddressResults . AddOrUpdate ( apiUrl , false , ( k , v ) = > false ) ;
2015-12-29 04:39:38 +01:00
return false ;
}
}
2019-01-06 21:50:43 +01:00
public string FriendlyName = >
string . IsNullOrEmpty ( ServerConfigurationManager . Configuration . ServerName )
? Environment . MachineName
: ServerConfigurationManager . Configuration . ServerName ;
2014-08-06 01:59:24 +02:00
2015-01-19 05:29:57 +01:00
public int HttpPort { get ; private set ; }
2014-03-17 05:25:11 +01:00
2015-01-19 05:29:57 +01:00
public int HttpsPort { get ; private set ; }
2015-01-07 04:36:42 +01:00
2013-02-26 17:10:55 +01:00
/// <summary>
/// Shuts down.
/// </summary>
2017-08-16 08:43:41 +02:00
public async Task Shutdown ( )
2013-02-26 17:10:55 +01:00
{
2017-09-09 20:51:24 +02:00
if ( IsShuttingDown )
{
return ;
}
IsShuttingDown = true ;
2013-09-05 19:26:03 +02:00
try
{
2013-10-03 20:02:23 +02:00
await SessionManager . SendServerShutdownNotification ( CancellationToken . None ) . ConfigureAwait ( false ) ;
2013-09-05 19:26:03 +02:00
}
catch ( Exception ex )
{
2018-12-20 13:11:26 +01:00
Logger . LogError ( ex , "Error sending server shutdown notification" ) ;
2013-09-05 19:26:03 +02:00
}
2016-11-13 05:33:51 +01:00
ShutdownInternal ( ) ;
2013-04-05 21:34:33 +02:00
}
2016-11-13 05:33:51 +01:00
protected abstract void ShutdownInternal ( ) ;
2014-04-26 04:55:07 +02:00
public event EventHandler HasUpdateAvailableChanged ;
2014-01-05 07:50:48 +01:00
private bool _hasUpdateAvailable ;
2019-03-13 22:32:52 +01:00
2014-04-26 04:55:07 +02:00
public bool HasUpdateAvailable
{
2019-01-06 21:50:43 +01:00
get = > _hasUpdateAvailable ;
2014-04-26 04:55:07 +02:00
set
{
var fireEvent = value & & ! _hasUpdateAvailable ;
_hasUpdateAvailable = value ;
if ( fireEvent )
{
2018-12-28 15:21:02 +01:00
HasUpdateAvailableChanged ? . Invoke ( this , EventArgs . Empty ) ;
2014-04-26 04:55:07 +02:00
}
}
}
2017-08-16 08:43:41 +02:00
/// <summary>
/// Removes the plugin.
/// </summary>
/// <param name="plugin">The plugin.</param>
public void RemovePlugin ( IPlugin plugin )
{
var list = Plugins . ToList ( ) ;
list . Remove ( plugin ) ;
Plugins = list . ToArray ( ) ;
}
2017-08-17 22:19:02 +02:00
2015-01-18 22:44:35 +01:00
/// <summary>
2019-01-08 17:29:34 +01:00
/// This returns localhost in the case of no external dns, and the hostname if the
2015-01-18 22:44:35 +01:00
/// dns is prefixed with a valid Uri prefix.
/// </summary>
/// <param name="externalDns">The external dns prefix to get the hostname of.</param>
2019-11-01 21:22:35 +01:00
/// <returns>The hostname in <paramref name="externalDns"/>.</returns>
2015-01-18 22:44:35 +01:00
private static string GetHostnameFromExternalDns ( string externalDns )
{
2018-09-12 19:26:21 +02:00
if ( string . IsNullOrEmpty ( externalDns ) )
2015-01-18 22:44:35 +01:00
{
return "localhost" ;
}
try
{
2015-01-19 07:42:31 +01:00
return new Uri ( externalDns ) . Host ;
2015-01-18 22:44:35 +01:00
}
2016-08-05 23:15:48 +02:00
catch
2015-01-18 22:44:35 +01:00
{
return externalDns ;
}
}
2016-04-24 05:03:49 +02:00
2017-11-21 23:14:56 +01:00
public virtual void LaunchUrl ( string url )
2016-11-21 00:48:52 +01:00
{
2017-12-03 23:14:35 +01:00
if ( ! CanLaunchWebBrowser )
2017-11-21 23:14:56 +01:00
{
throw new NotSupportedException ( ) ;
2016-11-21 00:48:52 +01:00
}
2016-12-07 21:02:34 +01:00
var process = ProcessFactory . Create ( new ProcessOptions
{
2016-11-21 00:48:52 +01:00
FileName = url ,
2019-03-13 22:32:52 +01:00
EnableRaisingEvents = true ,
2016-11-21 00:48:52 +01:00
UseShellExecute = true ,
ErrorDialog = false
} ) ;
process . Exited + = ProcessExited ;
try
{
process . Start ( ) ;
}
catch ( Exception ex )
{
2018-12-20 13:11:26 +01:00
Logger . LogError ( ex , "Error launching url: {url}" , url ) ;
2016-11-21 00:48:52 +01:00
throw ;
}
}
private static void ProcessExited ( object sender , EventArgs e )
{
( ( IProcess ) sender ) . Dispose ( ) ;
}
2016-09-03 19:16:36 +02:00
2017-03-22 19:37:04 +01:00
public virtual void EnableLoopback ( string appName )
2016-09-03 19:16:36 +02:00
{
2017-02-19 04:46:09 +01:00
}
2016-11-13 05:33:51 +01:00
2019-03-13 22:32:52 +01:00
private bool _disposed = false ;
2017-08-16 08:43:41 +02:00
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose ( )
{
2019-03-13 22:32:52 +01:00
Dispose ( true ) ;
GC . SuppressFinalize ( this ) ;
2017-08-16 08:43:41 +02:00
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose ( bool dispose )
{
2019-03-13 22:32:52 +01:00
if ( _disposed )
{
return ;
}
2017-08-16 08:43:41 +02:00
if ( dispose )
{
var type = GetType ( ) ;
2019-01-03 21:25:39 +01:00
Logger . LogInformation ( "Disposing {Type}" , type . Name ) ;
2017-08-16 08:43:41 +02:00
2019-03-13 22:32:52 +01:00
var parts = _disposableParts . Distinct ( ) . Where ( i = > i . GetType ( ) ! = type ) . ToList ( ) ;
_disposableParts . Clear ( ) ;
2017-08-16 08:43:41 +02:00
foreach ( var part in parts )
{
2019-01-03 21:25:39 +01:00
Logger . LogInformation ( "Disposing {Type}" , part . GetType ( ) . Name ) ;
2017-08-16 08:43:41 +02:00
try
{
part . Dispose ( ) ;
}
catch ( Exception ex )
{
2019-01-03 21:25:39 +01:00
Logger . LogError ( ex , "Error disposing {Type}" , part . GetType ( ) . Name ) ;
2017-08-16 08:43:41 +02:00
}
}
2019-04-03 14:22:17 +02:00
2019-08-14 20:24:44 +02:00
_userRepository ? . Dispose ( ) ;
2019-08-14 20:35:36 +02:00
_displayPreferencesRepository . Dispose ( ) ;
2017-08-16 08:43:41 +02:00
}
2019-03-13 22:32:52 +01:00
2019-08-14 20:35:36 +02:00
_userRepository = null ;
_displayPreferencesRepository = null ;
2019-03-13 22:32:52 +01:00
_disposed = true ;
2017-08-16 08:43:41 +02:00
}
2017-05-01 04:22:13 +02:00
}
2016-10-29 06:10:11 +02:00
2017-05-01 04:22:13 +02:00
internal class CertificateInfo
{
public string Path { get ; set ; }
public string Password { get ; set ; }
2013-02-24 22:53:54 +01:00
}
}