Added WebSocketSharp support and fixed Mono issues
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -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
src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs
Normal file
88
src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user