@@ -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); | ||||