diff --git a/src/Discord.Net.Rpc/Discord.Net.Rpc.csproj b/src/Discord.Net.Rpc/Discord.Net.Rpc.csproj
index 628c8e032..85c2bf4e0 100644
--- a/src/Discord.Net.Rpc/Discord.Net.Rpc.csproj
+++ b/src/Discord.Net.Rpc/Discord.Net.Rpc.csproj
@@ -19,6 +19,9 @@
Net\DefaultWebSocketClient.cs
+
+ ConnectionManager.cs
+
diff --git a/src/Discord.Net.Rpc/DiscordRpcClient.Events.cs b/src/Discord.Net.Rpc/DiscordRpcClient.Events.cs
index d3c50a5ec..2a9ae21bf 100644
--- a/src/Discord.Net.Rpc/DiscordRpcClient.Events.cs
+++ b/src/Discord.Net.Rpc/DiscordRpcClient.Events.cs
@@ -12,12 +12,12 @@ namespace Discord.Rpc
remove { _connectedEvent.Remove(value); }
}
private readonly AsyncEvent> _connectedEvent = new AsyncEvent>();
- public event Func Disconnected
+ public event Func Disconnected
{
add { _disconnectedEvent.Add(value); }
remove { _disconnectedEvent.Remove(value); }
}
- private readonly AsyncEvent> _disconnectedEvent = new AsyncEvent>();
+ private readonly AsyncEvent> _disconnectedEvent = new AsyncEvent>();
public event Func Ready
{
add { _readyEvent.Add(value); }
diff --git a/src/Discord.Net.Rpc/DiscordRpcClient.cs b/src/Discord.Net.Rpc/DiscordRpcClient.cs
index 5235c98d4..01d641204 100644
--- a/src/Discord.Net.Rpc/DiscordRpcClient.cs
+++ b/src/Discord.Net.Rpc/DiscordRpcClient.cs
@@ -40,6 +40,8 @@ namespace Discord.Rpc
_rpcLogger = LogManager.CreateLogger("RPC");
_connection = new ConnectionManager(_stateLock, _rpcLogger, config.ConnectionTimeout,
OnConnectingAsync, OnDisconnectingAsync, x => ApiClient.Disconnected += x);
+ _connection.Connected += () => _connectedEvent.InvokeAsync();
+ _connection.Disconnected += (ex, recon) => _disconnectedEvent.InvokeAsync(ex);
_serializer = new JsonSerializer { ContractResolver = new DiscordContractResolver() };
_serializer.Error += (s, e) =>
diff --git a/src/Discord.Net.WebSocket/Audio/AudioClient.cs b/src/Discord.Net.WebSocket/Audio/AudioClient.cs
index 5404227f2..30073baeb 100644
--- a/src/Discord.Net.WebSocket/Audio/AudioClient.cs
+++ b/src/Discord.Net.WebSocket/Audio/AudioClient.cs
@@ -59,28 +59,28 @@ namespace Discord.Audio
internal AudioClient(SocketGuild guild, int id)
{
Guild = guild;
+ _audioLogger = Discord.LogManager.CreateLogger($"Audio #{id}");
+
+ ApiClient = new DiscordVoiceAPIClient(guild.Id, Discord.WebSocketProvider, Discord.UdpSocketProvider);
+ ApiClient.SentGatewayMessage += async opCode => await _audioLogger.DebugAsync($"Sent {opCode}").ConfigureAwait(false);
+ ApiClient.SentDiscovery += async () => await _audioLogger.DebugAsync($"Sent Discovery").ConfigureAwait(false);
+ //ApiClient.SentData += async bytes => await _audioLogger.DebugAsync($"Sent {bytes} Bytes").ConfigureAwait(false);
+ ApiClient.ReceivedEvent += ProcessMessageAsync;
+ ApiClient.ReceivedPacket += ProcessPacketAsync;
_stateLock = new SemaphoreSlim(1, 1);
_connection = new ConnectionManager(_stateLock, _audioLogger, 30000,
OnConnectingAsync, OnDisconnectingAsync, x => ApiClient.Disconnected += x);
+ _connection.Connected += () => _connectedEvent.InvokeAsync();
+ _connection.Disconnected += (ex, recon) => _disconnectedEvent.InvokeAsync(ex);
_heartbeatTimes = new ConcurrentQueue();
-
- _audioLogger = Discord.LogManager.CreateLogger($"Audio #{id}");
_serializer = new JsonSerializer { ContractResolver = new DiscordContractResolver() };
_serializer.Error += (s, e) =>
{
_audioLogger.WarningAsync(e.ErrorContext.Error).GetAwaiter().GetResult();
e.ErrorContext.Handled = true;
- };
-
- ApiClient = new DiscordVoiceAPIClient(guild.Id, Discord.WebSocketProvider, Discord.UdpSocketProvider);
-
- ApiClient.SentGatewayMessage += async opCode => await _audioLogger.DebugAsync($"Sent {opCode}").ConfigureAwait(false);
- ApiClient.SentDiscovery += async () => await _audioLogger.DebugAsync($"Sent Discovery").ConfigureAwait(false);
- //ApiClient.SentData += async bytes => await _audioLogger.DebugAsync($"Sent {bytes} Bytes").ConfigureAwait(false);
- ApiClient.ReceivedEvent += ProcessMessageAsync;
- ApiClient.ReceivedPacket += ProcessPacketAsync;
+ };
LatencyUpdated += async (old, val) => await _audioLogger.VerboseAsync($"Latency = {val} ms").ConfigureAwait(false);
}
@@ -98,25 +98,32 @@ namespace Discord.Audio
private async Task OnConnectingAsync()
{
+ await _audioLogger.DebugAsync("Connecting ApiClient").ConfigureAwait(false);
await ApiClient.ConnectAsync("wss://" + _url).ConfigureAwait(false);
+ await _audioLogger.DebugAsync("Sending Identity").ConfigureAwait(false);
await ApiClient.SendIdentityAsync(_userId, _sessionId, _token).ConfigureAwait(false);
+
+ //Wait for READY
+ await _connection.WaitAsync().ConfigureAwait(false);
}
private async Task OnDisconnectingAsync(Exception ex)
{
- //Disconnect from server
+ await _audioLogger.DebugAsync("Disconnecting ApiClient").ConfigureAwait(false);
await ApiClient.DisconnectAsync().ConfigureAwait(false);
//Wait for tasks to complete
+ await _audioLogger.DebugAsync("Waiting for heartbeater").ConfigureAwait(false);
var heartbeatTask = _heartbeatTask;
if (heartbeatTask != null)
await heartbeatTask.ConfigureAwait(false);
_heartbeatTask = null;
- await Discord.ApiClient.SendVoiceStateUpdateAsync(Guild.Id, null, false, false).ConfigureAwait(false);
-
long time;
while (_heartbeatTimes.TryDequeue(out time)) { }
_lastMessageTime = 0;
+
+ await _audioLogger.DebugAsync("Sending Voice State").ConfigureAwait(false);
+ await Discord.ApiClient.SendVoiceStateUpdateAsync(Guild.Id, null, false, false).ConfigureAwait(false);
}
public AudioOutStream CreateOpusStream(int samplesPerFrame, int bufferMillis)
diff --git a/src/Discord.Net.Rest/ConnectionManager.cs b/src/Discord.Net.WebSocket/ConnectionManager.cs
similarity index 95%
rename from src/Discord.Net.Rest/ConnectionManager.cs
rename to src/Discord.Net.WebSocket/ConnectionManager.cs
index ab1f4790c..72926e2e3 100644
--- a/src/Discord.Net.Rest/ConnectionManager.cs
+++ b/src/Discord.Net.WebSocket/ConnectionManager.cs
@@ -2,6 +2,7 @@ using Discord.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
+using Discord.Net;
namespace Discord
{
@@ -39,7 +40,13 @@ namespace Discord
clientDisconnectHandler(ex =>
{
if (ex != null)
- Error(new Exception("WebSocket connection was closed", ex));
+ {
+ var ex2 = ex as WebSocketClosedException;
+ if (ex2?.CloseCode == 4006)
+ CriticalError(new Exception("WebSocket session expired", ex));
+ else
+ Error(new Exception("WebSocket connection was closed", ex));
+ }
else
Error(new Exception("WebSocket connection was closed"));
return Task.Delay(0);
@@ -50,7 +57,7 @@ namespace Discord
{
await AcquireConnectionLock().ConfigureAwait(false);
var reconnectCancelToken = new CancellationTokenSource();
- _reconnectCancelToken = new CancellationTokenSource();
+ _reconnectCancelToken = reconnectCancelToken;
_task = Task.Run(async () =>
{
try
diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs
index 092225376..d52de0af1 100644
--- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs
+++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs
@@ -95,6 +95,8 @@ namespace Discord.WebSocket
_gatewayLogger = LogManager.CreateLogger(ShardId == 0 && TotalShards == 1 ? "Gateway" : $"Shard #{ShardId}");
_connection = new ConnectionManager(_stateLock, _gatewayLogger, config.ConnectionTimeout,
OnConnectingAsync, OnDisconnectingAsync, x => ApiClient.Disconnected += x);
+ _connection.Connected += () => _connectedEvent.InvokeAsync();
+ _connection.Disconnected += (ex, recon) => _disconnectedEvent.InvokeAsync(ex);
_nextAudioId = 1;
_connectionGroupLock = groupLock;
@@ -173,8 +175,6 @@ namespace Discord.WebSocket
{
await _gatewayLogger.DebugAsync("Connecting ApiClient").ConfigureAwait(false);
await ApiClient.ConnectAsync().ConfigureAwait(false);
- await _gatewayLogger.DebugAsync("Raising Event").ConfigureAwait(false);
- await _connectedEvent.InvokeAsync().ConfigureAwait(false);
if (_sessionId != null)
{
@@ -189,7 +189,7 @@ namespace Discord.WebSocket
//Wait for READY
await _connection.WaitAsync().ConfigureAwait(false);
-
+
await _gatewayLogger.DebugAsync("Sending Status").ConfigureAwait(false);
await SendStatusAsync().ConfigureAwait(false);
diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
index 4e16985a7..007f52124 100644
--- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
+++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
@@ -506,15 +506,16 @@ namespace Discord.WebSocket
}
internal async Task FinishConnectAudio(int id, string url, string token)
{
+ //TODO: Mem Leak: Disconnected/Connected handlers arent cleaned up
var voiceState = GetVoiceState(Discord.CurrentUser.Id).Value;
await _audioLock.WaitAsync().ConfigureAwait(false);
try
{
+ var promise = _audioConnectPromise;
if (_audioClient == null)
{
var audioClient = new AudioClient(this, id);
- var promise = _audioConnectPromise;
audioClient.Disconnected += async ex =>
{
if (!promise.Task.IsCompleted)
@@ -532,7 +533,7 @@ namespace Discord.WebSocket
}
_audioClient.Connected += () =>
{
- var _ = _audioConnectPromise.TrySetResultAsync(_audioClient);
+ var _ = promise.TrySetResultAsync(_audioClient);
return Task.Delay(0);
};
await _audioClient.StartAsync(url, Discord.CurrentUser.Id, voiceState.VoiceSessionId, token).ConfigureAwait(false);