using MediaBrowser.Common.Implementations.IO; using MediaBrowser.Common.Implementations.Logging; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations; using MediaBrowser.Server.Mono.Native; using MediaBrowser.Server.Startup.Common; using Microsoft.Win32; using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Reflection; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Server.Implementations.Logging; namespace MediaBrowser.Server.Mono { public class MainClass { private static ApplicationHost _appHost; private static ILogger _logger; public static void Main(string[] args) { var applicationPath = Assembly.GetEntryAssembly().Location; var options = new StartupOptions(); // Allow this to be specified on the command line. var customProgramDataPath = options.GetOption("-programdata"); var appPaths = CreateApplicationPaths(applicationPath, customProgramDataPath); var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); logManager.ReloadLogger(LogSeverity.Info); logManager.AddConsoleOutput(); var logger = _logger = logManager.GetLogger("Main"); ApplicationHost.LogEnvironmentInfo(logger, appPaths, true); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; try { RunApplication(appPaths, logManager, options); } finally { logger.Info("Shutting down"); _appHost.Dispose(); } } private static ServerApplicationPaths CreateApplicationPaths(string applicationPath, string programDataPath) { if (string.IsNullOrEmpty(programDataPath)) { programDataPath = ApplicationPathHelper.GetProgramDataPath(applicationPath); } return new ServerApplicationPaths(programDataPath, applicationPath, Path.GetDirectoryName(applicationPath)); } private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, StartupOptions options) { SystemEvents.SessionEnding += SystemEvents_SessionEnding; // Allow all https requests ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); var fileSystem = new ManagedFileSystem(new PatternsLogger(logManager.GetLogger("FileSystem")), false, true); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); var nativeApp = new NativeApp(options); _appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "MBServer.Mono", nativeApp); if (options.ContainsOption("-v")) { Console.WriteLine(_appHost.ApplicationVersion.ToString()); return; } Console.WriteLine("appHost.Init"); var initProgress = new Progress(); var task = _appHost.Init(initProgress); Task.WaitAll(task); Console.WriteLine("Running startup tasks"); task = _appHost.RunStartupTasks(); Task.WaitAll(task); task = ApplicationTaskCompletionSource.Task; Task.WaitAll(task); } /// /// Handles the SessionEnding event of the SystemEvents control. /// /// The source of the event. /// The instance containing the event data. static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) { if (e.Reason == SessionEndReasons.SystemShutdown) { Shutdown(); } } /// /// Handles the UnhandledException event of the CurrentDomain control. /// /// The source of the event. /// The instance containing the event data. static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var exception = (Exception)e.ExceptionObject; new UnhandledExceptionWriter(_appHost.ServerConfigurationManager.ApplicationPaths, _logger, _appHost.LogManager).Log(exception); if (!Debugger.IsAttached) { Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(exception)); } } public static void Shutdown() { ApplicationTaskCompletionSource.SetResult(true); } public static void Restart(StartupOptions startupOptions) { _logger.Info("Disposing app host"); _appHost.Dispose(); _logger.Info("Starting new instance"); string module = startupOptions.GetOption("-restartpath"); string commandLineArgsString = startupOptions.GetOption("-restartargs") ?? string.Empty; if (string.IsNullOrWhiteSpace(module)) { module = Environment.GetCommandLineArgs().First(); } if (!startupOptions.ContainsOption("-restartargs")) { var args = Environment.GetCommandLineArgs() .Skip(1) .Select(NormalizeCommandLineArgument); commandLineArgsString = string.Join(" ", args.ToArray()); } _logger.Info("Executable: {0}", module); _logger.Info("Arguments: {0}", commandLineArgsString); Process.Start(module, commandLineArgsString); _logger.Info("Calling Environment.Exit"); Environment.Exit(0); } private static string NormalizeCommandLineArgument(string arg) { if (arg.IndexOf(" ", StringComparison.OrdinalIgnoreCase) == -1) { return arg; } return "\"" + arg + "\""; } } class NoCheckCertificatePolicy : ICertificatePolicy { public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } }