diff --git a/src/Discord.Net/DiscordWebSocket.cs b/src/Discord.Net/DiscordWebSocket.cs index f68d245a7..4462c6313 100644 --- a/src/Discord.Net/DiscordWebSocket.cs +++ b/src/Discord.Net/DiscordWebSocket.cs @@ -1,6 +1,7 @@ using Newtonsoft.Json; using System; using System.Collections.Concurrent; +using System.ComponentModel; using System.Net.WebSockets; using System.Text; using System.Threading; @@ -12,6 +13,7 @@ namespace Discord { private const int ReceiveChunkSize = 4096; private const int SendChunkSize = 4096; + private const int HR_TIMEOUT = -2147012894; protected readonly DiscordClient _client; protected readonly int _sendInterval; @@ -90,7 +92,7 @@ namespace Discord { if (_task != null) { - try { DisconnectInternal(new Exception("Disconnect requested by user.")); } catch (NullReferenceException) { } + try { DisconnectInternal(new Exception("Disconnect requested by user."), false); } catch (NullReferenceException) { } try { await _task; } catch (NullReferenceException) { } } } @@ -99,12 +101,11 @@ namespace Discord { _disconnectToken.Cancel(); } - protected void DisconnectInternal(Exception ex) + protected void DisconnectInternal(Exception ex, bool isUnexpected = true) { if (_disconnectReason == null) { - if (ex == null) - ex = new Exception("Disconnect requested by user."); + _wasDisconnectUnexpected = isUnexpected; _disconnectReason = ex; _disconnectToken.Cancel(); } @@ -141,14 +142,27 @@ namespace Discord { while (_webSocket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested) { - WebSocketReceiveResult result; + WebSocketReceiveResult result = null; do { - result = await _webSocket.ReceiveAsync(new ArraySegment(buffer), cancelToken); + if (_webSocket.State != WebSocketState.Open || cancelToken.IsCancellationRequested) + return; + + try + { + result = await _webSocket.ReceiveAsync(new ArraySegment(buffer), cancelToken); + } + catch (Win32Exception ex) + when (ex.HResult == HR_TIMEOUT) + { + string msg = $"Connection timed out."; + RaiseOnDebugMessage(DebugMessageType.Connection, msg); + DisconnectInternal(new Exception(msg)); + return; + } if (result.MessageType == WebSocketMessageType.Close) { - _wasDisconnectUnexpected = true; string msg = $"Got Close Message ({result.CloseStatus?.ToString() ?? "Unexpected"}, {result.CloseStatusDescription ?? "No Reason"})"; RaiseOnDebugMessage(DebugMessageType.Connection, msg); DisconnectInternal(new Exception(msg)); @@ -159,7 +173,7 @@ namespace Discord builder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); } - while (!result.EndOfMessage); + while (result == null || !result.EndOfMessage); #if DEBUG System.Diagnostics.Debug.WriteLine(">>> " + builder.ToString()); @@ -235,8 +249,16 @@ namespace Discord count = message.Length - (i * SendChunkSize); else count = SendChunkSize; - - await _webSocket.SendAsync(new ArraySegment(message, offset, count), WebSocketMessageType.Text, isLast, cancelToken); + + try + { + await _webSocket.SendAsync(new ArraySegment(message, offset, count), WebSocketMessageType.Text, isLast, cancelToken); + } + catch (Win32Exception ex) + when (ex.HResult == HR_TIMEOUT) + { + return; + } } }