Skip to content

Commit

Permalink
Rewrite class Frame
Browse files Browse the repository at this point in the history
  • Loading branch information
MarhiievHE committed Nov 8, 2023
1 parent ede8de9 commit 7df26af
Showing 1 changed file with 88 additions and 2 deletions.
90 changes: 88 additions & 2 deletions lib/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,91 @@ const DEFAULT_OPTIONS = {
const xor = (cond1, cond2) => (cond1 || cond2) && !(cond1 && cond2);

class Frame {
#frame = null;
#masked = null;
#dataOffset = null;
#mask = null;
#length = null;

constructor(frame) {
this.#frame = frame;
const length = BigInt(this.#frame[1] & 0x7f);
this.#masked = true;
switch (length) {
case 127n:
this.#dataOffset = 2 + 8 + MASK_LENGTH;
this.#mask = frame.subarray(2 + 8, 10 + MASK_LENGTH);
this.#length = frame.readBigUInt64BE(2);
break;
case 126n:
this.#dataOffset = 2 + 2 + MASK_LENGTH;
this.#mask = frame.subarray(2 + 2, 4 + MASK_LENGTH);
this.#length = BigInt(this.#frame.readUInt16BE(2));
break;
default:
this.#dataOffset = 2 + MASK_LENGTH;
this.#mask = frame.subarray(2, 2 + MASK_LENGTH);
this.#length = length;
}
}

unmask() {
if (!this.#masked) return;
for (let i = 0n; i < this.#length; ++i) {
this.#frame[BigInt(this.#dataOffset) + i] ^=
this.#mask[i & 0x0000000000000003n];
}
}

toString() {
return this.#frame.toString(
'utf8',
this.#dataOffset,
Number(BigInt(this.#dataOffset) + this.#length),
);
}

get frame() {
return this.#frame;
}

static from(data) {
if (Buffer.isBuffer(data)) {
if (data.length === 0) throw new Error('Empty frame!');
// let invalidStructureCheck = false;
if ((data[1] & 0x80) !== 0x80) throw new Error('1002: protocol error');
return new Frame(data);
}

if (typeof data === 'string') {
if (data.length === 0) throw new Error('Empty string!');
const payload = Buffer.from(data);
const length = payload.length;
let meta = Buffer.alloc(2);
meta[0] = 0x81; // FIN = 1, RSV = 0b000, opcode = 0b0001 (text frame)
if (length < LEN_16_BIT) {
meta[1] = length;
} else if (length < MAX_16_BIT) {
const len = Buffer.alloc(2);
len.writeUint16BE(length, 0);
meta[1] = LEN_16_BIT;
meta = Buffer.concat([meta, len]);
} else if (length < MAX_64_BIT) {
const len = Buffer.alloc(8);
len.writeBigUInt64BE(BigInt(length), 0);
meta[1] = LEN_64_BIT;
this.meta = Buffer.concat([meta, len]);
} else {
throw new Error('string is too long to encode in one frame!');
}
const frame = Buffer.concat([meta, payload]);
return new Frame(Buffer.from(frame));
}

throw new Error('Unsupported');
}
}
class FrameO {
#frame = null;
#mask = null;
#dataOffset = 6;
Expand Down Expand Up @@ -147,14 +232,15 @@ class Connection {
}

send(text) {
const frame = new Frame(text);
const frame = Frame.from(text);
this.socket.write(frame.frame);
}

receive(data) {
console.log('data: ', data[0], data.length);
if (data[0] !== OPCODE_SHORT) return;
const frame = new Frame(data);
const frame = Frame.from(data);
frame.unmask();
const text = frame.toString();
console.log('Message:', text);
this.send(`Echo "${text}"`);
Expand Down

0 comments on commit 7df26af

Please sign in to comment.