@andersbakken/fisk 4.0.53 → 4.0.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builder/VM_runtime.js +17 -17
- package/builder/fisk-builder.js +9300 -4508
- package/daemon/fisk-daemon.js +15 -1
- package/monitor/fisk-monitor.js +527 -113
- package/package.json +1 -1
- package/scheduler/fisk-scheduler.js +8977 -5217
package/monitor/fisk-monitor.js
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var require$$0$4 = require('events');
|
|
4
|
+
var require$$0$3 = require('events');
|
|
6
5
|
var require$$1 = require('https');
|
|
7
6
|
var require$$2$1 = require('http');
|
|
8
7
|
var require$$3 = require('net');
|
|
9
8
|
var require$$4 = require('tls');
|
|
10
|
-
var require$$
|
|
11
|
-
var require$$
|
|
9
|
+
var require$$5 = require('crypto');
|
|
10
|
+
var require$$0$2 = require('stream');
|
|
11
|
+
var require$$7 = require('url');
|
|
12
12
|
var require$$0$1 = require('zlib');
|
|
13
13
|
var require$$0 = require('fs');
|
|
14
14
|
var path = require('path');
|
|
15
15
|
var require$$2 = require('os');
|
|
16
|
-
var require$$0$2 = require('stream');
|
|
17
16
|
var assert = require('assert');
|
|
17
|
+
var blessed = require('@andersbakken/blessed');
|
|
18
18
|
var require$$1$1 = require('module');
|
|
19
19
|
|
|
20
20
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
21
21
|
|
|
22
|
-
var
|
|
23
|
-
var require$$0__default$4 = /*#__PURE__*/_interopDefaultLegacy(require$$0$4);
|
|
22
|
+
var require$$0__default$3 = /*#__PURE__*/_interopDefaultLegacy(require$$0$3);
|
|
24
23
|
var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
|
|
25
24
|
var require$$2__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$2$1);
|
|
26
25
|
var require$$3__default = /*#__PURE__*/_interopDefaultLegacy(require$$3);
|
|
27
26
|
var require$$4__default = /*#__PURE__*/_interopDefaultLegacy(require$$4);
|
|
28
|
-
var require$$
|
|
29
|
-
var require$$
|
|
27
|
+
var require$$5__default = /*#__PURE__*/_interopDefaultLegacy(require$$5);
|
|
28
|
+
var require$$0__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$0$2);
|
|
29
|
+
var require$$7__default = /*#__PURE__*/_interopDefaultLegacy(require$$7);
|
|
30
30
|
var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$1);
|
|
31
31
|
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
|
|
32
32
|
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
33
33
|
var require$$2__default = /*#__PURE__*/_interopDefaultLegacy(require$$2);
|
|
34
|
-
var require$$0__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$0$2);
|
|
35
34
|
var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
|
|
35
|
+
var blessed__default = /*#__PURE__*/_interopDefaultLegacy(blessed);
|
|
36
36
|
var require$$1__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$1$1);
|
|
37
37
|
|
|
38
38
|
var bufferUtilExports = {};
|
|
@@ -1028,6 +1028,7 @@ function inflateOnData(chunk) {
|
|
|
1028
1028
|
}
|
|
1029
1029
|
|
|
1030
1030
|
this[kError] = new RangeError('Max payload size exceeded');
|
|
1031
|
+
this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';
|
|
1031
1032
|
this[kError][kStatusCode$2] = 1009;
|
|
1032
1033
|
this.removeListener('data', inflateOnData);
|
|
1033
1034
|
this.reset();
|
|
@@ -1272,7 +1273,7 @@ const INFLATING = 5;
|
|
|
1272
1273
|
/**
|
|
1273
1274
|
* HyBi Receiver implementation.
|
|
1274
1275
|
*
|
|
1275
|
-
* @extends
|
|
1276
|
+
* @extends Writable
|
|
1276
1277
|
*/
|
|
1277
1278
|
class Receiver$1 extends Writable {
|
|
1278
1279
|
/**
|
|
@@ -1418,14 +1419,26 @@ class Receiver$1 extends Writable {
|
|
|
1418
1419
|
|
|
1419
1420
|
if ((buf[0] & 0x30) !== 0x00) {
|
|
1420
1421
|
this._loop = false;
|
|
1421
|
-
return error(
|
|
1422
|
+
return error(
|
|
1423
|
+
RangeError,
|
|
1424
|
+
'RSV2 and RSV3 must be clear',
|
|
1425
|
+
true,
|
|
1426
|
+
1002,
|
|
1427
|
+
'WS_ERR_UNEXPECTED_RSV_2_3'
|
|
1428
|
+
);
|
|
1422
1429
|
}
|
|
1423
1430
|
|
|
1424
1431
|
const compressed = (buf[0] & 0x40) === 0x40;
|
|
1425
1432
|
|
|
1426
1433
|
if (compressed && !this._extensions[PerMessageDeflate$3.extensionName]) {
|
|
1427
1434
|
this._loop = false;
|
|
1428
|
-
return error(
|
|
1435
|
+
return error(
|
|
1436
|
+
RangeError,
|
|
1437
|
+
'RSV1 must be clear',
|
|
1438
|
+
true,
|
|
1439
|
+
1002,
|
|
1440
|
+
'WS_ERR_UNEXPECTED_RSV_1'
|
|
1441
|
+
);
|
|
1429
1442
|
}
|
|
1430
1443
|
|
|
1431
1444
|
this._fin = (buf[0] & 0x80) === 0x80;
|
|
@@ -1435,31 +1448,61 @@ class Receiver$1 extends Writable {
|
|
|
1435
1448
|
if (this._opcode === 0x00) {
|
|
1436
1449
|
if (compressed) {
|
|
1437
1450
|
this._loop = false;
|
|
1438
|
-
return error(
|
|
1451
|
+
return error(
|
|
1452
|
+
RangeError,
|
|
1453
|
+
'RSV1 must be clear',
|
|
1454
|
+
true,
|
|
1455
|
+
1002,
|
|
1456
|
+
'WS_ERR_UNEXPECTED_RSV_1'
|
|
1457
|
+
);
|
|
1439
1458
|
}
|
|
1440
1459
|
|
|
1441
1460
|
if (!this._fragmented) {
|
|
1442
1461
|
this._loop = false;
|
|
1443
|
-
return error(
|
|
1462
|
+
return error(
|
|
1463
|
+
RangeError,
|
|
1464
|
+
'invalid opcode 0',
|
|
1465
|
+
true,
|
|
1466
|
+
1002,
|
|
1467
|
+
'WS_ERR_INVALID_OPCODE'
|
|
1468
|
+
);
|
|
1444
1469
|
}
|
|
1445
1470
|
|
|
1446
1471
|
this._opcode = this._fragmented;
|
|
1447
1472
|
} else if (this._opcode === 0x01 || this._opcode === 0x02) {
|
|
1448
1473
|
if (this._fragmented) {
|
|
1449
1474
|
this._loop = false;
|
|
1450
|
-
return error(
|
|
1475
|
+
return error(
|
|
1476
|
+
RangeError,
|
|
1477
|
+
`invalid opcode ${this._opcode}`,
|
|
1478
|
+
true,
|
|
1479
|
+
1002,
|
|
1480
|
+
'WS_ERR_INVALID_OPCODE'
|
|
1481
|
+
);
|
|
1451
1482
|
}
|
|
1452
1483
|
|
|
1453
1484
|
this._compressed = compressed;
|
|
1454
1485
|
} else if (this._opcode > 0x07 && this._opcode < 0x0b) {
|
|
1455
1486
|
if (!this._fin) {
|
|
1456
1487
|
this._loop = false;
|
|
1457
|
-
return error(
|
|
1488
|
+
return error(
|
|
1489
|
+
RangeError,
|
|
1490
|
+
'FIN must be set',
|
|
1491
|
+
true,
|
|
1492
|
+
1002,
|
|
1493
|
+
'WS_ERR_EXPECTED_FIN'
|
|
1494
|
+
);
|
|
1458
1495
|
}
|
|
1459
1496
|
|
|
1460
1497
|
if (compressed) {
|
|
1461
1498
|
this._loop = false;
|
|
1462
|
-
return error(
|
|
1499
|
+
return error(
|
|
1500
|
+
RangeError,
|
|
1501
|
+
'RSV1 must be clear',
|
|
1502
|
+
true,
|
|
1503
|
+
1002,
|
|
1504
|
+
'WS_ERR_UNEXPECTED_RSV_1'
|
|
1505
|
+
);
|
|
1463
1506
|
}
|
|
1464
1507
|
|
|
1465
1508
|
if (this._payloadLength > 0x7d) {
|
|
@@ -1468,12 +1511,19 @@ class Receiver$1 extends Writable {
|
|
|
1468
1511
|
RangeError,
|
|
1469
1512
|
`invalid payload length ${this._payloadLength}`,
|
|
1470
1513
|
true,
|
|
1471
|
-
1002
|
|
1514
|
+
1002,
|
|
1515
|
+
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
|
|
1472
1516
|
);
|
|
1473
1517
|
}
|
|
1474
1518
|
} else {
|
|
1475
1519
|
this._loop = false;
|
|
1476
|
-
return error(
|
|
1520
|
+
return error(
|
|
1521
|
+
RangeError,
|
|
1522
|
+
`invalid opcode ${this._opcode}`,
|
|
1523
|
+
true,
|
|
1524
|
+
1002,
|
|
1525
|
+
'WS_ERR_INVALID_OPCODE'
|
|
1526
|
+
);
|
|
1477
1527
|
}
|
|
1478
1528
|
|
|
1479
1529
|
if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
|
|
@@ -1482,11 +1532,23 @@ class Receiver$1 extends Writable {
|
|
|
1482
1532
|
if (this._isServer) {
|
|
1483
1533
|
if (!this._masked) {
|
|
1484
1534
|
this._loop = false;
|
|
1485
|
-
return error(
|
|
1535
|
+
return error(
|
|
1536
|
+
RangeError,
|
|
1537
|
+
'MASK must be set',
|
|
1538
|
+
true,
|
|
1539
|
+
1002,
|
|
1540
|
+
'WS_ERR_EXPECTED_MASK'
|
|
1541
|
+
);
|
|
1486
1542
|
}
|
|
1487
1543
|
} else if (this._masked) {
|
|
1488
1544
|
this._loop = false;
|
|
1489
|
-
return error(
|
|
1545
|
+
return error(
|
|
1546
|
+
RangeError,
|
|
1547
|
+
'MASK must be clear',
|
|
1548
|
+
true,
|
|
1549
|
+
1002,
|
|
1550
|
+
'WS_ERR_UNEXPECTED_MASK'
|
|
1551
|
+
);
|
|
1490
1552
|
}
|
|
1491
1553
|
|
|
1492
1554
|
if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
|
|
@@ -1535,7 +1597,8 @@ class Receiver$1 extends Writable {
|
|
|
1535
1597
|
RangeError,
|
|
1536
1598
|
'Unsupported WebSocket frame: payload length > 2^53 - 1',
|
|
1537
1599
|
false,
|
|
1538
|
-
1009
|
|
1600
|
+
1009,
|
|
1601
|
+
'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'
|
|
1539
1602
|
);
|
|
1540
1603
|
}
|
|
1541
1604
|
|
|
@@ -1554,7 +1617,13 @@ class Receiver$1 extends Writable {
|
|
|
1554
1617
|
this._totalPayloadLength += this._payloadLength;
|
|
1555
1618
|
if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
|
|
1556
1619
|
this._loop = false;
|
|
1557
|
-
return error(
|
|
1620
|
+
return error(
|
|
1621
|
+
RangeError,
|
|
1622
|
+
'Max payload size exceeded',
|
|
1623
|
+
false,
|
|
1624
|
+
1009,
|
|
1625
|
+
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
|
1626
|
+
);
|
|
1558
1627
|
}
|
|
1559
1628
|
}
|
|
1560
1629
|
|
|
@@ -1634,7 +1703,13 @@ class Receiver$1 extends Writable {
|
|
|
1634
1703
|
this._messageLength += buf.length;
|
|
1635
1704
|
if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
|
|
1636
1705
|
return cb(
|
|
1637
|
-
error(
|
|
1706
|
+
error(
|
|
1707
|
+
RangeError,
|
|
1708
|
+
'Max payload size exceeded',
|
|
1709
|
+
false,
|
|
1710
|
+
1009,
|
|
1711
|
+
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
|
1712
|
+
)
|
|
1638
1713
|
);
|
|
1639
1714
|
}
|
|
1640
1715
|
|
|
@@ -1681,7 +1756,13 @@ class Receiver$1 extends Writable {
|
|
|
1681
1756
|
|
|
1682
1757
|
if (!isValidUTF8(buf)) {
|
|
1683
1758
|
this._loop = false;
|
|
1684
|
-
return error(
|
|
1759
|
+
return error(
|
|
1760
|
+
Error,
|
|
1761
|
+
'invalid UTF-8 sequence',
|
|
1762
|
+
true,
|
|
1763
|
+
1007,
|
|
1764
|
+
'WS_ERR_INVALID_UTF8'
|
|
1765
|
+
);
|
|
1685
1766
|
}
|
|
1686
1767
|
|
|
1687
1768
|
this.emit('message', buf.toString());
|
|
@@ -1706,18 +1787,36 @@ class Receiver$1 extends Writable {
|
|
|
1706
1787
|
this.emit('conclude', 1005, '');
|
|
1707
1788
|
this.end();
|
|
1708
1789
|
} else if (data.length === 1) {
|
|
1709
|
-
return error(
|
|
1790
|
+
return error(
|
|
1791
|
+
RangeError,
|
|
1792
|
+
'invalid payload length 1',
|
|
1793
|
+
true,
|
|
1794
|
+
1002,
|
|
1795
|
+
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
|
|
1796
|
+
);
|
|
1710
1797
|
} else {
|
|
1711
1798
|
const code = data.readUInt16BE(0);
|
|
1712
1799
|
|
|
1713
1800
|
if (!isValidStatusCode$1(code)) {
|
|
1714
|
-
return error(
|
|
1801
|
+
return error(
|
|
1802
|
+
RangeError,
|
|
1803
|
+
`invalid status code ${code}`,
|
|
1804
|
+
true,
|
|
1805
|
+
1002,
|
|
1806
|
+
'WS_ERR_INVALID_CLOSE_CODE'
|
|
1807
|
+
);
|
|
1715
1808
|
}
|
|
1716
1809
|
|
|
1717
1810
|
const buf = data.slice(2);
|
|
1718
1811
|
|
|
1719
1812
|
if (!isValidUTF8(buf)) {
|
|
1720
|
-
return error(
|
|
1813
|
+
return error(
|
|
1814
|
+
Error,
|
|
1815
|
+
'invalid UTF-8 sequence',
|
|
1816
|
+
true,
|
|
1817
|
+
1007,
|
|
1818
|
+
'WS_ERR_INVALID_UTF8'
|
|
1819
|
+
);
|
|
1721
1820
|
}
|
|
1722
1821
|
|
|
1723
1822
|
this.emit('conclude', code, buf.toString());
|
|
@@ -1738,25 +1837,28 @@ var receiver = Receiver$1;
|
|
|
1738
1837
|
/**
|
|
1739
1838
|
* Builds an error object.
|
|
1740
1839
|
*
|
|
1741
|
-
* @param {(Error|RangeError)} ErrorCtor The error constructor
|
|
1840
|
+
* @param {function(new:Error|RangeError)} ErrorCtor The error constructor
|
|
1742
1841
|
* @param {String} message The error message
|
|
1743
1842
|
* @param {Boolean} prefix Specifies whether or not to add a default prefix to
|
|
1744
1843
|
* `message`
|
|
1745
1844
|
* @param {Number} statusCode The status code
|
|
1845
|
+
* @param {String} errorCode The exposed error code
|
|
1746
1846
|
* @return {(Error|RangeError)} The error
|
|
1747
1847
|
* @private
|
|
1748
1848
|
*/
|
|
1749
|
-
function error(ErrorCtor, message, prefix, statusCode) {
|
|
1849
|
+
function error(ErrorCtor, message, prefix, statusCode, errorCode) {
|
|
1750
1850
|
const err = new ErrorCtor(
|
|
1751
1851
|
prefix ? `Invalid WebSocket frame: ${message}` : message
|
|
1752
1852
|
);
|
|
1753
1853
|
|
|
1754
1854
|
Error.captureStackTrace(err, error);
|
|
1855
|
+
err.code = errorCode;
|
|
1755
1856
|
err[kStatusCode$1] = statusCode;
|
|
1756
1857
|
return err;
|
|
1757
1858
|
}
|
|
1758
1859
|
|
|
1759
|
-
|
|
1860
|
+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^net|tls$" }] */
|
|
1861
|
+
const { randomFillSync } = require$$5__default["default"];
|
|
1760
1862
|
|
|
1761
1863
|
const PerMessageDeflate$2 = permessageDeflate;
|
|
1762
1864
|
const { EMPTY_BUFFER: EMPTY_BUFFER$1 } = constants;
|
|
@@ -1772,7 +1874,7 @@ class Sender$1 {
|
|
|
1772
1874
|
/**
|
|
1773
1875
|
* Creates a Sender instance.
|
|
1774
1876
|
*
|
|
1775
|
-
* @param {net.Socket} socket The connection socket
|
|
1877
|
+
* @param {(net.Socket|tls.Socket)} socket The connection socket
|
|
1776
1878
|
* @param {Object} [extensions] An object containing the negotiated extensions
|
|
1777
1879
|
*/
|
|
1778
1880
|
constructor(socket, extensions) {
|
|
@@ -2565,13 +2667,15 @@ function format$2(extensions) {
|
|
|
2565
2667
|
|
|
2566
2668
|
var extension = { format: format$2, parse: parse$2 };
|
|
2567
2669
|
|
|
2568
|
-
|
|
2670
|
+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Readable$" }] */
|
|
2671
|
+
|
|
2672
|
+
const EventEmitter$1 = require$$0__default$3["default"];
|
|
2569
2673
|
const https = require$$1__default["default"];
|
|
2570
|
-
const http = require$$2__default$1["default"];
|
|
2674
|
+
const http$1 = require$$2__default$1["default"];
|
|
2571
2675
|
const net = require$$3__default["default"];
|
|
2572
2676
|
const tls = require$$4__default["default"];
|
|
2573
|
-
const { randomBytes, createHash: createHash$1 } = require$$
|
|
2574
|
-
const { URL } = require$$
|
|
2677
|
+
const { randomBytes, createHash: createHash$1 } = require$$5__default["default"];
|
|
2678
|
+
const { URL } = require$$7__default["default"];
|
|
2575
2679
|
|
|
2576
2680
|
const PerMessageDeflate$1 = permessageDeflate;
|
|
2577
2681
|
const Receiver = receiver;
|
|
@@ -2601,7 +2705,7 @@ class WebSocket$2 extends EventEmitter$1 {
|
|
|
2601
2705
|
/**
|
|
2602
2706
|
* Create a new `WebSocket`.
|
|
2603
2707
|
*
|
|
2604
|
-
* @param {(String|
|
|
2708
|
+
* @param {(String|URL)} address The URL to which to connect
|
|
2605
2709
|
* @param {(String|String[])} [protocols] The subprotocols
|
|
2606
2710
|
* @param {Object} [options] Connection options
|
|
2607
2711
|
*/
|
|
@@ -2677,6 +2781,50 @@ class WebSocket$2 extends EventEmitter$1 {
|
|
|
2677
2781
|
return Object.keys(this._extensions).join();
|
|
2678
2782
|
}
|
|
2679
2783
|
|
|
2784
|
+
/**
|
|
2785
|
+
* @type {Function}
|
|
2786
|
+
*/
|
|
2787
|
+
/* istanbul ignore next */
|
|
2788
|
+
get onclose() {
|
|
2789
|
+
return undefined;
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
/* istanbul ignore next */
|
|
2793
|
+
set onclose(listener) {}
|
|
2794
|
+
|
|
2795
|
+
/**
|
|
2796
|
+
* @type {Function}
|
|
2797
|
+
*/
|
|
2798
|
+
/* istanbul ignore next */
|
|
2799
|
+
get onerror() {
|
|
2800
|
+
return undefined;
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
/* istanbul ignore next */
|
|
2804
|
+
set onerror(listener) {}
|
|
2805
|
+
|
|
2806
|
+
/**
|
|
2807
|
+
* @type {Function}
|
|
2808
|
+
*/
|
|
2809
|
+
/* istanbul ignore next */
|
|
2810
|
+
get onopen() {
|
|
2811
|
+
return undefined;
|
|
2812
|
+
}
|
|
2813
|
+
|
|
2814
|
+
/* istanbul ignore next */
|
|
2815
|
+
set onopen(listener) {}
|
|
2816
|
+
|
|
2817
|
+
/**
|
|
2818
|
+
* @type {Function}
|
|
2819
|
+
*/
|
|
2820
|
+
/* istanbul ignore next */
|
|
2821
|
+
get onmessage() {
|
|
2822
|
+
return undefined;
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
/* istanbul ignore next */
|
|
2826
|
+
set onmessage(listener) {}
|
|
2827
|
+
|
|
2680
2828
|
/**
|
|
2681
2829
|
* @type {String}
|
|
2682
2830
|
*/
|
|
@@ -2701,7 +2849,8 @@ class WebSocket$2 extends EventEmitter$1 {
|
|
|
2701
2849
|
/**
|
|
2702
2850
|
* Set up the socket and the internal resources.
|
|
2703
2851
|
*
|
|
2704
|
-
* @param {net.Socket} socket The network socket between the
|
|
2852
|
+
* @param {(net.Socket|tls.Socket)} socket The network socket between the
|
|
2853
|
+
* server and client
|
|
2705
2854
|
* @param {Buffer} head The first packet of the upgraded stream
|
|
2706
2855
|
* @param {Number} [maxPayload=0] The maximum allowed message size
|
|
2707
2856
|
* @private
|
|
@@ -2790,7 +2939,13 @@ class WebSocket$2 extends EventEmitter$1 {
|
|
|
2790
2939
|
}
|
|
2791
2940
|
|
|
2792
2941
|
if (this.readyState === WebSocket$2.CLOSING) {
|
|
2793
|
-
if (
|
|
2942
|
+
if (
|
|
2943
|
+
this._closeFrameSent &&
|
|
2944
|
+
(this._closeFrameReceived || this._receiver._writableState.errorEmitted)
|
|
2945
|
+
) {
|
|
2946
|
+
this._socket.end();
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2794
2949
|
return;
|
|
2795
2950
|
}
|
|
2796
2951
|
|
|
@@ -2803,7 +2958,13 @@ class WebSocket$2 extends EventEmitter$1 {
|
|
|
2803
2958
|
if (err) return;
|
|
2804
2959
|
|
|
2805
2960
|
this._closeFrameSent = true;
|
|
2806
|
-
|
|
2961
|
+
|
|
2962
|
+
if (
|
|
2963
|
+
this._closeFrameReceived ||
|
|
2964
|
+
this._receiver._writableState.errorEmitted
|
|
2965
|
+
) {
|
|
2966
|
+
this._socket.end();
|
|
2967
|
+
}
|
|
2807
2968
|
});
|
|
2808
2969
|
|
|
2809
2970
|
//
|
|
@@ -2945,11 +3106,76 @@ class WebSocket$2 extends EventEmitter$1 {
|
|
|
2945
3106
|
}
|
|
2946
3107
|
}
|
|
2947
3108
|
|
|
2948
|
-
|
|
2949
|
-
|
|
3109
|
+
/**
|
|
3110
|
+
* @constant {Number} CONNECTING
|
|
3111
|
+
* @memberof WebSocket
|
|
3112
|
+
*/
|
|
3113
|
+
Object.defineProperty(WebSocket$2, 'CONNECTING', {
|
|
3114
|
+
enumerable: true,
|
|
3115
|
+
value: readyStates.indexOf('CONNECTING')
|
|
3116
|
+
});
|
|
3117
|
+
|
|
3118
|
+
/**
|
|
3119
|
+
* @constant {Number} CONNECTING
|
|
3120
|
+
* @memberof WebSocket.prototype
|
|
3121
|
+
*/
|
|
3122
|
+
Object.defineProperty(WebSocket$2.prototype, 'CONNECTING', {
|
|
3123
|
+
enumerable: true,
|
|
3124
|
+
value: readyStates.indexOf('CONNECTING')
|
|
3125
|
+
});
|
|
3126
|
+
|
|
3127
|
+
/**
|
|
3128
|
+
* @constant {Number} OPEN
|
|
3129
|
+
* @memberof WebSocket
|
|
3130
|
+
*/
|
|
3131
|
+
Object.defineProperty(WebSocket$2, 'OPEN', {
|
|
3132
|
+
enumerable: true,
|
|
3133
|
+
value: readyStates.indexOf('OPEN')
|
|
3134
|
+
});
|
|
3135
|
+
|
|
3136
|
+
/**
|
|
3137
|
+
* @constant {Number} OPEN
|
|
3138
|
+
* @memberof WebSocket.prototype
|
|
3139
|
+
*/
|
|
3140
|
+
Object.defineProperty(WebSocket$2.prototype, 'OPEN', {
|
|
3141
|
+
enumerable: true,
|
|
3142
|
+
value: readyStates.indexOf('OPEN')
|
|
3143
|
+
});
|
|
3144
|
+
|
|
3145
|
+
/**
|
|
3146
|
+
* @constant {Number} CLOSING
|
|
3147
|
+
* @memberof WebSocket
|
|
3148
|
+
*/
|
|
3149
|
+
Object.defineProperty(WebSocket$2, 'CLOSING', {
|
|
3150
|
+
enumerable: true,
|
|
3151
|
+
value: readyStates.indexOf('CLOSING')
|
|
3152
|
+
});
|
|
3153
|
+
|
|
3154
|
+
/**
|
|
3155
|
+
* @constant {Number} CLOSING
|
|
3156
|
+
* @memberof WebSocket.prototype
|
|
3157
|
+
*/
|
|
3158
|
+
Object.defineProperty(WebSocket$2.prototype, 'CLOSING', {
|
|
3159
|
+
enumerable: true,
|
|
3160
|
+
value: readyStates.indexOf('CLOSING')
|
|
3161
|
+
});
|
|
3162
|
+
|
|
3163
|
+
/**
|
|
3164
|
+
* @constant {Number} CLOSED
|
|
3165
|
+
* @memberof WebSocket
|
|
3166
|
+
*/
|
|
3167
|
+
Object.defineProperty(WebSocket$2, 'CLOSED', {
|
|
3168
|
+
enumerable: true,
|
|
3169
|
+
value: readyStates.indexOf('CLOSED')
|
|
3170
|
+
});
|
|
2950
3171
|
|
|
2951
|
-
|
|
2952
|
-
|
|
3172
|
+
/**
|
|
3173
|
+
* @constant {Number} CLOSED
|
|
3174
|
+
* @memberof WebSocket.prototype
|
|
3175
|
+
*/
|
|
3176
|
+
Object.defineProperty(WebSocket$2.prototype, 'CLOSED', {
|
|
3177
|
+
enumerable: true,
|
|
3178
|
+
value: readyStates.indexOf('CLOSED')
|
|
2953
3179
|
});
|
|
2954
3180
|
|
|
2955
3181
|
[
|
|
@@ -2969,14 +3195,7 @@ readyStates.forEach((readyState, i) => {
|
|
|
2969
3195
|
//
|
|
2970
3196
|
['open', 'error', 'close', 'message'].forEach((method) => {
|
|
2971
3197
|
Object.defineProperty(WebSocket$2.prototype, `on${method}`, {
|
|
2972
|
-
configurable: true,
|
|
2973
3198
|
enumerable: true,
|
|
2974
|
-
/**
|
|
2975
|
-
* Return the listener of the event.
|
|
2976
|
-
*
|
|
2977
|
-
* @return {(Function|undefined)} The event listener or `undefined`
|
|
2978
|
-
* @public
|
|
2979
|
-
*/
|
|
2980
3199
|
get() {
|
|
2981
3200
|
const listeners = this.listeners(method);
|
|
2982
3201
|
for (let i = 0; i < listeners.length; i++) {
|
|
@@ -2985,12 +3204,6 @@ readyStates.forEach((readyState, i) => {
|
|
|
2985
3204
|
|
|
2986
3205
|
return undefined;
|
|
2987
3206
|
},
|
|
2988
|
-
/**
|
|
2989
|
-
* Add a listener for the event.
|
|
2990
|
-
*
|
|
2991
|
-
* @param {Function} listener The listener to add
|
|
2992
|
-
* @public
|
|
2993
|
-
*/
|
|
2994
3207
|
set(listener) {
|
|
2995
3208
|
const listeners = this.listeners(method);
|
|
2996
3209
|
for (let i = 0; i < listeners.length; i++) {
|
|
@@ -3013,7 +3226,7 @@ var websocket = WebSocket$2;
|
|
|
3013
3226
|
* Initialize a WebSocket client.
|
|
3014
3227
|
*
|
|
3015
3228
|
* @param {WebSocket} websocket The client to initialize
|
|
3016
|
-
* @param {(String|
|
|
3229
|
+
* @param {(String|URL)} address The URL to which to connect
|
|
3017
3230
|
* @param {String} [protocols] The subprotocols
|
|
3018
3231
|
* @param {Object} [options] Connection options
|
|
3019
3232
|
* @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
|
|
@@ -3071,14 +3284,21 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3071
3284
|
const isUnixSocket = parsedUrl.protocol === 'ws+unix:';
|
|
3072
3285
|
|
|
3073
3286
|
if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) {
|
|
3074
|
-
|
|
3287
|
+
const err = new Error(`Invalid URL: ${websocket.url}`);
|
|
3288
|
+
|
|
3289
|
+
if (websocket._redirects === 0) {
|
|
3290
|
+
throw err;
|
|
3291
|
+
} else {
|
|
3292
|
+
emitErrorAndClose(websocket, err);
|
|
3293
|
+
return;
|
|
3294
|
+
}
|
|
3075
3295
|
}
|
|
3076
3296
|
|
|
3077
3297
|
const isSecure =
|
|
3078
3298
|
parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:';
|
|
3079
3299
|
const defaultPort = isSecure ? 443 : 80;
|
|
3080
3300
|
const key = randomBytes(16).toString('base64');
|
|
3081
|
-
const get = isSecure ? https.get : http.get;
|
|
3301
|
+
const get = isSecure ? https.get : http$1.get;
|
|
3082
3302
|
let perMessageDeflate;
|
|
3083
3303
|
|
|
3084
3304
|
opts.createConnection = isSecure ? tlsConnect : netConnect;
|
|
@@ -3128,6 +3348,61 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3128
3348
|
opts.path = parts[1];
|
|
3129
3349
|
}
|
|
3130
3350
|
|
|
3351
|
+
if (opts.followRedirects) {
|
|
3352
|
+
if (websocket._redirects === 0) {
|
|
3353
|
+
websocket._originalUnixSocket = isUnixSocket;
|
|
3354
|
+
websocket._originalSecure = isSecure;
|
|
3355
|
+
websocket._originalHostOrSocketPath = isUnixSocket
|
|
3356
|
+
? opts.socketPath
|
|
3357
|
+
: parsedUrl.host;
|
|
3358
|
+
|
|
3359
|
+
const headers = options && options.headers;
|
|
3360
|
+
|
|
3361
|
+
//
|
|
3362
|
+
// Shallow copy the user provided options so that headers can be changed
|
|
3363
|
+
// without mutating the original object.
|
|
3364
|
+
//
|
|
3365
|
+
options = { ...options, headers: {} };
|
|
3366
|
+
|
|
3367
|
+
if (headers) {
|
|
3368
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
3369
|
+
options.headers[key.toLowerCase()] = value;
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
} else {
|
|
3373
|
+
const isSameHost = isUnixSocket
|
|
3374
|
+
? websocket._originalUnixSocket
|
|
3375
|
+
? opts.socketPath === websocket._originalHostOrSocketPath
|
|
3376
|
+
: false
|
|
3377
|
+
: websocket._originalUnixSocket
|
|
3378
|
+
? false
|
|
3379
|
+
: parsedUrl.host === websocket._originalHostOrSocketPath;
|
|
3380
|
+
|
|
3381
|
+
if (!isSameHost || (websocket._originalSecure && !isSecure)) {
|
|
3382
|
+
//
|
|
3383
|
+
// Match curl 7.77.0 behavior and drop the following headers. These
|
|
3384
|
+
// headers are also dropped when following a redirect to a subdomain.
|
|
3385
|
+
//
|
|
3386
|
+
delete opts.headers.authorization;
|
|
3387
|
+
delete opts.headers.cookie;
|
|
3388
|
+
|
|
3389
|
+
if (!isSameHost) delete opts.headers.host;
|
|
3390
|
+
|
|
3391
|
+
opts.auth = undefined;
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
//
|
|
3396
|
+
// Match curl 7.77.0 behavior and make the first `Authorization` header win.
|
|
3397
|
+
// If the `Authorization` header is set, then there is nothing to do as it
|
|
3398
|
+
// will take precedence.
|
|
3399
|
+
//
|
|
3400
|
+
if (opts.auth && !options.headers.authorization) {
|
|
3401
|
+
options.headers.authorization =
|
|
3402
|
+
'Basic ' + Buffer.from(opts.auth).toString('base64');
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3131
3406
|
let req = (websocket._req = get(opts));
|
|
3132
3407
|
|
|
3133
3408
|
if (opts.timeout) {
|
|
@@ -3140,9 +3415,7 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3140
3415
|
if (req === null || req.aborted) return;
|
|
3141
3416
|
|
|
3142
3417
|
req = websocket._req = null;
|
|
3143
|
-
websocket
|
|
3144
|
-
websocket.emit('error', err);
|
|
3145
|
-
websocket.emitClose();
|
|
3418
|
+
emitErrorAndClose(websocket, err);
|
|
3146
3419
|
});
|
|
3147
3420
|
|
|
3148
3421
|
req.on('response', (res) => {
|
|
@@ -3162,7 +3435,14 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3162
3435
|
|
|
3163
3436
|
req.abort();
|
|
3164
3437
|
|
|
3165
|
-
|
|
3438
|
+
let addr;
|
|
3439
|
+
|
|
3440
|
+
try {
|
|
3441
|
+
addr = new URL(location, address);
|
|
3442
|
+
} catch (err) {
|
|
3443
|
+
emitErrorAndClose(websocket, err);
|
|
3444
|
+
return;
|
|
3445
|
+
}
|
|
3166
3446
|
|
|
3167
3447
|
initAsClient(websocket, addr, protocols, options);
|
|
3168
3448
|
} else if (!websocket.emit('unexpected-response', req, res)) {
|
|
@@ -3185,6 +3465,13 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3185
3465
|
|
|
3186
3466
|
req = websocket._req = null;
|
|
3187
3467
|
|
|
3468
|
+
const upgrade = res.headers.upgrade;
|
|
3469
|
+
|
|
3470
|
+
if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
|
|
3471
|
+
abortHandshake$1(websocket, socket, 'Invalid Upgrade header');
|
|
3472
|
+
return;
|
|
3473
|
+
}
|
|
3474
|
+
|
|
3188
3475
|
const digest = createHash$1('sha1')
|
|
3189
3476
|
.update(key + GUID$1)
|
|
3190
3477
|
.digest('base64');
|
|
@@ -3213,22 +3500,50 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3213
3500
|
|
|
3214
3501
|
if (serverProt) websocket._protocol = serverProt;
|
|
3215
3502
|
|
|
3216
|
-
|
|
3503
|
+
const secWebSocketExtensions = res.headers['sec-websocket-extensions'];
|
|
3504
|
+
|
|
3505
|
+
if (secWebSocketExtensions !== undefined) {
|
|
3506
|
+
if (!perMessageDeflate) {
|
|
3507
|
+
const message =
|
|
3508
|
+
'Server sent a Sec-WebSocket-Extensions header but no extension ' +
|
|
3509
|
+
'was requested';
|
|
3510
|
+
abortHandshake$1(websocket, socket, message);
|
|
3511
|
+
return;
|
|
3512
|
+
}
|
|
3513
|
+
|
|
3514
|
+
let extensions;
|
|
3515
|
+
|
|
3217
3516
|
try {
|
|
3218
|
-
|
|
3517
|
+
extensions = parse$1(secWebSocketExtensions);
|
|
3518
|
+
} catch (err) {
|
|
3519
|
+
const message = 'Invalid Sec-WebSocket-Extensions header';
|
|
3520
|
+
abortHandshake$1(websocket, socket, message);
|
|
3521
|
+
return;
|
|
3522
|
+
}
|
|
3523
|
+
|
|
3524
|
+
const extensionNames = Object.keys(extensions);
|
|
3219
3525
|
|
|
3220
|
-
|
|
3526
|
+
if (extensionNames.length) {
|
|
3527
|
+
if (
|
|
3528
|
+
extensionNames.length !== 1 ||
|
|
3529
|
+
extensionNames[0] !== PerMessageDeflate$1.extensionName
|
|
3530
|
+
) {
|
|
3531
|
+
const message =
|
|
3532
|
+
'Server indicated an extension that was not requested';
|
|
3533
|
+
abortHandshake$1(websocket, socket, message);
|
|
3534
|
+
return;
|
|
3535
|
+
}
|
|
3536
|
+
|
|
3537
|
+
try {
|
|
3221
3538
|
perMessageDeflate.accept(extensions[PerMessageDeflate$1.extensionName]);
|
|
3222
|
-
|
|
3223
|
-
|
|
3539
|
+
} catch (err) {
|
|
3540
|
+
const message = 'Invalid Sec-WebSocket-Extensions header';
|
|
3541
|
+
abortHandshake$1(websocket, socket, message);
|
|
3542
|
+
return;
|
|
3224
3543
|
}
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
socket,
|
|
3229
|
-
'Invalid Sec-WebSocket-Extensions header'
|
|
3230
|
-
);
|
|
3231
|
-
return;
|
|
3544
|
+
|
|
3545
|
+
websocket._extensions[PerMessageDeflate$1.extensionName] =
|
|
3546
|
+
perMessageDeflate;
|
|
3232
3547
|
}
|
|
3233
3548
|
}
|
|
3234
3549
|
|
|
@@ -3236,6 +3551,19 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3236
3551
|
});
|
|
3237
3552
|
}
|
|
3238
3553
|
|
|
3554
|
+
/**
|
|
3555
|
+
* Emit the `'error'` and `'close'` event.
|
|
3556
|
+
*
|
|
3557
|
+
* @param {WebSocket} websocket The WebSocket instance
|
|
3558
|
+
* @param {Error} The error to emit
|
|
3559
|
+
* @private
|
|
3560
|
+
*/
|
|
3561
|
+
function emitErrorAndClose(websocket, err) {
|
|
3562
|
+
websocket._readyState = WebSocket$2.CLOSING;
|
|
3563
|
+
websocket.emit('error', err);
|
|
3564
|
+
websocket.emitClose();
|
|
3565
|
+
}
|
|
3566
|
+
|
|
3239
3567
|
/**
|
|
3240
3568
|
* Create a `net.Socket` and initiate a connection.
|
|
3241
3569
|
*
|
|
@@ -3269,8 +3597,8 @@ function tlsConnect(options) {
|
|
|
3269
3597
|
* Abort the handshake and emit an error.
|
|
3270
3598
|
*
|
|
3271
3599
|
* @param {WebSocket} websocket The WebSocket instance
|
|
3272
|
-
* @param {(http.ClientRequest|net.Socket)} stream The request to
|
|
3273
|
-
* socket to destroy
|
|
3600
|
+
* @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to
|
|
3601
|
+
* abort or the socket to destroy
|
|
3274
3602
|
* @param {String} message The error message
|
|
3275
3603
|
* @private
|
|
3276
3604
|
*/
|
|
@@ -3343,13 +3671,15 @@ function sendAfterClose(websocket, data, cb) {
|
|
|
3343
3671
|
function receiverOnConclude(code, reason) {
|
|
3344
3672
|
const websocket = this[kWebSocket$1];
|
|
3345
3673
|
|
|
3346
|
-
websocket._socket.removeListener('data', socketOnData);
|
|
3347
|
-
websocket._socket.resume();
|
|
3348
|
-
|
|
3349
3674
|
websocket._closeFrameReceived = true;
|
|
3350
3675
|
websocket._closeMessage = reason;
|
|
3351
3676
|
websocket._closeCode = code;
|
|
3352
3677
|
|
|
3678
|
+
if (websocket._socket[kWebSocket$1] === undefined) return;
|
|
3679
|
+
|
|
3680
|
+
websocket._socket.removeListener('data', socketOnData);
|
|
3681
|
+
process.nextTick(resume, websocket._socket);
|
|
3682
|
+
|
|
3353
3683
|
if (code === 1005) websocket.close();
|
|
3354
3684
|
else websocket.close(code, reason);
|
|
3355
3685
|
}
|
|
@@ -3372,12 +3702,19 @@ function receiverOnDrain() {
|
|
|
3372
3702
|
function receiverOnError(err) {
|
|
3373
3703
|
const websocket = this[kWebSocket$1];
|
|
3374
3704
|
|
|
3375
|
-
websocket._socket
|
|
3705
|
+
if (websocket._socket[kWebSocket$1] !== undefined) {
|
|
3706
|
+
websocket._socket.removeListener('data', socketOnData);
|
|
3707
|
+
|
|
3708
|
+
//
|
|
3709
|
+
// On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See
|
|
3710
|
+
// https://github.com/websockets/ws/issues/1940.
|
|
3711
|
+
//
|
|
3712
|
+
process.nextTick(resume, websocket._socket);
|
|
3713
|
+
|
|
3714
|
+
websocket.close(err[kStatusCode]);
|
|
3715
|
+
}
|
|
3376
3716
|
|
|
3377
|
-
websocket._readyState = WebSocket$2.CLOSING;
|
|
3378
|
-
websocket._closeCode = err[kStatusCode];
|
|
3379
3717
|
websocket.emit('error', err);
|
|
3380
|
-
websocket._socket.destroy();
|
|
3381
3718
|
}
|
|
3382
3719
|
|
|
3383
3720
|
/**
|
|
@@ -3422,6 +3759,16 @@ function receiverOnPong(data) {
|
|
|
3422
3759
|
this[kWebSocket$1].emit('pong', data);
|
|
3423
3760
|
}
|
|
3424
3761
|
|
|
3762
|
+
/**
|
|
3763
|
+
* Resume a readable stream
|
|
3764
|
+
*
|
|
3765
|
+
* @param {Readable} stream The readable stream
|
|
3766
|
+
* @private
|
|
3767
|
+
*/
|
|
3768
|
+
function resume(stream) {
|
|
3769
|
+
stream.resume();
|
|
3770
|
+
}
|
|
3771
|
+
|
|
3425
3772
|
/**
|
|
3426
3773
|
* The listener of the `net.Socket` `'close'` event.
|
|
3427
3774
|
*
|
|
@@ -3431,10 +3778,13 @@ function socketOnClose() {
|
|
|
3431
3778
|
const websocket = this[kWebSocket$1];
|
|
3432
3779
|
|
|
3433
3780
|
this.removeListener('close', socketOnClose);
|
|
3781
|
+
this.removeListener('data', socketOnData);
|
|
3434
3782
|
this.removeListener('end', socketOnEnd);
|
|
3435
3783
|
|
|
3436
3784
|
websocket._readyState = WebSocket$2.CLOSING;
|
|
3437
3785
|
|
|
3786
|
+
let chunk;
|
|
3787
|
+
|
|
3438
3788
|
//
|
|
3439
3789
|
// The close frame might not have been received or the `'end'` event emitted,
|
|
3440
3790
|
// for example, if the socket was destroyed due to an error. Ensure that the
|
|
@@ -3442,13 +3792,19 @@ function socketOnClose() {
|
|
|
3442
3792
|
// it. If the readable side of the socket is in flowing mode then there is no
|
|
3443
3793
|
// buffered data as everything has been already written and `readable.read()`
|
|
3444
3794
|
// will return `null`. If instead, the socket is paused, any possible buffered
|
|
3445
|
-
// data will be read as a single chunk
|
|
3446
|
-
// `'data'` event.
|
|
3795
|
+
// data will be read as a single chunk.
|
|
3447
3796
|
//
|
|
3448
|
-
|
|
3797
|
+
if (
|
|
3798
|
+
!this._readableState.endEmitted &&
|
|
3799
|
+
!websocket._closeFrameReceived &&
|
|
3800
|
+
!websocket._receiver._writableState.errorEmitted &&
|
|
3801
|
+
(chunk = websocket._socket.read()) !== null
|
|
3802
|
+
) {
|
|
3803
|
+
websocket._receiver.write(chunk);
|
|
3804
|
+
}
|
|
3805
|
+
|
|
3449
3806
|
websocket._receiver.end();
|
|
3450
3807
|
|
|
3451
|
-
this.removeListener('data', socketOnData);
|
|
3452
3808
|
this[kWebSocket$1] = undefined;
|
|
3453
3809
|
|
|
3454
3810
|
clearTimeout(websocket._closeTimer);
|
|
@@ -3511,7 +3867,7 @@ const { Duplex } = require$$0__default$2["default"];
|
|
|
3511
3867
|
/**
|
|
3512
3868
|
* Emits the `'close'` event on a stream.
|
|
3513
3869
|
*
|
|
3514
|
-
* @param {
|
|
3870
|
+
* @param {Duplex} stream The stream.
|
|
3515
3871
|
* @private
|
|
3516
3872
|
*/
|
|
3517
3873
|
function emitClose$1(stream) {
|
|
@@ -3549,11 +3905,12 @@ function duplexOnError(err) {
|
|
|
3549
3905
|
*
|
|
3550
3906
|
* @param {WebSocket} ws The `WebSocket` to wrap
|
|
3551
3907
|
* @param {Object} [options] The options for the `Duplex` constructor
|
|
3552
|
-
* @return {
|
|
3908
|
+
* @return {Duplex} The duplex stream
|
|
3553
3909
|
* @public
|
|
3554
3910
|
*/
|
|
3555
3911
|
function createWebSocketStream(ws, options) {
|
|
3556
3912
|
let resumeOnReceiverDrain = true;
|
|
3913
|
+
let terminateOnDestroy = true;
|
|
3557
3914
|
|
|
3558
3915
|
function receiverOnDrain() {
|
|
3559
3916
|
if (resumeOnReceiverDrain) ws._socket.resume();
|
|
@@ -3587,6 +3944,16 @@ function createWebSocketStream(ws, options) {
|
|
|
3587
3944
|
ws.once('error', function error(err) {
|
|
3588
3945
|
if (duplex.destroyed) return;
|
|
3589
3946
|
|
|
3947
|
+
// Prevent `ws.terminate()` from being called by `duplex._destroy()`.
|
|
3948
|
+
//
|
|
3949
|
+
// - If the `'error'` event is emitted before the `'open'` event, then
|
|
3950
|
+
// `ws.terminate()` is a noop as no socket is assigned.
|
|
3951
|
+
// - Otherwise, the error is re-emitted by the listener of the `'error'`
|
|
3952
|
+
// event of the `Receiver` object. The listener already closes the
|
|
3953
|
+
// connection by calling `ws.close()`. This allows a close frame to be
|
|
3954
|
+
// sent to the other peer. If `ws.terminate()` is called right after this,
|
|
3955
|
+
// then the close frame might not be sent.
|
|
3956
|
+
terminateOnDestroy = false;
|
|
3590
3957
|
duplex.destroy(err);
|
|
3591
3958
|
});
|
|
3592
3959
|
|
|
@@ -3614,7 +3981,8 @@ function createWebSocketStream(ws, options) {
|
|
|
3614
3981
|
if (!called) callback(err);
|
|
3615
3982
|
process.nextTick(emitClose$1, duplex);
|
|
3616
3983
|
});
|
|
3617
|
-
|
|
3984
|
+
|
|
3985
|
+
if (terminateOnDestroy) ws.terminate();
|
|
3618
3986
|
};
|
|
3619
3987
|
|
|
3620
3988
|
duplex._final = function (callback) {
|
|
@@ -3646,7 +4014,10 @@ function createWebSocketStream(ws, options) {
|
|
|
3646
4014
|
};
|
|
3647
4015
|
|
|
3648
4016
|
duplex._read = function () {
|
|
3649
|
-
if (
|
|
4017
|
+
if (
|
|
4018
|
+
(ws.readyState === ws.OPEN || ws.readyState === ws.CLOSING) &&
|
|
4019
|
+
!resumeOnReceiverDrain
|
|
4020
|
+
) {
|
|
3650
4021
|
resumeOnReceiverDrain = true;
|
|
3651
4022
|
if (!ws._receiver._writableState.needDrain) ws._socket.resume();
|
|
3652
4023
|
}
|
|
@@ -3670,9 +4041,11 @@ function createWebSocketStream(ws, options) {
|
|
|
3670
4041
|
|
|
3671
4042
|
var stream = createWebSocketStream;
|
|
3672
4043
|
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
const
|
|
4044
|
+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^net|tls|https$" }] */
|
|
4045
|
+
|
|
4046
|
+
const EventEmitter = require$$0__default$3["default"];
|
|
4047
|
+
const http = require$$2__default$1["default"];
|
|
4048
|
+
const { createHash } = require$$5__default["default"];
|
|
3676
4049
|
|
|
3677
4050
|
const PerMessageDeflate = permessageDeflate;
|
|
3678
4051
|
const WebSocket$1 = websocket;
|
|
@@ -3681,6 +4054,10 @@ const { GUID, kWebSocket } = constants;
|
|
|
3681
4054
|
|
|
3682
4055
|
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
|
|
3683
4056
|
|
|
4057
|
+
const RUNNING = 0;
|
|
4058
|
+
const CLOSING = 1;
|
|
4059
|
+
const CLOSED = 2;
|
|
4060
|
+
|
|
3684
4061
|
/**
|
|
3685
4062
|
* Class representing a WebSocket server.
|
|
3686
4063
|
*
|
|
@@ -3704,7 +4081,8 @@ class WebSocketServer extends EventEmitter {
|
|
|
3704
4081
|
* @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
|
|
3705
4082
|
* permessage-deflate
|
|
3706
4083
|
* @param {Number} [options.port] The port where to bind the server
|
|
3707
|
-
* @param {http.Server} [options.server] A pre-created HTTP/S
|
|
4084
|
+
* @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
|
|
4085
|
+
* server to use
|
|
3708
4086
|
* @param {Function} [options.verifyClient] A hook to reject connections
|
|
3709
4087
|
* @param {Function} [callback] A listener for the `listening` event
|
|
3710
4088
|
*/
|
|
@@ -3726,15 +4104,20 @@ class WebSocketServer extends EventEmitter {
|
|
|
3726
4104
|
...options
|
|
3727
4105
|
};
|
|
3728
4106
|
|
|
3729
|
-
if (
|
|
4107
|
+
if (
|
|
4108
|
+
(options.port == null && !options.server && !options.noServer) ||
|
|
4109
|
+
(options.port != null && (options.server || options.noServer)) ||
|
|
4110
|
+
(options.server && options.noServer)
|
|
4111
|
+
) {
|
|
3730
4112
|
throw new TypeError(
|
|
3731
|
-
'One of the "port", "server", or "noServer" options
|
|
4113
|
+
'One and only one of the "port", "server", or "noServer" options ' +
|
|
4114
|
+
'must be specified'
|
|
3732
4115
|
);
|
|
3733
4116
|
}
|
|
3734
4117
|
|
|
3735
4118
|
if (options.port != null) {
|
|
3736
|
-
this._server = createServer((req, res) => {
|
|
3737
|
-
const body = STATUS_CODES[426];
|
|
4119
|
+
this._server = http.createServer((req, res) => {
|
|
4120
|
+
const body = http.STATUS_CODES[426];
|
|
3738
4121
|
|
|
3739
4122
|
res.writeHead(426, {
|
|
3740
4123
|
'Content-Length': body.length,
|
|
@@ -3767,6 +4150,7 @@ class WebSocketServer extends EventEmitter {
|
|
|
3767
4150
|
if (options.perMessageDeflate === true) options.perMessageDeflate = {};
|
|
3768
4151
|
if (options.clientTracking) this.clients = new Set();
|
|
3769
4152
|
this.options = options;
|
|
4153
|
+
this._state = RUNNING;
|
|
3770
4154
|
}
|
|
3771
4155
|
|
|
3772
4156
|
/**
|
|
@@ -3796,6 +4180,14 @@ class WebSocketServer extends EventEmitter {
|
|
|
3796
4180
|
close(cb) {
|
|
3797
4181
|
if (cb) this.once('close', cb);
|
|
3798
4182
|
|
|
4183
|
+
if (this._state === CLOSED) {
|
|
4184
|
+
process.nextTick(emitClose, this);
|
|
4185
|
+
return;
|
|
4186
|
+
}
|
|
4187
|
+
|
|
4188
|
+
if (this._state === CLOSING) return;
|
|
4189
|
+
this._state = CLOSING;
|
|
4190
|
+
|
|
3799
4191
|
//
|
|
3800
4192
|
// Terminate all associated clients.
|
|
3801
4193
|
//
|
|
@@ -3813,7 +4205,7 @@ class WebSocketServer extends EventEmitter {
|
|
|
3813
4205
|
// Close the http server if it was internally created.
|
|
3814
4206
|
//
|
|
3815
4207
|
if (this.options.port != null) {
|
|
3816
|
-
server.close((
|
|
4208
|
+
server.close(emitClose.bind(undefined, this));
|
|
3817
4209
|
return;
|
|
3818
4210
|
}
|
|
3819
4211
|
}
|
|
@@ -3843,7 +4235,8 @@ class WebSocketServer extends EventEmitter {
|
|
|
3843
4235
|
* Handle a HTTP Upgrade request.
|
|
3844
4236
|
*
|
|
3845
4237
|
* @param {http.IncomingMessage} req The request object
|
|
3846
|
-
* @param {net.Socket} socket The network socket between the
|
|
4238
|
+
* @param {(net.Socket|tls.Socket)} socket The network socket between the
|
|
4239
|
+
* server and client
|
|
3847
4240
|
* @param {Buffer} head The first packet of the upgraded stream
|
|
3848
4241
|
* @param {Function} cb Callback
|
|
3849
4242
|
* @public
|
|
@@ -3855,12 +4248,14 @@ class WebSocketServer extends EventEmitter {
|
|
|
3855
4248
|
req.headers['sec-websocket-key'] !== undefined
|
|
3856
4249
|
? req.headers['sec-websocket-key'].trim()
|
|
3857
4250
|
: false;
|
|
4251
|
+
const upgrade = req.headers.upgrade;
|
|
3858
4252
|
const version = +req.headers['sec-websocket-version'];
|
|
3859
4253
|
const extensions = {};
|
|
3860
4254
|
|
|
3861
4255
|
if (
|
|
3862
4256
|
req.method !== 'GET' ||
|
|
3863
|
-
|
|
4257
|
+
upgrade === undefined ||
|
|
4258
|
+
upgrade.toLowerCase() !== 'websocket' ||
|
|
3864
4259
|
!key ||
|
|
3865
4260
|
!keyRegex.test(key) ||
|
|
3866
4261
|
(version !== 8 && version !== 13) ||
|
|
@@ -3922,7 +4317,8 @@ class WebSocketServer extends EventEmitter {
|
|
|
3922
4317
|
* @param {String} key The value of the `Sec-WebSocket-Key` header
|
|
3923
4318
|
* @param {Object} extensions The accepted extensions
|
|
3924
4319
|
* @param {http.IncomingMessage} req The request object
|
|
3925
|
-
* @param {net.Socket} socket The network socket between the
|
|
4320
|
+
* @param {(net.Socket|tls.Socket)} socket The network socket between the
|
|
4321
|
+
* server and client
|
|
3926
4322
|
* @param {Buffer} head The first packet of the upgraded stream
|
|
3927
4323
|
* @param {Function} cb Callback
|
|
3928
4324
|
* @throws {Error} If called more than once with the same socket
|
|
@@ -3941,6 +4337,8 @@ class WebSocketServer extends EventEmitter {
|
|
|
3941
4337
|
);
|
|
3942
4338
|
}
|
|
3943
4339
|
|
|
4340
|
+
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
4341
|
+
|
|
3944
4342
|
const digest = createHash('sha1')
|
|
3945
4343
|
.update(key + GUID)
|
|
3946
4344
|
.digest('base64');
|
|
@@ -4030,6 +4428,7 @@ function addListeners(server, map) {
|
|
|
4030
4428
|
* @private
|
|
4031
4429
|
*/
|
|
4032
4430
|
function emitClose(server) {
|
|
4431
|
+
server._state = CLOSED;
|
|
4033
4432
|
server.emit('close');
|
|
4034
4433
|
}
|
|
4035
4434
|
|
|
@@ -4045,7 +4444,7 @@ function socketOnError() {
|
|
|
4045
4444
|
/**
|
|
4046
4445
|
* Close the connection when preconditions are not fulfilled.
|
|
4047
4446
|
*
|
|
4048
|
-
* @param {net.Socket} socket The socket of the upgrade request
|
|
4447
|
+
* @param {(net.Socket|tls.Socket)} socket The socket of the upgrade request
|
|
4049
4448
|
* @param {Number} code The HTTP response status code
|
|
4050
4449
|
* @param {String} [message] The HTTP response body
|
|
4051
4450
|
* @param {Object} [headers] Additional HTTP response headers
|
|
@@ -4053,7 +4452,7 @@ function socketOnError() {
|
|
|
4053
4452
|
*/
|
|
4054
4453
|
function abortHandshake(socket, code, message, headers) {
|
|
4055
4454
|
if (socket.writable) {
|
|
4056
|
-
message = message || STATUS_CODES[code];
|
|
4455
|
+
message = message || http.STATUS_CODES[code];
|
|
4057
4456
|
headers = {
|
|
4058
4457
|
Connection: 'close',
|
|
4059
4458
|
'Content-Type': 'text/html',
|
|
@@ -4062,7 +4461,7 @@ function abortHandshake(socket, code, message, headers) {
|
|
|
4062
4461
|
};
|
|
4063
4462
|
|
|
4064
4463
|
socket.write(
|
|
4065
|
-
`HTTP/1.1 ${code} ${STATUS_CODES[code]}\r\n` +
|
|
4464
|
+
`HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
|
|
4066
4465
|
Object.keys(headers)
|
|
4067
4466
|
.map((h) => `${h}: ${headers[h]}`)
|
|
4068
4467
|
.join('\r\n') +
|
|
@@ -5491,6 +5890,16 @@ function options (optionsOptions, argv) {
|
|
|
5491
5890
|
});
|
|
5492
5891
|
}
|
|
5493
5892
|
|
|
5893
|
+
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
5894
|
+
console.log(`Usage: fisk-monitor [options]
|
|
5895
|
+
|
|
5896
|
+
Options:
|
|
5897
|
+
--scheduler=URL Scheduler URL (default: ws://localhost:8097)
|
|
5898
|
+
|
|
5899
|
+
Config files: ~/.config/fisk/monitor.conf, /etc/xdg/fisk/monitor.conf
|
|
5900
|
+
Environment variables: FISK_MONITOR_SCHEDULER, etc.`);
|
|
5901
|
+
process.exit(0);
|
|
5902
|
+
}
|
|
5494
5903
|
const option = options({
|
|
5495
5904
|
prefix: "fisk/monitor",
|
|
5496
5905
|
noApplicationPath: true,
|
|
@@ -5740,9 +6149,10 @@ clientBox.on("select", (ev) => {
|
|
|
5740
6149
|
if (jobKey === "total") {
|
|
5741
6150
|
continue;
|
|
5742
6151
|
}
|
|
5743
|
-
|
|
6152
|
+
const sourceBasename = path__default["default"].basename(jobValue.sourcePath || jobValue.sourceFile || "");
|
|
6153
|
+
widest[0] = Math.max(sourceBasename.length + 1, widest[0]);
|
|
5744
6154
|
data.push([
|
|
5745
|
-
|
|
6155
|
+
sourceBasename,
|
|
5746
6156
|
jobValue.builder.ip + ":" + jobValue.builder.port,
|
|
5747
6157
|
humanizeDuration(now - jobValue.time)
|
|
5748
6158
|
]);
|
|
@@ -5929,6 +6339,7 @@ function formatCell(str, num, prefix, suffix) {
|
|
|
5929
6339
|
return (prefix || "") + (" " + str).padEnd(num, " ").substr(0, num) + (suffix || "");
|
|
5930
6340
|
}
|
|
5931
6341
|
let updateTimer;
|
|
6342
|
+
let refreshTimer;
|
|
5932
6343
|
let timeout = 0;
|
|
5933
6344
|
function updateBuilderBox() {
|
|
5934
6345
|
const builderWidth = builderContainer.width - 3;
|
|
@@ -6009,11 +6420,14 @@ function updateBuilderBox() {
|
|
|
6009
6420
|
if (currentFocus !== builderBox) {
|
|
6010
6421
|
builderBox.scrollTo(0);
|
|
6011
6422
|
}
|
|
6423
|
+
if (refreshTimer) {
|
|
6424
|
+
clearTimeout(refreshTimer);
|
|
6425
|
+
}
|
|
6012
6426
|
if (newest < 60000) {
|
|
6013
|
-
setTimeout(update, 1000);
|
|
6427
|
+
refreshTimer = setTimeout(update, 1000);
|
|
6014
6428
|
}
|
|
6015
6429
|
else {
|
|
6016
|
-
setTimeout(update, 60000);
|
|
6430
|
+
refreshTimer = setTimeout(update, 60000);
|
|
6017
6431
|
}
|
|
6018
6432
|
}
|
|
6019
6433
|
function updateClientBox() {
|