@meshagent/meshagent 0.37.1 → 0.38.0
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 +6 -0
- package/dist/browser/agent.js +74 -10
- package/dist/browser/developer-client.js +3 -0
- package/dist/browser/helpers.d.ts +2 -2
- package/dist/browser/helpers.js +1 -1
- package/dist/browser/meshagent-client.d.ts +25 -0
- package/dist/browser/meshagent-client.js +65 -0
- package/dist/browser/messaging-client.d.ts +29 -16
- package/dist/browser/messaging-client.js +256 -154
- package/dist/browser/participant.d.ts +7 -2
- package/dist/browser/participant.js +9 -9
- package/dist/browser/protocol.d.ts +85 -28
- package/dist/browser/protocol.js +356 -119
- package/dist/browser/room-client.d.ts +165 -29
- package/dist/browser/room-client.js +1114 -74
- package/dist/browser/room-event.d.ts +11 -0
- package/dist/browser/room-event.js +21 -1
- package/dist/browser/room-server-client.d.ts +2 -0
- package/dist/browser/room-server-client.js +6 -0
- package/dist/browser/runtime.d.ts +1 -1
- package/dist/browser/runtime.js +3 -1
- package/dist/browser/secrets-client.js +6 -2
- package/dist/browser/storage-client.d.ts +1 -0
- package/dist/browser/storage-client.js +9 -0
- package/dist/browser/sync-client.d.ts +16 -14
- package/dist/browser/sync-client.js +195 -116
- package/dist/esm/agent.js +74 -10
- package/dist/esm/developer-client.js +3 -0
- package/dist/esm/helpers.d.ts +2 -2
- package/dist/esm/helpers.js +1 -1
- package/dist/esm/meshagent-client.d.ts +25 -0
- package/dist/esm/meshagent-client.js +65 -0
- package/dist/esm/messaging-client.d.ts +29 -16
- package/dist/esm/messaging-client.js +256 -154
- package/dist/esm/participant.d.ts +7 -2
- package/dist/esm/participant.js +9 -9
- package/dist/esm/protocol.d.ts +85 -28
- package/dist/esm/protocol.js +352 -118
- package/dist/esm/room-client.d.ts +165 -29
- package/dist/esm/room-client.js +1112 -73
- package/dist/esm/room-event.d.ts +11 -0
- package/dist/esm/room-event.js +19 -0
- package/dist/esm/room-server-client.d.ts +2 -0
- package/dist/esm/room-server-client.js +7 -1
- package/dist/esm/runtime.d.ts +1 -1
- package/dist/esm/runtime.js +1 -1
- package/dist/esm/secrets-client.js +6 -2
- package/dist/esm/storage-client.d.ts +1 -0
- package/dist/esm/storage-client.js +9 -0
- package/dist/esm/sync-client.d.ts +16 -14
- package/dist/esm/sync-client.js +196 -117
- package/dist/node/agent.js +74 -10
- package/dist/node/developer-client.js +3 -0
- package/dist/node/helpers.d.ts +2 -2
- package/dist/node/helpers.js +1 -1
- package/dist/node/meshagent-client.d.ts +25 -0
- package/dist/node/meshagent-client.js +65 -0
- package/dist/node/messaging-client.d.ts +29 -16
- package/dist/node/messaging-client.js +256 -154
- package/dist/node/participant.d.ts +7 -2
- package/dist/node/participant.js +9 -9
- package/dist/node/protocol.d.ts +85 -28
- package/dist/node/protocol.js +356 -119
- package/dist/node/room-client.d.ts +165 -29
- package/dist/node/room-client.js +1114 -74
- package/dist/node/room-event.d.ts +11 -0
- package/dist/node/room-event.js +21 -1
- package/dist/node/room-server-client.d.ts +2 -0
- package/dist/node/room-server-client.js +6 -0
- package/dist/node/runtime.d.ts +1 -1
- package/dist/node/runtime.js +3 -1
- package/dist/node/secrets-client.js +6 -2
- package/dist/node/storage-client.d.ts +1 -0
- package/dist/node/storage-client.js +9 -0
- package/dist/node/sync-client.d.ts +16 -14
- package/dist/node/sync-client.js +195 -116
- package/package.json +6 -3
package/dist/node/protocol.js
CHANGED
|
@@ -3,10 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.WebSocketClientProtocol = exports.Protocol = exports.ProtocolMessageStream = exports.WebSocketProtocolChannel = exports.StreamProtocolChannel = void 0;
|
|
6
|
+
exports.WebSocketClientProtocol = exports.Protocol = exports.ProtocolMessageStream = exports.WebSocketProtocolChannel = exports.StreamProtocolChannel = exports.ProtocolHandshakeException = exports.ProtocolCloseException = exports.ProtocolReconnectUnsupportedException = exports.ProtocolCloseKind = void 0;
|
|
7
7
|
const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
|
|
8
|
-
const utils_1 = require("./utils");
|
|
9
8
|
const completer_1 = require("./completer");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
10
|
class ProtocolMessage {
|
|
11
11
|
constructor({ id, type, data }) {
|
|
12
12
|
this.id = id;
|
|
@@ -15,8 +15,45 @@ class ProtocolMessage {
|
|
|
15
15
|
this.sent = new completer_1.Completer();
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
+
var ProtocolCloseKind;
|
|
19
|
+
(function (ProtocolCloseKind) {
|
|
20
|
+
ProtocolCloseKind["CLIENT"] = "client";
|
|
21
|
+
ProtocolCloseKind["SERVER"] = "server";
|
|
22
|
+
ProtocolCloseKind["ERROR"] = "error";
|
|
23
|
+
})(ProtocolCloseKind || (exports.ProtocolCloseKind = ProtocolCloseKind = {}));
|
|
24
|
+
class ProtocolReconnectUnsupportedException extends Error {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = "ProtocolReconnectUnsupportedException";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.ProtocolReconnectUnsupportedException = ProtocolReconnectUnsupportedException;
|
|
31
|
+
class ProtocolCloseException extends Error {
|
|
32
|
+
constructor({ closeCode, reason }) {
|
|
33
|
+
super(reason == null || reason.trim().length === 0 ? `connection closed with status ${closeCode}` : reason);
|
|
34
|
+
this.name = "ProtocolCloseException";
|
|
35
|
+
this.closeCode = closeCode;
|
|
36
|
+
this.reason = reason;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.ProtocolCloseException = ProtocolCloseException;
|
|
40
|
+
class ProtocolHandshakeException extends Error {
|
|
41
|
+
constructor({ statusCode, statusText }) {
|
|
42
|
+
const normalizedStatusText = statusText?.trim();
|
|
43
|
+
super(normalizedStatusText == null || normalizedStatusText.length === 0
|
|
44
|
+
? `websocket connect failed with status ${statusCode}`
|
|
45
|
+
: `websocket connect failed with status ${statusCode}: ${normalizedStatusText}`);
|
|
46
|
+
this.name = "ProtocolHandshakeException";
|
|
47
|
+
this.statusCode = statusCode;
|
|
48
|
+
this.statusText = normalizedStatusText;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.ProtocolHandshakeException = ProtocolHandshakeException;
|
|
52
|
+
function isNodeRuntime() {
|
|
53
|
+
return typeof process !== "undefined" && process.release?.name === "node";
|
|
54
|
+
}
|
|
18
55
|
class StreamProtocolChannel {
|
|
19
|
-
constructor({ input, output }) {
|
|
56
|
+
constructor({ input, output, }) {
|
|
20
57
|
this.started = false;
|
|
21
58
|
this._iterator = null;
|
|
22
59
|
this.input = input;
|
|
@@ -28,29 +65,24 @@ class StreamProtocolChannel {
|
|
|
28
65
|
}
|
|
29
66
|
this.started = true;
|
|
30
67
|
(async () => {
|
|
31
|
-
this._iterator?.return(
|
|
68
|
+
this._iterator?.return(undefined);
|
|
32
69
|
try {
|
|
33
70
|
this._iterator = this.input.stream();
|
|
34
71
|
for await (const message of this._iterator) {
|
|
35
|
-
|
|
36
|
-
onDataReceived(message);
|
|
37
|
-
}
|
|
72
|
+
onDataReceived(message);
|
|
38
73
|
}
|
|
74
|
+
onDone?.();
|
|
39
75
|
}
|
|
40
76
|
catch (error) {
|
|
41
|
-
|
|
42
|
-
onError(error);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
finally {
|
|
46
|
-
if (onDone) {
|
|
47
|
-
onDone();
|
|
48
|
-
}
|
|
77
|
+
onError?.(error);
|
|
49
78
|
}
|
|
50
|
-
})()
|
|
79
|
+
})().catch((error) => {
|
|
80
|
+
onError?.(error);
|
|
81
|
+
});
|
|
51
82
|
}
|
|
52
83
|
dispose() {
|
|
53
|
-
this.
|
|
84
|
+
this.started = false;
|
|
85
|
+
this._iterator?.return(undefined);
|
|
54
86
|
this._iterator = null;
|
|
55
87
|
this.input.close();
|
|
56
88
|
}
|
|
@@ -63,54 +95,115 @@ class WebSocketProtocolChannel {
|
|
|
63
95
|
constructor({ url, jwt }) {
|
|
64
96
|
this.webSocket = null;
|
|
65
97
|
this._opened = new completer_1.Completer();
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
98
|
+
this._finished = false;
|
|
99
|
+
this._onUnexpectedResponse = (_request, response) => {
|
|
100
|
+
const statusCode = response.statusCode;
|
|
101
|
+
if (statusCode == null) {
|
|
102
|
+
this._finish("error", new Error("websocket connect failed"));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this._finish("error", new ProtocolHandshakeException({
|
|
106
|
+
statusCode,
|
|
107
|
+
statusText: response.statusMessage,
|
|
108
|
+
}));
|
|
109
|
+
};
|
|
110
|
+
this._onOpen = () => {
|
|
111
|
+
if (!this._opened.completed) {
|
|
112
|
+
this._opened.complete();
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
this._onMessage = (event) => {
|
|
68
116
|
const data = event.data;
|
|
69
117
|
if (data instanceof Blob) {
|
|
70
|
-
data.arrayBuffer().then((buffer) => {
|
|
71
|
-
|
|
72
|
-
this.onDataReceived(new Uint8Array(buffer));
|
|
73
|
-
}
|
|
118
|
+
void data.arrayBuffer().then((buffer) => {
|
|
119
|
+
this._onDataReceived?.(new Uint8Array(buffer));
|
|
74
120
|
});
|
|
121
|
+
return;
|
|
75
122
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
123
|
+
if (typeof data === "string") {
|
|
124
|
+
this._onDataReceived?.(utils_1.encoder.encode(data));
|
|
125
|
+
return;
|
|
80
126
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
127
|
+
if (data instanceof ArrayBuffer) {
|
|
128
|
+
this._onDataReceived?.(new Uint8Array(data));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (data instanceof Uint8Array) {
|
|
132
|
+
this._onDataReceived?.(data);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (ArrayBuffer.isView(data)) {
|
|
136
|
+
this._onDataReceived?.(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
|
|
85
137
|
}
|
|
86
138
|
};
|
|
139
|
+
this._onClose = (event) => {
|
|
140
|
+
if (event.code === 1000) {
|
|
141
|
+
this._finish("done");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const reason = typeof event.reason === "string" ? event.reason : event.reason.toString();
|
|
145
|
+
this._finish("error", new ProtocolCloseException({ closeCode: event.code, reason }));
|
|
146
|
+
};
|
|
147
|
+
this._onError = (event) => {
|
|
148
|
+
this._finish("error", event instanceof Error ? event : new Error("websocket error"));
|
|
149
|
+
};
|
|
87
150
|
this.url = url;
|
|
88
151
|
this.jwt = jwt;
|
|
89
152
|
}
|
|
90
153
|
start(onDataReceived, { onDone, onError }) {
|
|
91
|
-
if (typeof (onDataReceived) != "function") {
|
|
92
|
-
throw new Error("onDataReceived must be a function");
|
|
93
|
-
}
|
|
94
154
|
const url = new URL(this.url);
|
|
95
155
|
url.searchParams.set("token", this.jwt);
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
98
|
-
this.
|
|
99
|
-
this.
|
|
100
|
-
|
|
101
|
-
|
|
156
|
+
this._opened = new completer_1.Completer();
|
|
157
|
+
this._finished = false;
|
|
158
|
+
this._onDataReceived = onDataReceived;
|
|
159
|
+
this._doneHandler = onDone;
|
|
160
|
+
this._errorHandler = onError;
|
|
161
|
+
const socket = new isomorphic_ws_1.default(url.toString());
|
|
162
|
+
this.webSocket = socket;
|
|
163
|
+
if (isNodeRuntime()) {
|
|
164
|
+
socket.on("unexpected-response", this._onUnexpectedResponse);
|
|
102
165
|
}
|
|
103
|
-
|
|
104
|
-
|
|
166
|
+
socket.addEventListener("open", this._onOpen);
|
|
167
|
+
socket.addEventListener("message", this._onMessage);
|
|
168
|
+
socket.addEventListener("close", this._onClose);
|
|
169
|
+
socket.addEventListener("error", this._onError);
|
|
170
|
+
}
|
|
171
|
+
_finish(kind, error) {
|
|
172
|
+
if (this._finished) {
|
|
173
|
+
return;
|
|
105
174
|
}
|
|
175
|
+
this._finished = true;
|
|
176
|
+
if (kind === "done") {
|
|
177
|
+
this._doneHandler?.();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
this._errorHandler?.(error);
|
|
106
181
|
}
|
|
107
182
|
dispose() {
|
|
108
|
-
this.webSocket
|
|
183
|
+
const socket = this.webSocket;
|
|
109
184
|
this.webSocket = null;
|
|
185
|
+
this._onDataReceived = undefined;
|
|
186
|
+
if (socket == null) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
socket.removeEventListener("open", this._onOpen);
|
|
190
|
+
socket.removeEventListener("message", this._onMessage);
|
|
191
|
+
socket.removeEventListener("close", this._onClose);
|
|
192
|
+
socket.removeEventListener("error", this._onError);
|
|
193
|
+
if (isNodeRuntime()) {
|
|
194
|
+
socket.off("unexpected-response", this._onUnexpectedResponse);
|
|
195
|
+
}
|
|
196
|
+
if (socket.readyState === isomorphic_ws_1.default.CONNECTING || socket.readyState === isomorphic_ws_1.default.OPEN) {
|
|
197
|
+
socket.close(1000);
|
|
198
|
+
}
|
|
110
199
|
}
|
|
111
200
|
async sendData(data) {
|
|
112
201
|
await this._opened.fut;
|
|
113
|
-
this.webSocket
|
|
202
|
+
const socket = this.webSocket;
|
|
203
|
+
if (socket == null) {
|
|
204
|
+
throw new Error("websocket is closed");
|
|
205
|
+
}
|
|
206
|
+
socket.send(data);
|
|
114
207
|
}
|
|
115
208
|
}
|
|
116
209
|
exports.WebSocketProtocolChannel = WebSocketProtocolChannel;
|
|
@@ -120,15 +213,15 @@ class ProtocolMessageStream {
|
|
|
120
213
|
this._messageAdded = new completer_1.Completer();
|
|
121
214
|
this._closed = false;
|
|
122
215
|
}
|
|
123
|
-
|
|
216
|
+
add(message) {
|
|
124
217
|
this._messages.push(message);
|
|
125
218
|
if (!this._messageAdded.completed) {
|
|
126
219
|
this._messageAdded.complete();
|
|
127
220
|
}
|
|
128
221
|
}
|
|
129
222
|
close() {
|
|
223
|
+
this._closed = true;
|
|
130
224
|
if (!this._messageAdded.completed) {
|
|
131
|
-
this._closed = true;
|
|
132
225
|
this._messageAdded.complete();
|
|
133
226
|
}
|
|
134
227
|
}
|
|
@@ -137,9 +230,9 @@ class ProtocolMessageStream {
|
|
|
137
230
|
await this._messageAdded.fut;
|
|
138
231
|
this._messageAdded = new completer_1.Completer();
|
|
139
232
|
while (this._messages.length > 0 && !this._closed) {
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
yield
|
|
233
|
+
const message = this._messages.shift();
|
|
234
|
+
if (message !== undefined) {
|
|
235
|
+
yield message;
|
|
143
236
|
}
|
|
144
237
|
}
|
|
145
238
|
}
|
|
@@ -151,26 +244,87 @@ class Protocol {
|
|
|
151
244
|
this.handlers = {};
|
|
152
245
|
this._id = 0;
|
|
153
246
|
this._send = new ProtocolMessageStream();
|
|
247
|
+
this._done = new completer_1.Completer();
|
|
248
|
+
this._sendLoop = null;
|
|
249
|
+
this._open = false;
|
|
250
|
+
this._closed = false;
|
|
251
|
+
this._closeKind = null;
|
|
252
|
+
this._closeReason = null;
|
|
154
253
|
this._recvPacketId = 0;
|
|
155
254
|
this._recvState = "ready";
|
|
156
255
|
this._recvPacketTotal = 0;
|
|
157
256
|
this._recvMessageId = -1;
|
|
158
257
|
this._recvType = "";
|
|
159
258
|
this._recvPackets = [];
|
|
160
|
-
this._iterator = null;
|
|
161
259
|
this.channel = channel;
|
|
162
260
|
}
|
|
261
|
+
get url() {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
get token() {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
get isOpen() {
|
|
268
|
+
return this._open;
|
|
269
|
+
}
|
|
270
|
+
get isClosed() {
|
|
271
|
+
return this._closed;
|
|
272
|
+
}
|
|
273
|
+
get closeKind() {
|
|
274
|
+
return this._closeKind;
|
|
275
|
+
}
|
|
276
|
+
get closeReason() {
|
|
277
|
+
return this._closeReason;
|
|
278
|
+
}
|
|
279
|
+
get done() {
|
|
280
|
+
return this._done.fut;
|
|
281
|
+
}
|
|
282
|
+
async waitForClose() {
|
|
283
|
+
await this.done;
|
|
284
|
+
}
|
|
285
|
+
static createFactory(...args) {
|
|
286
|
+
const ProtocolCtor = this;
|
|
287
|
+
if (ProtocolCtor === Protocol) {
|
|
288
|
+
let used = false;
|
|
289
|
+
return () => {
|
|
290
|
+
if (used) {
|
|
291
|
+
throw new ProtocolReconnectUnsupportedException("protocolFactory was not configured for reconnecting this protocol");
|
|
292
|
+
}
|
|
293
|
+
used = true;
|
|
294
|
+
return new ProtocolCtor(...args);
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
return () => new ProtocolCtor(...args);
|
|
298
|
+
}
|
|
299
|
+
_setCloseState({ kind, reason, }) {
|
|
300
|
+
if (this._closeKind == null) {
|
|
301
|
+
this._closeKind = kind;
|
|
302
|
+
}
|
|
303
|
+
if (this._closeReason == null && reason != null && reason.trim().length > 0) {
|
|
304
|
+
this._closeReason = reason.trim();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
163
307
|
addHandler(type, handler) {
|
|
308
|
+
if (this.handlers[type] !== undefined) {
|
|
309
|
+
throw new Error(`already registered handler for ${type}`);
|
|
310
|
+
}
|
|
164
311
|
this.handlers[type] = handler;
|
|
165
312
|
}
|
|
166
|
-
removeHandler(type) {
|
|
313
|
+
removeHandler(type, handler) {
|
|
314
|
+
const current = this.handlers[type];
|
|
315
|
+
if (current !== handler) {
|
|
316
|
+
throw new Error(`handler mismatch for ${type}`);
|
|
317
|
+
}
|
|
167
318
|
delete this.handlers[type];
|
|
168
319
|
}
|
|
320
|
+
getHandler(type) {
|
|
321
|
+
return this.handlers[type];
|
|
322
|
+
}
|
|
169
323
|
async handleMessage(messageId, type, data) {
|
|
170
324
|
const handler = this.handlers[type] ?? this.handlers["*"];
|
|
171
|
-
if (
|
|
172
|
-
const
|
|
173
|
-
console.warn(`No handler for message type ${type}; data
|
|
325
|
+
if (handler == null) {
|
|
326
|
+
const unpacked = (0, utils_1.unpackMessage)(data);
|
|
327
|
+
console.warn(`No handler for message type ${type}; data:`, unpacked);
|
|
174
328
|
return;
|
|
175
329
|
}
|
|
176
330
|
await handler(this, messageId, type, data);
|
|
@@ -178,69 +332,139 @@ class Protocol {
|
|
|
178
332
|
getNextMessageId() {
|
|
179
333
|
return this._id++;
|
|
180
334
|
}
|
|
335
|
+
sendNowait(type, data, { id } = {}) {
|
|
336
|
+
if (this._sendError != null) {
|
|
337
|
+
throw this._sendError;
|
|
338
|
+
}
|
|
339
|
+
if (this._closed) {
|
|
340
|
+
throw new Error("protocol is closed");
|
|
341
|
+
}
|
|
342
|
+
const message = new ProtocolMessage({ id: id ?? this.getNextMessageId(), type, data });
|
|
343
|
+
this._send.add(message);
|
|
344
|
+
return message.id;
|
|
345
|
+
}
|
|
181
346
|
async send(type, data, id) {
|
|
182
|
-
const
|
|
183
|
-
this.
|
|
184
|
-
|
|
347
|
+
const message = new ProtocolMessage({ id: id ?? this.getNextMessageId(), type, data });
|
|
348
|
+
if (this._sendError != null) {
|
|
349
|
+
throw this._sendError;
|
|
350
|
+
}
|
|
351
|
+
if (this._closed) {
|
|
352
|
+
throw new Error("protocol is closed");
|
|
353
|
+
}
|
|
354
|
+
this._send.add(message);
|
|
355
|
+
await message.sent.fut;
|
|
185
356
|
}
|
|
186
357
|
async sendJson(object) {
|
|
187
|
-
|
|
358
|
+
await this.send("application/json", utils_1.encoder.encode(JSON.stringify(object)));
|
|
188
359
|
}
|
|
189
|
-
start({ onMessage, onDone, onError } = {}) {
|
|
360
|
+
start({ onMessage, onDone, onError, } = {}) {
|
|
361
|
+
if (this._sendLoop != null) {
|
|
362
|
+
throw new Error("protocol already started");
|
|
363
|
+
}
|
|
190
364
|
if (onMessage != null) {
|
|
191
365
|
this.addHandler("*", onMessage);
|
|
192
366
|
}
|
|
193
|
-
this.
|
|
194
|
-
this.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
const header = new Uint8Array(4 * 4);
|
|
201
|
-
const dataView = new DataView(header.buffer);
|
|
202
|
-
dataView.setUint32(0, (message.id & 0x000fffff00000000) / Math.pow(2, 32), false);
|
|
203
|
-
dataView.setUint32(4, message.id & 0xffffffff, false);
|
|
204
|
-
dataView.setUint32(8, 0, false);
|
|
205
|
-
dataView.setUint32(12, packets, false);
|
|
206
|
-
const headerPacket = (0, utils_1.mergeUint8Arrays)(header, utils_1.encoder.encode(message.type));
|
|
207
|
-
await this.channel.sendData(headerPacket);
|
|
208
|
-
for (var i = 0; i < packets; i++) {
|
|
209
|
-
const packetHeader = new Uint8Array(3 * 4);
|
|
210
|
-
const dataView = new DataView(packetHeader.buffer);
|
|
211
|
-
dataView.setUint32(0, (message.id & 0x000fffff00000000) / Math.pow(2, 32), false);
|
|
212
|
-
dataView.setUint32(4, message.id & 0xffffffff, false);
|
|
213
|
-
dataView.setUint32(8, i + 1, false);
|
|
214
|
-
const packet = (0, utils_1.mergeUint8Arrays)(packetHeader, message.data.subarray(i * 1024, Math.min((i + 1) * 1024, message.data.length)));
|
|
215
|
-
await this.channel.sendData(packet);
|
|
216
|
-
}
|
|
217
|
-
message.sent.resolve();
|
|
367
|
+
this._open = true;
|
|
368
|
+
this.channel.start(this.onDataReceived.bind(this), {
|
|
369
|
+
onDone: () => {
|
|
370
|
+
this._setCloseState({ kind: ProtocolCloseKind.SERVER });
|
|
371
|
+
this._shutdown();
|
|
372
|
+
if (!this._done.completed) {
|
|
373
|
+
this._done.complete(null);
|
|
218
374
|
}
|
|
219
|
-
|
|
220
|
-
|
|
375
|
+
onDone?.();
|
|
376
|
+
},
|
|
377
|
+
onError: (error) => {
|
|
378
|
+
this._setCloseState({
|
|
379
|
+
kind: ProtocolCloseKind.ERROR,
|
|
380
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
381
|
+
});
|
|
382
|
+
this._shutdown();
|
|
383
|
+
if (!this._done.completed) {
|
|
384
|
+
this._done.complete(error);
|
|
385
|
+
}
|
|
386
|
+
onError?.(error);
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
this._sendLoop = this._runSendLoop(onError);
|
|
221
390
|
}
|
|
222
|
-
|
|
391
|
+
close() {
|
|
392
|
+
this._setCloseState({ kind: ProtocolCloseKind.CLIENT });
|
|
393
|
+
this._shutdown();
|
|
223
394
|
this.channel.dispose();
|
|
224
|
-
this.
|
|
225
|
-
|
|
395
|
+
if (!this._done.completed) {
|
|
396
|
+
this._done.complete(null);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
dispose() {
|
|
400
|
+
this.close();
|
|
401
|
+
}
|
|
402
|
+
_shutdown() {
|
|
403
|
+
if (this._closed) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
this._closed = true;
|
|
407
|
+
this._open = false;
|
|
408
|
+
this._send.close();
|
|
409
|
+
}
|
|
410
|
+
async _runSendLoop(onError) {
|
|
411
|
+
for await (const message of this._send.stream()) {
|
|
412
|
+
try {
|
|
413
|
+
const packets = Math.ceil(message.data.length / 1024);
|
|
414
|
+
const header = new Uint8Array(16);
|
|
415
|
+
const headerView = new DataView(header.buffer);
|
|
416
|
+
headerView.setUint32(0, Math.floor(message.id / 2 ** 32), false);
|
|
417
|
+
headerView.setUint32(4, message.id & 0xffffffff, false);
|
|
418
|
+
headerView.setUint32(8, 0, false);
|
|
419
|
+
headerView.setUint32(12, packets, false);
|
|
420
|
+
await this.channel.sendData((0, utils_1.mergeUint8Arrays)(header, utils_1.encoder.encode(message.type)));
|
|
421
|
+
for (let i = 0; i < packets; i += 1) {
|
|
422
|
+
const packetHeader = new Uint8Array(12);
|
|
423
|
+
const packetHeaderView = new DataView(packetHeader.buffer);
|
|
424
|
+
packetHeaderView.setUint32(0, Math.floor(message.id / 2 ** 32), false);
|
|
425
|
+
packetHeaderView.setUint32(4, message.id & 0xffffffff, false);
|
|
426
|
+
packetHeaderView.setUint32(8, i + 1, false);
|
|
427
|
+
await this.channel.sendData((0, utils_1.mergeUint8Arrays)(packetHeader, message.data.subarray(i * 1024, Math.min((i + 1) * 1024, message.data.length))));
|
|
428
|
+
}
|
|
429
|
+
if (!message.sent.completed) {
|
|
430
|
+
message.sent.complete();
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
this._sendError = error;
|
|
435
|
+
this._setCloseState({
|
|
436
|
+
kind: ProtocolCloseKind.ERROR,
|
|
437
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
438
|
+
});
|
|
439
|
+
if (!message.sent.completed) {
|
|
440
|
+
message.sent.completeError(error);
|
|
441
|
+
}
|
|
442
|
+
this._shutdown();
|
|
443
|
+
if (!this._done.completed) {
|
|
444
|
+
this._done.complete(error);
|
|
445
|
+
}
|
|
446
|
+
onError?.(error);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
226
450
|
}
|
|
227
451
|
onDataReceived(dataPacket) {
|
|
228
|
-
const dataView = new DataView(dataPacket.buffer);
|
|
229
|
-
const messageId = dataView.getUint32(4, false) + dataView.getUint32(0, false) *
|
|
452
|
+
const dataView = new DataView(dataPacket.buffer, dataPacket.byteOffset, dataPacket.byteLength);
|
|
453
|
+
const messageId = dataView.getUint32(4, false) + dataView.getUint32(0, false) * 2 ** 32;
|
|
230
454
|
const packet = dataView.getUint32(8, false);
|
|
231
|
-
if (packet
|
|
455
|
+
if (packet !== this._recvPacketId) {
|
|
232
456
|
this._recvState = "error";
|
|
233
457
|
}
|
|
234
|
-
if (packet
|
|
235
|
-
if (this._recvState
|
|
458
|
+
if (packet === 0) {
|
|
459
|
+
if (this._recvState === "ready" || this._recvState === "error") {
|
|
236
460
|
this._recvPacketTotal = dataView.getUint32(12, false);
|
|
237
461
|
this._recvMessageId = messageId;
|
|
238
462
|
this._recvType = utils_1.decoder.decode(dataPacket.subarray(16));
|
|
239
|
-
if (this._recvPacketTotal
|
|
463
|
+
if (this._recvPacketTotal === 0) {
|
|
240
464
|
try {
|
|
241
465
|
const merged = (0, utils_1.mergeUint8Arrays)(...this._recvPackets);
|
|
242
466
|
this._recvPackets.length = 0;
|
|
243
|
-
this.
|
|
467
|
+
this._dispatchMessage({ messageId, type: this._recvType, data: merged });
|
|
244
468
|
}
|
|
245
469
|
finally {
|
|
246
470
|
this._recvState = "ready";
|
|
@@ -258,41 +482,54 @@ class Protocol {
|
|
|
258
482
|
this._recvState = "error";
|
|
259
483
|
this._recvPacketId = 0;
|
|
260
484
|
}
|
|
485
|
+
return;
|
|
261
486
|
}
|
|
262
|
-
|
|
487
|
+
if (this._recvState !== "processing") {
|
|
263
488
|
this._recvState = "error";
|
|
264
489
|
this._recvPacketId = 0;
|
|
490
|
+
return;
|
|
265
491
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
this.handleMessage(messageId, this._recvType, merged);
|
|
277
|
-
}
|
|
278
|
-
finally {
|
|
279
|
-
this._recvState = "ready";
|
|
280
|
-
this._recvPacketId = 0;
|
|
281
|
-
this._recvType = "";
|
|
282
|
-
this._recvMessageId = -1;
|
|
283
|
-
}
|
|
492
|
+
if (messageId !== this._recvMessageId) {
|
|
493
|
+
this._recvState = "error";
|
|
494
|
+
this._recvPacketId = 0;
|
|
495
|
+
}
|
|
496
|
+
this._recvPackets.push(dataPacket.subarray(12));
|
|
497
|
+
if (this._recvPacketTotal === this._recvPacketId) {
|
|
498
|
+
try {
|
|
499
|
+
const merged = (0, utils_1.mergeUint8Arrays)(...this._recvPackets);
|
|
500
|
+
this._recvPackets.length = 0;
|
|
501
|
+
this._dispatchMessage({ messageId, type: this._recvType, data: merged });
|
|
284
502
|
}
|
|
285
|
-
|
|
286
|
-
this.
|
|
503
|
+
finally {
|
|
504
|
+
this._recvState = "ready";
|
|
505
|
+
this._recvPacketId = 0;
|
|
506
|
+
this._recvType = "";
|
|
507
|
+
this._recvMessageId = -1;
|
|
287
508
|
}
|
|
509
|
+
return;
|
|
288
510
|
}
|
|
511
|
+
this._recvPacketId += 1;
|
|
512
|
+
}
|
|
513
|
+
_dispatchMessage({ messageId, type, data, }) {
|
|
514
|
+
void this.handleMessage(messageId, type, data).catch((error) => {
|
|
515
|
+
console.error("unhandled protocol message handler error", error);
|
|
516
|
+
});
|
|
289
517
|
}
|
|
290
518
|
}
|
|
291
519
|
exports.Protocol = Protocol;
|
|
292
520
|
class WebSocketClientProtocol extends Protocol {
|
|
293
521
|
constructor({ url, token }) {
|
|
294
|
-
|
|
295
|
-
|
|
522
|
+
super({
|
|
523
|
+
channel: new WebSocketProtocolChannel({ url, jwt: token }),
|
|
524
|
+
});
|
|
525
|
+
this._url = url;
|
|
526
|
+
this._token = token;
|
|
527
|
+
}
|
|
528
|
+
get url() {
|
|
529
|
+
return this._url;
|
|
530
|
+
}
|
|
531
|
+
get token() {
|
|
532
|
+
return this._token;
|
|
296
533
|
}
|
|
297
534
|
}
|
|
298
535
|
exports.WebSocketClientProtocol = WebSocketClientProtocol;
|