Add DEDICATED_DECOMPRESSOR CompressOption
This commit is contained in:
@@ -19,7 +19,7 @@ int main() {
|
|||||||
.passphrase = "1234"
|
.passphrase = "1234"
|
||||||
}).ws<PerSocketData>("/*", {
|
}).ws<PerSocketData>("/*", {
|
||||||
/* Settings */
|
/* Settings */
|
||||||
.compression = uWS::DEDICATED_COMPRESSOR_4KB,
|
.compression = uWS::CompressOptions(uWS::DEDICATED_COMPRESSOR_4KB | uWS::DEDICATED_DECOMPRESSOR),
|
||||||
.maxPayloadLength = 100 * 1024 * 1024,
|
.maxPayloadLength = 100 * 1024 * 1024,
|
||||||
.idleTimeout = 16,
|
.idleTimeout = 16,
|
||||||
.maxBackpressure = 100 * 1024 * 1024,
|
.maxBackpressure = 100 * 1024 * 1024,
|
||||||
@@ -30,6 +30,7 @@ int main() {
|
|||||||
.upgrade = nullptr,
|
.upgrade = nullptr,
|
||||||
.open = [](auto */*ws*/) {
|
.open = [](auto */*ws*/) {
|
||||||
/* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
|
/* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
|
||||||
|
|
||||||
},
|
},
|
||||||
.message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
|
.message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
|
||||||
ws->send(message, opCode, true);
|
ws->send(message, opCode, true);
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public:
|
|||||||
unsigned int numSubscribers(std::string_view topic) {
|
unsigned int numSubscribers(std::string_view topic) {
|
||||||
Topic *t = topicTree->lookupTopic(topic);
|
Topic *t = topicTree->lookupTopic(topic);
|
||||||
if (t) {
|
if (t) {
|
||||||
return t->size();
|
return (unsigned int) t->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+4
-1
@@ -236,8 +236,11 @@ 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 */
|
/* We always want shared inflation, (or the full 15) */
|
||||||
int wantedInflationWindow = 0;
|
int wantedInflationWindow = 0;
|
||||||
|
if (webSocketContextData->compression & DEDICATED_DECOMPRESSOR) {
|
||||||
|
wantedInflationWindow = 15;
|
||||||
|
}
|
||||||
|
|
||||||
/* Map from selected compressor */
|
/* Map from selected compressor */
|
||||||
int wantedCompressionWindow = (webSocketContextData->compression & 0xFF00) >> 8;
|
int wantedCompressionWindow = (webSocketContextData->compression & 0xFF00) >> 8;
|
||||||
|
|||||||
+13
-7
@@ -24,10 +24,14 @@
|
|||||||
|
|
||||||
/* 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 HIGH8(windowBits), LOW8(memLevel) */
|
/* Compressor mode is 16 low bit where HIGH8(windowBits), LOW8(memLevel) */
|
||||||
enum CompressOptions : uint32_t {
|
enum CompressOptions : uint32_t {
|
||||||
DISABLED = 0,
|
DISABLED = 0,
|
||||||
SHARED_COMPRESSOR = 1,
|
/* Highest bit is shared compressor */
|
||||||
|
SHARED_COMPRESSOR = (uint32_t)1 << (uint32_t)31,
|
||||||
|
/* Second highest bit is DEDICATED_DECOMPRESSOR */
|
||||||
|
DEDICATED_DECOMPRESSOR = (uint32_t)1 << (uint32_t)30,
|
||||||
|
/* Lowest 16 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,
|
||||||
@@ -59,15 +63,15 @@ namespace uWS {
|
|||||||
#if defined(UWS_NO_ZLIB) || defined(UWS_MOCK_ZLIB)
|
#if defined(UWS_NO_ZLIB) || defined(UWS_MOCK_ZLIB)
|
||||||
struct ZlibContext {};
|
struct ZlibContext {};
|
||||||
struct InflationStream {
|
struct InflationStream {
|
||||||
std::optional<std::string_view> inflate(ZlibContext *zlibContext, std::string_view compressed, size_t maxPayloadLength) {
|
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()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
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*/) {
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
DeflationStream(int compressOptions) {
|
DeflationStream(CompressOptions /*compressOptions*/) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
@@ -201,7 +205,7 @@ struct InflationStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Zero length inflates are possible and valid */
|
/* Zero length inflates are possible and valid */
|
||||||
std::optional<std::string_view> inflate(ZlibContext *zlibContext, std::string_view compressed, size_t maxPayloadLength) {
|
std::optional<std::string_view> inflate(ZlibContext *zlibContext, std::string_view compressed, size_t maxPayloadLength, bool reset) {
|
||||||
|
|
||||||
#ifdef UWS_USE_LIBDEFLATE
|
#ifdef UWS_USE_LIBDEFLATE
|
||||||
/* Try fast path first */
|
/* Try fast path first */
|
||||||
@@ -242,7 +246,9 @@ struct InflationStream {
|
|||||||
|
|
||||||
} while (inflationStream.avail_out == 0 && zlibContext->dynamicInflationBuffer.length() <= maxPayloadLength);
|
} while (inflationStream.avail_out == 0 && zlibContext->dynamicInflationBuffer.length() <= maxPayloadLength);
|
||||||
|
|
||||||
inflateReset(&inflationStream);
|
if (reset) {
|
||||||
|
inflateReset(&inflationStream);
|
||||||
|
}
|
||||||
|
|
||||||
if ((err != Z_BUF_ERROR && err != Z_OK) || zlibContext->dynamicInflationBuffer.length() > maxPayloadLength) {
|
if ((err != Z_BUF_ERROR && err != Z_OK) || zlibContext->dynamicInflationBuffer.length() > maxPayloadLength) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|||||||
+16
-2
@@ -72,7 +72,14 @@ private:
|
|||||||
webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
|
webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
|
||||||
|
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) s)));
|
LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) s)));
|
||||||
auto inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength);
|
/* Decompress using shared or dedicated decompressor */
|
||||||
|
std::optional<std::string_view> inflatedFrame;
|
||||||
|
if (webSocketData->inflationStream) {
|
||||||
|
inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, false);
|
||||||
|
} else {
|
||||||
|
inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!inflatedFrame.has_value()) {
|
if (!inflatedFrame.has_value()) {
|
||||||
forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
|
forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
|
||||||
return true;
|
return true;
|
||||||
@@ -124,7 +131,14 @@ private:
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
auto inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength);
|
/* Decompress using shared or dedicated decompressor */
|
||||||
|
std::optional<std::string_view> inflatedFrame;
|
||||||
|
if (webSocketData->inflationStream) {
|
||||||
|
inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, false);
|
||||||
|
} else {
|
||||||
|
inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!inflatedFrame.has_value()) {
|
if (!inflatedFrame.has_value()) {
|
||||||
forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
|
forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+12
-2
@@ -46,6 +46,8 @@ private:
|
|||||||
|
|
||||||
/* We might have a dedicated compressor */
|
/* We might have a dedicated compressor */
|
||||||
DeflationStream *deflationStream = nullptr;
|
DeflationStream *deflationStream = nullptr;
|
||||||
|
/* And / or a dedicated decompressor */
|
||||||
|
InflationStream *inflationStream = nullptr;
|
||||||
|
|
||||||
/* We could be a subscriber */
|
/* We could be a subscriber */
|
||||||
Subscriber *subscriber = nullptr;
|
Subscriber *subscriber = nullptr;
|
||||||
@@ -53,10 +55,14 @@ public:
|
|||||||
WebSocketData(bool perMessageDeflate, CompressOptions compressOptions, BackPressure &&backpressure) : AsyncSocketData<false>(std::move(backpressure)), WebSocketState<true>() {
|
WebSocketData(bool perMessageDeflate, CompressOptions compressOptions, BackPressure &&backpressure) : AsyncSocketData<false>(std::move(backpressure)), WebSocketState<true>() {
|
||||||
compressionStatus = perMessageDeflate ? ENABLED : DISABLED;
|
compressionStatus = perMessageDeflate ? ENABLED : DISABLED;
|
||||||
|
|
||||||
/* Initialize the dedicated sliding window */
|
/* Initialize the dedicated sliding window(s) */
|
||||||
if (perMessageDeflate && (compressOptions != CompressOptions::SHARED_COMPRESSOR)) {
|
if (perMessageDeflate && (0 == (compressOptions & CompressOptions::SHARED_COMPRESSOR))) {
|
||||||
deflationStream = new DeflationStream(compressOptions);
|
deflationStream = new DeflationStream(compressOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (perMessageDeflate && (compressOptions & CompressOptions::DEDICATED_DECOMPRESSOR)) {
|
||||||
|
inflationStream = new InflationStream();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~WebSocketData() {
|
~WebSocketData() {
|
||||||
@@ -64,6 +70,10 @@ public:
|
|||||||
delete deflationStream;
|
delete deflationStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inflationStream) {
|
||||||
|
delete inflationStream;
|
||||||
|
}
|
||||||
|
|
||||||
if (subscriber) {
|
if (subscriber) {
|
||||||
delete subscriber;
|
delete subscriber;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user