Update receiver.js

This commit is contained in:
ZyLacx 2021-12-27 17:15:58 +01:00
parent e73aa40151
commit f5c71c06a9

152
node_modules/ws/lib/receiver.js generated vendored
View file

@ -22,17 +22,17 @@ const INFLATING = 5;
/** /**
* HyBi Receiver implementation. * HyBi Receiver implementation.
* *
* @extends stream.Writable * @extends Writable
*/ */
class Receiver extends Writable { class Receiver extends Writable {
/** /**
* Creates a Receiver instance. * Creates a Receiver instance.
* *
* @param {String} binaryType The type for binary data * @param {String} [binaryType=nodebuffer] The type for binary data
* @param {Object} extensions An object containing the negotiated extensions * @param {Object} [extensions] An object containing the negotiated extensions
* @param {Boolean} isServer Specifies whether to operate in client or server * @param {Boolean} [isServer=false] Specifies whether to operate in client or
* mode * server mode
* @param {Number} maxPayload The maximum allowed message length * @param {Number} [maxPayload=0] The maximum allowed message length
*/ */
constructor(binaryType, extensions, isServer, maxPayload) { constructor(binaryType, extensions, isServer, maxPayload) {
super(); super();
@ -168,14 +168,26 @@ class Receiver extends Writable {
if ((buf[0] & 0x30) !== 0x00) { if ((buf[0] & 0x30) !== 0x00) {
this._loop = false; this._loop = false;
return error(RangeError, 'RSV2 and RSV3 must be clear', true, 1002); return error(
RangeError,
'RSV2 and RSV3 must be clear',
true,
1002,
'WS_ERR_UNEXPECTED_RSV_2_3'
);
} }
const compressed = (buf[0] & 0x40) === 0x40; const compressed = (buf[0] & 0x40) === 0x40;
if (compressed && !this._extensions[PerMessageDeflate.extensionName]) { if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
this._loop = false; this._loop = false;
return error(RangeError, 'RSV1 must be clear', true, 1002); return error(
RangeError,
'RSV1 must be clear',
true,
1002,
'WS_ERR_UNEXPECTED_RSV_1'
);
} }
this._fin = (buf[0] & 0x80) === 0x80; this._fin = (buf[0] & 0x80) === 0x80;
@ -185,31 +197,61 @@ class Receiver extends Writable {
if (this._opcode === 0x00) { if (this._opcode === 0x00) {
if (compressed) { if (compressed) {
this._loop = false; this._loop = false;
return error(RangeError, 'RSV1 must be clear', true, 1002); return error(
RangeError,
'RSV1 must be clear',
true,
1002,
'WS_ERR_UNEXPECTED_RSV_1'
);
} }
if (!this._fragmented) { if (!this._fragmented) {
this._loop = false; this._loop = false;
return error(RangeError, 'invalid opcode 0', true, 1002); return error(
RangeError,
'invalid opcode 0',
true,
1002,
'WS_ERR_INVALID_OPCODE'
);
} }
this._opcode = this._fragmented; this._opcode = this._fragmented;
} else if (this._opcode === 0x01 || this._opcode === 0x02) { } else if (this._opcode === 0x01 || this._opcode === 0x02) {
if (this._fragmented) { if (this._fragmented) {
this._loop = false; this._loop = false;
return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002); return error(
RangeError,
`invalid opcode ${this._opcode}`,
true,
1002,
'WS_ERR_INVALID_OPCODE'
);
} }
this._compressed = compressed; this._compressed = compressed;
} else if (this._opcode > 0x07 && this._opcode < 0x0b) { } else if (this._opcode > 0x07 && this._opcode < 0x0b) {
if (!this._fin) { if (!this._fin) {
this._loop = false; this._loop = false;
return error(RangeError, 'FIN must be set', true, 1002); return error(
RangeError,
'FIN must be set',
true,
1002,
'WS_ERR_EXPECTED_FIN'
);
} }
if (compressed) { if (compressed) {
this._loop = false; this._loop = false;
return error(RangeError, 'RSV1 must be clear', true, 1002); return error(
RangeError,
'RSV1 must be clear',
true,
1002,
'WS_ERR_UNEXPECTED_RSV_1'
);
} }
if (this._payloadLength > 0x7d) { if (this._payloadLength > 0x7d) {
@ -218,12 +260,19 @@ class Receiver extends Writable {
RangeError, RangeError,
`invalid payload length ${this._payloadLength}`, `invalid payload length ${this._payloadLength}`,
true, true,
1002 1002,
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
); );
} }
} else { } else {
this._loop = false; this._loop = false;
return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002); return error(
RangeError,
`invalid opcode ${this._opcode}`,
true,
1002,
'WS_ERR_INVALID_OPCODE'
);
} }
if (!this._fin && !this._fragmented) this._fragmented = this._opcode; if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
@ -232,11 +281,23 @@ class Receiver extends Writable {
if (this._isServer) { if (this._isServer) {
if (!this._masked) { if (!this._masked) {
this._loop = false; this._loop = false;
return error(RangeError, 'MASK must be set', true, 1002); return error(
RangeError,
'MASK must be set',
true,
1002,
'WS_ERR_EXPECTED_MASK'
);
} }
} else if (this._masked) { } else if (this._masked) {
this._loop = false; this._loop = false;
return error(RangeError, 'MASK must be clear', true, 1002); return error(
RangeError,
'MASK must be clear',
true,
1002,
'WS_ERR_UNEXPECTED_MASK'
);
} }
if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16; if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
@ -285,7 +346,8 @@ class Receiver extends Writable {
RangeError, RangeError,
'Unsupported WebSocket frame: payload length > 2^53 - 1', 'Unsupported WebSocket frame: payload length > 2^53 - 1',
false, false,
1009 1009,
'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'
); );
} }
@ -304,7 +366,13 @@ class Receiver extends Writable {
this._totalPayloadLength += this._payloadLength; this._totalPayloadLength += this._payloadLength;
if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) { if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
this._loop = false; this._loop = false;
return error(RangeError, 'Max payload size exceeded', false, 1009); return error(
RangeError,
'Max payload size exceeded',
false,
1009,
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
);
} }
} }
@ -384,7 +452,13 @@ class Receiver extends Writable {
this._messageLength += buf.length; this._messageLength += buf.length;
if (this._messageLength > this._maxPayload && this._maxPayload > 0) { if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
return cb( return cb(
error(RangeError, 'Max payload size exceeded', false, 1009) error(
RangeError,
'Max payload size exceeded',
false,
1009,
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
)
); );
} }
@ -431,7 +505,13 @@ class Receiver extends Writable {
if (!isValidUTF8(buf)) { if (!isValidUTF8(buf)) {
this._loop = false; this._loop = false;
return error(Error, 'invalid UTF-8 sequence', true, 1007); return error(
Error,
'invalid UTF-8 sequence',
true,
1007,
'WS_ERR_INVALID_UTF8'
);
} }
this.emit('message', buf.toString()); this.emit('message', buf.toString());
@ -456,18 +536,36 @@ class Receiver extends Writable {
this.emit('conclude', 1005, ''); this.emit('conclude', 1005, '');
this.end(); this.end();
} else if (data.length === 1) { } else if (data.length === 1) {
return error(RangeError, 'invalid payload length 1', true, 1002); return error(
RangeError,
'invalid payload length 1',
true,
1002,
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
);
} else { } else {
const code = data.readUInt16BE(0); const code = data.readUInt16BE(0);
if (!isValidStatusCode(code)) { if (!isValidStatusCode(code)) {
return error(RangeError, `invalid status code ${code}`, true, 1002); return error(
RangeError,
`invalid status code ${code}`,
true,
1002,
'WS_ERR_INVALID_CLOSE_CODE'
);
} }
const buf = data.slice(2); const buf = data.slice(2);
if (!isValidUTF8(buf)) { if (!isValidUTF8(buf)) {
return error(Error, 'invalid UTF-8 sequence', true, 1007); return error(
Error,
'invalid UTF-8 sequence',
true,
1007,
'WS_ERR_INVALID_UTF8'
);
} }
this.emit('conclude', code, buf.toString()); this.emit('conclude', code, buf.toString());
@ -488,20 +586,22 @@ module.exports = Receiver;
/** /**
* Builds an error object. * Builds an error object.
* *
* @param {(Error|RangeError)} ErrorCtor The error constructor * @param {function(new:Error|RangeError)} ErrorCtor The error constructor
* @param {String} message The error message * @param {String} message The error message
* @param {Boolean} prefix Specifies whether or not to add a default prefix to * @param {Boolean} prefix Specifies whether or not to add a default prefix to
* `message` * `message`
* @param {Number} statusCode The status code * @param {Number} statusCode The status code
* @param {String} errorCode The exposed error code
* @return {(Error|RangeError)} The error * @return {(Error|RangeError)} The error
* @private * @private
*/ */
function error(ErrorCtor, message, prefix, statusCode) { function error(ErrorCtor, message, prefix, statusCode, errorCode) {
const err = new ErrorCtor( const err = new ErrorCtor(
prefix ? `Invalid WebSocket frame: ${message}` : message prefix ? `Invalid WebSocket frame: ${message}` : message
); );
Error.captureStackTrace(err, error); Error.captureStackTrace(err, error);
err.code = errorCode;
err[kStatusCode] = statusCode; err[kStatusCode] = statusCode;
return err; return err;
} }