From 5cb75b581b0a8e745f82844e6a443f43431511ed Mon Sep 17 00:00:00 2001 From: brain Date: Mon, 15 Aug 2022 10:16:14 +0000 Subject: [PATCH] feat: https://discord.com/developers/docs/change-log#sessionspecific-gateway-resume-urls - https://github.com/discord/discord-api-docs/pull/5282 --- include/dpp/discordclient.h | 11 +++++++++++ src/dpp/discordclient.cpp | 11 +++++++++-- src/dpp/events/ready.cpp | 16 ++++++++++++++++ src/unittest.cpp | 18 +++++++++--------- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/include/dpp/discordclient.h b/include/dpp/discordclient.h index 95f4b3eb4f..38b545e2b5 100644 --- a/include/dpp/discordclient.h +++ b/include/dpp/discordclient.h @@ -257,6 +257,12 @@ class DPP_EXPORT discord_client : public websocket_client */ void end_zlib(); + /** + * @brief Update the websocket hostname with the resume url + * from the last READY event + */ + void set_resume_hostname(); + public: /** * @brief Owning cluster @@ -350,6 +356,11 @@ class DPP_EXPORT discord_client : public websocket_client */ std::unordered_map connecting_voice_channels; + /** + * @brief The gateway address we reconnect to when we resume a session + */ + std::string resume_gateway_url; + /** * @brief Log a message to whatever log the user is using. * The logged message is passed up the chain to the on_log event in user code which can then do whatever diff --git a/src/dpp/discordclient.cpp b/src/dpp/discordclient.cpp index d99938c042..80eff80e93 100644 --- a/src/dpp/discordclient.cpp +++ b/src/dpp/discordclient.cpp @@ -93,7 +93,8 @@ discord_client::discord_client(dpp::cluster* _cluster, uint32_t _shard_id, uint3 websocket_ping(0.0), ready(false), last_heartbeat_ack(time(nullptr)), - protocol(ws_proto) + protocol(ws_proto), + resume_gateway_url(DEFAULT_GATEWAY) { zlib = new zlibcontext(); etf = new etf_parser(); @@ -141,6 +142,11 @@ void discord_client::end_zlib() } } +void discord_client::set_resume_hostname() +{ + hostname = resume_gateway_url; +} + void discord_client::thread_run() { utility::set_thread_name(std::string("shard/") + std::to_string(shard_id)); @@ -155,9 +161,10 @@ void discord_client::thread_run() end_zlib(); setup_zlib(); do { - this->log(ll_debug, "Attempting reconnection of shard " + std::to_string(this->shard_id)); + this->log(ll_debug, "Attempting reconnection of shard " + std::to_string(this->shard_id) + " to wss://" + resume_gateway_url); error = false; try { + set_resume_hostname(); ssl_client::connect(); websocket_client::connect(); } diff --git a/src/dpp/events/ready.cpp b/src/dpp/events/ready.cpp index f5c36575d1..ab0d08387f 100644 --- a/src/dpp/events/ready.cpp +++ b/src/dpp/events/ready.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include using json = nlohmann::json; @@ -43,6 +44,21 @@ std::mutex protect_the_loot; void ready::handle(discord_client* client, json &j, const std::string &raw) { client->log(dpp::ll_info, "Shard id " + std::to_string(client->shard_id) + " (" + std::to_string(client->shard_id + 1) + "/" + std::to_string(client->max_shards) + ") ready!"); client->sessionid = j["d"]["session_id"]; + /* Session-specific gateway resume url + * https://discord.com/developers/docs/change-log#sessionspecific-gateway-resume-urls + * + * Discord give us the hostname wrapped in wss://crap/ like we're going to pass it to + * some top-heavy lib. Let's strip all this out if given to us so we just have a + * hostname. + */ + std::string ugly(j["d"]["resume_gateway_url"]); + if (ugly.substr(0, 6) == "wss://") { + client->resume_gateway_url = ugly.substr(6, ugly.length() - 7); + } else { + client->resume_gateway_url = ugly; + } + /* Pre-resolve it into our cache so that we aren't waiting on this when we need it later */ + static_cast(resolve_hostname(client->resume_gateway_url, "443")); client->ready = true; diff --git a/src/unittest.cpp b/src/unittest.cpp index 5d32cefdc3..abba3db59c 100644 --- a/src/unittest.cpp +++ b/src/unittest.cpp @@ -76,15 +76,15 @@ std::map tests = { {"COMPARISON", {tt_offline, "dpp::manged object comparison", false, false}}, {"CHANNELCACHE", {tt_online, "dpp::find_channel()", false, false}}, {"CHANNELTYPES", {tt_online, "dpp::channel type flags", false, false}}, - {"PERMISSION_CLASS", {tt_offline, "testing dpp::permission functionality", false, false}}, - {"USER.GET_MENTION", {tt_offline, "testing dpp::user::get_mention functionality", false, false}}, - {"USER.FORMAT_USERNAME", {tt_offline, "testing dpp::user::format_username functionality", false, false}}, - {"USER.GET_CREATION_TIME", {tt_offline, "testing dpp::user::get_creation_time functionality", false, false}}, - {"UTILITY.ICONHASH", {tt_offline, "testing dpp::utility::iconhash functionality", false, false}}, - {"UTILITY.MAKE_URL_PARAMETERS", {tt_offline, "testing dpp::utility::make_url_parameters functionality", false, false}}, - {"UTILITY.MARKDOWN_ESCAPE", {tt_offline, "testing dpp::utility::markdown_escape functionality", false, false}}, - {"UTILITY.TOKENIZE", {tt_offline, "testing dpp::utility::tokenize functionality", false, false}}, - {"UTILITY.URL_ENCODE", {tt_offline, "testing dpp::utility::url_encode functionality", false, false}}, + {"PERMISSION_CLASS", {tt_offline, "dpp::permission", false, false}}, + {"USER.GET_MENTION", {tt_offline, "dpp::user::get_mention", false, false}}, + {"USER.FORMAT_USERNAME", {tt_offline, "dpp::user::format_username", false, false}}, + {"USER.GET_CREATION_TIME", {tt_offline, "dpp::user::get_creation_time", false, false}}, + {"UTILITY.ICONHASH", {tt_offline, "dpp::utility::iconhash", false, false}}, + {"UTILITY.MAKE_URL_PARAMETERS", {tt_offline, "dpp::utility::make_url_parameters", false, false}}, + {"UTILITY.MARKDOWN_ESCAPE", {tt_offline, "dpp::utility::markdown_escape", false, false}}, + {"UTILITY.TOKENIZE", {tt_offline, "dpp::utility::tokenize", false, false}}, + {"UTILITY.URL_ENCODE", {tt_offline, "dpp::utility::url_encode", false, false}}, }; double start = dpp::utility::time_f();