diff --git a/src/Discord.Net.Net45/Discord.Net.csproj b/src/Discord.Net.Net45/Discord.Net.csproj
index 0340c2557..6c0149078 100644
--- a/src/Discord.Net.Net45/Discord.Net.csproj
+++ b/src/Discord.Net.Net45/Discord.Net.csproj
@@ -59,6 +59,9 @@
..\..\..\DiscordBot\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll
+
+ ..\..\..\DiscordBot\packages\WebSocketSharp.1.0.3-rc9\lib\websocket-sharp.dll
+
@@ -241,6 +244,9 @@
WebSockets\WebSocket.Events.cs
+
+ WebSockets\WebSocket.WebSocketSharp.cs
+
WebSockets\WebSocketMessage.cs
diff --git a/src/Discord.Net.Net45/packages.config b/src/Discord.Net.Net45/packages.config
index e09901c26..c5325909b 100644
--- a/src/Discord.Net.Net45/packages.config
+++ b/src/Discord.Net.Net45/packages.config
@@ -2,4 +2,5 @@
+
\ No newline at end of file
diff --git a/src/Discord.Net/WebSockets/Data/DataWebSocket.cs b/src/Discord.Net/WebSockets/Data/DataWebSocket.cs
index faa2c8d22..5011ed99a 100644
--- a/src/Discord.Net/WebSockets/Data/DataWebSocket.cs
+++ b/src/Discord.Net/WebSockets/Data/DataWebSocket.cs
@@ -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)
{
diff --git a/src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs b/src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs
index 6a13660e1..194fdbda7 100644
--- a/src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs
+++ b/src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs
@@ -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...
diff --git a/src/Discord.Net/WebSockets/WebSocket.BuiltIn.cs b/src/Discord.Net/WebSockets/WebSocket.BuiltIn.cs
index d177c9333..141f5839c 100644
--- a/src/Discord.Net/WebSockets/WebSocket.BuiltIn.cs
+++ b/src/Discord.Net/WebSockets/WebSocket.BuiltIn.cs
@@ -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 _sendQueue;
+ private readonly ConcurrentQueue _sendQueue;
private readonly int _sendInterval;
private ClientWebSocket _webSocket;
@@ -30,7 +31,7 @@ namespace Discord.WebSockets
public BuiltInWebSocketEngine(int sendInterval)
{
_sendInterval = sendInterval;
- _sendQueue = new ConcurrentQueue();
+ _sendQueue = new ConcurrentQueue();
}
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);
}
}
-}
\ No newline at end of file
+}
+#endif
\ No newline at end of file
diff --git a/src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs b/src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs
new file mode 100644
index 000000000..93fd379de
--- /dev/null
+++ b/src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs
@@ -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 _sendQueue;
+ private readonly int _sendInterval;
+ private readonly string _userAgent;
+ private readonly WebSocket _parent;
+ private WSSharpNWebSocket _webSocket;
+
+ public event EventHandler 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();
+ }
+
+ 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
\ No newline at end of file
diff --git a/src/Discord.Net/WebSockets/WebSocket.cs b/src/Discord.Net/WebSockets/WebSocket.cs
index 79537a3cf..7a74214e2 100644
--- a/src/Discord.Net/WebSockets/WebSocket.cs
+++ b/src/Discord.Net/WebSockets/WebSocket.cs
@@ -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)
diff --git a/src/Discord.Net/project.json b/src/Discord.Net/project.json
index 17726da0e..d3b42f940 100644
--- a/src/Discord.Net/project.json
+++ b/src/Discord.Net/project.json
@@ -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"
diff --git a/test/Discord.Net.Tests/Discord.Net.Tests.csproj b/test/Discord.Net.Tests/Discord.Net.Tests.csproj
index a4e5ea574..f1dbcb369 100644
--- a/test/Discord.Net.Tests/Discord.Net.Tests.csproj
+++ b/test/Discord.Net.Tests/Discord.Net.Tests.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU