isomorfeus-transport 2.0.7 → 2.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,180 +1,159 @@
1
- 'use strict';
2
-
3
- const { Duplex } = require('stream');
4
-
5
- /**
6
- * Emits the `'close'` event on a stream.
7
- *
8
- * @param {Duplex} stream The stream.
9
- * @private
10
- */
11
- function emitClose(stream) {
12
- stream.emit('close');
13
- }
14
-
15
- /**
16
- * The listener of the `'end'` event.
17
- *
18
- * @private
19
- */
20
- function duplexOnEnd() {
21
- if (!this.destroyed && this._writableState.finished) {
22
- this.destroy();
23
- }
24
- }
25
-
26
- /**
27
- * The listener of the `'error'` event.
28
- *
29
- * @param {Error} err The error
30
- * @private
31
- */
32
- function duplexOnError(err) {
33
- this.removeListener('error', duplexOnError);
34
- this.destroy();
35
- if (this.listenerCount('error') === 0) {
36
- // Do not suppress the throwing behavior.
37
- this.emit('error', err);
38
- }
39
- }
40
-
41
- /**
42
- * Wraps a `WebSocket` in a duplex stream.
43
- *
44
- * @param {WebSocket} ws The `WebSocket` to wrap
45
- * @param {Object} [options] The options for the `Duplex` constructor
46
- * @return {Duplex} The duplex stream
47
- * @public
48
- */
49
- function createWebSocketStream(ws, options) {
50
- let resumeOnReceiverDrain = true;
51
- let terminateOnDestroy = true;
52
-
53
- function receiverOnDrain() {
54
- if (resumeOnReceiverDrain) ws._socket.resume();
55
- }
56
-
57
- if (ws.readyState === ws.CONNECTING) {
58
- ws.once('open', function open() {
59
- ws._receiver.removeAllListeners('drain');
60
- ws._receiver.on('drain', receiverOnDrain);
61
- });
62
- } else {
63
- ws._receiver.removeAllListeners('drain');
64
- ws._receiver.on('drain', receiverOnDrain);
65
- }
66
-
67
- const duplex = new Duplex({
68
- ...options,
69
- autoDestroy: false,
70
- emitClose: false,
71
- objectMode: false,
72
- writableObjectMode: false
73
- });
74
-
75
- ws.on('message', function message(msg, isBinary) {
76
- const data =
77
- !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;
78
-
79
- if (!duplex.push(data)) {
80
- resumeOnReceiverDrain = false;
81
- ws._socket.pause();
82
- }
83
- });
84
-
85
- ws.once('error', function error(err) {
86
- if (duplex.destroyed) return;
87
-
88
- // Prevent `ws.terminate()` from being called by `duplex._destroy()`.
89
- //
90
- // - If the `'error'` event is emitted before the `'open'` event, then
91
- // `ws.terminate()` is a noop as no socket is assigned.
92
- // - Otherwise, the error is re-emitted by the listener of the `'error'`
93
- // event of the `Receiver` object. The listener already closes the
94
- // connection by calling `ws.close()`. This allows a close frame to be
95
- // sent to the other peer. If `ws.terminate()` is called right after this,
96
- // then the close frame might not be sent.
97
- terminateOnDestroy = false;
98
- duplex.destroy(err);
99
- });
100
-
101
- ws.once('close', function close() {
102
- if (duplex.destroyed) return;
103
-
104
- duplex.push(null);
105
- });
106
-
107
- duplex._destroy = function (err, callback) {
108
- if (ws.readyState === ws.CLOSED) {
109
- callback(err);
110
- process.nextTick(emitClose, duplex);
111
- return;
112
- }
113
-
114
- let called = false;
115
-
116
- ws.once('error', function error(err) {
117
- called = true;
118
- callback(err);
119
- });
120
-
121
- ws.once('close', function close() {
122
- if (!called) callback(err);
123
- process.nextTick(emitClose, duplex);
124
- });
125
-
126
- if (terminateOnDestroy) ws.terminate();
127
- };
128
-
129
- duplex._final = function (callback) {
130
- if (ws.readyState === ws.CONNECTING) {
131
- ws.once('open', function open() {
132
- duplex._final(callback);
133
- });
134
- return;
135
- }
136
-
137
- // If the value of the `_socket` property is `null` it means that `ws` is a
138
- // client websocket and the handshake failed. In fact, when this happens, a
139
- // socket is never assigned to the websocket. Wait for the `'error'` event
140
- // that will be emitted by the websocket.
141
- if (ws._socket === null) return;
142
-
143
- if (ws._socket._writableState.finished) {
144
- callback();
145
- if (duplex._readableState.endEmitted) duplex.destroy();
146
- } else {
147
- ws._socket.once('finish', function finish() {
148
- // `duplex` is not destroyed here because the `'end'` event will be
149
- // emitted on `duplex` after this `'finish'` event. The EOF signaling
150
- // `null` chunk is, in fact, pushed when the websocket emits `'close'`.
151
- callback();
152
- });
153
- ws.close();
154
- }
155
- };
156
-
157
- duplex._read = function () {
158
- if (ws.readyState === ws.OPEN && !resumeOnReceiverDrain) {
159
- resumeOnReceiverDrain = true;
160
- if (!ws._receiver._writableState.needDrain) ws._socket.resume();
161
- }
162
- };
163
-
164
- duplex._write = function (chunk, encoding, callback) {
165
- if (ws.readyState === ws.CONNECTING) {
166
- ws.once('open', function open() {
167
- duplex._write(chunk, encoding, callback);
168
- });
169
- return;
170
- }
171
-
172
- ws.send(chunk, callback);
173
- };
174
-
175
- duplex.on('end', duplexOnEnd);
176
- duplex.on('error', duplexOnError);
177
- return duplex;
178
- }
179
-
180
- module.exports = createWebSocketStream;
1
+ 'use strict';
2
+
3
+ const { Duplex } = require('stream');
4
+
5
+ /**
6
+ * Emits the `'close'` event on a stream.
7
+ *
8
+ * @param {Duplex} stream The stream.
9
+ * @private
10
+ */
11
+ function emitClose(stream) {
12
+ stream.emit('close');
13
+ }
14
+
15
+ /**
16
+ * The listener of the `'end'` event.
17
+ *
18
+ * @private
19
+ */
20
+ function duplexOnEnd() {
21
+ if (!this.destroyed && this._writableState.finished) {
22
+ this.destroy();
23
+ }
24
+ }
25
+
26
+ /**
27
+ * The listener of the `'error'` event.
28
+ *
29
+ * @param {Error} err The error
30
+ * @private
31
+ */
32
+ function duplexOnError(err) {
33
+ this.removeListener('error', duplexOnError);
34
+ this.destroy();
35
+ if (this.listenerCount('error') === 0) {
36
+ // Do not suppress the throwing behavior.
37
+ this.emit('error', err);
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Wraps a `WebSocket` in a duplex stream.
43
+ *
44
+ * @param {WebSocket} ws The `WebSocket` to wrap
45
+ * @param {Object} [options] The options for the `Duplex` constructor
46
+ * @return {Duplex} The duplex stream
47
+ * @public
48
+ */
49
+ function createWebSocketStream(ws, options) {
50
+ let terminateOnDestroy = true;
51
+
52
+ const duplex = new Duplex({
53
+ ...options,
54
+ autoDestroy: false,
55
+ emitClose: false,
56
+ objectMode: false,
57
+ writableObjectMode: false
58
+ });
59
+
60
+ ws.on('message', function message(msg, isBinary) {
61
+ const data =
62
+ !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;
63
+
64
+ if (!duplex.push(data)) ws.pause();
65
+ });
66
+
67
+ ws.once('error', function error(err) {
68
+ if (duplex.destroyed) return;
69
+
70
+ // Prevent `ws.terminate()` from being called by `duplex._destroy()`.
71
+ //
72
+ // - If the `'error'` event is emitted before the `'open'` event, then
73
+ // `ws.terminate()` is a noop as no socket is assigned.
74
+ // - Otherwise, the error is re-emitted by the listener of the `'error'`
75
+ // event of the `Receiver` object. The listener already closes the
76
+ // connection by calling `ws.close()`. This allows a close frame to be
77
+ // sent to the other peer. If `ws.terminate()` is called right after this,
78
+ // then the close frame might not be sent.
79
+ terminateOnDestroy = false;
80
+ duplex.destroy(err);
81
+ });
82
+
83
+ ws.once('close', function close() {
84
+ if (duplex.destroyed) return;
85
+
86
+ duplex.push(null);
87
+ });
88
+
89
+ duplex._destroy = function (err, callback) {
90
+ if (ws.readyState === ws.CLOSED) {
91
+ callback(err);
92
+ process.nextTick(emitClose, duplex);
93
+ return;
94
+ }
95
+
96
+ let called = false;
97
+
98
+ ws.once('error', function error(err) {
99
+ called = true;
100
+ callback(err);
101
+ });
102
+
103
+ ws.once('close', function close() {
104
+ if (!called) callback(err);
105
+ process.nextTick(emitClose, duplex);
106
+ });
107
+
108
+ if (terminateOnDestroy) ws.terminate();
109
+ };
110
+
111
+ duplex._final = function (callback) {
112
+ if (ws.readyState === ws.CONNECTING) {
113
+ ws.once('open', function open() {
114
+ duplex._final(callback);
115
+ });
116
+ return;
117
+ }
118
+
119
+ // If the value of the `_socket` property is `null` it means that `ws` is a
120
+ // client websocket and the handshake failed. In fact, when this happens, a
121
+ // socket is never assigned to the websocket. Wait for the `'error'` event
122
+ // that will be emitted by the websocket.
123
+ if (ws._socket === null) return;
124
+
125
+ if (ws._socket._writableState.finished) {
126
+ callback();
127
+ if (duplex._readableState.endEmitted) duplex.destroy();
128
+ } else {
129
+ ws._socket.once('finish', function finish() {
130
+ // `duplex` is not destroyed here because the `'end'` event will be
131
+ // emitted on `duplex` after this `'finish'` event. The EOF signaling
132
+ // `null` chunk is, in fact, pushed when the websocket emits `'close'`.
133
+ callback();
134
+ });
135
+ ws.close();
136
+ }
137
+ };
138
+
139
+ duplex._read = function () {
140
+ if (ws.isPaused) ws.resume();
141
+ };
142
+
143
+ duplex._write = function (chunk, encoding, callback) {
144
+ if (ws.readyState === ws.CONNECTING) {
145
+ ws.once('open', function open() {
146
+ duplex._write(chunk, encoding, callback);
147
+ });
148
+ return;
149
+ }
150
+
151
+ ws.send(chunk, callback);
152
+ };
153
+
154
+ duplex.on('end', duplexOnEnd);
155
+ duplex.on('error', duplexOnError);
156
+ return duplex;
157
+ }
158
+
159
+ module.exports = createWebSocketStream;
@@ -1,62 +1,62 @@
1
- 'use strict';
2
-
3
- const { tokenChars } = require('./validation');
4
-
5
- /**
6
- * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.
7
- *
8
- * @param {String} header The field value of the header
9
- * @return {Set} The subprotocol names
10
- * @public
11
- */
12
- function parse(header) {
13
- const protocols = new Set();
14
- let start = -1;
15
- let end = -1;
16
- let i = 0;
17
-
18
- for (i; i < header.length; i++) {
19
- const code = header.charCodeAt(i);
20
-
21
- if (end === -1 && tokenChars[code] === 1) {
22
- if (start === -1) start = i;
23
- } else if (
24
- i !== 0 &&
25
- (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
26
- ) {
27
- if (end === -1 && start !== -1) end = i;
28
- } else if (code === 0x2c /* ',' */) {
29
- if (start === -1) {
30
- throw new SyntaxError(`Unexpected character at index ${i}`);
31
- }
32
-
33
- if (end === -1) end = i;
34
-
35
- const protocol = header.slice(start, end);
36
-
37
- if (protocols.has(protocol)) {
38
- throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
39
- }
40
-
41
- protocols.add(protocol);
42
- start = end = -1;
43
- } else {
44
- throw new SyntaxError(`Unexpected character at index ${i}`);
45
- }
46
- }
47
-
48
- if (start === -1 || end !== -1) {
49
- throw new SyntaxError('Unexpected end of input');
50
- }
51
-
52
- const protocol = header.slice(start, i);
53
-
54
- if (protocols.has(protocol)) {
55
- throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
56
- }
57
-
58
- protocols.add(protocol);
59
- return protocols;
60
- }
61
-
62
- module.exports = { parse };
1
+ 'use strict';
2
+
3
+ const { tokenChars } = require('./validation');
4
+
5
+ /**
6
+ * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.
7
+ *
8
+ * @param {String} header The field value of the header
9
+ * @return {Set} The subprotocol names
10
+ * @public
11
+ */
12
+ function parse(header) {
13
+ const protocols = new Set();
14
+ let start = -1;
15
+ let end = -1;
16
+ let i = 0;
17
+
18
+ for (i; i < header.length; i++) {
19
+ const code = header.charCodeAt(i);
20
+
21
+ if (end === -1 && tokenChars[code] === 1) {
22
+ if (start === -1) start = i;
23
+ } else if (
24
+ i !== 0 &&
25
+ (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
26
+ ) {
27
+ if (end === -1 && start !== -1) end = i;
28
+ } else if (code === 0x2c /* ',' */) {
29
+ if (start === -1) {
30
+ throw new SyntaxError(`Unexpected character at index ${i}`);
31
+ }
32
+
33
+ if (end === -1) end = i;
34
+
35
+ const protocol = header.slice(start, end);
36
+
37
+ if (protocols.has(protocol)) {
38
+ throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
39
+ }
40
+
41
+ protocols.add(protocol);
42
+ start = end = -1;
43
+ } else {
44
+ throw new SyntaxError(`Unexpected character at index ${i}`);
45
+ }
46
+ }
47
+
48
+ if (start === -1 || end !== -1) {
49
+ throw new SyntaxError('Unexpected end of input');
50
+ }
51
+
52
+ const protocol = header.slice(start, i);
53
+
54
+ if (protocols.has(protocol)) {
55
+ throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
56
+ }
57
+
58
+ protocols.add(protocol);
59
+ return protocols;
60
+ }
61
+
62
+ module.exports = { parse };