Move most upgrading into HttpResponse

This commit is contained in:
Alex Hultman
2020-06-02 10:08:31 +02:00
parent c897cca38c
commit a8539e7463
2 changed files with 65 additions and 61 deletions
+7 -60
View File
@@ -25,8 +25,6 @@
#include "HttpResponse.h"
#include "WebSocketContext.h"
#include "WebSocket.h"
#include "WebSocketExtensions.h"
#include "WebSocketHandshake.h"
#include "PerMessageDeflate.h"
namespace uWS {
@@ -168,69 +166,18 @@ public:
// handle close here
} else {
/* Default handler upgrades to WebSocket */
std::string_view secWebSocketProtocol = req->getHeader("sec-websocket-protocol");
std::string_view secWebSocketExtensions = req->getHeader("sec-websocket-extensions");
res->upgrade(secWebSocketKey, secWebSocketProtocol, secWebSocketExtensions, behavior.compression);
}
/* Note: OpenSSL can be used here to speed this up somewhat */
char secWebSocketAccept[29] = {};
WebSocketHandshake::generate(secWebSocketKey.data(), secWebSocketAccept);
res->writeStatus("101 Switching Protocols")
->writeHeader("Upgrade", "websocket")
->writeHeader("Connection", "Upgrade")
->writeHeader("Sec-WebSocket-Accept", secWebSocketAccept);
/* Select first subprotocol if present */
std::string_view secWebSocketProtocol = req->getHeader("sec-websocket-protocol");
if (secWebSocketProtocol.length()) {
res->writeHeader("Sec-WebSocket-Protocol", secWebSocketProtocol.substr(0, secWebSocketProtocol.find(',')));
}
/* Negotiate compression, we may use a smaller compression window than we negotiate */
bool perMessageDeflate = false;
/* We are always allowed to share compressor, if perMessageDeflate */
int compressOptions = behavior.compression & SHARED_COMPRESSOR;
if (behavior.compression != DISABLED) {
std::string_view extensions = req->getHeader("sec-websocket-extensions");
if (extensions.length()) {
/* We never support client context takeover (the client cannot compress with a sliding window). */
int wantedOptions = PERMESSAGE_DEFLATE | CLIENT_NO_CONTEXT_TAKEOVER;
/* Shared compressor is the default */
if (behavior.compression == SHARED_COMPRESSOR) {
/* Disable per-socket compressor */
wantedOptions |= SERVER_NO_CONTEXT_TAKEOVER;
}
/* isServer = true */
ExtensionsNegotiator<true> extensionsNegotiator(wantedOptions);
extensionsNegotiator.readOffer(extensions);
/* Todo: remove these mid string copies */
std::string offer = extensionsNegotiator.generateOffer();
if (offer.length()) {
res->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 = behavior.compression;
}
}
}
/* This will add our mark */
res->upgrade();
/* Move any backpressure */
std::string backpressure(std::move(((AsyncSocketData<SSL> *) res->getHttpResponseData())->buffer));
@@ -249,7 +196,7 @@ public:
/* Initialize websocket with any moved backpressure intact */
httpContext->upgradeToWebSocket(
webSocket->init(perMessageDeflate, compressOptions, std::move(backpressure))
webSocket->init(/*perMessageDeflate*/ false, /*compressOptions*/ 0, std::move(backpressure))
);
/* Arm idleTimeout */
+58 -1
View File
@@ -25,6 +25,9 @@
#include "HttpContextData.h"
#include "Utilities.h"
#include "WebSocketExtensions.h"
#include "WebSocketHandshake.h"
#include "f2/function2.hpp"
/* todo: tryWrite is missing currently, only send smaller segments with write */
@@ -162,7 +165,61 @@ private:
}
/* This call is identical to end, but will never write content-length and is thus suitable for upgrades */
void upgrade() {
void upgrade(std::string_view secWebSocketKey, std::string_view secWebSocketProtocol, std::string_view secWebSocketExtensions, int compression) {
/* Note: OpenSSL can be used here to speed this up somewhat */
char secWebSocketAccept[29] = {};
WebSocketHandshake::generate(secWebSocketKey.data(), secWebSocketAccept);
writeStatus("101 Switching Protocols")
->writeHeader("Upgrade", "websocket")
->writeHeader("Connection", "Upgrade")
->writeHeader("Sec-WebSocket-Accept", secWebSocketAccept);
/* Select first subprotocol if present */
//std::string_view secWebSocketProtocol = req->getHeader("sec-websocket-protocol");
if (secWebSocketProtocol.length()) {
writeHeader("Sec-WebSocket-Protocol", secWebSocketProtocol.substr(0, secWebSocketProtocol.find(',')));
}
/* Negotiate compression, we may use a smaller compression window than we negotiate */
bool perMessageDeflate = false;
/* We are always allowed to share compressor, if perMessageDeflate */
int compressOptions = /*behavior.compression*/ compression & SHARED_COMPRESSOR;
if (/*behavior.compression*/ compression != DISABLED) {
//std::string_view extensions = req->getHeader("sec-websocket-extensions");
if (secWebSocketExtensions.length()) {
/* We never support client context takeover (the client cannot compress with a sliding window). */
int wantedOptions = PERMESSAGE_DEFLATE | CLIENT_NO_CONTEXT_TAKEOVER;
/* Shared compressor is the default */
if (/*behavior.compression*/ compression == SHARED_COMPRESSOR) {
/* Disable per-socket compressor */
wantedOptions |= SERVER_NO_CONTEXT_TAKEOVER;
}
/* isServer = true */
ExtensionsNegotiator<true> extensionsNegotiator(wantedOptions);
extensionsNegotiator.readOffer(secWebSocketExtensions);
/* Todo: remove these mid string copies */
std::string offer = extensionsNegotiator.generateOffer();
if (offer.length()) {
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 = /*behavior.*/compression;
}
}
}
internalEnd({nullptr, 0}, 0, false, false);
}