2018-08-12 14:38:45 +02:00
using System ;
using Microsoft.Extensions.Logging ;
using Microsoft.EntityFrameworkCore ;
using System.Collections.Generic ;
using System.Linq ;
using System.Threading.Tasks ;
using BTCPayServer.Data ;
using BTCPayServer.Services ;
using Microsoft.Extensions.Hosting ;
using System.Threading ;
using BTCPayServer.Configuration ;
using BTCPayServer.Logging ;
2018-08-12 16:23:26 +02:00
using NBitcoin.DataEncoders ;
2018-08-12 14:38:45 +02:00
namespace BTCPayServer.HostedServices
{
public class CheckConfigurationHostedService : IHostedService
{
private readonly BTCPayServerOptions _options ;
2019-09-19 09:53:35 +02:00
Task _testingConnection ;
CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource ( ) ;
2018-08-12 14:38:45 +02:00
public CheckConfigurationHostedService ( BTCPayServerOptions options )
{
_options = options ;
}
2019-08-27 16:30:25 +02:00
public bool CanUseSSH { get ; private set ; }
2018-08-12 14:38:45 +02:00
public Task StartAsync ( CancellationToken cancellationToken )
{
2019-09-19 09:53:35 +02:00
_testingConnection = TestConnection ( ) ;
2019-08-27 16:30:25 +02:00
return Task . CompletedTask ;
}
async Task TestConnection ( )
{
2019-09-19 09:53:35 +02:00
TimeSpan nextWait = TimeSpan . FromSeconds ( 10 ) ;
retry :
2019-08-27 16:30:25 +02:00
var canUseSSH = false ;
if ( _options . SSHSettings ! = null )
2018-08-12 14:38:45 +02:00
{
2019-08-27 16:30:25 +02:00
Logs . Configuration . LogInformation ( $"SSH settings detected, testing connection to {_options.SSHSettings.Username}@{_options.SSHSettings.Server} on port {_options.SSHSettings.Port} ..." ) ;
try
2018-08-12 14:38:45 +02:00
{
2019-08-27 16:30:25 +02:00
using ( var connection = await _options . SSHSettings . ConnectAsync ( ) )
2018-08-12 14:38:45 +02:00
{
2019-08-27 16:30:25 +02:00
await connection . DisconnectAsync ( ) ;
2018-08-12 14:38:45 +02:00
Logs . Configuration . LogInformation ( $"SSH connection succeeded" ) ;
2019-08-27 16:30:25 +02:00
canUseSSH = true ;
2018-08-12 14:38:45 +02:00
}
2019-08-27 16:30:25 +02:00
}
2019-08-27 16:39:17 +02:00
catch ( Renci . SshNet . Common . SshAuthenticationException ex )
2019-08-27 16:30:25 +02:00
{
2019-08-27 16:39:17 +02:00
Logs . Configuration . LogWarning ( $"SSH invalid credentials ({ex.Message})" ) ;
2019-08-27 16:30:25 +02:00
}
catch ( Exception ex )
{
var message = ex . Message ;
if ( ex is AggregateException aggrEx & & aggrEx . InnerException ? . Message ! = null )
2018-08-12 14:38:45 +02:00
{
2019-08-27 16:30:25 +02:00
message = aggrEx . InnerException . Message ;
2018-08-12 14:38:45 +02:00
}
2019-08-27 16:30:25 +02:00
Logs . Configuration . LogWarning ( $"SSH connection issue of type {ex.GetType().Name}: {message}" ) ;
2018-08-12 14:38:45 +02:00
}
2019-09-20 08:26:09 +02:00
if ( ! canUseSSH )
{
Logs . Configuration . LogWarning ( $"Retrying SSH connection in {(int)nextWait.TotalSeconds} seconds" ) ;
await Task . Delay ( nextWait , _cancellationTokenSource . Token ) ;
nextWait = TimeSpan . FromSeconds ( nextWait . TotalSeconds * 2 ) ;
if ( nextWait > TimeSpan . FromMinutes ( 10.0 ) )
nextWait = TimeSpan . FromMinutes ( 10.0 ) ;
goto retry ;
}
2019-09-19 09:53:35 +02:00
}
2019-08-27 16:30:25 +02:00
CanUseSSH = canUseSSH ;
2018-08-12 14:38:45 +02:00
}
2019-09-19 09:53:35 +02:00
public async Task StopAsync ( CancellationToken cancellationToken )
2018-08-12 14:38:45 +02:00
{
2019-09-19 09:53:35 +02:00
_cancellationTokenSource . Cancel ( ) ;
try
{
await _testingConnection ;
}
catch { }
2018-08-12 14:38:45 +02:00
}
}
}