public async Task SendAsync(VoiceOpCode opCode, object payload, RequestOptions options = null) { byte[] bytes = null; payload = new WebSocketMessage { Operation = (int)opCode, Payload = payload }; if (payload != null) { bytes = Encoding.UTF8.GetBytes(SerializeJson(payload)); } await _webSocketClient.SendAsync(bytes, 0, bytes.Length, true).ConfigureAwait(false); await _sentGatewayMessageEvent.InvokeAsync(opCode); }
private async Task ProcessMessageAsync(VoiceOpCode opCode, object payload) { #if BENCHMARK Stopwatch stopwatch = Stopwatch.StartNew(); try { #endif try { switch (opCode) { case VoiceOpCode.Ready: { await _audioLogger.DebugAsync("Received Ready").ConfigureAwait(false); var data = (payload as JToken).ToObject <ReadyEvent>(_serializer); _ssrc = data.SSRC; if (!data.Modes.Contains(DiscordVoiceAPIClient.Mode)) { throw new InvalidOperationException($"Discord does not support {DiscordVoiceAPIClient.Mode}"); } _heartbeatTime = 0; _heartbeatTask = RunHeartbeatAsync(data.HeartbeatInterval, _cancelToken.Token); var entry = await Dns.GetHostEntryAsync(_url).ConfigureAwait(false); ApiClient.SetUdpEndpoint(new IPEndPoint(entry.AddressList[0], data.Port)); await ApiClient.SendDiscoveryAsync(_ssrc).ConfigureAwait(false); } break; case VoiceOpCode.SessionDescription: { await _audioLogger.DebugAsync("Received SessionDescription").ConfigureAwait(false); var data = (payload as JToken).ToObject <SessionDescriptionEvent>(_serializer); if (data.Mode != DiscordVoiceAPIClient.Mode) { throw new InvalidOperationException($"Discord selected an unexpected mode: {data.Mode}"); } _secretKey = data.SecretKey; await ApiClient.SendSetSpeaking(true).ConfigureAwait(false); var _ = _connectTask.TrySetResultAsync(true); } break; case VoiceOpCode.HeartbeatAck: { await _audioLogger.DebugAsync("Received HeartbeatAck").ConfigureAwait(false); var heartbeatTime = _heartbeatTime; if (heartbeatTime != 0) { int latency = (int)(Environment.TickCount - _heartbeatTime); _heartbeatTime = 0; int before = Latency; Latency = latency; await _latencyUpdatedEvent.InvokeAsync(before, latency).ConfigureAwait(false); } } break; default: await _audioLogger.WarningAsync($"Unknown OpCode ({opCode})").ConfigureAwait(false); return; } } catch (Exception ex) { await _audioLogger.ErrorAsync($"Error handling {opCode}", ex).ConfigureAwait(false); return; } #if BENCHMARK } finally { stopwatch.Stop(); double millis = Math.Round(stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2); await _benchmarkLogger.DebugAsync($"{millis} ms").ConfigureAwait(false); } #endif }
private async Task ProcessMessageAsync(VoiceOpCode opCode, object payload) { _lastMessageTime = Environment.TickCount; try { switch (opCode) { case VoiceOpCode.Hello: { await _audioLogger.DebugAsync("Received Hello").ConfigureAwait(false); var data = (payload as JToken).ToObject <HelloEvent>(_serializer); _heartbeatInterval = data.HeartbeatInterval; } break; case VoiceOpCode.Ready: { await _audioLogger.DebugAsync("Received Ready").ConfigureAwait(false); var data = (payload as JToken).ToObject <ReadyEvent>(_serializer); _ssrc = data.SSRC; if (!data.Modes.Contains(DiscordVoiceAPIClient.Mode)) { throw new InvalidOperationException($"Discord does not support {DiscordVoiceAPIClient.Mode}"); } ApiClient.SetUdpEndpoint(data.Ip, data.Port); await ApiClient.SendDiscoveryAsync(_ssrc).ConfigureAwait(false); _heartbeatTask = RunHeartbeatAsync(_heartbeatInterval - 1000, _connection.CancelToken); // reserve a delay time of network } break; case VoiceOpCode.SessionDescription: { await _audioLogger.DebugAsync("Received SessionDescription").ConfigureAwait(false); var data = (payload as JToken).ToObject <SessionDescriptionEvent>(_serializer); if (data.Mode != DiscordVoiceAPIClient.Mode) { throw new InvalidOperationException($"Discord selected an unexpected mode: {data.Mode}"); } SecretKey = data.SecretKey; _isSpeaking = false; await ApiClient.SendSetSpeaking(false).ConfigureAwait(false); _keepaliveTask = RunKeepaliveAsync(5000, _connection.CancelToken); var _ = _connection.CompleteAsync(); } break; case VoiceOpCode.HeartbeatAck: { await _audioLogger.DebugAsync("Received HeartbeatAck").ConfigureAwait(false); if (_heartbeatTimes.TryDequeue(out long time)) { int latency = (int)(Environment.TickCount - time); int before = Latency; Latency = latency; await _latencyUpdatedEvent.InvokeAsync(before, latency).ConfigureAwait(false); } } break; case VoiceOpCode.Speaking: { await _audioLogger.DebugAsync("Received Speaking").ConfigureAwait(false); var data = (payload as JToken).ToObject <SpeakingEvent>(_serializer); _ssrcMap[data.Ssrc] = data.UserId; //TODO: Memory Leak: SSRCs are never cleaned up await _speakingUpdatedEvent.InvokeAsync(data.UserId, data.Speaking); } break; default: await _audioLogger.WarningAsync($"Unknown OpCode ({opCode})").ConfigureAwait(false); return; } } catch (Exception ex) { await _audioLogger.ErrorAsync($"Error handling {opCode}", ex).ConfigureAwait(false); return; } }
private async Task ProcessMessageAsync(VoiceOpCode opCode, object payload) { try { switch (opCode) { case VoiceOpCode.Ready: { await _audioLogger.DebugAsync("Received Ready").ConfigureAwait(false); var data = (payload as JToken).ToObject <ReadyEvent>(_serializer); _ssrc = data.SSRC; if (!data.Modes.Contains(DiscordVoiceAPIClient.Mode)) { throw new InvalidOperationException($"Discord does not support {DiscordVoiceAPIClient.Mode}"); } _heartbeatTime = 0; _heartbeatTask = RunHeartbeatAsync(data.HeartbeatInterval, _cancelTokenSource.Token); ApiClient.SetUdpEndpoint(_url, data.Port); await ApiClient.SendDiscoveryAsync(_ssrc).ConfigureAwait(false); } break; case VoiceOpCode.SessionDescription: { await _audioLogger.DebugAsync("Received SessionDescription").ConfigureAwait(false); var data = (payload as JToken).ToObject <SessionDescriptionEvent>(_serializer); if (data.Mode != DiscordVoiceAPIClient.Mode) { throw new InvalidOperationException($"Discord selected an unexpected mode: {data.Mode}"); } _secretKey = data.SecretKey; await ApiClient.SendSetSpeaking(true).ConfigureAwait(false); var _ = _connectTask.TrySetResultAsync(true); } break; case VoiceOpCode.HeartbeatAck: { await _audioLogger.DebugAsync("Received HeartbeatAck").ConfigureAwait(false); var heartbeatTime = _heartbeatTime; if (heartbeatTime != 0) { int latency = (int)(Environment.TickCount - _heartbeatTime); _heartbeatTime = 0; int before = Latency; Latency = latency; await _latencyUpdatedEvent.InvokeAsync(before, latency).ConfigureAwait(false); } } break; default: await _audioLogger.WarningAsync($"Unknown OpCode ({opCode})").ConfigureAwait(false); return; } } catch (Exception ex) { await _audioLogger.ErrorAsync($"Error handling {opCode}", ex).ConfigureAwait(false); return; } }