|
|
@@ -35,6 +35,7 @@ namespace Discord |
|
|
|
private int _unavailableGuilds; |
|
|
|
private long _lastGuildAvailableTime; |
|
|
|
private int _nextAudioId; |
|
|
|
private bool _canReconnect; |
|
|
|
|
|
|
|
/// <summary> Gets the shard if of this client. </summary> |
|
|
|
public int ShardId { get; } |
|
|
@@ -114,7 +115,7 @@ namespace Discord |
|
|
|
protected override async Task OnLogoutAsync() |
|
|
|
{ |
|
|
|
if (ConnectionState != ConnectionState.Disconnected) |
|
|
|
await DisconnectInternalAsync(null).ConfigureAwait(false); |
|
|
|
await DisconnectInternalAsync(null, false).ConfigureAwait(false); |
|
|
|
|
|
|
|
_voiceRegions = ImmutableDictionary.Create<string, VoiceRegion>(); |
|
|
|
} |
|
|
@@ -125,7 +126,7 @@ namespace Discord |
|
|
|
await _connectionLock.WaitAsync().ConfigureAwait(false); |
|
|
|
try |
|
|
|
{ |
|
|
|
await ConnectInternalAsync().ConfigureAwait(false); |
|
|
|
await ConnectInternalAsync(false).ConfigureAwait(false); |
|
|
|
} |
|
|
|
finally { _connectionLock.Release(); } |
|
|
|
|
|
|
@@ -136,17 +137,17 @@ namespace Discord |
|
|
|
await _guildDownloadTask.ConfigureAwait(false); |
|
|
|
} |
|
|
|
} |
|
|
|
private async Task ConnectInternalAsync() |
|
|
|
private async Task ConnectInternalAsync(bool isReconnecting) |
|
|
|
{ |
|
|
|
if (LoginState != LoginState.LoggedIn) |
|
|
|
throw new InvalidOperationException("You must log in before connecting."); |
|
|
|
|
|
|
|
if (_reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested) |
|
|
|
if (!isReconnecting && _reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested) |
|
|
|
_reconnectCancelToken.Cancel(); |
|
|
|
|
|
|
|
var state = ConnectionState; |
|
|
|
if (state == ConnectionState.Connecting || state == ConnectionState.Connected) |
|
|
|
await DisconnectInternalAsync(null).ConfigureAwait(false); |
|
|
|
await DisconnectInternalAsync(null, isReconnecting).ConfigureAwait(false); |
|
|
|
|
|
|
|
ConnectionState = ConnectionState.Connecting; |
|
|
|
await _gatewayLogger.InfoAsync("Connecting").ConfigureAwait(false); |
|
|
@@ -164,12 +165,13 @@ namespace Discord |
|
|
|
await ApiClient.SendIdentifyAsync().ConfigureAwait(false); |
|
|
|
|
|
|
|
await _connectTask.Task.ConfigureAwait(false); |
|
|
|
_canReconnect = true; |
|
|
|
ConnectionState = ConnectionState.Connected; |
|
|
|
await _gatewayLogger.InfoAsync("Connected").ConfigureAwait(false); |
|
|
|
} |
|
|
|
catch (Exception) |
|
|
|
{ |
|
|
|
await DisconnectInternalAsync(null).ConfigureAwait(false); |
|
|
|
await DisconnectInternalAsync(null, isReconnecting).ConfigureAwait(false); |
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
@@ -180,7 +182,7 @@ namespace Discord |
|
|
|
await _connectionLock.WaitAsync().ConfigureAwait(false); |
|
|
|
try |
|
|
|
{ |
|
|
|
await DisconnectInternalAsync(null).ConfigureAwait(false); |
|
|
|
await DisconnectInternalAsync(null, false).ConfigureAwait(false); |
|
|
|
} |
|
|
|
finally { _connectionLock.Release(); } |
|
|
|
} |
|
|
@@ -190,14 +192,18 @@ namespace Discord |
|
|
|
await _connectionLock.WaitAsync().ConfigureAwait(false); |
|
|
|
try |
|
|
|
{ |
|
|
|
await DisconnectInternalAsync(ex).ConfigureAwait(false); |
|
|
|
await DisconnectInternalAsync(ex, false).ConfigureAwait(false); |
|
|
|
} |
|
|
|
finally { _connectionLock.Release(); } |
|
|
|
} |
|
|
|
private async Task DisconnectInternalAsync(Exception ex) |
|
|
|
private async Task DisconnectInternalAsync(Exception ex, bool isReconnecting) |
|
|
|
{ |
|
|
|
if (_reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested) |
|
|
|
_reconnectCancelToken.Cancel(); |
|
|
|
if (!isReconnecting) |
|
|
|
{ |
|
|
|
_canReconnect = false; |
|
|
|
if (_reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested) |
|
|
|
_reconnectCancelToken.Cancel(); |
|
|
|
} |
|
|
|
|
|
|
|
ulong guildId; |
|
|
|
|
|
|
@@ -242,7 +248,8 @@ namespace Discord |
|
|
|
await _connectionLock.WaitAsync().ConfigureAwait(false); |
|
|
|
try |
|
|
|
{ |
|
|
|
await DisconnectInternalAsync(null).ConfigureAwait(false); |
|
|
|
if (!_canReconnect || _reconnectTask != null) return; |
|
|
|
await DisconnectInternalAsync(null, true).ConfigureAwait(false); |
|
|
|
_reconnectCancelToken = new CancellationTokenSource(); |
|
|
|
_reconnectTask = ReconnectInternalAsync(_reconnectCancelToken.Token); |
|
|
|
} |
|
|
@@ -253,34 +260,37 @@ namespace Discord |
|
|
|
try |
|
|
|
{ |
|
|
|
int nextReconnectDelay = 1000; |
|
|
|
while (!cancelToken.IsCancellationRequested) |
|
|
|
while (true) |
|
|
|
{ |
|
|
|
await Task.Delay(nextReconnectDelay, cancelToken).ConfigureAwait(false); |
|
|
|
nextReconnectDelay *= 2; |
|
|
|
if (nextReconnectDelay > 30000) |
|
|
|
nextReconnectDelay = 30000; |
|
|
|
|
|
|
|
await _connectionLock.WaitAsync().ConfigureAwait(false); |
|
|
|
try |
|
|
|
{ |
|
|
|
await Task.Delay(nextReconnectDelay, cancelToken).ConfigureAwait(false); |
|
|
|
nextReconnectDelay *= 2; |
|
|
|
if (nextReconnectDelay > 30000) |
|
|
|
nextReconnectDelay = 30000; |
|
|
|
|
|
|
|
await _connectionLock.WaitAsync().ConfigureAwait(false); |
|
|
|
try |
|
|
|
{ |
|
|
|
if (cancelToken.IsCancellationRequested) return; |
|
|
|
await ConnectInternalAsync().ConfigureAwait(false); |
|
|
|
} |
|
|
|
finally { _connectionLock.Release(); } |
|
|
|
if (cancelToken.IsCancellationRequested) return; |
|
|
|
await ConnectInternalAsync(true).ConfigureAwait(false); |
|
|
|
_reconnectTask = null; |
|
|
|
return; |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
await _gatewayLogger.WarningAsync("Reconnect failed", ex).ConfigureAwait(false); |
|
|
|
} |
|
|
|
finally { _connectionLock.Release(); } |
|
|
|
} |
|
|
|
} |
|
|
|
catch (OperationCanceledException) { } |
|
|
|
finally |
|
|
|
catch (OperationCanceledException) |
|
|
|
{ |
|
|
|
_reconnectTask = null; |
|
|
|
await _connectionLock.WaitAsync().ConfigureAwait(false); |
|
|
|
try |
|
|
|
{ |
|
|
|
await _gatewayLogger.DebugAsync("Reconnect cancelled").ConfigureAwait(false); |
|
|
|
_reconnectTask = null; |
|
|
|
} |
|
|
|
finally { _connectionLock.Release(); } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|