Browse Source

Added WebSocketSharp support and fixed Mono issues

tags/docs-0.9
RogueException 9 years ago
parent
commit
9c9884c1ae
9 changed files with 130 additions and 23 deletions
  1. +6
    -0
      src/Discord.Net.Net45/Discord.Net.csproj
  2. +1
    -0
      src/Discord.Net.Net45/packages.config
  3. +1
    -1
      src/Discord.Net/WebSockets/Data/DataWebSocket.cs
  4. +4
    -2
      src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs
  5. +12
    -9
      src/Discord.Net/WebSockets/WebSocket.BuiltIn.cs
  6. +88
    -0
      src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs
  7. +13
    -8
      src/Discord.Net/WebSockets/WebSocket.cs
  8. +4
    -2
      src/Discord.Net/project.json
  9. +1
    -1
      test/Discord.Net.Tests/Discord.Net.Tests.csproj

+ 6
- 0
src/Discord.Net.Net45/Discord.Net.csproj View File

@@ -59,6 +59,9 @@
<Reference Include="RestSharp, Version=105.2.3.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\..\..\DiscordBot\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll</HintPath>
</Reference>
<Reference Include="websocket-sharp, Version=1.0.2.36589, Culture=neutral, PublicKeyToken=5660b08a1845a91e">
<HintPath>..\..\..\DiscordBot\packages\WebSocketSharp.1.0.3-rc9\lib\websocket-sharp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="lib\libopus.so" />
@@ -241,6 +244,9 @@
<Compile Include="..\Discord.Net\WebSockets\WebSocket.Events.cs">
<Link>WebSockets\WebSocket.Events.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\WebSockets\WebSocket.WebSocketSharp.cs">
<Link>WebSockets\WebSocket.WebSocketSharp.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\WebSockets\WebSocketMessage.cs">
<Link>WebSockets\WebSocketMessage.cs</Link>
</Compile>


+ 1
- 0
src/Discord.Net.Net45/packages.config View File

@@ -2,4 +2,5 @@
<packages>
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="RestSharp" version="105.2.3" targetFramework="net45" />
<package id="WebSocketSharp" version="1.0.3-rc9" targetFramework="net45" />
</packages>

+ 1
- 1
src/Discord.Net/WebSockets/Data/DataWebSocket.cs View File

@@ -40,7 +40,7 @@ namespace Discord.WebSockets.Data
{
try
{
var cancelToken = ParentCancelToken;
var cancelToken = ParentCancelToken.Value;
await Task.Delay(_client.Config.ReconnectDelay, cancelToken).ConfigureAwait(false);
while (!cancelToken.IsCancellationRequested)
{


+ 4
- 2
src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs View File

@@ -85,7 +85,7 @@ namespace Discord.WebSockets.Voice
{
try
{
var cancelToken = ParentCancelToken;
var cancelToken = ParentCancelToken.Value;
await Task.Delay(_client.Config.ReconnectDelay, cancelToken).ConfigureAwait(false);
while (!cancelToken.IsCancellationRequested)
{
@@ -127,7 +127,8 @@ namespace Discord.WebSockets.Voice
{
#if USE_THREAD
_sendThread = new Thread(new ThreadStart(() => SendVoiceAsync(_cancelToken)));
_sendThread.Start();
_sendThread.IsBackground = true;
_sendThread.Start();
#else
tasks.Add(SendVoiceAsync());
#endif
@@ -138,6 +139,7 @@ namespace Discord.WebSockets.Voice
if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) != 0)
{
_receiveThread = new Thread(new ThreadStart(() => ReceiveVoiceAsync(_cancelToken)));
_sendThread.IsBackground = true;
_receiveThread.Start();
}
else //Dont make an OS thread if we only want to capture one packet...


+ 12
- 9
src/Discord.Net/WebSockets/WebSocket.BuiltIn.cs View File

@@ -1,4 +1,5 @@
using Discord.Helpers;
#if DNXCORE50
using Discord.Helpers;
using System;
using System.Collections.Concurrent;
using System.ComponentModel;
@@ -16,7 +17,7 @@ namespace Discord.WebSockets
private const int SendChunkSize = 4096;
private const int HR_TIMEOUT = -2147012894;

private readonly ConcurrentQueue<byte[]> _sendQueue;
private readonly ConcurrentQueue<string> _sendQueue;
private readonly int _sendInterval;
private ClientWebSocket _webSocket;

@@ -30,7 +31,7 @@ namespace Discord.WebSockets
public BuiltInWebSocketEngine(int sendInterval)
{
_sendInterval = sendInterval;
_sendQueue = new ConcurrentQueue<byte[]>();
_sendQueue = new ConcurrentQueue<string>();
}

public Task Connect(string host, CancellationToken cancelToken)
@@ -42,7 +43,7 @@ namespace Discord.WebSockets

public Task Disconnect()
{
byte[] ignored;
string ignored;
while (_sendQueue.TryDequeue(out ignored)) { }
_webSocket.Dispose();
_webSocket = new ClientWebSocket();
@@ -107,12 +108,13 @@ namespace Discord.WebSockets
{
try
{
byte[] bytes;
while (_webSocket.State == State.Open && !cancelToken.IsCancellationRequested)
{
while (_sendQueue.TryDequeue(out bytes))
string json;
while (_sendQueue.TryDequeue(out json))
{
var frameCount = (int)Math.Ceiling((double)bytes.Length / SendChunkSize);
byte[] bytes = Encoding.UTF8.GetBytes(json);
int frameCount = (int)Math.Ceiling((double)bytes.Length / SendChunkSize);

int offset = 0;
for (var i = 0; i < frameCount; i++, offset += SendChunkSize)
@@ -142,9 +144,10 @@ namespace Discord.WebSockets
});
}
public void QueueMessage(byte[] message)
public void QueueMessage(string message)
{
_sendQueue.Enqueue(message);
}
}
}
}
#endif

+ 88
- 0
src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs View File

@@ -0,0 +1,88 @@
#if !DNXCORE50
using Discord.Helpers;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WSSharpNWebSocket = WebSocketSharp.WebSocket;

namespace Discord.WebSockets
{
public class WSSharpWebSocketEngine : IWebSocketEngine
{
private readonly ConcurrentQueue<string> _sendQueue;
private readonly int _sendInterval;
private readonly string _userAgent;
private readonly WebSocket _parent;
private WSSharpNWebSocket _webSocket;

public event EventHandler<WebSocketMessageEventArgs> ProcessMessage;
private void RaiseProcessMessage(string msg)
{
if (ProcessMessage != null)
ProcessMessage(this, new WebSocketMessageEventArgs(msg));
}

internal WSSharpWebSocketEngine(WebSocket parent, string userAgent, int sendInterval)
{
_parent = parent;
_userAgent = userAgent;
_sendInterval = sendInterval;
_sendQueue = new ConcurrentQueue<string>();
}

public Task Connect(string host, CancellationToken cancelToken)
{
_webSocket = new WSSharpNWebSocket(host);
_webSocket.EmitOnPing = false;
_webSocket.EnableRedirection = true;
_webSocket.Compression = WebSocketSharp.CompressionMethod.None;
_webSocket.OnMessage += (s, e) => RaiseProcessMessage(e.Data);
_webSocket.OnError += (s, e) => _parent.RaiseOnLog(LogMessageSeverity.Error, $"Websocket Error: {e.Message}");
_webSocket.Connect();
return TaskHelper.CompletedTask;
}

public Task Disconnect()
{
string ignored;
while (_sendQueue.TryDequeue(out ignored)) { }
_webSocket.Close();
return TaskHelper.CompletedTask;
}

public Task[] GetTasks(CancellationToken cancelToken)
{
return new Task[]
{
SendAsync(cancelToken)
};
}

private Task SendAsync(CancellationToken cancelToken)
{
return Task.Run(async () =>
{
try
{
while (_webSocket.IsAlive && !cancelToken.IsCancellationRequested)
{
string json;
while (_sendQueue.TryDequeue(out json))
_webSocket.Send(json);
await Task.Delay(_sendInterval, cancelToken).ConfigureAwait(false);
}
}
catch (OperationCanceledException) { }
});
}

public void QueueMessage(string message)
{
_sendQueue.Enqueue(message);
}
}
}
#endif

+ 13
- 8
src/Discord.Net/WebSockets/WebSocket.cs View File

@@ -28,7 +28,7 @@ namespace Discord.WebSockets

Task Connect(string host, CancellationToken cancelToken);
Task Disconnect();
void QueueMessage(byte[] message);
void QueueMessage(string message);
Task[] GetTasks(CancellationToken cancelToken);
}

@@ -47,7 +47,7 @@ namespace Discord.WebSockets
private DateTime _lastHeartbeat;
private Task _runTask;

public CancellationToken ParentCancelToken { get; set; }
public CancellationToken? ParentCancelToken { get; set; }
public CancellationToken CancelToken => _cancelToken;
private CancellationTokenSource _cancelTokenSource;
protected CancellationToken _cancelToken;
@@ -61,11 +61,16 @@ namespace Discord.WebSockets
{
_client = client;
_logLevel = client.Config.LogLevel;

_loginTimeout = client.Config.ConnectionTimeout;
_cancelToken = new CancellationToken(true);
_connectedEvent = new ManualResetEventSlim(false);

#if DNXCORE50
_engine = new BuiltInWebSocketEngine(client.Config.WebSocketInterval);
#else
_engine = new WSSharpWebSocketEngine(this, client.Config.UserAgent, client.Config.WebSocketInterval);
#endif
_engine.ProcessMessage += async (s, e) =>
{
if (_logLevel >= LogMessageSeverity.Debug)
@@ -84,10 +89,11 @@ namespace Discord.WebSockets
await Disconnect().ConfigureAwait(false);

_cancelTokenSource = new CancellationTokenSource();
if (ParentCancelToken != null)
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelTokenSource.Token, ParentCancelToken).Token;
else
_cancelToken = _cancelTokenSource.Token;
if (ParentCancelToken == null)
throw new InvalidOperationException("Parent cancel token was never set.");
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelTokenSource.Token, ParentCancelToken.Value).Token;
/*else
_cancelToken = _cancelTokenSource.Token;*/

_lastHeartbeat = DateTime.UtcNow;
await _engine.Connect(Host, _cancelToken).ConfigureAwait(false);
@@ -198,8 +204,7 @@ namespace Discord.WebSockets
string json = JsonConvert.SerializeObject(message);
if (_logLevel >= LogMessageSeverity.Debug)
RaiseOnLog(LogMessageSeverity.Debug, $"Out: " + json);
var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message));
_engine.QueueMessage(bytes);
_engine.QueueMessage(json);
}

private Task HeartbeatAsync(CancellationToken cancelToken)


+ 4
- 2
src/Discord.Net/project.json View File

@@ -27,7 +27,8 @@
"frameworks": {
"net45": {
"dependencies": {
"RestSharp": "105.2.3"
"RestSharp": "105.2.3",
"WebSocketSharp": "1.0.3-rc9"
},
"frameworkAssemblies": {
"System.Net.Http": "4.0.0.0"
@@ -35,7 +36,8 @@
},
"dnx451": {
"dependencies": {
"RestSharp": "105.2.3"
"RestSharp": "105.2.3",
"WebSocketSharp": "1.0.3-rc9"
},
"frameworkAssemblies": {
"System.Net.Http": "4.0.0.0"


+ 1
- 1
test/Discord.Net.Tests/Discord.Net.Tests.csproj View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>


Loading…
Cancel
Save