Skip to content

Commit 91215ef

Browse files
committed
implement websocket ping
1 parent 7d4f682 commit 91215ef

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

include/sleepy_discord/asio_websocketconnection.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,29 @@ namespace SleepyDiscord {
5858
EventReceiver receiver;
5959

6060
using SocketPtrType = std::shared_ptr<asio::ssl::stream<asio::ip::tcp::socket>>;
61+
using MallocDeleter = decltype(&free);
6162

6263
// https://stackoverflow.com/a/60580965
6364
// a few changes made to make this more sane. Firstly, we need to know the length later, so a pair is returned.
6465
// if error, 2nd in pair will be -1
6566
// Example:
66-
// std::pair<std::shared_ptr<char> std::size_t> secKey = encodeBase64(nonce.data(), nonce.size());
67+
// auto secKey = encodeBase64(nonce.data(), nonce.size());
6768
// if (secKey.second == -1) return;
68-
std::pair<std::shared_ptr<char>, std::size_t> encodeBase64(const unsigned char* input, std::size_t length) {
69+
std::pair<std::unique_ptr<char, MallocDeleter>, std::size_t> encodeBase64(const unsigned char* input, std::size_t length) {
6970
const auto pl = 4 * ((length + 2) / 3);
7071
auto output = reinterpret_cast<char*>(calloc(pl + 1, 1)); // +1 for the terminating null that EVP_EncodeBlock adds on
7172
const auto ol = EVP_EncodeBlock(reinterpret_cast<unsigned char*>(output), input, static_cast<int>(length));
7273
if (pl != ol) { std::cerr << "encode predicted " << pl << " but we got " << ol << "\n"; }
73-
return { std::shared_ptr<char>(output, free), ol };
74+
return { std::unique_ptr<char, MallocDeleter>(output, free), ol};
7475
}
7576

7677
// this check doesn't seem to handle padding so the check is replaced
77-
std::pair<std::shared_ptr<unsigned char>, std::size_t> decodeBase64(const char* input, std::size_t length) {
78+
std::pair<std::unique_ptr<unsigned char, MallocDeleter>, std::size_t> decodeBase64(const char* input, std::size_t length) {
7879
const auto pl = 3 * length / 4;
7980
auto output = reinterpret_cast<unsigned char*>(calloc(pl + 1, 1));
8081
const auto ol = EVP_DecodeBlock(output, reinterpret_cast<const unsigned char*>(input), static_cast<int>(length));
8182
if (ol == -1) { std::cerr << "decode returned error \n"; }
82-
return { std::shared_ptr<unsigned char>(output, free), ol };
83+
return { std::unique_ptr<unsigned char, MallocDeleter>(output, free), ol };
8384
}
8485

8586
template<typename Task>
@@ -176,8 +177,8 @@ namespace SleepyDiscord {
176177
self->logError("Couldn't connect, random number generator failed", err);
177178
return cleanUp();
178179
}
179-
std::pair<std::shared_ptr<char>, std::size_t> secKey = self->encodeBase64(nonce.data(), nonce.size());
180-
std::shared_ptr<char> secKeyPtr = secKey.first;
180+
auto secKey = self->encodeBase64(nonce.data(), nonce.size());
181+
auto secKeyPtr = std::shared_ptr<char>(std::move(secKey.first));
181182
if (secKey.second == -1) return;
182183
std::size_t secKeyLength = secKey.second;
183184

@@ -290,8 +291,8 @@ namespace SleepyDiscord {
290291
std::memcpy(hashInput.data() + secKeyLength, websocketGUID.data(), websocketGUID.length());
291292
std::array<unsigned char, SHA_DIGEST_LENGTH> acceptHash{ };
292293
SHA1(hashInput.data(), hashInput.size(), acceptHash.data());
293-
std::pair<std::shared_ptr<char>, std::size_t> expectedAccept = self->encodeBase64(acceptHash.data(), acceptHash.size());
294-
std::shared_ptr<char> expectedAcceptPtr = std::move(expectedAccept.first);
294+
auto expectedAccept = self->encodeBase64(acceptHash.data(), acceptHash.size());
295+
auto expectedAcceptPtr = std::move(expectedAccept.first);
295296
if (expectedAccept.second == -1) {
296297
self->logError("Couldn't parse upgrade response, encode base64 failed", err);
297298
return cleanUp();
@@ -610,10 +611,11 @@ namespace SleepyDiscord {
610611
}
611612
uint64_t temp = net2System64(networkInt);
612613

613-
constexpr bool pointerIsTooSmall = (std::numeric_limits<std::size_t>::max)() < (std::numeric_limits<uint64_t>::max)();
614+
constexpr auto pointerMax = (std::numeric_limits<std::size_t>::max)();
615+
constexpr bool pointerIsTooSmall = pointerMax < (std::numeric_limits<uint64_t>::max)();
614616
if ( // on a 32 bit or 16 bit system, we can't put the message in memory
615617
// the compiler should be smart enough to get rid of this on 64-bit systems
616-
pointerIsTooSmall && ((std::numeric_limits<std::size_t>::max)() < payloadLength)
618+
pointerIsTooSmall && (pointerMax < payloadLength)
617619
) { // doubt that Discord would ever sent a 4 GB websocket payload, so just kill it
618620
std::cerr << "Can't read message larger then max pointer value\n";
619621
disconnect(1009, "sizeof(PTR)<MSG");
@@ -686,10 +688,10 @@ namespace SleepyDiscord {
686688
}
687689
} break;
688690
case pingOp:
689-
// I doubt Discord would sent this
691+
send(payload, static_cast<uint16_t>(pongOp), nullptr);
690692
break;
691693
case pongOp:
692-
// only needed if ping send is implemented
694+
// OK
693695
break;
694696
case continueOp:
695697
// shouldn't happen because we don't support websocket fragmentation

0 commit comments

Comments
 (0)