| @@ -75,8 +75,9 @@ namespace Discord | |||
| public Users Users => _users; | |||
| private readonly Users _users; | |||
| public CancellationToken CancelToken => _cancelToken.Token; | |||
| private CancellationTokenSource _cancelToken; | |||
| public CancellationToken CancelToken => _cancelToken; | |||
| private CancellationTokenSource _cancelTokenSource; | |||
| private CancellationToken _cancelToken; | |||
| /// <summary> Initializes a new instance of the DiscordClient class. </summary> | |||
| public DiscordClient(DiscordClientConfig config = null) | |||
| @@ -509,7 +510,7 @@ namespace Discord | |||
| if (_config.EnableVoice) | |||
| { | |||
| string host = "wss://" + data.Endpoint.Split(':')[0]; | |||
| await _voiceSocket.Login(host, data.GuildId, _currentUserId, _dataSocket.SessionId, data.Token).ConfigureAwait(false); | |||
| await _voiceSocket.Login(host, data.GuildId, _currentUserId, _dataSocket.SessionId, data.Token, _cancelToken).ConfigureAwait(false); | |||
| } | |||
| } | |||
| break; | |||
| @@ -576,7 +577,8 @@ namespace Discord | |||
| try | |||
| { | |||
| _disconnectedEvent.Reset(); | |||
| _cancelToken = new CancellationTokenSource(); | |||
| _cancelTokenSource = new CancellationTokenSource(); | |||
| _cancelToken = _cancelTokenSource.Token; | |||
| _state = (int)DiscordClientState.Connecting; | |||
| _api.Token = token; | |||
| @@ -584,14 +586,14 @@ namespace Discord | |||
| if (_config.LogLevel >= LogMessageSeverity.Verbose) | |||
| RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Authentication, $"Websocket endpoint: {url}"); | |||
| await _dataSocket.Login(url, token).ConfigureAwait(false); | |||
| await _dataSocket.Login(url, token, _cancelToken).ConfigureAwait(false); | |||
| _runTask = RunTasks(); | |||
| try | |||
| { | |||
| //Cancel if either Disconnect is called, data socket errors or timeout is reached | |||
| var cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelToken.Token, _dataSocket.CancelToken).Token; | |||
| var cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelToken, _dataSocket.CancelToken).Token; | |||
| if (!_connectedEvent.Wait(_config.ConnectionTimeout, cancelToken)) | |||
| throw new Exception("Operation timed out."); | |||
| } | |||
| @@ -638,7 +640,7 @@ namespace Discord | |||
| { | |||
| _wasDisconnectUnexpected = isUnexpected; | |||
| _disconnectReason = ExceptionDispatchInfo.Capture(ex); | |||
| _cancelToken.Cancel(); | |||
| _cancelTokenSource.Cancel(); | |||
| } | |||
| if (!skipAwait) | |||
| @@ -730,7 +732,7 @@ namespace Discord | |||
| //Experimental | |||
| private Task MessageQueueLoop() | |||
| { | |||
| var cancelToken = _cancelToken.Token; | |||
| var cancelToken = _cancelToken; | |||
| int interval = _config.MessageQueueInterval; | |||
| return Task.Run(async () => | |||
| @@ -1,6 +1,7 @@ | |||
| using Newtonsoft.Json; | |||
| using Newtonsoft.Json.Linq; | |||
| using System; | |||
| using System.Threading; | |||
| using System.Threading.Tasks; | |||
| namespace Discord.Net.WebSockets | |||
| @@ -18,9 +19,9 @@ namespace Discord.Net.WebSockets | |||
| { | |||
| } | |||
| public async Task Login(string host, string token) | |||
| public async Task Login(string host, string token, CancellationToken cancelToken) | |||
| { | |||
| await base.Connect(host); | |||
| await base.Connect(host, cancelToken); | |||
| Commands.Login msg = new Commands.Login(); | |||
| msg.Payload.Token = token; | |||
| @@ -52,14 +52,14 @@ namespace Discord.Net.WebSockets | |||
| _targetAudioBufferLength = client.Config.VoiceBufferLength / 20; //20 ms frames | |||
| } | |||
| public Task Login(string host, string serverId, string userId, string sessionId, string token) | |||
| public Task Login(string host, string serverId, string userId, string sessionId, string token, CancellationToken cancelToken) | |||
| { | |||
| _serverId = serverId; | |||
| _userId = userId; | |||
| _sessionId = sessionId; | |||
| _token = token; | |||
| return base.Connect(host); | |||
| return base.Connect(host, cancelToken); | |||
| } | |||
| protected override Task[] Run() | |||
| @@ -110,8 +110,7 @@ namespace Discord.Net.WebSockets | |||
| private async Task ReceiveVoiceAsync() | |||
| { | |||
| var cancelSource = _cancelToken; | |||
| var cancelToken = cancelSource.Token; | |||
| var cancelToken = _cancelToken; | |||
| await Task.Run(async () => | |||
| { | |||
| @@ -145,8 +144,8 @@ namespace Discord.Net.WebSockets | |||
| #else | |||
| private Task SendVoiceAsync() | |||
| { | |||
| var cancelSource = _cancelToken; | |||
| var cancelToken = cancelSource.Token; | |||
| var cancelToken = _cancelToken; | |||
| return Task.Run(async () => | |||
| { | |||
| #endif | |||
| @@ -239,7 +238,7 @@ namespace Discord.Net.WebSockets | |||
| //Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken | |||
| private Task WatcherAsync() | |||
| { | |||
| var cancelToken = _cancelToken.Token; | |||
| var cancelToken = _cancelToken; | |||
| return cancelToken.Wait() | |||
| .ContinueWith(_ => _udp.Close()); | |||
| } | |||
| @@ -387,7 +386,7 @@ namespace Discord.Net.WebSockets | |||
| public void SendPCMFrames(byte[] data, int bytes) | |||
| { | |||
| var cancelToken = _cancelToken.Token; | |||
| var cancelToken = _cancelToken; | |||
| if (!_isReady || cancelToken == null) | |||
| throw new InvalidOperationException("Not connected to a voice server."); | |||
| if (bytes == 0) | |||
| @@ -441,7 +440,7 @@ namespace Discord.Net.WebSockets | |||
| Buffer.BlockCopy(_encodingBuffer, 0, payload, 0, encodedLength); | |||
| //Wait until the queue has a spot open | |||
| _sendQueueWait.Wait(_cancelToken.Token); | |||
| _sendQueueWait.Wait(_cancelToken); | |||
| _sendQueue.Enqueue(payload); | |||
| if (_sendQueue.Count >= _targetAudioBufferLength) | |||
| _sendQueueWait.Reset(); | |||
| @@ -47,8 +47,9 @@ namespace Discord.Net.WebSockets | |||
| protected ExceptionDispatchInfo _disconnectReason; | |||
| private bool _wasDisconnectUnexpected; | |||
| public CancellationToken CancelToken => _cancelToken.Token; | |||
| protected CancellationTokenSource _cancelToken; | |||
| public CancellationToken CancelToken => _cancelToken; | |||
| private CancellationTokenSource _cancelTokenSource; | |||
| protected CancellationToken _cancelToken; | |||
| public WebSocket(DiscordClient client) | |||
| { | |||
| @@ -64,20 +65,18 @@ namespace Discord.Net.WebSockets | |||
| }; | |||
| } | |||
| protected virtual async Task Connect(string host) | |||
| protected virtual async Task Connect(string host, CancellationToken cancelToken) | |||
| { | |||
| if (_state != (int)WebSocketState.Disconnected) | |||
| throw new InvalidOperationException("Client is already connected or connecting to the server."); | |||
| try | |||
| { | |||
| await Disconnect().ConfigureAwait(false); | |||
| _state = (int)WebSocketState.Connecting; | |||
| _cancelToken = new CancellationTokenSource(); | |||
| _cancelTokenSource = new CancellationTokenSource(); | |||
| _cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelTokenSource.Token, cancelToken).Token; | |||
| await _engine.Connect(host, _cancelToken.Token).ConfigureAwait(false); | |||
| await _engine.Connect(host, _cancelToken).ConfigureAwait(false); | |||
| _host = host; | |||
| _lastHeartbeat = DateTime.UtcNow; | |||
| @@ -94,8 +93,8 @@ namespace Discord.Net.WebSockets | |||
| _state = (int)WebSocketState.Connected; | |||
| RaiseConnected(); | |||
| } | |||
| public Task Reconnect() | |||
| => Connect(_host); | |||
| /*public Task Reconnect(CancellationToken cancelToken) | |||
| => Connect(_host, _cancelToken);*/ | |||
| public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false); | |||
| protected async Task DisconnectInternal(Exception ex, bool isUnexpected = true, bool skipAwait = false) | |||
| @@ -118,7 +117,7 @@ namespace Discord.Net.WebSockets | |||
| { | |||
| _wasDisconnectUnexpected = isUnexpected; | |||
| _disconnectReason = ExceptionDispatchInfo.Capture(ex); | |||
| _cancelToken.Cancel(); | |||
| _cancelTokenSource.Cancel(); | |||
| } | |||
| if (!skipAwait) | |||
| @@ -154,12 +153,16 @@ namespace Discord.Net.WebSockets | |||
| } | |||
| protected virtual Task[] Run() | |||
| { | |||
| var cancelToken = _cancelToken.Token; | |||
| var cancelToken = _cancelToken; | |||
| return _engine.RunTasks(cancelToken) | |||
| .Concat(new Task[] { HeartbeatAsync(cancelToken) }) | |||
| .ToArray(); | |||
| } | |||
| protected virtual Task Cleanup() { return TaskHelper.CompletedTask; } | |||
| protected virtual Task Cleanup() | |||
| { | |||
| _cancelTokenSource = null; | |||
| return TaskHelper.CompletedTask; | |||
| } | |||
| protected abstract Task ProcessMessage(string json); | |||
| protected abstract object GetKeepAlive(); | |||