Experimental: rewrite extensions negotiation

This commit is contained in:
Alex Hultman
2021-01-11 07:27:40 +01:00
parent a86a500f3b
commit 7265ffe480
8 changed files with 236 additions and 155 deletions
+26 -54
View File
@@ -214,67 +214,39 @@ public:
writeHeader("Sec-WebSocket-Protocol", secWebSocketProtocol.substr(0, secWebSocketProtocol.find(',')));
}
/* Negotiate compression, we may use a smaller compression window than we negotiate */
/* Negotiate compression */
bool perMessageDeflate = false;
/* We are always allowed to share compressor, if perMessageDeflate */
int compressOptions = webSocketContextData->compression & SHARED_COMPRESSOR;
if (webSocketContextData->compression != DISABLED) {
if (secWebSocketExtensions.length()) {
/* We never support client context takeover (the client cannot compress with a sliding window). */
unsigned int wantedOptions = PERMESSAGE_DEFLATE | CLIENT_NO_CONTEXT_TAKEOVER;
CompressOptions compressOptions = CompressOptions::DISABLED;
if (secWebSocketExtensions.length() && webSocketContextData->compression != DISABLED) {
/* Shared compressor is the default */
if (webSocketContextData->compression == SHARED_COMPRESSOR) {
/* Disable per-socket compressor */
wantedOptions |= SERVER_NO_CONTEXT_TAKEOVER;
}
/* We always want shared inflation */
int wantedInflationWindow = 0;
/* isServer = true */
ExtensionsNegotiator<true> extensionsNegotiator(wantedOptions);
extensionsNegotiator.readOffer(secWebSocketExtensions);
/* Map from selected compressor */
int wantedCompressionWindow = (webSocketContextData->compression & 0xFF00) >> 8;
/* Todo: remove these mid string copies */
std::string offer = extensionsNegotiator.generateOffer();
if (offer.length()) {
auto [negCompression, negCompressionWindow, negInflationWindow, negResponse] =
uWS::negotiateCompression(true, wantedCompressionWindow, wantedInflationWindow,
secWebSocketExtensions);
/* Todo: this is a quick fix that should be properly moved to ExtensionsNegotiator */
if (webSocketContextData->compression & DEDICATED_COMPRESSOR &&
webSocketContextData->compression != DEDICATED_COMPRESSOR_256KB) {
/* 3kb, 4kb is 9, 256 is 15 (default) */
int maxServerWindowBits = 9;
switch (webSocketContextData->compression) {
case DEDICATED_COMPRESSOR_8KB:
maxServerWindowBits = 10;
break;
case DEDICATED_COMPRESSOR_16KB:
maxServerWindowBits = 11;
break;
case DEDICATED_COMPRESSOR_32KB:
maxServerWindowBits = 12;
break;
case DEDICATED_COMPRESSOR_64KB:
maxServerWindowBits = 13;
break;
case DEDICATED_COMPRESSOR_128KB:
maxServerWindowBits = 14;
break;
}
offer += "; server_max_window_bits=";
offer += std::to_string(maxServerWindowBits);
if (negCompression) {
perMessageDeflate = true;
/* Map from windowBits to compressor */
if (negCompressionWindow == 0) {
compressOptions = CompressOptions::SHARED_COMPRESSOR;
} else {
compressOptions = (CompressOptions) ((uint32_t) (negCompressionWindow << 8)
| (uint32_t) (negCompressionWindow - 7));
/* If we are dedicated and have the 3kb then correct any 4kb to 3kb,
* (they both share the windowBits = 9) */
if (webSocketContextData->compression == DEDICATED_COMPRESSOR_3KB) {
compressOptions = DEDICATED_COMPRESSOR_3KB;
}
writeHeader("Sec-WebSocket-Extensions", offer);
}
/* Did we negotiate permessage-deflate? */
if (extensionsNegotiator.getNegotiatedOptions() & PERMESSAGE_DEFLATE) {
perMessageDeflate = true;
}
/* Is the server allowed to compress with a sliding window? */
if (!(extensionsNegotiator.getNegotiatedOptions() & SERVER_NO_CONTEXT_TAKEOVER)) {
compressOptions = webSocketContextData->compression;
}
writeHeader("Sec-WebSocket-Extensions", negResponse);
}
}
@@ -372,7 +344,7 @@ public:
/* Write an HTTP header with unsigned int value */
HttpResponse *writeHeader(std::string_view key, uint64_t value) {
writeStatus(HTTP_200_OK);
Super::write(key.data(), (int) key.length());
Super::write(": ", 2);
writeUnsigned64(value);