Skip to content

Commit 7d4f682

Browse files
committed
fix compile issues with voice connection
fix compiler errors with boost asio Fix outdated azure wim image azure pipelines use newer openssl version azure pipeline switch to x86 azure pipelines use cmake command to build rename endian to net_endian
1 parent 71f4b85 commit 7d4f682

File tree

6 files changed

+67
-51
lines changed

6 files changed

+67
-51
lines changed

azure-pipelines.yml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
# https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net
55

66
pool:
7-
vmImage: 'VS2017-Win2016'
7+
vmImage: 'windows-2022'
88

99
variables:
1010
solution: 'build/*.sln'
11-
buildPlatform: Win32
11+
buildPlatform: 'x86'
1212
buildConfiguration: 'Release'
1313

1414
steps:
@@ -24,15 +24,13 @@ steps:
2424

2525
- script: |
2626
cd vcpkg
27-
.\vcpkg install openssl-windows:x86-windows-static
27+
.\vcpkg install openssl:x86-windows-static
2828
displayName: 'OpenSSL Install'
2929

3030
- task: CMake@1
3131
inputs:
32-
CMakeArgs: .. -DBUILD_SLEEPY_DISCORD_EXAMPLES=1 -DCMAKE_TOOLCHAIN_FILE=D:\a\1\s\vcpkg\scripts\buildsystems\vcpkg.cmake -DOPENSSL_USE_STATIC_LIBS=TRUE -DOPENSSL_ROOT_DIR="D:\a\1\s\vcpkg\installed\x86-windows-static" -DBUILD_CPR_TESTS=OFF
32+
CMakeArgs: .. -A Win32 -DBUILD_SLEEPY_DISCORD_EXAMPLES=1 -DCMAKE_TOOLCHAIN_FILE=D:\a\1\s\vcpkg\scripts\buildsystems\vcpkg.cmake -DOPENSSL_USE_STATIC_LIBS=TRUE -DOPENSSL_ROOT_DIR="D:\a\1\s\vcpkg\installed\x86-windows-static" -DBUILD_CPR_TESTS=OFF
3333

34-
- task: VSBuild@1
34+
- task: CMake@1
3535
inputs:
36-
solution: '$(solution)'
37-
platform: '$(buildPlatform)'
38-
configuration: '$(buildConfiguration)'
36+
CMakeArgs: --build . --config Release

examples/sound-player/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <random> //For noise
2+
#include <queue>
23
#include "sleepy_discord/sleepy_discord.h"
34
#include "IO_file.h" //For music
45

include/sleepy_discord/asio_websocketconnection.h

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
#include <string>
44
#include <utility>
55
#include <iostream>
6+
#include <algorithm>
7+
8+
#include "sleepy_discord/net_endian.h"
9+
#include "version_helper.h"
10+
611
#include "asio_include.h"
712
#if defined(SLEEPY_USE_BOOST_ASIO)
813
#include <boost/asio/ssl.hpp>
@@ -17,14 +22,12 @@
1722
#include <asio/read.hpp>
1823
#include <asio/streambuf.hpp>
1924
#endif
25+
2026
#include <openssl/x509.h>
2127
#include <openssl/evp.h>
2228
#include <openssl/rand.h>
2329
#include <openssl/sha.h>
24-
#include "endian.h"
25-
#include "version_helper.h"
2630

27-
// to do: handle muliple frames in one read
2831
// to do: use a log event and remove iostream include
2932

3033
namespace SleepyDiscord {
@@ -118,11 +121,11 @@ namespace SleepyDiscord {
118121

119122
cancelSignal->emit(asio::cancellation_type::all);
120123
self->logError("connect took too long, canceling", err);
121-
self->socketPtr->async_shutdown();
124+
self->socketPtr->async_shutdown([](const asio::error_code& _) {});
122125
});
123126

124127
auto cleanUp = [self, connectDeadline]() {
125-
self->socketPtr->async_shutdown();
128+
self->socketPtr->async_shutdown([](const asio::error_code& _) {});
126129
connectDeadline->cancel();
127130
};
128131

@@ -238,11 +241,12 @@ namespace SleepyDiscord {
238241
std::string headerFieldRight = response.substr(offset, newLinePos - offset);
239242
offset = newLinePos + 2;
240243
// insert to the map with the key being lowercase ASCII only
241-
std::transform(headerFieldLeft.begin(), headerFieldLeft.end(), headerFieldLeft.begin(), std::tolower);
244+
std::transform(headerFieldLeft.begin(), headerFieldLeft.end(), headerFieldLeft.begin(), [](char c) {
245+
return std::tolower(c);
246+
});
242247
headers.insert(std::make_pair(headerFieldLeft, std::move(headerFieldRight)));
243248
}
244249
offset += 2; // + 2 to skip end of header
245-
const auto bodyStart = offset;
246250

247251
// easyer to write it like this, but a map of functions might be faster
248252
{
@@ -253,7 +257,9 @@ namespace SleepyDiscord {
253257
}
254258
const std::string expectedValue = "websocket";
255259
std::string& value = iter->second;
256-
std::transform(value.begin(), value.end(), value.begin(), std::tolower);
260+
std::transform(value.begin(), value.end(), value.begin(), [](char c) {
261+
return std::tolower(c);
262+
});
257263
if (value != expectedValue) {
258264
self->logError("HTTP protocol switch to websocket failed, incorrect Upgrade value from server", err);
259265
return cleanUp();
@@ -268,7 +274,9 @@ namespace SleepyDiscord {
268274
}
269275
const std::string expectedValue = "upgrade";
270276
std::string& value = iter->second;
271-
std::transform(value.begin(), value.end(), value.begin(), std::tolower);
277+
std::transform(value.begin(), value.end(), value.begin(), [](char c) {
278+
return std::tolower(c);
279+
});
272280
if (value != expectedValue) {
273281
self->logError("HTTP protocol switch to websocket failed, incorrect Connection value from server", err);
274282
return cleanUp();
@@ -344,7 +352,7 @@ namespace SleepyDiscord {
344352
// so they are basically the same to us. But, the server might do the validation, so this
345353
// should be set correctly by the sender to prevent a invalid UTF-8 error.
346354
uint16_t opCode,
347-
std::function<void(asio::error_code)> callback
355+
std::function<void(const asio::error_code&)> callback
348356
) {
349357
if (!ready.load()) { // can't send while not connected
350358
std::cerr << "Can't send while not connected\n";
@@ -374,11 +382,11 @@ namespace SleepyDiscord {
374382

375383
switch (shortPayloadLength) {
376384
case 126: {
377-
auto netInt16 = system2net16(static_cast<uint16_t>(payloadLength));
385+
auto netInt16 = system2net16<uint8_t>(static_cast<uint16_t>(payloadLength));
378386
message->append(netInt16.data(), netInt16.size());
379387
} break;
380388
case 127: {
381-
auto netInt64 = system2net64(static_cast<uint64_t>(payloadLength));
389+
auto netInt64 = system2net64<uint8_t>(static_cast<uint64_t>(payloadLength));
382390
message->append(netInt64.data(), netInt64.size());
383391
} break;
384392
default: break;
@@ -411,10 +419,10 @@ namespace SleepyDiscord {
411419

412420
if (socketPtr == nullptr) return; // already disconnected
413421
auto self = shared_from_this();
414-
auto netCloseInt = system2net16(code);
422+
auto netCloseInt = system2net16<uint8_t>(code);
415423
std::basic_string<uint8_t> closePayload{ netCloseInt.data(), netCloseInt.size() };
416424
closePayload.append(reinterpret_cast<const uint8_t*>(reason.data()), reason.length());
417-
send(closePayload, 0x8 /*Close*/, [self, closeSocketAfterSend](asio::error_code& err) {
425+
send(closePayload, 0x8 /*Close*/, [self, closeSocketAfterSend](const asio::error_code& err) {
418426
if (err || closeSocketAfterSend) {
419427
self->shutdown();
420428
}
@@ -469,7 +477,7 @@ namespace SleepyDiscord {
469477

470478
void receiveFullHandshake(std::shared_ptr<std::array<char, 256>> responsePtr, const std::size_t length, int score = 0) {
471479
const static std::array<char, 4> endOfHandshake = { '\r', '\n', '\r', '\n' };
472-
for (int i = 0; i < length; i += 1) {
480+
for (std::size_t i = 0; i < length; i += 1) {
473481
if (responsePtr->data()[i] == endOfHandshake[score]) {
474482
score += 1;
475483
if (score == 4) {
@@ -529,15 +537,15 @@ namespace SleepyDiscord {
529537
std::memcpy(&secondByte, &temp, 1);
530538
}
531539

532-
constexpr int8_t hasMaskByte = 1; constexpr int8_t hasMaskBit = static_cast<uint8_t>(0b1000'0000);
540+
constexpr int8_t hasMaskBit = static_cast<uint8_t>(0b1000'0000);
533541
bool hasMask = (secondByte & hasMaskBit) == hasMaskBit;
534542
const std::size_t maskLength = hasMask ? sizeof(uint32_t) : 0;
535543
if (hasMask) { // Servers shouldn't sent masked payloads
536544
std::cerr << "Recevied masked websocket message, Servers shouldn't send masked payloads\n";
537545
return;
538546
}
539547

540-
constexpr int8_t hasExtendedLengthByte = 1; constexpr int8_t hasExtendedLength = static_cast<uint8_t>(0b0111'1111);
548+
constexpr int8_t hasExtendedLength = static_cast<uint8_t>(0b0111'1111);
541549
int8_t length7Bit = secondByte & hasExtendedLength;
542550
std::size_t lengthOfLength;
543551
switch (length7Bit) {
@@ -580,7 +588,7 @@ namespace SleepyDiscord {
580588
auto self = shared_from_this();
581589
std::istream inputStream(readBuffer.get());
582590
int extendedLengthPrefixLength;
583-
uint64_t payloadLength;
591+
std::size_t payloadLength;
584592
switch (frame.length7Bit) {
585593
case 126: {
586594
constexpr std::size_t size = sizeof(uint16_t);
@@ -600,7 +608,19 @@ namespace SleepyDiscord {
600608
inputStream.read(temp.data(), networkInt.size());
601609
std::memcpy(networkInt.data(), temp.data(), networkInt.size());
602610
}
603-
payloadLength = net2System64(networkInt);
611+
uint64_t temp = net2System64(networkInt);
612+
613+
constexpr bool pointerIsTooSmall = (std::numeric_limits<std::size_t>::max)() < (std::numeric_limits<uint64_t>::max)();
614+
if ( // on a 32 bit or 16 bit system, we can't put the message in memory
615+
// 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)
617+
) { // doubt that Discord would ever sent a 4 GB websocket payload, so just kill it
618+
std::cerr << "Can't read message larger then max pointer value\n";
619+
disconnect(1009, "sizeof(PTR)<MSG");
620+
return;
621+
}
622+
623+
payloadLength = static_cast<std::size_t>(temp);
604624
} break;
605625
default:
606626
extendedLengthPrefixLength = 0;
@@ -610,11 +630,11 @@ namespace SleepyDiscord {
610630

611631
const std::size_t maskStart = 2 + static_cast<size_t>(extendedLengthPrefixLength);
612632
const std::size_t payloadStart = maskStart + frame.maskLength;
613-
const std::size_t fullMessageLength = payloadStart + payloadLength;
633+
const std::size_t leftOverLength = length - payloadStart;
614634

615-
if (length < fullMessageLength) {
635+
if (leftOverLength < payloadLength) {
616636
// we don't have the whole message, loop receive until we have the whole message
617-
const std::size_t bytesLeftToGet = fullMessageLength - length;
637+
const std::size_t bytesLeftToGet = payloadLength - leftOverLength;
618638
asio::async_read(*(self->socketPtr), *readBuffer, asio::transfer_at_least(bytesLeftToGet), [self, readBuffer, frame, payloadLength, bytesLeftToGet](const asio::error_code& err, const std::size_t length) {
619639
if (err) {
620640
std::cerr << "failed to read whole\n";
@@ -627,7 +647,7 @@ namespace SleepyDiscord {
627647
else {
628648
// we have the whole message, we don't need to read again
629649
self->onPayload(frame.opCode, readBuffer, payloadLength);
630-
afterPayload(length - fullMessageLength, readBuffer);
650+
afterPayload(leftOverLength - payloadLength, readBuffer);
631651
}
632652
}
633653

@@ -671,6 +691,8 @@ namespace SleepyDiscord {
671691
case pongOp:
672692
// only needed if ping send is implemented
673693
break;
694+
case continueOp:
695+
// shouldn't happen because we don't support websocket fragmentation
674696
default:
675697
std::cerr << "Unknown op code from server\n";
676698
return;
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#pragma once
2+
#include <array>
23
#include <utility>
3-
#include <cstdint>
44
#include <cstring>
5-
#include <array>
65
#if __cplusplus >= 202002L
76
#include <bit>
87
#define SLEEPY_ENDIAN_IF if constexpr
@@ -33,15 +32,15 @@ namespace SleepyDiscord {
3332
#endif
3433
}
3534

36-
template<typename Byte = uint8_t>
35+
template<typename Byte>
3736
const std::array<Byte, 2> getByteOrder2() {
3837
const short bytes{ 0x0100 };
3938
const void* address{ static_cast<const void*>(&bytes) };
4039
const Byte* byteOrder{ static_cast<const Byte*>(address) };
4140
return std::array<Byte, 2>{byteOrder[0], byteOrder[1]};
4241
}
4342

44-
template<typename Byte = uint8_t>
43+
template<typename Byte>
4544
const std::array<Byte, 8> getByteOrder8() {
4645
const long long bytes{ 0x0706050403020100 };
4746
const void* address{ static_cast<const void*>(&bytes) };
@@ -59,7 +58,7 @@ namespace SleepyDiscord {
5958

6059
// you don't need to know the endianness, bitshifting works across endians
6160

62-
template<typename Byte = uint8_t>
61+
template<typename Byte>
6362
uint16_t net2System16(const std::array<Byte, 2> value) {
6463
static_assert(sizeof(uint16_t) == 2, "uint16_t must be 2 bytes large");
6564
constexpr Endian systemEndian = getSystemEndian();
@@ -75,7 +74,7 @@ namespace SleepyDiscord {
7574
);
7675
}
7776

78-
template<typename Byte = uint8_t>
77+
template<typename Byte>
7978
uint64_t net2System64(const std::array<Byte, 8> value) {
8079
static_assert(sizeof(uint64_t) == 8, "uint16_t must be 8 bytes large");
8180
constexpr Endian systemEndian = getSystemEndian();
@@ -97,7 +96,7 @@ namespace SleepyDiscord {
9796
);
9897
}
9998

100-
template<typename Byte = uint8_t>
99+
template<typename Byte>
101100
std::array<Byte, 2> system2net16(const uint16_t value) {
102101
static_assert(sizeof(uint16_t) == 2, "uint16_t must be 8 bytes large");
103102
std::array<Byte, 2> output{};
@@ -113,7 +112,7 @@ namespace SleepyDiscord {
113112
return output;
114113
}
115114

116-
template<typename Byte = uint8_t>
115+
template<typename Byte>
117116
std::array<Byte, 8> system2net64(const uint64_t value) {
118117
static_assert(sizeof(uint64_t) == 8, "uint16_t must be 8 bytes large");
119118
std::array<Byte, 8> output{};

sleepy_discord/client.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -740,14 +740,13 @@ namespace SleepyDiscord {
740740
}
741741

742742
void BaseDiscordClient::processMessage(const WebSocketMessage message) {
743-
switch (message.opCode) {
744-
case WebSocketMessage::OPCode::binary: {
743+
if (useTrasportConnection != -1) {
745744
if (!compressionHandler)
746-
break;
745+
return;
747746
compressionHandler->uncompress(message.payload);
748747

749748
//when using transport connections, Discord ends streams the flush siginal
750-
constexpr std::array<const char, 4> flushSiginal = { 0, 0, '\xFF', '\xFF'};
749+
constexpr std::array<const char, 4> flushSiginal = { 0, 0, '\xFF', '\xFF' };
751750
constexpr std::size_t siginalLength = flushSiginal.max_size();
752751
bool endsWithFlushSiginal = false;
753752
if (useTrasportConnection == 1 && siginalLength <= message.payload.length()) {
@@ -765,13 +764,10 @@ namespace SleepyDiscord {
765764
compressionHandler->getOutput(*uncompressed);
766765
processMessage(*uncompressed);
767766
}
768-
break;
769-
}
770-
case WebSocketMessage::OPCode::text: {
767+
return;
768+
} else {
771769
processMessage(message.payload);
772-
break;
773-
}
774-
default: break;
770+
return;
775771
}
776772
}
777773

@@ -897,7 +893,7 @@ namespace SleepyDiscord {
897893
voiceConnections.emplace_front( this, context );
898894
VoiceConnection& voiceConnection = voiceConnections.front();
899895

900-
connect(endpoint, &voiceConnection, voiceConnection.connection);
896+
connect(endpoint, voiceConnection, voiceConnection.connection);
901897

902898
//remove from wait list
903899
waitingVoiceContexts.remove_if(

sleepy_discord/voice_connection.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ namespace SleepyDiscord {
210210
if (reconnectTimer.isValid()) //overwrite reconnect timer
211211
reconnectTimer.stop();
212212
reconnectTimer = origin->schedule([this]() {
213-
origin->connect(getWebSocketURI(context.endpoint), this, connection);
213+
origin->connect(getWebSocketURI(context.endpoint), *this, connection);
214214
}, getRetryDelay());
215215
++consecutiveReconnectsCount;
216216
}

0 commit comments

Comments
 (0)