isomorfeus-transport 2.0.6 → 2.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/isomorfeus/transport/rack_middleware.rb +1 -0
- data/lib/isomorfeus/transport/version.rb +1 -1
- data/lib/isomorfeus/transport/websocket_client.rb +6 -2
- data/lib/isomorfeus/transport.rb +3 -2
- data/node_modules/.package-lock.json +27 -27
- data/node_modules/ws/LICENSE +19 -19
- data/node_modules/ws/README.md +489 -496
- data/node_modules/ws/browser.js +8 -8
- data/node_modules/ws/index.js +13 -13
- data/node_modules/ws/lib/buffer-util.js +126 -126
- data/node_modules/ws/lib/constants.js +12 -12
- data/node_modules/ws/lib/event-target.js +266 -266
- data/node_modules/ws/lib/extension.js +203 -203
- data/node_modules/ws/lib/limiter.js +55 -55
- data/node_modules/ws/lib/permessage-deflate.js +511 -511
- data/node_modules/ws/lib/receiver.js +618 -612
- data/node_modules/ws/lib/sender.js +478 -414
- data/node_modules/ws/lib/stream.js +159 -180
- data/node_modules/ws/lib/subprotocol.js +62 -62
- data/node_modules/ws/lib/validation.js +124 -124
- data/node_modules/ws/lib/websocket-server.js +485 -485
- data/node_modules/ws/lib/websocket.js +1225 -1144
- data/node_modules/ws/package.json +61 -61
- data/node_modules/ws/wrapper.mjs +8 -8
- data/package.json +1 -1
- metadata +8 -8
@@ -1,203 +1,203 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const { tokenChars } = require('./validation');
|
4
|
-
|
5
|
-
/**
|
6
|
-
* Adds an offer to the map of extension offers or a parameter to the map of
|
7
|
-
* parameters.
|
8
|
-
*
|
9
|
-
* @param {Object} dest The map of extension offers or parameters
|
10
|
-
* @param {String} name The extension or parameter name
|
11
|
-
* @param {(Object|Boolean|String)} elem The extension parameters or the
|
12
|
-
* parameter value
|
13
|
-
* @private
|
14
|
-
*/
|
15
|
-
function push(dest, name, elem) {
|
16
|
-
if (dest[name] === undefined) dest[name] = [elem];
|
17
|
-
else dest[name].push(elem);
|
18
|
-
}
|
19
|
-
|
20
|
-
/**
|
21
|
-
* Parses the `Sec-WebSocket-Extensions` header into an object.
|
22
|
-
*
|
23
|
-
* @param {String} header The field value of the header
|
24
|
-
* @return {Object} The parsed object
|
25
|
-
* @public
|
26
|
-
*/
|
27
|
-
function parse(header) {
|
28
|
-
const offers = Object.create(null);
|
29
|
-
let params = Object.create(null);
|
30
|
-
let mustUnescape = false;
|
31
|
-
let isEscaping = false;
|
32
|
-
let inQuotes = false;
|
33
|
-
let extensionName;
|
34
|
-
let paramName;
|
35
|
-
let start = -1;
|
36
|
-
let code = -1;
|
37
|
-
let end = -1;
|
38
|
-
let i = 0;
|
39
|
-
|
40
|
-
for (; i < header.length; i++) {
|
41
|
-
code = header.charCodeAt(i);
|
42
|
-
|
43
|
-
if (extensionName === undefined) {
|
44
|
-
if (end === -1 && tokenChars[code] === 1) {
|
45
|
-
if (start === -1) start = i;
|
46
|
-
} else if (
|
47
|
-
i !== 0 &&
|
48
|
-
(code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
|
49
|
-
) {
|
50
|
-
if (end === -1 && start !== -1) end = i;
|
51
|
-
} else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
|
52
|
-
if (start === -1) {
|
53
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
54
|
-
}
|
55
|
-
|
56
|
-
if (end === -1) end = i;
|
57
|
-
const name = header.slice(start, end);
|
58
|
-
if (code === 0x2c) {
|
59
|
-
push(offers, name, params);
|
60
|
-
params = Object.create(null);
|
61
|
-
} else {
|
62
|
-
extensionName = name;
|
63
|
-
}
|
64
|
-
|
65
|
-
start = end = -1;
|
66
|
-
} else {
|
67
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
68
|
-
}
|
69
|
-
} else if (paramName === undefined) {
|
70
|
-
if (end === -1 && tokenChars[code] === 1) {
|
71
|
-
if (start === -1) start = i;
|
72
|
-
} else if (code === 0x20 || code === 0x09) {
|
73
|
-
if (end === -1 && start !== -1) end = i;
|
74
|
-
} else if (code === 0x3b || code === 0x2c) {
|
75
|
-
if (start === -1) {
|
76
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
77
|
-
}
|
78
|
-
|
79
|
-
if (end === -1) end = i;
|
80
|
-
push(params, header.slice(start, end), true);
|
81
|
-
if (code === 0x2c) {
|
82
|
-
push(offers, extensionName, params);
|
83
|
-
params = Object.create(null);
|
84
|
-
extensionName = undefined;
|
85
|
-
}
|
86
|
-
|
87
|
-
start = end = -1;
|
88
|
-
} else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {
|
89
|
-
paramName = header.slice(start, i);
|
90
|
-
start = end = -1;
|
91
|
-
} else {
|
92
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
93
|
-
}
|
94
|
-
} else {
|
95
|
-
//
|
96
|
-
// The value of a quoted-string after unescaping must conform to the
|
97
|
-
// token ABNF, so only token characters are valid.
|
98
|
-
// Ref: https://tools.ietf.org/html/rfc6455#section-9.1
|
99
|
-
//
|
100
|
-
if (isEscaping) {
|
101
|
-
if (tokenChars[code] !== 1) {
|
102
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
103
|
-
}
|
104
|
-
if (start === -1) start = i;
|
105
|
-
else if (!mustUnescape) mustUnescape = true;
|
106
|
-
isEscaping = false;
|
107
|
-
} else if (inQuotes) {
|
108
|
-
if (tokenChars[code] === 1) {
|
109
|
-
if (start === -1) start = i;
|
110
|
-
} else if (code === 0x22 /* '"' */ && start !== -1) {
|
111
|
-
inQuotes = false;
|
112
|
-
end = i;
|
113
|
-
} else if (code === 0x5c /* '\' */) {
|
114
|
-
isEscaping = true;
|
115
|
-
} else {
|
116
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
117
|
-
}
|
118
|
-
} else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
|
119
|
-
inQuotes = true;
|
120
|
-
} else if (end === -1 && tokenChars[code] === 1) {
|
121
|
-
if (start === -1) start = i;
|
122
|
-
} else if (start !== -1 && (code === 0x20 || code === 0x09)) {
|
123
|
-
if (end === -1) end = i;
|
124
|
-
} else if (code === 0x3b || code === 0x2c) {
|
125
|
-
if (start === -1) {
|
126
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
127
|
-
}
|
128
|
-
|
129
|
-
if (end === -1) end = i;
|
130
|
-
let value = header.slice(start, end);
|
131
|
-
if (mustUnescape) {
|
132
|
-
value = value.replace(/\\/g, '');
|
133
|
-
mustUnescape = false;
|
134
|
-
}
|
135
|
-
push(params, paramName, value);
|
136
|
-
if (code === 0x2c) {
|
137
|
-
push(offers, extensionName, params);
|
138
|
-
params = Object.create(null);
|
139
|
-
extensionName = undefined;
|
140
|
-
}
|
141
|
-
|
142
|
-
paramName = undefined;
|
143
|
-
start = end = -1;
|
144
|
-
} else {
|
145
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
146
|
-
}
|
147
|
-
}
|
148
|
-
}
|
149
|
-
|
150
|
-
if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
|
151
|
-
throw new SyntaxError('Unexpected end of input');
|
152
|
-
}
|
153
|
-
|
154
|
-
if (end === -1) end = i;
|
155
|
-
const token = header.slice(start, end);
|
156
|
-
if (extensionName === undefined) {
|
157
|
-
push(offers, token, params);
|
158
|
-
} else {
|
159
|
-
if (paramName === undefined) {
|
160
|
-
push(params, token, true);
|
161
|
-
} else if (mustUnescape) {
|
162
|
-
push(params, paramName, token.replace(/\\/g, ''));
|
163
|
-
} else {
|
164
|
-
push(params, paramName, token);
|
165
|
-
}
|
166
|
-
push(offers, extensionName, params);
|
167
|
-
}
|
168
|
-
|
169
|
-
return offers;
|
170
|
-
}
|
171
|
-
|
172
|
-
/**
|
173
|
-
* Builds the `Sec-WebSocket-Extensions` header field value.
|
174
|
-
*
|
175
|
-
* @param {Object} extensions The map of extensions and parameters to format
|
176
|
-
* @return {String} A string representing the given object
|
177
|
-
* @public
|
178
|
-
*/
|
179
|
-
function format(extensions) {
|
180
|
-
return Object.keys(extensions)
|
181
|
-
.map((extension) => {
|
182
|
-
let configurations = extensions[extension];
|
183
|
-
if (!Array.isArray(configurations)) configurations = [configurations];
|
184
|
-
return configurations
|
185
|
-
.map((params) => {
|
186
|
-
return [extension]
|
187
|
-
.concat(
|
188
|
-
Object.keys(params).map((k) => {
|
189
|
-
let values = params[k];
|
190
|
-
if (!Array.isArray(values)) values = [values];
|
191
|
-
return values
|
192
|
-
.map((v) => (v === true ? k : `${k}=${v}`))
|
193
|
-
.join('; ');
|
194
|
-
})
|
195
|
-
)
|
196
|
-
.join('; ');
|
197
|
-
})
|
198
|
-
.join(', ');
|
199
|
-
})
|
200
|
-
.join(', ');
|
201
|
-
}
|
202
|
-
|
203
|
-
module.exports = { format, parse };
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const { tokenChars } = require('./validation');
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Adds an offer to the map of extension offers or a parameter to the map of
|
7
|
+
* parameters.
|
8
|
+
*
|
9
|
+
* @param {Object} dest The map of extension offers or parameters
|
10
|
+
* @param {String} name The extension or parameter name
|
11
|
+
* @param {(Object|Boolean|String)} elem The extension parameters or the
|
12
|
+
* parameter value
|
13
|
+
* @private
|
14
|
+
*/
|
15
|
+
function push(dest, name, elem) {
|
16
|
+
if (dest[name] === undefined) dest[name] = [elem];
|
17
|
+
else dest[name].push(elem);
|
18
|
+
}
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Parses the `Sec-WebSocket-Extensions` header into an object.
|
22
|
+
*
|
23
|
+
* @param {String} header The field value of the header
|
24
|
+
* @return {Object} The parsed object
|
25
|
+
* @public
|
26
|
+
*/
|
27
|
+
function parse(header) {
|
28
|
+
const offers = Object.create(null);
|
29
|
+
let params = Object.create(null);
|
30
|
+
let mustUnescape = false;
|
31
|
+
let isEscaping = false;
|
32
|
+
let inQuotes = false;
|
33
|
+
let extensionName;
|
34
|
+
let paramName;
|
35
|
+
let start = -1;
|
36
|
+
let code = -1;
|
37
|
+
let end = -1;
|
38
|
+
let i = 0;
|
39
|
+
|
40
|
+
for (; i < header.length; i++) {
|
41
|
+
code = header.charCodeAt(i);
|
42
|
+
|
43
|
+
if (extensionName === undefined) {
|
44
|
+
if (end === -1 && tokenChars[code] === 1) {
|
45
|
+
if (start === -1) start = i;
|
46
|
+
} else if (
|
47
|
+
i !== 0 &&
|
48
|
+
(code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
|
49
|
+
) {
|
50
|
+
if (end === -1 && start !== -1) end = i;
|
51
|
+
} else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
|
52
|
+
if (start === -1) {
|
53
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
54
|
+
}
|
55
|
+
|
56
|
+
if (end === -1) end = i;
|
57
|
+
const name = header.slice(start, end);
|
58
|
+
if (code === 0x2c) {
|
59
|
+
push(offers, name, params);
|
60
|
+
params = Object.create(null);
|
61
|
+
} else {
|
62
|
+
extensionName = name;
|
63
|
+
}
|
64
|
+
|
65
|
+
start = end = -1;
|
66
|
+
} else {
|
67
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
68
|
+
}
|
69
|
+
} else if (paramName === undefined) {
|
70
|
+
if (end === -1 && tokenChars[code] === 1) {
|
71
|
+
if (start === -1) start = i;
|
72
|
+
} else if (code === 0x20 || code === 0x09) {
|
73
|
+
if (end === -1 && start !== -1) end = i;
|
74
|
+
} else if (code === 0x3b || code === 0x2c) {
|
75
|
+
if (start === -1) {
|
76
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
77
|
+
}
|
78
|
+
|
79
|
+
if (end === -1) end = i;
|
80
|
+
push(params, header.slice(start, end), true);
|
81
|
+
if (code === 0x2c) {
|
82
|
+
push(offers, extensionName, params);
|
83
|
+
params = Object.create(null);
|
84
|
+
extensionName = undefined;
|
85
|
+
}
|
86
|
+
|
87
|
+
start = end = -1;
|
88
|
+
} else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {
|
89
|
+
paramName = header.slice(start, i);
|
90
|
+
start = end = -1;
|
91
|
+
} else {
|
92
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
93
|
+
}
|
94
|
+
} else {
|
95
|
+
//
|
96
|
+
// The value of a quoted-string after unescaping must conform to the
|
97
|
+
// token ABNF, so only token characters are valid.
|
98
|
+
// Ref: https://tools.ietf.org/html/rfc6455#section-9.1
|
99
|
+
//
|
100
|
+
if (isEscaping) {
|
101
|
+
if (tokenChars[code] !== 1) {
|
102
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
103
|
+
}
|
104
|
+
if (start === -1) start = i;
|
105
|
+
else if (!mustUnescape) mustUnescape = true;
|
106
|
+
isEscaping = false;
|
107
|
+
} else if (inQuotes) {
|
108
|
+
if (tokenChars[code] === 1) {
|
109
|
+
if (start === -1) start = i;
|
110
|
+
} else if (code === 0x22 /* '"' */ && start !== -1) {
|
111
|
+
inQuotes = false;
|
112
|
+
end = i;
|
113
|
+
} else if (code === 0x5c /* '\' */) {
|
114
|
+
isEscaping = true;
|
115
|
+
} else {
|
116
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
117
|
+
}
|
118
|
+
} else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
|
119
|
+
inQuotes = true;
|
120
|
+
} else if (end === -1 && tokenChars[code] === 1) {
|
121
|
+
if (start === -1) start = i;
|
122
|
+
} else if (start !== -1 && (code === 0x20 || code === 0x09)) {
|
123
|
+
if (end === -1) end = i;
|
124
|
+
} else if (code === 0x3b || code === 0x2c) {
|
125
|
+
if (start === -1) {
|
126
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
127
|
+
}
|
128
|
+
|
129
|
+
if (end === -1) end = i;
|
130
|
+
let value = header.slice(start, end);
|
131
|
+
if (mustUnescape) {
|
132
|
+
value = value.replace(/\\/g, '');
|
133
|
+
mustUnescape = false;
|
134
|
+
}
|
135
|
+
push(params, paramName, value);
|
136
|
+
if (code === 0x2c) {
|
137
|
+
push(offers, extensionName, params);
|
138
|
+
params = Object.create(null);
|
139
|
+
extensionName = undefined;
|
140
|
+
}
|
141
|
+
|
142
|
+
paramName = undefined;
|
143
|
+
start = end = -1;
|
144
|
+
} else {
|
145
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
|
151
|
+
throw new SyntaxError('Unexpected end of input');
|
152
|
+
}
|
153
|
+
|
154
|
+
if (end === -1) end = i;
|
155
|
+
const token = header.slice(start, end);
|
156
|
+
if (extensionName === undefined) {
|
157
|
+
push(offers, token, params);
|
158
|
+
} else {
|
159
|
+
if (paramName === undefined) {
|
160
|
+
push(params, token, true);
|
161
|
+
} else if (mustUnescape) {
|
162
|
+
push(params, paramName, token.replace(/\\/g, ''));
|
163
|
+
} else {
|
164
|
+
push(params, paramName, token);
|
165
|
+
}
|
166
|
+
push(offers, extensionName, params);
|
167
|
+
}
|
168
|
+
|
169
|
+
return offers;
|
170
|
+
}
|
171
|
+
|
172
|
+
/**
|
173
|
+
* Builds the `Sec-WebSocket-Extensions` header field value.
|
174
|
+
*
|
175
|
+
* @param {Object} extensions The map of extensions and parameters to format
|
176
|
+
* @return {String} A string representing the given object
|
177
|
+
* @public
|
178
|
+
*/
|
179
|
+
function format(extensions) {
|
180
|
+
return Object.keys(extensions)
|
181
|
+
.map((extension) => {
|
182
|
+
let configurations = extensions[extension];
|
183
|
+
if (!Array.isArray(configurations)) configurations = [configurations];
|
184
|
+
return configurations
|
185
|
+
.map((params) => {
|
186
|
+
return [extension]
|
187
|
+
.concat(
|
188
|
+
Object.keys(params).map((k) => {
|
189
|
+
let values = params[k];
|
190
|
+
if (!Array.isArray(values)) values = [values];
|
191
|
+
return values
|
192
|
+
.map((v) => (v === true ? k : `${k}=${v}`))
|
193
|
+
.join('; ');
|
194
|
+
})
|
195
|
+
)
|
196
|
+
.join('; ');
|
197
|
+
})
|
198
|
+
.join(', ');
|
199
|
+
})
|
200
|
+
.join(', ');
|
201
|
+
}
|
202
|
+
|
203
|
+
module.exports = { format, parse };
|
@@ -1,55 +1,55 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const kDone = Symbol('kDone');
|
4
|
-
const kRun = Symbol('kRun');
|
5
|
-
|
6
|
-
/**
|
7
|
-
* A very simple job queue with adjustable concurrency. Adapted from
|
8
|
-
* https://github.com/STRML/async-limiter
|
9
|
-
*/
|
10
|
-
class Limiter {
|
11
|
-
/**
|
12
|
-
* Creates a new `Limiter`.
|
13
|
-
*
|
14
|
-
* @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
|
15
|
-
* to run concurrently
|
16
|
-
*/
|
17
|
-
constructor(concurrency) {
|
18
|
-
this[kDone] = () => {
|
19
|
-
this.pending--;
|
20
|
-
this[kRun]();
|
21
|
-
};
|
22
|
-
this.concurrency = concurrency || Infinity;
|
23
|
-
this.jobs = [];
|
24
|
-
this.pending = 0;
|
25
|
-
}
|
26
|
-
|
27
|
-
/**
|
28
|
-
* Adds a job to the queue.
|
29
|
-
*
|
30
|
-
* @param {Function} job The job to run
|
31
|
-
* @public
|
32
|
-
*/
|
33
|
-
add(job) {
|
34
|
-
this.jobs.push(job);
|
35
|
-
this[kRun]();
|
36
|
-
}
|
37
|
-
|
38
|
-
/**
|
39
|
-
* Removes a job from the queue and runs it if possible.
|
40
|
-
*
|
41
|
-
* @private
|
42
|
-
*/
|
43
|
-
[kRun]() {
|
44
|
-
if (this.pending === this.concurrency) return;
|
45
|
-
|
46
|
-
if (this.jobs.length) {
|
47
|
-
const job = this.jobs.shift();
|
48
|
-
|
49
|
-
this.pending++;
|
50
|
-
job(this[kDone]);
|
51
|
-
}
|
52
|
-
}
|
53
|
-
}
|
54
|
-
|
55
|
-
module.exports = Limiter;
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const kDone = Symbol('kDone');
|
4
|
+
const kRun = Symbol('kRun');
|
5
|
+
|
6
|
+
/**
|
7
|
+
* A very simple job queue with adjustable concurrency. Adapted from
|
8
|
+
* https://github.com/STRML/async-limiter
|
9
|
+
*/
|
10
|
+
class Limiter {
|
11
|
+
/**
|
12
|
+
* Creates a new `Limiter`.
|
13
|
+
*
|
14
|
+
* @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
|
15
|
+
* to run concurrently
|
16
|
+
*/
|
17
|
+
constructor(concurrency) {
|
18
|
+
this[kDone] = () => {
|
19
|
+
this.pending--;
|
20
|
+
this[kRun]();
|
21
|
+
};
|
22
|
+
this.concurrency = concurrency || Infinity;
|
23
|
+
this.jobs = [];
|
24
|
+
this.pending = 0;
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Adds a job to the queue.
|
29
|
+
*
|
30
|
+
* @param {Function} job The job to run
|
31
|
+
* @public
|
32
|
+
*/
|
33
|
+
add(job) {
|
34
|
+
this.jobs.push(job);
|
35
|
+
this[kRun]();
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Removes a job from the queue and runs it if possible.
|
40
|
+
*
|
41
|
+
* @private
|
42
|
+
*/
|
43
|
+
[kRun]() {
|
44
|
+
if (this.pending === this.concurrency) return;
|
45
|
+
|
46
|
+
if (this.jobs.length) {
|
47
|
+
const job = this.jobs.shift();
|
48
|
+
|
49
|
+
this.pending++;
|
50
|
+
job(this[kDone]);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
module.exports = Limiter;
|