diff --git a/include/dpp/discordvoiceclient.h b/include/dpp/discordvoiceclient.h index 11bfae3567..148d05d70f 100644 --- a/include/dpp/discordvoiceclient.h +++ b/include/dpp/discordvoiceclient.h @@ -64,6 +64,8 @@ class audio_mixer; inline constexpr size_t send_audio_raw_max_length = 11520; +inline constexpr size_t secret_key_size = 32; + /* * @brief For holding a moving average of the number of current voice users, for applying a smooth gain ramp. */ @@ -394,7 +396,12 @@ class DPP_EXPORT discord_voice_client : public websocket_client * If it has been sent, this is non-null and points to a * sequence of exactly 32 bytes. */ - uint8_t* secret_key; + std::array secret_key; + + /** + * @brief True if the voice client has a secret key + */ + bool has_secret_key{false}; /** * @brief Sequence number of outbound audio. This is incremented diff --git a/src/davetest/dave.cpp b/src/davetest/dave.cpp index 478fafa118..2a0bb4e139 100644 --- a/src/davetest/dave.cpp +++ b/src/davetest/dave.cpp @@ -24,6 +24,29 @@ #include #include +std::string get_testdata_dir() { + char *env_var = getenv("TEST_DATA_DIR"); + return (env_var ? env_var : "../../testdata/"); +} + +std::vector load_test_audio() { + std::vector testaudio; + std::string dir = get_testdata_dir(); + std::ifstream input (dir + "Robot.pcm", std::ios::in|std::ios::binary|std::ios::ate); + if (input.is_open()) { + size_t testaudio_size = input.tellg(); + testaudio.resize(testaudio_size); + input.seekg(0, std::ios::beg); + input.read((char*)testaudio.data(), testaudio_size); + input.close(); + } + else { + std::cout << "ERROR: Can't load " + dir + "Robot.pcm\n"; + exit(1); + } + return testaudio; +} + int main() { using namespace std::chrono_literals; char* t = getenv("DPP_UNIT_TEST_TOKEN"); @@ -40,10 +63,20 @@ int main() { std::cout << "[" << dpp::utility::current_date_time() << "] " << dpp::utility::loglevel(log.severity) << ": " << log.message << std::endl; }); + std::vector testaudio = load_test_audio(); + + dave_test.on_voice_ready([&](const dpp::voice_ready_t & event) { + dpp::discord_voice_client* v = event.voice_client; + if (v && v->is_ready()) { + v->send_audio_raw((uint16_t*)testaudio.data(), testaudio.size()); + } + }); + + dave_test.on_guild_create([&](const dpp::guild_create_t & event) { if (event.created->id == TEST_GUILD_ID) { dpp::discord_client* s = dave_test.get_shard(0); - s->connect_voice(TEST_GUILD_ID, TEST_VC_ID, false, false, true); + s->connect_voice(TEST_GUILD_ID, TEST_VC_ID, false, false, false); } }); dave_test.start(false); diff --git a/src/dpp/discordvoiceclient.cpp b/src/dpp/discordvoiceclient.cpp index 222680e549..f94d2c37a4 100644 --- a/src/dpp/discordvoiceclient.cpp +++ b/src/dpp/discordvoiceclient.cpp @@ -327,7 +327,6 @@ discord_voice_client::discord_voice_client(dpp::cluster* _cluster, snowflake _ch encoder(nullptr), repacketizer(nullptr), fd(INVALID_SOCKET), - secret_key(nullptr), sequence(0), receive_sequence(0), timestamp(0), @@ -404,12 +403,10 @@ void discord_voice_client::cleanup() voice_courier.join(); } #endif - delete[] secret_key; - secret_key = nullptr; } bool discord_voice_client::is_ready() { - return secret_key != nullptr; + return has_secret_key; } bool discord_voice_client::is_playing() { @@ -649,15 +646,14 @@ bool discord_voice_client::handle_frame(const std::string &data, ws_opcode opcod /* Session description */ case voice_opcode_connection_description: { json &d = j["d"]; - secret_key = new uint8_t[32]; size_t ofs = 0; for (auto & c : d["secret_key"]) { - *(secret_key + ofs) = (uint8_t)c; - ofs++; - if (ofs > 31) { + secret_key[ofs++] = (uint8_t)c; + if (ofs > secret_key.size() - 1) { break; } } + has_secret_key = true; if (dave_version != dave_version_none) { if (j["d"]["dave_protocol_version"] != static_cast(dave_version)) { @@ -902,7 +898,7 @@ void discord_voice_client::read_ready() * 4 byte extension header (magic 0xBEDE + 16-bit denoting extension length) */ total_header_len, - nonce, secret_key) != 0) { + nonce, secret_key.data()) != 0) { /* Invalid Discord RTP payload. */ return; } @@ -1430,7 +1426,7 @@ discord_voice_client& discord_voice_client::send_audio_opus(uint8_t* opus_packet memcpy(encrypt_nonce, &noncel, sizeof(noncel)); /* Execute */ - crypto_aead_xchacha20poly1305_ietf_encrypt( + int r = crypto_aead_xchacha20poly1305_ietf_encrypt( payload.data() + sizeof(header), nullptr, encoded_audio.data(), @@ -1440,7 +1436,7 @@ discord_voice_client& discord_voice_client::send_audio_opus(uint8_t* opus_packet sizeof(header), nullptr, static_cast(encrypt_nonce), - secret_key); + secret_key.data()); /* Append the 4 byte nonce to the resulting payload */ std::memcpy(payload.data() + payload.size() - sizeof(noncel), &noncel, sizeof(noncel));