|
|
@@ -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<byte>(buffer), cancelToken); |
|
|
|
if (_webSocket.State != WebSocketState.Open || cancelToken.IsCancellationRequested) |
|
|
|
return; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(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<byte>(message, offset, count), WebSocketMessageType.Text, isLast, cancelToken); |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
await _webSocket.SendAsync(new ArraySegment<byte>(message, offset, count), WebSocketMessageType.Text, isLast, cancelToken); |
|
|
|
} |
|
|
|
catch (Win32Exception ex) |
|
|
|
when (ex.HResult == HR_TIMEOUT) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|