Fix and add more decompressors
This commit is contained in:
@@ -310,7 +310,7 @@ public:
|
|||||||
/* Initialize loop's deflate inflate streams */
|
/* Initialize loop's deflate inflate streams */
|
||||||
if (!loopData->zlibContext) {
|
if (!loopData->zlibContext) {
|
||||||
loopData->zlibContext = new ZlibContext;
|
loopData->zlibContext = new ZlibContext;
|
||||||
loopData->inflationStream = new InflationStream;
|
loopData->inflationStream = new InflationStream(CompressOptions::DEDICATED_DECOMPRESSOR);
|
||||||
loopData->deflationStream = new DeflationStream(CompressOptions::DEDICATED_COMPRESSOR);
|
loopData->deflationStream = new DeflationStream(CompressOptions::DEDICATED_COMPRESSOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-7
@@ -236,14 +236,14 @@ public:
|
|||||||
CompressOptions compressOptions = CompressOptions::DISABLED;
|
CompressOptions compressOptions = CompressOptions::DISABLED;
|
||||||
if (secWebSocketExtensions.length() && webSocketContextData->compression != DISABLED) {
|
if (secWebSocketExtensions.length() && webSocketContextData->compression != DISABLED) {
|
||||||
|
|
||||||
/* We always want shared inflation, (or the full 15) */
|
/* Make sure to map SHARED_DECOMPRESSOR to windowBits = 0, not 1 */
|
||||||
int wantedInflationWindow = 0;
|
int wantedInflationWindow = 0;
|
||||||
if (webSocketContextData->compression & DEDICATED_DECOMPRESSOR) {
|
if ((webSocketContextData->compression & CompressOptions::_DECOMPRESSOR_MASK) != CompressOptions::SHARED_DECOMPRESSOR) {
|
||||||
wantedInflationWindow = 15;
|
wantedInflationWindow = (webSocketContextData->compression & CompressOptions::_DECOMPRESSOR_MASK) >> 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map from selected compressor */
|
/* Map from selected compressor (this automatically maps SHARED_COMPRESSOR to windowBits 0, not 1) */
|
||||||
int wantedCompressionWindow = (webSocketContextData->compression & 0xFF00) >> 8;
|
int wantedCompressionWindow = (webSocketContextData->compression & CompressOptions::_COMPRESSOR_MASK) >> 8;
|
||||||
|
|
||||||
auto [negCompression, negCompressionWindow, negInflationWindow, negResponse] =
|
auto [negCompression, negCompressionWindow, negInflationWindow, negResponse] =
|
||||||
negotiateCompression(true, wantedCompressionWindow, wantedInflationWindow,
|
negotiateCompression(true, wantedCompressionWindow, wantedInflationWindow,
|
||||||
@@ -252,7 +252,7 @@ public:
|
|||||||
if (negCompression) {
|
if (negCompression) {
|
||||||
perMessageDeflate = true;
|
perMessageDeflate = true;
|
||||||
|
|
||||||
/* Map from windowBits to compressor */
|
/* Map from negotiated windowBits to compressor and decompressor */
|
||||||
if (negCompressionWindow == 0) {
|
if (negCompressionWindow == 0) {
|
||||||
compressOptions = CompressOptions::SHARED_COMPRESSOR;
|
compressOptions = CompressOptions::SHARED_COMPRESSOR;
|
||||||
} else {
|
} else {
|
||||||
@@ -261,11 +261,18 @@ public:
|
|||||||
|
|
||||||
/* If we are dedicated and have the 3kb then correct any 4kb to 3kb,
|
/* If we are dedicated and have the 3kb then correct any 4kb to 3kb,
|
||||||
* (they both share the windowBits = 9) */
|
* (they both share the windowBits = 9) */
|
||||||
if (webSocketContextData->compression == DEDICATED_COMPRESSOR_3KB) {
|
if (webSocketContextData->compression & DEDICATED_COMPRESSOR_3KB) {
|
||||||
compressOptions = DEDICATED_COMPRESSOR_3KB;
|
compressOptions = DEDICATED_COMPRESSOR_3KB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Here we modify the above compression with negotiated decompressor */
|
||||||
|
if (negInflationWindow == 0) {
|
||||||
|
compressOptions = CompressOptions(compressOptions | CompressOptions::SHARED_DECOMPRESSOR);
|
||||||
|
} else {
|
||||||
|
compressOptions = CompressOptions(compressOptions | (negInflationWindow << 12));
|
||||||
|
}
|
||||||
|
|
||||||
writeHeader("Sec-WebSocket-Extensions", negResponse);
|
writeHeader("Sec-WebSocket-Extensions", negResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-9
@@ -21,17 +21,34 @@
|
|||||||
#define UWS_PERMESSAGEDEFLATE_H
|
#define UWS_PERMESSAGEDEFLATE_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
/* We always define these options no matter if ZLIB is enabled or not */
|
/* We always define these options no matter if ZLIB is enabled or not */
|
||||||
namespace uWS {
|
namespace uWS {
|
||||||
/* Compressor mode is 16 low bit where HIGH8(windowBits), LOW8(memLevel) */
|
/* Compressor mode is 12 lowest bits where HIGH4(windowBits), LOW8(memLevel).
|
||||||
enum CompressOptions : uint32_t {
|
* Decompressor mode is 4 highest bits (windowBits).
|
||||||
|
* If compressor or decompressor bits are 1, then they are shared.
|
||||||
|
* If everything is just simply 0, then everything is disabled. */
|
||||||
|
enum CompressOptions : uint16_t {
|
||||||
|
/* These are not actual compression options */
|
||||||
|
_COMPRESSOR_MASK = 0x0FFF,
|
||||||
|
_DECOMPRESSOR_MASK = 0xF000,
|
||||||
|
/* Disabled, shared, shared are "special" values */
|
||||||
DISABLED = 0,
|
DISABLED = 0,
|
||||||
/* Highest bit is shared compressor */
|
SHARED_COMPRESSOR = 1,
|
||||||
SHARED_COMPRESSOR = (uint32_t)1 << (uint32_t)31,
|
SHARED_DECOMPRESSOR = 1 << 12,
|
||||||
/* Second highest bit is DEDICATED_DECOMPRESSOR */
|
/* Highest 4 bits describe decompressor */
|
||||||
DEDICATED_DECOMPRESSOR = (uint32_t)1 << (uint32_t)30,
|
DEDICATED_DECOMPRESSOR_32KB = 15 << 12,
|
||||||
/* Lowest 16 bit describe compressor */
|
DEDICATED_DECOMPRESSOR_16KB = 14 << 12,
|
||||||
|
DEDICATED_DECOMPRESSOR_8KB = 13 << 12,
|
||||||
|
DEDICATED_DECOMPRESSOR_4KB = 12 << 12,
|
||||||
|
DEDICATED_DECOMPRESSOR_2KB = 11 << 12,
|
||||||
|
DEDICATED_DECOMPRESSOR_1KB = 10 << 12,
|
||||||
|
DEDICATED_DECOMPRESSOR_512B = 9 << 12,
|
||||||
|
/* Same as 32kb */
|
||||||
|
DEDICATED_DECOMPRESSOR = 15 << 12,
|
||||||
|
|
||||||
|
/* Lowest 12 bit describe compressor */
|
||||||
DEDICATED_COMPRESSOR_3KB = 9 << 8 | 1,
|
DEDICATED_COMPRESSOR_3KB = 9 << 8 | 1,
|
||||||
DEDICATED_COMPRESSOR_4KB = 9 << 8 | 2,
|
DEDICATED_COMPRESSOR_4KB = 9 << 8 | 2,
|
||||||
DEDICATED_COMPRESSOR_8KB = 10 << 8 | 3,
|
DEDICATED_COMPRESSOR_8KB = 10 << 8 | 3,
|
||||||
@@ -66,6 +83,8 @@ struct InflationStream {
|
|||||||
std::optional<std::string_view> inflate(ZlibContext * /*zlibContext*/, std::string_view compressed, size_t maxPayloadLength, bool /*reset*/) {
|
std::optional<std::string_view> inflate(ZlibContext * /*zlibContext*/, std::string_view compressed, size_t maxPayloadLength, bool /*reset*/) {
|
||||||
return compressed.substr(0, std::min(maxPayloadLength, compressed.length()));
|
return compressed.substr(0, std::min(maxPayloadLength, compressed.length()));
|
||||||
}
|
}
|
||||||
|
InflationStream(CompressOptions /*compressOptions*/) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct DeflationStream {
|
struct DeflationStream {
|
||||||
std::string_view deflate(ZlibContext * /*zlibContext*/, std::string_view raw, bool /*reset*/) {
|
std::string_view deflate(ZlibContext * /*zlibContext*/, std::string_view raw, bool /*reset*/) {
|
||||||
@@ -196,8 +215,10 @@ struct DeflationStream {
|
|||||||
struct InflationStream {
|
struct InflationStream {
|
||||||
z_stream inflationStream = {};
|
z_stream inflationStream = {};
|
||||||
|
|
||||||
InflationStream() {
|
InflationStream(CompressOptions compressOptions) {
|
||||||
inflateInit2(&inflationStream, -15);
|
/* Inflation windowBits are the top 4 bits of the 16 bit compressOptions */
|
||||||
|
//printf("%d\n", -(compressOptions >> 12));
|
||||||
|
inflateInit2(&inflationStream, -(compressOptions >> 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
~InflationStream() {
|
~InflationStream() {
|
||||||
@@ -225,6 +246,11 @@ struct InflationStream {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Append tail to chunk */
|
||||||
|
unsigned char tail[4] = {0x00, 0x00, 0xff, 0xff};
|
||||||
|
memcpy((char *)compressed.data() + compressed.length(), tail, 4);
|
||||||
|
compressed = {compressed.data(), compressed.length() + 4};
|
||||||
|
|
||||||
/* We clear this one here, could be done better */
|
/* We clear this one here, could be done better */
|
||||||
zlibContext->dynamicInflationBuffer.clear();
|
zlibContext->dynamicInflationBuffer.clear();
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ private:
|
|||||||
if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
|
if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
|
||||||
webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
|
webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
|
||||||
|
|
||||||
/* 9 bytes of padding for libdeflate */
|
/* 9 bytes of padding for libdeflate, 4 for zlib */
|
||||||
webSocketData->fragmentBuffer.append("123456789");
|
webSocketData->fragmentBuffer.append("123456789");
|
||||||
|
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(
|
LoopData *loopData = (LoopData *) us_loop_ext(
|
||||||
|
|||||||
+7
-6
@@ -56,12 +56,13 @@ public:
|
|||||||
compressionStatus = perMessageDeflate ? ENABLED : DISABLED;
|
compressionStatus = perMessageDeflate ? ENABLED : DISABLED;
|
||||||
|
|
||||||
/* Initialize the dedicated sliding window(s) */
|
/* Initialize the dedicated sliding window(s) */
|
||||||
if (perMessageDeflate && (0 == (compressOptions & CompressOptions::SHARED_COMPRESSOR))) {
|
if (perMessageDeflate) {
|
||||||
deflationStream = new DeflationStream(compressOptions);
|
if ((compressOptions & CompressOptions::_COMPRESSOR_MASK) != CompressOptions::SHARED_COMPRESSOR) {
|
||||||
}
|
deflationStream = new DeflationStream(compressOptions);
|
||||||
|
}
|
||||||
if (perMessageDeflate && (compressOptions & CompressOptions::DEDICATED_DECOMPRESSOR)) {
|
if ((compressOptions & CompressOptions::_DECOMPRESSOR_MASK) != CompressOptions::SHARED_DECOMPRESSOR) {
|
||||||
inflationStream = new InflationStream();
|
inflationStream = new InflationStream(compressOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user