Never compress 0 bytes, finish pub/sub ded. compr.

This commit is contained in:
Alex Hultman
2020-06-22 07:10:43 +02:00
parent e9e6d3fa34
commit f52d816032
5 changed files with 21 additions and 10 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ int main() {
/* Very simple WebSocket broadcasting echo server */
uWS::App().ws<PerSocketData>("/*", {
/* Settings */
.compression = uWS::SHARED_COMPRESSOR,
.compression = uWS::DEDICATED_COMPRESSOR_3KB,
.maxPayloadLength = 16 * 1024 * 1024,
.idleTimeout = 10,
.maxBackpressure = 1 * 1024 * 1024,
+1 -1
View File
@@ -28,7 +28,7 @@ int main() {
/* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
},
.message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
ws->send(message, opCode);
ws->send(message, opCode, true);
},
.drain = [](auto *ws) {
/* Check ws->getBufferedAmount() here */
+3 -1
View File
@@ -131,7 +131,7 @@ struct DeflationStream {
deflateInit2(&deflationStream, 1, Z_DEFLATED, windowBits, memLevel, Z_DEFAULT_STRATEGY);
}
/* Deflate and optionally reset */
/* Deflate and optionally reset. You must not deflate an empty string. */
std::string_view deflate(ZlibContext *zlibContext, std::string_view raw, bool reset) {
/* Odd place to clear this one, fix */
zlibContext->dynamicDeflationBuffer.clear();
@@ -167,6 +167,8 @@ struct DeflationStream {
return {(char *) zlibContext->dynamicDeflationBuffer.data(), zlibContext->dynamicDeflationBuffer.length() - 4};
}
/* Note: We will get an interger overflow resulting in heap buffer overflow if Z_BUF_ERROR is returned
* from passing 0 as avail_in. Therefore we must not deflate an empty string */
return {
zlibContext->deflationBuffer,
DEFLATE_OUTPUT_CHUNK - deflationStream.avail_out - 4
+3 -3
View File
@@ -71,8 +71,8 @@ public:
if (compress) {
WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
/* Check and correct the compress hint */
if (opCode < 3 && webSocketData->compressionStatus == WebSocketData::ENABLED) {
/* Check and correct the compress hint. It is never valid to compress 0 bytes */
if (message.length() && opCode < 3 && webSocketData->compressionStatus == WebSocketData::ENABLED) {
LoopData *loopData = Super::getLoopData();
/* Compress using either shared or dedicated deflationStream */
if (webSocketData->deflationStream) {
@@ -94,7 +94,7 @@ public:
/* Get size, alloate size, write if needed */
size_t messageFrameSize = protocol::messageFrameSize(message.length());
auto[sendBuffer, requiresWrite] = Super::getSendBuffer(messageFrameSize);
auto [sendBuffer, requiresWrite] = Super::getSendBuffer(messageFrameSize);
protocol::formatMessage<isServer>(sendBuffer, message.data(), message.length(), opCode, message.length(), compress);
/* This is the slow path, when we couldn't cork for the user */
if (requiresWrite) {
+13 -4
View File
@@ -92,15 +92,22 @@ public:
WebSocket<SSL, true> *ws = (WebSocket<SSL, true> *) asyncSocket;
/* We need to handle being corked, and corking here */
bool needsUncorking = false;
if (!ws->isCorked() && ws->canCork()) {
asyncSocket->cork();
needsUncorking = true;
}
while (selectedData.length()) {
/* Interpret the data like so */
/* Interpret the data like so, because this is how we shoved it in */
MessageMetadata mm;
memcpy((char *) &mm, selectedData.data(), sizeof(MessageMetadata));
std::string_view unframedMessage(selectedData.data() + sizeof(MessageMetadata), mm.length);
//std::cout << "<" << unframedMessage << ">" << std::endl;
/* Skip this message if our backpressure is too high */
if (maxBackpressure && ws->getBufferedAmount() > maxBackpressure) {
break;
}
/* Here we perform the actual compression and framing */
ws->send(unframedMessage, mm.opCode, mm.compress);
@@ -110,7 +117,9 @@ public:
}
/* Here we need to uncork or keep it as was */
if (needsUncorking) {
asyncSocket->uncork();
}
/* See below */
return 0;