Fix up WebSocketContext.h

This commit is contained in:
Alex Hultman
2019-02-10 01:08:10 +01:00
parent f1bdbc968b
commit a419221a28
+30 -59
View File
@@ -23,8 +23,6 @@
#include "WebSocketData.h"
#include "WebSocket.h"
// todo: this module needs fixing! see below!
namespace uWS {
template <bool SSL, bool isServer>
@@ -61,9 +59,7 @@ private:
/* Returns true on breakage */
static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, uWS::WebSocketState<isServer> *webSocketState, void *s) {
/* WebSocketData and WebSocketContextData */
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
us_new_socket_context(SSL, (us_new_socket_t *) s)
);
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
WebSocketData *webSocketData = (WebSocketData *) us_new_socket_ext(SSL, (us_new_socket_t *) s);
/* Is this a non-control frame? */
@@ -75,12 +71,7 @@ private:
if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
LoopData *loopData = (LoopData *)us_loop_ext(
us_new_socket_context_loop(SSL,
us_new_socket_context(SSL, (us_new_socket_t *)s)
)
);
LoopData *loopData = (LoopData *) us_loop_ext(us_new_socket_context_loop(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s)));
std::string_view inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength);
if (!inflatedFrame.length()) {
forceClose(webSocketState, s);
@@ -100,7 +91,7 @@ private:
/* Emit message event & break if we are closed or shut down when returning */
if (webSocketContextData->messageHandler) {
webSocketContextData->messageHandler((WebSocket<SSL, isServer> *) s, std::string_view(data, length), (uWS::OpCode) opCode);
if (us_new_socket_is_closed(SSL, (us_new_socket_t *)s) || webSocketData->isShuttingDown) {
if (us_new_socket_is_closed(SSL, (us_new_socket_t *) s) || webSocketData->isShuttingDown) {
return true;
}
}
@@ -153,7 +144,7 @@ private:
/* Emit message and check for shutdown or close */
if (webSocketContextData->messageHandler) {
webSocketContextData->messageHandler((WebSocket<SSL, isServer> *) s, std::string_view(data, length), (uWS::OpCode) opCode);
if (us_new_socket_is_closed(SSL, (us_new_socket_t *)s) || webSocketData->isShuttingDown) {
if (us_new_socket_is_closed(SSL, (us_new_socket_t *) s) || webSocketData->isShuttingDown) {
return true;
}
}
@@ -221,9 +212,7 @@ private:
}
static bool refusePayloadLength(uint64_t length, uWS::WebSocketState<isServer> *wState, void *s) {
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
us_new_socket_context(SSL, (us_new_socket_t *)s)
);
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
/* Return true for refuse, false for accept */
return webSocketContextData->maxPayloadLength < length;
@@ -241,9 +230,7 @@ private:
WebSocketData *webSocketData = (WebSocketData *) (us_new_socket_ext(SSL, s));
if (!webSocketData->isShuttingDown) {
/* Emit close event */
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
us_new_socket_context(SSL, (us_new_socket_t *)s)
);
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
if (webSocketContextData->closeHandler) {
webSocketContextData->closeHandler((WebSocket<SSL, true> *) s, 1006, {});
@@ -271,40 +258,28 @@ private:
return s;
}
/* Everytime we get data, we reset the timeout to our idleTimeout, that's the only timer we have */
/* If not in websocket shutdown state, for every */
// återställ inte om vi är i shutdown state, dvs, ge den inte massa tid på sig att skicka massa skit-frames mellan och upphålla oss!
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
us_new_socket_context(SSL, (us_new_socket_t *) s)
);
us_new_socket_timeout(SSL, (us_new_socket_t *) s, webSocketContextData->idleTimeout);
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
auto *asyncSocket = (AsyncSocket<SSL> *) s;
/* Every time we get data and not in shutdown state we simply reset the timeout */
asyncSocket->timeout(webSocketContextData->idleTimeout);
/* We always cork on data */
AsyncSocket<SSL> *webSocket = (AsyncSocket<SSL> *) s;
webSocket->cork();
asyncSocket->cork();
/* This parser has virtually no overhead */
uWS::WebSocketProtocol<isServer, WebSocketContext<SSL, isServer>>::consume(data, length, (WebSocketState<isServer> *) webSocketData, s);
// todo: we need to check for close and shutdown here? as we just emitted a bunch of message/close events!
/* Uncorking a closed socekt is fine, in fact it is needed */
asyncSocket->uncork();
// todo: check for failures here just like for HTTP
webSocket->uncork();
// cannot do anything else if closed
if (us_new_socket_is_closed(SSL, (us_new_socket_t *) s)) {
return s;
}
// I guess we need to check drain here - emit drain if we had to poll for writable
// are we shutdown? can onnly call this if we did succeed uncork!
if (webSocketData->isShuttingDown) {
webSocket->shutdown();
/* If uncorking was successful and we are in shutdown state then send TCP FIN */
if (asyncSocket->getBufferedAmount() == 0) {
/* We can now be in shutdown state */
if (webSocketData->isShuttingDown) {
/* Shutting down a closed socket is handled by uSockets and just fine */
asyncSocket->shutdown();
}
}
return s;
@@ -318,35 +293,31 @@ private:
return s;
}
AsyncSocket<SSL> *webSocket = (AsyncSocket<SSL> *) s;
AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
WebSocketData *webSocketData = (WebSocketData *)(us_new_socket_ext(SSL, s));
/* We store old backpressure since it is unclear whether write drained anything */
int backpressure = webSocket->getBufferedAmount();
int backpressure = asyncSocket->getBufferedAmount();
/* Drain as much as possible */
webSocket->write(nullptr, 0);
asyncSocket->write(nullptr, 0);
/* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
if (backpressure < webSocket->getBufferedAmount()) {
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
us_new_socket_context(SSL, (us_new_socket_t *)s)
);
webSocket->timeout(webSocketContextData->idleTimeout);
if (backpressure < asyncSocket->getBufferedAmount()) {
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
asyncSocket->timeout(webSocketContextData->idleTimeout);
}
/* Are we in (WebSocket) shutdown mode? */
if (webSocketData->isShuttingDown) {
/* Check if we just now drained completely */
if (webSocket->getBufferedAmount() == 0) {
if (asyncSocket->getBufferedAmount() == 0) {
/* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
webSocket->shutdown();
asyncSocket->shutdown();
}
} else if (backpressure > webSocket->getBufferedAmount()) {
} else if (backpressure > asyncSocket->getBufferedAmount()) {
/* Only call drain if we actually drained backpressure */
WebSocketContextData<SSL> *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL,
us_new_socket_context(SSL, (us_new_socket_t *)s)
);
auto *webSocketContextData = (WebSocketContextData<SSL> *) us_new_socket_context_ext(SSL, us_new_socket_context(SSL, (us_new_socket_t *) s));
if (webSocketContextData->drainHandler) {
webSocketContextData->drainHandler((WebSocket<SSL, isServer> *) s);
}