2020-06-28 21:44:35 -05:00
using System ;
2020-06-28 17:55:27 +09:00
using System.Threading ;
2018-08-12 21:38:45 +09:00
using System.Threading.Tasks ;
2020-06-28 17:55:27 +09:00
using BTCPayServer.Configuration ;
using BTCPayServer.Logging ;
2018-08-12 21:38:45 +09:00
using Microsoft.Extensions.Hosting ;
2020-06-28 17:55:27 +09:00
using Microsoft.Extensions.Logging ;
2018-08-12 21:38:45 +09:00
namespace BTCPayServer.HostedServices
{
public class CheckConfigurationHostedService : IHostedService
{
private readonly BTCPayServerOptions _options ;
2019-09-19 16:53:35 +09:00
Task _testingConnection ;
2020-06-28 22:07:48 -05:00
readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource ( ) ;
2018-08-12 21:38:45 +09:00
public CheckConfigurationHostedService ( BTCPayServerOptions options )
{
_options = options ;
}
2019-08-27 23:30:25 +09:00
public bool CanUseSSH { get ; private set ; }
2018-08-12 21:38:45 +09:00
public Task StartAsync ( CancellationToken cancellationToken )
{
2019-09-19 16:53:35 +09:00
_testingConnection = TestConnection ( ) ;
2019-08-27 23:30:25 +09:00
return Task . CompletedTask ;
}
async Task TestConnection ( )
{
2019-09-19 16:53:35 +09:00
TimeSpan nextWait = TimeSpan . FromSeconds ( 10 ) ;
2020-06-28 17:55:27 +09:00
retry :
2019-08-27 23:30:25 +09:00
var canUseSSH = false ;
if ( _options . SSHSettings ! = null )
2018-08-12 21:38:45 +09:00
{
2019-08-27 23:30:25 +09: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 21:38:45 +09:00
{
2019-10-21 16:34:26 +09:00
using ( var connection = await _options . SSHSettings . ConnectAsync ( _cancellationTokenSource . Token ) )
2018-08-12 21:38:45 +09:00
{
2019-10-21 18:43:53 +09:00
await connection . DisconnectAsync ( _cancellationTokenSource . Token ) ;
2018-08-12 21:38:45 +09:00
Logs . Configuration . LogInformation ( $"SSH connection succeeded" ) ;
2019-08-27 23:30:25 +09:00
canUseSSH = true ;
2018-08-12 21:38:45 +09:00
}
2019-08-27 23:30:25 +09:00
}
2019-08-27 23:39:17 +09:00
catch ( Renci . SshNet . Common . SshAuthenticationException ex )
2019-08-27 23:30:25 +09:00
{
2019-08-27 23:39:17 +09:00
Logs . Configuration . LogWarning ( $"SSH invalid credentials ({ex.Message})" ) ;
2019-08-27 23:30:25 +09:00
}
catch ( Exception ex )
{
var message = ex . Message ;
if ( ex is AggregateException aggrEx & & aggrEx . InnerException ? . Message ! = null )
2018-08-12 21:38:45 +09:00
{
2019-08-27 23:30:25 +09:00
message = aggrEx . InnerException . Message ;
2018-08-12 21:38:45 +09:00
}
2019-08-27 23:30:25 +09:00
Logs . Configuration . LogWarning ( $"SSH connection issue of type {ex.GetType().Name}: {message}" ) ;
2018-08-12 21:38:45 +09:00
}
2019-09-20 15:26:09 +09: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 16:53:35 +09:00
}
2019-08-27 23:30:25 +09:00
CanUseSSH = canUseSSH ;
2018-08-12 21:38:45 +09:00
}
2019-09-19 16:53:35 +09:00
public async Task StopAsync ( CancellationToken cancellationToken )
2018-08-12 21:38:45 +09:00
{
2019-09-19 16:53:35 +09:00
_cancellationTokenSource . Cancel ( ) ;
try
{
2019-10-26 23:40:35 +09:00
// Renci SSH sometimes is deadlocking, so we just wait at most 5 seconds
await Task . WhenAny ( _testingConnection , Task . Delay ( 5000 , _cancellationTokenSource . Token ) ) ;
2019-09-19 16:53:35 +09:00
}
catch { }
2019-10-21 16:34:26 +09:00
Logs . PayServer . LogInformation ( $"{this.GetType().Name} successfully exited..." ) ;
2018-08-12 21:38:45 +09:00
}
}
}