Commit ee22eebb authored by Alex Hultman's avatar Alex Hultman
Browse files

Optimize control frame path, 104 byte WebSockets

parent 3f3874d1
......@@ -11,13 +11,14 @@ struct Group;
template <const bool isServer>
struct WIN32_EXPORT WebSocket : uS::Socket, WebSocketProtocol<isServer> {
std::string fragmentBuffer;
enum CompressionStatus : char {
DISABLED,
ENABLED,
COMPRESSED_FRAME
} compressionStatus;
char hasOutstandingPong = false;
std::string fragmentBuffer, controlBuffer;
unsigned char controlTipLength = 0;
WebSocket(bool perMessageDeflate, uS::Socket *socket) : uS::Socket(std::move(*socket)) {
compressionStatus = perMessageDeflate ? CompressionStatus::ENABLED : CompressionStatus::DISABLED;
......
......@@ -3,7 +3,7 @@
namespace uWS {
template <const bool isServer>
bool WebSocketProtocol<isServer>::setCompressed(void *user) {
bool WebSocketProtocol<isServer>::setCompressed(void *user) {
WebSocket<isServer> *webSocket = (WebSocket<isServer> *) user;
if (webSocket->compressionStatus == WebSocket<isServer>::CompressionStatus::ENABLED) {
......@@ -80,28 +80,53 @@ bool WebSocketProtocol<isServer>::handleFragment(char *data, size_t length, unsi
}
}
} else {
// todo: we don't need to buffer up in most cases!
webSocket->controlBuffer.append(data, length);
if (!remainingBytes && fin) {
if (!remainingBytes && fin && !webSocket->controlTipLength) {
if (opCode == CLOSE) {
CloseFrame closeFrame = parseClosePayload((char *) webSocket->controlBuffer.data(), webSocket->controlBuffer.length());
CloseFrame closeFrame = parseClosePayload(data, length);
webSocket->close(closeFrame.code, closeFrame.message, closeFrame.length);
return true;
} else {
if (opCode == PING) {
webSocket->send(webSocket->controlBuffer.data(), webSocket->controlBuffer.length(), (OpCode) OpCode::PONG);
((Group<isServer> *) webSocket->nodeData)->pingHandler(webSocket, (char *) webSocket->controlBuffer.data(), webSocket->controlBuffer.length());
webSocket->send(data, length, (OpCode) OpCode::PONG);
((Group<isServer> *) webSocket->nodeData)->pingHandler(webSocket, data, length);
if (webSocket->isClosed() || webSocket->isShuttingDown()) {
return true;
}
} else if (opCode == PONG) {
((Group<isServer> *) webSocket->nodeData)->pongHandler(webSocket, (char *) webSocket->controlBuffer.data(), webSocket->controlBuffer.length());
((Group<isServer> *) webSocket->nodeData)->pongHandler(webSocket, data, length);
if (webSocket->isClosed() || webSocket->isShuttingDown()) {
return true;
}
}
}
webSocket->controlBuffer.clear();
} else {
webSocket->fragmentBuffer.append(data, length);
webSocket->controlTipLength += length;
if (!remainingBytes && fin) {
char *controlBuffer = (char *) webSocket->fragmentBuffer.data() + webSocket->fragmentBuffer.length() - webSocket->controlTipLength;
if (opCode == CLOSE) {
CloseFrame closeFrame = parseClosePayload(controlBuffer, webSocket->controlTipLength);
webSocket->close(closeFrame.code, closeFrame.message, closeFrame.length);
return true;
} else {
if (opCode == PING) {
webSocket->send(controlBuffer, webSocket->controlTipLength, (OpCode) OpCode::PONG);
((Group<isServer> *) webSocket->nodeData)->pingHandler(webSocket, controlBuffer, webSocket->controlTipLength);
if (webSocket->isClosed() || webSocket->isShuttingDown()) {
return true;
}
} else if (opCode == PONG) {
((Group<isServer> *) webSocket->nodeData)->pongHandler(webSocket, controlBuffer, webSocket->controlTipLength);
if (webSocket->isClosed() || webSocket->isShuttingDown()) {
return true;
}
}
}
webSocket->fragmentBuffer.resize(webSocket->fragmentBuffer.length() - webSocket->controlTipLength);
webSocket->controlTipLength = 0;
}
}
}
......
......@@ -1001,8 +1001,13 @@ void serveHttp() {
}
void testReceivePerformance() {
// "Rock it with HTML5 WebSockets!"
unsigned char webSocketMessage[] = {0x81, 0x9c, 0x37, 0x22, 0x79, 0xa5, 0x65, 0x4d, 0x1a, 0xce, 0x17, 0x4b, 0x0d, 0x85, 0x40, 0x4b
// Text "Rock it with HTML5 WebSocket"
/*unsigned char webSocketMessage[] = {0x81, 0x9c, 0x37, 0x22, 0x79, 0xa5, 0x65, 0x4d, 0x1a, 0xce, 0x17, 0x4b, 0x0d, 0x85, 0x40, 0x4b
,0x0d, 0xcd, 0x17, 0x6a, 0x2d, 0xe8, 0x7b, 0x17, 0x59, 0xf2, 0x52, 0x40, 0x2a, 0xca, 0x54, 0x49
,0x1c, 0xd1};*/
// Pong "Rock it with HTML5 WebSocket"
unsigned char webSocketMessage[] = {0x8a, 0x9c, 0x37, 0x22, 0x79, 0xa5, 0x65, 0x4d, 0x1a, 0xce, 0x17, 0x4b, 0x0d, 0x85, 0x40, 0x4b
,0x0d, 0xcd, 0x17, 0x6a, 0x2d, 0xe8, 0x7b, 0x17, 0x59, 0xf2, 0x52, 0x40, 0x2a, 0xca, 0x54, 0x49
,0x1c, 0xd1};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment