Fixed audio and a few ConnectionManager issues
This commit is contained in:
@@ -19,6 +19,9 @@
|
||||
<Compile Include="..\Discord.Net.WebSocket\Net\DefaultWebSocketClient.cs">
|
||||
<Link>Net\DefaultWebSocketClient.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.WebSocket\ConnectionManager.cs">
|
||||
<Link>ConnectionManager.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />
|
||||
|
||||
@@ -12,12 +12,12 @@ namespace Discord.Rpc
|
||||
remove { _connectedEvent.Remove(value); }
|
||||
}
|
||||
private readonly AsyncEvent<Func<Task>> _connectedEvent = new AsyncEvent<Func<Task>>();
|
||||
public event Func<Exception, bool, Task> Disconnected
|
||||
public event Func<Exception, Task> Disconnected
|
||||
{
|
||||
add { _disconnectedEvent.Add(value); }
|
||||
remove { _disconnectedEvent.Remove(value); }
|
||||
}
|
||||
private readonly AsyncEvent<Func<Exception, bool, Task>> _disconnectedEvent = new AsyncEvent<Func<Exception, bool, Task>>();
|
||||
private readonly AsyncEvent<Func<Exception, Task>> _disconnectedEvent = new AsyncEvent<Func<Exception, Task>>();
|
||||
public event Func<Task> Ready
|
||||
{
|
||||
add { _readyEvent.Add(value); }
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
@@ -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<long>();
|
||||
|
||||
_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)
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user