Skip to content

Commit

Permalink
Fix reconnection with connection being lost
Browse files Browse the repository at this point in the history
After changes regarding to callbacks handling, we accidentally broke the reconnection logic. In particular, forced connection implicitly did disconnect with disconnect callback, but disconnect callback killed our callbacks handling loop for future connection since it was instructed to not reconnect... Pretty convulated logic.

Let's attempt to fix and simplify it. There is no forced connection concept anymore, but rather a new reconnect function which either, triggers reconnection through usual disconnection logic, or connects in edge case if we attempted to reconnect with already disconnnected client.

This way the status transition is more predictable, as we Connect() only in 3 cases:
- Initial start, including !start command, when we actually spawn the callbacks handling loop
- Upon disconnection, if we're configured to reconnect
- Reconnection, in case we're already disconnected and can't use above

And we use reconnect when:
- Failure in heartbeats to detect disconnections sooner
- Failure in refreshing access tokens, since if we lose our refresh token then the only way to get a new one is to reconnect

And finally disconnect is triggered when:
- Stopping the bot, especially !stop
- Bulletproofing against trying to connect when !KeepRunning and likewise
- Usual Steam maintenance and other network issues (which usually trigger reconnection)

The codebase is too huge to analyze every possible edge case, but with this logic I can no longer reproduce the previous issue
  • Loading branch information
JustArchi committed Sep 13, 2024
1 parent 061e61b commit cefa3e1
Showing 1 changed file with 19 additions and 10 deletions.
29 changes: 19 additions & 10 deletions ArchiSteamFarm/Steam/Bot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,7 @@ internal async Task<bool> RefreshWebSession(bool force = false) {

if (string.IsNullOrEmpty(RefreshToken)) {
// Without refresh token we can't get fresh access tokens, relog needed
await Connect(true).ConfigureAwait(false);
await Reconnect().ConfigureAwait(false);

return false;
}
Expand All @@ -1663,7 +1663,7 @@ internal async Task<bool> RefreshWebSession(bool force = false) {

BotDatabase.RefreshToken = RefreshToken = null;

await Connect(true).ConfigureAwait(false);
await Reconnect().ConfigureAwait(false);

return false;
}
Expand All @@ -1674,7 +1674,7 @@ internal async Task<bool> RefreshWebSession(bool force = false) {

ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(SteamClient.Authentication.GenerateAccessTokenForAppAsync)));

await Connect(true).ConfigureAwait(false);
await Reconnect().ConfigureAwait(false);

return false;
}
Expand All @@ -1690,7 +1690,7 @@ internal async Task<bool> RefreshWebSession(bool force = false) {
// We got the tokens, but failed to authorize? Purge them just to be sure and reconnect
BotDatabase.AccessToken = AccessToken = null;

await Connect(true).ConfigureAwait(false);
await Reconnect().ConfigureAwait(false);

return false;
} finally {
Expand Down Expand Up @@ -2025,14 +2025,14 @@ internal static IOrderedDictionary ValidateGamesToRedeemInBackground(IOrderedDic
return gamesToRedeemInBackground;
}

private async Task Connect(bool force = false) {
if (!force && (!KeepRunning || SteamClient.IsConnected)) {
private async Task Connect() {
if (!KeepRunning || SteamClient.IsConnected) {
return;
}

await LimitLoginRequestsAsync().ConfigureAwait(false);

if (!force && (!KeepRunning || SteamClient.IsConnected)) {
if (!KeepRunning || SteamClient.IsConnected) {
return;
}

Expand Down Expand Up @@ -2079,11 +2079,11 @@ private async Task Destroy(bool force = false) {
await PluginsCore.OnBotDestroy(this).ConfigureAwait(false);
}

private void Disconnect() {
private void Disconnect(bool reconnect = false) {
StopConnectionFailureTimer();

LastLogOnResult = EResult.OK;
ReconnectOnUserInitiated = false;
ReconnectOnUserInitiated = reconnect;

SteamClient.Disconnect();
}
Expand Down Expand Up @@ -2324,7 +2324,8 @@ private async void HeartBeat(object? state = null) {
if (++HeartBeatFailures >= (byte) Math.Ceiling(connectionTimeout / 10.0)) {
HeartBeatFailures = byte.MaxValue;
ArchiLogger.LogGenericWarning(Strings.BotConnectionLost);
Utilities.InBackground(() => Connect(true));

Utilities.InBackground(Reconnect);
}
}
}
Expand Down Expand Up @@ -3535,6 +3536,14 @@ private void OnWalletInfo(SteamUser.WalletInfoCallback callback) {
WalletCurrency = callback.Currency;
}

private async Task Reconnect() {
if (SteamClient.IsConnected) {
Disconnect(true);
} else {
await Connect().ConfigureAwait(false);
}
}

private async void RedeemGamesInBackground(object? state = null) {
if (!await GamesRedeemerInBackgroundSemaphore.WaitAsync(0).ConfigureAwait(false)) {
return;
Expand Down

0 comments on commit cefa3e1

Please sign in to comment.