diff --git a/include/dpp/discordclient.h b/include/dpp/discordclient.h index 7cd04b848d..3ede9eabaa 100644 --- a/include/dpp/discordclient.h +++ b/include/dpp/discordclient.h @@ -558,10 +558,8 @@ class DPP_EXPORT discord_client : public websocket_client * other object, along with the seq number. * * @param old Previous connection to resume from - * @param sequence Sequence number of previous session - * @param session_id Session ID of previous session */ - explicit discord_client(discord_client& old, uint64_t sequence, const std::string& session_id); + explicit discord_client(discord_client& old); /** * @brief Destroy the discord client object diff --git a/src/dpp/cluster.cpp b/src/dpp/cluster.cpp index 27df0edd38..4576d1df17 100644 --- a/src/dpp/cluster.cpp +++ b/src/dpp/cluster.cpp @@ -18,6 +18,7 @@ * limitations under the License. * ************************************************************************************/ +#include "discordclient.h" #include #include #include @@ -231,56 +232,51 @@ void cluster::start(start_type return_after) { if (now >= shard_reconnect_time) { /* This shard needs to be reconnected */ reconnections.erase(reconnect); - std::unique_ptr old = nullptr; + std::unique_ptr cl_old = {}; + std::unique_ptr cl_new = {}; { std::shared_lock lk(shards_mutex); - old = std::move(shards[shard_id]); + cl_old = std::move(shards[shard_id]); } log(ll_info, "Reconnecting shard " + std::to_string(shard_id)); /* Make a new resumed connection based off the old one */ + bool resume = false; try { - bool resume = false; - std::unique_lock lk(shards_mutex); - if (old != nullptr) { - /* These values must be copied to the new connection - * to attempt to resume it - */ - auto seq_no = old->last_seq; - auto session_id = old->sessionid; - + if (cl_old != nullptr) { log(ll_trace, "Attempting resume..."); - shards[shard_id] = nullptr; - shards[shard_id] = std::make_unique(*old, seq_no, session_id); + cl_new = std::make_unique(*cl_old); resume = true; } else { log(ll_trace, "Attempting full reconnection..."); - shards[shard_id] = nullptr; - shards[shard_id] = std::make_unique(this, shard_id, numshards, token, intents, compressed, ws_mode); + cl_new = std::make_unique(this, shard_id, numshards, token, intents, compressed, ws_mode); } - /* Delete the old one */ - log(ll_trace, "Attempting to delete old connection..."); - old.reset(); - old = nullptr; /* Set up the new shard's IO events */ log(ll_trace, "Running new connection..."); - if (resume) { - /* Start connecting only after the old client is destroyed */ - shards[shard_id]->start_connecting(); - std::unique_lock lock(shards[shard_id]->voice_mutex); - for (auto &c : shards[shard_id]->connecting_voice_channels) { - c.second->connect(); - } - } - shards[shard_id]->run(); + cl_new->run(); } catch (const std::exception& e) { std::unique_lock lk(shards_mutex); log(ll_info, "Exception when reconnecting shard " + std::to_string(shard_id) + ": " + std::string(e.what())); - shards[shard_id].reset(); - old.reset(); - old = nullptr; - shards[shard_id] = nullptr; add_reconnect(shard_id); + shards[shard_id] = std::move(cl_old); + return; + } + /* Delete the old one */ + if (cl_old != nullptr) { + log(ll_trace, "Deleting old connection..."); + std::unique_lock lk(shards_mutex); + cl_old = nullptr; + } + log(ll_trace, "Installing new connection..."); + std::unique_lock lk(shards_mutex); + shards[shard_id] = std::move(cl_new); + if (resume) { + /* Start connecting only after the old client is destroyed */ + shards[shard_id]->start_connecting(); + std::unique_lock lock(shards[shard_id]->voice_mutex); + for (auto &c : shards[shard_id]->connecting_voice_channels) { + c.second->connect(); + } } /* It is not possible to reconnect another shard within the same 5-second window, * due to discords strict rate limiting on shard connections, so we bail out here diff --git a/src/dpp/discordclient.cpp b/src/dpp/discordclient.cpp index 22990e5209..12a1b6010d 100644 --- a/src/dpp/discordclient.cpp +++ b/src/dpp/discordclient.cpp @@ -52,7 +52,7 @@ constexpr int LARGE_THRESHOLD = 250; /** * @brief Resume constructor for websocket client */ -discord_client::discord_client(discord_client &old, uint64_t sequence, const std::string& session_id) +discord_client::discord_client(discord_client &old) : websocket_client(old.owner, old.resume_gateway_url, "443", old.compressed ? (old.protocol == ws_json ? PATH_COMPRESSED_JSON : PATH_COMPRESSED_ETF) : (old.protocol == ws_json ? PATH_UNCOMPRESSED_JSON : PATH_UNCOMPRESSED_ETF)), compressed(old.compressed), zlib(nullptr), @@ -64,10 +64,10 @@ discord_client::discord_client(discord_client &old, uint64_t sequence, const std last_heartbeat(time(nullptr)), shard_id(old.shard_id), max_shards(old.max_shards), - last_seq(sequence), + last_seq(old.last_seq), token(old.token), intents(old.intents), - sessionid(session_id), + sessionid(old.sessionid), resumes(old.resumes), reconnects(old.reconnects), websocket_ping(old.websocket_ping),