Added XHRRawOutput, XHRTiming and VoiceInput debug types
This commit is contained in:
@@ -110,6 +110,9 @@
|
|||||||
<Compile Include="..\Discord.Net\Helpers\JsonHttpClient.cs">
|
<Compile Include="..\Discord.Net\Helpers\JsonHttpClient.cs">
|
||||||
<Link>Helpers\JsonHttpClient.cs</Link>
|
<Link>Helpers\JsonHttpClient.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Discord.Net\Helpers\JsonHttpClient.Events.cs">
|
||||||
|
<Link>Helpers\JsonHttpClient.Events.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Discord.Net\HttpException.cs">
|
<Compile Include="..\Discord.Net\HttpException.cs">
|
||||||
<Link>HttpException.cs</Link>
|
<Link>HttpException.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ namespace Discord
|
|||||||
WebSocketRawInput, //TODO: Make Http instanced and add a rawoutput event
|
WebSocketRawInput, //TODO: Make Http instanced and add a rawoutput event
|
||||||
WebSocketUnknownOpCode,
|
WebSocketUnknownOpCode,
|
||||||
WebSocketUnknownEvent,
|
WebSocketUnknownEvent,
|
||||||
VoiceOutput
|
XHRRawOutput,
|
||||||
|
XHRTiming,
|
||||||
|
VoiceInput,
|
||||||
|
VoiceOutput,
|
||||||
}
|
}
|
||||||
public sealed class LogMessageEventArgs : EventArgs
|
public sealed class LogMessageEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -90,8 +90,6 @@ namespace Discord
|
|||||||
_blockEvent = new ManualResetEventSlim(true);
|
_blockEvent = new ManualResetEventSlim(true);
|
||||||
_config = config ?? new DiscordClientConfig();
|
_config = config ?? new DiscordClientConfig();
|
||||||
_rand = new Random();
|
_rand = new Random();
|
||||||
_http = new JsonHttpClient();
|
|
||||||
_api = new DiscordAPI(_http);
|
|
||||||
|
|
||||||
_serializer = new JsonSerializer();
|
_serializer = new JsonSerializer();
|
||||||
#if TEST_RESPONSES
|
#if TEST_RESPONSES
|
||||||
@@ -367,7 +365,12 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
_webSocket = new DiscordDataSocket(this, _config.ConnectionTimeout, _config.WebSocketInterval);
|
_http = new JsonHttpClient(config.EnableDebug);
|
||||||
|
_api = new DiscordAPI(_http);
|
||||||
|
if (_config.EnableDebug)
|
||||||
|
_http.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, e.Message);
|
||||||
|
|
||||||
|
_webSocket = new DiscordDataSocket(this, config.ConnectionTimeout, config.WebSocketInterval, config.EnableDebug);
|
||||||
_webSocket.Connected += (s, e) => RaiseConnected();
|
_webSocket.Connected += (s, e) => RaiseConnected();
|
||||||
_webSocket.Disconnected += async (s, e) =>
|
_webSocket.Disconnected += async (s, e) =>
|
||||||
{
|
{
|
||||||
@@ -406,7 +409,7 @@ namespace Discord
|
|||||||
#if !DNXCORE50
|
#if !DNXCORE50
|
||||||
if (_config.EnableVoice)
|
if (_config.EnableVoice)
|
||||||
{
|
{
|
||||||
_voiceWebSocket = new DiscordVoiceSocket(this, _config.VoiceConnectionTimeout, _config.WebSocketInterval);
|
_voiceWebSocket = new DiscordVoiceSocket(this, _config.VoiceConnectionTimeout, _config.WebSocketInterval, config.EnableDebug);
|
||||||
_voiceWebSocket.Connected += (s, e) => RaiseVoiceConnected();
|
_voiceWebSocket.Connected += (s, e) => RaiseVoiceConnected();
|
||||||
_voiceWebSocket.Disconnected += async (s, e) =>
|
_voiceWebSocket.Disconnected += async (s, e) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Discord.API.Models;
|
using Discord.API.Models;
|
||||||
using Discord.Helpers;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System;
|
using System;
|
||||||
@@ -13,8 +12,8 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
private readonly ManualResetEventSlim _connectWaitOnLogin, _connectWaitOnLogin2;
|
private readonly ManualResetEventSlim _connectWaitOnLogin, _connectWaitOnLogin2;
|
||||||
|
|
||||||
public DiscordDataSocket(DiscordClient client, int timeout, int interval)
|
public DiscordDataSocket(DiscordClient client, int timeout, int interval, bool isDebug)
|
||||||
: base(client, timeout, interval)
|
: base(client, timeout, interval, isDebug)
|
||||||
{
|
{
|
||||||
_connectWaitOnLogin = new ManualResetEventSlim(false);
|
_connectWaitOnLogin = new ManualResetEventSlim(false);
|
||||||
_connectWaitOnLogin2 = new ManualResetEventSlim(false);
|
_connectWaitOnLogin2 = new ManualResetEventSlim(false);
|
||||||
@@ -72,7 +71,8 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownOpCode, "Unknown DataSocket op: " + msg.Operation);
|
if (_isDebug)
|
||||||
|
RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownOpCode, "Unknown DataSocket op: " + msg.Operation);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if DNXCORE
|
#if DNXCORE
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ namespace Discord
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public DiscordVoiceSocket(DiscordClient client, int timeout, int interval)
|
public DiscordVoiceSocket(DiscordClient client, int timeout, int interval, bool isDebug)
|
||||||
: base(client, timeout, interval)
|
: base(client, timeout, interval, isDebug)
|
||||||
{
|
{
|
||||||
_connectWaitOnLogin = new ManualResetEventSlim(false);
|
_connectWaitOnLogin = new ManualResetEventSlim(false);
|
||||||
#if !DNXCORE50
|
#if !DNXCORE50
|
||||||
@@ -287,7 +287,8 @@ namespace Discord
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownOpCode, "Unknown VoiceSocket op: " + msg.Operation);
|
if (_isDebug)
|
||||||
|
RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownOpCode, "Unknown VoiceSocket op: " + msg.Operation);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if DNXCORE50
|
#if DNXCORE50
|
||||||
@@ -322,25 +323,42 @@ namespace Discord
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Parse RTP Data
|
//Parse RTP Data
|
||||||
/*if (length < 12)
|
if (length < 12)
|
||||||
throw new Exception($"Unexpected message length. Expected >= 12, got {length}.");
|
{
|
||||||
|
if (_isDebug)
|
||||||
|
RaiseOnDebugMessage(DebugMessageType.VoiceInput, $"Unexpected message length. Expected >= 12, got {length}.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
byte flags = buffer[0];
|
byte flags = buffer[0];
|
||||||
if (flags != 0x80)
|
if (flags != 0x80)
|
||||||
throw new Exception("Unexpected Flags");
|
{
|
||||||
|
if (_isDebug)
|
||||||
|
RaiseOnDebugMessage(DebugMessageType.VoiceInput, $"Unexpected Flags: {flags}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
byte payloadType = buffer[1];
|
byte payloadType = buffer[1];
|
||||||
if (payloadType != 0x78)
|
if (payloadType != 0x78)
|
||||||
throw new Exception("Unexpected Payload Type");
|
{
|
||||||
|
if (_isDebug)
|
||||||
|
RaiseOnDebugMessage(DebugMessageType.VoiceInput, $"Unexpected Payload Type: {flags}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ushort sequenceNumber = (ushort)((buffer[2] << 8) | buffer[3]);
|
ushort sequenceNumber = (ushort)((buffer[2] << 8) |
|
||||||
uint timestamp = (uint)((buffer[4] << 24) | (buffer[5] << 16) |
|
buffer[3] << 0);
|
||||||
(buffer[6] << 8) | (buffer[7] << 0));
|
uint timestamp = (uint)((buffer[4] << 24) |
|
||||||
uint ssrc = (uint)((buffer[8] << 24) | (buffer[9] << 16) |
|
(buffer[5] << 16) |
|
||||||
(buffer[10] << 8) | (buffer[11] << 0));
|
(buffer[6] << 8) |
|
||||||
|
(buffer[7] << 0));
|
||||||
|
uint ssrc = (uint)((buffer[8] << 24) |
|
||||||
|
(buffer[9] << 16) |
|
||||||
|
(buffer[10] << 8) |
|
||||||
|
(buffer[11] << 0));
|
||||||
|
|
||||||
//Decrypt
|
//Decrypt
|
||||||
if (_mode == "xsalsa20_poly1305")
|
/*if (_mode == "xsalsa20_poly1305")
|
||||||
{
|
{
|
||||||
if (length < 36) //12 + 24
|
if (length < 36) //12 + 24
|
||||||
throw new Exception($"Unexpected message length. Expected >= 36, got {length}.");
|
throw new Exception($"Unexpected message length. Expected >= 36, got {length}.");
|
||||||
@@ -362,6 +380,8 @@ namespace Discord
|
|||||||
buffer = newBuffer;
|
buffer = newBuffer;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
if (_isDebug)
|
||||||
|
RaiseOnDebugMessage(DebugMessageType.VoiceInput, $"Received {buffer.Length - 12} bytes.");
|
||||||
//TODO: Use Voice Data
|
//TODO: Use Voice Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,22 +14,24 @@ namespace Discord
|
|||||||
private const int SendChunkSize = 4096;
|
private const int SendChunkSize = 4096;
|
||||||
|
|
||||||
protected readonly DiscordClient _client;
|
protected readonly DiscordClient _client;
|
||||||
protected volatile CancellationTokenSource _disconnectToken;
|
|
||||||
protected int _timeout, _heartbeatInterval;
|
|
||||||
protected readonly int _sendInterval;
|
protected readonly int _sendInterval;
|
||||||
protected string _host;
|
protected readonly bool _isDebug;
|
||||||
|
private readonly ConcurrentQueue<byte[]> _sendQueue;
|
||||||
|
|
||||||
|
protected volatile CancellationTokenSource _disconnectToken;
|
||||||
private volatile ClientWebSocket _webSocket;
|
private volatile ClientWebSocket _webSocket;
|
||||||
private volatile Task _tasks;
|
private volatile Task _tasks;
|
||||||
private ConcurrentQueue<byte[]> _sendQueue;
|
protected string _host;
|
||||||
|
protected int _timeout, _heartbeatInterval;
|
||||||
private DateTime _lastHeartbeat;
|
private DateTime _lastHeartbeat;
|
||||||
private bool _isConnected;
|
private bool _isConnected;
|
||||||
|
|
||||||
public DiscordWebSocket(DiscordClient client, int timeout, int interval)
|
public DiscordWebSocket(DiscordClient client, int timeout, int interval, bool isDebug)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_timeout = timeout;
|
_timeout = timeout;
|
||||||
_sendInterval = interval;
|
_sendInterval = interval;
|
||||||
|
_isDebug = isDebug;
|
||||||
|
|
||||||
_sendQueue = new ConcurrentQueue<byte[]>();
|
_sendQueue = new ConcurrentQueue<byte[]>();
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/Discord.Net/Helpers/JsonHttpClient.Events.cs
Normal file
14
src/Discord.Net/Helpers/JsonHttpClient.Events.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Discord.Helpers
|
||||||
|
{
|
||||||
|
internal partial class JsonHttpClient
|
||||||
|
{
|
||||||
|
public event EventHandler<LogMessageEventArgs> OnDebugMessage;
|
||||||
|
protected void RaiseOnDebugMessage(DebugMessageType type, string message)
|
||||||
|
{
|
||||||
|
if (OnDebugMessage != null)
|
||||||
|
OnDebugMessage(this, new LogMessageEventArgs(type, message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using Discord.API;
|
using Discord.API;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@@ -9,24 +8,22 @@ using System.Net;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Discord.Helpers
|
namespace Discord.Helpers
|
||||||
{
|
{
|
||||||
internal class JsonHttpClient
|
internal partial class JsonHttpClient
|
||||||
{
|
{
|
||||||
#if TEST_RESPONSES
|
private bool _isDebug;
|
||||||
private const bool _isDebug = true;
|
|
||||||
#else
|
|
||||||
private const bool _isDebug = false;
|
|
||||||
#endif
|
|
||||||
private readonly HttpClient _client;
|
private readonly HttpClient _client;
|
||||||
private readonly HttpMethod _patch;
|
private readonly HttpMethod _patch;
|
||||||
#if TEST_RESPONSES
|
#if TEST_RESPONSES
|
||||||
private readonly JsonSerializerSettings _settings;
|
private readonly JsonSerializerSettings _settings;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public JsonHttpClient()
|
public JsonHttpClient(bool isDebug)
|
||||||
{
|
{
|
||||||
|
_isDebug = isDebug;
|
||||||
_patch = new HttpMethod("PATCH"); //Not sure why this isn't a default...
|
_patch = new HttpMethod("PATCH"); //Not sure why this isn't a default...
|
||||||
|
|
||||||
_client = new HttpClient(new HttpClientHandler
|
_client = new HttpClient(new HttpClientHandler
|
||||||
@@ -131,8 +128,8 @@ namespace Discord.Helpers
|
|||||||
private async Task<string> Send(HttpMethod method, string path, HttpContent content)
|
private async Task<string> Send(HttpMethod method, string path, HttpContent content)
|
||||||
{
|
{
|
||||||
string responseJson = await SendRequest(method, path, content, true);
|
string responseJson = await SendRequest(method, path, content, true);
|
||||||
if (path.StartsWith(Endpoints.BaseApi))
|
if (path.StartsWith(Endpoints.BaseApi) && !string.IsNullOrEmpty(responseJson))
|
||||||
CheckEmptyResponse(responseJson);
|
throw new Exception("API check failed: Response is not empty.");
|
||||||
return responseJson;
|
return responseJson;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -142,9 +139,25 @@ namespace Discord.Helpers
|
|||||||
|
|
||||||
private async Task<string> SendRequest(HttpMethod method, string path, HttpContent content, bool hasResponse)
|
private async Task<string> SendRequest(HttpMethod method, string path, HttpContent content, bool hasResponse)
|
||||||
{
|
{
|
||||||
#if TEST_RESPONSES
|
Stopwatch stopwatch = null;
|
||||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
if (_isDebug)
|
||||||
#endif
|
{
|
||||||
|
if (content != null)
|
||||||
|
{
|
||||||
|
if (content is StringContent)
|
||||||
|
{
|
||||||
|
string json = await (content as StringContent).ReadAsStringAsync();
|
||||||
|
RaiseOnDebugMessage(DebugMessageType.XHRRawOutput, $"{method} {path}: {json}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte[] bytes = await content.ReadAsByteArrayAsync();
|
||||||
|
RaiseOnDebugMessage(DebugMessageType.XHRRawOutput, $"{method} {path}: {bytes.Length} bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stopwatch = Stopwatch.StartNew();
|
||||||
|
}
|
||||||
|
|
||||||
string result;
|
string result;
|
||||||
using (HttpRequestMessage msg = new HttpRequestMessage(method, path))
|
using (HttpRequestMessage msg = new HttpRequestMessage(method, path))
|
||||||
{
|
{
|
||||||
@@ -168,21 +181,14 @@ namespace Discord.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TEST_RESPONSES
|
if (_isDebug)
|
||||||
stopwatch.Stop();
|
{
|
||||||
Debug.WriteLine($"{method} {path}: {Math.Round(stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond, 2)}ms");
|
stopwatch.Stop();
|
||||||
#endif
|
RaiseOnDebugMessage(DebugMessageType.XHRTiming, $"{method} {path}: {Math.Round(stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond, 2)}ms");
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TEST_RESPONSES
|
|
||||||
private void CheckEmptyResponse(string json)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(json))
|
|
||||||
throw new Exception("API check failed: Response is not empty.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private StringContent AsJson(object obj)
|
private StringContent AsJson(object obj)
|
||||||
{
|
{
|
||||||
return new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json");
|
return new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json");
|
||||||
|
|||||||
Reference in New Issue
Block a user