From 454bd6f43d69c7fa9043262f00c3d68eda827df4 Mon Sep 17 00:00:00 2001 From: RogueException Date: Wed, 23 Sep 2015 22:42:25 -0300 Subject: [PATCH] Voice stability patches --- src/Discord.Net/DiscordClient.Voice.cs | 31 ++++++++++++++----- src/Discord.Net/DiscordClient.cs | 17 +++++----- .../Net/WebSockets/DataWebSocket.cs | 3 +- .../Net/WebSockets/VoiceWebSocket.cs | 8 +++-- src/Discord.Net/Net/WebSockets/WebSocket.cs | 20 +++++++----- 5 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/Discord.Net/DiscordClient.Voice.cs b/src/Discord.Net/DiscordClient.Voice.cs index 8e5962f1f..3a434a99e 100644 --- a/src/Discord.Net/DiscordClient.Voice.cs +++ b/src/Discord.Net/DiscordClient.Voice.cs @@ -15,10 +15,22 @@ namespace Discord if (channelId == null) throw new ArgumentNullException(nameof(channelId)); await LeaveVoiceServer().ConfigureAwait(false); - _voiceSocket.SetServer(serverId); - _dataSocket.SendJoinVoice(serverId, channelId); - //await _voiceSocket.WaitForConnection().ConfigureAwait(false); - //TODO: Add another ManualResetSlim to wait on here, base it off of DiscordClient's setup + + try + { + await Task.Run(() => + { + _voiceSocket.SetServer(serverId); + _dataSocket.SendJoinVoice(serverId, channelId); + _voiceSocket.WaitForConnection(); + }) + .Timeout(_config.ConnectionTimeout) + .ConfigureAwait(false); + } + catch (TaskCanceledException) + { + await LeaveVoiceServer().ConfigureAwait(false); + } } public async Task LeaveVoiceServer() { @@ -26,9 +38,12 @@ namespace Discord if (_voiceSocket.State != Net.WebSockets.WebSocketState.Disconnected) { - await _voiceSocket.Disconnect().ConfigureAwait(false); - await TaskHelper.CompletedTask.ConfigureAwait(false); - _dataSocket.SendLeaveVoice(); + var serverId = _voiceSocket.CurrentVoiceServerId; + if (serverId != null) + { + await _voiceSocket.Disconnect().ConfigureAwait(false); + _dataSocket.SendLeaveVoice(serverId); + } } } @@ -57,7 +72,7 @@ namespace Discord { CheckReady(checkVoice: true); - _voiceSocket.Wait(); + _voiceSocket.WaitForQueue(); await TaskHelper.CompletedTask.ConfigureAwait(false); } } diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index c3af7dcca..b13933267 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -32,11 +32,12 @@ namespace Discord private readonly ManualResetEvent _disconnectedEvent; private readonly ManualResetEventSlim _connectedEvent; private readonly JsonSerializer _serializer; - protected ExceptionDispatchInfo _disconnectReason; private Task _runTask; - private bool _wasDisconnectUnexpected; private string _token; + protected ExceptionDispatchInfo _disconnectReason; + private bool _wasDisconnectUnexpected; + /// Returns the id of the current logged-in user. public string CurrentUserId => _currentUserId; private string _currentUserId; @@ -754,14 +755,14 @@ namespace Discord //When the first task ends, make sure the rest do too await DisconnectInternal(skipAwait: true); - bool wasUnexpected = _wasDisconnectUnexpected; - _wasDisconnectUnexpected = false; - - await Cleanup(wasUnexpected).ConfigureAwait(false); + await Cleanup().ConfigureAwait(false); _runTask = null; } - private async Task Cleanup(bool wasUnexpected) + private async Task Cleanup() { + var wasDisconnectUnexpected = _wasDisconnectUnexpected; + _wasDisconnectUnexpected = false; + await _dataSocket.Disconnect().ConfigureAwait(false); if (_config.EnableVoice) await _voiceSocket.Disconnect().ConfigureAwait(false); @@ -783,7 +784,7 @@ namespace Discord _currentUserId = null; _token = null; - if (!wasUnexpected) + if (!wasDisconnectUnexpected) { _state = (int)DiscordClientState.Disconnected; _disconnectedEvent.Set(); diff --git a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs index ccba18bd8..2f5effb9c 100644 --- a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs +++ b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs @@ -119,9 +119,10 @@ namespace Discord.Net.WebSockets joinVoice.Payload.ChannelId = channelId; QueueMessage(joinVoice); } - public void SendLeaveVoice() + public void SendLeaveVoice(string serverId) { var leaveVoice = new Commands.JoinVoice(); + leaveVoice.Payload.ServerId = serverId; QueueMessage(leaveVoice); } } diff --git a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs index 6da093bb4..52f76a3c2 100644 --- a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs +++ b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs @@ -514,9 +514,13 @@ namespace Discord.Net.WebSockets return new VoiceCommands.KeepAlive(); } - public void Wait() + public void WaitForQueue() { - _sendQueueEmptyWait.Wait(); + _sendQueueEmptyWait.Wait(_cancelToken); + } + public void WaitForConnection() + { + _connectedEvent.Wait(); } } } diff --git a/src/Discord.Net/Net/WebSockets/WebSocket.cs b/src/Discord.Net/Net/WebSockets/WebSocket.cs index 6728dab4e..aa12279c8 100644 --- a/src/Discord.Net/Net/WebSockets/WebSocket.cs +++ b/src/Discord.Net/Net/WebSockets/WebSocket.cs @@ -37,31 +37,33 @@ namespace Discord.Net.WebSockets protected readonly IWebSocketEngine _engine; protected readonly DiscordClient _client; protected readonly LogMessageSeverity _logLevel; + protected readonly ManualResetEventSlim _connectedEvent; - public string Host { get; set; } + protected ExceptionDispatchInfo _disconnectReason; + protected bool _wasDisconnectUnexpected; + protected WebSocketState _disconnectState; protected int _loginTimeout, _heartbeatInterval; private DateTime _lastHeartbeat; private Task _runTask; - public WebSocketState State => (WebSocketState)_state; - protected int _state; - - protected ExceptionDispatchInfo _disconnectReason; - protected bool _wasDisconnectUnexpected; - protected WebSocketState _disconnectState; - public CancellationToken ParentCancelToken { get; set; } public CancellationToken CancelToken => _cancelToken; private CancellationTokenSource _cancelTokenSource; protected CancellationToken _cancelToken; + public string Host { get; set; } + + public WebSocketState State => (WebSocketState)_state; + protected int _state; + public WebSocket(DiscordClient client) { _client = client; _logLevel = client.Config.LogLevel; _loginTimeout = client.Config.ConnectionTimeout; _cancelToken = new CancellationToken(true); + _connectedEvent = new ManualResetEventSlim(false); _engine = new BuiltInWebSocketEngine(client.Config.WebSocketInterval); _engine.ProcessMessage += async (s, e) => @@ -102,6 +104,7 @@ namespace Discord.Net.WebSockets protected void CompleteConnect() { _state = (int)WebSocketState.Connected; + _connectedEvent.Set(); RaiseConnected(); } /*public Task Reconnect(CancellationToken cancelToken) @@ -184,6 +187,7 @@ namespace Discord.Net.WebSockets var oldState = _state; _state = (int)WebSocketState.Disconnected; _runTask = null; + _connectedEvent.Reset(); if (disconnectState == WebSocketState.Connected) RaiseDisconnected(wasDisconnectUnexpected, _disconnectReason?.SourceException);