Browse Source

Added support for compressed websocket messages.

tags/docs-0.9
RogueException 9 years ago
parent
commit
0f31e18592
5 changed files with 57 additions and 15 deletions
  1. +5
    -1
      src/Discord.Net/API/WebSockets.cs
  2. +3
    -0
      src/Discord.Net/Net/WebSockets/DataWebSocket.cs
  3. +9
    -3
      src/Discord.Net/Net/WebSockets/IWebSocketEngine.cs
  4. +22
    -5
      src/Discord.Net/Net/WebSockets/WebSocket.cs
  5. +18
    -6
      src/Discord.Net/Net/WebSockets/WebSocketSharpEngine.cs

+ 5
- 1
src/Discord.Net/API/WebSockets.cs View File

@@ -56,7 +56,11 @@ namespace Discord.API
public int Version = 3;
[JsonProperty("properties")]
public Dictionary<string, string> Properties = new Dictionary<string, string>();
}
[JsonProperty("large_threshold", NullValueHandling = NullValueHandling.Ignore)]
public int? LargeThreshold;
[JsonProperty("compress", NullValueHandling = NullValueHandling.Ignore)]
public bool? Compress;
}
}
internal sealed class ResumeCommand : WebSocketMessage<ResumeCommand.Data>
{


+ 3
- 0
src/Discord.Net/Net/WebSockets/DataWebSocket.cs View File

@@ -26,6 +26,8 @@ namespace Discord.Net.WebSockets
LoginCommand msg = new LoginCommand();
msg.Payload.Token = token;
msg.Payload.Properties["$device"] = "Discord.Net";
//msg.Payload.LargeThreshold = 50;
msg.Payload.Compress = true;
QueueMessage(msg);
}
private async Task Redirect(string server)
@@ -67,6 +69,7 @@ namespace Discord.Net.WebSockets

protected override async Task ProcessMessage(string json)
{
await base.ProcessMessage(json);
var msg = JsonConvert.DeserializeObject<WebSocketMessage>(json);
if (msg.Sequence.HasValue)
_lastSeq = msg.Sequence.Value;


+ 9
- 3
src/Discord.Net/Net/WebSockets/IWebSocketEngine.cs View File

@@ -5,15 +5,21 @@ using System.Threading.Tasks;

namespace Discord.Net.WebSockets
{
internal class WebSocketMessageEventArgs : EventArgs
internal class WebSocketBinaryMessageEventArgs : EventArgs
{
public readonly byte[] Data;
public WebSocketBinaryMessageEventArgs(byte[] data) { Data = data; }
}
internal class WebSocketTextMessageEventArgs : EventArgs
{
public readonly string Message;
public WebSocketMessageEventArgs(string msg) { Message = msg; }
public WebSocketTextMessageEventArgs(string msg) { Message = msg; }
}

internal interface IWebSocketEngine
{
event EventHandler<WebSocketMessageEventArgs> ProcessMessage;
event EventHandler<WebSocketBinaryMessageEventArgs> BinaryMessage;
event EventHandler<WebSocketTextMessageEventArgs> TextMessage;

Task Connect(string host, CancellationToken cancelToken);
Task Disconnect();


+ 22
- 5
src/Discord.Net/Net/WebSockets/WebSocket.cs View File

@@ -1,6 +1,8 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading;
@@ -51,13 +53,23 @@ namespace Discord.Net.WebSockets
_connectedEvent = new ManualResetEventSlim(false);
_engine = new WebSocketSharpEngine(this, client.Config);
_engine.ProcessMessage += async (s, e) =>
_engine.BinaryMessage += async (s, e) =>
{
using (var compressed = new MemoryStream(e.Data, 2, e.Data.Length - 2))
using (var decompressed = new MemoryStream())
{
using (var zlib = new DeflateStream(compressed, CompressionMode.Decompress))
await zlib.CopyToAsync(decompressed);
decompressed.Position = 0;
using (var reader = new StreamReader(decompressed))
await ProcessMessage(await reader.ReadToEndAsync());
}
};
_engine.TextMessage += async (s, e) =>
{
if (_logLevel >= LogMessageSeverity.Debug)
RaiseOnLog(LogMessageSeverity.Debug, $"In: {e.Message}");
await ProcessMessage(e.Message);
};
}
}

protected async Task BeginConnect()
{
@@ -185,7 +197,12 @@ namespace Discord.Net.WebSockets
RaiseDisconnected(wasDisconnectUnexpected, _disconnectReason?.SourceException);
}

protected abstract Task ProcessMessage(string json);
protected virtual Task ProcessMessage(string json)
{
if (_logLevel >= LogMessageSeverity.Debug)
RaiseOnLog(LogMessageSeverity.Debug, $"In: {json}");
return TaskHelper.CompletedTask;
}
protected abstract object GetKeepAlive();
protected void QueueMessage(object message)


+ 18
- 6
src/Discord.Net/Net/WebSockets/WebSocketSharpEngine.cs View File

@@ -15,11 +15,17 @@ namespace Discord.Net.WebSockets
private readonly WebSocket _parent;
private WSSharpNWebSocket _webSocket;

public event EventHandler<WebSocketMessageEventArgs> ProcessMessage;
private void RaiseProcessMessage(string msg)
public event EventHandler<WebSocketBinaryMessageEventArgs> BinaryMessage;
public event EventHandler<WebSocketTextMessageEventArgs> TextMessage;
private void RaiseBinaryMessage(byte[] data)
{
if (ProcessMessage != null)
ProcessMessage(this, new WebSocketMessageEventArgs(msg));
if (BinaryMessage != null)
BinaryMessage(this, new WebSocketBinaryMessageEventArgs(data));
}
private void RaiseTextMessage(string msg)
{
if (TextMessage != null)
TextMessage(this, new WebSocketTextMessageEventArgs(msg));
}

internal WebSocketSharpEngine(WebSocket parent, DiscordWSClientConfig config)
@@ -34,9 +40,15 @@ namespace Discord.Net.WebSockets
_webSocket = new WSSharpNWebSocket(host);
_webSocket.EmitOnPing = false;
_webSocket.EnableRedirection = true;
_webSocket.Compression = WebSocketSharp.CompressionMethod.None;
_webSocket.Compression = WebSocketSharp.CompressionMethod.Deflate;
_webSocket.SetProxy(_config.ProxyUrl, _config.ProxyCredentials?.UserName, _config.ProxyCredentials?.Password);
_webSocket.OnMessage += (s, e) => RaiseProcessMessage(e.Data);
_webSocket.OnMessage += (s, e) =>
{
if (e.Type == WebSocketSharp.Opcode.Binary)
RaiseBinaryMessage(e.RawData);
else if (e.Type == WebSocketSharp.Opcode.Text)
RaiseTextMessage(e.Data);
};
_webSocket.OnError += async (s, e) =>
{
_parent.RaiseOnLog(LogMessageSeverity.Error, e.Exception.GetBaseException().Message);


Loading…
Cancel
Save