Skip to content

Commit

Permalink
refactor: magic numbers in discordclient
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis committed Dec 3, 2024
1 parent 8c0c5d2 commit 5f5489e
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# TODO: Discuss about -readability-identifier-length, -readability-avoid-const-params-in-decls
Checks: "-*,bugprone-*,cert-*,clang-analyzer-*,concurrency-*,cppcoreguidelines-*,llvm-namespace-comment,modernize-*,performance-*,portability-*,readability-*,-bugprone-implicit-widening-of-multiplication-result, -bugprone-easily-swappable-parameters,-readability-identifier-length,-portability-restrict-system-includes,-modernize-use-trailing-return-type,-cppcoreguidelines-non-private-member-variables-in-classes,-readability-avoid-const-params-in-decls"
Checks: "-*,bugprone-*,cert-*,clang-analyzer-*,concurrency-*,cppcoreguidelines-*,llvm-namespace-comment,modernize-*,performance-*,portability-*,readability-*,-bugprone-implicit-widening-of-multiplication-result, -bugprone-easily-swappable-parameters,-readability-identifier-length,-portability-restrict-system-includes,-modernize-use-trailing-return-type,-cppcoreguidelines-non-private-member-variables-in-classes,-readability-avoid-const-params-in-decls,-cppcoreguidelines-owning-memory,-readability-function-cognitive-complexity"
82 changes: 80 additions & 2 deletions include/dpp/discordclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,84 @@ class cluster;
*/
class zlibcontext;

/**
* @brief Represents different event opcodes sent and received on a shard websocket
*/
enum shard_frame_type : int {

/**
* @brief An event was dispatched.
* @note Receive only
*/
ft_dispatch = 0,

/**
* @brief Fired periodically by the client to keep the connection alive.
* @note Send/Receive
*/
ft_heartbeat = 1,

/**
* @brief Starts a new session during the initial handshake.
* @note Send only
*/
ft_identify = 2,

/**
* @brief Update the client's presence.
* @note Send only
*/
ft_presence = 3,

/**
* @brief Used to join/leave or move between voice channels.
* @note Send only
*/
ft_voice_state_update = 4,

/**
* @brief Resume a previous session that was disconnected.
* @note Send only
*/
ft_resume = 6,

/**
* @brief You should attempt to reconnect and resume immediately.
* @note Receive only
*/
ft_reconnect = 7,

/**
* @brief Request information about offline guild members in a large guild.
* @note Send only
*/
ft_request_guild_members = 8,

/**
* @brief The session has been invalidated. You should reconnect and identify/resume accordingly.
* @note Receive only
*/
ft_invalid_session = 9,

/**
* @brief Sent immediately after connecting, contains the heartbeat interval to use.
* @note Receive only
*/
ft_hello = 10,

/**
* @brief Sent in response to receiving a heartbeat to acknowledge that it has been received.
* @note Receive only
*/
ft_heartbeat_ack = 11,

/**
* @brief Request information about soundboard sounds in a set of guilds.
* @note Send only
*/
ft_request_soundboard_sounds = 31,
};

/**
* @brief Represents a connection to a voice channel.
* A client can only connect to one voice channel per guild at a time, so these are stored in a map
Expand Down Expand Up @@ -118,14 +196,14 @@ class DPP_EXPORT voiceconn {
*
* @return true if ready to connect
*/
bool is_ready();
bool is_ready() const;

/**
* @brief return true if the connection is active (websocket exists)
*
* @return true if has an active websocket
*/
bool is_active();
bool is_active() const;

/**
* @brief Create websocket object and connect it.
Expand Down
47 changes: 21 additions & 26 deletions src/dpp/discordclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@
#define PATH_COMPRESSED_JSON "/?v=" DISCORD_API_VERSION "&encoding=json&compress=zlib-stream"
#define PATH_UNCOMPRESSED_ETF "/?v=" DISCORD_API_VERSION "&encoding=etf"
#define PATH_COMPRESSED_ETF "/?v=" DISCORD_API_VERSION "&encoding=etf&compress=zlib-stream"
#define DECOMP_BUFFER_SIZE 512 * 1024

#define STRINGIFY(a) STRINGIFY_(a)
#define STRINGIFY_(a) #a

#ifndef DPP_OS
#define DPP_OS unknown
#define DPP_OS unknown
#endif

namespace dpp {

constexpr size_t DECOMP_BUFFER_SIZE = 512 * 1024;

/**
* @brief This is an opaque class containing zlib library specific structures.
* We define it this way so that the public facing D++ library doesn't require
Expand Down Expand Up @@ -130,7 +130,7 @@ void discord_client::on_disconnect()
ssl_client::close();
end_zlib();
/* Stop the timer first if its already ticking, to prevent concurrent reconnects */
if (reconnect_timer) {
if (reconnect_timer != 0U) {
owner->stop_timer(reconnect_timer);
reconnect_timer = 0;
}
Expand Down Expand Up @@ -206,29 +206,25 @@ bool discord_client::handle_frame(const std::string &buffer, ws_opcode opcode)
zlib->d_stream.next_in = (Bytef *)buffer.c_str();
zlib->d_stream.avail_in = (uInt)buffer.size();
do {
int have = 0;
zlib->d_stream.next_out = (Bytef*)decomp_buffer;
zlib->d_stream.avail_out = DECOMP_BUFFER_SIZE;
int ret = inflate(&(zlib->d_stream), Z_NO_FLUSH);
have = DECOMP_BUFFER_SIZE - zlib->d_stream.avail_out;
int have = DECOMP_BUFFER_SIZE - zlib->d_stream.avail_out;
switch (ret)
{
case Z_NEED_DICT:
case Z_STREAM_ERROR:
this->error(err_compression_stream);
this->close();
return true;
break;
return true;
case Z_DATA_ERROR:
this->error(err_compression_data);
this->close();
return true;
break;
return true;
case Z_MEM_ERROR:
this->error(err_compression_memory);
this->close();
return true;
break;
return true;
case Z_OK:
this->decompressed.append((const char*)decomp_buffer, have);
this->decompressed_total += have;
Expand Down Expand Up @@ -288,15 +284,15 @@ bool discord_client::handle_frame(const std::string &buffer, ws_opcode opcode)
uint32_t op = o->get<uint32_t>();

switch (op) {
case 9:
case ft_invalid_session:
/* Reset session state and fall through to 10 */
op = 10;
log(dpp::ll_debug, "Failed to resume session " + sessionid + ", will reidentify");
this->sessionid.clear();
this->last_seq = 0;
/* No break here, falls through to state 10 to cause a reidentify */
[[fallthrough]];
case 10:
case ft_hello:
/* Need to check carefully for the existence of this before we try to access it! */
if (j.find("d") != j.end() && j["d"].find("heartbeat_interval") != j["d"].end() && !j["d"]["heartbeat_interval"].is_null()) {
this->heartbeat_interval = j["d"]["heartbeat_interval"].get<uint32_t>();
Expand All @@ -306,7 +302,7 @@ bool discord_client::handle_frame(const std::string &buffer, ws_opcode opcode)
/* Resume */
log(dpp::ll_debug, "Resuming session " + sessionid + " with seq=" + std::to_string(last_seq));
json obj = {
{ "op", 6 },
{ "op", ft_resume },
{ "d", {
{"token", this->token },
{"session_id", this->sessionid },
Expand All @@ -321,9 +317,8 @@ bool discord_client::handle_frame(const std::string &buffer, ws_opcode opcode)
auto connect_now = [this]() {
log(dpp::ll_debug, "Connecting new session...");
json obj = {
{ "op", 2 },
{
"d",
{ "op", ft_identify },
{ "d",
{
{ "token", this->token },
{ "properties",
Expand Down Expand Up @@ -356,18 +351,18 @@ bool discord_client::handle_frame(const std::string &buffer, ws_opcode opcode)
this->last_heartbeat_ack = time(nullptr);
websocket_ping = 0;
break;
case 0: {
case ft_dispatch: {
std::string event = j["t"];
handle_event(event, j, data);
}
break;
case 7:
case ft_reconnect:
log(dpp::ll_debug, "Reconnection requested, closing socket " + sessionid);
message_queue.clear();
this->close();
break;
/* Heartbeat ack */
case 11:
case ft_heartbeat_ack:
this->last_heartbeat_ack = time(nullptr);
websocket_ping = utility::time_f() - ping_start;
break;
Expand Down Expand Up @@ -514,7 +509,7 @@ void discord_client::one_second_timer()
if (this->heartbeat_interval && this->last_seq) {
/* Check if we're due to emit a heartbeat */
if (time(nullptr) > last_heartbeat + ((heartbeat_interval / 1000.0) * 0.75)) {
last_ping_message = jsonobj_to_string(json({{"op", 1}, {"d", last_seq}}));
last_ping_message = jsonobj_to_string(json({{"op", ft_heartbeat}, {"d", last_seq}}));
queue_message(last_ping_message, true);
last_heartbeat = time(nullptr);
}
Expand Down Expand Up @@ -588,7 +583,7 @@ discord_client& discord_client::connect_voice(snowflake guild_id, snowflake chan
*/
log(ll_debug, "Sending op 4 to join VC, guild " + std::to_string(guild_id) + " channel " + std::to_string(channel_id) + (enable_dave ? " WITH DAVE" : ""));
queue_message(jsonobj_to_string(json({
{ "op", 4 },
{ "op", ft_voice_state_update },
{ "d", {
{ "guild_id", std::to_string(guild_id) },
{ "channel_id", std::to_string(channel_id) },
Expand Down Expand Up @@ -617,7 +612,7 @@ void discord_client::disconnect_voice_internal(snowflake guild_id, bool emit_jso
log(ll_debug, "Disconnecting voice, guild: " + std::to_string(guild_id));
if (emit_json) {
queue_message(jsonobj_to_string(json({
{ "op", 4 },
{ "op", ft_voice_state_update },
{ "d", {
{ "guild_id", std::to_string(guild_id) },
{ "channel_id", json::value_t::null },
Expand Down Expand Up @@ -652,11 +647,11 @@ voiceconn* discord_client::get_voice(snowflake guild_id) {
voiceconn::voiceconn(discord_client* o, snowflake _channel_id, bool enable_dave) : creator(o), channel_id(_channel_id), voiceclient(nullptr), dave(enable_dave) {
}

bool voiceconn::is_ready() {
bool voiceconn::is_ready() const {
return (!websocket_hostname.empty() && !session_id.empty() && !token.empty());
}

bool voiceconn::is_active() {
bool voiceconn::is_active() const {
return voiceclient != nullptr;
}

Expand Down
3 changes: 2 additions & 1 deletion src/dpp/events/guild_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
************************************************************************************/
#include <dpp/discordevents.h>
#include <dpp/cluster.h>
#include <dpp/discordclient.h>
#include <dpp/guild.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
Expand Down Expand Up @@ -136,7 +137,7 @@ void guild_create::handle(discord_client* client, json &j, const std::string &ra
dpp::get_guild_cache()->store(g);
if (is_new_guild && g->id && (client->intents & dpp::i_guild_members)) {
if (client->creator->cache_policy.user_policy == cp_aggressive) {
json chunk_req = json({{"op", 8}, {"d", {{"guild_id",std::to_string(g->id)},{"query",""},{"limit",0}}}});
json chunk_req = json({{"op", ft_request_guild_members}, {"d", {{"guild_id",std::to_string(g->id)},{"query",""},{"limit",0}}}});
if (client->intents & dpp::i_guild_presences) {
chunk_req["d"]["presences"] = true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/dpp/presence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
************************************************************************************/
#include <dpp/presence.h>
#include <dpp/discordevents.h>
#include <dpp/discordclient.h>
#include <dpp/json.h>

namespace dpp {
Expand Down Expand Up @@ -250,7 +251,7 @@ json presence::to_json_impl(bool with_id) const {
};
json j({

{"op", 3},
{"op", ft_presence},
{"d",
{
{ "status", status_name_mapping[status()] },
Expand Down

0 comments on commit 5f5489e

Please sign in to comment.