internal VoiceNextConnection(DiscordClient client, DiscordGuild guild, DiscordChannel channel, VoiceNextConfiguration config, VoiceServerUpdatePayload server, VoiceStateUpdatePayload state) { Discord = client; Guild = guild; Channel = channel; SSRCMap = new ConcurrentDictionary <uint, ulong>(); _userSpeaking = new AsyncEvent <UserSpeakingEventArgs>(Discord.EventErrorHandler, "USER_SPEAKING"); _userLeft = new AsyncEvent <VoiceUserLeaveEventArgs>(Discord.EventErrorHandler, "USER_LEFT"); #if !NETSTANDARD1_1 _voiceReceived = new AsyncEvent <VoiceReceiveEventArgs>(Discord.EventErrorHandler, "VOICE_RECEIVED"); #endif _voiceSocketError = new AsyncEvent <SocketErrorEventArgs>(Discord.EventErrorHandler, "VOICE_WS_ERROR"); TokenSource = new CancellationTokenSource(); Configuration = config; Opus = new OpusCodec(48000, 2, Configuration.VoiceApplication); Sodium = new SodiumCodec(); Rtp = new RtpCodec(); ServerData = server; StateData = state; var eps = ServerData.Endpoint; var epi = eps.LastIndexOf(':'); var eph = string.Empty; var epp = 80; if (epi != -1) { eph = eps.Substring(0, epi); epp = int.Parse(eps.Substring(epi + 1)); } else { eph = eps; } ConnectionEndpoint = new ConnectionEndpoint { Hostname = eph, Port = epp }; ReadyWait = new TaskCompletionSource <bool>(); IsInitialized = false; IsDisposed = false; PlayingWait = null; PlaybackSemaphore = new SemaphoreSlim(1, 1); UdpClient = Discord.Configuration.UdpClientFactory(); VoiceWs = Discord.Configuration.WebSocketClientFactory(Discord.Configuration.Proxy); VoiceWs.OnDisconnect += VoiceWS_SocketClosed; VoiceWs.OnMessage += VoiceWS_SocketMessage; VoiceWs.OnConnect += VoiceWS_SocketOpened; VoiceWs.OnError += VoiceWs_SocketErrored; }
private async Task ProcessPayloadAsync(BaseDiscordPayload payload) { LogHandler <WsVoiceClient> .Log.Debug($"Received {Enum.GetName(typeof(VoiceOpType), payload.Op)} payload."); switch (payload.Op) { case VoiceOpType.Ready: Vrp = payload.Data.TryCast <VoiceReadyPayload>(); _udp = new UdpClient(Vrp.IpAddress, Vrp.Port); await _udp.SendDiscoveryAsync(Vrp.Ssrc).ConfigureAwait(false); LogHandler <WsVoiceClient> .Log.Debug($"Sent UDP discovery with {Vrp.Ssrc} ssrc."); _heartBeatTask = HandleHeartbeatAsync(Vrp.HeartbeatInterval); LogHandler <WsVoiceClient> .Log.Debug( $"Started heartbeat task with {Vrp.HeartbeatInterval} interval."); var selectProtocol = new BaseDiscordPayload(VoiceOpType.SelectProtocol, new SelectPayload(Vrp.IpAddress, Vrp.Port)); await _socket.SendAsync(selectProtocol) .ConfigureAwait(false); LogHandler <WsVoiceClient> .Log.Debug($"Sent select protocol with {Vrp.IpAddress}:{Vrp.Port}."); _ = VoiceSenderTask(); break; case VoiceOpType.SessionDescription: var sdp = payload.Data.TryCast <SessionDescriptionPayload>(); if (sdp.Mode != "xsalsa20_poly1305") { return; } _sdp = sdp; SodiumCodec = new SodiumCodec(_sdp.SecretKey); await _socket.SendAsync(new BaseDiscordPayload(VoiceOpType.Speaking, new { delay = 0, speaking = false })).ConfigureAwait(false); _ = SendKeepAliveAsync().ConfigureAwait(false); break; case VoiceOpType.Hello: var helloPayload = payload.Data.TryCast <HelloPayload>(); if (_heartBeatTask != null) { _heartBeatCancel.Cancel(false); _heartBeatTask.Dispose(); _heartBeatTask = null; } _heartBeatTask = HandleHeartbeatAsync(helloPayload.HeartBeatInterval); break; } }