@soundworks/core 4.0.0-alpha.22 → 4.0.0-alpha.23
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/CHANGELOG.md +9 -3
- package/package.json +13 -14
- package/src/client/Client.js +224 -188
- package/src/client/Socket.js +74 -241
- package/src/common/constants.js +0 -1
- package/src/common/logger.js +15 -0
- package/src/common/sockets-utils.js +0 -63
- package/src/common/version.js +1 -1
- package/src/server/Plugin.js +22 -10
- package/src/server/Server.js +22 -46
- package/src/server/Socket.js +126 -250
- package/src/server/Sockets.js +103 -127
- package/src/server/audit-network-latency.worker.js +4 -3
- package/types/client/Client.d.ts +41 -8
- package/types/client/Client.d.ts.map +1 -1
- package/types/client/Context.d.ts +40 -14
- package/types/client/Context.d.ts.map +1 -1
- package/types/client/Plugin.d.ts +42 -41
- package/types/client/Plugin.d.ts.map +1 -1
- package/types/client/PluginManager.d.ts +26 -11
- package/types/client/PluginManager.d.ts.map +1 -1
- package/types/client/SharedState.d.ts +1 -1
- package/types/client/SharedState.d.ts.map +1 -1
- package/types/client/SharedStateCollection.d.ts +41 -0
- package/types/client/SharedStateCollection.d.ts.map +1 -0
- package/types/client/Socket.d.ts +41 -30
- package/types/client/Socket.d.ts.map +1 -1
- package/types/client/StateManager.d.ts +1 -1
- package/types/client/StateManager.d.ts.map +1 -1
- package/types/client/index.d.ts +0 -8
- package/types/common/BasePlugin.d.ts +24 -19
- package/types/common/BasePlugin.d.ts.map +1 -1
- package/types/common/BasePluginManager.d.ts +17 -5
- package/types/common/BasePluginManager.d.ts.map +1 -1
- package/types/common/BaseSharedState.d.ts +100 -29
- package/types/common/BaseSharedState.d.ts.map +1 -1
- package/types/common/BaseSharedStateCollection.d.ts +183 -0
- package/types/common/BaseSharedStateCollection.d.ts.map +1 -0
- package/types/common/BaseStateManager.d.ts +83 -18
- package/types/common/BaseStateManager.d.ts.map +1 -1
- package/types/common/BatchedTransport.d.ts +21 -0
- package/types/common/BatchedTransport.d.ts.map +1 -0
- package/types/common/ParameterBag.d.ts +61 -40
- package/types/common/ParameterBag.d.ts.map +1 -1
- package/types/common/PromiseStore.d.ts +11 -0
- package/types/common/PromiseStore.d.ts.map +1 -0
- package/types/common/SharedStatePrivate.d.ts +4 -3
- package/types/common/SharedStatePrivate.d.ts.map +1 -1
- package/types/common/constants.d.ts +10 -1
- package/types/common/constants.d.ts.map +1 -1
- package/types/common/logger.d.ts +1 -1
- package/types/common/sockets-utils.d.ts.map +1 -1
- package/types/common/version.d.ts +3 -0
- package/types/common/version.d.ts.map +1 -0
- package/types/server/Client.d.ts +5 -0
- package/types/server/Client.d.ts.map +1 -1
- package/types/server/Context.d.ts +162 -22
- package/types/server/Context.d.ts.map +1 -1
- package/types/server/ContextManager.d.ts +4 -4
- package/types/server/ContextManager.d.ts.map +1 -1
- package/types/server/Plugin.d.ts +56 -55
- package/types/server/Plugin.d.ts.map +1 -1
- package/types/server/PluginManager.d.ts +26 -6
- package/types/server/PluginManager.d.ts.map +1 -1
- package/types/server/Server.d.ts +207 -70
- package/types/server/Server.d.ts.map +1 -1
- package/types/server/SharedState.d.ts +1 -1
- package/types/server/SharedState.d.ts.map +1 -1
- package/types/server/SharedStateCollection.d.ts +41 -0
- package/types/server/SharedStateCollection.d.ts.map +1 -0
- package/types/server/Socket.d.ts +93 -57
- package/types/server/Socket.d.ts.map +1 -1
- package/types/server/Sockets.d.ts +32 -25
- package/types/server/Sockets.d.ts.map +1 -1
- package/types/server/StateManager.d.ts +242 -27
- package/types/server/StateManager.d.ts.map +1 -1
- package/types/server/audit-network-latency.worker.d.ts +2 -1
- package/types/server/audit-schema.d.ts +8 -8
- package/types/server/crypto.d.ts +3 -0
- package/types/server/crypto.d.ts.map +1 -0
- package/types/server/index.d.ts +0 -4
- package/types/common/promise-store.d.ts +0 -4
- package/types/common/promise-store.d.ts.map +0 -1
- package/types/common/utils.d.ts +0 -5
- package/types/common/utils.d.ts.map +0 -1
package/src/client/Socket.js
CHANGED
|
@@ -2,34 +2,16 @@ import { isBrowser } from '@ircam/sc-utils';
|
|
|
2
2
|
import WebSocket from 'isomorphic-ws';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
PING_INTERVAL,
|
|
6
|
-
PING_LATENCY_TOLERANCE,
|
|
7
5
|
PING_MESSAGE,
|
|
8
6
|
PONG_MESSAGE,
|
|
9
7
|
} from '../common/constants.js';
|
|
10
8
|
import logger from '../common/logger.js';
|
|
11
9
|
import {
|
|
12
|
-
packBinaryMessage,
|
|
13
|
-
unpackBinaryMessage,
|
|
14
10
|
packStringMessage,
|
|
15
11
|
unpackStringMessage,
|
|
16
12
|
} from '../common/sockets-utils.js';
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
// `close`:
|
|
21
|
-
// Fired when a connection with a websocket is closed.
|
|
22
|
-
// Also available via the onclose property
|
|
23
|
-
// `error`:
|
|
24
|
-
// Fired when a connection with a websocket has been closed because of an error,
|
|
25
|
-
// such as whensome data couldn't be sent.
|
|
26
|
-
// Also available via the onerror property.
|
|
27
|
-
// `message`:
|
|
28
|
-
// Fired when data is received through a websocket.
|
|
29
|
-
// Also available via the onmessage property.
|
|
30
|
-
// `open`:
|
|
31
|
-
// Fired when a connection with a websocket is opened.
|
|
32
|
-
// Also available via the onopen property.
|
|
14
|
+
export const kSocketTerminate = Symbol('soundworks:socket-terminate');
|
|
33
15
|
|
|
34
16
|
/**
|
|
35
17
|
* The Socket class is a simple publish / subscribe wrapper built on top of the
|
|
@@ -53,26 +35,10 @@ import {
|
|
|
53
35
|
* @hideconstructor
|
|
54
36
|
*/
|
|
55
37
|
class Socket {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* @private
|
|
61
|
-
*/
|
|
62
|
-
this.ws = null;
|
|
63
|
-
/**
|
|
64
|
-
* WebSocket instance configured with `binaryType = 'arraybuffer'`.
|
|
65
|
-
*
|
|
66
|
-
* @private
|
|
67
|
-
*/
|
|
68
|
-
this.binaryWs = null;
|
|
69
|
-
/** @private */
|
|
70
|
-
this._stringListeners = new Map();
|
|
71
|
-
/** @private */
|
|
72
|
-
this._binaryListeners = new Map();
|
|
73
|
-
/** @private */
|
|
74
|
-
this._heartbeatId = null;
|
|
75
|
-
}
|
|
38
|
+
#socket = null;
|
|
39
|
+
#listeners = new Map();
|
|
40
|
+
|
|
41
|
+
constructor() {}
|
|
76
42
|
|
|
77
43
|
/**
|
|
78
44
|
* Initialize a websocket connection with the server. Automatically called
|
|
@@ -80,20 +46,10 @@ class Socket {
|
|
|
80
46
|
*
|
|
81
47
|
* @param {string} role - Role of the client (see {@link client.Client#role})
|
|
82
48
|
* @param {object} config - Configuration of the sockets
|
|
83
|
-
* @
|
|
84
|
-
* @ignore
|
|
49
|
+
* @private
|
|
85
50
|
*/
|
|
86
51
|
async init(role, config) {
|
|
87
|
-
// unique key that allows to associate the two sockets to the same client.
|
|
88
|
-
// note: the key is only used to pair to two sockets, so its usage is very
|
|
89
|
-
// limited in time therefore a random number should hopefully be sufficient.
|
|
90
|
-
const key = (Math.random() + '').replace(/^0\./, '');
|
|
91
|
-
|
|
92
|
-
// open web sockets
|
|
93
52
|
let { path } = config.env.websockets;
|
|
94
|
-
|
|
95
|
-
// @note: keep this check
|
|
96
|
-
// backward compatibility w/ assetsDomain and websocket old config way
|
|
97
53
|
// cf. https://github.com/collective-soundworks/soundworks/issues/35
|
|
98
54
|
if (config.env.subpath) {
|
|
99
55
|
path = `${config.env.subpath}/${path}`;
|
|
@@ -121,77 +77,66 @@ class Socket {
|
|
|
121
77
|
};
|
|
122
78
|
}
|
|
123
79
|
|
|
124
|
-
|
|
125
|
-
let queryParams = `role=${role}&key=${key}`;
|
|
80
|
+
let queryParams = `role=${role}`;
|
|
126
81
|
|
|
127
82
|
if (config.token) {
|
|
128
83
|
queryParams += `&token=${config.token}`;
|
|
129
84
|
}
|
|
130
85
|
|
|
86
|
+
const url = `${protocol}//${serverAddress}:${port}/${path}?${queryParams}`;
|
|
87
|
+
|
|
131
88
|
// ----------------------------------------------------------
|
|
132
|
-
//
|
|
89
|
+
// Init socket
|
|
133
90
|
// ----------------------------------------------------------
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
await new Promise(resolve => {
|
|
91
|
+
return new Promise(resolve => {
|
|
137
92
|
let connectionRefusedLogged = false;
|
|
138
93
|
|
|
139
94
|
const trySocket = async () => {
|
|
140
|
-
const ws = new WebSocket(
|
|
95
|
+
const ws = new WebSocket(url, webSocketOptions);
|
|
141
96
|
|
|
142
|
-
ws.addEventListener('open',
|
|
97
|
+
ws.addEventListener('open', openEvent => {
|
|
143
98
|
// parse incoming messages for pubsub
|
|
144
|
-
this
|
|
99
|
+
this.#socket = ws;
|
|
145
100
|
|
|
146
|
-
|
|
147
|
-
// broken but not detected by the client
|
|
148
|
-
// @note (2024-04): unstable and creates more issues than it solves, disable
|
|
149
|
-
// for now and review later
|
|
150
|
-
// const heartbeat = () => {
|
|
151
|
-
// clearTimeout(this._heartbeatId);
|
|
152
|
-
|
|
153
|
-
// this._heartbeatId = setTimeout(() => {
|
|
154
|
-
// console.log('> HEARTBEAT missed, closing...');
|
|
155
|
-
// this.terminate();
|
|
156
|
-
// }, PING_INTERVAL + PING_LATENCY_TOLERANCE);
|
|
157
|
-
// };
|
|
158
|
-
|
|
159
|
-
// heartbeat();
|
|
160
|
-
|
|
161
|
-
this.ws.addEventListener('message', e => {
|
|
101
|
+
this.#socket.addEventListener('message', e => {
|
|
162
102
|
if (e.data === PING_MESSAGE) {
|
|
163
103
|
// heartbeat();
|
|
164
|
-
this.
|
|
104
|
+
this.#socket.send(PONG_MESSAGE);
|
|
165
105
|
// do not propagate ping / pong messages
|
|
166
106
|
return;
|
|
167
107
|
}
|
|
168
108
|
|
|
169
109
|
const [channel, args] = unpackStringMessage(e.data);
|
|
170
|
-
this
|
|
110
|
+
this.#dispatchEvent(channel, ...args);
|
|
171
111
|
});
|
|
172
112
|
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
113
|
+
// propagate "native" events
|
|
114
|
+
// `close`:
|
|
115
|
+
// Fired when a connection with a websocket is closed.
|
|
116
|
+
// Also available via the onclose property
|
|
117
|
+
// `error`:
|
|
118
|
+
// Fired when a connection with a websocket has been closed because of an error,
|
|
119
|
+
// such as whensome data couldn't be sent.
|
|
120
|
+
// Also available via the onerror property.
|
|
121
|
+
// `message`:
|
|
122
|
+
// Fired when data is received through a websocket.
|
|
123
|
+
// Also available via the onmessage property.
|
|
124
|
+
// `open`:
|
|
125
|
+
// Fired when a connection with a websocket is opened.
|
|
126
|
+
// Also available via the onopen property.
|
|
127
|
+
[
|
|
128
|
+
'close',
|
|
129
|
+
'error',
|
|
130
|
+
'upgrade',
|
|
131
|
+
'message',
|
|
132
|
+
].forEach(eventName => {
|
|
133
|
+
this.#socket.addEventListener(eventName, e => {
|
|
134
|
+
this.#dispatchEvent(eventName, e);
|
|
135
|
+
});
|
|
136
|
+
})
|
|
191
137
|
|
|
192
138
|
// forward open event
|
|
193
|
-
this
|
|
194
|
-
|
|
139
|
+
this.#dispatchEvent('open', openEvent);
|
|
195
140
|
// continue with raw socket
|
|
196
141
|
resolve();
|
|
197
142
|
});
|
|
@@ -207,11 +152,13 @@ class Socket {
|
|
|
207
152
|
|
|
208
153
|
// for node clients, retry connection
|
|
209
154
|
if (e.error && e.error.code === 'ECONNREFUSED') {
|
|
155
|
+
// we want to log the warning just once
|
|
210
156
|
if (!connectionRefusedLogged) {
|
|
211
157
|
logger.log('[soundworks.Socket] Connection refused, waiting for the server to start');
|
|
212
158
|
connectionRefusedLogged = true;
|
|
213
159
|
}
|
|
214
160
|
|
|
161
|
+
// retry in 1 second
|
|
215
162
|
setTimeout(trySocket, 1000);
|
|
216
163
|
}
|
|
217
164
|
}
|
|
@@ -220,39 +167,6 @@ class Socket {
|
|
|
220
167
|
|
|
221
168
|
trySocket();
|
|
222
169
|
});
|
|
223
|
-
|
|
224
|
-
// ----------------------------------------------------------
|
|
225
|
-
// init binary socket
|
|
226
|
-
// ----------------------------------------------------------
|
|
227
|
-
const binarySocketUrl = `${url}?binary=1&${queryParams}`;
|
|
228
|
-
|
|
229
|
-
await new Promise(resolve => {
|
|
230
|
-
const ws = new WebSocket(binarySocketUrl, webSocketOptions);
|
|
231
|
-
ws.binaryType = 'arraybuffer';
|
|
232
|
-
|
|
233
|
-
ws.addEventListener('open', connectEvent => {
|
|
234
|
-
// parse incoming messages for pubsub
|
|
235
|
-
this.binaryWs = ws;
|
|
236
|
-
this.binaryWs.addEventListener('message', e => {
|
|
237
|
-
const [channel, data] = unpackBinaryMessage(e.data);
|
|
238
|
-
this._emit(true, channel, data);
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
// broadcast all `WebSocket` native events
|
|
242
|
-
['close', 'error', 'upgrade', 'message'].forEach(eventName => {
|
|
243
|
-
this.binaryWs.addEventListener(eventName, (e) => {
|
|
244
|
-
this._emit(true, eventName, e);
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
// forward open event
|
|
249
|
-
this._emit(true, 'open', connectEvent);
|
|
250
|
-
resolve();
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// wait for both sockets connected
|
|
255
|
-
return Promise.resolve();
|
|
256
170
|
}
|
|
257
171
|
|
|
258
172
|
/**
|
|
@@ -261,28 +175,18 @@ class Socket {
|
|
|
261
175
|
*
|
|
262
176
|
* Is also called when a disconnection is detected by the heartbeat (note that
|
|
263
177
|
* in this case, the launcher will call `client.stop()` but the listeners are
|
|
264
|
-
* already cleared so the event will be trigerred only once
|
|
265
|
-
*
|
|
266
|
-
* @private
|
|
178
|
+
* already cleared so the event will be trigerred only once.
|
|
267
179
|
*/
|
|
268
|
-
async
|
|
269
|
-
const closeListeners = this.
|
|
270
|
-
const closeBinaryListeners = this._binaryListeners.get('close');
|
|
271
|
-
|
|
180
|
+
async [kSocketTerminate]() {
|
|
181
|
+
const closeListeners = this.#listeners.get('close');
|
|
272
182
|
this.removeAllListeners();
|
|
273
|
-
this.removeAllBinaryListeners();
|
|
274
183
|
|
|
275
|
-
this.
|
|
276
|
-
this.binaryWs.close();
|
|
184
|
+
this.#socket.close();
|
|
277
185
|
|
|
278
186
|
if (closeListeners) {
|
|
279
187
|
closeListeners.forEach(listener => listener());
|
|
280
188
|
}
|
|
281
189
|
|
|
282
|
-
if (closeBinaryListeners) {
|
|
283
|
-
closeBinaryListeners.forEach(listener => listener());
|
|
284
|
-
}
|
|
285
|
-
|
|
286
190
|
return Promise.resolve();
|
|
287
191
|
}
|
|
288
192
|
|
|
@@ -290,63 +194,14 @@ class Socket {
|
|
|
290
194
|
* @param {boolean} binary - Emit to either the string or binary socket.
|
|
291
195
|
* @param {string} channel - Channel name.
|
|
292
196
|
* @param {...*} args - Content of the message.
|
|
293
|
-
* @private
|
|
294
197
|
*/
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (listeners.has(channel)) {
|
|
299
|
-
const callbacks = listeners.get(channel);
|
|
198
|
+
#dispatchEvent(channel, ...args) {
|
|
199
|
+
if (this.#listeners.has(channel)) {
|
|
200
|
+
const callbacks = this.#listeners.get(channel);
|
|
300
201
|
callbacks.forEach(callback => callback(...args));
|
|
301
202
|
}
|
|
302
203
|
}
|
|
303
204
|
|
|
304
|
-
/**
|
|
305
|
-
* @param {Function[]} listeners - List of listeners, either for the string or binary socket.
|
|
306
|
-
* @param {string} channel - Channel name.
|
|
307
|
-
* @param {Function} callback - The function to be added to the listeners.
|
|
308
|
-
* @private
|
|
309
|
-
*/
|
|
310
|
-
_addListener(listeners, channel, callback) {
|
|
311
|
-
if (!listeners.has(channel)) {
|
|
312
|
-
listeners.set(channel, new Set());
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const callbacks = listeners.get(channel);
|
|
316
|
-
callbacks.add(callback);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* @param {Function[]} listeners - List of listeners, either for the string or binary socket.
|
|
321
|
-
* @param {string} channel - Channel name.
|
|
322
|
-
* @param {Function} callback - The function to be removed from the listeners.
|
|
323
|
-
* @private
|
|
324
|
-
*/
|
|
325
|
-
_removeListener(listeners, channel, callback) {
|
|
326
|
-
if (listeners.has(channel)) {
|
|
327
|
-
const callbacks = listeners.get(channel);
|
|
328
|
-
callbacks.delete(callback);
|
|
329
|
-
|
|
330
|
-
if (callbacks.size === 0) {
|
|
331
|
-
listeners.delete(channel);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* @param {Function[]} listeners - List of listeners, either for the string or binary socket.
|
|
338
|
-
* @param {string} [channel=null] - Channel name of the listeners to remove. If null
|
|
339
|
-
* all the listeners are cleared.
|
|
340
|
-
* @private
|
|
341
|
-
*/
|
|
342
|
-
_removeAllListeners(listeners, channel = null) {
|
|
343
|
-
if (channel === null) {
|
|
344
|
-
listeners.clear();
|
|
345
|
-
} else if (listeners.has(channel)) {
|
|
346
|
-
listeners.delete(channel);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
205
|
/**
|
|
351
206
|
* Send messages with JSON compatible data types on a given channel.
|
|
352
207
|
*
|
|
@@ -355,8 +210,10 @@ class Socket {
|
|
|
355
210
|
* JSON compatible data types (i.e. string, number, boolean, object, array and null).
|
|
356
211
|
*/
|
|
357
212
|
send(channel, ...args) {
|
|
358
|
-
|
|
359
|
-
|
|
213
|
+
if (this.#socket.readyState === 1) {
|
|
214
|
+
const msg = packStringMessage(channel, ...args);
|
|
215
|
+
this.#socket.send(msg);
|
|
216
|
+
}
|
|
360
217
|
}
|
|
361
218
|
|
|
362
219
|
/**
|
|
@@ -368,7 +225,12 @@ class Socket {
|
|
|
368
225
|
* {@link server.Socket#send} method.
|
|
369
226
|
*/
|
|
370
227
|
addListener(channel, callback) {
|
|
371
|
-
this.
|
|
228
|
+
if (!this.#listeners.has(channel)) {
|
|
229
|
+
this.#listeners.set(channel, new Set());
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const callbacks = this.#listeners.get(channel);
|
|
233
|
+
callbacks.add(callback);
|
|
372
234
|
}
|
|
373
235
|
|
|
374
236
|
/**
|
|
@@ -378,7 +240,14 @@ class Socket {
|
|
|
378
240
|
* @param {Function} callback - Callback to remove.
|
|
379
241
|
*/
|
|
380
242
|
removeListener(channel, callback) {
|
|
381
|
-
this.
|
|
243
|
+
if (this.#listeners.has(channel)) {
|
|
244
|
+
const callbacks = this.#listeners.get(channel);
|
|
245
|
+
callbacks.delete(callback);
|
|
246
|
+
|
|
247
|
+
if (callbacks.size === 0) {
|
|
248
|
+
this.#listeners.delete(channel);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
382
251
|
}
|
|
383
252
|
|
|
384
253
|
/**
|
|
@@ -387,47 +256,11 @@ class Socket {
|
|
|
387
256
|
* @param {string} channel - Channel name.
|
|
388
257
|
*/
|
|
389
258
|
removeAllListeners(channel = null) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
*
|
|
396
|
-
* @param {string} channel - Channel name.
|
|
397
|
-
* @param {TypedArray} typedArray - Binary data to be sent.
|
|
398
|
-
*/
|
|
399
|
-
sendBinary(channel, typedArray) {
|
|
400
|
-
const msg = packBinaryMessage(channel, typedArray);
|
|
401
|
-
this.binaryWs.send(msg);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Listen binary messages on a given channel
|
|
406
|
-
*
|
|
407
|
-
* @param {string} channel - Channel name.
|
|
408
|
-
* @param {Function} callback - Callback to execute when a message is received.
|
|
409
|
-
*/
|
|
410
|
-
addBinaryListener(channel, callback) {
|
|
411
|
-
this._addListener(this._binaryListeners, channel, callback);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* Remove a listener of binary compatible messages from a given channel
|
|
416
|
-
*
|
|
417
|
-
* @param {string} channel - Channel name.
|
|
418
|
-
* @param {Function} callback - Callback to remove.
|
|
419
|
-
*/
|
|
420
|
-
removeBinaryListener(channel, callback) {
|
|
421
|
-
this._removeListener(this._binaryListeners, channel, callback);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* Remove all listeners of binary compatible messages on a given channel
|
|
426
|
-
*
|
|
427
|
-
* @param {string} channel - Channel of the message.
|
|
428
|
-
*/
|
|
429
|
-
removeAllBinaryListeners(channel = null) {
|
|
430
|
-
this._removeAllListeners(this._binaryListeners, channel);
|
|
259
|
+
if (channel === null) {
|
|
260
|
+
this.#listeners.clear();
|
|
261
|
+
} else if (this.#listeners.has(channel)) {
|
|
262
|
+
this.#listeners.delete(channel);
|
|
263
|
+
}
|
|
431
264
|
}
|
|
432
265
|
}
|
|
433
266
|
|
package/src/common/constants.js
CHANGED
package/src/common/logger.js
CHANGED
|
@@ -126,6 +126,21 @@ const logger = {
|
|
|
126
126
|
console.log(` ${name} ${chalk.red('errors')}`);
|
|
127
127
|
},
|
|
128
128
|
|
|
129
|
+
warnVersionDiscepancies(clientRole, clientVersion, serverVersion) {
|
|
130
|
+
console.warn(`
|
|
131
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
132
|
+
|
|
133
|
+
WARNING
|
|
134
|
+
|
|
135
|
+
Version discrepancies between server and "${clientRole}" client:
|
|
136
|
+
+ server: ${serverVersion} | client: ${clientVersion}
|
|
137
|
+
|
|
138
|
+
This might lead to unexpected behavior, you should consider to re-install your
|
|
139
|
+
dependencies on both your server and clients.
|
|
140
|
+
|
|
141
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`);
|
|
142
|
+
},
|
|
143
|
+
|
|
129
144
|
log(msg) {
|
|
130
145
|
if (!this.verbose) {
|
|
131
146
|
return;
|
|
@@ -1,66 +1,3 @@
|
|
|
1
|
-
import 'fast-text-encoding';
|
|
2
|
-
|
|
3
|
-
const encoder = new TextEncoder('utf-8');
|
|
4
|
-
const decoder = new TextDecoder('utf-8');
|
|
5
|
-
|
|
6
|
-
const types = [
|
|
7
|
-
'Int8Array',
|
|
8
|
-
'Uint8Array',
|
|
9
|
-
'Uint8ClampedArray',
|
|
10
|
-
'Int16Array',
|
|
11
|
-
'Uint16Array',
|
|
12
|
-
'Int32Array',
|
|
13
|
-
'Uint32Array',
|
|
14
|
-
'Float32Array',
|
|
15
|
-
'Float64Array',
|
|
16
|
-
'BigInt64Array',
|
|
17
|
-
'BigUint64Array',
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
// @note - probably some room for optimizations
|
|
21
|
-
|
|
22
|
-
/** @private */
|
|
23
|
-
export function packBinaryMessage(channel, data) {
|
|
24
|
-
const channelBuffer = encoder.encode(channel);
|
|
25
|
-
const channelSize = channelBuffer.byteLength;
|
|
26
|
-
const startOffset = Math.ceil((channelSize + 3) / data.BYTES_PER_ELEMENT) * data.BYTES_PER_ELEMENT;
|
|
27
|
-
const bufferSize = startOffset + data.byteLength;
|
|
28
|
-
const typeName = data.constructor.name;
|
|
29
|
-
const typeIndex = types.indexOf(typeName);
|
|
30
|
-
|
|
31
|
-
if (typeIndex === -1) {
|
|
32
|
-
throw new Error(`Invalid TypedArray type: ${typeName}`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const view = new Uint8Array(bufferSize);
|
|
36
|
-
view[0] = channelSize;
|
|
37
|
-
view[1] = typeIndex;
|
|
38
|
-
view[2] = startOffset;
|
|
39
|
-
|
|
40
|
-
view.set(channelBuffer, 3, channelSize);
|
|
41
|
-
view.set(new Uint8Array(data.buffer), startOffset, data.byteLength);
|
|
42
|
-
|
|
43
|
-
return view.buffer;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** @private */
|
|
47
|
-
export function unpackBinaryMessage(buffer /* arraybuffer */) {
|
|
48
|
-
const infos = new Uint8Array(buffer, 0, 3);
|
|
49
|
-
const channelSize = infos[0];
|
|
50
|
-
const typeIndex = infos[1];
|
|
51
|
-
const startOffset = infos[2];
|
|
52
|
-
|
|
53
|
-
// need to slice as the library recreates a UInt8Array from the whole buffer
|
|
54
|
-
// @todo - see if this copy could be avoided (probably needs a pull request)
|
|
55
|
-
const channelBuffer = new Uint8Array(buffer.slice(3, 3 + channelSize));
|
|
56
|
-
const channel = decoder.decode(channelBuffer);
|
|
57
|
-
const type = types[typeIndex];
|
|
58
|
-
// slice (copy) the underlying ArrayBuffer to create a clean TypedArray
|
|
59
|
-
const data = new globalThis[type](buffer.slice(startOffset));
|
|
60
|
-
|
|
61
|
-
return [channel, data];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
1
|
/** @private */
|
|
65
2
|
export function packStringMessage(channel, ...args) {
|
|
66
3
|
return JSON.stringify([channel, args]);
|
package/src/common/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// [WARNING] This file is generated, do not edit
|
|
2
|
-
export default '4.0.0-alpha.
|
|
2
|
+
export default '4.0.0-alpha.23';
|
package/src/server/Plugin.js
CHANGED
|
@@ -33,6 +33,9 @@ import BasePlugin from '../common/BasePlugin.js';
|
|
|
33
33
|
* @inheritdoc
|
|
34
34
|
*/
|
|
35
35
|
class Plugin extends BasePlugin {
|
|
36
|
+
#server = null;
|
|
37
|
+
#clients = new Set();
|
|
38
|
+
|
|
36
39
|
/**
|
|
37
40
|
* @param {server.Server} server - The soundworks server instance.
|
|
38
41
|
* @param {string} id - User defined id of the plugin as defined in
|
|
@@ -40,16 +43,25 @@ class Plugin extends BasePlugin {
|
|
|
40
43
|
*/
|
|
41
44
|
constructor(server, id) {
|
|
42
45
|
super(id);
|
|
46
|
+
this.#server = server;
|
|
47
|
+
}
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Instance of soundworks server.
|
|
51
|
+
* @type {server.Server}
|
|
52
|
+
* @see {@link server.Server}
|
|
53
|
+
*/
|
|
54
|
+
get server() {
|
|
55
|
+
return this.#server;
|
|
56
|
+
}
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Set of the clients registered in the plugin.
|
|
60
|
+
* @type {Set<server.Client>}
|
|
61
|
+
* @see {@link server.Client}
|
|
62
|
+
*/
|
|
63
|
+
get clients() {
|
|
64
|
+
return this.#clients;
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
/**
|
|
@@ -60,7 +72,7 @@ class Plugin extends BasePlugin {
|
|
|
60
72
|
* @param {server.Client} client
|
|
61
73
|
*/
|
|
62
74
|
async addClient(client) {
|
|
63
|
-
this
|
|
75
|
+
this.#clients.add(client);
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
/**
|
|
@@ -71,7 +83,7 @@ class Plugin extends BasePlugin {
|
|
|
71
83
|
* @param {server.Client} client
|
|
72
84
|
*/
|
|
73
85
|
async removeClient(client) {
|
|
74
|
-
this
|
|
86
|
+
this.#clients.delete(client);
|
|
75
87
|
}
|
|
76
88
|
}
|
|
77
89
|
|