* Runs whenever a new chunk is received. * Callback is called whenever there are no more chunks buffering, * or not enough bytes are buffered to parse.
(callback)
| 94 | * or not enough bytes are buffered to parse. |
| 95 | */ |
| 96 | run (callback) { |
| 97 | while (this.#loop) { |
| 98 | if (this.#state === parserStates.INFO) { |
| 99 | // If there aren't enough bytes to parse the payload length, etc. |
| 100 | if (this.#byteOffset < 2) { |
| 101 | return callback() |
| 102 | } |
| 103 | |
| 104 | const buffer = this.consume(2) |
| 105 | const fin = (buffer[0] & 0x80) !== 0 |
| 106 | const opcode = buffer[0] & 0x0F |
| 107 | const masked = (buffer[1] & 0x80) === 0x80 |
| 108 | |
| 109 | const fragmented = !fin && opcode !== opcodes.CONTINUATION |
| 110 | const payloadLength = buffer[1] & 0x7F |
| 111 | |
| 112 | const rsv1 = buffer[0] & 0x40 |
| 113 | const rsv2 = buffer[0] & 0x20 |
| 114 | const rsv3 = buffer[0] & 0x10 |
| 115 | |
| 116 | if (!isValidOpcode(opcode)) { |
| 117 | failWebsocketConnection(this.#handler, 1002, 'Invalid opcode received') |
| 118 | return callback() |
| 119 | } |
| 120 | |
| 121 | if (masked) { |
| 122 | failWebsocketConnection(this.#handler, 1002, 'Frame cannot be masked') |
| 123 | return callback() |
| 124 | } |
| 125 | |
| 126 | // MUST be 0 unless an extension is negotiated that defines meanings |
| 127 | // for non-zero values. If a nonzero value is received and none of |
| 128 | // the negotiated extensions defines the meaning of such a nonzero |
| 129 | // value, the receiving endpoint MUST _Fail the WebSocket |
| 130 | // Connection_. |
| 131 | // This document allocates the RSV1 bit of the WebSocket header for |
| 132 | // PMCEs and calls the bit the "Per-Message Compressed" bit. On a |
| 133 | // WebSocket connection where a PMCE is in use, this bit indicates |
| 134 | // whether a message is compressed or not. |
| 135 | if (rsv1 !== 0 && !this.#extensions.has('permessage-deflate')) { |
| 136 | failWebsocketConnection(this.#handler, 1002, 'Expected RSV1 to be clear.') |
| 137 | return |
| 138 | } |
| 139 | |
| 140 | if (rsv2 !== 0 || rsv3 !== 0) { |
| 141 | failWebsocketConnection(this.#handler, 1002, 'RSV1, RSV2, RSV3 must be clear') |
| 142 | return |
| 143 | } |
| 144 | |
| 145 | if (fragmented && !isTextBinaryFrame(opcode)) { |
| 146 | // Only text and binary frames can be fragmented |
| 147 | failWebsocketConnection(this.#handler, 1002, 'Invalid frame type was fragmented.') |
| 148 | return |
| 149 | } |
| 150 | |
| 151 | // If we are already parsing a text/binary frame and do not receive either |
| 152 | // a continuation frame or close frame, fail the connection. |
| 153 | if (isTextBinaryFrame(opcode) && this.#fragments.length > 0) { |
no test coverage detected