From 563e95b5c1e88f6cfb5641306c86c13fec7f5329 Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Sat, 28 Dec 2019 22:57:02 +0100 Subject: [PATCH] Automatically cork WebSocket::send --- src/WebSocket.h | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/WebSocket.h b/src/WebSocket.h index eeb848f..8d37557 100644 --- a/src/WebSocket.h +++ b/src/WebSocket.h @@ -55,12 +55,6 @@ public: /* Send or buffer a WebSocket frame, compressed or not. Returns false on increased user space backpressure. */ bool send(std::string_view message, uWS::OpCode opCode = uWS::OpCode::BINARY, bool compress = false) { - /* Every send resets the timeout */ - WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, - (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) - ); - AsyncSocket::timeout(webSocketContextData->idleTimeout); - /* Transform the message to compressed domain if requested */ if (compress) { WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData(); @@ -79,20 +73,44 @@ public: } } + /* Check to see if we can cork for the user */ + bool automaticallyCorked = false; + if (!Super::isCorked() && Super::canCork()) { + automaticallyCorked = true; + Super::cork(); + } + /* Get size, alloate size, write if needed */ size_t messageFrameSize = protocol::messageFrameSize(message.length()); auto[sendBuffer, requiresWrite] = Super::getSendBuffer(messageFrameSize); protocol::formatMessage(sendBuffer, message.data(), message.length(), opCode, message.length(), compress); + /* This is the slow path, when we couldn't cork for the user */ if (requiresWrite) { auto[written, failed] = Super::write(sendBuffer, (int) messageFrameSize); - /* For now, we are slow here (fix!) */ + /* For now, we are slow here */ free(sendBuffer); - /* Return true for success */ - return !failed; + if (failed) { + /* Return false for failure, skipping to reset the timeout below */ + return false; + } } + /* Uncork here if we automatically corked for the user */ + if (automaticallyCorked) { + auto [written, failed] = Super::uncork(); + if (failed) { + return false; + } + } + + /* Every successful send resets the timeout */ + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, + (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) + ); + AsyncSocket::timeout(webSocketContextData->idleTimeout); + /* Return success */ return true; }