diff --git a/include/dpp/discordclient.h b/include/dpp/discordclient.h index 7cd04b848d..35924c7441 100644 --- a/include/dpp/discordclient.h +++ b/include/dpp/discordclient.h @@ -228,7 +228,7 @@ class DPP_EXPORT voiceconn : public std::enable_shared_from_this { */ bool is_active() const; - voiceconn& request(bool failed_resume = false); + voiceconn& request(bool session_invalid = true); /** * @brief Create websocket object and connect it. diff --git a/include/dpp/discordvoiceclient.h b/include/dpp/discordvoiceclient.h index 16338eb9ac..dcd048f16b 100644 --- a/include/dpp/discordvoiceclient.h +++ b/include/dpp/discordvoiceclient.h @@ -233,7 +233,7 @@ using privacy_code_callback_t = std::function; /** * @brief A callback for a full reconnection after the voice client disconnects due to error. */ -using full_reconnection_callback_t = std::function; +using full_reconnection_callback_t = std::function; /** @brief Implements a discord voice connection. * Each discord_voice_client connects to one voice channel and derives from a websocket client. @@ -441,6 +441,13 @@ class DPP_EXPORT discord_voice_client : public websocket_client */ bool sent_stop_frames{}; + /** + * @brief Whether we got 4006 session invalid error code + * + * This is to tell reconnect callback to clear session data for the next reconnect attempt + */ + bool session_invalid{}; + /** * @brief Number of times we have tried to reconnect in the last few seconds */ diff --git a/src/dpp/discordclient.cpp b/src/dpp/discordclient.cpp index 22990e5209..e4e8b2d322 100644 --- a/src/dpp/discordclient.cpp +++ b/src/dpp/discordclient.cpp @@ -607,11 +607,11 @@ voiceconn::~voiceconn() { this->disconnect(); } -voiceconn& voiceconn::request(bool failed_resume) { +voiceconn& voiceconn::request(bool session_invalid) { /* Creating new connection from previously failed Opcode 7 Resume doesn't guarantee */ /* to receive voice_state_update AND voice_server_update event */ - /* Keep previous session data so we can reconnect */ - if (!failed_resume) { + /* Keep previous session data if still valid so we can reconnect */ + if (session_invalid) { this->token.clear(); this->session_id.clear(); this->websocket_hostname.clear(); @@ -626,9 +626,9 @@ voiceconn& voiceconn::connect() { if (this->is_ready() && !this->is_active()) { try { this->creator->log(ll_debug, "Connecting voice for guild " + std::to_string(this->guild_id) + " channel " + std::to_string(this->channel_id)); - full_reconnection_callback_t reconnection_callback = [weak_this=weak_from_this()] { + full_reconnection_callback_t reconnection_callback = [weak_this=weak_from_this()] (bool session_invalid) { if (std::shared_ptr strong_this = weak_this.lock()) { - strong_this->request(true); + strong_this->request(session_invalid); } }; this->voiceclient = std::make_unique(creator->creator, std::move(reconnection_callback), this->channel_id, this->guild_id, this->token, this->session_id, this->websocket_hostname, this->dave); diff --git a/src/dpp/discordvoiceclient.cpp b/src/dpp/discordvoiceclient.cpp index 62e0a52a42..7b445b65d2 100644 --- a/src/dpp/discordvoiceclient.cpp +++ b/src/dpp/discordvoiceclient.cpp @@ -235,6 +235,7 @@ void discord_voice_client::error(uint32_t errorcode) log(dpp::ll_error, "This is a non-recoverable error, giving up on voice connection"); } + this->session_invalid = errorcode == 4006; this->close(); } diff --git a/src/dpp/voice/enabled/thread.cpp b/src/dpp/voice/enabled/thread.cpp index e816b0a63f..262fd0fde5 100644 --- a/src/dpp/voice/enabled/thread.cpp +++ b/src/dpp/voice/enabled/thread.cpp @@ -46,7 +46,9 @@ void discord_voice_client::on_disconnect() { /* If we've looped 5 or more times, abort the loop. */ if (terminating || times_looped >= 5) { log(dpp::ll_warning, "Reached max loops whilst attempting to read from the websocket. Starting a full reconnection."); - owner->queue_work(1, reconnection_callback); + bool si = this->session_invalid; + auto rc = reconnection_callback; + owner->queue_work(1, [rc, si]() { rc(si) ;}); return; } last_loop_time = current_time;