2018-06-17 02:39:03 +00:00
using CommandLine ;
2018-05-01 12:00:02 +00:00
using CommandLine.Text ;
using Jackett.Common.Models.Config ;
2018-06-17 02:39:03 +00:00
using Jackett.Common.Services ;
2018-05-20 11:21:08 +00:00
using Jackett.Common.Services.Interfaces ;
2018-05-01 12:00:02 +00:00
using Jackett.Common.Utils ;
2018-05-01 11:13:20 +00:00
using Microsoft.AspNetCore ;
using Microsoft.AspNetCore.Hosting ;
using Microsoft.Extensions.Configuration ;
2018-05-20 11:21:08 +00:00
using NLog ;
2018-05-01 12:00:02 +00:00
using System ;
using System.Collections.Generic ;
2018-06-17 02:39:03 +00:00
using System.Diagnostics ;
2018-05-30 11:43:58 +00:00
using System.IO ;
2018-05-01 12:00:02 +00:00
using System.Linq ;
2018-05-20 11:21:08 +00:00
using System.Runtime.InteropServices ;
2018-05-01 11:13:20 +00:00
namespace Jackett.Server
{
2018-06-03 11:11:18 +00:00
public static class Program
2018-05-01 11:13:20 +00:00
{
2018-05-01 12:00:02 +00:00
public static IConfiguration Configuration { get ; set ; }
2018-06-03 11:11:18 +00:00
private static RuntimeSettings Settings { get ; set ; }
2018-06-10 02:33:16 +00:00
public static bool isWebHostRestart = false ;
2018-06-03 11:11:18 +00:00
2018-05-01 11:13:20 +00:00
public static void Main ( string [ ] args )
{
2018-06-03 11:11:18 +00:00
AppDomain . CurrentDomain . ProcessExit + = CurrentDomain_ProcessExit ;
2018-06-17 04:12:52 +00:00
var commandLineParser = new Parser ( settings = > settings . CaseSensitive = false ) ;
2018-06-10 02:33:16 +00:00
var optionsResult = commandLineParser . ParseArguments < ConsoleOptions > ( args ) ;
var runtimeDictionary = new Dictionary < string , string > ( ) ;
ConsoleOptions consoleOptions = new ConsoleOptions ( ) ;
2018-06-03 11:11:18 +00:00
2018-05-01 12:00:02 +00:00
optionsResult . WithNotParsed ( errors = >
{
var text = HelpText . AutoBuild ( optionsResult ) ;
text . Copyright = " " ;
2018-06-03 11:11:18 +00:00
text . Heading = "Jackett v" + EnvironmentUtil . JackettVersion ;
Console . WriteLine ( text ) ;
2018-05-20 11:21:08 +00:00
Environment . Exit ( 1 ) ;
2018-05-01 12:00:02 +00:00
return ;
} ) ;
optionsResult . WithParsed ( options = >
{
2018-06-03 11:11:18 +00:00
if ( string . IsNullOrEmpty ( options . Client ) )
{
//TODO: Remove libcurl once off owin
options . Client = "httpclient" ;
}
Settings = options . ToRunTimeSettings ( ) ;
2018-05-20 11:21:08 +00:00
consoleOptions = options ;
2018-06-10 02:33:16 +00:00
runtimeDictionary = GetValues ( Settings ) ;
2018-05-01 12:00:02 +00:00
} ) ;
2018-06-16 08:32:08 +00:00
LogManager . Configuration = Initialisation . SetupLogging ( Settings ) ;
Logger logger = LogManager . GetCurrentClassLogger ( ) ;
logger . Info ( "Starting Jackett v" + EnvironmentUtil . JackettVersion ) ;
2018-06-17 02:39:03 +00:00
// create PID file early
if ( ! string . IsNullOrWhiteSpace ( Settings . PIDFile ) )
{
try
{
var proc = Process . GetCurrentProcess ( ) ;
File . WriteAllText ( Settings . PIDFile , proc . Id . ToString ( ) ) ;
}
catch ( Exception e )
{
logger . Error ( e , "Error while creating the PID file" ) ;
}
}
2018-06-17 04:02:13 +00:00
Initialisation . ProcessSettings ( Settings , logger ) ;
2018-06-17 02:39:03 +00:00
ISerializeService serializeService = new SerializeService ( ) ;
IProcessService processService = new ProcessService ( logger ) ;
IConfigurationService configurationService = new ConfigurationService ( serializeService , processService , logger , Settings ) ;
if ( consoleOptions . Install | | consoleOptions . Uninstall | | consoleOptions . StartService | | consoleOptions . StopService | | consoleOptions . ReserveUrls )
{
bool isWindows = Environment . OSVersion . Platform = = PlatformID . Win32NT ;
if ( isWindows )
{
ServerConfig serverConfig = configurationService . BuildServerConfig ( Settings ) ;
Initialisation . ProcessWindowsSpecificArgs ( consoleOptions , processService , serverConfig , logger ) ;
}
else
{
logger . Error ( $"ReserveUrls and service arguments only apply to Windows, please remove them from your start arguments" ) ;
Environment . Exit ( 1 ) ;
}
}
2018-05-01 12:00:02 +00:00
var builder = new ConfigurationBuilder ( ) ;
builder . AddInMemoryCollection ( runtimeDictionary ) ;
Configuration = builder . Build ( ) ;
2018-06-16 08:06:14 +00:00
do
2018-05-20 11:21:08 +00:00
{
2018-06-16 08:06:14 +00:00
if ( ! isWebHostRestart )
2018-05-20 11:21:08 +00:00
{
2018-06-17 04:39:49 +00:00
if ( consoleOptions . Port ! = 0 | | consoleOptions . ListenPublic | | consoleOptions . ListenPrivate )
2018-05-20 11:21:08 +00:00
{
2018-06-17 04:39:49 +00:00
ServerConfig serverConfiguration = configurationService . BuildServerConfig ( Settings ) ;
Initialisation . ProcessConsoleOverrides ( consoleOptions , processService , serverConfiguration , configurationService , logger ) ;
2018-05-20 11:21:08 +00:00
}
}
2018-06-17 04:39:49 +00:00
ServerConfig serverConfig = configurationService . BuildServerConfig ( Settings ) ;
Int32 . TryParse ( serverConfig . Port . ToString ( ) , out Int32 configPort ) ;
2018-06-16 08:06:14 +00:00
string [ ] url = serverConfig . GetListenAddresses ( serverConfig . AllowExternal ) . Take ( 1 ) . ToArray ( ) ; //Kestrel doesn't need 127.0.0.1 and localhost to be registered, remove once off OWIN
2018-05-20 11:21:08 +00:00
2018-06-10 02:33:16 +00:00
isWebHostRestart = false ;
2018-06-16 08:06:14 +00:00
try
{
CreateWebHostBuilder ( args , url ) . Build ( ) . Run ( ) ;
}
catch ( Exception ex )
{
if ( ex . InnerException is Microsoft . AspNetCore . Connections . AddressInUseException )
{
2018-06-17 02:39:03 +00:00
logger . Error ( "Address already in use: Most likely Jackett is already running. " + ex . Message ) ;
2018-06-16 08:06:14 +00:00
Environment . Exit ( 1 ) ;
}
2018-06-17 02:39:03 +00:00
logger . Error ( ex ) ;
2018-06-16 08:06:14 +00:00
throw ;
}
2018-06-10 02:33:16 +00:00
} while ( isWebHostRestart ) ;
2018-05-01 12:00:02 +00:00
}
public static Dictionary < string , string > GetValues ( object obj )
{
return obj
. GetType ( )
. GetProperties ( )
. ToDictionary ( p = > "RuntimeSettings:" + p . Name , p = > p . GetValue ( obj ) = = null ? null : p . GetValue ( obj ) . ToString ( ) ) ;
2018-05-01 11:13:20 +00:00
}
2018-06-03 11:11:18 +00:00
private static void CurrentDomain_ProcessExit ( object sender , EventArgs e )
{
try
{
if ( Settings ! = null & & ! string . IsNullOrWhiteSpace ( Settings . PIDFile ) )
{
var PIDFile = Settings . PIDFile ;
if ( File . Exists ( PIDFile ) )
{
Console . WriteLine ( "Deleting PID file " + PIDFile ) ;
File . Delete ( PIDFile ) ;
}
2018-06-17 02:39:03 +00:00
LogManager . Shutdown ( ) ;
2018-06-03 11:11:18 +00:00
}
}
catch ( Exception ex )
{
Console . Error . WriteLine ( ex . ToString ( ) , "Error while deleting the PID file" ) ;
}
}
2018-05-20 11:21:08 +00:00
public static IWebHostBuilder CreateWebHostBuilder ( string [ ] args , string [ ] urls ) = >
2018-05-12 03:16:56 +00:00
WebHost . CreateDefaultBuilder ( args )
. UseConfiguration ( Configuration )
2018-06-10 02:33:16 +00:00
. UseUrls ( urls )
. PreferHostingUrls ( true )
2018-05-12 03:16:56 +00:00
. UseStartup < Startup > ( ) ;
2018-05-01 11:13:20 +00:00
}
}