From 1aa25dc83f2409267556257bc8bb2549ea30d83c Mon Sep 17 00:00:00 2001 From: Archie Date: Tue, 23 Jul 2024 22:46:08 +0100 Subject: [PATCH 1/5] refactor: readability changes to sslclient and wsclient --- include/dpp/httpsclient.h | 2 +- include/dpp/wsclient.h | 7 +- src/dpp/sslclient.cpp | 56 ++++----- src/dpp/wsclient.cpp | 242 +++++++++++++++++++------------------- 4 files changed, 157 insertions(+), 150 deletions(-) diff --git a/include/dpp/httpsclient.h b/include/dpp/httpsclient.h index 0090c68af4..eec9c7b257 100644 --- a/include/dpp/httpsclient.h +++ b/include/dpp/httpsclient.h @@ -32,7 +32,7 @@ namespace dpp { -static inline const std::string http_version = "DiscordBot (https://github.com/brainboxdotcc/DPP, " +static inline constexpr std::string http_version = "DiscordBot (https://github.com/brainboxdotcc/DPP, " + to_hex(DPP_VERSION_MAJOR, false) + "." + to_hex(DPP_VERSION_MINOR, false) + "." + to_hex(DPP_VERSION_PATCH, false) + ")"; diff --git a/include/dpp/wsclient.h b/include/dpp/wsclient.h index b1a1b1870d..18f483dcb6 100644 --- a/include/dpp/wsclient.h +++ b/include/dpp/wsclient.h @@ -151,11 +151,10 @@ class DPP_EXPORT websocket_client : public ssl_client { size_t fill_header(unsigned char* outbuf, size_t sendlength, ws_opcode opcode); /** - * @brief Handle ping and pong requests. - * @param ping True if this is a ping, false if it is a pong - * @param payload The ping payload, to be returned as-is for a ping + * @brief Handle ping requests. + * @param payload The ping payload, to be returned as-is for a pong */ - void handle_ping_pong(bool ping, const std::string &payload); + void handle_ping(const std::string &payload); protected: diff --git a/src/dpp/sslclient.cpp b/src/dpp/sslclient.cpp index ee7f4d7af0..d3a191e1c8 100644 --- a/src/dpp/sslclient.cpp +++ b/src/dpp/sslclient.cpp @@ -73,7 +73,7 @@ #include /* Maximum allowed time in milliseconds for socket read/write timeouts and connect() */ -#define SOCKET_OP_TIMEOUT 5000 +constexpr uint16_t SOCKET_OP_TIMEOUT{5000}; namespace dpp { @@ -123,10 +123,10 @@ thread_local std::unordered_map keepalives; * SSL_read in non-blocking mode will only read 16k at a time. There's no point in a bigger buffer as * it'd go unused. */ -#define DPP_BUFSIZE 16 * 1024 +constexpr uint32_t DPP_BUFSIZE{16 * 1024}; /* Represents a failed socket system call, e.g. connect() failure */ -const int ERROR_STATUS = -1; +constexpr int ERROR_STATUS{-1}; bool close_socket(dpp::socket sfd) { @@ -197,25 +197,26 @@ int connect_with_timeout(dpp::socket sockfd, const struct sockaddr *addr, sockle #endif if (rc == -1 && err != EWOULDBLOCK && err != EINPROGRESS) { throw connection_exception(err_connect_failure, strerror(errno)); - } else { - /* Set a deadline timestamp 'timeout' ms from now */ - double deadline = utility::time_f() + (timeout_ms / 1000.0); - do { - rc = -1; - if (utility::time_f() >= deadline) { - throw connection_exception(err_connection_timed_out, "Connection timed out"); - } - pollfd pfd = {}; - pfd.fd = sockfd; - pfd.events = POLLOUT; - int r = ::poll(&pfd, 1, 10); - if (r > 0 && pfd.revents & POLLOUT) { - rc = 0; - } else if (r != 0 || pfd.revents & POLLERR) { - throw connection_exception(err_connection_timed_out, strerror(errno)); - } - } while (rc == -1); } + + /* Set a deadline timestamp 'timeout' ms from now */ + double deadline = utility::time_f() + (timeout_ms / 1000.0); + + do { + if (utility::time_f() >= deadline) { + throw connection_exception(err_connection_timed_out, "Connection timed out"); + } + pollfd pfd = {}; + pfd.fd = sockfd; + pfd.events = POLLOUT; + const int r = ::poll(&pfd, 1, 10); + if (r > 0 && pfd.revents & POLLOUT) { + rc = 0; + } else if (r != 0 || pfd.revents & POLLERR) { + throw connection_exception(err_connection_timed_out, strerror(errno)); + } + } while (rc == -1); + if (!set_nonblocking(sockfd, false)) { throw connection_exception(err_nonblocking_failure, "Can't switch socket to blocking mode!"); } @@ -502,16 +503,17 @@ void ssl_client::read_loop() read_blocked_on_write = false; read_blocked = false; r = (int) ::recv(sfd, server_to_client_buffer, DPP_BUFSIZE, 0); + if (r <= 0) { /* error or EOF */ return; - } else { - buffer.append(server_to_client_buffer, r); - if (!this->handle_buffer(buffer)) { - return; - } - bytes_in += r; } + + buffer.append(server_to_client_buffer, r); + if (!this->handle_buffer(buffer)) { + return; + } + bytes_in += r; } else { do { read_blocked_on_write = false; diff --git a/src/dpp/wsclient.cpp b/src/dpp/wsclient.cpp index 91d1281065..e5e6eae41f 100644 --- a/src/dpp/wsclient.cpp +++ b/src/dpp/wsclient.cpp @@ -127,50 +127,57 @@ void websocket_client::write(const std::string &data) bool websocket_client::handle_buffer(std::string &buffer) { - switch (state) { - case HTTP_HEADERS: - if (buffer.find("\r\n\r\n") != std::string::npos) { - /* Got all headers, proceed to new state */ - - /* Get headers string */ - std::string headers = buffer.substr(0, buffer.find("\r\n\r\n")); - - /* Modify buffer, remove headers section */ - buffer.erase(0, buffer.find("\r\n\r\n") + 4); - - /* Process headers into map */ - std::vector h = utility::tokenize(headers); - if (h.size()) { - std::string status_line = h[0]; - h.erase(h.begin()); - /* HTTP/1.1 101 Switching Protocols */ - std::vector status = utility::tokenize(status_line, " "); - if (status.size() >= 3 && status[1] == "101") { - for(auto &hd : h) { - std::string::size_type sep = hd.find(": "); - if (sep != std::string::npos) { - std::string key = hd.substr(0, sep); - std::string value = hd.substr(sep + 2, hd.length()); - http_headers[key] = value; - } - } - - state = CONNECTED; - } else if (status.size() < 3) { - log(ll_warning, "Malformed HTTP response on websocket"); - return false; - } else if (status[1] != "200" && status[1] != "204") { - log(ll_warning, "Received unhandled code: " + status[1]); - return false; - } + if (state == HTTP_HEADERS) { + /* We can expect Discord to end all packets with this. + * If they don't, something is wrong and we should abort. + */ + if (buffer.find("\r\n\r\n") == std::string::npos) { + return false; + } + + /* Got all headers, proceed to new state */ + + /* Get headers string */ + std::string headers = buffer.substr(0, buffer.find("\r\n\r\n")); + + /* Modify buffer, remove headers section */ + buffer.erase(0, buffer.find("\r\n\r\n") + 4); + + /* Process headers into map */ + std::vector h = utility::tokenize(headers); + + /* No headers? Something aint right. */ + if (h.empty()) { + return false; + } + + std::string status_line = h[0]; + h.erase(h.begin()); + std::vector status = utility::tokenize(status_line, " "); + /* HTTP/1.1 101 Switching Protocols */ + if (status.size() >= 3 && status[1] == "101") { + for(auto &hd : h) { + std::string::size_type sep = hd.find(": "); + if (sep != std::string::npos) { + std::string key = hd.substr(0, sep); + std::string value = hd.substr(sep + 2, hd.length()); + http_headers[key] = value; } } - break; - case CONNECTED: - /* Process packets until we can't */ - while (this->parseheader(buffer)); - break; + + state = CONNECTED; + } else if (status.size() < 3) { + log(ll_warning, "Malformed HTTP response on websocket"); + return false; + } else if (status[1] != "200" && status[1] != "204") { + log(ll_warning, "Received unhandled code: " + status[1]); + return false; + } + } else if (state == CONNECTED) { + /* Process packets until we can't */ + while (this->parseheader(buffer)); } + return true; } @@ -184,88 +191,89 @@ bool websocket_client::parseheader(std::string &data) if (data.size() < 4) { /* Not enough data to form a frame yet */ return false; - } else { - unsigned char opcode = data[0]; - switch (opcode & ~WS_FINBIT) { - case OP_CONTINUATION: - case OP_TEXT: - case OP_BINARY: - case OP_PING: - case OP_PONG: { - unsigned char len1 = data[1]; - unsigned int payloadstartoffset = 2; - - if (len1 & WS_MASKBIT) { - len1 &= ~WS_MASKBIT; - payloadstartoffset += 2; - /* We don't handle masked data, because discord doesn't send it */ - return true; - } + } - /* 6 bit ("small") length frame */ - uint64_t len = len1; - - if (len1 == WS_PAYLOAD_LENGTH_MAGIC_LARGE) { - /* 24 bit ("large") length frame */ - if (data.length() < 8) { - /* We don't have a complete header yet */ - return false; - } - - unsigned char len2 = (unsigned char)data[2]; - unsigned char len3 = (unsigned char)data[3]; - len = (len2 << 8) | len3; - - payloadstartoffset += 2; - } else if (len1 == WS_PAYLOAD_LENGTH_MAGIC_HUGE) { - /* 64 bit ("huge") length frame */ - if (data.length() < 10) { - /* We don't have a complete header yet */ - return false; - } - len = 0; - for (int v = 2, shift = 56; v < 10; ++v, shift -= 8) { - unsigned char l = (unsigned char)data[v]; - len |= (uint64_t)(l & 0xff) << shift; - } - payloadstartoffset += 8; - } + unsigned char opcode = data[0]; + switch (opcode & ~WS_FINBIT) { + case OP_CONTINUATION: + case OP_TEXT: + case OP_BINARY: + case OP_PING: + case OP_PONG: { + unsigned char len1 = data[1]; + unsigned int payloadstartoffset = 2; + + if (len1 & WS_MASKBIT) { + len1 &= ~WS_MASKBIT; + payloadstartoffset += 2; + /* We don't handle masked data, because discord doesn't send it */ + return true; + } - if (data.length() < payloadstartoffset + len) { - /* We don't have a complete frame yet */ - return false; - } + /* 6 bit ("small") length frame */ + uint64_t len = len1; - if ((opcode & ~WS_FINBIT) == OP_PING || (opcode & ~WS_FINBIT) == OP_PONG) { - handle_ping_pong((opcode & ~WS_FINBIT) == OP_PING, data.substr(payloadstartoffset, len)); - } else { - /* Pass this frame to the deriving class */ - this->handle_frame(data.substr(payloadstartoffset, len)); + if (len1 == WS_PAYLOAD_LENGTH_MAGIC_LARGE) { + /* 24 bit ("large") length frame */ + if (data.length() < 8) { + /* We don't have a complete header yet */ + return false; } - /* Remove this frame from the input buffer */ - data.erase(data.begin(), data.begin() + payloadstartoffset + len); + unsigned char len2 = (unsigned char)data[2]; + unsigned char len3 = (unsigned char)data[3]; + len = (len2 << 8) | len3; - return true; + payloadstartoffset += 2; + } else if (len1 == WS_PAYLOAD_LENGTH_MAGIC_HUGE) { + /* 64 bit ("huge") length frame */ + if (data.length() < 10) { + /* We don't have a complete header yet */ + return false; + } + len = 0; + for (int v = 2, shift = 56; v < 10; ++v, shift -= 8) { + unsigned char l = (unsigned char)data[v]; + len |= (uint64_t)(l & 0xff) << shift; + } + payloadstartoffset += 8; } - break; - case OP_CLOSE: { - uint16_t error = data[2] & 0xff; - error <<= 8; - error |= (data[3] & 0xff); - this->error(error); + if (data.length() < payloadstartoffset + len) { + /* We don't have a complete frame yet */ return false; } - break; - default: { - this->error(0); - return false; + if ((opcode & ~WS_FINBIT) == OP_PING) { + handle_ping(data.substr(payloadstartoffset, len)); + } else if ((opcode & ~WS_FINBIT) != OP_PONG) { + /* Pass this frame to the deriving class */ + this->handle_frame(data.substr(payloadstartoffset, len)); } - break; + + /* Remove this frame from the input buffer */ + data.erase(data.begin(), data.begin() + payloadstartoffset + len); + + return true; + } + break; + + case OP_CLOSE: { + uint16_t error = data[2] & 0xff; + error <<= 8; + error |= (data[3] & 0xff); + this->error(error); + return false; + } + break; + + default: { + this->error(0); + return false; } + break; } + return false; } @@ -282,16 +290,14 @@ void websocket_client::one_second_timer() } } -void websocket_client::handle_ping_pong(bool ping, const std::string &payload) +void websocket_client::handle_ping(const std::string &payload) { - if (ping) { - /* For receiving pings we echo back their payload with the type OP_PONG */ - unsigned char out[MAXHEADERSIZE]; - size_t s = this->fill_header(out, payload.length(), OP_PONG); - std::string header((const char*)out, s); - ssl_client::write(header); - ssl_client::write(payload); - } + /* For receiving pings we echo back their payload with the type OP_PONG */ + unsigned char out[MAXHEADERSIZE]; + size_t s = this->fill_header(out, payload.length(), OP_PONG); + std::string header((const char*)out, s); + ssl_client::write(header); + ssl_client::write(payload); } void websocket_client::send_close_packet() From 76ddba827318f57fe1fc2073443eb09febe64e21 Mon Sep 17 00:00:00 2001 From: Archie Date: Wed, 24 Jul 2024 10:56:30 +0100 Subject: [PATCH 2/5] refactor, fix: removed constexpr for http_version, moved send to std::string_view, removed spaces --- include/dpp/httpsclient.h | 2 +- include/dpp/sslclient.h | 2 +- include/dpp/wsclient.h | 38 +++++++++++++++++++------------------- src/dpp/sslclient.cpp | 2 +- src/dpp/wsclient.cpp | 19 ++++++++++--------- 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/include/dpp/httpsclient.h b/include/dpp/httpsclient.h index eec9c7b257..0090c68af4 100644 --- a/include/dpp/httpsclient.h +++ b/include/dpp/httpsclient.h @@ -32,7 +32,7 @@ namespace dpp { -static inline constexpr std::string http_version = "DiscordBot (https://github.com/brainboxdotcc/DPP, " +static inline const std::string http_version = "DiscordBot (https://github.com/brainboxdotcc/DPP, " + to_hex(DPP_VERSION_MAJOR, false) + "." + to_hex(DPP_VERSION_MINOR, false) + "." + to_hex(DPP_VERSION_PATCH, false) + ")"; diff --git a/include/dpp/sslclient.h b/include/dpp/sslclient.h index f43e3a575d..17b1447dc3 100644 --- a/include/dpp/sslclient.h +++ b/include/dpp/sslclient.h @@ -242,7 +242,7 @@ class DPP_EXPORT ssl_client * @param data Data to be written to the buffer * @note The data may not be written immediately and may be written at a later time to the socket. */ - virtual void write(const std::string &data); + virtual void write(const std::string_view data); /** * @brief Close socket connection diff --git a/include/dpp/wsclient.h b/include/dpp/wsclient.h index 18f483dcb6..0d76ba2136 100644 --- a/include/dpp/wsclient.h +++ b/include/dpp/wsclient.h @@ -37,7 +37,7 @@ enum websocket_protocol_t : uint8_t { * @brief JSON data, text, UTF-8 character set */ ws_json = 0, - + /** * @brief Erlang Term Format (ETF) binary protocol */ @@ -68,32 +68,32 @@ enum ws_opcode : uint8_t { /** * @brief Continuation. */ - OP_CONTINUATION = 0x00, + OP_CONTINUATION = 0x00, /** * @brief Text frame. */ - OP_TEXT = 0x01, + OP_TEXT = 0x01, /** * @brief Binary frame. */ - OP_BINARY = 0x02, + OP_BINARY = 0x02, /** * @brief Close notification with close code. */ - OP_CLOSE = 0x08, + OP_CLOSE = 0x08, /** * @brief Low level ping. */ - OP_PING = 0x09, + OP_PING = 0x09, /** * @brief Low level pong. */ - OP_PONG = 0x0a + OP_PONG = 0x0a }; /** @@ -130,7 +130,7 @@ class DPP_EXPORT websocket_client : public ssl_client { * @param buffer The buffer to operate on. Will modify the string removing completed items from the head of the queue * @return true if a complete header has been received */ - bool parseheader(std::string &buffer); + bool parseheader(std::string& buffer); /** * @brief Unpack a frame and pass completed frames up the stack. @@ -139,7 +139,7 @@ class DPP_EXPORT websocket_client : public ssl_client { * @param first True if is the first element (reserved for future use) * @return true if a complete frame has been received */ - bool unpack(std::string &buffer, uint32_t offset, bool first = true); + bool unpack(std::string& buffer, uint32_t offset, bool first = true); /** * @brief Fill a header for outbound messages @@ -154,7 +154,7 @@ class DPP_EXPORT websocket_client : public ssl_client { * @brief Handle ping requests. * @param payload The ping payload, to be returned as-is for a pong */ - void handle_ping(const std::string &payload); + void handle_ping(const std::string& payload); protected: @@ -167,7 +167,7 @@ class DPP_EXPORT websocket_client : public ssl_client { * @brief Get websocket state * @return websocket state */ - ws_state get_state(); + ws_state get_state() const; public: @@ -180,41 +180,41 @@ class DPP_EXPORT websocket_client : public ssl_client { * @note Voice websockets only support OP_TEXT, and other websockets must be * OP_BINARY if you are going to send ETF. */ - websocket_client(const std::string &hostname, const std::string &port = "443", const std::string &urlpath = "", ws_opcode opcode = OP_BINARY); + websocket_client(const std::string& hostname, const std::string& port = "443", const std::string& urlpath = "", ws_opcode opcode = OP_BINARY); /** * @brief Destroy the websocket client object */ - virtual ~websocket_client() = default; + virtual ~websocket_client() = default; /** * @brief Write to websocket. Encapsulates data in frames if the status is CONNECTED. * @param data The data to send. */ - virtual void write(const std::string &data); + virtual void write(const std::string_view data); /** * @brief Processes incoming frames from the SSL socket input buffer. * @param buffer The buffer contents. Can modify this value removing the head elements when processed. */ - virtual bool handle_buffer(std::string &buffer); + virtual bool handle_buffer(std::string& buffer); /** * @brief Close websocket */ - virtual void close(); + virtual void close(); /** * @brief Receives raw frame content only without headers - * + * * @param buffer The buffer contents * @return True if the frame was successfully handled. False if no valid frame is in the buffer. */ - virtual bool handle_frame(const std::string &buffer); + virtual bool handle_frame(const std::string& buffer); /** * @brief Called upon error frame. - * + * * @param errorcode The error code from the websocket server */ virtual void error(uint32_t errorcode); diff --git a/src/dpp/sslclient.cpp b/src/dpp/sslclient.cpp index d3a191e1c8..6449076e35 100644 --- a/src/dpp/sslclient.cpp +++ b/src/dpp/sslclient.cpp @@ -379,7 +379,7 @@ void ssl_client::connect() } } -void ssl_client::write(const std::string &data) +void ssl_client::write(const std::string_view data) { /* If we are in nonblocking mode, append to the buffer, * otherwise just use SSL_write directly. The only time we diff --git a/src/dpp/wsclient.cpp b/src/dpp/wsclient.cpp index e5e6eae41f..295bbf9e35 100644 --- a/src/dpp/wsclient.cpp +++ b/src/dpp/wsclient.cpp @@ -37,7 +37,7 @@ constexpr size_t WS_MAX_PAYLOAD_LENGTH_SMALL = 125; constexpr size_t WS_MAX_PAYLOAD_LENGTH_LARGE = 65535; constexpr size_t MAXHEADERSIZE = sizeof(uint64_t) + 2; -websocket_client::websocket_client(const std::string &hostname, const std::string &port, const std::string &urlpath, ws_opcode opcode) +websocket_client::websocket_client(const std::string& hostname, const std::string& port, const std::string& urlpath, ws_opcode opcode) : ssl_client(hostname, port), state(HTTP_HEADERS), path(urlpath), @@ -73,7 +73,7 @@ void websocket_client::connect() ); } -bool websocket_client::handle_frame(const std::string &buffer) +bool websocket_client::handle_frame(const std::string& buffer) { /* This is a stub for classes that derive the websocket client */ return true; @@ -111,7 +111,7 @@ size_t websocket_client::fill_header(unsigned char* outbuf, size_t sendlength, w } -void websocket_client::write(const std::string &data) +void websocket_client::write(const std::string_view data) { if (state == HTTP_HEADERS) { /* Simple write */ @@ -125,7 +125,7 @@ void websocket_client::write(const std::string &data) } } -bool websocket_client::handle_buffer(std::string &buffer) +bool websocket_client::handle_buffer(std::string& buffer) { if (state == HTTP_HEADERS) { /* We can expect Discord to end all packets with this. @@ -174,19 +174,19 @@ bool websocket_client::handle_buffer(std::string &buffer) return false; } } else if (state == CONNECTED) { - /* Process packets until we can't */ - while (this->parseheader(buffer)); + /* Process packets until we can't (buffer will erase data until parseheader returns false) */ + while (this->parseheader(buffer)){} } return true; } -ws_state websocket_client::get_state() +ws_state websocket_client::get_state() const { return this->state; } -bool websocket_client::parseheader(std::string &data) +bool websocket_client::parseheader(std::string& data) { if (data.size() < 4) { /* Not enough data to form a frame yet */ @@ -244,9 +244,10 @@ bool websocket_client::parseheader(std::string &data) return false; } + /* If we received a ping, we need to handle it. */ if ((opcode & ~WS_FINBIT) == OP_PING) { handle_ping(data.substr(payloadstartoffset, len)); - } else if ((opcode & ~WS_FINBIT) != OP_PONG) { + } else if ((opcode & ~WS_FINBIT) != OP_PONG) { /* Otherwise, handle everything else apart from a PONG. */ /* Pass this frame to the deriving class */ this->handle_frame(data.substr(payloadstartoffset, len)); } From e0fd67ecc9c780a5b91c2c0ddb6894529e875508 Mon Sep 17 00:00:00 2001 From: Archie Date: Wed, 24 Jul 2024 11:41:24 +0100 Subject: [PATCH 3/5] refactor: removed un-needed includes, more indentation corrections --- include/dpp/wsclient.h | 4 +--- src/dpp/sslclient.cpp | 35 ++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/dpp/wsclient.h b/include/dpp/wsclient.h index 0d76ba2136..98b48aa3de 100644 --- a/include/dpp/wsclient.h +++ b/include/dpp/wsclient.h @@ -23,8 +23,6 @@ #include #include #include -#include -#include #include namespace dpp { @@ -167,7 +165,7 @@ class DPP_EXPORT websocket_client : public ssl_client { * @brief Get websocket state * @return websocket state */ - ws_state get_state() const; + [[nodiscard]] ws_state get_state() const; public: diff --git a/src/dpp/sslclient.cpp b/src/dpp/sslclient.cpp index 6449076e35..96091d0242 100644 --- a/src/dpp/sslclient.cpp +++ b/src/dpp/sslclient.cpp @@ -176,8 +176,8 @@ bool set_nonblocking(dpp::socket sockfd, bool non_blocking) */ int connect_with_timeout(dpp::socket sockfd, const struct sockaddr *addr, socklen_t addrlen, unsigned int timeout_ms) { #ifdef __APPLE__ - /* Unreliable on OSX right now */ - return (::connect(sockfd, addr, addrlen)); + /* Unreliable on OSX right now */ + return (::connect(sockfd, addr, addrlen)); #else if (!set_nonblocking(sockfd, true)) { throw dpp::connection_exception(err_nonblocking_failure, "Can't switch socket to non-blocking mode!"); @@ -227,7 +227,7 @@ int connect_with_timeout(dpp::socket sockfd, const struct sockaddr *addr, sockle #ifndef _WIN32 void set_signal_handler(int signal) { - struct sigaction sa; + struct sigaction sa{}; sigaction(signal, nullptr, &sa); if (sa.sa_flags == 0 && sa.sa_handler == nullptr) { sa = {}; @@ -389,16 +389,17 @@ void ssl_client::write(const std::string_view data) */ if (nonblocking) { obuffer += data; + return; + } + + const int data_length = static_cast(data.length()); + if (plaintext) { + if (sfd == INVALID_SOCKET || ::send(sfd, data.data(), data_length, 0) != data_length) { + throw dpp::connection_exception(err_write, "write() failed"); + } } else { - const int data_length = (int)data.length(); - if (plaintext) { - if (sfd == INVALID_SOCKET || ::send(sfd, data.data(), data_length, 0) != data_length) { - throw dpp::connection_exception(err_write, "write() failed"); - } - } else { - if (SSL_write(ssl->ssl, data.data(), data_length) != data_length) { - throw dpp::connection_exception(err_ssl_write, "SSL_write() failed"); - } + if (SSL_write(ssl->ssl, data.data(), data_length) != data_length) { + throw dpp::connection_exception(err_ssl_write, "SSL_write() failed"); } } } @@ -579,14 +580,14 @@ void ssl_client::read_loop() if (r < 0) { /* Write error */ return; - } else { - client_to_server_length -= r; - client_to_server_offset += r; - bytes_out += r; } + + client_to_server_length -= r; + client_to_server_offset += r; + bytes_out += r; } else { r = SSL_write(ssl->ssl, client_to_server_buffer + client_to_server_offset, (int)client_to_server_length); - + switch(SSL_get_error(ssl->ssl,r)) { /* We wrote something */ case SSL_ERROR_NONE: From ddd4ead6e1072bc6434f52d9d3c31a3b5ae48d36 Mon Sep 17 00:00:00 2001 From: Archie Date: Wed, 24 Jul 2024 11:48:30 +0100 Subject: [PATCH 4/5] refactor: added a full stop because circleci --- include/dpp/sslclient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dpp/sslclient.h b/include/dpp/sslclient.h index 17b1447dc3..8869aef420 100644 --- a/include/dpp/sslclient.h +++ b/include/dpp/sslclient.h @@ -239,7 +239,7 @@ class DPP_EXPORT ssl_client /** * @brief Write to the output buffer. - * @param data Data to be written to the buffer + * @param data Data to be written to the buffer. * @note The data may not be written immediately and may be written at a later time to the socket. */ virtual void write(const std::string_view data); From bf67165e77f1f4727f2847ab4999db3cd97721c3 Mon Sep 17 00:00:00 2001 From: Archie Date: Wed, 24 Jul 2024 11:52:31 +0100 Subject: [PATCH 5/5] refactor: changed DPP_BUFSIZE to be uint16_t instead of uint32_t --- src/dpp/sslclient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dpp/sslclient.cpp b/src/dpp/sslclient.cpp index 96091d0242..e66dd1204a 100644 --- a/src/dpp/sslclient.cpp +++ b/src/dpp/sslclient.cpp @@ -123,7 +123,7 @@ thread_local std::unordered_map keepalives; * SSL_read in non-blocking mode will only read 16k at a time. There's no point in a bigger buffer as * it'd go unused. */ -constexpr uint32_t DPP_BUFSIZE{16 * 1024}; +constexpr uint16_t DPP_BUFSIZE{16 * 1024}; /* Represents a failed socket system call, e.g. connect() failure */ constexpr int ERROR_STATUS{-1};