Browse Source

Added better WebSocket disconnect support

tags/docs-0.9
Brandon Smith 9 years ago
parent
commit
61644d1f77
1 changed files with 32 additions and 10 deletions
  1. +32
    -10
      src/Discord.Net/DiscordWebSocket.cs

+ 32
- 10
src/Discord.Net/DiscordWebSocket.cs View File

@@ -1,6 +1,7 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.ComponentModel;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@@ -12,6 +13,7 @@ namespace Discord
{ {
private const int ReceiveChunkSize = 4096; private const int ReceiveChunkSize = 4096;
private const int SendChunkSize = 4096; private const int SendChunkSize = 4096;
private const int HR_TIMEOUT = -2147012894;


protected readonly DiscordClient _client; protected readonly DiscordClient _client;
protected readonly int _sendInterval; protected readonly int _sendInterval;
@@ -90,7 +92,7 @@ namespace Discord
{ {
if (_task != null) 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) { } try { await _task; } catch (NullReferenceException) { }
} }
} }
@@ -99,12 +101,11 @@ namespace Discord
{ {
_disconnectToken.Cancel(); _disconnectToken.Cancel();
} }
protected void DisconnectInternal(Exception ex)
protected void DisconnectInternal(Exception ex, bool isUnexpected = true)
{ {
if (_disconnectReason == null) if (_disconnectReason == null)
{ {
if (ex == null)
ex = new Exception("Disconnect requested by user.");
_wasDisconnectUnexpected = isUnexpected;
_disconnectReason = ex; _disconnectReason = ex;
_disconnectToken.Cancel(); _disconnectToken.Cancel();
} }
@@ -141,14 +142,27 @@ namespace Discord
{ {
while (_webSocket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested) while (_webSocket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested)
{ {
WebSocketReceiveResult result;
WebSocketReceiveResult result = null;
do 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) if (result.MessageType == WebSocketMessageType.Close)
{ {
_wasDisconnectUnexpected = true;
string msg = $"Got Close Message ({result.CloseStatus?.ToString() ?? "Unexpected"}, {result.CloseStatusDescription ?? "No Reason"})"; string msg = $"Got Close Message ({result.CloseStatus?.ToString() ?? "Unexpected"}, {result.CloseStatusDescription ?? "No Reason"})";
RaiseOnDebugMessage(DebugMessageType.Connection, msg); RaiseOnDebugMessage(DebugMessageType.Connection, msg);
DisconnectInternal(new Exception(msg)); DisconnectInternal(new Exception(msg));
@@ -159,7 +173,7 @@ namespace Discord
builder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); builder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count));


} }
while (!result.EndOfMessage);
while (result == null || !result.EndOfMessage);


#if DEBUG #if DEBUG
System.Diagnostics.Debug.WriteLine(">>> " + builder.ToString()); System.Diagnostics.Debug.WriteLine(">>> " + builder.ToString());
@@ -235,8 +249,16 @@ namespace Discord
count = message.Length - (i * SendChunkSize); count = message.Length - (i * SendChunkSize);
else else
count = SendChunkSize; 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;
}
} }
} }




Loading…
Cancel
Save