Commit 0177561b authored by Medicean's avatar Medicean Committed by Medicean

Upgrade(ThirdParty): upgrade ws to 6.2.2

parent 7bb309f8
{ {
"name": "async-limiter", "_args": [
"version": "1.0.1", [
"async-limiter@~1.0.0",
"/Users/m/workspace/antSword/node_modules/ws"
]
],
"_from": "async-limiter@>=1.0.0 <1.1.0",
"_hasShrinkwrap": false,
"_id": "async-limiter@1.0.1",
"_inCache": true,
"_installable": true,
"_location": "/async-limiter",
"_nodeVersion": "10.16.0",
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/async-limiter_1.0.1_1564760633070_0.6974331182093105"
},
"_npmUser": {
"email": "samuel.trace.reed@gmail.com",
"name": "strml"
},
"_npmVersion": "6.9.0",
"_phantomChildren": {},
"_requested": {
"name": "async-limiter",
"raw": "async-limiter@~1.0.0",
"rawSpec": "~1.0.0",
"scope": null,
"spec": ">=1.0.0 <1.1.0",
"type": "range"
},
"_requiredBy": [
"/ws"
],
"_resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"_shasum": "dd379e94f0db8310b08291f9d64c3209766617fd",
"_shrinkwrap": null,
"_spec": "async-limiter@~1.0.0",
"_where": "/Users/m/workspace/antSword/node_modules/ws",
"author": {
"name": "Samuel Reed"
},
"bugs": {
"url": "https://github.com/strml/async-limiter/issues"
},
"dependencies": {},
"description": "asynchronous function queue with adjustable concurrency", "description": "asynchronous function queue with adjustable concurrency",
"devDependencies": {
"coveralls": "^3.0.3",
"eslint": "^5.16.0",
"eslint-plugin-mocha": "^5.3.0",
"intelli-espower-loader": "^1.0.1",
"mocha": "^6.1.4",
"nyc": "^14.1.1",
"power-assert": "^1.6.1"
},
"directories": {},
"dist": {
"fileCount": 7,
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdRFo5CRA9TVsSAnZWagAAE8EP/AoamQTvsA8uUcSUKc4L\nL7rKbbH4m5Cv1Z7qeBXLV3KJHI+dhn/mKU2hOpnXHgks5Az4ELlOX9O1vo9j\nLYtN8ZMGEkMIx+k7OcVexaXLcK9ALliEMNoNy4cIVc+exBS4eKFPmaEx5DmD\nNf+eCG6jkA9WY/kYSmFnus7C0B7d2PMdmtBZKdzWya9PAB5BYEoz3/GYhJZG\nEFYHmWKtMDB6LMSZ0FSXwABV6QXWn5kk3fXaPX1NtMHLw+QCT/sWt+0cOnIE\nak2s8WOry7Fsx5wXQmKbd8854LC+yVT1f7RR7eBhKAlTk74nwfNDr84UBJIr\n+0G0RdgISOzLghtRFu3SqYKynXTjdlycZG9vvcHW9oPGI2ZiC2cHuiqc4+K7\ndYX1HGQICjflTmb+RR0vGNXiy3v6YBWgpItdeziPO2K+0uN6SJr1BidQ8oKI\nd49psu/xNvMhdwOo19+/Bt7n7nT4uzej8K7uQO81BJC0ITeNfaC/z9M/4VOg\nFuixwvvzfs+/RABxzXKZqOMVlAnAb4U/PBcliklyUBeZ62PDkqnBxdrOekf5\nacstUU3K5bAaBV8taKHEa1+tqYUjVEcaolDDKgmO0dxD9FlKAMlhck9ildO7\nnjODiNgcSMUlMmHGUZCEvjSt1YptntzC0DHwxWUjszaR4p0Iz0c0AyOYGH7T\nRewy\r\n=MPQY\r\n-----END PGP SIGNATURE-----\r\n",
"shasum": "dd379e94f0db8310b08291f9d64c3209766617fd",
"signatures": [
{
"keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
"sig": "MEUCIQCYVwf0HXqe0bWbc7zYVM/9lbWUqBw9ET6oj9oL/MIGvQIgagFO41z8Ssm5K6bLiDP0KO4AMvSxGKLjZzN2hdLQgpM="
}
],
"tarball": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"unpackedSize": 6900
},
"gitHead": "f3bb66f26e69a5747a6483e32c775a02632020ee",
"homepage": "https://github.com/strml/async-limiter#readme",
"keywords": [ "keywords": [
"throttle", "throttle",
"async", "async",
...@@ -12,24 +82,26 @@ ...@@ -12,24 +82,26 @@
"concurrency", "concurrency",
"concurrent" "concurrent"
], ],
"dependencies": {}, "license": "MIT",
"devDependencies": { "maintainers": [
"coveralls": "^3.0.3", {
"eslint": "^5.16.0", "email": "samuel.trace.reed@gmail.com",
"eslint-plugin-mocha": "^5.3.0", "name": "strml"
"intelli-espower-loader": "^1.0.1", }
"mocha": "^6.1.4", ],
"nyc": "^14.1.1", "name": "async-limiter",
"power-assert": "^1.6.1" "optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/strml/async-limiter.git"
}, },
"scripts": { "scripts": {
"test": "mocha --require intelli-espower-loader test/",
"travis": "npm run lint && npm run test",
"coverage": "nyc npm test && nyc report --reporter=text-lcov | coveralls", "coverage": "nyc npm test && nyc report --reporter=text-lcov | coveralls",
"example": "node example", "example": "node example",
"lint": "eslint ." "lint": "eslint .",
"test": "mocha --require intelli-espower-loader test/",
"travis": "npm run lint && npm run test"
}, },
"repository": "https://github.com/strml/async-limiter.git", "version": "1.0.1"
"author": "Samuel Reed <samuel.trace.reed@gmail.com",
"license": "MIT"
} }
# ws: a Node.js WebSocket library # ws: a Node.js WebSocket library
[![Version npm](https://img.shields.io/npm/v/ws.svg)](https://www.npmjs.com/package/ws) [![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws)
[![Linux Build](https://img.shields.io/travis/websockets/ws/master.svg)](https://travis-ci.org/websockets/ws) [![Linux Build](https://img.shields.io/travis/websockets/ws/master.svg?logo=travis)](https://travis-ci.org/websockets/ws)
[![Windows Build](https://ci.appveyor.com/api/projects/status/github/websockets/ws?branch=master&svg=true)](https://ci.appveyor.com/project/lpinca/ws) [![Windows Build](https://img.shields.io/appveyor/ci/lpinca/ws/master.svg?logo=appveyor)](https://ci.appveyor.com/project/lpinca/ws)
[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg)](https://coveralls.io/r/websockets/ws?branch=master) [![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg)](https://coveralls.io/github/websockets/ws)
ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and
server implementation. server implementation.
......
'use strict'; 'use strict';
const { EMPTY_BUFFER } = require('./constants');
/** /**
* Merges an array of buffers into a new buffer. * Merges an array of buffers into a new buffer.
* *
...@@ -9,6 +11,9 @@ ...@@ -9,6 +11,9 @@
* @public * @public
*/ */
function concat(list, totalLength) { function concat(list, totalLength) {
if (list.length === 0) return EMPTY_BUFFER;
if (list.length === 1) return list[0];
const target = Buffer.allocUnsafe(totalLength); const target = Buffer.allocUnsafe(totalLength);
var offset = 0; var offset = 0;
...@@ -52,21 +57,88 @@ function _unmask(buffer, mask) { ...@@ -52,21 +57,88 @@ function _unmask(buffer, mask) {
} }
} }
/**
* Converts a buffer to an `ArrayBuffer`.
*
* @param {Buffer} buf The buffer to convert
* @return {ArrayBuffer} Converted buffer
* @public
*/
function toArrayBuffer(buf) {
if (buf.byteLength === buf.buffer.byteLength) {
return buf.buffer;
}
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
}
/**
* Converts `data` to a `Buffer`.
*
* @param {*} data The data to convert
* @return {Buffer} The buffer
* @throws {TypeError}
* @public
*/
function toBuffer(data) {
toBuffer.readOnly = true;
if (Buffer.isBuffer(data)) return data;
var buf;
if (data instanceof ArrayBuffer) {
buf = Buffer.from(data);
} else if (ArrayBuffer.isView(data)) {
buf = viewToBuffer(data);
} else {
buf = Buffer.from(data);
toBuffer.readOnly = false;
}
return buf;
}
/**
* Converts an `ArrayBuffer` view into a buffer.
*
* @param {(DataView|TypedArray)} view The view to convert
* @return {Buffer} Converted view
* @private
*/
function viewToBuffer(view) {
const buf = Buffer.from(view.buffer);
if (view.byteLength !== view.buffer.byteLength) {
return buf.slice(view.byteOffset, view.byteOffset + view.byteLength);
}
return buf;
}
try { try {
const bufferUtil = require('bufferutil'); const bufferUtil = require('bufferutil');
const bu = bufferUtil.BufferUtil || bufferUtil; const bu = bufferUtil.BufferUtil || bufferUtil;
module.exports = { module.exports = {
concat,
mask(source, mask, output, offset, length) { mask(source, mask, output, offset, length) {
if (length < 48) _mask(source, mask, output, offset, length); if (length < 48) _mask(source, mask, output, offset, length);
else bu.mask(source, mask, output, offset, length); else bu.mask(source, mask, output, offset, length);
}, },
toArrayBuffer,
toBuffer,
unmask(buffer, mask) { unmask(buffer, mask) {
if (buffer.length < 32) _unmask(buffer, mask); if (buffer.length < 32) _unmask(buffer, mask);
else bu.unmask(buffer, mask); else bu.unmask(buffer, mask);
}, }
concat
}; };
} catch (e) /* istanbul ignore next */ { } catch (e) /* istanbul ignore next */ {
module.exports = { concat, mask: _mask, unmask: _unmask }; module.exports = {
concat,
mask: _mask,
toArrayBuffer,
toBuffer,
unmask: _unmask
};
} }
'use strict'; 'use strict';
const stream = require('stream'); const { Writable } = require('stream');
const PerMessageDeflate = require('./permessage-deflate'); const PerMessageDeflate = require('./permessage-deflate');
const bufferUtil = require('./buffer-util'); const {
const validation = require('./validation'); BINARY_TYPES,
const constants = require('./constants'); EMPTY_BUFFER,
kStatusCode,
kWebSocket
} = require('./constants');
const { concat, toArrayBuffer, unmask } = require('./buffer-util');
const { isValidStatusCode, isValidUTF8 } = require('./validation');
const GET_INFO = 0; const GET_INFO = 0;
const GET_PAYLOAD_LENGTH_16 = 1; const GET_PAYLOAD_LENGTH_16 = 1;
...@@ -19,7 +24,7 @@ const INFLATING = 5; ...@@ -19,7 +24,7 @@ const INFLATING = 5;
* *
* @extends stream.Writable * @extends stream.Writable
*/ */
class Receiver extends stream.Writable { class Receiver extends Writable {
/** /**
* Creates a Receiver instance. * Creates a Receiver instance.
* *
...@@ -30,8 +35,8 @@ class Receiver extends stream.Writable { ...@@ -30,8 +35,8 @@ class Receiver extends stream.Writable {
constructor(binaryType, extensions, maxPayload) { constructor(binaryType, extensions, maxPayload) {
super(); super();
this._binaryType = binaryType || constants.BINARY_TYPES[0]; this._binaryType = binaryType || BINARY_TYPES[0];
this[constants.kWebSocket] = undefined; this[kWebSocket] = undefined;
this._extensions = extensions || {}; this._extensions = extensions || {};
this._maxPayload = maxPayload | 0; this._maxPayload = maxPayload | 0;
...@@ -315,7 +320,7 @@ class Receiver extends stream.Writable { ...@@ -315,7 +320,7 @@ class Receiver extends stream.Writable {
* @private * @private
*/ */
getData(cb) { getData(cb) {
var data = constants.EMPTY_BUFFER; var data = EMPTY_BUFFER;
if (this._payloadLength) { if (this._payloadLength) {
if (this._bufferedBytes < this._payloadLength) { if (this._bufferedBytes < this._payloadLength) {
...@@ -324,7 +329,7 @@ class Receiver extends stream.Writable { ...@@ -324,7 +329,7 @@ class Receiver extends stream.Writable {
} }
data = this.consume(this._payloadLength); data = this.consume(this._payloadLength);
if (this._masked) bufferUtil.unmask(data, this._mask); if (this._masked) unmask(data, this._mask);
} }
if (this._opcode > 0x07) return this.controlMessage(data); if (this._opcode > 0x07) return this.controlMessage(data);
...@@ -398,18 +403,18 @@ class Receiver extends stream.Writable { ...@@ -398,18 +403,18 @@ class Receiver extends stream.Writable {
var data; var data;
if (this._binaryType === 'nodebuffer') { if (this._binaryType === 'nodebuffer') {
data = toBuffer(fragments, messageLength); data = concat(fragments, messageLength);
} else if (this._binaryType === 'arraybuffer') { } else if (this._binaryType === 'arraybuffer') {
data = toArrayBuffer(toBuffer(fragments, messageLength)); data = toArrayBuffer(concat(fragments, messageLength));
} else { } else {
data = fragments; data = fragments;
} }
this.emit('message', data); this.emit('message', data);
} else { } else {
const buf = toBuffer(fragments, messageLength); const buf = concat(fragments, messageLength);
if (!validation.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);
} }
...@@ -440,13 +445,13 @@ class Receiver extends stream.Writable { ...@@ -440,13 +445,13 @@ class Receiver extends stream.Writable {
} else { } else {
const code = data.readUInt16BE(0); const code = data.readUInt16BE(0);
if (!validation.isValidStatusCode(code)) { if (!isValidStatusCode(code)) {
return error(RangeError, `invalid status code ${code}`, true, 1002); return error(RangeError, `invalid status code ${code}`, true, 1002);
} }
const buf = data.slice(2); const buf = data.slice(2);
if (!validation.isValidUTF8(buf)) { if (!isValidUTF8(buf)) {
return error(Error, 'invalid UTF-8 sequence', true, 1007); return error(Error, 'invalid UTF-8 sequence', true, 1007);
} }
...@@ -482,34 +487,6 @@ function error(ErrorCtor, message, prefix, statusCode) { ...@@ -482,34 +487,6 @@ function error(ErrorCtor, message, prefix, statusCode) {
); );
Error.captureStackTrace(err, error); Error.captureStackTrace(err, error);
err[constants.kStatusCode] = statusCode; err[kStatusCode] = statusCode;
return err; return err;
} }
/**
* Makes a buffer from a list of fragments.
*
* @param {Buffer[]} fragments The list of fragments composing the message
* @param {Number} messageLength The length of the message
* @return {Buffer}
* @private
*/
function toBuffer(fragments, messageLength) {
if (fragments.length === 1) return fragments[0];
if (fragments.length > 1) return bufferUtil.concat(fragments, messageLength);
return constants.EMPTY_BUFFER;
}
/**
* Converts a buffer to an `ArrayBuffer`.
*
* @param {Buffer} buf The buffer to convert
* @return {ArrayBuffer} Converted buffer
*/
function toArrayBuffer(buf) {
if (buf.byteLength === buf.buffer.byteLength) {
return buf.buffer;
}
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
}
'use strict'; 'use strict';
const crypto = require('crypto'); const { randomBytes } = require('crypto');
const PerMessageDeflate = require('./permessage-deflate'); const PerMessageDeflate = require('./permessage-deflate');
const bufferUtil = require('./buffer-util'); const { EMPTY_BUFFER } = require('./constants');
const validation = require('./validation'); const { isValidStatusCode } = require('./validation');
const constants = require('./constants'); const { mask: applyMask, toBuffer } = require('./buffer-util');
/** /**
* HyBi Sender implementation. * HyBi Sender implementation.
...@@ -43,7 +43,7 @@ class Sender { ...@@ -43,7 +43,7 @@ class Sender {
* @public * @public
*/ */
static frame(data, options) { static frame(data, options) {
const merge = data.length < 1024 || (options.mask && options.readOnly); const merge = options.mask && options.readOnly;
var offset = options.mask ? 6 : 2; var offset = options.mask ? 6 : 2;
var payloadLength = data.length; var payloadLength = data.length;
...@@ -60,6 +60,8 @@ class Sender { ...@@ -60,6 +60,8 @@ class Sender {
target[0] = options.fin ? options.opcode | 0x80 : options.opcode; target[0] = options.fin ? options.opcode | 0x80 : options.opcode;
if (options.rsv1) target[0] |= 0x40; if (options.rsv1) target[0] |= 0x40;
target[1] = payloadLength;
if (payloadLength === 126) { if (payloadLength === 126) {
target.writeUInt16BE(data.length, 2); target.writeUInt16BE(data.length, 2);
} else if (payloadLength === 127) { } else if (payloadLength === 127) {
...@@ -67,30 +69,22 @@ class Sender { ...@@ -67,30 +69,22 @@ class Sender {
target.writeUInt32BE(data.length, 6); target.writeUInt32BE(data.length, 6);
} }
if (!options.mask) { if (!options.mask) return [target, data];
target[1] = payloadLength;
if (merge) {
data.copy(target, offset);
return [target];
}
return [target, data];
}
const mask = crypto.randomBytes(4); const mask = randomBytes(4);
target[1] = payloadLength | 0x80; target[1] |= 0x80;
target[offset - 4] = mask[0]; target[offset - 4] = mask[0];
target[offset - 3] = mask[1]; target[offset - 3] = mask[1];
target[offset - 2] = mask[2]; target[offset - 2] = mask[2];
target[offset - 1] = mask[3]; target[offset - 1] = mask[3];
if (merge) { if (merge) {
bufferUtil.mask(data, mask, target, offset, data.length); applyMask(data, mask, target, offset, data.length);
return [target]; return [target];
} }
bufferUtil.mask(data, mask, data, 0, data.length); applyMask(data, mask, data, 0, data.length);
return [target, data]; return [target, data];
} }
...@@ -107,11 +101,8 @@ class Sender { ...@@ -107,11 +101,8 @@ class Sender {
var buf; var buf;
if (code === undefined) { if (code === undefined) {
buf = constants.EMPTY_BUFFER; buf = EMPTY_BUFFER;
} else if ( } else if (typeof code !== 'number' || !isValidStatusCode(code)) {
typeof code !== 'number' ||
!validation.isValidStatusCode(code)
) {
throw new TypeError('First argument must be a valid error code number'); throw new TypeError('First argument must be a valid error code number');
} else if (data === undefined || data === '') { } else if (data === undefined || data === '') {
buf = Buffer.allocUnsafe(2); buf = Buffer.allocUnsafe(2);
...@@ -159,23 +150,12 @@ class Sender { ...@@ -159,23 +150,12 @@ class Sender {
* @public * @public
*/ */
ping(data, mask, cb) { ping(data, mask, cb) {
var readOnly = true; const buf = toBuffer(data);
if (!Buffer.isBuffer(data)) {
if (data instanceof ArrayBuffer) {
data = Buffer.from(data);
} else if (ArrayBuffer.isView(data)) {
data = viewToBuffer(data);
} else {
data = Buffer.from(data);
readOnly = false;
}
}
if (this._deflating) { if (this._deflating) {
this.enqueue([this.doPing, data, mask, readOnly, cb]); this.enqueue([this.doPing, buf, mask, toBuffer.readOnly, cb]);
} else { } else {
this.doPing(data, mask, readOnly, cb); this.doPing(buf, mask, toBuffer.readOnly, cb);
} }
} }
...@@ -210,23 +190,12 @@ class Sender { ...@@ -210,23 +190,12 @@ class Sender {
* @public * @public
*/ */
pong(data, mask, cb) { pong(data, mask, cb) {
var readOnly = true; const buf = toBuffer(data);
if (!Buffer.isBuffer(data)) {
if (data instanceof ArrayBuffer) {
data = Buffer.from(data);
} else if (ArrayBuffer.isView(data)) {
data = viewToBuffer(data);
} else {
data = Buffer.from(data);
readOnly = false;
}
}
if (this._deflating) { if (this._deflating) {
this.enqueue([this.doPong, data, mask, readOnly, cb]); this.enqueue([this.doPong, buf, mask, toBuffer.readOnly, cb]);
} else { } else {
this.doPong(data, mask, readOnly, cb); this.doPong(buf, mask, toBuffer.readOnly, cb);
} }
} }
...@@ -265,27 +234,15 @@ class Sender { ...@@ -265,27 +234,15 @@ class Sender {
* @public * @public
*/ */
send(data, options, cb) { send(data, options, cb) {
const buf = toBuffer(data);
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
var opcode = options.binary ? 2 : 1; var opcode = options.binary ? 2 : 1;
var rsv1 = options.compress; var rsv1 = options.compress;
var readOnly = true;
if (!Buffer.isBuffer(data)) {
if (data instanceof ArrayBuffer) {
data = Buffer.from(data);
} else if (ArrayBuffer.isView(data)) {
data = viewToBuffer(data);
} else {
data = Buffer.from(data);
readOnly = false;
}
}
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
if (this._firstFragment) { if (this._firstFragment) {
this._firstFragment = false; this._firstFragment = false;
if (rsv1 && perMessageDeflate) { if (rsv1 && perMessageDeflate) {
rsv1 = data.length >= perMessageDeflate._threshold; rsv1 = buf.length >= perMessageDeflate._threshold;
} }
this._compress = rsv1; this._compress = rsv1;
} else { } else {
...@@ -301,22 +258,22 @@ class Sender { ...@@ -301,22 +258,22 @@ class Sender {
rsv1, rsv1,
opcode, opcode,
mask: options.mask, mask: options.mask,
readOnly readOnly: toBuffer.readOnly
}; };
if (this._deflating) { if (this._deflating) {
this.enqueue([this.dispatch, data, this._compress, opts, cb]); this.enqueue([this.dispatch, buf, this._compress, opts, cb]);
} else { } else {
this.dispatch(data, this._compress, opts, cb); this.dispatch(buf, this._compress, opts, cb);
} }
} else { } else {
this.sendFrame( this.sendFrame(
Sender.frame(data, { Sender.frame(buf, {
fin: options.fin, fin: options.fin,
rsv1: false, rsv1: false,
opcode, opcode,
mask: options.mask, mask: options.mask,
readOnly readOnly: toBuffer.readOnly
}), }),
cb cb
); );
...@@ -388,8 +345,10 @@ class Sender { ...@@ -388,8 +345,10 @@ class Sender {
*/ */
sendFrame(list, cb) { sendFrame(list, cb) {
if (list.length === 2) { if (list.length === 2) {
this._socket.cork();
this._socket.write(list[0]); this._socket.write(list[0]);
this._socket.write(list[1], cb); this._socket.write(list[1], cb);
this._socket.uncork();
} else { } else {
this._socket.write(list[0], cb); this._socket.write(list[0], cb);
} }
...@@ -397,20 +356,3 @@ class Sender { ...@@ -397,20 +356,3 @@ class Sender {
} }
module.exports = Sender; module.exports = Sender;
/**
* Converts an `ArrayBuffer` view into a buffer.
*
* @param {(DataView|TypedArray)} view The view to convert
* @return {Buffer} Converted view
* @private
*/
function viewToBuffer(view) {
const buf = Buffer.from(view.buffer);
if (view.byteLength !== view.buffer.byteLength) {
return buf.slice(view.byteOffset, view.byteOffset + view.byteLength);
}
return buf;
}
...@@ -6,8 +6,10 @@ const http = require('http'); ...@@ -6,8 +6,10 @@ const http = require('http');
const PerMessageDeflate = require('./permessage-deflate'); const PerMessageDeflate = require('./permessage-deflate');
const extension = require('./extension'); const extension = require('./extension');
const constants = require('./constants');
const WebSocket = require('./websocket'); const WebSocket = require('./websocket');
const { GUID } = require('./constants');
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
/** /**
* Class representing a WebSocket server. * Class representing a WebSocket server.
...@@ -19,16 +21,20 @@ class WebSocketServer extends EventEmitter { ...@@ -19,16 +21,20 @@ class WebSocketServer extends EventEmitter {
* Create a `WebSocketServer` instance. * Create a `WebSocketServer` instance.
* *
* @param {Object} options Configuration options * @param {Object} options Configuration options
* @param {Number} options.backlog The maximum length of the queue of pending
* connections
* @param {Boolean} options.clientTracking Specifies whether or not to track
* clients
* @param {Function} options.handleProtocols An hook to handle protocols
* @param {String} options.host The hostname where to bind the server * @param {String} options.host The hostname where to bind the server
* @param {Number} options.maxPayload The maximum allowed message size
* @param {Boolean} options.noServer Enable no server mode
* @param {String} options.path Accept only connections matching this path
* @param {(Boolean|Object)} options.perMessageDeflate Enable/disable
* permessage-deflate
* @param {Number} options.port The port where to bind the server * @param {Number} options.port The port where to bind the server
* @param {http.Server} options.server A pre-created HTTP/S server to use * @param {http.Server} options.server A pre-created HTTP/S server to use
* @param {Function} options.verifyClient An hook to reject connections * @param {Function} options.verifyClient An hook to reject connections
* @param {Function} options.handleProtocols An hook to handle protocols
* @param {String} options.path Accept only connections matching this path
* @param {Boolean} options.noServer Enable no server mode
* @param {Boolean} options.clientTracking Specifies whether or not to track clients
* @param {(Boolean|Object)} options.perMessageDeflate Enable/disable permessage-deflate
* @param {Number} options.maxPayload The maximum allowed message size
* @param {Function} callback A listener for the `listening` event * @param {Function} callback A listener for the `listening` event
*/ */
constructor(options, callback) { constructor(options, callback) {
...@@ -176,13 +182,18 @@ class WebSocketServer extends EventEmitter { ...@@ -176,13 +182,18 @@ class WebSocketServer extends EventEmitter {
handleUpgrade(req, socket, head, cb) { handleUpgrade(req, socket, head, cb) {
socket.on('error', socketOnError); socket.on('error', socketOnError);
const key =
req.headers['sec-websocket-key'] !== undefined
? req.headers['sec-websocket-key'].trim()
: false;
const version = +req.headers['sec-websocket-version']; const version = +req.headers['sec-websocket-version'];
const extensions = {}; const extensions = {};
if ( if (
req.method !== 'GET' || req.method !== 'GET' ||
req.headers.upgrade.toLowerCase() !== 'websocket' || req.headers.upgrade.toLowerCase() !== 'websocket' ||
!req.headers['sec-websocket-key'] || !key ||
!keyRegex.test(key) ||
(version !== 8 && version !== 13) || (version !== 8 && version !== 13) ||
!this.shouldHandle(req) !this.shouldHandle(req)
) { ) {
...@@ -225,7 +236,7 @@ class WebSocketServer extends EventEmitter { ...@@ -225,7 +236,7 @@ class WebSocketServer extends EventEmitter {
return abortHandshake(socket, code || 401, message, headers); return abortHandshake(socket, code || 401, message, headers);
} }
this.completeUpgrade(extensions, req, socket, head, cb); this.completeUpgrade(key, extensions, req, socket, head, cb);
}); });
return; return;
} }
...@@ -233,12 +244,13 @@ class WebSocketServer extends EventEmitter { ...@@ -233,12 +244,13 @@ class WebSocketServer extends EventEmitter {
if (!this.options.verifyClient(info)) return abortHandshake(socket, 401); if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
} }
this.completeUpgrade(extensions, req, socket, head, cb); this.completeUpgrade(key, extensions, req, socket, head, cb);
} }
/** /**
* Upgrade the connection to WebSocket. * Upgrade the connection to WebSocket.
* *
* @param {String} key The value of the `Sec-WebSocket-Key` header
* @param {Object} extensions The accepted extensions * @param {Object} extensions The accepted extensions
* @param {http.IncomingMessage} req The request object * @param {http.IncomingMessage} req The request object
* @param {net.Socket} socket The network socket between the server and client * @param {net.Socket} socket The network socket between the server and client
...@@ -246,29 +258,29 @@ class WebSocketServer extends EventEmitter { ...@@ -246,29 +258,29 @@ class WebSocketServer extends EventEmitter {
* @param {Function} cb Callback * @param {Function} cb Callback
* @private * @private
*/ */
completeUpgrade(extensions, req, socket, head, cb) { completeUpgrade(key, extensions, req, socket, head, cb) {
// //
// Destroy the socket if the client has already sent a FIN packet. // Destroy the socket if the client has already sent a FIN packet.
// //
if (!socket.readable || !socket.writable) return socket.destroy(); if (!socket.readable || !socket.writable) return socket.destroy();
const key = crypto const digest = crypto
.createHash('sha1') .createHash('sha1')
.update(req.headers['sec-websocket-key'] + constants.GUID, 'binary') .update(key + GUID)
.digest('base64'); .digest('base64');
const headers = [ const headers = [
'HTTP/1.1 101 Switching Protocols', 'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket', 'Upgrade: websocket',
'Connection: Upgrade', 'Connection: Upgrade',
`Sec-WebSocket-Accept: ${key}` `Sec-WebSocket-Accept: ${digest}`
]; ];
const ws = new WebSocket(null); const ws = new WebSocket(null);
var protocol = req.headers['sec-websocket-protocol']; var protocol = req.headers['sec-websocket-protocol'];
if (protocol) { if (protocol) {
protocol = protocol.trim().split(/ *, */); protocol = protocol.split(',').map(trim);
// //
// Optionally call external protocol selection handler. // Optionally call external protocol selection handler.
...@@ -387,3 +399,15 @@ function abortHandshake(socket, code, message, headers) { ...@@ -387,3 +399,15 @@ function abortHandshake(socket, code, message, headers) {
socket.removeListener('error', socketOnError); socket.removeListener('error', socketOnError);
socket.destroy(); socket.destroy();
} }
/**
* Remove whitespace characters from both ends of a string.
*
* @param {String} str The string
* @return {String} A new string representing `str` stripped of whitespace
* characters from both its beginning and end
* @private
*/
function trim(str) {
return str.trim();
}
...@@ -11,14 +11,20 @@ const url = require('url'); ...@@ -11,14 +11,20 @@ const url = require('url');
const PerMessageDeflate = require('./permessage-deflate'); const PerMessageDeflate = require('./permessage-deflate');
const EventTarget = require('./event-target'); const EventTarget = require('./event-target');
const extension = require('./extension'); const extension = require('./extension');
const constants = require('./constants');
const Receiver = require('./receiver'); const Receiver = require('./receiver');
const Sender = require('./sender'); const Sender = require('./sender');
const {
BINARY_TYPES,
EMPTY_BUFFER,
GUID,
kStatusCode,
kWebSocket,
NOOP
} = require('./constants');
const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']; const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
const kWebSocket = constants.kWebSocket;
const protocolVersions = [8, 13]; const protocolVersions = [8, 13];
const closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly. const closeTimeout = 30 * 1000;
/** /**
* Class representing a WebSocket. * Class representing a WebSocket.
...@@ -39,19 +45,21 @@ class WebSocket extends EventEmitter { ...@@ -39,19 +45,21 @@ class WebSocket extends EventEmitter {
this.readyState = WebSocket.CONNECTING; this.readyState = WebSocket.CONNECTING;
this.protocol = ''; this.protocol = '';
this._binaryType = constants.BINARY_TYPES[0]; this._binaryType = BINARY_TYPES[0];
this._closeFrameReceived = false; this._closeFrameReceived = false;
this._closeFrameSent = false; this._closeFrameSent = false;
this._closeMessage = ''; this._closeMessage = '';
this._closeTimer = null; this._closeTimer = null;
this._closeCode = 1006; this._closeCode = 1006;
this._extensions = {}; this._extensions = {};
this._isServer = true;
this._receiver = null; this._receiver = null;
this._sender = null; this._sender = null;
this._socket = null; this._socket = null;
if (address !== null) { if (address !== null) {
this._isServer = false;
this._redirects = 0;
if (Array.isArray(protocols)) { if (Array.isArray(protocols)) {
protocols = protocols.join(', '); protocols = protocols.join(', ');
} else if (typeof protocols === 'object' && protocols !== null) { } else if (typeof protocols === 'object' && protocols !== null) {
...@@ -59,7 +67,9 @@ class WebSocket extends EventEmitter { ...@@ -59,7 +67,9 @@ class WebSocket extends EventEmitter {
protocols = undefined; protocols = undefined;
} }
initAsClient.call(this, address, protocols, options); initAsClient(this, address, protocols, options);
} else {
this._isServer = true;
} }
} }
...@@ -77,8 +87,9 @@ class WebSocket extends EventEmitter { ...@@ -77,8 +87,9 @@ class WebSocket extends EventEmitter {
} }
/** /**
* This deviates from the WHATWG interface since ws doesn't support the required * This deviates from the WHATWG interface since ws doesn't support the
* default "blob" type (instead we define a custom "nodebuffer" type). * required default "blob" type (instead we define a custom "nodebuffer"
* type).
* *
* @type {String} * @type {String}
*/ */
...@@ -87,7 +98,7 @@ class WebSocket extends EventEmitter { ...@@ -87,7 +98,7 @@ class WebSocket extends EventEmitter {
} }
set binaryType(type) { set binaryType(type) {
if (!constants.BINARY_TYPES.includes(type)) return; if (!BINARY_TYPES.includes(type)) return;
this._binaryType = type; this._binaryType = type;
...@@ -220,20 +231,16 @@ class WebSocket extends EventEmitter { ...@@ -220,20 +231,16 @@ class WebSocket extends EventEmitter {
if (err) return; if (err) return;
this._closeFrameSent = true; this._closeFrameSent = true;
if (this._closeFrameReceived) this._socket.end();
if (this._socket.writable) {
if (this._closeFrameReceived) this._socket.end();
//
// Ensure that the connection is closed even if the closing handshake
// fails.
//
this._closeTimer = setTimeout(
this._socket.destroy.bind(this._socket),
closeTimeout
);
}
}); });
//
// Specify a timeout for the closing handshake to complete.
//
this._closeTimer = setTimeout(
this._socket.destroy.bind(this._socket),
closeTimeout
);
} }
/** /**
...@@ -265,7 +272,7 @@ class WebSocket extends EventEmitter { ...@@ -265,7 +272,7 @@ class WebSocket extends EventEmitter {
if (typeof data === 'number') data = data.toString(); if (typeof data === 'number') data = data.toString();
if (mask === undefined) mask = !this._isServer; if (mask === undefined) mask = !this._isServer;
this._sender.ping(data || constants.EMPTY_BUFFER, mask, cb); this._sender.ping(data || EMPTY_BUFFER, mask, cb);
} }
/** /**
...@@ -297,7 +304,7 @@ class WebSocket extends EventEmitter { ...@@ -297,7 +304,7 @@ class WebSocket extends EventEmitter {
if (typeof data === 'number') data = data.toString(); if (typeof data === 'number') data = data.toString();
if (mask === undefined) mask = !this._isServer; if (mask === undefined) mask = !this._isServer;
this._sender.pong(data || constants.EMPTY_BUFFER, mask, cb); this._sender.pong(data || EMPTY_BUFFER, mask, cb);
} }
/** /**
...@@ -344,7 +351,7 @@ class WebSocket extends EventEmitter { ...@@ -344,7 +351,7 @@ class WebSocket extends EventEmitter {
opts.compress = false; opts.compress = false;
} }
this._sender.send(data || constants.EMPTY_BUFFER, opts, cb); this._sender.send(data || EMPTY_BUFFER, opts, cb);
} }
/** /**
...@@ -417,22 +424,31 @@ module.exports = WebSocket; ...@@ -417,22 +424,31 @@ module.exports = WebSocket;
/** /**
* Initialize a WebSocket client. * Initialize a WebSocket client.
* *
* @param {WebSocket} websocket The client to initialize
* @param {(String|url.Url|url.URL)} address The URL to which to connect * @param {(String|url.Url|url.URL)} address The URL to which to connect
* @param {String} protocols The subprotocols * @param {String} protocols The subprotocols
* @param {Object} options Connection options * @param {Object} options Connection options
* @param {(Boolean|Object)} options.perMessageDeflate Enable/disable permessage-deflate * @param {(Boolean|Object)} options.perMessageDeflate Enable/disable
* @param {Number} options.handshakeTimeout Timeout in milliseconds for the handshake request * permessage-deflate
* @param {Number} options.protocolVersion Value of the `Sec-WebSocket-Version` header * @param {Number} options.handshakeTimeout Timeout in milliseconds for the
* @param {String} options.origin Value of the `Origin` or `Sec-WebSocket-Origin` header * handshake request
* @param {Number} options.protocolVersion Value of the `Sec-WebSocket-Version`
* header
* @param {String} options.origin Value of the `Origin` or
* `Sec-WebSocket-Origin` header
* @param {Number} options.maxPayload The maximum allowed message size * @param {Number} options.maxPayload The maximum allowed message size
* @param {Boolean} options.followRedirects Whether or not to follow redirects
* @param {Number} options.maxRedirects The maximum number of redirects allowed
* @private * @private
*/ */
function initAsClient(address, protocols, options) { function initAsClient(websocket, address, protocols, options) {
options = Object.assign( const opts = Object.assign(
{ {
protocolVersion: protocolVersions[1], protocolVersion: protocolVersions[1],
maxPayload: 100 * 1024 * 1024,
perMessageDeflate: true, perMessageDeflate: true,
maxPayload: 100 * 1024 * 1024 followRedirects: false,
maxRedirects: 10
}, },
options, options,
{ {
...@@ -449,136 +465,159 @@ function initAsClient(address, protocols, options) { ...@@ -449,136 +465,159 @@ function initAsClient(address, protocols, options) {
} }
); );
if (!protocolVersions.includes(options.protocolVersion)) { if (!protocolVersions.includes(opts.protocolVersion)) {
throw new RangeError( throw new RangeError(
`Unsupported protocol version: ${options.protocolVersion} ` + `Unsupported protocol version: ${opts.protocolVersion} ` +
`(supported versions: ${protocolVersions.join(', ')})` `(supported versions: ${protocolVersions.join(', ')})`
); );
} }
this._isServer = false;
var parsedUrl; var parsedUrl;
if (typeof address === 'object' && address.href !== undefined) { if (typeof address === 'object' && address.href !== undefined) {
parsedUrl = address; parsedUrl = address;
this.url = address.href; websocket.url = address.href;
} else { } else {
// //
// The WHATWG URL constructor is not available on Node.js < 6.13.0 // The WHATWG URL constructor is not available on Node.js < 6.13.0
// //
parsedUrl = url.URL ? new url.URL(address) : url.parse(address); parsedUrl = url.URL ? new url.URL(address) : url.parse(address);
this.url = address; websocket.url = address;
} }
const isUnixSocket = parsedUrl.protocol === 'ws+unix:'; const isUnixSocket = parsedUrl.protocol === 'ws+unix:';
if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) { if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) {
throw new Error(`Invalid URL: ${this.url}`); throw new Error(`Invalid URL: ${websocket.url}`);
} }
const isSecure = const isSecure =
parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:'; parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:';
const defaultPort = isSecure ? 443 : 80; const defaultPort = isSecure ? 443 : 80;
const key = crypto.randomBytes(16).toString('base64'); const key = crypto.randomBytes(16).toString('base64');
const httpObj = isSecure ? https : http; const get = isSecure ? https.get : http.get;
const path = parsedUrl.search const path = parsedUrl.search
? `${parsedUrl.pathname || '/'}${parsedUrl.search}` ? `${parsedUrl.pathname || '/'}${parsedUrl.search}`
: parsedUrl.pathname || '/'; : parsedUrl.pathname || '/';
var perMessageDeflate; var perMessageDeflate;
options.createConnection = isSecure ? tlsConnect : netConnect; opts.createConnection = isSecure ? tlsConnect : netConnect;
options.defaultPort = options.defaultPort || defaultPort; opts.defaultPort = opts.defaultPort || defaultPort;
options.port = parsedUrl.port || defaultPort; opts.port = parsedUrl.port || defaultPort;
options.host = parsedUrl.hostname.startsWith('[') opts.host = parsedUrl.hostname.startsWith('[')
? parsedUrl.hostname.slice(1, -1) ? parsedUrl.hostname.slice(1, -1)
: parsedUrl.hostname; : parsedUrl.hostname;
options.headers = Object.assign( opts.headers = Object.assign(
{ {
'Sec-WebSocket-Version': options.protocolVersion, 'Sec-WebSocket-Version': opts.protocolVersion,
'Sec-WebSocket-Key': key, 'Sec-WebSocket-Key': key,
Connection: 'Upgrade', Connection: 'Upgrade',
Upgrade: 'websocket' Upgrade: 'websocket'
}, },
options.headers opts.headers
); );
options.path = path; opts.path = path;
options.timeout = options.handshakeTimeout; opts.timeout = opts.handshakeTimeout;
if (options.perMessageDeflate) { if (opts.perMessageDeflate) {
perMessageDeflate = new PerMessageDeflate( perMessageDeflate = new PerMessageDeflate(
options.perMessageDeflate !== true ? options.perMessageDeflate : {}, opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},
false, false,
options.maxPayload opts.maxPayload
); );
options.headers['Sec-WebSocket-Extensions'] = extension.format({ opts.headers['Sec-WebSocket-Extensions'] = extension.format({
[PerMessageDeflate.extensionName]: perMessageDeflate.offer() [PerMessageDeflate.extensionName]: perMessageDeflate.offer()
}); });
} }
if (protocols) { if (protocols) {
options.headers['Sec-WebSocket-Protocol'] = protocols; opts.headers['Sec-WebSocket-Protocol'] = protocols;
} }
if (options.origin) { if (opts.origin) {
if (options.protocolVersion < 13) { if (opts.protocolVersion < 13) {
options.headers['Sec-WebSocket-Origin'] = options.origin; opts.headers['Sec-WebSocket-Origin'] = opts.origin;
} else { } else {
options.headers.Origin = options.origin; opts.headers.Origin = opts.origin;
} }
} }
if (parsedUrl.auth) { if (parsedUrl.auth) {
options.auth = parsedUrl.auth; opts.auth = parsedUrl.auth;
} else if (parsedUrl.username || parsedUrl.password) { } else if (parsedUrl.username || parsedUrl.password) {
options.auth = `${parsedUrl.username}:${parsedUrl.password}`; opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
} }
if (isUnixSocket) { if (isUnixSocket) {
const parts = path.split(':'); const parts = path.split(':');
options.socketPath = parts[0]; opts.socketPath = parts[0];
options.path = parts[1]; opts.path = parts[1];
} }
var req = (this._req = httpObj.get(options)); var req = (websocket._req = get(opts));
if (options.handshakeTimeout) { if (opts.timeout) {
req.on('timeout', () => { req.on('timeout', () => {
abortHandshake(this, req, 'Opening handshake has timed out'); abortHandshake(websocket, req, 'Opening handshake has timed out');
}); });
} }
req.on('error', (err) => { req.on('error', (err) => {
if (this._req.aborted) return; if (websocket._req.aborted) return;
req = this._req = null; req = websocket._req = null;
this.readyState = WebSocket.CLOSING; websocket.readyState = WebSocket.CLOSING;
this.emit('error', err); websocket.emit('error', err);
this.emitClose(); websocket.emitClose();
}); });
req.on('response', (res) => { req.on('response', (res) => {
if (this.emit('unexpected-response', req, res)) return; const location = res.headers.location;
const statusCode = res.statusCode;
if (
location &&
opts.followRedirects &&
statusCode >= 300 &&
statusCode < 400
) {
if (++websocket._redirects > opts.maxRedirects) {
abortHandshake(websocket, req, 'Maximum redirects exceeded');
return;
}
req.abort();
const addr = url.URL
? new url.URL(location, address)
: url.resolve(address, location);
abortHandshake(this, req, `Unexpected server response: ${res.statusCode}`); initAsClient(websocket, addr, protocols, options);
} else if (!websocket.emit('unexpected-response', req, res)) {
abortHandshake(
websocket,
req,
`Unexpected server response: ${res.statusCode}`
);
}
}); });
req.on('upgrade', (res, socket, head) => { req.on('upgrade', (res, socket, head) => {
this.emit('upgrade', res); websocket.emit('upgrade', res);
// //
// The user may have closed the connection from a listener of the `upgrade` // The user may have closed the connection from a listener of the `upgrade`
// event. // event.
// //
if (this.readyState !== WebSocket.CONNECTING) return; if (websocket.readyState !== WebSocket.CONNECTING) return;
req = this._req = null; req = websocket._req = null;
const digest = crypto const digest = crypto
.createHash('sha1') .createHash('sha1')
.update(key + constants.GUID, 'binary') .update(key + GUID)
.digest('base64'); .digest('base64');
if (res.headers['sec-websocket-accept'] !== digest) { if (res.headers['sec-websocket-accept'] !== digest) {
abortHandshake(this, socket, 'Invalid Sec-WebSocket-Accept header'); abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header');
return; return;
} }
...@@ -595,11 +634,11 @@ function initAsClient(address, protocols, options) { ...@@ -595,11 +634,11 @@ function initAsClient(address, protocols, options) {
} }
if (protError) { if (protError) {
abortHandshake(this, socket, protError); abortHandshake(websocket, socket, protError);
return; return;
} }
if (serverProt) this.protocol = serverProt; if (serverProt) websocket.protocol = serverProt;
if (perMessageDeflate) { if (perMessageDeflate) {
try { try {
...@@ -609,15 +648,21 @@ function initAsClient(address, protocols, options) { ...@@ -609,15 +648,21 @@ function initAsClient(address, protocols, options) {
if (extensions[PerMessageDeflate.extensionName]) { if (extensions[PerMessageDeflate.extensionName]) {
perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]); perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
this._extensions[PerMessageDeflate.extensionName] = perMessageDeflate; websocket._extensions[
PerMessageDeflate.extensionName
] = perMessageDeflate;
} }
} catch (err) { } catch (err) {
abortHandshake(this, socket, 'Invalid Sec-WebSocket-Extensions header'); abortHandshake(
websocket,
socket,
'Invalid Sec-WebSocket-Extensions header'
);
return; return;
} }
} }
this.setSocket(socket, head, options.maxPayload); websocket.setSocket(socket, head, opts.maxPayload);
}); });
} }
...@@ -720,7 +765,7 @@ function receiverOnError(err) { ...@@ -720,7 +765,7 @@ function receiverOnError(err) {
websocket._socket.removeListener('data', socketOnData); websocket._socket.removeListener('data', socketOnData);
websocket.readyState = WebSocket.CLOSING; websocket.readyState = WebSocket.CLOSING;
websocket._closeCode = err[constants.kStatusCode]; websocket._closeCode = err[kStatusCode];
websocket.emit('error', err); websocket.emit('error', err);
websocket._socket.destroy(); websocket._socket.destroy();
} }
...@@ -753,7 +798,7 @@ function receiverOnMessage(data) { ...@@ -753,7 +798,7 @@ function receiverOnMessage(data) {
function receiverOnPing(data) { function receiverOnPing(data) {
const websocket = this[kWebSocket]; const websocket = this[kWebSocket];
websocket.pong(data, !websocket._isServer, constants.NOOP); websocket.pong(data, !websocket._isServer, NOOP);
websocket.emit('ping', data); websocket.emit('ping', data);
} }
...@@ -843,10 +888,8 @@ function socketOnError() { ...@@ -843,10 +888,8 @@ function socketOnError() {
const websocket = this[kWebSocket]; const websocket = this[kWebSocket];
this.removeListener('error', socketOnError); this.removeListener('error', socketOnError);
this.on('error', constants.NOOP); this.on('error', NOOP);
if (websocket) { websocket.readyState = WebSocket.CLOSING;
websocket.readyState = WebSocket.CLOSING; this.destroy();
this.destroy();
}
} }
{ {
"name": "ws", "_args": [
"version": "6.1.4", [
"ws@6.2.2",
"/Users/m/workspace/antSword"
]
],
"_from": "ws@6.2.2",
"_hasShrinkwrap": false,
"_id": "ws@6.2.2",
"_inCache": true,
"_installable": true,
"_location": "/ws",
"_nodeVersion": "16.2.0",
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/ws_6.2.2_1622572492507_0.791522012984119"
},
"_npmUser": {
"email": "luigipinca@gmail.com",
"name": "lpinca"
},
"_npmVersion": "7.13.0",
"_phantomChildren": {},
"_requested": {
"name": "ws",
"raw": "ws@6.2.2",
"rawSpec": "6.2.2",
"scope": null,
"spec": "6.2.2",
"type": "version"
},
"_requiredBy": [
"#USER"
],
"_resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
"_shasum": "dd5cdbd57a9979916097652d78f1cc5faea0c32e",
"_shrinkwrap": null,
"_spec": "ws@6.2.2",
"_where": "/Users/m/workspace/antSword",
"author": {
"email": "einaros@gmail.com",
"name": "Einar Otto Stangvik",
"url": "http://2x.io"
},
"browser": "browser.js",
"bugs": {
"url": "https://github.com/websockets/ws/issues"
},
"dependencies": {
"async-limiter": "~1.0.0"
},
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js", "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
"devDependencies": {
"benchmark": "~2.1.4",
"bufferutil": "~4.0.0",
"coveralls": "~3.0.3",
"eslint": "~5.15.0",
"eslint-config-prettier": "~4.1.0",
"eslint-plugin-prettier": "~3.0.0",
"mocha": "~6.0.0",
"nyc": "~13.3.0",
"prettier": "~1.16.1",
"utf-8-validate": "~5.0.0"
},
"directories": {},
"dist": {
"fileCount": 15,
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgtn3NCRA9TVsSAnZWagAAxFsP/jSEBOvCrZ5dtS/nj0ua\nqsCbU/Y1wqG/M0edJS6b9hM2SgKdmHPH9byqgrBs6SlEBSi8v0H0XEhvUjd0\nW3SNXps8SA0j7O1v6Sbb9YbJm0RU14Cq0gOngxJ/uad6XOOwCSsQqV9FfA9R\nnzx9QBXnJVks+q/LS3qDJ2XbvBDD4nA+YiIPJHu9nry21Z+lC48lsMQinLVZ\n4pAvCHAYNzgUg0J6B0qQQ+wc+i9Ml/3CRUmZMJ32h/yx2zzdwQ5zR5PDl3xb\nKhROfEE2kybahk7bYMIwBCVNPhe+WeoOKBJlu7V/Mzx3x/RnsSLUu6pF2alI\nvNfb4cS9B0ik9p8OdC9ULauDVKwHusfoxNjtmDFqDmxgh0zEnCQidhaWep0k\nwg30GmEkx3lzGWgjOJ8/1svW0TFVUUojGvQQc0qmgM+9Rn2tqcWkdV+xNm6A\nymtt9ZDpPPFBPmtipqbcRcLU7JuLM9PUz6xqRBCYyerBc1aqO0/oIevFuC/F\nifB8ZNPVvVwUJq2gz0KTkrnqpa1GDvaP4abFihpuXeodhN9QEF1YvCItdoAp\n4kWSOpVVpLfmJAxEgtHhkCKwfYJEP8lf7mjS+ilnkeP0cKO6Aq/N693fnH1W\nWE12+K2HXSmpWzoyKiFyU7psS9afANp4QbQsVh/mhQKSGRyIl4wmU1emJT9b\nv8eQ\r\n=1LXy\r\n-----END PGP SIGNATURE-----\r\n",
"shasum": "dd5cdbd57a9979916097652d78f1cc5faea0c32e",
"signatures": [
{
"keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
"sig": "MEYCIQDTi3OXyBRVRRDbt1DkzzQvNJvHj01yrckBeI61CKkihAIhAJ20N24tK5ntCd8n0EL5JZEQVtwt2nYggGUWmIgr9pVY"
}
],
"tarball": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
"unpackedSize": 101735
},
"gitHead": "9bdb58070d64c33a9beeac7c732aac0f4e7e18b7",
"homepage": "https://github.com/websockets/ws",
"keywords": [ "keywords": [
"HyBi", "HyBi",
"Push", "Push",
...@@ -10,36 +88,37 @@ ...@@ -10,36 +88,37 @@
"WebSockets", "WebSockets",
"real-time" "real-time"
], ],
"homepage": "https://github.com/websockets/ws",
"bugs": "https://github.com/websockets/ws/issues",
"repository": "websockets/ws",
"author": "Einar Otto Stangvik <einaros@gmail.com> (http://2x.io)",
"license": "MIT", "license": "MIT",
"main": "index.js", "main": "index.js",
"browser": "browser.js", "maintainers": [
"files": [ {
"browser.js", "email": "einaros@gmail.com",
"index.js", "name": "einaros"
"lib/*.js" },
{
"email": "npm@3rd-Eden.com",
"name": "v1"
},
{
"email": "luigipinca@gmail.com",
"name": "lpinca"
},
{
"email": "npmjs@3rd-Eden.com",
"name": "3rdeden"
}
], ],
"name": "ws",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/websockets/ws.git"
},
"scripts": { "scripts": {
"test": "npm run lint && nyc --reporter=html --reporter=text mocha test/*.test.js",
"integration": "npm run lint && mocha test/*.integration.js", "integration": "npm run lint && mocha test/*.integration.js",
"lint": "eslint . --ignore-path .gitignore && prettylint '**/*.{json,md}' --ignore-path .gitignore" "lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yml}\"",
}, "test": "npm run lint && nyc --reporter=html --reporter=text mocha test/*.test.js"
"dependencies": {
"async-limiter": "~1.0.0"
}, },
"devDependencies": { "version": "6.2.2"
"benchmark": "~2.1.4",
"bufferutil": "~4.0.0",
"eslint": "~5.14.0",
"eslint-config-prettier": "~4.0.0",
"eslint-plugin-prettier": "~3.0.0",
"mocha": "~5.2.0",
"nyc": "~13.3.0",
"prettier": "~1.16.1",
"prettylint": "~1.0.0",
"utf-8-validate": "~5.0.0"
}
} }
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
"superagent-proxy": "3.0.0", "superagent-proxy": "3.0.0",
"tar": "4.4.18", "tar": "4.4.18",
"through": "2.3.8", "through": "2.3.8",
"ws": "6.1.4", "ws": "6.2.2",
"mime": "2.6.0", "mime": "2.6.0",
"xml2js": "0.4.23" "xml2js": "0.4.23"
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment