Add WITH_LIBDEFLATE option, pass Autobahn
This commit is contained in:
@@ -4,3 +4,6 @@
|
|||||||
[submodule "fuzzing/libEpollFuzzer"]
|
[submodule "fuzzing/libEpollFuzzer"]
|
||||||
path = fuzzing/libEpollFuzzer
|
path = fuzzing/libEpollFuzzer
|
||||||
url = https://github.com/uNetworking/libEpollFuzzer
|
url = https://github.com/uNetworking/libEpollFuzzer
|
||||||
|
[submodule "libdeflate"]
|
||||||
|
path = libdeflate
|
||||||
|
url = https://github.com/ebiggers/libdeflate
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ ifeq ($(WITH_PROXY),1)
|
|||||||
override CXXFLAGS += -DUWS_WITH_PROXY
|
override CXXFLAGS += -DUWS_WITH_PROXY
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# WITH_LIBDEFLATE=1 enables fast paths for SHARED_COMPRESSOR and inflation
|
||||||
|
ifeq ($(WITH_LIBDEFLATE),1)
|
||||||
|
override CXXFLAGS += -I libdeflate -DUWS_USE_LIBDEFLATE
|
||||||
|
override LDFLAGS += libdeflate/libdeflate.a
|
||||||
|
endif
|
||||||
|
|
||||||
# WITH_OPENSSL=1 enables OpenSSL 1.1+ support
|
# WITH_OPENSSL=1 enables OpenSSL 1.1+ support
|
||||||
ifeq ($(WITH_OPENSSL),1)
|
ifeq ($(WITH_OPENSSL),1)
|
||||||
# With problems on macOS, make sure to pass needed LDFLAGS required to find these
|
# With problems on macOS, make sure to pass needed LDFLAGS required to find these
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ int main() {
|
|||||||
}).ws<PerSocketData>("/*", {
|
}).ws<PerSocketData>("/*", {
|
||||||
/* Settings */
|
/* Settings */
|
||||||
.compression = uWS::SHARED_COMPRESSOR,
|
.compression = uWS::SHARED_COMPRESSOR,
|
||||||
.maxPayloadLength = 16 * 1024,
|
.maxPayloadLength = 16 * 1024 * 1024,
|
||||||
.idleTimeout = 16,
|
.idleTimeout = 16,
|
||||||
.maxBackpressure = 1 * 1024 * 1024,
|
.maxBackpressure = 1 * 1024 * 1024,
|
||||||
.closeOnBackpressureLimit = false,
|
.closeOnBackpressureLimit = false,
|
||||||
|
|||||||
Submodule
+1
Submodule libdeflate added at 4d3c0f00d5
@@ -46,6 +46,11 @@ namespace uWS {
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
#ifdef UWS_USE_LIBDEFLATE
|
||||||
|
#include "libdeflate.h"
|
||||||
|
#include <cstring>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace uWS {
|
namespace uWS {
|
||||||
|
|
||||||
/* Do not compile this module if we don't want it */
|
/* Do not compile this module if we don't want it */
|
||||||
@@ -77,14 +82,29 @@ struct ZlibContext {
|
|||||||
char *deflationBuffer;
|
char *deflationBuffer;
|
||||||
char *inflationBuffer;
|
char *inflationBuffer;
|
||||||
|
|
||||||
|
#ifdef UWS_USE_LIBDEFLATE
|
||||||
|
libdeflate_decompressor *decompressor;
|
||||||
|
libdeflate_compressor *compressor;
|
||||||
|
#endif
|
||||||
|
|
||||||
ZlibContext() {
|
ZlibContext() {
|
||||||
deflationBuffer = (char *) malloc(LARGE_BUFFER_SIZE);
|
deflationBuffer = (char *) malloc(LARGE_BUFFER_SIZE);
|
||||||
inflationBuffer = (char *) malloc(LARGE_BUFFER_SIZE);
|
inflationBuffer = (char *) malloc(LARGE_BUFFER_SIZE);
|
||||||
|
|
||||||
|
#ifdef UWS_USE_LIBDEFLATE
|
||||||
|
decompressor = libdeflate_alloc_decompressor();
|
||||||
|
compressor = libdeflate_alloc_compressor(7);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~ZlibContext() {
|
~ZlibContext() {
|
||||||
free(deflationBuffer);
|
free(deflationBuffer);
|
||||||
free(inflationBuffer);
|
free(inflationBuffer);
|
||||||
|
|
||||||
|
#ifdef UWS_USE_LIBDEFLATE
|
||||||
|
libdeflate_free_decompressor(decompressor);
|
||||||
|
libdeflate_free_compressor(compressor);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,6 +125,22 @@ struct DeflationStream {
|
|||||||
|
|
||||||
/* Deflate and optionally reset. You must not deflate an empty string. */
|
/* Deflate and optionally reset. You must not deflate an empty string. */
|
||||||
std::string_view deflate(ZlibContext *zlibContext, std::string_view raw, bool reset) {
|
std::string_view deflate(ZlibContext *zlibContext, std::string_view raw, bool reset) {
|
||||||
|
|
||||||
|
#ifdef UWS_USE_LIBDEFLATE
|
||||||
|
/* Run a fast path in case of shared_compressor */
|
||||||
|
if (reset) {
|
||||||
|
size_t written = 0;
|
||||||
|
static unsigned char buf[1024 + 1];
|
||||||
|
|
||||||
|
written = libdeflate_deflate_compress(zlibContext->compressor, raw.data(), raw.length(), buf, 1024);
|
||||||
|
|
||||||
|
if (written) {
|
||||||
|
memcpy(&buf[written], "\x00", 1);
|
||||||
|
return std::string_view((char *) buf, written + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Odd place to clear this one, fix */
|
/* Odd place to clear this one, fix */
|
||||||
zlibContext->dynamicDeflationBuffer.clear();
|
zlibContext->dynamicDeflationBuffer.clear();
|
||||||
|
|
||||||
@@ -166,6 +202,24 @@ 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) {
|
||||||
|
|
||||||
|
#ifdef UWS_USE_LIBDEFLATE
|
||||||
|
/* Try fast path first */
|
||||||
|
size_t written = 0;
|
||||||
|
static char buf[1024];
|
||||||
|
|
||||||
|
/* We have to pad 9 bytes and restore those bytes when done since 9 is more than 6 of next WebSocket message */
|
||||||
|
char tmp[9];
|
||||||
|
memcpy(tmp, (char *) compressed.data() + compressed.length(), 9);
|
||||||
|
memcpy((char *) compressed.data() + compressed.length(), "\x00\x00\xff\xff\x01\x00\x00\xff\xff", 9);
|
||||||
|
libdeflate_result res = libdeflate_deflate_decompress(zlibContext->decompressor, compressed.data(), compressed.length(), buf, 1024, &written);
|
||||||
|
memcpy((char *) compressed.data() + compressed.length(), tmp, 9);
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
|
/* Fast path wins */
|
||||||
|
return std::string_view(buf, written);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We clear this one here, could be done better */
|
/* We clear this one here, could be done better */
|
||||||
zlibContext->dynamicInflationBuffer.clear();
|
zlibContext->dynamicInflationBuffer.clear();
|
||||||
|
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ 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;
|
||||||
|
|
||||||
// what's really the story here?
|
/* 9 bytes of padding for libdeflate */
|
||||||
webSocketData->fragmentBuffer.append("....");
|
webSocketData->fragmentBuffer.append("123456789");
|
||||||
|
|
||||||
LoopData *loopData = (LoopData *) us_loop_ext(
|
LoopData *loopData = (LoopData *) us_loop_ext(
|
||||||
us_socket_context_loop(SSL,
|
us_socket_context_loop(SSL,
|
||||||
@@ -124,7 +124,7 @@ private:
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
auto inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 4}, webSocketContextData->maxPayloadLength);
|
auto inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength);
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user