private void ReceiveVoiceAsync(CancellationToken cancelToken) { try { byte[] packet, decodingBuffer = null, nonce = null, result; int packetLength, resultOffset, resultLength; IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0); if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) != 0) { decodingBuffer = new byte[MaxOpusSize]; nonce = new byte[24]; } while (!cancelToken.IsCancellationRequested) { Thread.Sleep(1); if (_udp.Available > 0) { packet = _udp.Receive(ref endpoint); packetLength = packet.Length; if (packetLength > 0 && endpoint.Equals(_endpoint)) { if (_state != (int)WebSocketState.Connected) { if (packetLength != 70) { return; } int port = packet[68] | packet[69] << 8; string ip = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0'); var login2 = new VoiceLogin2Command(); login2.Payload.Protocol = "udp"; login2.Payload.SocketData.Address = ip; login2.Payload.SocketData.Mode = _encryptionMode; login2.Payload.SocketData.Port = port; QueueMessage(login2); if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) == 0) { return; } } else { //Parse RTP Data if (packetLength < 12) { return; } byte flags = packet[0]; if (flags != 0x80) { return; } byte payloadType = packet[1]; if (payloadType != 0x78) { return; } ushort sequenceNumber = (ushort)((packet[2] << 8) | packet[3] << 0); uint timestamp = (uint)((packet[4] << 24) | (packet[5] << 16) | (packet[6] << 8) | (packet[7] << 0)); uint ssrc = (uint)((packet[8] << 24) | (packet[9] << 16) | (packet[10] << 8) | (packet[11] << 0)); //Decrypt if (_isEncrypted) { if (packetLength < 28) //12 + 16 (RTP + Poly1305 MAC) { return; } Buffer.BlockCopy(packet, 0, nonce, 0, 12); int ret = Sodium.Decrypt(packet, 12, packetLength - 12, decodingBuffer, nonce, _secretKey); if (ret != 0) { continue; } result = decodingBuffer; resultOffset = 0; resultLength = packetLength - 28; } else //Plain { result = packet; resultOffset = 12; resultLength = packetLength - 12; } /*if (_logLevel >= LogMessageSeverity.Debug) * RaiseOnLog(LogMessageSeverity.Debug, $"Received {buffer.Length - 12} bytes.");*/ string userId; if (_ssrcMapping.TryGetValue(ssrc, out userId)) { RaiseOnPacket(userId, _channelId, result, resultOffset, resultLength); } } } } } } catch (OperationCanceledException) { } catch (InvalidOperationException) { } //Includes ObjectDisposedException }
private void ReceiveVoiceAsync(CancellationToken cancelToken) { try { byte[] packet, decodingBuffer = null, nonce = null, result; int packetLength, resultOffset, resultLength; IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0); if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) != 0) { decodingBuffer = new byte[MaxOpusSize]; nonce = new byte[24]; } while (!cancelToken.IsCancellationRequested) { Thread.Sleep(1); if (_udp.Available > 0) { packet = _udp.Receive(ref endpoint); packetLength = packet.Length; if (packetLength > 0 && endpoint.Equals(_endpoint)) { if (_state != (int)WebSocketState.Connected) { if (packetLength != 70) return; int port = packet[68] | packet[69] << 8; string ip = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0'); var login2 = new VoiceLogin2Command(); login2.Payload.Protocol = "udp"; login2.Payload.SocketData.Address = ip; login2.Payload.SocketData.Mode = _encryptionMode; login2.Payload.SocketData.Port = port; QueueMessage(login2); if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) == 0) return; } else { //Parse RTP Data if (packetLength < 12) return; byte flags = packet[0]; if (flags != 0x80) return; byte payloadType = packet[1]; if (payloadType != 0x78) return; ushort sequenceNumber = (ushort)((packet[2] << 8) | packet[3] << 0); uint timestamp = (uint)((packet[4] << 24) | (packet[5] << 16) | (packet[6] << 8) | (packet[7] << 0)); uint ssrc = (uint)((packet[8] << 24) | (packet[9] << 16) | (packet[10] << 8) | (packet[11] << 0)); //Decrypt if (_isEncrypted) { if (packetLength < 28) //12 + 16 (RTP + Poly1305 MAC) return; Buffer.BlockCopy(packet, 0, nonce, 0, 12); int ret = Sodium.Decrypt(packet, 12, packetLength - 12, decodingBuffer, nonce, _secretKey); if (ret != 0) continue; result = decodingBuffer; resultOffset = 0; resultLength = packetLength - 28; } else //Plain { result = packet; resultOffset = 12; resultLength = packetLength - 12; } /*if (_logLevel >= LogMessageSeverity.Debug) RaiseOnLog(LogMessageSeverity.Debug, $"Received {buffer.Length - 12} bytes.");*/ string userId; if (_ssrcMapping.TryGetValue(ssrc, out userId)) RaiseOnPacket(userId, _channelId, result, resultOffset, resultLength); } } } } } catch (OperationCanceledException) { } catch (InvalidOperationException) { } //Includes ObjectDisposedException }