Fixed reconnect crash
This commit is contained in:
@@ -95,7 +95,7 @@ namespace Discord
|
|||||||
_api = new DiscordAPIClient(_config.LogLevel);
|
_api = new DiscordAPIClient(_config.LogLevel);
|
||||||
_dataSocket = new DataWebSocket(this);
|
_dataSocket = new DataWebSocket(this);
|
||||||
_dataSocket.Connected += (s, e) => { if (_state == (int)DiscordClientState.Connecting) CompleteConnect(); };
|
_dataSocket.Connected += (s, e) => { if (_state == (int)DiscordClientState.Connecting) CompleteConnect(); };
|
||||||
_dataSocket.Disconnected += async (s, e) => { RaiseDisconnected(e); if (e.WasUnexpected) await Connect(_token); /*await _dataSocket.Reconnect(_cancelToken);*/ };
|
_dataSocket.Disconnected += async (s, e) => { RaiseDisconnected(e); if (e.WasUnexpected) await Reconnect(_token); };
|
||||||
if (_config.EnableVoice)
|
if (_config.EnableVoice)
|
||||||
{
|
{
|
||||||
_voiceSocket = new VoiceWebSocket(this);
|
_voiceSocket = new VoiceWebSocket(this);
|
||||||
@@ -553,6 +553,7 @@ namespace Discord
|
|||||||
/// <summary> Connects to the Discord server with the provided token. </summary>
|
/// <summary> Connects to the Discord server with the provided token. </summary>
|
||||||
public async Task Connect(string token)
|
public async Task Connect(string token)
|
||||||
{
|
{
|
||||||
|
if (_state != (int)DiscordClientState.Disconnected)
|
||||||
await Disconnect().ConfigureAwait(false);
|
await Disconnect().ConfigureAwait(false);
|
||||||
|
|
||||||
if (_config.LogLevel >= LogMessageSeverity.Verbose)
|
if (_config.LogLevel >= LogMessageSeverity.Verbose)
|
||||||
@@ -564,6 +565,7 @@ namespace Discord
|
|||||||
/// <returns> Returns a token for future connections. </returns>
|
/// <returns> Returns a token for future connections. </returns>
|
||||||
public async Task<string> Connect(string email, string password)
|
public async Task<string> Connect(string email, string password)
|
||||||
{
|
{
|
||||||
|
if (_state != (int)DiscordClientState.Disconnected)
|
||||||
await Disconnect().ConfigureAwait(false);
|
await Disconnect().ConfigureAwait(false);
|
||||||
|
|
||||||
var response = await _api.Login(email, password).ConfigureAwait(false);
|
var response = await _api.Login(email, password).ConfigureAwait(false);
|
||||||
@@ -572,11 +574,15 @@ namespace Discord
|
|||||||
|
|
||||||
return await ConnectInternal(response.Token).ConfigureAwait(false);
|
return await ConnectInternal(response.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
private Task Reconnect(string token)
|
||||||
|
{
|
||||||
|
if (_config.LogLevel >= LogMessageSeverity.Verbose)
|
||||||
|
RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Authentication, $"Using cached token.");
|
||||||
|
|
||||||
|
return ConnectInternal(token);
|
||||||
|
}
|
||||||
private async Task<string> ConnectInternal(string token)
|
private async Task<string> ConnectInternal(string token)
|
||||||
{
|
{
|
||||||
if (_state != (int)DiscordClientState.Disconnected)
|
|
||||||
throw new InvalidOperationException("Client is already connected or connecting to the server.");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_disconnectedEvent.Reset();
|
_disconnectedEvent.Reset();
|
||||||
@@ -618,14 +624,14 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
protected void CompleteConnect()
|
protected void CompleteConnect()
|
||||||
{
|
{
|
||||||
_state = (int)WebSocketState.Connected;
|
_state = (int)DiscordClientState.Connected;
|
||||||
_connectedEvent.Set();
|
_connectedEvent.Set();
|
||||||
RaiseConnected();
|
RaiseConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Disconnects from the Discord server, canceling any pending requests. </summary>
|
/// <summary> Disconnects from the Discord server, canceling any pending requests. </summary>
|
||||||
public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false);
|
public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false);
|
||||||
protected Task DisconnectInternal(Exception ex, bool isUnexpected = true, bool skipAwait = false)
|
protected Task DisconnectInternal(Exception ex = null, bool isUnexpected = true, bool skipAwait = false)
|
||||||
{
|
{
|
||||||
int oldState;
|
int oldState;
|
||||||
bool hasWriterLock;
|
bool hasWriterLock;
|
||||||
@@ -644,7 +650,7 @@ namespace Discord
|
|||||||
if (hasWriterLock)
|
if (hasWriterLock)
|
||||||
{
|
{
|
||||||
_wasDisconnectUnexpected = isUnexpected;
|
_wasDisconnectUnexpected = isUnexpected;
|
||||||
_disconnectReason = ExceptionDispatchInfo.Capture(ex);
|
_disconnectReason = ex != null ? ExceptionDispatchInfo.Capture(ex) : null;
|
||||||
_cancelTokenSource.Cancel();
|
_cancelTokenSource.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,12 +668,12 @@ namespace Discord
|
|||||||
else
|
else
|
||||||
task = _cancelToken.Wait();
|
task = _cancelToken.Wait();
|
||||||
|
|
||||||
try
|
try { await task.ConfigureAwait(false); }
|
||||||
{
|
|
||||||
await task.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex) { await DisconnectInternal(ex, skipAwait: true).ConfigureAwait(false); }
|
catch (Exception ex) { await DisconnectInternal(ex, skipAwait: true).ConfigureAwait(false); }
|
||||||
|
|
||||||
|
//When the first task ends, make sure the rest do too
|
||||||
|
await DisconnectInternal(skipAwait: true);
|
||||||
|
|
||||||
bool wasUnexpected = _wasDisconnectUnexpected;
|
bool wasUnexpected = _wasDisconnectUnexpected;
|
||||||
_wasDisconnectUnexpected = false;
|
_wasDisconnectUnexpected = false;
|
||||||
|
|
||||||
@@ -680,8 +686,11 @@ namespace Discord
|
|||||||
if (_config.EnableVoice)
|
if (_config.EnableVoice)
|
||||||
await _voiceSocket.Disconnect().ConfigureAwait(false);
|
await _voiceSocket.Disconnect().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (_config.UseMessageQueue)
|
||||||
|
{
|
||||||
Message ignored;
|
Message ignored;
|
||||||
while (_pendingMessages.TryDequeue(out ignored)) { }
|
while (_pendingMessages.TryDequeue(out ignored)) { }
|
||||||
|
}
|
||||||
|
|
||||||
_channels.Clear();
|
_channels.Clear();
|
||||||
_members.Clear();
|
_members.Clear();
|
||||||
|
|||||||
@@ -70,6 +70,29 @@ namespace Discord.Net.WebSockets
|
|||||||
|
|
||||||
await Connect(host, cancelToken);
|
await Connect(host, cancelToken);
|
||||||
}
|
}
|
||||||
|
public async Task Reconnect(CancellationToken cancelToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Delay(_client.Config.ReconnectDelay, cancelToken).ConfigureAwait(false);
|
||||||
|
while (!cancelToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Connect(_host, cancelToken).ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) { throw; }
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
RaiseOnLog(LogMessageSeverity.Error, $"DataSocket reconnect failed: {ex.GetBaseException().Message}");
|
||||||
|
//Net is down? We can keep trying to reconnect until the user runs Disconnect()
|
||||||
|
await Task.Delay(_client.Config.FailedReconnectDelay, cancelToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) { }
|
||||||
|
}
|
||||||
|
|
||||||
protected override Task[] Run()
|
protected override Task[] Run()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,29 +69,6 @@ namespace Discord.Net.WebSockets
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Reconnect(CancellationToken cancelToken)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.Delay(_client.Config.ReconnectDelay, cancelToken).ConfigureAwait(false);
|
|
||||||
while (!cancelToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Connect(_host, cancelToken).ConfigureAwait(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException) { throw; }
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
RaiseOnLog(LogMessageSeverity.Error, $"DataSocket reconnect failed: {ex.GetBaseException().Message}");
|
|
||||||
//Net is down? We can keep trying to reconnect until the user runs Disconnect()
|
|
||||||
await Task.Delay(_client.Config.FailedReconnectDelay, cancelToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException) { }
|
|
||||||
}
|
|
||||||
protected virtual async Task Connect(string host, CancellationToken cancelToken)
|
protected virtual async Task Connect(string host, CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
if (_state != (int)WebSocketState.Disconnected)
|
if (_state != (int)WebSocketState.Disconnected)
|
||||||
@@ -127,7 +104,7 @@ namespace Discord.Net.WebSockets
|
|||||||
=> Connect(_host, _cancelToken);*/
|
=> Connect(_host, _cancelToken);*/
|
||||||
|
|
||||||
public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false);
|
public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false);
|
||||||
protected Task DisconnectInternal(Exception ex, bool isUnexpected = true, bool skipAwait = false)
|
protected Task DisconnectInternal(Exception ex = null, bool isUnexpected = true, bool skipAwait = false)
|
||||||
{
|
{
|
||||||
int oldState;
|
int oldState;
|
||||||
bool hasWriterLock;
|
bool hasWriterLock;
|
||||||
@@ -146,7 +123,7 @@ namespace Discord.Net.WebSockets
|
|||||||
if (hasWriterLock)
|
if (hasWriterLock)
|
||||||
{
|
{
|
||||||
_wasDisconnectUnexpected = isUnexpected;
|
_wasDisconnectUnexpected = isUnexpected;
|
||||||
_disconnectReason = ExceptionDispatchInfo.Capture(ex);
|
_disconnectReason = ex != null ? ExceptionDispatchInfo.Capture(ex) : null;
|
||||||
_cancelTokenSource.Cancel();
|
_cancelTokenSource.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,13 +135,17 @@ namespace Discord.Net.WebSockets
|
|||||||
|
|
||||||
protected virtual async Task RunTasks()
|
protected virtual async Task RunTasks()
|
||||||
{
|
{
|
||||||
Task task = Task.WhenAll(Run());
|
Task[] tasks = Run();
|
||||||
|
Task firstTask = Task.WhenAny(tasks);
|
||||||
|
Task allTasks = Task.WhenAll(tasks);
|
||||||
|
|
||||||
try
|
try { await firstTask.ConfigureAwait(false); }
|
||||||
{
|
catch (Exception ex) { await DisconnectInternal(ex: ex, skipAwait: true).ConfigureAwait(false); }
|
||||||
await task.ConfigureAwait(false);
|
|
||||||
}
|
//When the first task ends, make sure the rest do too
|
||||||
catch (Exception ex) { await DisconnectInternal(ex, skipAwait: true).ConfigureAwait(false); }
|
await DisconnectInternal(skipAwait: true);
|
||||||
|
try { await allTasks.ConfigureAwait(false); }
|
||||||
|
catch { }
|
||||||
|
|
||||||
bool wasUnexpected = _wasDisconnectUnexpected;
|
bool wasUnexpected = _wasDisconnectUnexpected;
|
||||||
_wasDisconnectUnexpected = false;
|
_wasDisconnectUnexpected = false;
|
||||||
@@ -207,7 +188,7 @@ namespace Discord.Net.WebSockets
|
|||||||
{
|
{
|
||||||
while (!cancelToken.IsCancellationRequested)
|
while (!cancelToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
if (_heartbeatInterval > 0)
|
if (_state == (int)WebSocketState.Connected)
|
||||||
{
|
{
|
||||||
QueueMessage(GetKeepAlive());
|
QueueMessage(GetKeepAlive());
|
||||||
await Task.Delay(_heartbeatInterval, cancelToken).ConfigureAwait(false);
|
await Task.Delay(_heartbeatInterval, cancelToken).ConfigureAwait(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user