2021-04-01 05:27:22 +02:00
using System ;
2017-09-13 08:47:34 +02:00
using System.IO ;
2023-01-06 14:18:07 +01:00
using System.Linq ;
2017-09-13 08:47:34 +02:00
using System.Net ;
2023-01-06 14:18:07 +01:00
using System.Reflection ;
2020-06-28 10:55:27 +02:00
using System.Runtime.CompilerServices ;
2023-11-28 15:19:47 +01:00
using System.Threading.Tasks ;
2020-06-28 10:55:27 +02:00
using BTCPayServer.Configuration ;
using BTCPayServer.Hosting ;
using BTCPayServer.Logging ;
2021-04-01 05:27:22 +02:00
using BTCPayServer.Plugins ;
2020-06-28 10:55:27 +02:00
using Microsoft.AspNetCore.Hosting ;
using Microsoft.AspNetCore.Hosting.Server.Features ;
2021-04-01 05:27:22 +02:00
using Microsoft.Extensions.Configuration ;
2020-06-28 10:55:27 +02:00
using Microsoft.Extensions.Logging ;
2017-09-13 08:47:34 +02:00
2020-06-28 10:55:27 +02:00
[assembly: InternalsVisibleTo("BTCPayServer.Tests")]
2023-07-19 11:47:32 +02:00
2017-09-13 08:47:34 +02:00
namespace BTCPayServer
{
2017-10-27 10:53:04 +02:00
class Program
{
2023-11-28 15:19:47 +01:00
static async Task Main ( string [ ] args )
2017-10-27 10:53:04 +02:00
{
2022-01-01 14:05:24 +01:00
if ( args . Length > 0 & & args [ 0 ] = = "run" )
args = args . Skip ( 1 ) . ToArray ( ) ; // Hack to make dotnet watch work
2022-01-12 12:12:10 +01:00
2017-10-27 10:53:04 +02:00
ServicePointManager . DefaultConnectionLimit = 100 ;
IWebHost host = null ;
2018-01-15 06:42:51 +01:00
var processor = new ConsoleLoggerProcessor ( ) ;
2023-11-28 15:19:47 +01:00
var loggerProvider = new CustomConsoleLogProvider ( processor ) ;
2020-01-12 07:32:26 +01:00
using var loggerFactory = new LoggerFactory ( ) ;
2017-10-27 10:53:04 +02:00
loggerFactory . AddProvider ( loggerProvider ) ;
var logger = loggerFactory . CreateLogger ( "Configuration" ) ;
2023-11-28 15:19:47 +01:00
var logs = new Logs ( ) ;
2022-02-06 06:37:19 +01:00
logs . Configure ( loggerFactory ) ;
2021-04-01 05:27:22 +02:00
IConfiguration conf = null ;
2017-10-27 10:53:04 +02:00
try
{
2023-01-16 02:37:17 +01:00
var confBuilder = new DefaultConfiguration ( ) { Logger = logger } . CreateConfigurationBuilder ( args ) ;
2023-02-16 10:32:26 +01:00
if ( confBuilder is null )
return ;
2023-01-16 02:37:17 +01:00
#if DEBUG
confBuilder . AddJsonFile ( "appsettings.dev.json" , true , false ) ;
#endif
conf = confBuilder . Build ( ) ;
2017-09-13 08:47:34 +02:00
2024-04-30 11:29:05 +02:00
var confirm = conf . GetOrDefault < bool > ( "EXPERIMENTALV2_CONFIRM" , false ) ;
if ( ! confirm )
{
throw new ConfigException ( "You are running an experimental version of BTCPay Server that is the basis for v2. Many things will change and break, including irreversible database migrations. THERE IS NO WAY BACK. Please confirm you understand this by setting the setting EXPERIMENTALV2_CONFIRM=true" ) ;
}
2022-01-12 12:12:10 +01:00
var builder = new WebHostBuilder ( )
2017-10-27 10:53:04 +02:00
. UseKestrel ( )
. UseConfiguration ( conf )
. ConfigureLogging ( l = >
{
l . AddFilter ( "Microsoft" , LogLevel . Error ) ;
2021-11-04 16:13:40 +01:00
if ( ! conf . GetOrDefault < bool > ( "verbose" , false ) )
l . AddFilter ( "Events" , LogLevel . Warning ) ;
2024-08-27 02:53:28 +02:00
// Uncomment this to see EF queries
//l.AddFilter("Microsoft.EntityFrameworkCore.Database.Command", LogLevel.Trace);
2019-03-07 11:29:32 +01:00
l . AddFilter ( "System.Net.Http.HttpClient" , LogLevel . Critical ) ;
2018-01-18 10:12:01 +01:00
l . AddFilter ( "Microsoft.AspNetCore.Antiforgery.Internal" , LogLevel . Critical ) ;
2021-04-20 07:06:32 +02:00
l . AddFilter ( "Fido2NetLib.DistributedCacheMetadataService" , LogLevel . Error ) ;
2018-01-15 06:42:51 +01:00
l . AddProvider ( new CustomConsoleLogProvider ( processor ) ) ;
2017-10-27 10:53:04 +02:00
} )
2022-01-12 12:12:10 +01:00
. UseStartup < Startup > ( ) ;
// When we run the app with dotnet run (typically in dev env), the wwwroot isn't in the same directory
// than this assembly.
// But when we use dotnet publish, the wwwroot is published alongside the assembly!
// This fix https://github.com/btcpayserver/btcpayserver/issues/1894
var defaultContentPath = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) ;
var defaultWebRoot = Path . Combine ( defaultContentPath , "wwwroot" ) ;
var defaultWebRootExists = Directory . Exists ( defaultWebRoot ) ;
if ( ! defaultWebRootExists )
{
// When we use dotnet run...
builder . UseContentRoot ( Directory . GetCurrentDirectory ( ) ) ;
}
host = builder . Build ( ) ;
2023-11-28 15:19:47 +01:00
await host . StartWithTasksAsync ( ) ;
2017-10-27 10:53:04 +02:00
var urls = host . ServerFeatures . Get < IServerAddressesFeature > ( ) . Addresses ;
foreach ( var url in urls )
{
2022-01-01 14:05:24 +01:00
// Some tools such as dotnet watch parse this exact log to open the browser
logger . LogInformation ( "Now listening on: " + url ) ;
2017-10-27 10:53:04 +02:00
}
2023-11-28 15:19:47 +01:00
await host . WaitForShutdownAsync ( ) ;
2017-10-27 10:53:04 +02:00
}
catch ( ConfigException ex )
{
if ( ! string . IsNullOrEmpty ( ex . Message ) )
2021-11-22 09:16:08 +01:00
logs . Configuration . LogError ( ex . Message ) ;
2017-10-27 10:53:04 +02:00
}
2023-01-18 06:15:27 +01:00
catch ( Exception e ) when ( PluginManager . IsExceptionByPlugin ( e , out var pluginName ) )
2021-04-01 05:27:22 +02:00
{
2023-01-18 06:15:27 +01:00
logs . Configuration . LogError ( e , $"Disabling plugin {pluginName} as it crashed on startup" ) ;
2021-04-01 05:27:22 +02:00
var pluginDir = new DataDirectories ( ) . Configure ( conf ) . PluginDir ;
2023-01-18 06:15:27 +01:00
PluginManager . DisablePlugin ( pluginDir , pluginName ) ;
2021-04-01 05:27:22 +02:00
}
2017-10-27 10:53:04 +02:00
finally
{
2018-01-15 06:42:51 +01:00
processor . Dispose ( ) ;
2020-06-28 10:55:27 +02:00
if ( host = = null )
2021-11-22 09:16:08 +01:00
logs . Configuration . LogError ( "Configuration error" ) ;
2023-11-28 15:19:47 +01:00
host ? . Dispose ( ) ;
await Serilog . Log . CloseAndFlushAsync ( ) ;
2017-10-27 10:53:04 +02:00
loggerProvider . Dispose ( ) ;
}
}
}
2017-09-13 08:47:34 +02:00
}