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;
        }
Esempio n. 2
0
        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;
            }
        }