2025-01-18 20:25:39 -06:00
|
|
|
using System.Timers;
|
2025-10-05 17:13:47 -05:00
|
|
|
using LANCommander.SDK.Services;
|
2025-01-18 20:25:39 -06:00
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Timer = System.Timers.Timer;
|
|
|
|
|
|
|
|
|
|
namespace LANCommander.Launcher.Services;
|
|
|
|
|
|
|
|
|
|
public class KeepAliveService : BaseService
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
private readonly AuthenticationService _authenticationService;
|
|
|
|
|
private readonly IConnectionClient _connectionClient;
|
2025-01-18 20:25:39 -06:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
private Timer? _checkConnectionTimer;
|
|
|
|
|
private Timer? _retryConnectionTimer;
|
2025-01-18 20:25:39 -06:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
private readonly int _pingInterval = 2000;
|
|
|
|
|
private readonly int _retryInterval = 1000;
|
2025-06-16 01:36:39 +02:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
private int _retryCount;
|
2025-10-22 00:09:18 -05:00
|
|
|
private readonly int _maxRetries = 30;
|
|
|
|
|
private readonly int _retryGracePeriod = 10;
|
2025-01-18 20:25:39 -06:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
private bool _connectionLost = false;
|
|
|
|
|
private bool _isCheckConnectionActive = false;
|
|
|
|
|
private bool _isRetryConnectionActive = false;
|
2025-06-10 01:37:15 +02:00
|
|
|
|
2025-01-18 20:25:39 -06:00
|
|
|
public event EventHandler ConnectionSevered;
|
2025-06-16 01:36:39 +02:00
|
|
|
public event EventHandler ConnectionRetryNext;
|
2025-01-18 20:25:39 -06:00
|
|
|
public event EventHandler ConnectionLostPermanently;
|
|
|
|
|
public event EventHandler ConnectionEstablished;
|
|
|
|
|
|
|
|
|
|
public KeepAliveService(
|
|
|
|
|
ILogger<KeepAliveService> logger,
|
2025-10-05 17:13:47 -05:00
|
|
|
AuthenticationService authenticationService,
|
|
|
|
|
IConnectionClient connectionClient) : base(logger)
|
2025-01-18 20:25:39 -06:00
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_authenticationService = authenticationService;
|
|
|
|
|
_connectionClient = connectionClient;
|
2025-10-05 17:13:47 -05:00
|
|
|
|
|
|
|
|
connectionClient.OnConnect += (sender, args) => StartMonitoring();
|
|
|
|
|
connectionClient.OnDisconnect += (sender, args) => StopMonitoring();
|
2025-01-18 20:25:39 -06:00
|
|
|
|
|
|
|
|
ConnectionEstablished += (sender, args) => StartMonitoring();
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-16 01:36:39 +02:00
|
|
|
public (int current, int total) GetRetryCount()
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
return (_retryCount, _maxRetries);
|
2025-06-16 01:36:39 +02:00
|
|
|
}
|
|
|
|
|
|
2025-01-18 20:25:39 -06:00
|
|
|
public void StartMonitoring()
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_retryCount = 0;
|
|
|
|
|
_connectionLost = false;
|
2025-01-18 20:25:39 -06:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
_checkConnectionTimer?.Stop();
|
|
|
|
|
_checkConnectionTimer?.Dispose();
|
2025-01-18 20:25:39 -06:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
_checkConnectionTimer = new Timer(_pingInterval);
|
|
|
|
|
_checkConnectionTimer.Elapsed += CheckConnection!;
|
|
|
|
|
_checkConnectionTimer.AutoReset = true;
|
|
|
|
|
_checkConnectionTimer.Start();
|
2025-01-18 20:25:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void StopMonitoring()
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_retryCount = 0;
|
|
|
|
|
_checkConnectionTimer?.Stop();
|
|
|
|
|
_checkConnectionTimer?.Dispose();
|
|
|
|
|
_retryConnectionTimer?.Stop();
|
|
|
|
|
_retryConnectionTimer?.Dispose();
|
2025-01-18 20:25:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void CheckConnection(object sender, ElapsedEventArgs e)
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
if (_isCheckConnectionActive) return;
|
|
|
|
|
_isCheckConnectionActive = true;
|
2025-01-18 20:25:39 -06:00
|
|
|
|
2025-06-16 01:36:39 +02:00
|
|
|
try
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
var serverOnline = await _authenticationService.IsServerOnlineAsync();
|
2025-06-16 01:36:39 +02:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
if (!serverOnline && !_connectionLost)
|
2025-06-16 01:36:39 +02:00
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_checkConnectionTimer?.Stop();
|
|
|
|
|
_checkConnectionTimer?.Dispose();
|
|
|
|
|
_checkConnectionTimer = null;
|
2025-06-16 01:36:39 +02:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
_connectionLost = true;
|
2025-06-16 01:36:39 +02:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
_retryConnectionTimer = new Timer(_retryInterval);
|
|
|
|
|
_retryConnectionTimer.Elapsed += RetryConnection!;
|
|
|
|
|
_retryConnectionTimer.AutoReset = false;
|
|
|
|
|
_retryConnectionTimer.Start();
|
2025-06-16 01:36:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
2025-01-18 20:25:39 -06:00
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_isCheckConnectionActive = false;
|
2025-01-18 20:25:39 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void RetryConnection(object sender, ElapsedEventArgs e)
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
if (_isRetryConnectionActive) return;
|
|
|
|
|
_isRetryConnectionActive = true;
|
2025-01-18 20:25:39 -06:00
|
|
|
|
2025-06-16 01:36:39 +02:00
|
|
|
try
|
2025-01-18 20:25:39 -06:00
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
if (_connectionClient.IsConnected() && _connectionLost)
|
2025-01-18 20:25:39 -06:00
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_connectionLost = false;
|
2025-06-16 01:36:39 +02:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
_retryConnectionTimer?.Stop();
|
|
|
|
|
_retryConnectionTimer?.Dispose();
|
|
|
|
|
_retryConnectionTimer = null;
|
2025-06-16 01:20:03 +02:00
|
|
|
|
2025-06-16 01:36:39 +02:00
|
|
|
ConnectionEstablished?.Invoke(this, EventArgs.Empty);
|
|
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
await _connectionClient.ConnectAsync();
|
2025-06-16 01:36:39 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_retryCount++;
|
|
|
|
|
_retryConnectionTimer?.Start();
|
2025-06-16 01:36:39 +02:00
|
|
|
ConnectionRetryNext?.Invoke(this, EventArgs.Empty);
|
2025-10-22 00:09:18 -05:00
|
|
|
|
|
|
|
|
if (_retryCount == _retryGracePeriod)
|
|
|
|
|
ConnectionSevered?.Invoke(this, EventArgs.Empty);
|
2025-06-16 01:36:39 +02:00
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
if (_retryCount == _maxRetries)
|
2025-06-16 01:36:39 +02:00
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_retryConnectionTimer?.Stop();
|
|
|
|
|
_retryConnectionTimer?.Dispose();
|
|
|
|
|
_retryConnectionTimer = null;
|
2025-06-16 01:20:03 +02:00
|
|
|
|
2025-06-16 01:36:39 +02:00
|
|
|
ConnectionLostPermanently?.Invoke(this, EventArgs.Empty);
|
|
|
|
|
|
2025-10-05 19:30:59 -05:00
|
|
|
await _connectionClient.EnableOfflineModeAsync();
|
2025-06-16 01:36:39 +02:00
|
|
|
}
|
2025-01-18 20:25:39 -06:00
|
|
|
}
|
|
|
|
|
}
|
2025-06-16 01:36:39 +02:00
|
|
|
finally
|
|
|
|
|
{
|
2025-10-05 19:30:59 -05:00
|
|
|
_isRetryConnectionActive = false;
|
2025-06-16 01:36:39 +02:00
|
|
|
}
|
2025-01-18 20:25:39 -06:00
|
|
|
}
|
|
|
|
|
}
|