Add WITH_LIBDEFLATE option, pass Autobahn

This commit is contained in:
Alex Hultman
2021-02-24 09:22:04 +01:00
parent 414fd1b6a9
commit 3eae7116e7
6 changed files with 68 additions and 4 deletions
+3
View File
@@ -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
+6
View File
@@ -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
+1 -1
View File
@@ -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
+54
View File
@@ -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();
+3 -3
View File
@@ -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;