| @@ -15,10 +15,22 @@ namespace Discord | |||||
| if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | ||||
| await LeaveVoiceServer().ConfigureAwait(false); | 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() | public async Task LeaveVoiceServer() | ||||
| { | { | ||||
| @@ -26,9 +38,12 @@ namespace Discord | |||||
| if (_voiceSocket.State != Net.WebSockets.WebSocketState.Disconnected) | 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); | CheckReady(checkVoice: true); | ||||
| _voiceSocket.Wait(); | |||||
| _voiceSocket.WaitForQueue(); | |||||
| await TaskHelper.CompletedTask.ConfigureAwait(false); | await TaskHelper.CompletedTask.ConfigureAwait(false); | ||||
| } | } | ||||
| } | } | ||||
| @@ -32,11 +32,12 @@ namespace Discord | |||||
| private readonly ManualResetEvent _disconnectedEvent; | private readonly ManualResetEvent _disconnectedEvent; | ||||
| private readonly ManualResetEventSlim _connectedEvent; | private readonly ManualResetEventSlim _connectedEvent; | ||||
| private readonly JsonSerializer _serializer; | private readonly JsonSerializer _serializer; | ||||
| protected ExceptionDispatchInfo _disconnectReason; | |||||
| private Task _runTask; | private Task _runTask; | ||||
| private bool _wasDisconnectUnexpected; | |||||
| private string _token; | private string _token; | ||||
| protected ExceptionDispatchInfo _disconnectReason; | |||||
| private bool _wasDisconnectUnexpected; | |||||
| /// <summary> Returns the id of the current logged-in user. </summary> | /// <summary> Returns the id of the current logged-in user. </summary> | ||||
| public string CurrentUserId => _currentUserId; | public string CurrentUserId => _currentUserId; | ||||
| private string _currentUserId; | private string _currentUserId; | ||||
| @@ -754,14 +755,14 @@ namespace Discord | |||||
| //When the first task ends, make sure the rest do too | //When the first task ends, make sure the rest do too | ||||
| await DisconnectInternal(skipAwait: true); | await DisconnectInternal(skipAwait: true); | ||||
| bool wasUnexpected = _wasDisconnectUnexpected; | |||||
| _wasDisconnectUnexpected = false; | |||||
| await Cleanup(wasUnexpected).ConfigureAwait(false); | |||||
| await Cleanup().ConfigureAwait(false); | |||||
| _runTask = null; | _runTask = null; | ||||
| } | } | ||||
| private async Task Cleanup(bool wasUnexpected) | |||||
| private async Task Cleanup() | |||||
| { | { | ||||
| var wasDisconnectUnexpected = _wasDisconnectUnexpected; | |||||
| _wasDisconnectUnexpected = false; | |||||
| await _dataSocket.Disconnect().ConfigureAwait(false); | await _dataSocket.Disconnect().ConfigureAwait(false); | ||||
| if (_config.EnableVoice) | if (_config.EnableVoice) | ||||
| await _voiceSocket.Disconnect().ConfigureAwait(false); | await _voiceSocket.Disconnect().ConfigureAwait(false); | ||||
| @@ -783,7 +784,7 @@ namespace Discord | |||||
| _currentUserId = null; | _currentUserId = null; | ||||
| _token = null; | _token = null; | ||||
| if (!wasUnexpected) | |||||
| if (!wasDisconnectUnexpected) | |||||
| { | { | ||||
| _state = (int)DiscordClientState.Disconnected; | _state = (int)DiscordClientState.Disconnected; | ||||
| _disconnectedEvent.Set(); | _disconnectedEvent.Set(); | ||||
| @@ -119,9 +119,10 @@ namespace Discord.Net.WebSockets | |||||
| joinVoice.Payload.ChannelId = channelId; | joinVoice.Payload.ChannelId = channelId; | ||||
| QueueMessage(joinVoice); | QueueMessage(joinVoice); | ||||
| } | } | ||||
| public void SendLeaveVoice() | |||||
| public void SendLeaveVoice(string serverId) | |||||
| { | { | ||||
| var leaveVoice = new Commands.JoinVoice(); | var leaveVoice = new Commands.JoinVoice(); | ||||
| leaveVoice.Payload.ServerId = serverId; | |||||
| QueueMessage(leaveVoice); | QueueMessage(leaveVoice); | ||||
| } | } | ||||
| } | } | ||||
| @@ -514,9 +514,13 @@ namespace Discord.Net.WebSockets | |||||
| return new VoiceCommands.KeepAlive(); | return new VoiceCommands.KeepAlive(); | ||||
| } | } | ||||
| public void Wait() | |||||
| public void WaitForQueue() | |||||
| { | { | ||||
| _sendQueueEmptyWait.Wait(); | |||||
| _sendQueueEmptyWait.Wait(_cancelToken); | |||||
| } | |||||
| public void WaitForConnection() | |||||
| { | |||||
| _connectedEvent.Wait(); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -37,31 +37,33 @@ namespace Discord.Net.WebSockets | |||||
| protected readonly IWebSocketEngine _engine; | protected readonly IWebSocketEngine _engine; | ||||
| protected readonly DiscordClient _client; | protected readonly DiscordClient _client; | ||||
| protected readonly LogMessageSeverity _logLevel; | 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; | protected int _loginTimeout, _heartbeatInterval; | ||||
| private DateTime _lastHeartbeat; | private DateTime _lastHeartbeat; | ||||
| private Task _runTask; | 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 ParentCancelToken { get; set; } | ||||
| public CancellationToken CancelToken => _cancelToken; | public CancellationToken CancelToken => _cancelToken; | ||||
| private CancellationTokenSource _cancelTokenSource; | private CancellationTokenSource _cancelTokenSource; | ||||
| protected CancellationToken _cancelToken; | protected CancellationToken _cancelToken; | ||||
| public string Host { get; set; } | |||||
| public WebSocketState State => (WebSocketState)_state; | |||||
| protected int _state; | |||||
| public WebSocket(DiscordClient client) | public WebSocket(DiscordClient client) | ||||
| { | { | ||||
| _client = client; | _client = client; | ||||
| _logLevel = client.Config.LogLevel; | _logLevel = client.Config.LogLevel; | ||||
| _loginTimeout = client.Config.ConnectionTimeout; | _loginTimeout = client.Config.ConnectionTimeout; | ||||
| _cancelToken = new CancellationToken(true); | _cancelToken = new CancellationToken(true); | ||||
| _connectedEvent = new ManualResetEventSlim(false); | |||||
| _engine = new BuiltInWebSocketEngine(client.Config.WebSocketInterval); | _engine = new BuiltInWebSocketEngine(client.Config.WebSocketInterval); | ||||
| _engine.ProcessMessage += async (s, e) => | _engine.ProcessMessage += async (s, e) => | ||||
| @@ -102,6 +104,7 @@ namespace Discord.Net.WebSockets | |||||
| protected void CompleteConnect() | protected void CompleteConnect() | ||||
| { | { | ||||
| _state = (int)WebSocketState.Connected; | _state = (int)WebSocketState.Connected; | ||||
| _connectedEvent.Set(); | |||||
| RaiseConnected(); | RaiseConnected(); | ||||
| } | } | ||||
| /*public Task Reconnect(CancellationToken cancelToken) | /*public Task Reconnect(CancellationToken cancelToken) | ||||
| @@ -184,6 +187,7 @@ namespace Discord.Net.WebSockets | |||||
| var oldState = _state; | var oldState = _state; | ||||
| _state = (int)WebSocketState.Disconnected; | _state = (int)WebSocketState.Disconnected; | ||||
| _runTask = null; | _runTask = null; | ||||
| _connectedEvent.Reset(); | |||||
| if (disconnectState == WebSocketState.Connected) | if (disconnectState == WebSocketState.Connected) | ||||
| RaiseDisconnected(wasDisconnectUnexpected, _disconnectReason?.SourceException); | RaiseDisconnected(wasDisconnectUnexpected, _disconnectReason?.SourceException); | ||||