skaarj1989 / mWebSockets

WebSockets for microcontrollers
https://skaarj1989.github.io/mWebSockets/autobahn-testsuite/servers/
MIT License
108 stars 23 forks source link

RSV1 set to one but must be zero #23

Closed gitneko closed 3 years ago

gitneko commented 4 years ago

I'm currently in the works of making this library work with MKR1000 and WiFi101 and I'm testing this with a Node.js websocket client. However whenever I try to send a message from Node.js, the connection will fail with Invalid WebSocket frame: RSV1 must be clear, which indicates this library sets RSV1 to one, even though no extension was actually negated (https://github.com/websockets/ws/issues/1140#issuecomment-308016758, https://tools.ietf.org/html/rfc6455#section-5.2).

In my config.h I've uncommented the "debug macros"

#define _DEBUG
#define _DUMP_HANDSHAKE
#define _DUMP_HEADER
#define _DUMP_FRAME_DATA

And on the serial I can see the following getting printed (and that's all of it):

17:43:13.645 -> [Line #0] GET / HTTP/1.1
17:43:13.645 -> [Line #1] Sec-WebSocket-Version: 13
17:43:13.645 -> [Line #2] Sec-WebSocket-Key: aaab5frEyNghA1Yrsz9Fxg==
17:43:13.645 -> [Line #3] Connection: Upgrade
17:43:13.645 -> [Line #4] Upgrade: websocket
17:43:13.645 -> [Line #5] Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
17:43:13.645 -> [Line #6] Host: 192.168.1.39:3000
17:43:13.645 -> [Line #7] 
17:43:13.679 -> New websocket connection

Node.js output:

connected
RangeError: Invalid WebSocket frame: RSV1 must be clear
    at Receiver.getInfo (C:\Users\GG\Downloads\node_modules\ws\lib\receiver.js:178:14)
    at Receiver.startLoop (C:\Users\GG\Downloads\node_modules\ws\lib\receiver.js:131:22)
    at Receiver._write (C:\Users\GG\Downloads\node_modules\ws\lib\receiver.js:78:10)
    at writeOrBuffer (_stream_writable.js:352:12)
    at Receiver.Writable.write (_stream_writable.js:303:10)
    at Socket.socketOnData (C:\Users\GG\Downloads\node_modules\ws\lib\websocket.js:872:35)
    at Socket.emit (events.js:314:20)
    at addChunk (_stream_readable.js:307:12)
    at readableAddChunk (_stream_readable.js:282:9)
    at Socket.Readable.push (_stream_readable.js:221:10) {
  [Symbol(status-code)]: 1002
}

Node.js client code:

const WebSocket = require('ws');

const ws = new WebSocket('ws://192.168.1.39:3000');

const data = {
    "type": "standard",
    "id": 128,
    "dlc": null,
    "rtr": false,
    "data": "hello123"
};

ws.on('error', function (error) {
  console.log(error);
});

ws.on('open', function () {
  console.log('connected');
  setTimeout(() => ws.send(JSON.stringify(data)), 2000);
});

ws.on('message', function (data) {
  console.log(data);
});

I'm using a little more code for all my setup and peripheries, but this is a simplified version:

net::WebSocketServer wss(3000);

void ws_configure_websocket() {
  wss.onConnection([](net::WebSocket& ws) {
    ws.onClose([](net::WebSocket& wsc, const net::WebSocket::CloseCode& code, const char* reason, uint16_t length) {
      Serial.println("Websocket client closed");
    });

    ws.onMessage([](net::WebSocket& wsc, const net::WebSocket::DataType& dataType, const char* message, uint16_t length) {
      Serial.println("New websocket message");
    });

    Serial.println("New websocket connection");
  });

  wss.begin();
}

void ws_loop_websocket() {
  int status = WiFi.status();

  if (status == WL_CONNECTED) {
    wss.listen();
  }
}

void setup() {
 ws_configure_websocket();
}

void loop() {
  ws_loop_websocket();
}
skaarj1989 commented 4 years ago
  1. Test against RSV passed
  2. This implementation does not support any websocket extensions (due to lack of memory).

Can you force disable permessage-deflate in node.js?

gitneko commented 4 years ago

The Node.js ws client documentation says that the extension is only enabled if the server supports it and it is enabled, which means that the extension must be negotiated before it is used (which is done by sending a HTTP header in the response to the initial HTTP request).

Which suggests to me, even though the server does not support it, it sends a RSV1 even though it's not enabled and negotiated. Looking at the code, the protocol implementation seems flawed to me. I'll report back after more investigation and testing.

skaarj1989 commented 4 years ago

On your server listing I don't see any RX FRAME TX FRAME