bare-ws 1.2.1 → 1.3.1
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/lib/constants.js +3 -1
- package/lib/errors.js +16 -0
- package/lib/frame.js +2 -2
- package/lib/socket.js +67 -11
- package/package.json +3 -3
package/lib/constants.js
CHANGED
package/lib/errors.js
CHANGED
|
@@ -15,6 +15,22 @@ module.exports = class WebSocketError extends Error {
|
|
|
15
15
|
return 'WebSocketError'
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
static NOT_CONNECTED (msg = 'Socket is not connected') {
|
|
19
|
+
return new WebSocketError(msg, 'NOT_CONNECTED', 0, WebSocketError.NOT_CONNECTED)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static UNEXPECTED_RSV1 (msg = 'RSV1 must be unset') {
|
|
23
|
+
return new WebSocketError(msg, 'UNEXPECTED_RSV1', status.PROTOCOL_ERROR, WebSocketError.UNEXPECTED_RSV1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static UNEXPECTED_RSV2 (msg = 'RSV2 must be unset') {
|
|
27
|
+
return new WebSocketError(msg, 'UNEXPECTED_RSV2', status.PROTOCOL_ERROR, WebSocketError.UNEXPECTED_RSV2)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static UNEXPECTED_RSV3 (msg = 'RSV3 must be unset') {
|
|
31
|
+
return new WebSocketError(msg, 'UNEXPECTED_RSV3', status.PROTOCOL_ERROR, WebSocketError.UNEXPECTED_RSV3)
|
|
32
|
+
}
|
|
33
|
+
|
|
18
34
|
static EXPECTED_MASK (msg = 'MASK must be set') {
|
|
19
35
|
return new WebSocketError(msg, 'EXPECTED_MASK', status.PROTOCOL_ERROR, WebSocketError.EXPECTED_MASK)
|
|
20
36
|
}
|
package/lib/frame.js
CHANGED
|
@@ -58,7 +58,7 @@ exports.preencode = function preencode (state, f) {
|
|
|
58
58
|
|
|
59
59
|
if (length <= 0x7d) i++
|
|
60
60
|
else {
|
|
61
|
-
if (length
|
|
61
|
+
if (length <= 0xffff) i += 3
|
|
62
62
|
else i += 9
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -91,7 +91,7 @@ exports.encode = function encode (state, f) {
|
|
|
91
91
|
|
|
92
92
|
if (length <= 0x7d) b[i++] |= length
|
|
93
93
|
else {
|
|
94
|
-
if (length
|
|
94
|
+
if (length <= 0xffff) {
|
|
95
95
|
b[i++] |= 0x7e
|
|
96
96
|
|
|
97
97
|
v.setUint16(i, length, false)
|
package/lib/socket.js
CHANGED
|
@@ -12,7 +12,7 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
12
12
|
constructor (url, opts = {}) {
|
|
13
13
|
if (typeof url === 'string') url = new URL(url)
|
|
14
14
|
|
|
15
|
-
if (
|
|
15
|
+
if (isURL(url)) {
|
|
16
16
|
opts = opts ? { ...opts } : {}
|
|
17
17
|
|
|
18
18
|
opts.host = url.hostname
|
|
@@ -21,6 +21,10 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
21
21
|
opts.secure = url.protocol === 'https:' || url.protocol === 'wss:'
|
|
22
22
|
} else {
|
|
23
23
|
opts = url ? { ...url } : {}
|
|
24
|
+
|
|
25
|
+
// For Node.js compatibility
|
|
26
|
+
opts.host = opts.hostname || opts.host
|
|
27
|
+
opts.port = typeof opts.port === 'string' ? parseInt(opts.port, 10) : opts.port
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
const {
|
|
@@ -28,7 +32,7 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
28
32
|
socket = null
|
|
29
33
|
} = opts
|
|
30
34
|
|
|
31
|
-
super()
|
|
35
|
+
super({ eagerOpen: true })
|
|
32
36
|
|
|
33
37
|
this._socket = null
|
|
34
38
|
this._isServer = isServer
|
|
@@ -44,6 +48,22 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
44
48
|
else this._connect(opts)
|
|
45
49
|
}
|
|
46
50
|
|
|
51
|
+
ping (data) {
|
|
52
|
+
if (this._socket === null) throw errors.NOT_CONNECTED()
|
|
53
|
+
|
|
54
|
+
if (typeof data === 'string') data = Buffer.from(data)
|
|
55
|
+
|
|
56
|
+
this._socket.write(new Frame(opcode.PING, data, { mask: this._mask }).toBuffer())
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
pong (data) {
|
|
60
|
+
if (this._socket === null) throw errors.NOT_CONNECTED()
|
|
61
|
+
|
|
62
|
+
if (typeof data === 'string') data = Buffer.from(data)
|
|
63
|
+
|
|
64
|
+
this._socket.write(new Frame(opcode.PONG, data, { mask: this._mask }).toBuffer())
|
|
65
|
+
}
|
|
66
|
+
|
|
47
67
|
_attach (socket) {
|
|
48
68
|
this._socket = socket
|
|
49
69
|
|
|
@@ -85,31 +105,46 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
85
105
|
while (this._buffer !== null) {
|
|
86
106
|
const state = { start: 0, end: this._buffer.length, buffer: this._buffer }
|
|
87
107
|
|
|
88
|
-
|
|
108
|
+
let frame
|
|
109
|
+
try {
|
|
110
|
+
frame = Frame.decode(state)
|
|
111
|
+
} catch (err) {
|
|
112
|
+
return this.destroy(err)
|
|
113
|
+
}
|
|
89
114
|
|
|
90
115
|
if (frame === null) return
|
|
91
116
|
|
|
92
117
|
this._buffer = state.start === state.end ? null : this._buffer.subarray(state.start)
|
|
93
118
|
|
|
94
|
-
|
|
119
|
+
try {
|
|
120
|
+
this._onframe(frame)
|
|
121
|
+
} catch (err) {
|
|
122
|
+
return this.destroy(err)
|
|
123
|
+
}
|
|
95
124
|
}
|
|
96
125
|
}
|
|
97
126
|
|
|
98
127
|
_onframe (frame) {
|
|
128
|
+
if (frame.rsv1) throw errors.UNEXPECTED_RSV1()
|
|
129
|
+
|
|
130
|
+
if (frame.rsv2) throw errors.UNEXPECTED_RSV2()
|
|
131
|
+
|
|
132
|
+
if (frame.rsv3) throw errors.UNEXPECTED_RSV3()
|
|
133
|
+
|
|
99
134
|
if (frame.payload.length > 0 && !frame.mask === this._isServer) {
|
|
100
|
-
|
|
135
|
+
throw this._isServer ? errors.EXPECTED_MASK() : errors.UNEXPECTED_MASK()
|
|
101
136
|
}
|
|
102
137
|
|
|
103
138
|
if (frame.fin === false) {
|
|
104
139
|
if (this._fragments.push(frame) === 1) { // First frame
|
|
105
|
-
if (frame.opcode === opcode.CONTINUATION)
|
|
140
|
+
if (frame.opcode === opcode.CONTINUATION) throw errors.UNEXPECTED_CONTINUATION()
|
|
106
141
|
|
|
107
|
-
if (frame.opcode >= opcode.CLOSE)
|
|
142
|
+
if (frame.opcode >= opcode.CLOSE) throw errors.UNEXPECTED_CONTROL()
|
|
108
143
|
|
|
109
144
|
return
|
|
110
145
|
}
|
|
111
146
|
|
|
112
|
-
if (frame.opcode !== opcode.CONTINUATION)
|
|
147
|
+
if (frame.opcode !== opcode.CONTINUATION) throw errors.EXPECTED_CONTINUATION()
|
|
113
148
|
|
|
114
149
|
return
|
|
115
150
|
}
|
|
@@ -120,8 +155,17 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
120
155
|
this.end()
|
|
121
156
|
return
|
|
122
157
|
|
|
158
|
+
case opcode.PING:
|
|
159
|
+
this.pong(frame.payload)
|
|
160
|
+
this.emit('ping', frame.payload)
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
case opcode.PONG:
|
|
164
|
+
this.emit('pong', frame.payload)
|
|
165
|
+
return
|
|
166
|
+
|
|
123
167
|
case opcode.CONTINUATION: {
|
|
124
|
-
if (this._fragments.length === 0)
|
|
168
|
+
if (this._fragments.length === 0) throw errors.UNEXPECTED_CONTINUATION()
|
|
125
169
|
|
|
126
170
|
frame.opcode = this._fragments[0].opcode
|
|
127
171
|
|
|
@@ -137,7 +181,7 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
137
181
|
}
|
|
138
182
|
|
|
139
183
|
default:
|
|
140
|
-
if (this._fragments.length > 0)
|
|
184
|
+
if (this._fragments.length > 0) throw errors.EXPECTED_CONTINUATION()
|
|
141
185
|
}
|
|
142
186
|
|
|
143
187
|
switch (frame.opcode) {
|
|
@@ -147,7 +191,7 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
147
191
|
break
|
|
148
192
|
|
|
149
193
|
default:
|
|
150
|
-
|
|
194
|
+
throw errors.INVALID_OPCODE()
|
|
151
195
|
}
|
|
152
196
|
}
|
|
153
197
|
|
|
@@ -230,3 +274,15 @@ function defaultPort (url) {
|
|
|
230
274
|
|
|
231
275
|
return null
|
|
232
276
|
}
|
|
277
|
+
|
|
278
|
+
// https://url.spec.whatwg.org/#api
|
|
279
|
+
function isURL (url) {
|
|
280
|
+
return (
|
|
281
|
+
url !== null &&
|
|
282
|
+
typeof url === 'object' &&
|
|
283
|
+
typeof url.protocol === 'string' &&
|
|
284
|
+
typeof url.hostname === 'string' &&
|
|
285
|
+
typeof url.pathname === 'string' &&
|
|
286
|
+
typeof url.search === 'string'
|
|
287
|
+
)
|
|
288
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bare-ws",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "WebSocket library for JavaScript",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"bare-crypto": "^1.2.0",
|
|
30
30
|
"bare-events": "^2.3.1",
|
|
31
|
-
"bare-http1": "^3.
|
|
32
|
-
"bare-https": "^1.
|
|
31
|
+
"bare-http1": "^3.8.0",
|
|
32
|
+
"bare-https": "^1.3.0",
|
|
33
33
|
"bare-stream": "^2.1.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|