@dxos/network-manager 0.1.22 → 0.1.24-next.6b1f434
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/dist/lib/browser/chunk-2TROGP2W.mjs +2155 -0
- package/dist/lib/browser/chunk-2TROGP2W.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +21 -2136
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +28 -2013
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node/index.cjs +43 -46
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +44 -47
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/connection-log.d.ts +2 -2
- package/dist/types/src/swarm/swarm.d.ts +0 -1
- package/dist/types/src/swarm/swarm.d.ts.map +1 -1
- package/dist/types/src/testing/test-wire-protocol.d.ts.map +1 -1
- package/dist/types/src/tests/basic-test-suite.d.ts.map +1 -1
- package/dist/types/src/tests/utils.d.ts.map +1 -1
- package/package.json +16 -16
- package/src/connection-log.ts +2 -2
- package/src/network-manager.ts +4 -4
- package/src/swarm/swarm.ts +17 -17
- package/src/testing/test-wire-protocol.ts +5 -2
- package/src/tests/basic-test-suite.ts +60 -27
- package/src/tests/utils.ts +2 -1
- package/src/tests/webrtc-transport.test.ts +0 -3
- package/src/transport/webrtc-transport-proxy.test.ts +5 -6
|
@@ -1,2020 +1,35 @@
|
|
|
1
1
|
import "@dxos/node-std/globals"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import {
|
|
3
|
+
FullyConnectedTopology,
|
|
4
|
+
MemoryTransportFactory,
|
|
5
|
+
NetworkManager,
|
|
6
|
+
WebRTCTransport,
|
|
7
|
+
WebRTCTransportProxyFactory,
|
|
8
|
+
WebRTCTransportService,
|
|
9
|
+
createTeleportProtocolFactory
|
|
10
|
+
} from "../chunk-2TROGP2W.mjs";
|
|
9
11
|
|
|
10
12
|
// packages/core/mesh/network-manager/src/testing/test-builder.ts
|
|
11
|
-
import { PublicKey as
|
|
13
|
+
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
12
14
|
import { MemorySignalManager, MemorySignalManagerContext, WebsocketSignalManager } from "@dxos/messaging";
|
|
13
|
-
import { schema
|
|
14
|
-
import { ConnectionState
|
|
15
|
+
import { schema } from "@dxos/protocols";
|
|
16
|
+
import { ConnectionState } from "@dxos/protocols/proto/dxos/client/services";
|
|
15
17
|
import { createLinkedPorts, createProtoRpcPeer } from "@dxos/rpc";
|
|
16
|
-
import { ComplexMap as
|
|
17
|
-
|
|
18
|
-
// packages/core/mesh/network-manager/src/network-manager.ts
|
|
19
|
-
import assert5 from "@dxos/node-std/assert";
|
|
20
|
-
import { Event as Event5 } from "@dxos/async";
|
|
21
|
-
import { PublicKey as PublicKey6 } from "@dxos/keys";
|
|
22
|
-
import { log as log6 } from "@dxos/log";
|
|
23
|
-
import { Messenger } from "@dxos/messaging";
|
|
24
|
-
import { ConnectionState as ConnectionState2 } from "@dxos/protocols/proto/dxos/client/services";
|
|
25
|
-
import { ComplexMap as ComplexMap5 } from "@dxos/util";
|
|
26
|
-
|
|
27
|
-
// packages/core/mesh/network-manager/src/connection-log.ts
|
|
28
|
-
import { Event as Event4 } from "@dxos/async";
|
|
29
|
-
import { raise } from "@dxos/debug";
|
|
30
|
-
import { PublicKey as PublicKey5 } from "@dxos/keys";
|
|
31
|
-
import { ComplexMap as ComplexMap4 } from "@dxos/util";
|
|
32
|
-
|
|
33
|
-
// packages/core/mesh/network-manager/src/swarm/connection.ts
|
|
34
|
-
import assert from "@dxos/node-std/assert";
|
|
35
|
-
import { Event, synchronized } from "@dxos/async";
|
|
36
|
-
import { ErrorStream } from "@dxos/debug";
|
|
37
|
-
import { log } from "@dxos/log";
|
|
38
|
-
var __decorate = function(decorators, target, key, desc) {
|
|
39
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
40
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
41
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
42
|
-
else
|
|
43
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
44
|
-
if (d = decorators[i])
|
|
45
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
46
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
47
|
-
};
|
|
48
|
-
var ConnectionState;
|
|
49
|
-
(function(ConnectionState6) {
|
|
50
|
-
ConnectionState6[
|
|
51
|
-
/**
|
|
52
|
-
* Initial state. Connection is registered but no attempt to connect to the remote peer has been performed.
|
|
53
|
-
* Might mean that we are waiting for the answer signal from the remote peer.
|
|
54
|
-
*/
|
|
55
|
-
"INITIAL"
|
|
56
|
-
] = "INITIAL";
|
|
57
|
-
ConnectionState6[
|
|
58
|
-
/**
|
|
59
|
-
* Trying to establish connection.
|
|
60
|
-
*/
|
|
61
|
-
"CONNECTING"
|
|
62
|
-
] = "CONNECTING";
|
|
63
|
-
ConnectionState6[
|
|
64
|
-
/**
|
|
65
|
-
* Connection is established.
|
|
66
|
-
*/
|
|
67
|
-
"CONNECTED"
|
|
68
|
-
] = "CONNECTED";
|
|
69
|
-
ConnectionState6[
|
|
70
|
-
/**
|
|
71
|
-
* Connection is being closed.
|
|
72
|
-
*/
|
|
73
|
-
"CLOSING"
|
|
74
|
-
] = "CLOSING";
|
|
75
|
-
ConnectionState6[
|
|
76
|
-
/**
|
|
77
|
-
* Connection closed.
|
|
78
|
-
*/
|
|
79
|
-
"CLOSED"
|
|
80
|
-
] = "CLOSED";
|
|
81
|
-
})(ConnectionState || (ConnectionState = {}));
|
|
82
|
-
var Connection = class {
|
|
83
|
-
constructor(topic, ownId, remoteId, sessionId, initiator, _signalMessaging, _protocol, _transportFactory) {
|
|
84
|
-
this.topic = topic;
|
|
85
|
-
this.ownId = ownId;
|
|
86
|
-
this.remoteId = remoteId;
|
|
87
|
-
this.sessionId = sessionId;
|
|
88
|
-
this.initiator = initiator;
|
|
89
|
-
this._signalMessaging = _signalMessaging;
|
|
90
|
-
this._protocol = _protocol;
|
|
91
|
-
this._transportFactory = _transportFactory;
|
|
92
|
-
this._state = ConnectionState.INITIAL;
|
|
93
|
-
this._bufferedSignals = [];
|
|
94
|
-
this.stateChanged = new Event();
|
|
95
|
-
this.errors = new ErrorStream();
|
|
96
|
-
}
|
|
97
|
-
get state() {
|
|
98
|
-
return this._state;
|
|
99
|
-
}
|
|
100
|
-
get transport() {
|
|
101
|
-
return this._transport;
|
|
102
|
-
}
|
|
103
|
-
get protocol() {
|
|
104
|
-
return this._protocol;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Create an underlying transport and prepares it for the connection.
|
|
108
|
-
*/
|
|
109
|
-
// TODO(burdon): Make async?
|
|
110
|
-
openConnection() {
|
|
111
|
-
assert(this._state === ConnectionState.INITIAL, "Invalid state.");
|
|
112
|
-
this._changeState(ConnectionState.CONNECTING);
|
|
113
|
-
this._protocol.initialize().catch((err) => {
|
|
114
|
-
this.errors.raise(err);
|
|
115
|
-
});
|
|
116
|
-
assert(!this._transport);
|
|
117
|
-
this._transport = this._transportFactory.createTransport({
|
|
118
|
-
initiator: this.initiator,
|
|
119
|
-
stream: this._protocol.stream,
|
|
120
|
-
sendSignal: async (signal) => {
|
|
121
|
-
await this._signalMessaging.signal({
|
|
122
|
-
author: this.ownId,
|
|
123
|
-
recipient: this.remoteId,
|
|
124
|
-
sessionId: this.sessionId,
|
|
125
|
-
topic: this.topic,
|
|
126
|
-
data: {
|
|
127
|
-
signal
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
this._transport.connected.once(() => {
|
|
133
|
-
this._changeState(ConnectionState.CONNECTED);
|
|
134
|
-
});
|
|
135
|
-
this._transport.closed.once(() => {
|
|
136
|
-
this._transport = void 0;
|
|
137
|
-
this.close().catch((err) => this.errors.raise(err));
|
|
138
|
-
});
|
|
139
|
-
this._transport.errors.handle((err) => {
|
|
140
|
-
if (this._state !== ConnectionState.CLOSED && this._state !== ConnectionState.CLOSING) {
|
|
141
|
-
this.errors.raise(err);
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
for (const signal of this._bufferedSignals) {
|
|
145
|
-
void this._transport.signal(signal);
|
|
146
|
-
}
|
|
147
|
-
this._bufferedSignals = [];
|
|
148
|
-
}
|
|
149
|
-
async close() {
|
|
150
|
-
var _a;
|
|
151
|
-
if (this._state === ConnectionState.CLOSED) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
this._changeState(ConnectionState.CLOSING);
|
|
155
|
-
log("closing...", {
|
|
156
|
-
peerId: this.ownId
|
|
157
|
-
}, {
|
|
158
|
-
file: "connection.ts",
|
|
159
|
-
line: 142,
|
|
160
|
-
scope: this,
|
|
161
|
-
callSite: (f, a) => f(...a)
|
|
162
|
-
});
|
|
163
|
-
try {
|
|
164
|
-
await this._protocol.destroy();
|
|
165
|
-
} catch (err) {
|
|
166
|
-
log.catch(err, {}, {
|
|
167
|
-
file: "connection.ts",
|
|
168
|
-
line: 148,
|
|
169
|
-
scope: this,
|
|
170
|
-
callSite: (f, a) => f(...a)
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
try {
|
|
174
|
-
await ((_a = this._transport) == null ? void 0 : _a.destroy());
|
|
175
|
-
} catch (err1) {
|
|
176
|
-
log.catch(err1, {}, {
|
|
177
|
-
file: "connection.ts",
|
|
178
|
-
line: 155,
|
|
179
|
-
scope: this,
|
|
180
|
-
callSite: (f, a) => f(...a)
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
log("closed", {
|
|
184
|
-
peerId: this.ownId
|
|
185
|
-
}, {
|
|
186
|
-
file: "connection.ts",
|
|
187
|
-
line: 158,
|
|
188
|
-
scope: this,
|
|
189
|
-
callSite: (f, a) => f(...a)
|
|
190
|
-
});
|
|
191
|
-
this._changeState(ConnectionState.CLOSED);
|
|
192
|
-
}
|
|
193
|
-
async signal(msg) {
|
|
194
|
-
var _a, _b;
|
|
195
|
-
assert(msg.sessionId);
|
|
196
|
-
if (!msg.sessionId.equals(this.sessionId)) {
|
|
197
|
-
log("dropping signal for incorrect session id", {}, {
|
|
198
|
-
file: "connection.ts",
|
|
199
|
-
line: 165,
|
|
200
|
-
scope: this,
|
|
201
|
-
callSite: (f, a) => f(...a)
|
|
202
|
-
});
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
assert(msg.data.signal);
|
|
206
|
-
assert((_a = msg.author) == null ? void 0 : _a.equals(this.remoteId));
|
|
207
|
-
assert((_b = msg.recipient) == null ? void 0 : _b.equals(this.ownId));
|
|
208
|
-
if (this._state === ConnectionState.INITIAL) {
|
|
209
|
-
log("buffered signal", {
|
|
210
|
-
peerId: this.ownId,
|
|
211
|
-
remoteId: this.remoteId,
|
|
212
|
-
msg: msg.data
|
|
213
|
-
}, {
|
|
214
|
-
file: "connection.ts",
|
|
215
|
-
line: 173,
|
|
216
|
-
scope: this,
|
|
217
|
-
callSite: (f, a) => f(...a)
|
|
218
|
-
});
|
|
219
|
-
this._bufferedSignals.push(msg.data.signal);
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
assert(this._transport, "Connection not ready to accept signals.");
|
|
223
|
-
log("received signal", {
|
|
224
|
-
peerId: this.ownId,
|
|
225
|
-
remoteId: this.remoteId,
|
|
226
|
-
msg: msg.data
|
|
227
|
-
}, {
|
|
228
|
-
file: "connection.ts",
|
|
229
|
-
line: 179,
|
|
230
|
-
scope: this,
|
|
231
|
-
callSite: (f, a) => f(...a)
|
|
232
|
-
});
|
|
233
|
-
await this._transport.signal(msg.data.signal);
|
|
234
|
-
}
|
|
235
|
-
_changeState(state) {
|
|
236
|
-
assert(state !== this._state, "Already in this state.");
|
|
237
|
-
this._state = state;
|
|
238
|
-
this.stateChanged.emit(state);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
__decorate([
|
|
242
|
-
synchronized
|
|
243
|
-
], Connection.prototype, "close", null);
|
|
244
|
-
|
|
245
|
-
// packages/core/mesh/network-manager/src/swarm/swarm.ts
|
|
246
|
-
import assert4 from "@dxos/node-std/assert";
|
|
247
|
-
import { Event as Event2, scheduleTask, sleep, synchronized as synchronized3 } from "@dxos/async";
|
|
248
|
-
import { Context } from "@dxos/context";
|
|
249
|
-
import { ErrorStream as ErrorStream2 } from "@dxos/debug";
|
|
250
|
-
import { PublicKey as PublicKey3 } from "@dxos/keys";
|
|
251
|
-
import { log as log4, logInfo } from "@dxos/log";
|
|
252
|
-
import { ComplexMap as ComplexMap2, isNotNullOrUndefined } from "@dxos/util";
|
|
18
|
+
import { ComplexMap as ComplexMap2 } from "@dxos/util";
|
|
253
19
|
|
|
254
|
-
// packages/core/mesh/network-manager/src/
|
|
255
|
-
import
|
|
20
|
+
// packages/core/mesh/network-manager/src/testing/test-wire-protocol.ts
|
|
21
|
+
import { asyncTimeout, Event } from "@dxos/async";
|
|
256
22
|
import { PublicKey } from "@dxos/keys";
|
|
257
|
-
import { log
|
|
258
|
-
import {
|
|
23
|
+
import { log } from "@dxos/log";
|
|
24
|
+
import { TestExtension } from "@dxos/teleport";
|
|
259
25
|
import { ComplexMap } from "@dxos/util";
|
|
260
|
-
var MessageRouter = class {
|
|
261
|
-
constructor({ sendMessage, onSignal, onOffer, topic }) {
|
|
262
|
-
this._offerRecords = new ComplexMap((key) => key.toHex());
|
|
263
|
-
this._sendMessage = sendMessage;
|
|
264
|
-
this._onSignal = onSignal;
|
|
265
|
-
this._onOffer = onOffer;
|
|
266
|
-
this._topic = topic;
|
|
267
|
-
}
|
|
268
|
-
async receiveMessage({ author, recipient, payload }) {
|
|
269
|
-
var _a, _b, _c;
|
|
270
|
-
if (payload.type_url !== "dxos.mesh.swarm.SwarmMessage") {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
const message = schema.getCodecForType("dxos.mesh.swarm.SwarmMessage").decode(payload.value);
|
|
274
|
-
if (!this._topic.equals(message.topic)) {
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
log2("received", {
|
|
278
|
-
from: author,
|
|
279
|
-
to: recipient,
|
|
280
|
-
msg: message
|
|
281
|
-
}, {
|
|
282
|
-
file: "message-router.ts",
|
|
283
|
-
line: 67,
|
|
284
|
-
scope: this,
|
|
285
|
-
callSite: (f, a) => f(...a)
|
|
286
|
-
});
|
|
287
|
-
if ((_a = message.data) == null ? void 0 : _a.offer) {
|
|
288
|
-
await this._handleOffer({
|
|
289
|
-
author,
|
|
290
|
-
recipient,
|
|
291
|
-
message
|
|
292
|
-
});
|
|
293
|
-
} else if ((_b = message.data) == null ? void 0 : _b.answer) {
|
|
294
|
-
await this._resolveAnswers(message);
|
|
295
|
-
} else if ((_c = message.data) == null ? void 0 : _c.signal) {
|
|
296
|
-
await this._handleSignal({
|
|
297
|
-
author,
|
|
298
|
-
recipient,
|
|
299
|
-
message
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
async signal(message) {
|
|
304
|
-
var _a;
|
|
305
|
-
assert2((_a = message.data) == null ? void 0 : _a.signal);
|
|
306
|
-
await this._sendReliableMessage({
|
|
307
|
-
author: message.author,
|
|
308
|
-
recipient: message.recipient,
|
|
309
|
-
message
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
async offer(message) {
|
|
313
|
-
const networkMessage = {
|
|
314
|
-
...message,
|
|
315
|
-
messageId: PublicKey.random()
|
|
316
|
-
};
|
|
317
|
-
return new Promise((resolve, reject) => {
|
|
318
|
-
this._offerRecords.set(networkMessage.messageId, {
|
|
319
|
-
resolve,
|
|
320
|
-
reject
|
|
321
|
-
});
|
|
322
|
-
return this._sendReliableMessage({
|
|
323
|
-
author: message.author,
|
|
324
|
-
recipient: message.recipient,
|
|
325
|
-
message: networkMessage
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
async _sendReliableMessage({ author, recipient, message }) {
|
|
330
|
-
var _a;
|
|
331
|
-
const networkMessage = {
|
|
332
|
-
...message,
|
|
333
|
-
// Setting unique message_id if it not specified yet.
|
|
334
|
-
messageId: (_a = message.messageId) != null ? _a : PublicKey.random()
|
|
335
|
-
};
|
|
336
|
-
log2("sending", {
|
|
337
|
-
from: author,
|
|
338
|
-
to: recipient,
|
|
339
|
-
msg: networkMessage
|
|
340
|
-
}, {
|
|
341
|
-
file: "message-router.ts",
|
|
342
|
-
line: 117,
|
|
343
|
-
scope: this,
|
|
344
|
-
callSite: (f, a) => f(...a)
|
|
345
|
-
});
|
|
346
|
-
await this._encodeAndSend({
|
|
347
|
-
author,
|
|
348
|
-
recipient,
|
|
349
|
-
message: networkMessage
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
async _encodeAndSend({ author, recipient, message }) {
|
|
353
|
-
await this._sendMessage({
|
|
354
|
-
author,
|
|
355
|
-
recipient,
|
|
356
|
-
payload: {
|
|
357
|
-
type_url: "dxos.mesh.swarm.SwarmMessage",
|
|
358
|
-
value: schema.getCodecForType("dxos.mesh.swarm.SwarmMessage").encode(message)
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
async _resolveAnswers(message) {
|
|
363
|
-
var _a, _b, _c;
|
|
364
|
-
assert2((_b = (_a = message.data) == null ? void 0 : _a.answer) == null ? void 0 : _b.offerMessageId, "No offerMessageId");
|
|
365
|
-
const offerRecord = this._offerRecords.get(message.data.answer.offerMessageId);
|
|
366
|
-
if (offerRecord) {
|
|
367
|
-
this._offerRecords.delete(message.data.answer.offerMessageId);
|
|
368
|
-
assert2((_c = message.data) == null ? void 0 : _c.answer, "No answer");
|
|
369
|
-
log2("resolving", {
|
|
370
|
-
answer: message.data.answer
|
|
371
|
-
}, {
|
|
372
|
-
file: "message-router.ts",
|
|
373
|
-
line: 146,
|
|
374
|
-
scope: this,
|
|
375
|
-
callSite: (f, a) => f(...a)
|
|
376
|
-
});
|
|
377
|
-
offerRecord.resolve(message.data.answer);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
async _handleOffer({ author, recipient, message }) {
|
|
381
|
-
assert2(message.data.offer, "No offer");
|
|
382
|
-
const offerMessage = {
|
|
383
|
-
author,
|
|
384
|
-
recipient,
|
|
385
|
-
...message,
|
|
386
|
-
data: {
|
|
387
|
-
offer: message.data.offer
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
const answer = await this._onOffer(offerMessage);
|
|
391
|
-
answer.offerMessageId = message.messageId;
|
|
392
|
-
await this._sendReliableMessage({
|
|
393
|
-
author: recipient,
|
|
394
|
-
recipient: author,
|
|
395
|
-
message: {
|
|
396
|
-
topic: message.topic,
|
|
397
|
-
sessionId: message.sessionId,
|
|
398
|
-
data: {
|
|
399
|
-
answer
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
async _handleSignal({ author, recipient, message }) {
|
|
405
|
-
assert2(message.messageId);
|
|
406
|
-
assert2(message.data.signal, "No Signal");
|
|
407
|
-
const signalMessage = {
|
|
408
|
-
author,
|
|
409
|
-
recipient,
|
|
410
|
-
...message,
|
|
411
|
-
data: {
|
|
412
|
-
signal: message.data.signal
|
|
413
|
-
}
|
|
414
|
-
};
|
|
415
|
-
await this._onSignal(signalMessage);
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
// packages/core/mesh/network-manager/src/swarm/peer.ts
|
|
420
|
-
import assert3 from "@dxos/node-std/assert";
|
|
421
|
-
import { synchronized as synchronized2 } from "@dxos/async";
|
|
422
|
-
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
423
|
-
import { log as log3 } from "@dxos/log";
|
|
424
|
-
var __decorate2 = function(decorators, target, key, desc) {
|
|
425
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
426
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
427
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
428
|
-
else
|
|
429
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
430
|
-
if (d = decorators[i])
|
|
431
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
432
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
433
|
-
};
|
|
434
|
-
var Peer = class {
|
|
435
|
-
constructor(id, topic, localPeerId, _signalMessaging, _protocolProvider, _transportFactory, _callbacks) {
|
|
436
|
-
this.id = id;
|
|
437
|
-
this.topic = topic;
|
|
438
|
-
this.localPeerId = localPeerId;
|
|
439
|
-
this._signalMessaging = _signalMessaging;
|
|
440
|
-
this._protocolProvider = _protocolProvider;
|
|
441
|
-
this._transportFactory = _transportFactory;
|
|
442
|
-
this._callbacks = _callbacks;
|
|
443
|
-
this.advertizing = false;
|
|
444
|
-
this.initiating = false;
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Respond to remote offer.
|
|
448
|
-
*/
|
|
449
|
-
async onOffer(message) {
|
|
450
|
-
const remoteId = message.author;
|
|
451
|
-
if (this.connection || this.initiating) {
|
|
452
|
-
if (remoteId.toHex() < this.localPeerId.toHex()) {
|
|
453
|
-
log3("closing local connection and accepting remote peer's offer", {
|
|
454
|
-
id: this.id,
|
|
455
|
-
topic: this.topic,
|
|
456
|
-
peerId: this.localPeerId
|
|
457
|
-
}, {
|
|
458
|
-
file: "peer.ts",
|
|
459
|
-
line: 84,
|
|
460
|
-
scope: this,
|
|
461
|
-
callSite: (f, a) => f(...a)
|
|
462
|
-
});
|
|
463
|
-
if (this.connection) {
|
|
464
|
-
await this.closeConnection();
|
|
465
|
-
}
|
|
466
|
-
} else {
|
|
467
|
-
return {
|
|
468
|
-
accept: false
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
if (await this._callbacks.onOffer(remoteId)) {
|
|
473
|
-
if (!this.connection) {
|
|
474
|
-
assert3(message.sessionId);
|
|
475
|
-
const connection = this._createConnection(false, message.sessionId);
|
|
476
|
-
try {
|
|
477
|
-
connection.openConnection();
|
|
478
|
-
} catch (err) {
|
|
479
|
-
log3.warn("connection error", {
|
|
480
|
-
topic: this.topic,
|
|
481
|
-
peerId: this.localPeerId,
|
|
482
|
-
remoteId: this.id,
|
|
483
|
-
err
|
|
484
|
-
}, {
|
|
485
|
-
file: "peer.ts",
|
|
486
|
-
line: 108,
|
|
487
|
-
scope: this,
|
|
488
|
-
callSite: (f, a) => f(...a)
|
|
489
|
-
});
|
|
490
|
-
await this.closeConnection();
|
|
491
|
-
}
|
|
492
|
-
return {
|
|
493
|
-
accept: true
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
return {
|
|
498
|
-
accept: false
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
/**
|
|
502
|
-
* Initiate a connection to the remote peer.
|
|
503
|
-
*/
|
|
504
|
-
async initiateConnection() {
|
|
505
|
-
assert3(!this.initiating, "Initiation in progress.");
|
|
506
|
-
assert3(!this.connection, "Already connected.");
|
|
507
|
-
const sessionId = PublicKey2.random();
|
|
508
|
-
log3("initiating...", {
|
|
509
|
-
id: this.id,
|
|
510
|
-
topic: this.topic,
|
|
511
|
-
peerId: this.id,
|
|
512
|
-
sessionId
|
|
513
|
-
}, {
|
|
514
|
-
file: "peer.ts",
|
|
515
|
-
line: 126,
|
|
516
|
-
scope: this,
|
|
517
|
-
callSite: (f, a) => f(...a)
|
|
518
|
-
});
|
|
519
|
-
const connection = this._createConnection(true, sessionId);
|
|
520
|
-
this.initiating = true;
|
|
521
|
-
try {
|
|
522
|
-
const answer = await this._signalMessaging.offer({
|
|
523
|
-
author: this.localPeerId,
|
|
524
|
-
recipient: this.id,
|
|
525
|
-
sessionId,
|
|
526
|
-
topic: this.topic,
|
|
527
|
-
data: {
|
|
528
|
-
offer: {}
|
|
529
|
-
}
|
|
530
|
-
});
|
|
531
|
-
log3("received", {
|
|
532
|
-
answer,
|
|
533
|
-
topic: this.topic,
|
|
534
|
-
ownId: this.localPeerId,
|
|
535
|
-
remoteId: this.id
|
|
536
|
-
}, {
|
|
537
|
-
file: "peer.ts",
|
|
538
|
-
line: 138,
|
|
539
|
-
scope: this,
|
|
540
|
-
callSite: (f, a) => f(...a)
|
|
541
|
-
});
|
|
542
|
-
if (connection.state !== ConnectionState.INITIAL) {
|
|
543
|
-
log3("ignoring response", {}, {
|
|
544
|
-
file: "peer.ts",
|
|
545
|
-
line: 140,
|
|
546
|
-
scope: this,
|
|
547
|
-
callSite: (f, a) => f(...a)
|
|
548
|
-
});
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
if (!answer.accept) {
|
|
552
|
-
this._callbacks.onRejected();
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
connection.openConnection();
|
|
556
|
-
this._callbacks.onAccepted();
|
|
557
|
-
} catch (err) {
|
|
558
|
-
log3.warn("initiation error", {
|
|
559
|
-
topic: this.topic,
|
|
560
|
-
peerId: this.localPeerId,
|
|
561
|
-
remoteId: this.id,
|
|
562
|
-
err
|
|
563
|
-
}, {
|
|
564
|
-
file: "peer.ts",
|
|
565
|
-
line: 151,
|
|
566
|
-
scope: this,
|
|
567
|
-
callSite: (f, a) => f(...a)
|
|
568
|
-
});
|
|
569
|
-
await this.closeConnection();
|
|
570
|
-
throw err;
|
|
571
|
-
} finally {
|
|
572
|
-
this.initiating = false;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* Create new connection.
|
|
577
|
-
* Either we're initiating a connection or creating one in response to an offer from the other peer.
|
|
578
|
-
*/
|
|
579
|
-
_createConnection(initiator, sessionId) {
|
|
580
|
-
log3("creating connection", {
|
|
581
|
-
topic: this.topic,
|
|
582
|
-
peerId: this.localPeerId,
|
|
583
|
-
remoteId: this.id,
|
|
584
|
-
initiator,
|
|
585
|
-
sessionId
|
|
586
|
-
}, {
|
|
587
|
-
file: "peer.ts",
|
|
588
|
-
line: 165,
|
|
589
|
-
scope: this,
|
|
590
|
-
callSite: (f, a) => f(...a)
|
|
591
|
-
});
|
|
592
|
-
assert3(!this.connection, "Already connected.");
|
|
593
|
-
const connection = new Connection(
|
|
594
|
-
this.topic,
|
|
595
|
-
this.localPeerId,
|
|
596
|
-
this.id,
|
|
597
|
-
sessionId,
|
|
598
|
-
initiator,
|
|
599
|
-
this._signalMessaging,
|
|
600
|
-
// TODO(dmaretskyi): Init only when connection is established.
|
|
601
|
-
this._protocolProvider({
|
|
602
|
-
initiator,
|
|
603
|
-
localPeerId: this.localPeerId,
|
|
604
|
-
remotePeerId: this.id,
|
|
605
|
-
topic: this.topic
|
|
606
|
-
}),
|
|
607
|
-
this._transportFactory
|
|
608
|
-
);
|
|
609
|
-
this._callbacks.onInitiated(connection);
|
|
610
|
-
connection.stateChanged.on((state) => {
|
|
611
|
-
switch (state) {
|
|
612
|
-
case ConnectionState.CONNECTED: {
|
|
613
|
-
this._callbacks.onConnected();
|
|
614
|
-
break;
|
|
615
|
-
}
|
|
616
|
-
case ConnectionState.CLOSED: {
|
|
617
|
-
log3("connection closed", {
|
|
618
|
-
topic: this.topic,
|
|
619
|
-
peerId: this.localPeerId,
|
|
620
|
-
remoteId: this.id,
|
|
621
|
-
initiator
|
|
622
|
-
}, {
|
|
623
|
-
file: "peer.ts",
|
|
624
|
-
line: 194,
|
|
625
|
-
scope: this,
|
|
626
|
-
callSite: (f, a) => f(...a)
|
|
627
|
-
});
|
|
628
|
-
assert3(this.connection === connection, "Connection mismatch (race condition).");
|
|
629
|
-
this.connection = void 0;
|
|
630
|
-
this._callbacks.onDisconnected();
|
|
631
|
-
break;
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
});
|
|
635
|
-
connection.errors.handle((err) => {
|
|
636
|
-
log3.warn("connection error", {
|
|
637
|
-
topic: this.topic,
|
|
638
|
-
peerId: this.localPeerId,
|
|
639
|
-
remoteId: this.id,
|
|
640
|
-
initiator,
|
|
641
|
-
err
|
|
642
|
-
}, {
|
|
643
|
-
file: "peer.ts",
|
|
644
|
-
line: 204,
|
|
645
|
-
scope: this,
|
|
646
|
-
callSite: (f, a) => f(...a)
|
|
647
|
-
});
|
|
648
|
-
void this.closeConnection();
|
|
649
|
-
});
|
|
650
|
-
this.connection = connection;
|
|
651
|
-
return connection;
|
|
652
|
-
}
|
|
653
|
-
async closeConnection() {
|
|
654
|
-
if (!this.connection) {
|
|
655
|
-
return;
|
|
656
|
-
}
|
|
657
|
-
const connection = this.connection;
|
|
658
|
-
log3("closing...", {
|
|
659
|
-
peerId: this.id,
|
|
660
|
-
sessionId: connection.sessionId
|
|
661
|
-
}, {
|
|
662
|
-
file: "peer.ts",
|
|
663
|
-
line: 220,
|
|
664
|
-
scope: this,
|
|
665
|
-
callSite: (f, a) => f(...a)
|
|
666
|
-
});
|
|
667
|
-
await connection.close();
|
|
668
|
-
log3("closed", {
|
|
669
|
-
peerId: this.id,
|
|
670
|
-
sessionId: connection.sessionId
|
|
671
|
-
}, {
|
|
672
|
-
file: "peer.ts",
|
|
673
|
-
line: 226,
|
|
674
|
-
scope: this,
|
|
675
|
-
callSite: (f, a) => f(...a)
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
async onSignal(message) {
|
|
679
|
-
if (!this.connection) {
|
|
680
|
-
log3("dropping signal message for non-existent connection", {
|
|
681
|
-
message
|
|
682
|
-
}, {
|
|
683
|
-
file: "peer.ts",
|
|
684
|
-
line: 231,
|
|
685
|
-
scope: this,
|
|
686
|
-
callSite: (f, a) => f(...a)
|
|
687
|
-
});
|
|
688
|
-
return;
|
|
689
|
-
}
|
|
690
|
-
await this.connection.signal(message);
|
|
691
|
-
}
|
|
692
|
-
async destroy() {
|
|
693
|
-
var _a;
|
|
694
|
-
log3("Destroying peer", {
|
|
695
|
-
peerId: this.id,
|
|
696
|
-
topic: this.topic
|
|
697
|
-
}, {
|
|
698
|
-
file: "peer.ts",
|
|
699
|
-
line: 239,
|
|
700
|
-
scope: this,
|
|
701
|
-
callSite: (f, a) => f(...a)
|
|
702
|
-
});
|
|
703
|
-
await ((_a = this == null ? void 0 : this.connection) == null ? void 0 : _a.close());
|
|
704
|
-
}
|
|
705
|
-
};
|
|
706
|
-
__decorate2([
|
|
707
|
-
synchronized2
|
|
708
|
-
], Peer.prototype, "destroy", null);
|
|
709
|
-
|
|
710
|
-
// packages/core/mesh/network-manager/src/swarm/swarm.ts
|
|
711
|
-
var __decorate3 = function(decorators, target, key, desc) {
|
|
712
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
713
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
714
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
715
|
-
else
|
|
716
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
717
|
-
if (d = decorators[i])
|
|
718
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
719
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
720
|
-
};
|
|
721
|
-
var INITIATION_DELAY = 100;
|
|
722
|
-
var getClassName = (obj) => Object.getPrototypeOf(obj).constructor.name;
|
|
723
|
-
var Swarm = class {
|
|
724
|
-
// TODO(burdon): Swarm => Peer.create/destroy =< Connection.open/close
|
|
725
|
-
// TODO(burdon): Split up properties.
|
|
726
|
-
constructor(_topic, _ownPeerId, _topology, _protocolProvider, _messenger, _transportFactory, _label) {
|
|
727
|
-
this._topic = _topic;
|
|
728
|
-
this._ownPeerId = _ownPeerId;
|
|
729
|
-
this._topology = _topology;
|
|
730
|
-
this._protocolProvider = _protocolProvider;
|
|
731
|
-
this._messenger = _messenger;
|
|
732
|
-
this._transportFactory = _transportFactory;
|
|
733
|
-
this._label = _label;
|
|
734
|
-
this._peers = new ComplexMap2(PublicKey3.hash);
|
|
735
|
-
this._ctx = new Context();
|
|
736
|
-
this.connectionAdded = new Event2();
|
|
737
|
-
this.disconnected = new Event2();
|
|
738
|
-
this.connected = new Event2();
|
|
739
|
-
this.errors = new ErrorStream2();
|
|
740
|
-
this.instanceId = PublicKey3.random();
|
|
741
|
-
log4("creating swarm", {
|
|
742
|
-
peerId: _ownPeerId
|
|
743
|
-
}, {
|
|
744
|
-
file: "swarm.ts",
|
|
745
|
-
line: 80,
|
|
746
|
-
scope: this,
|
|
747
|
-
callSite: (f, a) => f(...a)
|
|
748
|
-
});
|
|
749
|
-
_topology.init(this._getSwarmController());
|
|
750
|
-
this._swarmMessenger = new MessageRouter({
|
|
751
|
-
sendMessage: async (msg) => await this._messenger.sendMessage(msg),
|
|
752
|
-
onSignal: async (msg) => await this.onSignal(msg),
|
|
753
|
-
onOffer: async (msg) => await this.onOffer(msg),
|
|
754
|
-
topic: this._topic
|
|
755
|
-
});
|
|
756
|
-
this._messenger.listen({
|
|
757
|
-
peerId: this._ownPeerId,
|
|
758
|
-
payloadType: "dxos.mesh.swarm.SwarmMessage",
|
|
759
|
-
onMessage: async (message) => await this._swarmMessenger.receiveMessage(message)
|
|
760
|
-
}).catch((error) => log4.catch(error, {}, {
|
|
761
|
-
file: "swarm.ts",
|
|
762
|
-
line: 96,
|
|
763
|
-
scope: this,
|
|
764
|
-
callSite: (f, a) => f(...a)
|
|
765
|
-
}));
|
|
766
|
-
}
|
|
767
|
-
get connections() {
|
|
768
|
-
return Array.from(this._peers.values()).map((peer) => peer.connection).filter(isNotNullOrUndefined);
|
|
769
|
-
}
|
|
770
|
-
get ownPeerId() {
|
|
771
|
-
return this._ownPeerId;
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* Custom label assigned to this swarm. Used in devtools to display human-readable names for swarms.
|
|
775
|
-
*/
|
|
776
|
-
get label() {
|
|
777
|
-
return this._label;
|
|
778
|
-
}
|
|
779
|
-
get topic() {
|
|
780
|
-
return this._topic;
|
|
781
|
-
}
|
|
782
|
-
// TODO(burdon): async open?
|
|
783
|
-
async destroy() {
|
|
784
|
-
log4("destroying...", {}, {
|
|
785
|
-
file: "swarm.ts",
|
|
786
|
-
line: 124,
|
|
787
|
-
scope: this,
|
|
788
|
-
callSite: (f, a) => f(...a)
|
|
789
|
-
});
|
|
790
|
-
await this._ctx.dispose();
|
|
791
|
-
await this._topology.destroy();
|
|
792
|
-
await Promise.all(Array.from(this._peers.keys()).map((key) => this._destroyPeer(key)));
|
|
793
|
-
log4("destroyed", {}, {
|
|
794
|
-
file: "swarm.ts",
|
|
795
|
-
line: 128,
|
|
796
|
-
scope: this,
|
|
797
|
-
callSite: (f, a) => f(...a)
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
async setTopology(topology) {
|
|
801
|
-
assert4(!this._ctx.disposed, "Swarm is offline");
|
|
802
|
-
if (topology === this._topology) {
|
|
803
|
-
return;
|
|
804
|
-
}
|
|
805
|
-
log4("setting topology", {
|
|
806
|
-
previous: getClassName(this._topology),
|
|
807
|
-
topology: getClassName(topology)
|
|
808
|
-
}, {
|
|
809
|
-
file: "swarm.ts",
|
|
810
|
-
line: 136,
|
|
811
|
-
scope: this,
|
|
812
|
-
callSite: (f, a) => f(...a)
|
|
813
|
-
});
|
|
814
|
-
await this._topology.destroy();
|
|
815
|
-
this._topology = topology;
|
|
816
|
-
this._topology.init(this._getSwarmController());
|
|
817
|
-
this._topology.update();
|
|
818
|
-
}
|
|
819
|
-
onSwarmEvent(swarmEvent) {
|
|
820
|
-
log4("swarm event", {
|
|
821
|
-
swarmEvent
|
|
822
|
-
}, {
|
|
823
|
-
file: "swarm.ts",
|
|
824
|
-
line: 149,
|
|
825
|
-
scope: this,
|
|
826
|
-
callSite: (f, a) => f(...a)
|
|
827
|
-
});
|
|
828
|
-
if (swarmEvent.peerAvailable) {
|
|
829
|
-
if (this._ctx.disposed) {
|
|
830
|
-
log4.warn("ignored for offline swarm", {}, {
|
|
831
|
-
file: "swarm.ts",
|
|
832
|
-
line: 153,
|
|
833
|
-
scope: this,
|
|
834
|
-
callSite: (f, a) => f(...a)
|
|
835
|
-
});
|
|
836
|
-
return;
|
|
837
|
-
}
|
|
838
|
-
const peerId = PublicKey3.from(swarmEvent.peerAvailable.peer);
|
|
839
|
-
log4("new peer", {
|
|
840
|
-
peerId
|
|
841
|
-
}, {
|
|
842
|
-
file: "swarm.ts",
|
|
843
|
-
line: 157,
|
|
844
|
-
scope: this,
|
|
845
|
-
callSite: (f, a) => f(...a)
|
|
846
|
-
});
|
|
847
|
-
if (!peerId.equals(this._ownPeerId)) {
|
|
848
|
-
const peer = this._getOrCreatePeer(peerId);
|
|
849
|
-
peer.advertizing = true;
|
|
850
|
-
}
|
|
851
|
-
} else if (swarmEvent.peerLeft) {
|
|
852
|
-
const peer1 = this._peers.get(PublicKey3.from(swarmEvent.peerLeft.peer));
|
|
853
|
-
if (peer1) {
|
|
854
|
-
peer1.advertizing = false;
|
|
855
|
-
if (!peer1.connection || peer1.connection.state !== ConnectionState.CONNECTED) {
|
|
856
|
-
void this._destroyPeer(peer1.id).catch((err) => log4.catch(err, {}, {
|
|
857
|
-
file: "swarm.ts",
|
|
858
|
-
line: 168,
|
|
859
|
-
scope: this,
|
|
860
|
-
callSite: (f, a) => f(...a)
|
|
861
|
-
}));
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
this._topology.update();
|
|
866
|
-
}
|
|
867
|
-
async onOffer(message) {
|
|
868
|
-
var _a, _b;
|
|
869
|
-
log4("offer", {
|
|
870
|
-
message
|
|
871
|
-
}, {
|
|
872
|
-
file: "swarm.ts",
|
|
873
|
-
line: 178,
|
|
874
|
-
scope: this,
|
|
875
|
-
callSite: (f, a) => f(...a)
|
|
876
|
-
});
|
|
877
|
-
if (this._ctx.disposed) {
|
|
878
|
-
log4.info("ignored for offline swarm", {}, {
|
|
879
|
-
file: "swarm.ts",
|
|
880
|
-
line: 180,
|
|
881
|
-
scope: this,
|
|
882
|
-
callSite: (f, a) => f(...a)
|
|
883
|
-
});
|
|
884
|
-
return {
|
|
885
|
-
accept: false
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
|
-
assert4(message.author);
|
|
889
|
-
if (!((_a = message.recipient) == null ? void 0 : _a.equals(this._ownPeerId))) {
|
|
890
|
-
log4("rejecting offer with incorrect peerId", {
|
|
891
|
-
message
|
|
892
|
-
}, {
|
|
893
|
-
file: "swarm.ts",
|
|
894
|
-
line: 187,
|
|
895
|
-
scope: this,
|
|
896
|
-
callSite: (f, a) => f(...a)
|
|
897
|
-
});
|
|
898
|
-
return {
|
|
899
|
-
accept: false
|
|
900
|
-
};
|
|
901
|
-
}
|
|
902
|
-
if (!((_b = message.topic) == null ? void 0 : _b.equals(this._topic))) {
|
|
903
|
-
log4("rejecting offer with incorrect topic", {
|
|
904
|
-
message
|
|
905
|
-
}, {
|
|
906
|
-
file: "swarm.ts",
|
|
907
|
-
line: 191,
|
|
908
|
-
scope: this,
|
|
909
|
-
callSite: (f, a) => f(...a)
|
|
910
|
-
});
|
|
911
|
-
return {
|
|
912
|
-
accept: false
|
|
913
|
-
};
|
|
914
|
-
}
|
|
915
|
-
const peer = this._getOrCreatePeer(message.author);
|
|
916
|
-
const answer = await peer.onOffer(message);
|
|
917
|
-
this._topology.update();
|
|
918
|
-
return answer;
|
|
919
|
-
}
|
|
920
|
-
async onSignal(message) {
|
|
921
|
-
var _a, _b;
|
|
922
|
-
log4("signal", {
|
|
923
|
-
message
|
|
924
|
-
}, {
|
|
925
|
-
file: "swarm.ts",
|
|
926
|
-
line: 202,
|
|
927
|
-
scope: this,
|
|
928
|
-
callSite: (f, a) => f(...a)
|
|
929
|
-
});
|
|
930
|
-
if (this._ctx.disposed) {
|
|
931
|
-
log4.info("ignored for offline swarm", {}, {
|
|
932
|
-
file: "swarm.ts",
|
|
933
|
-
line: 204,
|
|
934
|
-
scope: this,
|
|
935
|
-
callSite: (f, a) => f(...a)
|
|
936
|
-
});
|
|
937
|
-
return;
|
|
938
|
-
}
|
|
939
|
-
assert4((_a = message.recipient) == null ? void 0 : _a.equals(this._ownPeerId), `Invalid signal peer id expected=${this.ownPeerId}, actual=${message.recipient}`);
|
|
940
|
-
assert4((_b = message.topic) == null ? void 0 : _b.equals(this._topic));
|
|
941
|
-
assert4(message.author);
|
|
942
|
-
const peer = this._getOrCreatePeer(message.author);
|
|
943
|
-
await peer.onSignal(message);
|
|
944
|
-
}
|
|
945
|
-
// For debug purposes
|
|
946
|
-
async goOffline() {
|
|
947
|
-
await this._ctx.dispose();
|
|
948
|
-
[
|
|
949
|
-
...this._peers.values()
|
|
950
|
-
].forEach((peer) => {
|
|
951
|
-
peer.advertizing = false;
|
|
952
|
-
});
|
|
953
|
-
await Promise.all([
|
|
954
|
-
...this._peers.keys()
|
|
955
|
-
].map((peerId) => this._closeConnection(peerId)));
|
|
956
|
-
}
|
|
957
|
-
// For debug purposes
|
|
958
|
-
async goOnline() {
|
|
959
|
-
this._ctx = new Context();
|
|
960
|
-
[
|
|
961
|
-
...this._peers.values()
|
|
962
|
-
].forEach((peer) => {
|
|
963
|
-
peer.advertizing = true;
|
|
964
|
-
});
|
|
965
|
-
this._topology.update();
|
|
966
|
-
}
|
|
967
|
-
_getOrCreatePeer(peerId) {
|
|
968
|
-
let peer = this._peers.get(peerId);
|
|
969
|
-
if (!peer) {
|
|
970
|
-
peer = new Peer(peerId, this._topic, this._ownPeerId, this._swarmMessenger, this._protocolProvider, this._transportFactory, {
|
|
971
|
-
onInitiated: (connection) => {
|
|
972
|
-
this.connectionAdded.emit(connection);
|
|
973
|
-
},
|
|
974
|
-
onConnected: () => {
|
|
975
|
-
this.connected.emit(peerId);
|
|
976
|
-
},
|
|
977
|
-
onDisconnected: async () => {
|
|
978
|
-
if (!peer.advertizing) {
|
|
979
|
-
await this._destroyPeer(peer.id);
|
|
980
|
-
}
|
|
981
|
-
this.disconnected.emit(peerId);
|
|
982
|
-
this._topology.update();
|
|
983
|
-
},
|
|
984
|
-
onRejected: () => {
|
|
985
|
-
if (this._peers.has(peerId)) {
|
|
986
|
-
void this._destroyPeer(peerId);
|
|
987
|
-
}
|
|
988
|
-
},
|
|
989
|
-
onAccepted: () => {
|
|
990
|
-
this._topology.update();
|
|
991
|
-
},
|
|
992
|
-
onOffer: (remoteId) => {
|
|
993
|
-
return this._topology.onOffer(remoteId);
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
this._peers.set(peerId, peer);
|
|
997
|
-
}
|
|
998
|
-
return peer;
|
|
999
|
-
}
|
|
1000
|
-
async _destroyPeer(peerId) {
|
|
1001
|
-
assert4(this._peers.has(peerId));
|
|
1002
|
-
await this._peers.get(peerId).destroy();
|
|
1003
|
-
this._peers.delete(peerId);
|
|
1004
|
-
}
|
|
1005
|
-
_getSwarmController() {
|
|
1006
|
-
return {
|
|
1007
|
-
getState: () => ({
|
|
1008
|
-
ownPeerId: this._ownPeerId,
|
|
1009
|
-
connected: Array.from(this._peers.values()).filter((peer) => peer.connection).map((peer) => peer.id),
|
|
1010
|
-
candidates: Array.from(this._peers.values()).filter((peer) => !peer.connection && peer.advertizing).map((peer) => peer.id)
|
|
1011
|
-
}),
|
|
1012
|
-
connect: (peer) => {
|
|
1013
|
-
if (this._ctx.disposed) {
|
|
1014
|
-
return;
|
|
1015
|
-
}
|
|
1016
|
-
scheduleTask(this._ctx, async () => {
|
|
1017
|
-
try {
|
|
1018
|
-
await this._initiateConnection(peer);
|
|
1019
|
-
} catch (err) {
|
|
1020
|
-
log4.warn("initiation error", err, {
|
|
1021
|
-
file: "swarm.ts",
|
|
1022
|
-
line: 311,
|
|
1023
|
-
scope: this,
|
|
1024
|
-
callSite: (f, a) => f(...a)
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
});
|
|
1028
|
-
},
|
|
1029
|
-
disconnect: async (peer) => {
|
|
1030
|
-
if (this._ctx.disposed) {
|
|
1031
|
-
return;
|
|
1032
|
-
}
|
|
1033
|
-
scheduleTask(this._ctx, async () => {
|
|
1034
|
-
await this._closeConnection(peer);
|
|
1035
|
-
this._topology.update();
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
};
|
|
1039
|
-
}
|
|
1040
|
-
/**
|
|
1041
|
-
* Creates a connection then sends message over signal network.
|
|
1042
|
-
*/
|
|
1043
|
-
async _initiateConnection(remoteId) {
|
|
1044
|
-
if (remoteId.toHex() < this._ownPeerId.toHex()) {
|
|
1045
|
-
log4("initiation delay", {
|
|
1046
|
-
remoteId
|
|
1047
|
-
}, {
|
|
1048
|
-
file: "swarm.ts",
|
|
1049
|
-
line: 336,
|
|
1050
|
-
scope: this,
|
|
1051
|
-
callSite: (f, a) => f(...a)
|
|
1052
|
-
});
|
|
1053
|
-
await sleep(INITIATION_DELAY);
|
|
1054
|
-
}
|
|
1055
|
-
if (this._ctx.disposed) {
|
|
1056
|
-
return;
|
|
1057
|
-
}
|
|
1058
|
-
const peer = this._getOrCreatePeer(remoteId);
|
|
1059
|
-
if (peer.connection) {
|
|
1060
|
-
return;
|
|
1061
|
-
}
|
|
1062
|
-
log4("initiating connection...", {
|
|
1063
|
-
remoteId
|
|
1064
|
-
}, {
|
|
1065
|
-
file: "swarm.ts",
|
|
1066
|
-
line: 350,
|
|
1067
|
-
scope: this,
|
|
1068
|
-
callSite: (f, a) => f(...a)
|
|
1069
|
-
});
|
|
1070
|
-
await peer.initiateConnection();
|
|
1071
|
-
this._topology.update();
|
|
1072
|
-
log4("initiated", {
|
|
1073
|
-
remoteId
|
|
1074
|
-
}, {
|
|
1075
|
-
file: "swarm.ts",
|
|
1076
|
-
line: 353,
|
|
1077
|
-
scope: this,
|
|
1078
|
-
callSite: (f, a) => f(...a)
|
|
1079
|
-
});
|
|
1080
|
-
}
|
|
1081
|
-
async _closeConnection(peerId) {
|
|
1082
|
-
const peer = this._peers.get(peerId);
|
|
1083
|
-
if (!peer) {
|
|
1084
|
-
return;
|
|
1085
|
-
}
|
|
1086
|
-
await peer.closeConnection();
|
|
1087
|
-
}
|
|
1088
|
-
};
|
|
1089
|
-
__decorate3([
|
|
1090
|
-
logInfo
|
|
1091
|
-
], Swarm.prototype, "instanceId", void 0);
|
|
1092
|
-
__decorate3([
|
|
1093
|
-
logInfo
|
|
1094
|
-
], Swarm.prototype, "ownPeerId", null);
|
|
1095
|
-
__decorate3([
|
|
1096
|
-
logInfo
|
|
1097
|
-
], Swarm.prototype, "topic", null);
|
|
1098
|
-
__decorate3([
|
|
1099
|
-
synchronized3
|
|
1100
|
-
], Swarm.prototype, "onSwarmEvent", null);
|
|
1101
|
-
__decorate3([
|
|
1102
|
-
synchronized3
|
|
1103
|
-
], Swarm.prototype, "onOffer", null);
|
|
1104
|
-
__decorate3([
|
|
1105
|
-
synchronized3
|
|
1106
|
-
], Swarm.prototype, "goOnline", null);
|
|
1107
|
-
|
|
1108
|
-
// packages/core/mesh/network-manager/src/swarm/swarm-mapper.ts
|
|
1109
|
-
import { Event as Event3, EventSubscriptions } from "@dxos/async";
|
|
1110
|
-
import { PublicKey as PublicKey4 } from "@dxos/keys";
|
|
1111
|
-
import { log as log5 } from "@dxos/log";
|
|
1112
|
-
import { ComplexMap as ComplexMap3 } from "@dxos/util";
|
|
1113
|
-
var SwarmMapper = class {
|
|
1114
|
-
get peers() {
|
|
1115
|
-
return Array.from(this._peers.values());
|
|
1116
|
-
}
|
|
1117
|
-
// prettier-ignore
|
|
1118
|
-
constructor(_swarm) {
|
|
1119
|
-
this._swarm = _swarm;
|
|
1120
|
-
this._subscriptions = new EventSubscriptions();
|
|
1121
|
-
this._connectionSubscriptions = new ComplexMap3(PublicKey4.hash);
|
|
1122
|
-
this._peers = new ComplexMap3(PublicKey4.hash);
|
|
1123
|
-
this.mapUpdated = new Event3();
|
|
1124
|
-
this._subscriptions.add(_swarm.connectionAdded.on((connection) => {
|
|
1125
|
-
this._update();
|
|
1126
|
-
this._connectionSubscriptions.set(connection.remoteId, connection.stateChanged.on(() => {
|
|
1127
|
-
this._update();
|
|
1128
|
-
}));
|
|
1129
|
-
}));
|
|
1130
|
-
this._subscriptions.add(_swarm.disconnected.on((peerId) => {
|
|
1131
|
-
var _a;
|
|
1132
|
-
(_a = this._connectionSubscriptions.get(peerId)) == null ? void 0 : _a();
|
|
1133
|
-
this._connectionSubscriptions.delete(peerId);
|
|
1134
|
-
this._update();
|
|
1135
|
-
}));
|
|
1136
|
-
this._update();
|
|
1137
|
-
}
|
|
1138
|
-
_update() {
|
|
1139
|
-
log5("updating swarm", {}, {
|
|
1140
|
-
file: "swarm-mapper.ts",
|
|
1141
|
-
line: 75,
|
|
1142
|
-
scope: this,
|
|
1143
|
-
callSite: (f, a) => f(...a)
|
|
1144
|
-
});
|
|
1145
|
-
this._peers.clear();
|
|
1146
|
-
this._peers.set(this._swarm.ownPeerId, {
|
|
1147
|
-
id: this._swarm.ownPeerId,
|
|
1148
|
-
state: "ME",
|
|
1149
|
-
connections: []
|
|
1150
|
-
});
|
|
1151
|
-
for (const connection of this._swarm.connections) {
|
|
1152
|
-
this._peers.set(connection.remoteId, {
|
|
1153
|
-
id: connection.remoteId,
|
|
1154
|
-
state: connection.state,
|
|
1155
|
-
connections: [
|
|
1156
|
-
this._swarm.ownPeerId
|
|
1157
|
-
]
|
|
1158
|
-
});
|
|
1159
|
-
}
|
|
1160
|
-
log5("graph changed", {
|
|
1161
|
-
directConnections: this._swarm.connections.length,
|
|
1162
|
-
totalPeersInSwarm: this._peers.size
|
|
1163
|
-
}, {
|
|
1164
|
-
file: "swarm-mapper.ts",
|
|
1165
|
-
line: 116,
|
|
1166
|
-
scope: this,
|
|
1167
|
-
callSite: (f, a) => f(...a)
|
|
1168
|
-
});
|
|
1169
|
-
this.mapUpdated.emit(Array.from(this._peers.values()));
|
|
1170
|
-
}
|
|
1171
|
-
// TODO(burdon): Async open/close.
|
|
1172
|
-
destroy() {
|
|
1173
|
-
Array.from(this._connectionSubscriptions.values()).forEach((cb) => cb());
|
|
1174
|
-
this._subscriptions.clear();
|
|
1175
|
-
}
|
|
1176
|
-
};
|
|
1177
|
-
|
|
1178
|
-
// packages/core/mesh/network-manager/src/connection-log.ts
|
|
1179
|
-
var EventType;
|
|
1180
|
-
(function(EventType2) {
|
|
1181
|
-
EventType2["CONNECTION_STATE_CHANGED"] = "CONNECTION_STATE_CHANGED";
|
|
1182
|
-
EventType2["PROTOCOL_ERROR"] = "PROTOCOL_ERROR";
|
|
1183
|
-
EventType2["PROTOCOL_EXTENSIONS_INITIALIZED"] = "PROTOCOL_EXTENSIONS_INITIALIZED";
|
|
1184
|
-
EventType2["PROTOCOL_EXTENSIONS_HANDSHAKE"] = "PROTOCOL_EXTENSIONS_HANDSHAKE";
|
|
1185
|
-
EventType2["PROTOCOL_HANDSHAKE"] = "PROTOCOL_HANDSHAKE";
|
|
1186
|
-
})(EventType || (EventType = {}));
|
|
1187
|
-
var ConnectionLog = class {
|
|
1188
|
-
constructor() {
|
|
1189
|
-
/**
|
|
1190
|
-
* SwarmId => info
|
|
1191
|
-
*/
|
|
1192
|
-
this._swarms = new ComplexMap4(PublicKey5.hash);
|
|
1193
|
-
this.update = new Event4();
|
|
1194
|
-
}
|
|
1195
|
-
getSwarmInfo(swarmId) {
|
|
1196
|
-
var _a;
|
|
1197
|
-
return (_a = this._swarms.get(swarmId)) != null ? _a : raise(new Error(`Swarm not found: ${swarmId}`));
|
|
1198
|
-
}
|
|
1199
|
-
get swarms() {
|
|
1200
|
-
return Array.from(this._swarms.values());
|
|
1201
|
-
}
|
|
1202
|
-
swarmJoined(swarm) {
|
|
1203
|
-
const info = {
|
|
1204
|
-
id: swarm.instanceId,
|
|
1205
|
-
topic: swarm.topic,
|
|
1206
|
-
isActive: true,
|
|
1207
|
-
label: swarm.label,
|
|
1208
|
-
connections: []
|
|
1209
|
-
};
|
|
1210
|
-
this._swarms.set(swarm.instanceId, info);
|
|
1211
|
-
this.update.emit();
|
|
1212
|
-
swarm.connectionAdded.on((connection) => {
|
|
1213
|
-
const connectionInfo = {
|
|
1214
|
-
state: ConnectionState.INITIAL,
|
|
1215
|
-
remotePeerId: connection.remoteId,
|
|
1216
|
-
sessionId: connection.sessionId,
|
|
1217
|
-
transport: connection.transport && Object.getPrototypeOf(connection.transport).constructor.name,
|
|
1218
|
-
protocolExtensions: [],
|
|
1219
|
-
events: []
|
|
1220
|
-
};
|
|
1221
|
-
info.connections.push(connectionInfo);
|
|
1222
|
-
this.update.emit();
|
|
1223
|
-
connection.stateChanged.on((state) => {
|
|
1224
|
-
connectionInfo.state = state;
|
|
1225
|
-
connectionInfo.events.push({
|
|
1226
|
-
type: EventType.CONNECTION_STATE_CHANGED,
|
|
1227
|
-
newState: state
|
|
1228
|
-
});
|
|
1229
|
-
this.update.emit();
|
|
1230
|
-
});
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
swarmLeft(swarm) {
|
|
1234
|
-
this.getSwarmInfo(swarm.instanceId).isActive = false;
|
|
1235
|
-
this.update.emit();
|
|
1236
|
-
}
|
|
1237
|
-
};
|
|
1238
|
-
|
|
1239
|
-
// packages/core/mesh/network-manager/src/network-manager.ts
|
|
1240
|
-
var NetworkManager = class {
|
|
1241
|
-
constructor({ transportFactory, signalManager, log: log14 }) {
|
|
1242
|
-
this._swarms = new ComplexMap5(PublicKey6.hash);
|
|
1243
|
-
this._mappers = new ComplexMap5(PublicKey6.hash);
|
|
1244
|
-
this._connectionState = ConnectionState2.ONLINE;
|
|
1245
|
-
this.connectionStateChanged = new Event5();
|
|
1246
|
-
this.topicsUpdated = new Event5();
|
|
1247
|
-
this._transportFactory = transportFactory;
|
|
1248
|
-
this._signalManager = signalManager;
|
|
1249
|
-
this._signalManager.swarmEvent.on(({ topic, swarmEvent: event }) => {
|
|
1250
|
-
var _a;
|
|
1251
|
-
return (_a = this._swarms.get(topic)) == null ? void 0 : _a.onSwarmEvent(event);
|
|
1252
|
-
});
|
|
1253
|
-
this._messenger = new Messenger({
|
|
1254
|
-
signalManager: this._signalManager
|
|
1255
|
-
});
|
|
1256
|
-
this._signalConnection = {
|
|
1257
|
-
join: (opts) => this._signalManager.join(opts),
|
|
1258
|
-
leave: (opts) => this._signalManager.leave(opts)
|
|
1259
|
-
};
|
|
1260
|
-
if (log14) {
|
|
1261
|
-
this._connectionLog = new ConnectionLog();
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
// TODO(burdon): Remove access (Devtools only).
|
|
1265
|
-
get connectionLog() {
|
|
1266
|
-
return this._connectionLog;
|
|
1267
|
-
}
|
|
1268
|
-
// TODO(burdon): Remove access (Devtools only).
|
|
1269
|
-
get signalManager() {
|
|
1270
|
-
return this._signalManager;
|
|
1271
|
-
}
|
|
1272
|
-
get connectionState() {
|
|
1273
|
-
return this._connectionState;
|
|
1274
|
-
}
|
|
1275
|
-
// TODO(burdon): Reconcile with "discovery_key".
|
|
1276
|
-
get topics() {
|
|
1277
|
-
return Array.from(this._swarms.keys());
|
|
1278
|
-
}
|
|
1279
|
-
getSwarmMap(topic) {
|
|
1280
|
-
return this._mappers.get(topic);
|
|
1281
|
-
}
|
|
1282
|
-
getSwarm(topic) {
|
|
1283
|
-
return this._swarms.get(topic);
|
|
1284
|
-
}
|
|
1285
|
-
async open() {
|
|
1286
|
-
await this._messenger.open();
|
|
1287
|
-
await this._signalManager.open();
|
|
1288
|
-
}
|
|
1289
|
-
async close() {
|
|
1290
|
-
for (const topic of this._swarms.keys()) {
|
|
1291
|
-
await this.leaveSwarm(topic).catch((err) => {
|
|
1292
|
-
log6(err, {}, {
|
|
1293
|
-
file: "network-manager.ts",
|
|
1294
|
-
line: 136,
|
|
1295
|
-
scope: this,
|
|
1296
|
-
callSite: (f, a) => f(...a)
|
|
1297
|
-
});
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
|
-
await this._messenger.close();
|
|
1301
|
-
await this._signalManager.close();
|
|
1302
|
-
}
|
|
1303
|
-
/**
|
|
1304
|
-
* Join the swarm.
|
|
1305
|
-
*/
|
|
1306
|
-
async joinSwarm({ topic, peerId, topology, protocolProvider: protocol, label }) {
|
|
1307
|
-
var _a;
|
|
1308
|
-
assert5(PublicKey6.isPublicKey(topic));
|
|
1309
|
-
assert5(PublicKey6.isPublicKey(peerId));
|
|
1310
|
-
assert5(topology);
|
|
1311
|
-
assert5(typeof protocol === "function");
|
|
1312
|
-
if (this._swarms.has(topic)) {
|
|
1313
|
-
throw new Error(`Already connected to swarm: ${PublicKey6.from(topic)}`);
|
|
1314
|
-
}
|
|
1315
|
-
log6("joining", {
|
|
1316
|
-
topic: PublicKey6.from(topic),
|
|
1317
|
-
peerId,
|
|
1318
|
-
topology: topology.toString()
|
|
1319
|
-
}, {
|
|
1320
|
-
file: "network-manager.ts",
|
|
1321
|
-
line: 162,
|
|
1322
|
-
scope: this,
|
|
1323
|
-
callSite: (f, a) => f(...a)
|
|
1324
|
-
});
|
|
1325
|
-
const swarm = new Swarm(topic, peerId, topology, protocol, this._messenger, this._transportFactory, label);
|
|
1326
|
-
swarm.errors.handle((error) => {
|
|
1327
|
-
log6("swarm error", {
|
|
1328
|
-
error
|
|
1329
|
-
}, {
|
|
1330
|
-
file: "network-manager.ts",
|
|
1331
|
-
line: 165,
|
|
1332
|
-
scope: this,
|
|
1333
|
-
callSite: (f, a) => f(...a)
|
|
1334
|
-
});
|
|
1335
|
-
});
|
|
1336
|
-
this._swarms.set(topic, swarm);
|
|
1337
|
-
this._signalConnection.join({
|
|
1338
|
-
topic,
|
|
1339
|
-
peerId
|
|
1340
|
-
}).catch((error) => log6.catch(error, {}, {
|
|
1341
|
-
file: "network-manager.ts",
|
|
1342
|
-
line: 169,
|
|
1343
|
-
scope: this,
|
|
1344
|
-
callSite: (f, a) => f(...a)
|
|
1345
|
-
}));
|
|
1346
|
-
this._mappers.set(topic, new SwarmMapper(swarm));
|
|
1347
|
-
this.topicsUpdated.emit();
|
|
1348
|
-
(_a = this._connectionLog) == null ? void 0 : _a.swarmJoined(swarm);
|
|
1349
|
-
log6("joined", {
|
|
1350
|
-
topic: PublicKey6.from(topic),
|
|
1351
|
-
count: this._swarms.size
|
|
1352
|
-
}, {
|
|
1353
|
-
file: "network-manager.ts",
|
|
1354
|
-
line: 174,
|
|
1355
|
-
scope: this,
|
|
1356
|
-
callSite: (f, a) => f(...a)
|
|
1357
|
-
});
|
|
1358
|
-
return {
|
|
1359
|
-
close: () => this.leaveSwarm(topic)
|
|
1360
|
-
};
|
|
1361
|
-
}
|
|
1362
|
-
/**
|
|
1363
|
-
* Close the connection.
|
|
1364
|
-
*/
|
|
1365
|
-
async leaveSwarm(topic) {
|
|
1366
|
-
var _a;
|
|
1367
|
-
if (!this._swarms.has(topic)) {
|
|
1368
|
-
log6.warn("swarm not open", {
|
|
1369
|
-
topic: PublicKey6.from(topic).truncate()
|
|
1370
|
-
}, {
|
|
1371
|
-
file: "network-manager.ts",
|
|
1372
|
-
line: 186,
|
|
1373
|
-
scope: this,
|
|
1374
|
-
callSite: (f, a) => f(...a)
|
|
1375
|
-
});
|
|
1376
|
-
return;
|
|
1377
|
-
}
|
|
1378
|
-
log6("leaving", {
|
|
1379
|
-
topic: PublicKey6.from(topic)
|
|
1380
|
-
}, {
|
|
1381
|
-
file: "network-manager.ts",
|
|
1382
|
-
line: 190,
|
|
1383
|
-
scope: this,
|
|
1384
|
-
callSite: (f, a) => f(...a)
|
|
1385
|
-
});
|
|
1386
|
-
const swarm = this._swarms.get(topic);
|
|
1387
|
-
await this._signalConnection.leave({
|
|
1388
|
-
topic,
|
|
1389
|
-
peerId: swarm.ownPeerId
|
|
1390
|
-
});
|
|
1391
|
-
const map = this._mappers.get(topic);
|
|
1392
|
-
map.destroy();
|
|
1393
|
-
this._mappers.delete(topic);
|
|
1394
|
-
(_a = this._connectionLog) == null ? void 0 : _a.swarmLeft(swarm);
|
|
1395
|
-
await swarm.destroy();
|
|
1396
|
-
this._swarms.delete(topic);
|
|
1397
|
-
await this.topicsUpdated.emit();
|
|
1398
|
-
log6("left", {
|
|
1399
|
-
topic: PublicKey6.from(topic),
|
|
1400
|
-
count: this._swarms.size
|
|
1401
|
-
}, {
|
|
1402
|
-
file: "network-manager.ts",
|
|
1403
|
-
line: 204,
|
|
1404
|
-
scope: this,
|
|
1405
|
-
callSite: (f, a) => f(...a)
|
|
1406
|
-
});
|
|
1407
|
-
}
|
|
1408
|
-
async setConnectionState(state) {
|
|
1409
|
-
if (state === this._connectionState) {
|
|
1410
|
-
return;
|
|
1411
|
-
}
|
|
1412
|
-
switch (state) {
|
|
1413
|
-
case ConnectionState2.OFFLINE: {
|
|
1414
|
-
this._connectionState = state;
|
|
1415
|
-
await this._messenger.close();
|
|
1416
|
-
await this._signalManager.close();
|
|
1417
|
-
await Promise.all([
|
|
1418
|
-
...this._swarms.values()
|
|
1419
|
-
].map((swarm) => swarm.goOffline()));
|
|
1420
|
-
break;
|
|
1421
|
-
}
|
|
1422
|
-
case ConnectionState2.ONLINE: {
|
|
1423
|
-
this._connectionState = state;
|
|
1424
|
-
this._messenger.open();
|
|
1425
|
-
await this._signalManager.open();
|
|
1426
|
-
await Promise.all([
|
|
1427
|
-
...this._swarms.values()
|
|
1428
|
-
].map((swarm) => swarm.goOnline()));
|
|
1429
|
-
break;
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
this.connectionStateChanged.emit(this._connectionState);
|
|
1433
|
-
}
|
|
1434
|
-
};
|
|
1435
|
-
|
|
1436
|
-
// packages/core/mesh/network-manager/src/topology/fully-connected-topology.ts
|
|
1437
|
-
import assert6 from "@dxos/node-std/assert";
|
|
1438
|
-
var FullyConnectedTopology = class {
|
|
1439
|
-
toString() {
|
|
1440
|
-
return "FullyConnectedTopology";
|
|
1441
|
-
}
|
|
1442
|
-
init(controller) {
|
|
1443
|
-
assert6(!this._controller, "Already initialized");
|
|
1444
|
-
this._controller = controller;
|
|
1445
|
-
}
|
|
1446
|
-
update() {
|
|
1447
|
-
assert6(this._controller, "Not initialized");
|
|
1448
|
-
const { candidates: discovered } = this._controller.getState();
|
|
1449
|
-
for (const peer of discovered) {
|
|
1450
|
-
this._controller.connect(peer);
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
async onOffer(peer) {
|
|
1454
|
-
return true;
|
|
1455
|
-
}
|
|
1456
|
-
async destroy() {
|
|
1457
|
-
}
|
|
1458
|
-
};
|
|
1459
|
-
|
|
1460
|
-
// packages/core/mesh/network-manager/src/topology/mmst-topology.ts
|
|
1461
|
-
import assert7 from "@dxos/node-std/assert";
|
|
1462
|
-
import distance from "xor-distance";
|
|
1463
|
-
import { log as log7 } from "@dxos/log";
|
|
1464
|
-
|
|
1465
|
-
// packages/core/mesh/network-manager/src/topology/star-topology.ts
|
|
1466
|
-
import assert8 from "@dxos/node-std/assert";
|
|
1467
|
-
import { log as log8 } from "@dxos/log";
|
|
1468
|
-
|
|
1469
|
-
// packages/core/mesh/network-manager/src/transport/memory-transport.ts
|
|
1470
|
-
import assert9 from "@dxos/node-std/assert";
|
|
1471
|
-
import { Transform } from "@dxos/node-std/stream";
|
|
1472
|
-
import { Event as Event6, Trigger } from "@dxos/async";
|
|
1473
|
-
import { ErrorStream as ErrorStream3 } from "@dxos/debug";
|
|
1474
|
-
import { PublicKey as PublicKey7 } from "@dxos/keys";
|
|
1475
|
-
import { log as log9, logInfo as logInfo2 } from "@dxos/log";
|
|
1476
|
-
import { ComplexMap as ComplexMap6 } from "@dxos/util";
|
|
1477
|
-
var __decorate4 = function(decorators, target, key, desc) {
|
|
1478
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1479
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
1480
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
1481
|
-
else
|
|
1482
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
1483
|
-
if (d = decorators[i])
|
|
1484
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1485
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1486
|
-
};
|
|
1487
|
-
var MEMORY_TRANSPORT_DELAY = 1;
|
|
1488
|
-
var createStreamDelay = (delay) => {
|
|
1489
|
-
return new Transform({
|
|
1490
|
-
objectMode: true,
|
|
1491
|
-
transform: (chunk, _, cb) => {
|
|
1492
|
-
setTimeout(() => cb(null, chunk), delay);
|
|
1493
|
-
}
|
|
1494
|
-
});
|
|
1495
|
-
};
|
|
1496
|
-
var MemoryTransportFactory = {
|
|
1497
|
-
createTransport: (params) => new MemoryTransport(params)
|
|
1498
|
-
};
|
|
1499
|
-
var _MemoryTransport = class {
|
|
1500
|
-
constructor(options) {
|
|
1501
|
-
var _a;
|
|
1502
|
-
this.options = options;
|
|
1503
|
-
this.closed = new Event6();
|
|
1504
|
-
this.connected = new Event6();
|
|
1505
|
-
this.errors = new ErrorStream3();
|
|
1506
|
-
this._remote = new Trigger();
|
|
1507
|
-
this._outgoingDelay = createStreamDelay(MEMORY_TRANSPORT_DELAY);
|
|
1508
|
-
this._incomingDelay = createStreamDelay(MEMORY_TRANSPORT_DELAY);
|
|
1509
|
-
this._destroyed = false;
|
|
1510
|
-
this._instanceId = PublicKey7.random();
|
|
1511
|
-
log9("creating", {}, {
|
|
1512
|
-
file: "memory-transport.ts",
|
|
1513
|
-
line: 64,
|
|
1514
|
-
scope: this,
|
|
1515
|
-
callSite: (f, a) => f(...a)
|
|
1516
|
-
});
|
|
1517
|
-
assert9(!_MemoryTransport._connections.has(this._instanceId), "Duplicate memory connection");
|
|
1518
|
-
_MemoryTransport._connections.set(this._instanceId, this);
|
|
1519
|
-
if (this.options.initiator) {
|
|
1520
|
-
setTimeout(async () => {
|
|
1521
|
-
log9("sending signal", {}, {
|
|
1522
|
-
file: "memory-transport.ts",
|
|
1523
|
-
line: 73,
|
|
1524
|
-
scope: this,
|
|
1525
|
-
callSite: (f, a) => f(...a)
|
|
1526
|
-
});
|
|
1527
|
-
void this.options.sendSignal({
|
|
1528
|
-
payload: {
|
|
1529
|
-
transportId: this._instanceId.toHex()
|
|
1530
|
-
}
|
|
1531
|
-
});
|
|
1532
|
-
});
|
|
1533
|
-
} else {
|
|
1534
|
-
this._remote.wait({
|
|
1535
|
-
timeout: (_a = this.options.timeout) != null ? _a : 1e3
|
|
1536
|
-
}).then((remoteId) => {
|
|
1537
|
-
if (this._destroyed) {
|
|
1538
|
-
return;
|
|
1539
|
-
}
|
|
1540
|
-
this._remoteInstanceId = remoteId;
|
|
1541
|
-
this._remoteConnection = _MemoryTransport._connections.get(this._remoteInstanceId);
|
|
1542
|
-
if (!this._remoteConnection) {
|
|
1543
|
-
this._destroyed = true;
|
|
1544
|
-
this.closed.emit();
|
|
1545
|
-
return;
|
|
1546
|
-
}
|
|
1547
|
-
assert9(!this._remoteConnection._remoteConnection, new Error(`Remote already connected: ${this._remoteInstanceId}`));
|
|
1548
|
-
this._remoteConnection._remoteConnection = this;
|
|
1549
|
-
this._remoteConnection._remoteInstanceId = this._instanceId;
|
|
1550
|
-
log9("connected", {}, {
|
|
1551
|
-
file: "memory-transport.ts",
|
|
1552
|
-
line: 102,
|
|
1553
|
-
scope: this,
|
|
1554
|
-
callSite: (f, a) => f(...a)
|
|
1555
|
-
});
|
|
1556
|
-
this.options.stream.pipe(this._outgoingDelay).pipe(this._remoteConnection.options.stream).pipe(this._incomingDelay).pipe(this.options.stream);
|
|
1557
|
-
this.connected.emit();
|
|
1558
|
-
this._remoteConnection.connected.emit();
|
|
1559
|
-
}).catch((err) => {
|
|
1560
|
-
if (this._destroyed) {
|
|
1561
|
-
return;
|
|
1562
|
-
}
|
|
1563
|
-
this.errors.raise(err);
|
|
1564
|
-
});
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
async destroy() {
|
|
1568
|
-
log9("closing", {}, {
|
|
1569
|
-
file: "memory-transport.ts",
|
|
1570
|
-
line: 123,
|
|
1571
|
-
scope: this,
|
|
1572
|
-
callSite: (f, a) => f(...a)
|
|
1573
|
-
});
|
|
1574
|
-
this._destroyed = true;
|
|
1575
|
-
_MemoryTransport._connections.delete(this._instanceId);
|
|
1576
|
-
if (this._remoteConnection) {
|
|
1577
|
-
log9("closing", {}, {
|
|
1578
|
-
file: "memory-transport.ts",
|
|
1579
|
-
line: 128,
|
|
1580
|
-
scope: this,
|
|
1581
|
-
callSite: (f, a) => f(...a)
|
|
1582
|
-
});
|
|
1583
|
-
this._remoteConnection._destroyed = true;
|
|
1584
|
-
_MemoryTransport._connections.delete(this._remoteInstanceId);
|
|
1585
|
-
this._outgoingDelay.unpipe();
|
|
1586
|
-
this._incomingDelay.unpipe();
|
|
1587
|
-
this._remoteConnection.closed.emit();
|
|
1588
|
-
this._remoteConnection._remoteConnection = void 0;
|
|
1589
|
-
this._remoteConnection = void 0;
|
|
1590
|
-
log9("closed", {}, {
|
|
1591
|
-
file: "memory-transport.ts",
|
|
1592
|
-
line: 146,
|
|
1593
|
-
scope: this,
|
|
1594
|
-
callSite: (f, a) => f(...a)
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1597
|
-
this.closed.emit();
|
|
1598
|
-
log9("closed", {}, {
|
|
1599
|
-
file: "memory-transport.ts",
|
|
1600
|
-
line: 150,
|
|
1601
|
-
scope: this,
|
|
1602
|
-
callSite: (f, a) => f(...a)
|
|
1603
|
-
});
|
|
1604
|
-
}
|
|
1605
|
-
signal({ payload }) {
|
|
1606
|
-
log9("received signal", {
|
|
1607
|
-
payload
|
|
1608
|
-
}, {
|
|
1609
|
-
file: "memory-transport.ts",
|
|
1610
|
-
line: 154,
|
|
1611
|
-
scope: this,
|
|
1612
|
-
callSite: (f, a) => f(...a)
|
|
1613
|
-
});
|
|
1614
|
-
if (!(payload == null ? void 0 : payload.transportId)) {
|
|
1615
|
-
return;
|
|
1616
|
-
}
|
|
1617
|
-
const transportId = payload.transportId;
|
|
1618
|
-
if (transportId) {
|
|
1619
|
-
const remoteId = PublicKey7.fromHex(transportId);
|
|
1620
|
-
this._remote.wake(remoteId);
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
};
|
|
1624
|
-
var MemoryTransport = _MemoryTransport;
|
|
1625
|
-
// TODO(burdon): Remove static properties (inject context into constructor).
|
|
1626
|
-
MemoryTransport._connections = new ComplexMap6(PublicKey7.hash);
|
|
1627
|
-
__decorate4([
|
|
1628
|
-
logInfo2
|
|
1629
|
-
], MemoryTransport.prototype, "_instanceId", void 0);
|
|
1630
|
-
__decorate4([
|
|
1631
|
-
logInfo2
|
|
1632
|
-
], MemoryTransport.prototype, "_remoteInstanceId", void 0);
|
|
1633
|
-
|
|
1634
|
-
// packages/core/mesh/network-manager/src/transport/webrtc-transport.ts
|
|
1635
|
-
import assert10 from "@dxos/node-std/assert";
|
|
1636
|
-
import SimplePeerConstructor from "simple-peer";
|
|
1637
|
-
import { Event as Event7 } from "@dxos/async";
|
|
1638
|
-
import { ErrorStream as ErrorStream4, raise as raise2 } from "@dxos/debug";
|
|
1639
|
-
import { log as log10 } from "@dxos/log";
|
|
1640
|
-
|
|
1641
|
-
// packages/core/mesh/network-manager/src/transport/webrtc.ts
|
|
1642
|
-
var wrtc = null;
|
|
1643
|
-
try {
|
|
1644
|
-
wrtc = __require("@koush/wrtc");
|
|
1645
|
-
} catch (e) {
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
// packages/core/mesh/network-manager/src/transport/webrtc-transport.ts
|
|
1649
|
-
var WebRTCTransport = class {
|
|
1650
|
-
constructor(params) {
|
|
1651
|
-
var _a;
|
|
1652
|
-
this.params = params;
|
|
1653
|
-
this._closed = false;
|
|
1654
|
-
this.closed = new Event7();
|
|
1655
|
-
this.connected = new Event7();
|
|
1656
|
-
this.errors = new ErrorStream4();
|
|
1657
|
-
log10("created connection", params, {
|
|
1658
|
-
file: "webrtc-transport.ts",
|
|
1659
|
-
line: 35,
|
|
1660
|
-
scope: this,
|
|
1661
|
-
callSite: (f, a) => f(...a)
|
|
1662
|
-
});
|
|
1663
|
-
this._peer = new SimplePeerConstructor({
|
|
1664
|
-
initiator: this.params.initiator,
|
|
1665
|
-
wrtc: SimplePeerConstructor.WEBRTC_SUPPORT ? void 0 : (_a = wrtc) != null ? _a : raise2(new Error("wrtc not available")),
|
|
1666
|
-
config: this.params.webrtcConfig
|
|
1667
|
-
});
|
|
1668
|
-
this._peer.on("signal", async (data) => {
|
|
1669
|
-
log10("signal", data, {
|
|
1670
|
-
file: "webrtc-transport.ts",
|
|
1671
|
-
line: 43,
|
|
1672
|
-
scope: this,
|
|
1673
|
-
callSite: (f, a) => f(...a)
|
|
1674
|
-
});
|
|
1675
|
-
await this.params.sendSignal({
|
|
1676
|
-
payload: {
|
|
1677
|
-
data
|
|
1678
|
-
}
|
|
1679
|
-
});
|
|
1680
|
-
});
|
|
1681
|
-
this._peer.on("connect", () => {
|
|
1682
|
-
log10("connected", {}, {
|
|
1683
|
-
file: "webrtc-transport.ts",
|
|
1684
|
-
line: 48,
|
|
1685
|
-
scope: this,
|
|
1686
|
-
callSite: (f, a) => f(...a)
|
|
1687
|
-
});
|
|
1688
|
-
this.params.stream.pipe(this._peer).pipe(this.params.stream);
|
|
1689
|
-
this.connected.emit();
|
|
1690
|
-
});
|
|
1691
|
-
this._peer.on("close", async () => {
|
|
1692
|
-
log10("closed", {}, {
|
|
1693
|
-
file: "webrtc-transport.ts",
|
|
1694
|
-
line: 54,
|
|
1695
|
-
scope: this,
|
|
1696
|
-
callSite: (f, a) => f(...a)
|
|
1697
|
-
});
|
|
1698
|
-
await this._disconnectStreams();
|
|
1699
|
-
this.closed.emit();
|
|
1700
|
-
});
|
|
1701
|
-
this._peer.on("error", async (err) => {
|
|
1702
|
-
this.errors.raise(err);
|
|
1703
|
-
await this.destroy();
|
|
1704
|
-
});
|
|
1705
|
-
}
|
|
1706
|
-
async destroy() {
|
|
1707
|
-
log10("closing...", {}, {
|
|
1708
|
-
file: "webrtc-transport.ts",
|
|
1709
|
-
line: 66,
|
|
1710
|
-
scope: this,
|
|
1711
|
-
callSite: (f, a) => f(...a)
|
|
1712
|
-
});
|
|
1713
|
-
this._closed = true;
|
|
1714
|
-
await this._disconnectStreams();
|
|
1715
|
-
this._peer.destroy();
|
|
1716
|
-
this.closed.emit();
|
|
1717
|
-
log10("closed", {}, {
|
|
1718
|
-
file: "webrtc-transport.ts",
|
|
1719
|
-
line: 71,
|
|
1720
|
-
scope: this,
|
|
1721
|
-
callSite: (f, a) => f(...a)
|
|
1722
|
-
});
|
|
1723
|
-
}
|
|
1724
|
-
signal(signal) {
|
|
1725
|
-
if (this._closed) {
|
|
1726
|
-
return;
|
|
1727
|
-
}
|
|
1728
|
-
assert10(signal.payload.data, "Signal message must contain signal data.");
|
|
1729
|
-
this._peer.signal(signal.payload.data);
|
|
1730
|
-
}
|
|
1731
|
-
async _disconnectStreams() {
|
|
1732
|
-
var _a, _b, _c, _d;
|
|
1733
|
-
(_d = (_c = (_b = (_a = this.params.stream).unpipe) == null ? void 0 : _b.call(_a, this._peer)) == null ? void 0 : _c.unpipe) == null ? void 0 : _d.call(_c, this.params.stream);
|
|
1734
|
-
}
|
|
1735
|
-
};
|
|
1736
|
-
|
|
1737
|
-
// packages/core/mesh/network-manager/src/transport/webrtc-transport-service.ts
|
|
1738
|
-
import assert11 from "@dxos/node-std/assert";
|
|
1739
|
-
import { Duplex } from "@dxos/node-std/stream";
|
|
1740
|
-
import { Stream } from "@dxos/codec-protobuf";
|
|
1741
|
-
import { PublicKey as PublicKey8 } from "@dxos/keys";
|
|
1742
|
-
import { log as log11 } from "@dxos/log";
|
|
1743
|
-
import { ConnectionState as ConnectionState3 } from "@dxos/protocols/proto/dxos/mesh/bridge";
|
|
1744
|
-
import { ComplexMap as ComplexMap7 } from "@dxos/util";
|
|
1745
|
-
var WebRTCTransportService = class {
|
|
1746
|
-
// prettier-ignore
|
|
1747
|
-
constructor(_webrtcConfig) {
|
|
1748
|
-
this._webrtcConfig = _webrtcConfig;
|
|
1749
|
-
this.transports = new ComplexMap7(PublicKey8.hash);
|
|
1750
|
-
}
|
|
1751
|
-
open(request) {
|
|
1752
|
-
const rpcStream = new Stream(({ ready, next, close }) => {
|
|
1753
|
-
const duplex = new Duplex({
|
|
1754
|
-
read: () => {
|
|
1755
|
-
},
|
|
1756
|
-
write: function(chunk, _, callback) {
|
|
1757
|
-
next({
|
|
1758
|
-
data: {
|
|
1759
|
-
payload: chunk
|
|
1760
|
-
}
|
|
1761
|
-
});
|
|
1762
|
-
callback();
|
|
1763
|
-
}
|
|
1764
|
-
});
|
|
1765
|
-
const transport = new WebRTCTransport({
|
|
1766
|
-
initiator: request.initiator,
|
|
1767
|
-
stream: duplex,
|
|
1768
|
-
sendSignal: async (signal) => {
|
|
1769
|
-
next({
|
|
1770
|
-
signal: {
|
|
1771
|
-
payload: signal
|
|
1772
|
-
}
|
|
1773
|
-
});
|
|
1774
|
-
}
|
|
1775
|
-
});
|
|
1776
|
-
next({
|
|
1777
|
-
connection: {
|
|
1778
|
-
state: ConnectionState3.CONNECTING
|
|
1779
|
-
}
|
|
1780
|
-
});
|
|
1781
|
-
transport.connected.on(() => {
|
|
1782
|
-
next({
|
|
1783
|
-
connection: {
|
|
1784
|
-
state: ConnectionState3.CONNECTED
|
|
1785
|
-
}
|
|
1786
|
-
});
|
|
1787
|
-
});
|
|
1788
|
-
transport.errors.handle((err) => {
|
|
1789
|
-
next({
|
|
1790
|
-
connection: {
|
|
1791
|
-
state: ConnectionState3.CLOSED,
|
|
1792
|
-
error: err.toString()
|
|
1793
|
-
}
|
|
1794
|
-
});
|
|
1795
|
-
close(err);
|
|
1796
|
-
});
|
|
1797
|
-
transport.closed.on(() => {
|
|
1798
|
-
next({
|
|
1799
|
-
connection: {
|
|
1800
|
-
state: ConnectionState3.CLOSED
|
|
1801
|
-
}
|
|
1802
|
-
});
|
|
1803
|
-
close();
|
|
1804
|
-
});
|
|
1805
|
-
ready();
|
|
1806
|
-
this.transports.set(request.proxyId, {
|
|
1807
|
-
transport,
|
|
1808
|
-
stream: duplex
|
|
1809
|
-
});
|
|
1810
|
-
});
|
|
1811
|
-
return rpcStream;
|
|
1812
|
-
}
|
|
1813
|
-
async sendSignal({ proxyId, signal }) {
|
|
1814
|
-
assert11(this.transports.has(proxyId));
|
|
1815
|
-
await this.transports.get(proxyId).transport.signal(signal);
|
|
1816
|
-
}
|
|
1817
|
-
async sendData({ proxyId, payload }) {
|
|
1818
|
-
assert11(this.transports.has(proxyId));
|
|
1819
|
-
await this.transports.get(proxyId).stream.push(payload);
|
|
1820
|
-
}
|
|
1821
|
-
async close({ proxyId }) {
|
|
1822
|
-
var _a, _b;
|
|
1823
|
-
await ((_a = this.transports.get(proxyId)) == null ? void 0 : _a.transport.destroy());
|
|
1824
|
-
await ((_b = this.transports.get(proxyId)) == null ? void 0 : _b.stream.end());
|
|
1825
|
-
this.transports.delete(proxyId);
|
|
1826
|
-
log11("Closed.", {}, {
|
|
1827
|
-
file: "webrtc-transport-service.ts",
|
|
1828
|
-
line: 108,
|
|
1829
|
-
scope: this,
|
|
1830
|
-
callSite: (f, a) => f(...a)
|
|
1831
|
-
});
|
|
1832
|
-
}
|
|
1833
|
-
};
|
|
1834
|
-
|
|
1835
|
-
// packages/core/mesh/network-manager/src/transport/webrtc-transport-proxy.ts
|
|
1836
|
-
import assert12 from "@dxos/node-std/assert";
|
|
1837
|
-
import { Event as Event8 } from "@dxos/async";
|
|
1838
|
-
import { Context as Context2 } from "@dxos/context";
|
|
1839
|
-
import { ErrorStream as ErrorStream5 } from "@dxos/debug";
|
|
1840
|
-
import { PublicKey as PublicKey9 } from "@dxos/keys";
|
|
1841
|
-
import { log as log12 } from "@dxos/log";
|
|
1842
|
-
import { ConnectionState as ConnectionState4 } from "@dxos/protocols/proto/dxos/mesh/bridge";
|
|
1843
|
-
var WebRTCTransportProxy = class {
|
|
1844
|
-
// prettier-ignore
|
|
1845
|
-
constructor(_params) {
|
|
1846
|
-
this._params = _params;
|
|
1847
|
-
this._proxyId = PublicKey9.random();
|
|
1848
|
-
this._ctx = new Context2();
|
|
1849
|
-
this.closed = new Event8();
|
|
1850
|
-
this._closed = false;
|
|
1851
|
-
this.connected = new Event8();
|
|
1852
|
-
this.errors = new ErrorStream5();
|
|
1853
|
-
this._serviceStream = this._params.bridgeService.open({
|
|
1854
|
-
proxyId: this._proxyId,
|
|
1855
|
-
initiator: this._params.initiator
|
|
1856
|
-
});
|
|
1857
|
-
this._serviceStream.waitUntilReady().then(() => {
|
|
1858
|
-
this._serviceStream.subscribe(async (event) => {
|
|
1859
|
-
log12("WebRTCTransportProxy: event", event, {
|
|
1860
|
-
file: "webrtc-transport-proxy.ts",
|
|
1861
|
-
line: 49,
|
|
1862
|
-
scope: this,
|
|
1863
|
-
callSite: (f, a) => f(...a)
|
|
1864
|
-
});
|
|
1865
|
-
if (event.connection) {
|
|
1866
|
-
await this._handleConnection(event.connection);
|
|
1867
|
-
} else if (event.data) {
|
|
1868
|
-
this._handleData(event.data);
|
|
1869
|
-
} else if (event.signal) {
|
|
1870
|
-
await this._handleSignal(event.signal);
|
|
1871
|
-
}
|
|
1872
|
-
});
|
|
1873
|
-
const dataListener = async (data) => {
|
|
1874
|
-
try {
|
|
1875
|
-
await this._params.bridgeService.sendData({
|
|
1876
|
-
proxyId: this._proxyId,
|
|
1877
|
-
payload: data
|
|
1878
|
-
});
|
|
1879
|
-
} catch (err) {
|
|
1880
|
-
log12.catch(err, {}, {
|
|
1881
|
-
file: "webrtc-transport-proxy.ts",
|
|
1882
|
-
line: 66,
|
|
1883
|
-
scope: this,
|
|
1884
|
-
callSite: (f, a) => f(...a)
|
|
1885
|
-
});
|
|
1886
|
-
}
|
|
1887
|
-
};
|
|
1888
|
-
this._params.stream.on("data", dataListener);
|
|
1889
|
-
this._ctx.onDispose(() => {
|
|
1890
|
-
this._params.stream.off("data", dataListener);
|
|
1891
|
-
});
|
|
1892
|
-
}, (error) => log12.catch(error, {}, {
|
|
1893
|
-
file: "webrtc-transport-proxy.ts",
|
|
1894
|
-
line: 72,
|
|
1895
|
-
scope: this,
|
|
1896
|
-
callSite: (f, a) => f(...a)
|
|
1897
|
-
}));
|
|
1898
|
-
}
|
|
1899
|
-
async _handleConnection(connectionEvent) {
|
|
1900
|
-
if (connectionEvent.error) {
|
|
1901
|
-
this.errors.raise(new Error(connectionEvent.error));
|
|
1902
|
-
}
|
|
1903
|
-
switch (connectionEvent.state) {
|
|
1904
|
-
case ConnectionState4.CONNECTED: {
|
|
1905
|
-
this.connected.emit();
|
|
1906
|
-
break;
|
|
1907
|
-
}
|
|
1908
|
-
case ConnectionState4.CLOSED: {
|
|
1909
|
-
await this.destroy();
|
|
1910
|
-
break;
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
_handleData(dataEvent) {
|
|
1915
|
-
this._params.stream.write(Buffer.from(dataEvent.payload));
|
|
1916
|
-
}
|
|
1917
|
-
async _handleSignal(signalEvent) {
|
|
1918
|
-
await this._params.sendSignal(signalEvent.payload);
|
|
1919
|
-
}
|
|
1920
|
-
signal(signal) {
|
|
1921
|
-
this._params.bridgeService.sendSignal({
|
|
1922
|
-
proxyId: this._proxyId,
|
|
1923
|
-
signal
|
|
1924
|
-
}).catch((err) => this.errors.raise(err));
|
|
1925
|
-
}
|
|
1926
|
-
// TODO(burdon): Move open from constructor.
|
|
1927
|
-
async destroy() {
|
|
1928
|
-
await this._ctx.dispose();
|
|
1929
|
-
if (this._closed) {
|
|
1930
|
-
return;
|
|
1931
|
-
}
|
|
1932
|
-
this._serviceStream.close();
|
|
1933
|
-
try {
|
|
1934
|
-
await this._params.bridgeService.close({
|
|
1935
|
-
proxyId: this._proxyId
|
|
1936
|
-
});
|
|
1937
|
-
} catch (err) {
|
|
1938
|
-
log12.catch(err, {}, {
|
|
1939
|
-
file: "webrtc-transport-proxy.ts",
|
|
1940
|
-
line: 123,
|
|
1941
|
-
scope: this,
|
|
1942
|
-
callSite: (f, a) => f(...a)
|
|
1943
|
-
});
|
|
1944
|
-
}
|
|
1945
|
-
this.closed.emit();
|
|
1946
|
-
this._closed = true;
|
|
1947
|
-
}
|
|
1948
|
-
/**
|
|
1949
|
-
* Called when underlying proxy service becomes unavailable.
|
|
1950
|
-
*/
|
|
1951
|
-
// TODO(burdon): Option on close method.
|
|
1952
|
-
forceClose() {
|
|
1953
|
-
this._serviceStream.close();
|
|
1954
|
-
this.closed.emit();
|
|
1955
|
-
this._closed = true;
|
|
1956
|
-
}
|
|
1957
|
-
};
|
|
1958
|
-
var WebRTCTransportProxyFactory = class {
|
|
1959
|
-
constructor() {
|
|
1960
|
-
this._connections = /* @__PURE__ */ new Set();
|
|
1961
|
-
}
|
|
1962
|
-
/**
|
|
1963
|
-
* Sets the current BridgeService to be used to open connections.
|
|
1964
|
-
* Calling this method will close any existing connections.
|
|
1965
|
-
*/
|
|
1966
|
-
setBridgeService(bridgeService) {
|
|
1967
|
-
this._bridgeService = bridgeService;
|
|
1968
|
-
for (const connection of this._connections) {
|
|
1969
|
-
connection.forceClose();
|
|
1970
|
-
}
|
|
1971
|
-
return this;
|
|
1972
|
-
}
|
|
1973
|
-
createTransport(options) {
|
|
1974
|
-
assert12(this._bridgeService, "WebRTCTransportProxyFactory is not ready to open connections");
|
|
1975
|
-
const transport = new WebRTCTransportProxy({
|
|
1976
|
-
...options,
|
|
1977
|
-
bridgeService: this._bridgeService
|
|
1978
|
-
});
|
|
1979
|
-
this._connections.add(transport);
|
|
1980
|
-
transport.closed.on(() => this._connections.delete(transport));
|
|
1981
|
-
return transport;
|
|
1982
|
-
}
|
|
1983
|
-
};
|
|
1984
|
-
|
|
1985
|
-
// packages/core/mesh/network-manager/src/testing/test-wire-protocol.ts
|
|
1986
|
-
import { Event as Event9 } from "@dxos/async";
|
|
1987
|
-
import { PublicKey as PublicKey10 } from "@dxos/keys";
|
|
1988
|
-
import { log as log13 } from "@dxos/log";
|
|
1989
|
-
import { TestExtension } from "@dxos/teleport";
|
|
1990
|
-
import { ComplexMap as ComplexMap8 } from "@dxos/util";
|
|
1991
|
-
|
|
1992
|
-
// packages/core/mesh/network-manager/src/wire-protocol.ts
|
|
1993
|
-
import { Teleport } from "@dxos/teleport";
|
|
1994
|
-
var createTeleportProtocolFactory = (onConnection) => {
|
|
1995
|
-
return (params) => {
|
|
1996
|
-
const teleport = new Teleport(params);
|
|
1997
|
-
return {
|
|
1998
|
-
stream: teleport.stream,
|
|
1999
|
-
initialize: async () => {
|
|
2000
|
-
await teleport.open();
|
|
2001
|
-
await onConnection(teleport);
|
|
2002
|
-
},
|
|
2003
|
-
destroy: async () => {
|
|
2004
|
-
await teleport.close();
|
|
2005
|
-
}
|
|
2006
|
-
};
|
|
2007
|
-
};
|
|
2008
|
-
};
|
|
2009
|
-
|
|
2010
|
-
// packages/core/mesh/network-manager/src/testing/test-wire-protocol.ts
|
|
2011
26
|
var TestWireProtocol = class {
|
|
2012
27
|
constructor(peerId) {
|
|
2013
28
|
this.peerId = peerId;
|
|
2014
|
-
this.connections = new
|
|
2015
|
-
this.connected = new
|
|
29
|
+
this.connections = new ComplexMap(PublicKey.hash);
|
|
30
|
+
this.connected = new Event();
|
|
2016
31
|
this.factory = createTeleportProtocolFactory(async (teleport) => {
|
|
2017
|
-
|
|
32
|
+
log("create", {
|
|
2018
33
|
remotePeerId: teleport.remotePeerId
|
|
2019
34
|
}, {
|
|
2020
35
|
file: "test-wire-protocol.ts",
|
|
@@ -2036,7 +51,7 @@ var TestWireProtocol = class {
|
|
|
2036
51
|
if (this.connections.has(peerId)) {
|
|
2037
52
|
return this.connections.get(peerId);
|
|
2038
53
|
}
|
|
2039
|
-
|
|
54
|
+
log("waitForConnection", {
|
|
2040
55
|
peerId
|
|
2041
56
|
}, {
|
|
2042
57
|
file: "test-wire-protocol.ts",
|
|
@@ -2044,7 +59,7 @@ var TestWireProtocol = class {
|
|
|
2044
59
|
scope: this,
|
|
2045
60
|
callSite: (f, a) => f(...a)
|
|
2046
61
|
});
|
|
2047
|
-
await this.connected.waitFor((connectedId) => connectedId.equals(peerId));
|
|
62
|
+
await asyncTimeout(this.connected.waitFor((connectedId) => connectedId.equals(peerId)), 1e3);
|
|
2048
63
|
return this.connections.get(peerId);
|
|
2049
64
|
}
|
|
2050
65
|
async testConnection(peerId) {
|
|
@@ -2073,8 +88,8 @@ var TestBuilder = class {
|
|
|
2073
88
|
var TestPeer = class {
|
|
2074
89
|
constructor(testBuilder) {
|
|
2075
90
|
this.testBuilder = testBuilder;
|
|
2076
|
-
this.peerId =
|
|
2077
|
-
this._swarms = new
|
|
91
|
+
this.peerId = PublicKey2.random();
|
|
92
|
+
this._swarms = new ComplexMap2(PublicKey2.hash);
|
|
2078
93
|
this._networkManager = this.createNetworkManager();
|
|
2079
94
|
}
|
|
2080
95
|
// TODO(burdon): Move to TestBuilder.
|
|
@@ -2086,7 +101,7 @@ var TestPeer = class {
|
|
|
2086
101
|
this._proxy = createProtoRpcPeer({
|
|
2087
102
|
port: proxyPort,
|
|
2088
103
|
requested: {
|
|
2089
|
-
BridgeService:
|
|
104
|
+
BridgeService: schema.getService("dxos.mesh.bridge.BridgeService")
|
|
2090
105
|
},
|
|
2091
106
|
noHandshake: true,
|
|
2092
107
|
encodingOptions: {
|
|
@@ -2096,7 +111,7 @@ var TestPeer = class {
|
|
|
2096
111
|
this._service = createProtoRpcPeer({
|
|
2097
112
|
port: servicePort,
|
|
2098
113
|
exposed: {
|
|
2099
|
-
BridgeService:
|
|
114
|
+
BridgeService: schema.getService("dxos.mesh.bridge.BridgeService")
|
|
2100
115
|
},
|
|
2101
116
|
handlers: {
|
|
2102
117
|
BridgeService: new WebRTCTransportService()
|
|
@@ -2144,10 +159,10 @@ var TestPeer = class {
|
|
|
2144
159
|
return swarm;
|
|
2145
160
|
}
|
|
2146
161
|
async goOffline() {
|
|
2147
|
-
await this._networkManager.setConnectionState(
|
|
162
|
+
await this._networkManager.setConnectionState(ConnectionState.OFFLINE);
|
|
2148
163
|
}
|
|
2149
164
|
async goOnline() {
|
|
2150
|
-
await this._networkManager.setConnectionState(
|
|
165
|
+
await this._networkManager.setConnectionState(ConnectionState.ONLINE);
|
|
2151
166
|
}
|
|
2152
167
|
};
|
|
2153
168
|
var TestSwarmConnection = class {
|