proof-of-concept sending packets to client

This commit is contained in:
hippoz 2021-02-03 02:18:28 +02:00
parent 7fd4c589df
commit a53cd1b771
Signed by: hippoz
GPG key ID: 7C52899193467641
3 changed files with 53 additions and 3 deletions

View file

@ -8,6 +8,7 @@ const wormhole = new Wormhole({ urls: [ '/hello' ], httpServer });
wormhole.on('connect', ({ socket, accept, reject }) => {
accept();
socket.sendText('hello');
});
httpServer.listen(8080);

View file

@ -14,6 +14,8 @@ class WebsocketFrame {
this.MASK = undefined;
this.PayloadLen = undefined;
this.PayloadLenEx = undefined; // This is for when PayloadLen needs to be extended
// 4 bytes - masking key
this.MaskingKey = undefined;
@ -23,6 +25,30 @@ class WebsocketFrame {
}
}
WebsocketFrame.prototype.toBuffer = function() {
const packet = [];
const firstByte = this.FIN << 0x07 | this.RSVx << 0x06 | this.Opcode;
const secondByte = this.MASK << 0x07 | this.PayloadLen;
const headerBuffer = Buffer.from([firstByte, secondByte]);
packet.push(headerBuffer);
let lenBuffer;
if (this.PayloadLen === 126) {
lenBuffer = Buffer.alloc(2);
buf.writeUint16BE(this.PayloadLenEx);
} else if (this.PayloadLen === 127) {
lenBuffer = Buffer.alloc(8);
buf.writeBigUint64BE(this.PayloadLenEx);
}
lenBuffer && packet.push(lenBuffer);
this.MASK && packet.push(this.MaskingKey);
packet.push(this.PayloadData);
return Buffer.concat(packet);
};
const parseWebsocketFrame = (data) => {
const firstByte = data.getUint8(0);
const secondByte = data.getUint8(1);
@ -42,18 +68,20 @@ const parseWebsocketFrame = (data) => {
// Handle Payload len cases and set the masking key offset
if (frame.PayloadLen === 126) {
frame.PayloadLen = data.getUint16(2);
frame.PayloadLenEx = data.getUint16(2);
maskingKeyOffset = 4; // 4 byte offset, because we also read 2 bytes with getUint16 above (2 bytes (normal size) + 2 bytes)
} else if (frame.PayloadLen === 127) {
frame.PayloadLen = data.getBigUint64(2);
frame.PayloadLenEx = data.getBigUint64(2);
maskingKeyOffset = 10; // 10 byte offset, because we also read 8 bytes with getBigUint64 above (2 bytes (normal size) + 8 bytes)
} else {
frame.PayloadLenEx = frame.PayloadLen;
}
const maskingKeyEnd = maskingKeyOffset + 4; // (4 bytes because it is a 32 bit value)
if (frame.MASK) frame.MaskingKey = data.buffer.slice(maskingKeyOffset, maskingKeyEnd); // Create a new buffer starting at the masking key offset and ending at the masking key end (duh).
// TODO: Separate extension data from application data
frame.PayloadData = data.buffer.slice(maskingKeyEnd, maskingKeyEnd + frame.PayloadLen); // Create a new buffer that starts at the end of the masking key and ends at (the end of the masking key + payload length)
frame.PayloadData = data.buffer.slice(maskingKeyEnd, maskingKeyEnd + frame.PayloadLenEx); // Create a new buffer that starts at the end of the masking key and ends at (the end of the masking key + payload length)
// TODO: implement unmasked string decoding
if (frame.MASK) {

View file

@ -16,6 +16,27 @@ class Socket {
}
}
Socket.prototype.sendText = function(text) {
const frame = new parser.WebsocketFrame();
frame.FIN = 1;
frame.RSVx = 0;
frame.Opcode = 0x01;
frame.MASK = 0;
const length = text.length;
if (length > 125) {
frame.PayloadLen = 126;
} else if (length >= 65536) {
frame.PayloadLen = 127;
} else if (length <= 125) {
frame.PayloadLen = length;
}
frame.PayloadLenEx = length;
frame.PayloadData = Buffer.from(text);
this._socket.write(frame.toBuffer());
};
Socket.prototype._decodePayload = function(payload) {
console.log(parser.parseWebsocketFrame(new DataView(payload)));
};