Add WITH_LIBDEFLATE option, pass Autobahn
This commit is contained in:
@@ -4,3 +4,6 @@
|
||||
[submodule "fuzzing/libEpollFuzzer"]
|
||||
path = fuzzing/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
|
||||
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
|
||||
ifeq ($(WITH_OPENSSL),1)
|
||||
# With problems on macOS, make sure to pass needed LDFLAGS required to find these
|
||||
|
||||
@@ -20,7 +20,7 @@ int main() {
|
||||
}).ws<PerSocketData>("/*", {
|
||||
/* Settings */
|
||||
.compression = uWS::SHARED_COMPRESSOR,
|
||||
.maxPayloadLength = 16 * 1024,
|
||||
.maxPayloadLength = 16 * 1024 * 1024,
|
||||
.idleTimeout = 16,
|
||||
.maxBackpressure = 1 * 1024 * 1024,
|
||||
.closeOnBackpressureLimit = false,
|
||||
|
||||
Submodule
+1
Submodule libdeflate added at 4d3c0f00d5
@@ -46,6 +46,11 @@ namespace uWS {
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#ifdef UWS_USE_LIBDEFLATE
|
||||
#include "libdeflate.h"
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
namespace uWS {
|
||||
|
||||
/* Do not compile this module if we don't want it */
|
||||
@@ -77,14 +82,29 @@ struct ZlibContext {
|
||||
char *deflationBuffer;
|
||||
char *inflationBuffer;
|
||||
|
||||
#ifdef UWS_USE_LIBDEFLATE
|
||||
libdeflate_decompressor *decompressor;
|
||||
libdeflate_compressor *compressor;
|
||||
#endif
|
||||
|
||||
ZlibContext() {
|
||||
deflationBuffer = (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() {
|
||||
free(deflationBuffer);
|
||||
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. */
|
||||
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 */
|
||||
zlibContext->dynamicDeflationBuffer.clear();
|
||||
|
||||
@@ -166,6 +202,24 @@ struct InflationStream {
|
||||
/* Zero length inflates are possible and valid */
|
||||
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 */
|
||||
zlibContext->dynamicInflationBuffer.clear();
|
||||
|
||||
|
||||
@@ -115,8 +115,8 @@ private:
|
||||
if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
|
||||
webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
|
||||
|
||||
// what's really the story here?
|
||||
webSocketData->fragmentBuffer.append("....");
|
||||
/* 9 bytes of padding for libdeflate */
|
||||
webSocketData->fragmentBuffer.append("123456789");
|
||||
|
||||
LoopData *loopData = (LoopData *) us_loop_ext(
|
||||
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()) {
|
||||
forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user