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