@dxos/network-manager 0.6.13-main.548ca8d → 0.6.13-staging.1e988a3
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-IDPSMH73.mjs → chunk-XYSYUN63.mjs} +1031 -1230
- package/dist/lib/browser/chunk-XYSYUN63.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +19 -10
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +27 -18
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-MCPADZS5.cjs → chunk-4YAYC7WN.cjs} +1175 -1247
- package/dist/lib/node/chunk-4YAYC7WN.cjs.map +7 -0
- package/dist/lib/node/index.cjs +37 -27
- package/dist/lib/node/index.cjs.map +2 -2
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +29 -20
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/signal/ice.d.ts.map +1 -1
- package/dist/types/src/signal/integration.test.d.ts +2 -0
- package/dist/types/src/signal/integration.test.d.ts.map +1 -0
- package/dist/types/src/signal/swarm-messenger.test.d.ts +2 -0
- package/dist/types/src/signal/swarm-messenger.test.d.ts.map +1 -0
- package/dist/types/src/swarm/connection.d.ts.map +1 -1
- package/dist/types/src/swarm/swarm.d.ts +1 -1
- package/dist/types/src/testing/test-builder.d.ts +2 -2
- package/dist/types/src/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/tests/basic-test-suite.d.ts.map +1 -1
- package/dist/types/src/tests/property-test-suite.d.ts.map +1 -1
- package/dist/types/src/tests/tcp-transport.test.d.ts +2 -0
- package/dist/types/src/tests/tcp-transport.test.d.ts.map +1 -0
- package/dist/types/src/tests/utils.d.ts.map +1 -1
- package/dist/types/src/transport/index.d.ts +5 -1
- package/dist/types/src/transport/index.d.ts.map +1 -1
- package/dist/types/src/transport/libdatachannel-transport.d.ts +42 -0
- package/dist/types/src/transport/libdatachannel-transport.d.ts.map +1 -0
- package/dist/types/src/transport/libdatachannel-transport.test.d.ts +2 -0
- package/dist/types/src/transport/libdatachannel-transport.test.d.ts.map +1 -0
- package/dist/types/src/transport/memory-transport.d.ts +2 -2
- package/dist/types/src/transport/memory-transport.d.ts.map +1 -1
- package/dist/types/src/transport/memory-transport.test.d.ts +2 -0
- package/dist/types/src/transport/memory-transport.test.d.ts.map +1 -0
- package/dist/types/src/transport/simplepeer-simple-peer.d.ts +2 -0
- package/dist/types/src/transport/simplepeer-simple-peer.d.ts.map +1 -0
- package/dist/types/src/transport/simplepeer-transport-proxy-test.d.ts +2 -0
- package/dist/types/src/transport/simplepeer-transport-proxy-test.d.ts.map +1 -0
- package/dist/types/src/transport/{webrtc/rtc-transport-proxy.d.ts → simplepeer-transport-proxy.d.ts} +12 -10
- package/dist/types/src/transport/simplepeer-transport-proxy.d.ts.map +1 -0
- package/dist/types/src/transport/{webrtc/rtc-transport-service.d.ts → simplepeer-transport-service.d.ts} +7 -9
- package/dist/types/src/transport/simplepeer-transport-service.d.ts.map +1 -0
- package/dist/types/src/transport/simplepeer-transport.d.ts +36 -0
- package/dist/types/src/transport/simplepeer-transport.d.ts.map +1 -0
- package/dist/types/src/transport/simplepeer-transport.test.d.ts +2 -0
- package/dist/types/src/transport/simplepeer-transport.test.d.ts.map +1 -0
- package/dist/types/src/transport/{tcp/tcp-transport.browser.d.ts → tcp-transport.browser.d.ts} +3 -3
- package/dist/types/src/transport/tcp-transport.browser.d.ts.map +1 -0
- package/dist/types/src/transport/{tcp/tcp-transport.d.ts → tcp-transport.d.ts} +3 -3
- package/dist/types/src/transport/tcp-transport.d.ts.map +1 -0
- package/dist/types/src/transport/transport.d.ts +6 -7
- package/dist/types/src/transport/transport.d.ts.map +1 -1
- package/dist/types/src/transport/webrtc.d.ts +6 -0
- package/dist/types/src/transport/webrtc.d.ts.map +1 -0
- package/package.json +30 -53
- package/src/globals.d.ts +7 -0
- package/src/signal/ice.test.ts +3 -1
- package/src/signal/ice.ts +1 -6
- package/src/signal/{integration.node.test.ts → integration.test.ts} +15 -9
- package/src/signal/{swarm-messenger.node.test.ts → swarm-messenger.test.ts} +23 -13
- package/src/swarm/connection-limiter.test.ts +6 -3
- package/src/swarm/connection.test.ts +38 -63
- package/src/swarm/connection.ts +5 -5
- package/src/swarm/swarm.test.ts +11 -9
- package/src/swarm/swarm.ts +1 -1
- package/src/testing/test-builder.ts +28 -12
- package/src/tests/basic-test-suite.ts +33 -34
- package/src/tests/memory-transport.test.ts +42 -40
- package/src/tests/property-test-suite.ts +22 -21
- package/src/tests/tcp-transport.test.ts +67 -0
- package/src/tests/utils.ts +2 -3
- package/src/tests/webrtc-transport.test.ts +9 -9
- package/src/transport/index.ts +5 -1
- package/src/transport/libdatachannel-transport.test.ts +100 -0
- package/src/transport/libdatachannel-transport.ts +376 -0
- package/src/transport/memory-transport.test.ts +74 -0
- package/src/transport/memory-transport.ts +0 -2
- package/src/transport/simplepeer-simple-peer.ts +26 -0
- package/src/transport/simplepeer-transport-proxy-test.ts +181 -0
- package/src/transport/simplepeer-transport-proxy.ts +246 -0
- package/src/transport/simplepeer-transport-service.ts +160 -0
- package/src/transport/simplepeer-transport.test.ts +61 -0
- package/src/transport/simplepeer-transport.ts +250 -0
- package/src/transport/{tcp/tcp-transport.browser.ts → tcp-transport.browser.ts} +3 -7
- package/src/transport/{tcp/tcp-transport.ts → tcp-transport.ts} +1 -3
- package/src/transport/transport.ts +7 -8
- package/src/transport/webrtc.ts +15 -0
- package/src/typings.d.ts +2 -8
- package/dist/lib/browser/chunk-GW3YM55A.mjs +0 -14
- package/dist/lib/browser/chunk-GW3YM55A.mjs.map +0 -7
- package/dist/lib/browser/chunk-IDPSMH73.mjs.map +0 -7
- package/dist/lib/browser/transport/tcp/index.mjs +0 -39
- package/dist/lib/browser/transport/tcp/index.mjs.map +0 -7
- package/dist/lib/node/chunk-MCPADZS5.cjs.map +0 -7
- package/dist/lib/node/transport/tcp/index.cjs +0 -191
- package/dist/lib/node/transport/tcp/index.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-NL5MMIE4.mjs +0 -4388
- package/dist/lib/node-esm/chunk-NL5MMIE4.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -50
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/testing/index.mjs +0 -280
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/transport/tcp/index.mjs +0 -159
- package/dist/lib/node-esm/transport/tcp/index.mjs.map +0 -7
- package/dist/types/src/signal/integration.node.test.d.ts +0 -2
- package/dist/types/src/signal/integration.node.test.d.ts.map +0 -1
- package/dist/types/src/signal/swarm-messenger.node.test.d.ts +0 -2
- package/dist/types/src/signal/swarm-messenger.node.test.d.ts.map +0 -1
- package/dist/types/src/tests/tcp-transport.node.test.d.ts +0 -2
- package/dist/types/src/tests/tcp-transport.node.test.d.ts.map +0 -1
- package/dist/types/src/transport/tcp/index.d.ts +0 -2
- package/dist/types/src/transport/tcp/index.d.ts.map +0 -1
- package/dist/types/src/transport/tcp/tcp-transport.browser.d.ts.map +0 -1
- package/dist/types/src/transport/tcp/tcp-transport.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/index.d.ts +0 -4
- package/dist/types/src/transport/webrtc/index.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-connection-factory.d.ts +0 -14
- package/dist/types/src/transport/webrtc/rtc-connection-factory.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts +0 -68
- package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts +0 -33
- package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-channel.test.d.ts +0 -2
- package/dist/types/src/transport/webrtc/rtc-transport-channel.test.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts +0 -4
- package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-proxy.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-proxy.test.d.ts +0 -2
- package/dist/types/src/transport/webrtc/rtc-transport-proxy.test.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-service.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-stats.d.ts +0 -4
- package/dist/types/src/transport/webrtc/rtc-transport-stats.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport.test.d.ts +0 -2
- package/dist/types/src/transport/webrtc/rtc-transport.test.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/test-utils.d.ts +0 -5
- package/dist/types/src/transport/webrtc/test-utils.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/utils.d.ts +0 -3
- package/dist/types/src/transport/webrtc/utils.d.ts.map +0 -1
- package/src/tests/tcp-transport.node.test.ts +0 -65
- package/src/transport/tcp/index.ts +0 -5
- package/src/transport/webrtc/index.ts +0 -7
- package/src/transport/webrtc/rtc-connection-factory.ts +0 -82
- package/src/transport/webrtc/rtc-peer-connection.ts +0 -472
- package/src/transport/webrtc/rtc-transport-channel.test.ts +0 -176
- package/src/transport/webrtc/rtc-transport-channel.ts +0 -195
- package/src/transport/webrtc/rtc-transport-factory.ts +0 -28
- package/src/transport/webrtc/rtc-transport-proxy.test.ts +0 -413
- package/src/transport/webrtc/rtc-transport-proxy.ts +0 -264
- package/src/transport/webrtc/rtc-transport-service.ts +0 -192
- package/src/transport/webrtc/rtc-transport-stats.ts +0 -67
- package/src/transport/webrtc/rtc-transport.test.ts +0 -198
- package/src/transport/webrtc/test-utils.ts +0 -22
- package/src/transport/webrtc/utils.ts +0 -36
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import "@dxos/node-std/globals";
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// inject-globals:@inject-globals
|
|
2
10
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
11
|
+
global,
|
|
12
|
+
Buffer as Buffer2,
|
|
13
|
+
process
|
|
14
|
+
} from "@dxos/node-std/inject-globals";
|
|
5
15
|
|
|
6
16
|
// packages/core/mesh/network-manager/src/swarm/connection.ts
|
|
7
17
|
import { DeferredTask, Event, sleep, scheduleTask, scheduleTaskInterval, synchronized, Trigger } from "@dxos/async";
|
|
@@ -10,7 +20,7 @@ import { ErrorStream } from "@dxos/debug";
|
|
|
10
20
|
import { invariant } from "@dxos/invariant";
|
|
11
21
|
import { PublicKey } from "@dxos/keys";
|
|
12
22
|
import { log, logInfo } from "@dxos/log";
|
|
13
|
-
import { CancelledError, ProtocolError, ConnectionResetError, ConnectivityError, TimeoutError, trace } from "@dxos/protocols";
|
|
23
|
+
import { CancelledError, ProtocolError, ConnectionResetError, ConnectivityError, TimeoutError, UnknownProtocolError, trace } from "@dxos/protocols";
|
|
14
24
|
function _ts_decorate(decorators, target, key, desc) {
|
|
15
25
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
26
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -46,11 +56,11 @@ var Connection = class {
|
|
|
46
56
|
this._callbacks = _callbacks;
|
|
47
57
|
this._ctx = new Context(void 0, {
|
|
48
58
|
F: __dxlog_file,
|
|
49
|
-
L:
|
|
59
|
+
L: 101
|
|
50
60
|
});
|
|
51
61
|
this.connectedTimeoutContext = new Context(void 0, {
|
|
52
62
|
F: __dxlog_file,
|
|
53
|
-
L:
|
|
63
|
+
L: 102
|
|
54
64
|
});
|
|
55
65
|
this._protocolClosed = new Trigger();
|
|
56
66
|
this._transportClosed = new Trigger();
|
|
@@ -73,7 +83,7 @@ var Connection = class {
|
|
|
73
83
|
initiator: this.initiator
|
|
74
84
|
}, {
|
|
75
85
|
F: __dxlog_file,
|
|
76
|
-
L:
|
|
86
|
+
L: 138,
|
|
77
87
|
S: this,
|
|
78
88
|
C: (f, a) => f(...a)
|
|
79
89
|
});
|
|
@@ -96,7 +106,7 @@ var Connection = class {
|
|
|
96
106
|
async openConnection() {
|
|
97
107
|
invariant(this._state === "INITIAL", "Invalid state.", {
|
|
98
108
|
F: __dxlog_file,
|
|
99
|
-
L:
|
|
109
|
+
L: 168,
|
|
100
110
|
S: this,
|
|
101
111
|
A: [
|
|
102
112
|
"this._state === ConnectionState.INITIAL",
|
|
@@ -107,7 +117,7 @@ var Connection = class {
|
|
|
107
117
|
id: this._instanceId
|
|
108
118
|
}), {
|
|
109
119
|
F: __dxlog_file,
|
|
110
|
-
L:
|
|
120
|
+
L: 169,
|
|
111
121
|
S: this,
|
|
112
122
|
C: (f, a) => f(...a)
|
|
113
123
|
});
|
|
@@ -119,7 +129,7 @@ var Connection = class {
|
|
|
119
129
|
initiator: this.initiator
|
|
120
130
|
}, {
|
|
121
131
|
F: __dxlog_file,
|
|
122
|
-
L:
|
|
132
|
+
L: 170,
|
|
123
133
|
S: this,
|
|
124
134
|
C: (f, a) => f(...a)
|
|
125
135
|
});
|
|
@@ -130,7 +140,7 @@ var Connection = class {
|
|
|
130
140
|
this._protocol.stream.on("close", () => {
|
|
131
141
|
log("protocol stream closed", void 0, {
|
|
132
142
|
F: __dxlog_file,
|
|
133
|
-
L:
|
|
143
|
+
L: 187,
|
|
134
144
|
S: this,
|
|
135
145
|
C: (f, a) => f(...a)
|
|
136
146
|
});
|
|
@@ -140,7 +150,7 @@ var Connection = class {
|
|
|
140
150
|
scheduleTask(this.connectedTimeoutContext, async () => {
|
|
141
151
|
log.info(`timeout waiting ${TRANSPORT_CONNECTION_TIMEOUT / 1e3}s for transport to connect, aborting`, void 0, {
|
|
142
152
|
F: __dxlog_file,
|
|
143
|
-
L:
|
|
153
|
+
L: 195,
|
|
144
154
|
S: this,
|
|
145
155
|
C: (f, a) => f(...a)
|
|
146
156
|
});
|
|
@@ -148,7 +158,7 @@ var Connection = class {
|
|
|
148
158
|
}, TRANSPORT_CONNECTION_TIMEOUT);
|
|
149
159
|
invariant(!this._transport, void 0, {
|
|
150
160
|
F: __dxlog_file,
|
|
151
|
-
L:
|
|
161
|
+
L: 203,
|
|
152
162
|
S: this,
|
|
153
163
|
A: [
|
|
154
164
|
"!this._transport",
|
|
@@ -156,14 +166,12 @@ var Connection = class {
|
|
|
156
166
|
]
|
|
157
167
|
});
|
|
158
168
|
this._transport = this._transportFactory.createTransport({
|
|
159
|
-
ownPeerKey: this.localInfo.peerKey,
|
|
160
|
-
remotePeerKey: this.remoteInfo.peerKey,
|
|
161
|
-
topic: this.topic.toHex(),
|
|
162
169
|
initiator: this.initiator,
|
|
163
170
|
stream: this._protocol.stream,
|
|
164
171
|
sendSignal: async (signal) => this._sendSignal(signal),
|
|
165
172
|
sessionId: this.sessionId
|
|
166
173
|
});
|
|
174
|
+
await this._transport.open();
|
|
167
175
|
this._transport.connected.once(async () => {
|
|
168
176
|
this._changeState("CONNECTED");
|
|
169
177
|
await this.connectedTimeoutContext.dispose();
|
|
@@ -209,13 +217,21 @@ var Connection = class {
|
|
|
209
217
|
C: (f, a) => f(...a)
|
|
210
218
|
});
|
|
211
219
|
this.abort().catch((err2) => this.errors.raise(err2));
|
|
220
|
+
} else if (err instanceof UnknownProtocolError) {
|
|
221
|
+
log.warn("unsure what to do with UnknownProtocolError, will keep on truckin", {
|
|
222
|
+
err
|
|
223
|
+
}, {
|
|
224
|
+
F: __dxlog_file,
|
|
225
|
+
L: 242,
|
|
226
|
+
S: this,
|
|
227
|
+
C: (f, a) => f(...a)
|
|
228
|
+
});
|
|
212
229
|
}
|
|
213
230
|
if (this._state !== "CLOSED" && this._state !== "CLOSING") {
|
|
214
231
|
await this.connectedTimeoutContext.dispose();
|
|
215
232
|
this.errors.raise(err);
|
|
216
233
|
}
|
|
217
234
|
});
|
|
218
|
-
await this._transport.open();
|
|
219
235
|
for (const signal of this._incomingSignalBuffer) {
|
|
220
236
|
void this._transport.onSignal(signal);
|
|
221
237
|
}
|
|
@@ -582,20 +598,15 @@ var createIceProvider = (iceProviders) => {
|
|
|
582
598
|
}
|
|
583
599
|
cachedIceServers = (await Promise.all(iceProviders.map(({ urls }) => asyncTimeout(fetch(urls, {
|
|
584
600
|
method: "GET"
|
|
585
|
-
}), 1e4).then((response) => response.json()).catch((err) => {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
S: void 0,
|
|
595
|
-
C: (f, a) => f(...a)
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
})))).filter(isNotNullOrUndefined).map(({ iceServers }) => iceServers).flat();
|
|
601
|
+
}), 1e4).then((response) => response.json()).catch((err) => log2.error("Failed to fetch ICE servers from provider", {
|
|
602
|
+
urls,
|
|
603
|
+
err
|
|
604
|
+
}, {
|
|
605
|
+
F: __dxlog_file2,
|
|
606
|
+
L: 27,
|
|
607
|
+
S: void 0,
|
|
608
|
+
C: (f, a) => f(...a)
|
|
609
|
+
}))))).filter(isNotNullOrUndefined).map(({ iceServers }) => iceServers).flat();
|
|
599
610
|
return cachedIceServers;
|
|
600
611
|
}
|
|
601
612
|
};
|
|
@@ -2619,7 +2630,7 @@ var sortByXorDistance = (keys, reference) => {
|
|
|
2619
2630
|
};
|
|
2620
2631
|
var distXor = (a, b) => {
|
|
2621
2632
|
const maxLength = Math.max(a.length, b.length);
|
|
2622
|
-
const result =
|
|
2633
|
+
const result = Buffer2.allocUnsafe(maxLength);
|
|
2623
2634
|
for (let i = 0; i < maxLength; i++) {
|
|
2624
2635
|
result[i] = (a[i] || 0) ^ (b[i] || 0);
|
|
2625
2636
|
}
|
|
@@ -2854,12 +2865,11 @@ var MemoryTransport = class _MemoryTransport {
|
|
|
2854
2865
|
this.errors.raise(err);
|
|
2855
2866
|
});
|
|
2856
2867
|
}
|
|
2857
|
-
return this;
|
|
2858
2868
|
}
|
|
2859
2869
|
async close() {
|
|
2860
2870
|
log11("closing...", void 0, {
|
|
2861
2871
|
F: __dxlog_file12,
|
|
2862
|
-
L:
|
|
2872
|
+
L: 129,
|
|
2863
2873
|
S: this,
|
|
2864
2874
|
C: (f, a) => f(...a)
|
|
2865
2875
|
});
|
|
@@ -2880,18 +2890,17 @@ var MemoryTransport = class _MemoryTransport {
|
|
|
2880
2890
|
this.closed.emit();
|
|
2881
2891
|
log11("closed", void 0, {
|
|
2882
2892
|
F: __dxlog_file12,
|
|
2883
|
-
L:
|
|
2893
|
+
L: 157,
|
|
2884
2894
|
S: this,
|
|
2885
2895
|
C: (f, a) => f(...a)
|
|
2886
2896
|
});
|
|
2887
|
-
return this;
|
|
2888
2897
|
}
|
|
2889
2898
|
async onSignal({ payload }) {
|
|
2890
2899
|
log11("received signal", {
|
|
2891
2900
|
payload
|
|
2892
2901
|
}, {
|
|
2893
2902
|
F: __dxlog_file12,
|
|
2894
|
-
L:
|
|
2903
|
+
L: 161,
|
|
2895
2904
|
S: this,
|
|
2896
2905
|
C: (f, a) => f(...a)
|
|
2897
2906
|
});
|
|
@@ -2927,978 +2936,524 @@ var toError = (err) => err instanceof Error ? err : new Error(String(err));
|
|
|
2927
2936
|
// packages/core/mesh/network-manager/src/transport/transport.ts
|
|
2928
2937
|
var TransportKind;
|
|
2929
2938
|
(function(TransportKind2) {
|
|
2930
|
-
TransportKind2["
|
|
2931
|
-
TransportKind2["
|
|
2939
|
+
TransportKind2["SIMPLE_PEER"] = "SIMPLE_PEER";
|
|
2940
|
+
TransportKind2["SIMPLE_PEER_PROXY"] = "SIMPLE_PEER_PROXY";
|
|
2941
|
+
TransportKind2["LIBDATACHANNEL"] = "LIBDATACHANNEL";
|
|
2932
2942
|
TransportKind2["MEMORY"] = "MEMORY";
|
|
2933
2943
|
TransportKind2["TCP"] = "TCP";
|
|
2934
2944
|
})(TransportKind || (TransportKind = {}));
|
|
2935
2945
|
|
|
2936
|
-
// packages/core/mesh/network-manager/src/transport/
|
|
2937
|
-
import
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
}
|
|
2943
|
-
async createConnection(config) {
|
|
2944
|
-
return new RTCPeerConnection(config);
|
|
2945
|
-
}
|
|
2946
|
-
async initConnection(connection, info) {
|
|
2947
|
-
}
|
|
2948
|
-
};
|
|
2949
|
-
var NodeRtcConnectionFactory = class _NodeRtcConnectionFactory {
|
|
2950
|
-
static {
|
|
2951
|
-
this._createdConnections = 0;
|
|
2952
|
-
}
|
|
2953
|
-
static {
|
|
2954
|
-
this._cleanupMutex = new Mutex();
|
|
2955
|
-
}
|
|
2956
|
-
// This should be inside the function to avoid triggering `eval` in the global scope.
|
|
2957
|
-
// eslint-disable-next-line no-new-func
|
|
2958
|
-
// TODO(burdon): Do imports here?
|
|
2959
|
-
async initialize() {
|
|
2960
|
-
}
|
|
2961
|
-
async onConnectionDestroyed() {
|
|
2962
|
-
return _NodeRtcConnectionFactory._cleanupMutex.executeSynchronized(async () => {
|
|
2963
|
-
if (--_NodeRtcConnectionFactory._createdConnections === 0) {
|
|
2964
|
-
(await import("#node-datachannel")).cleanup();
|
|
2965
|
-
}
|
|
2966
|
-
});
|
|
2967
|
-
}
|
|
2968
|
-
async createConnection(config) {
|
|
2969
|
-
return _NodeRtcConnectionFactory._cleanupMutex.executeSynchronized(async () => {
|
|
2970
|
-
const { RTCPeerConnection: RTCPeerConnection1 } = await import("#node-datachannel/polyfill");
|
|
2971
|
-
_NodeRtcConnectionFactory._createdConnections++;
|
|
2972
|
-
return new RTCPeerConnection1(config);
|
|
2973
|
-
});
|
|
2974
|
-
}
|
|
2975
|
-
async initConnection(connection, info) {
|
|
2976
|
-
if (info.initiator) {
|
|
2977
|
-
connection.onnegotiationneeded?.(null);
|
|
2978
|
-
}
|
|
2979
|
-
}
|
|
2980
|
-
};
|
|
2981
|
-
var getRtcConnectionFactory = () => {
|
|
2982
|
-
return typeof globalThis.RTCPeerConnection === "undefined" ? new NodeRtcConnectionFactory() : new BrowserRtcConnectionFactory();
|
|
2983
|
-
};
|
|
2984
|
-
|
|
2985
|
-
// packages/core/mesh/network-manager/src/transport/webrtc/rtc-peer-connection.ts
|
|
2986
|
-
import { synchronized as synchronized5, Trigger as Trigger3, Mutex as Mutex2 } from "@dxos/async";
|
|
2987
|
-
import { invariant as invariant12 } from "@dxos/invariant";
|
|
2988
|
-
import { log as log13, logInfo as logInfo4 } from "@dxos/log";
|
|
2989
|
-
import { ConnectivityError as ConnectivityError3 } from "@dxos/protocols";
|
|
2990
|
-
import { trace as trace4 } from "@dxos/tracing";
|
|
2991
|
-
|
|
2992
|
-
// packages/core/mesh/network-manager/src/transport/webrtc/rtc-transport-channel.ts
|
|
2993
|
-
import { Duplex } from "@dxos/node-std/stream";
|
|
2994
|
-
import { Event as AsyncEvent } from "@dxos/async";
|
|
2995
|
-
import { Resource } from "@dxos/context";
|
|
2996
|
-
import { ErrorStream as ErrorStream4 } from "@dxos/debug";
|
|
2997
|
-
import { invariant as invariant11 } from "@dxos/invariant";
|
|
2946
|
+
// packages/core/mesh/network-manager/src/transport/simplepeer-transport.ts
|
|
2947
|
+
import SimplePeerConstructor from "simple-peer";
|
|
2948
|
+
import invariant11 from "tiny-invariant";
|
|
2949
|
+
import { Event as Event8, synchronized as synchronized5 } from "@dxos/async";
|
|
2950
|
+
import { ErrorStream as ErrorStream4, raise as raise2 } from "@dxos/debug";
|
|
2951
|
+
import { PublicKey as PublicKey10 } from "@dxos/keys";
|
|
2998
2952
|
import { log as log12 } from "@dxos/log";
|
|
2999
|
-
import { ConnectivityError as ConnectivityError2 } from "@dxos/protocols";
|
|
2953
|
+
import { ConnectionResetError as ConnectionResetError2, ConnectivityError as ConnectivityError2, ProtocolError as ProtocolError2, UnknownProtocolError as UnknownProtocolError2, trace as trace4 } from "@dxos/protocols";
|
|
2954
|
+
|
|
2955
|
+
// packages/core/mesh/network-manager/src/transport/webrtc.ts
|
|
2956
|
+
var wrtc = null;
|
|
2957
|
+
try {
|
|
2958
|
+
wrtc = __require("@koush/wrtc");
|
|
2959
|
+
} catch {
|
|
2960
|
+
}
|
|
3000
2961
|
|
|
3001
|
-
// packages/core/mesh/network-manager/src/transport/
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
if (
|
|
3006
|
-
|
|
2962
|
+
// packages/core/mesh/network-manager/src/transport/simplepeer-transport.ts
|
|
2963
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
2964
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2965
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2966
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2967
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2968
|
+
}
|
|
2969
|
+
var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/simplepeer-transport.ts";
|
|
2970
|
+
var createSimplePeerTransportFactory = (webrtcConfig, iceProvider) => ({
|
|
2971
|
+
createTransport: (options) => new SimplePeerTransport({
|
|
2972
|
+
...options,
|
|
2973
|
+
webrtcConfig,
|
|
2974
|
+
iceProvider
|
|
2975
|
+
})
|
|
2976
|
+
});
|
|
2977
|
+
var SimplePeerTransport = class {
|
|
2978
|
+
get isOpen() {
|
|
2979
|
+
return this._piped && !this._closed;
|
|
3007
2980
|
}
|
|
3008
|
-
|
|
3009
|
-
|
|
2981
|
+
/**
|
|
2982
|
+
* @params opts.config formatted as per https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection
|
|
2983
|
+
*/
|
|
2984
|
+
constructor(_params) {
|
|
2985
|
+
this._params = _params;
|
|
2986
|
+
this._peer = void 0;
|
|
2987
|
+
this._closed = false;
|
|
2988
|
+
this._piped = false;
|
|
2989
|
+
this.closed = new Event8();
|
|
2990
|
+
this.connected = new Event8();
|
|
2991
|
+
this.errors = new ErrorStream4();
|
|
2992
|
+
this._instanceId = PublicKey10.random().toHex();
|
|
3010
2993
|
}
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
2994
|
+
async getStats() {
|
|
2995
|
+
const stats = await this._getStats();
|
|
2996
|
+
if (!stats) {
|
|
2997
|
+
return {
|
|
2998
|
+
bytesSent: 0,
|
|
2999
|
+
bytesReceived: 0,
|
|
3000
|
+
packetsSent: 0,
|
|
3001
|
+
packetsReceived: 0,
|
|
3002
|
+
rawStats: {}
|
|
3003
|
+
};
|
|
3004
|
+
}
|
|
3016
3005
|
return {
|
|
3017
|
-
bytesSent:
|
|
3018
|
-
bytesReceived:
|
|
3019
|
-
packetsSent:
|
|
3020
|
-
packetsReceived:
|
|
3021
|
-
rawStats:
|
|
3006
|
+
bytesSent: stats.transport.bytesSent,
|
|
3007
|
+
bytesReceived: stats.transport.bytesReceived,
|
|
3008
|
+
packetsSent: stats.transport.packetsSent,
|
|
3009
|
+
packetsReceived: stats.transport.packetsReceived,
|
|
3010
|
+
rawStats: stats.raw
|
|
3022
3011
|
};
|
|
3023
3012
|
}
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
};
|
|
3047
|
-
|
|
3048
|
-
// packages/core/mesh/network-manager/src/transport/webrtc/rtc-transport-channel.ts
|
|
3049
|
-
var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/webrtc/rtc-transport-channel.ts";
|
|
3050
|
-
var MAX_MESSAGE_SIZE = 64 * 1024;
|
|
3051
|
-
var MAX_BUFFERED_AMOUNT = 64 * 1024;
|
|
3052
|
-
var RtcTransportChannel = class extends Resource {
|
|
3053
|
-
constructor(_connection, _options) {
|
|
3054
|
-
super();
|
|
3055
|
-
this._connection = _connection;
|
|
3056
|
-
this._options = _options;
|
|
3057
|
-
this.closed = new AsyncEvent();
|
|
3058
|
-
this.connected = new AsyncEvent();
|
|
3059
|
-
this.errors = new ErrorStream4();
|
|
3060
|
-
this._streamDataFlushedCallback = null;
|
|
3061
|
-
this._isChannelCreationInProgress = false;
|
|
3062
|
-
}
|
|
3063
|
-
get isRtcChannelCreationInProgress() {
|
|
3064
|
-
return this._isChannelCreationInProgress;
|
|
3013
|
+
async _getStats() {
|
|
3014
|
+
if (typeof this._peer?._pc?.getStats !== "function") {
|
|
3015
|
+
return null;
|
|
3016
|
+
}
|
|
3017
|
+
return await this._peer._pc.getStats().then((stats) => {
|
|
3018
|
+
const statsEntries = Array.from(stats.entries());
|
|
3019
|
+
const transport = statsEntries.filter((s) => s[1].type === "transport")[0][1];
|
|
3020
|
+
const candidatePair = statsEntries.filter((s) => s[0] === transport.selectedCandidatePairId);
|
|
3021
|
+
let selectedCandidatePair;
|
|
3022
|
+
let remoteCandidate;
|
|
3023
|
+
if (candidatePair.length > 0) {
|
|
3024
|
+
selectedCandidatePair = candidatePair[0][1];
|
|
3025
|
+
remoteCandidate = statsEntries.filter((s) => s[0] === selectedCandidatePair.remoteCandidateId)[0][1];
|
|
3026
|
+
}
|
|
3027
|
+
return {
|
|
3028
|
+
datachannel: statsEntries.filter((s) => s[1].type === "data-channel")[0][1],
|
|
3029
|
+
transport,
|
|
3030
|
+
selectedCandidatePair,
|
|
3031
|
+
remoteCandidate,
|
|
3032
|
+
raw: Object.fromEntries(stats.entries())
|
|
3033
|
+
};
|
|
3034
|
+
});
|
|
3065
3035
|
}
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3036
|
+
async getDetails() {
|
|
3037
|
+
const stats = await this._getStats();
|
|
3038
|
+
const rc = stats?.remoteCandidate;
|
|
3039
|
+
if (!rc) {
|
|
3040
|
+
return "unavailable";
|
|
3069
3041
|
}
|
|
3042
|
+
if (rc.candidateType === "relay") {
|
|
3043
|
+
return `${rc.ip}:${rc.port}/${rc.protocol} relay for ${rc.relatedAddress}:${rc.relatedPort}`;
|
|
3044
|
+
}
|
|
3045
|
+
return `${rc.ip}:${rc.port}/${rc.protocol} ${rc.candidateType}`;
|
|
3070
3046
|
}
|
|
3071
|
-
async
|
|
3072
|
-
|
|
3047
|
+
async open() {
|
|
3048
|
+
log12.trace("dxos.mesh.webrtc-transport.open", trace4.begin({
|
|
3049
|
+
id: this._instanceId
|
|
3050
|
+
}), {
|
|
3073
3051
|
F: __dxlog_file13,
|
|
3074
|
-
L:
|
|
3052
|
+
L: 122,
|
|
3075
3053
|
S: this,
|
|
3076
|
-
|
|
3077
|
-
"!this._isChannelCreationInProgress",
|
|
3078
|
-
""
|
|
3079
|
-
]
|
|
3080
|
-
});
|
|
3081
|
-
this._isChannelCreationInProgress = true;
|
|
3082
|
-
this._connection.createDataChannel(this._options.topic).then((channel) => {
|
|
3083
|
-
if (this.isOpen) {
|
|
3084
|
-
this._channel = channel;
|
|
3085
|
-
this._initChannel(this._channel);
|
|
3086
|
-
} else {
|
|
3087
|
-
this._safeCloseChannel(channel);
|
|
3088
|
-
}
|
|
3089
|
-
}).catch((err) => {
|
|
3090
|
-
if (this.isOpen) {
|
|
3091
|
-
this.errors.raise(new ConnectivityError2(`Failed to create a channel: ${err?.message ?? "unknown reason."}`));
|
|
3092
|
-
}
|
|
3093
|
-
}).finally(() => {
|
|
3094
|
-
this._isChannelCreationInProgress = false;
|
|
3054
|
+
C: (f, a) => f(...a)
|
|
3095
3055
|
});
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
this._safeCloseChannel(this._channel);
|
|
3100
|
-
this._channel = void 0;
|
|
3101
|
-
this._stream = void 0;
|
|
3102
|
-
}
|
|
3103
|
-
this.closed.emit();
|
|
3104
|
-
log12("closed", void 0, {
|
|
3056
|
+
log12("created connection", {
|
|
3057
|
+
params: this._params
|
|
3058
|
+
}, {
|
|
3105
3059
|
F: __dxlog_file13,
|
|
3106
|
-
L:
|
|
3060
|
+
L: 123,
|
|
3107
3061
|
S: this,
|
|
3108
3062
|
C: (f, a) => f(...a)
|
|
3109
3063
|
});
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3064
|
+
const providedIceServers = await this._params.iceProvider?.getIceServers();
|
|
3065
|
+
if (!this._params.webrtcConfig) {
|
|
3066
|
+
this._params.webrtcConfig = {};
|
|
3067
|
+
}
|
|
3068
|
+
this._params.webrtcConfig.iceServers = [
|
|
3069
|
+
...this._params.webrtcConfig.iceServers ?? [],
|
|
3070
|
+
...providedIceServers ?? []
|
|
3071
|
+
];
|
|
3072
|
+
this._peer = new SimplePeerConstructor({
|
|
3073
|
+
channelName: "dxos.mesh.transport",
|
|
3074
|
+
initiator: this._params.initiator,
|
|
3075
|
+
wrtc: SimplePeerConstructor.WEBRTC_SUPPORT ? void 0 : wrtc ?? raise2(new Error("wrtc not available")),
|
|
3076
|
+
config: this._params.webrtcConfig
|
|
3077
|
+
});
|
|
3078
|
+
this._peer.on("signal", async (data) => {
|
|
3079
|
+
log12("signal", data, {
|
|
3080
|
+
F: __dxlog_file13,
|
|
3081
|
+
L: 142,
|
|
3082
|
+
S: this,
|
|
3083
|
+
C: (f, a) => f(...a)
|
|
3084
|
+
});
|
|
3085
|
+
await this._params.sendSignal({
|
|
3086
|
+
payload: {
|
|
3087
|
+
data
|
|
3088
|
+
}
|
|
3089
|
+
});
|
|
3090
|
+
});
|
|
3091
|
+
this._peer.on("connect", () => {
|
|
3092
|
+
log12("connected", void 0, {
|
|
3093
|
+
F: __dxlog_file13,
|
|
3094
|
+
L: 147,
|
|
3095
|
+
S: this,
|
|
3096
|
+
C: (f, a) => f(...a)
|
|
3097
|
+
});
|
|
3098
|
+
this._params.stream.pipe(this._peer).pipe(this._params.stream);
|
|
3099
|
+
this._piped = true;
|
|
3100
|
+
this.connected.emit();
|
|
3101
|
+
});
|
|
3102
|
+
this._peer.on("close", async () => {
|
|
3103
|
+
log12("closed", void 0, {
|
|
3104
|
+
F: __dxlog_file13,
|
|
3105
|
+
L: 154,
|
|
3106
|
+
S: this,
|
|
3107
|
+
C: (f, a) => f(...a)
|
|
3108
|
+
});
|
|
3109
|
+
await this.close();
|
|
3110
|
+
});
|
|
3111
|
+
this._peer.on("error", async (err) => {
|
|
3112
|
+
if (typeof RTCError !== "undefined" && err instanceof RTCError) {
|
|
3113
|
+
if (err.errorDetail === "sctp-failure") {
|
|
3114
|
+
this.errors.raise(new ConnectionResetError2("sctp-failure from RTCError", err));
|
|
3115
|
+
} else {
|
|
3116
|
+
log12.info("unknown RTCError", {
|
|
3117
|
+
err
|
|
3117
3118
|
}, {
|
|
3118
3119
|
F: __dxlog_file13,
|
|
3119
|
-
L:
|
|
3120
|
+
L: 165,
|
|
3120
3121
|
S: this,
|
|
3121
3122
|
C: (f, a) => f(...a)
|
|
3122
3123
|
});
|
|
3123
|
-
this.
|
|
3124
|
-
return;
|
|
3124
|
+
this.errors.raise(new UnknownProtocolError2("unknown RTCError", err));
|
|
3125
3125
|
}
|
|
3126
|
-
|
|
3126
|
+
} else if ("code" in err) {
|
|
3127
|
+
log12.info("simple-peer error", err, {
|
|
3127
3128
|
F: __dxlog_file13,
|
|
3128
|
-
L:
|
|
3129
|
+
L: 170,
|
|
3129
3130
|
S: this,
|
|
3130
3131
|
C: (f, a) => f(...a)
|
|
3131
3132
|
});
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3133
|
+
switch (err.code) {
|
|
3134
|
+
case "ERR_WEBRTC_SUPPORT":
|
|
3135
|
+
this.errors.raise(new ProtocolError2("WebRTC not supported", err));
|
|
3136
|
+
break;
|
|
3137
|
+
case "ERR_SIGNALING":
|
|
3138
|
+
this.errors.raise(new ConnectivityError2("signaling failure", err));
|
|
3139
|
+
break;
|
|
3140
|
+
case "ERR_ICE_CONNECTION_FAILURE":
|
|
3141
|
+
case "ERR_DATA_CHANNEL":
|
|
3142
|
+
case "ERR_CONNECTION_FAILURE":
|
|
3143
|
+
this.errors.raise(new ConnectivityError2("unknown communication failure", err));
|
|
3144
|
+
break;
|
|
3145
|
+
// errors due to library issues or improper API usage
|
|
3146
|
+
case "ERR_CREATE_OFFER":
|
|
3147
|
+
case "ERR_CREATE_ANSWER":
|
|
3148
|
+
case "ERR_SET_LOCAL_DESCRIPTION":
|
|
3149
|
+
case "ERR_SET_REMOTE_DESCRIPTION":
|
|
3150
|
+
case "ERR_ADD_ICE_CANDIDATE":
|
|
3151
|
+
this.errors.raise(new UnknownProtocolError2("unknown simple-peer library failure", err));
|
|
3152
|
+
break;
|
|
3153
|
+
default:
|
|
3154
|
+
this.errors.raise(new Error("unknown simple-peer error"));
|
|
3155
|
+
break;
|
|
3156
|
+
}
|
|
3157
|
+
} else {
|
|
3158
|
+
log12.info("unknown peer connection error", err, {
|
|
3145
3159
|
F: __dxlog_file13,
|
|
3146
|
-
L:
|
|
3160
|
+
L: 196,
|
|
3147
3161
|
S: this,
|
|
3148
3162
|
C: (f, a) => f(...a)
|
|
3149
3163
|
});
|
|
3150
|
-
|
|
3151
|
-
}
|
|
3152
|
-
|
|
3153
|
-
if (
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3164
|
+
this.errors.raise(err);
|
|
3165
|
+
}
|
|
3166
|
+
try {
|
|
3167
|
+
if (typeof this._peer?._pc?.getStats === "function") {
|
|
3168
|
+
this._peer._pc.getStats().then((stats) => {
|
|
3169
|
+
log12.info("report after webrtc error", {
|
|
3170
|
+
config: this._params.webrtcConfig,
|
|
3171
|
+
stats: Object.fromEntries(stats.entries())
|
|
3172
|
+
}, {
|
|
3173
|
+
F: __dxlog_file13,
|
|
3174
|
+
L: 204,
|
|
3175
|
+
S: this,
|
|
3176
|
+
C: (f, a) => f(...a)
|
|
3177
|
+
});
|
|
3159
3178
|
});
|
|
3160
|
-
return;
|
|
3161
|
-
}
|
|
3162
|
-
let data = event.data;
|
|
3163
|
-
if (data instanceof ArrayBuffer) {
|
|
3164
|
-
data = Buffer.from(data);
|
|
3165
|
-
}
|
|
3166
|
-
this._stream.push(data);
|
|
3167
|
-
},
|
|
3168
|
-
onerror: (event) => {
|
|
3169
|
-
if (this.isOpen) {
|
|
3170
|
-
const err = event.error instanceof Error ? event.error : new Error(`Datachannel error: ${event.type}.`);
|
|
3171
|
-
this.errors.raise(err);
|
|
3172
3179
|
}
|
|
3173
|
-
}
|
|
3174
|
-
|
|
3175
|
-
const cb = this._streamDataFlushedCallback;
|
|
3176
|
-
this._streamDataFlushedCallback = null;
|
|
3177
|
-
cb?.();
|
|
3178
|
-
}
|
|
3179
|
-
});
|
|
3180
|
-
}
|
|
3181
|
-
async _handleChannelWrite(chunk, callback) {
|
|
3182
|
-
if (!this._channel) {
|
|
3183
|
-
log12.warn("writing to a channel after a connection was closed", void 0, {
|
|
3184
|
-
F: __dxlog_file13,
|
|
3185
|
-
L: 145,
|
|
3186
|
-
S: this,
|
|
3187
|
-
C: (f, a) => f(...a)
|
|
3188
|
-
});
|
|
3189
|
-
return;
|
|
3190
|
-
}
|
|
3191
|
-
if (chunk.length > MAX_MESSAGE_SIZE) {
|
|
3192
|
-
const error = new Error(`Message too large: ${chunk.length} > ${MAX_MESSAGE_SIZE}.`);
|
|
3193
|
-
this.errors.raise(error);
|
|
3194
|
-
callback();
|
|
3195
|
-
return;
|
|
3196
|
-
}
|
|
3197
|
-
try {
|
|
3198
|
-
this._channel.send(chunk);
|
|
3199
|
-
} catch (err) {
|
|
3200
|
-
this.errors.raise(err);
|
|
3201
|
-
callback();
|
|
3202
|
-
return;
|
|
3203
|
-
}
|
|
3204
|
-
if (this._channel.bufferedAmount > MAX_BUFFERED_AMOUNT) {
|
|
3205
|
-
if (this._streamDataFlushedCallback !== null) {
|
|
3206
|
-
log12.error("consumer trying to write before we are ready for more data", void 0, {
|
|
3180
|
+
} catch (err2) {
|
|
3181
|
+
log12.catch(err2, void 0, {
|
|
3207
3182
|
F: __dxlog_file13,
|
|
3208
|
-
L:
|
|
3183
|
+
L: 211,
|
|
3209
3184
|
S: this,
|
|
3210
3185
|
C: (f, a) => f(...a)
|
|
3211
3186
|
});
|
|
3212
3187
|
}
|
|
3213
|
-
this.
|
|
3214
|
-
}
|
|
3215
|
-
|
|
3216
|
-
|
|
3188
|
+
await this.close();
|
|
3189
|
+
});
|
|
3190
|
+
log12.trace("dxos.mesh.webrtc-transport.open", trace4.end({
|
|
3191
|
+
id: this._instanceId
|
|
3192
|
+
}), {
|
|
3193
|
+
F: __dxlog_file13,
|
|
3194
|
+
L: 217,
|
|
3195
|
+
S: this,
|
|
3196
|
+
C: (f, a) => f(...a)
|
|
3197
|
+
});
|
|
3217
3198
|
}
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
});
|
|
3199
|
+
async close() {
|
|
3200
|
+
log12("closing...", void 0, {
|
|
3201
|
+
F: __dxlog_file13,
|
|
3202
|
+
L: 222,
|
|
3203
|
+
S: this,
|
|
3204
|
+
C: (f, a) => f(...a)
|
|
3205
|
+
});
|
|
3206
|
+
if (this._closed) {
|
|
3207
|
+
return;
|
|
3228
3208
|
}
|
|
3209
|
+
this._disconnectStreams();
|
|
3210
|
+
this._peer.destroy();
|
|
3211
|
+
this._closed = true;
|
|
3212
|
+
this.closed.emit();
|
|
3213
|
+
log12("closed", void 0, {
|
|
3214
|
+
F: __dxlog_file13,
|
|
3215
|
+
L: 230,
|
|
3216
|
+
S: this,
|
|
3217
|
+
C: (f, a) => f(...a)
|
|
3218
|
+
});
|
|
3229
3219
|
}
|
|
3230
|
-
onSignal(signal) {
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
async getDetails() {
|
|
3234
|
-
return describeSelectedRemoteCandidate(this._connection.currentConnection);
|
|
3235
|
-
}
|
|
3236
|
-
async getStats() {
|
|
3237
|
-
return createRtcTransportStats(this._connection.currentConnection, this._options.topic);
|
|
3238
|
-
}
|
|
3239
|
-
};
|
|
3240
|
-
|
|
3241
|
-
// packages/core/mesh/network-manager/src/transport/webrtc/utils.ts
|
|
3242
|
-
var chooseInitiatorPeer = (peer1Key, peer2Key) => peer1Key < peer2Key ? peer1Key : peer2Key;
|
|
3243
|
-
var areSdpEqual = (sdp1, sdp2) => {
|
|
3244
|
-
const sdp1Lines = deduplicatedSdpLines(sdp1);
|
|
3245
|
-
const sdp2Lines = deduplicatedSdpLines(sdp2);
|
|
3246
|
-
if (sdp1Lines.length !== sdp2Lines.length) {
|
|
3247
|
-
return false;
|
|
3248
|
-
}
|
|
3249
|
-
return sdp1Lines.every((line, idx) => line === sdp2Lines[idx]);
|
|
3250
|
-
};
|
|
3251
|
-
var deduplicatedSdpLines = (sdp) => {
|
|
3252
|
-
const deduplicatedLines = [];
|
|
3253
|
-
const seenLines = [];
|
|
3254
|
-
for (const line of sdp.split("\r\n")) {
|
|
3255
|
-
if (line.startsWith("m")) {
|
|
3256
|
-
seenLines.length = 0;
|
|
3220
|
+
async onSignal(signal) {
|
|
3221
|
+
if (this._closed) {
|
|
3222
|
+
return;
|
|
3257
3223
|
}
|
|
3258
|
-
|
|
3259
|
-
|
|
3224
|
+
invariant11(signal.payload.data, "Signal message must contain signal data.");
|
|
3225
|
+
invariant11(this._peer, "Peer must be initialized before receiving signals.");
|
|
3226
|
+
this._peer.signal(signal.payload.data);
|
|
3227
|
+
}
|
|
3228
|
+
_disconnectStreams() {
|
|
3229
|
+
if (this._piped) {
|
|
3230
|
+
this._params.stream.unpipe?.(this._peer)?.unpipe?.(this._params.stream);
|
|
3260
3231
|
}
|
|
3261
|
-
seenLines.push(line);
|
|
3262
|
-
deduplicatedLines.push(line);
|
|
3263
3232
|
}
|
|
3264
|
-
return deduplicatedLines;
|
|
3265
3233
|
};
|
|
3234
|
+
_ts_decorate6([
|
|
3235
|
+
synchronized5
|
|
3236
|
+
], SimplePeerTransport.prototype, "open", null);
|
|
3237
|
+
_ts_decorate6([
|
|
3238
|
+
synchronized5
|
|
3239
|
+
], SimplePeerTransport.prototype, "close", null);
|
|
3240
|
+
_ts_decorate6([
|
|
3241
|
+
synchronized5
|
|
3242
|
+
], SimplePeerTransport.prototype, "onSignal", null);
|
|
3266
3243
|
|
|
3267
|
-
// packages/core/mesh/network-manager/src/transport/
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
}
|
|
3274
|
-
|
|
3275
|
-
var
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
this.
|
|
3279
|
-
this.
|
|
3280
|
-
this.
|
|
3281
|
-
this._dataChannels = /* @__PURE__ */ new Map();
|
|
3282
|
-
this._readyForCandidates = new Trigger3();
|
|
3283
|
-
this._offerProcessingMutex = new Mutex2();
|
|
3284
|
-
this._initiator = chooseInitiatorPeer(_options.ownPeerKey, _options.remotePeerKey) === _options.ownPeerKey;
|
|
3285
|
-
}
|
|
3286
|
-
get transportChannelCount() {
|
|
3287
|
-
return this._transportChannels.size;
|
|
3288
|
-
}
|
|
3289
|
-
get currentConnection() {
|
|
3290
|
-
return this._connection;
|
|
3244
|
+
// packages/core/mesh/network-manager/src/transport/simplepeer-transport-service.ts
|
|
3245
|
+
import { Duplex } from "@dxos/node-std/stream";
|
|
3246
|
+
import { Stream } from "@dxos/codec-protobuf";
|
|
3247
|
+
import { invariant as invariant12 } from "@dxos/invariant";
|
|
3248
|
+
import { PublicKey as PublicKey11 } from "@dxos/keys";
|
|
3249
|
+
import { log as log13 } from "@dxos/log";
|
|
3250
|
+
import { ConnectionState as ConnectionState3 } from "@dxos/protocols/proto/dxos/mesh/bridge";
|
|
3251
|
+
import { ComplexMap as ComplexMap8 } from "@dxos/util";
|
|
3252
|
+
var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/simplepeer-transport-service.ts";
|
|
3253
|
+
var SimplePeerTransportService = class {
|
|
3254
|
+
constructor(_webrtcConfig, _iceProvider) {
|
|
3255
|
+
this._webrtcConfig = _webrtcConfig;
|
|
3256
|
+
this._iceProvider = _iceProvider;
|
|
3257
|
+
this.transports = new ComplexMap8(PublicKey11.hash);
|
|
3291
3258
|
}
|
|
3292
|
-
|
|
3293
|
-
const
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
log13("waiting for initiator-peer to open a data channel", void 0, {
|
|
3310
|
-
F: __dxlog_file14,
|
|
3311
|
-
L: 90,
|
|
3312
|
-
S: this,
|
|
3313
|
-
C: (f, a) => f(...a)
|
|
3314
|
-
});
|
|
3315
|
-
return new Promise((resolve, reject) => {
|
|
3316
|
-
this._channelCreatedCallbacks.set(topic, {
|
|
3317
|
-
resolve,
|
|
3318
|
-
reject
|
|
3319
|
-
});
|
|
3320
|
-
});
|
|
3321
|
-
}
|
|
3322
|
-
}
|
|
3323
|
-
createTransportChannel(options) {
|
|
3324
|
-
const channel = new RtcTransportChannel(this, options);
|
|
3325
|
-
this._transportChannels.set(options.topic, channel);
|
|
3326
|
-
channel.closed.on(() => {
|
|
3327
|
-
this._transportChannels.delete(options.topic);
|
|
3328
|
-
if (this._transportChannels.size === 0) {
|
|
3329
|
-
this._lockAndCloseConnection();
|
|
3330
|
-
}
|
|
3331
|
-
});
|
|
3332
|
-
return channel;
|
|
3333
|
-
}
|
|
3334
|
-
async _openConnection() {
|
|
3335
|
-
if (this._connection) {
|
|
3336
|
-
return this._connection;
|
|
3337
|
-
}
|
|
3338
|
-
log13("initializing connection...", () => ({
|
|
3339
|
-
remotePeer: this._options.remotePeerKey
|
|
3340
|
-
}), {
|
|
3341
|
-
F: __dxlog_file14,
|
|
3342
|
-
L: 115,
|
|
3343
|
-
S: this,
|
|
3344
|
-
C: (f, a) => f(...a)
|
|
3345
|
-
});
|
|
3346
|
-
const config = await this._loadConnectionConfig();
|
|
3347
|
-
const connection = await this._factory.createConnection(config);
|
|
3348
|
-
const iceCandidateErrors = [];
|
|
3349
|
-
Object.assign(connection, {
|
|
3350
|
-
onnegotiationneeded: async () => {
|
|
3351
|
-
invariant12(this._initiator, void 0, {
|
|
3352
|
-
F: __dxlog_file14,
|
|
3353
|
-
L: 130,
|
|
3354
|
-
S: this,
|
|
3355
|
-
A: [
|
|
3356
|
-
"this._initiator",
|
|
3357
|
-
""
|
|
3358
|
-
]
|
|
3359
|
-
});
|
|
3360
|
-
if (connection !== this._connection) {
|
|
3361
|
-
this._onConnectionCallbackAfterClose("onnegotiationneeded", connection);
|
|
3362
|
-
return;
|
|
3363
|
-
}
|
|
3364
|
-
log13("onnegotiationneeded", void 0, {
|
|
3365
|
-
F: __dxlog_file14,
|
|
3366
|
-
L: 137,
|
|
3367
|
-
S: this,
|
|
3368
|
-
C: (f, a) => f(...a)
|
|
3369
|
-
});
|
|
3370
|
-
try {
|
|
3371
|
-
const offer = await connection.createOffer();
|
|
3372
|
-
await connection.setLocalDescription(offer);
|
|
3373
|
-
await this._sendDescription(connection, offer);
|
|
3374
|
-
} catch (err) {
|
|
3375
|
-
this._lockAndAbort(connection, err);
|
|
3376
|
-
}
|
|
3377
|
-
},
|
|
3378
|
-
// When ICE candidate identified (should be sent to remote peer) and when ICE gathering finalized.
|
|
3379
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/icecandidate_event
|
|
3380
|
-
onicecandidate: async (event) => {
|
|
3381
|
-
if (connection !== this._connection) {
|
|
3382
|
-
this._onConnectionCallbackAfterClose("onicecandidate", connection);
|
|
3383
|
-
return;
|
|
3384
|
-
}
|
|
3385
|
-
if (event.candidate) {
|
|
3386
|
-
log13("onicecandidate", {
|
|
3387
|
-
candidate: event.candidate.candidate
|
|
3388
|
-
}, {
|
|
3389
|
-
F: __dxlog_file14,
|
|
3390
|
-
L: 156,
|
|
3391
|
-
S: this,
|
|
3392
|
-
C: (f, a) => f(...a)
|
|
3393
|
-
});
|
|
3394
|
-
await this._sendIceCandidate(event.candidate);
|
|
3395
|
-
} else {
|
|
3396
|
-
log13("onicecandidate gathering complete", void 0, {
|
|
3397
|
-
F: __dxlog_file14,
|
|
3398
|
-
L: 159,
|
|
3399
|
-
S: this,
|
|
3400
|
-
C: (f, a) => f(...a)
|
|
3259
|
+
open(request) {
|
|
3260
|
+
const rpcStream = new Stream(({ ready, next, close }) => {
|
|
3261
|
+
const duplex = new Duplex({
|
|
3262
|
+
read: () => {
|
|
3263
|
+
const callbacks = [
|
|
3264
|
+
...transportState.writeCallbacks
|
|
3265
|
+
];
|
|
3266
|
+
transportState.writeCallbacks.length = 0;
|
|
3267
|
+
for (const cb of callbacks) {
|
|
3268
|
+
cb();
|
|
3269
|
+
}
|
|
3270
|
+
},
|
|
3271
|
+
write: function(chunk, _, callback) {
|
|
3272
|
+
next({
|
|
3273
|
+
data: {
|
|
3274
|
+
payload: chunk
|
|
3275
|
+
}
|
|
3401
3276
|
});
|
|
3277
|
+
callback();
|
|
3402
3278
|
}
|
|
3403
|
-
}
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
}
|
|
3422
|
-
log13("oniceconnectionstatechange", {
|
|
3423
|
-
state: connection.iceConnectionState
|
|
3424
|
-
}, {
|
|
3425
|
-
F: __dxlog_file14,
|
|
3426
|
-
L: 179,
|
|
3427
|
-
S: this,
|
|
3428
|
-
C: (f, a) => f(...a)
|
|
3429
|
-
});
|
|
3430
|
-
if (connection.iceConnectionState === "failed") {
|
|
3431
|
-
this._lockAndAbort(connection, createIceFailureError(iceCandidateErrors));
|
|
3279
|
+
});
|
|
3280
|
+
const transport = new SimplePeerTransport({
|
|
3281
|
+
initiator: request.initiator,
|
|
3282
|
+
stream: duplex,
|
|
3283
|
+
webrtcConfig: this._webrtcConfig,
|
|
3284
|
+
sendSignal: async (signal) => {
|
|
3285
|
+
next({
|
|
3286
|
+
signal: {
|
|
3287
|
+
payload: signal
|
|
3288
|
+
}
|
|
3289
|
+
});
|
|
3290
|
+
},
|
|
3291
|
+
iceProvider: this._iceProvider
|
|
3292
|
+
});
|
|
3293
|
+
void transport.open();
|
|
3294
|
+
next({
|
|
3295
|
+
connection: {
|
|
3296
|
+
state: ConnectionState3.CONNECTING
|
|
3432
3297
|
}
|
|
3433
|
-
}
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
if (connection !== this._connection) {
|
|
3439
|
-
if (connection.connectionState !== "closed" && connection.connectionState !== "failed") {
|
|
3440
|
-
this._onConnectionCallbackAfterClose("onconnectionstatechange", connection);
|
|
3298
|
+
});
|
|
3299
|
+
transport.connected.on(() => {
|
|
3300
|
+
next({
|
|
3301
|
+
connection: {
|
|
3302
|
+
state: ConnectionState3.CONNECTED
|
|
3441
3303
|
}
|
|
3442
|
-
return;
|
|
3443
|
-
}
|
|
3444
|
-
log13("onconnectionstatechange", {
|
|
3445
|
-
state: connection.connectionState
|
|
3446
|
-
}, {
|
|
3447
|
-
F: __dxlog_file14,
|
|
3448
|
-
L: 196,
|
|
3449
|
-
S: this,
|
|
3450
|
-
C: (f, a) => f(...a)
|
|
3451
3304
|
});
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
}, {
|
|
3460
|
-
F: __dxlog_file14,
|
|
3461
|
-
L: 203,
|
|
3462
|
-
S: this,
|
|
3463
|
-
C: (f, a) => f(...a)
|
|
3464
|
-
});
|
|
3465
|
-
},
|
|
3466
|
-
// When channel is added to connection.
|
|
3467
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/datachannel_event
|
|
3468
|
-
ondatachannel: (event) => {
|
|
3469
|
-
invariant12(!this._initiator, "Initiator is expected to create data channels.", {
|
|
3470
|
-
F: __dxlog_file14,
|
|
3471
|
-
L: 209,
|
|
3472
|
-
S: this,
|
|
3473
|
-
A: [
|
|
3474
|
-
"!this._initiator",
|
|
3475
|
-
"'Initiator is expected to create data channels.'"
|
|
3476
|
-
]
|
|
3305
|
+
});
|
|
3306
|
+
transport.errors.handle((err) => {
|
|
3307
|
+
next({
|
|
3308
|
+
connection: {
|
|
3309
|
+
state: ConnectionState3.CLOSED,
|
|
3310
|
+
error: err.toString()
|
|
3311
|
+
}
|
|
3477
3312
|
});
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
F: __dxlog_file14,
|
|
3486
|
-
L: 216,
|
|
3487
|
-
S: this,
|
|
3488
|
-
C: (f, a) => f(...a)
|
|
3313
|
+
close(err);
|
|
3314
|
+
});
|
|
3315
|
+
transport.closed.on(() => {
|
|
3316
|
+
next({
|
|
3317
|
+
connection: {
|
|
3318
|
+
state: ConnectionState3.CLOSED
|
|
3319
|
+
}
|
|
3489
3320
|
});
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
await this._factory.initConnection(connection, {
|
|
3501
|
-
initiator: this._initiator
|
|
3321
|
+
close();
|
|
3322
|
+
});
|
|
3323
|
+
const transportState = {
|
|
3324
|
+
transport,
|
|
3325
|
+
stream: duplex,
|
|
3326
|
+
writeCallbacks: [],
|
|
3327
|
+
state: "OPEN"
|
|
3328
|
+
};
|
|
3329
|
+
ready();
|
|
3330
|
+
this.transports.set(request.proxyId, transportState);
|
|
3502
3331
|
});
|
|
3503
|
-
return
|
|
3332
|
+
return rpcStream;
|
|
3504
3333
|
}
|
|
3505
|
-
|
|
3506
|
-
this.
|
|
3507
|
-
}
|
|
3508
|
-
_abortConnection(connection, error) {
|
|
3509
|
-
if (connection !== this._connection) {
|
|
3510
|
-
log13.error("attempted to abort an inactive connection", {
|
|
3511
|
-
error
|
|
3512
|
-
}, {
|
|
3513
|
-
F: __dxlog_file14,
|
|
3514
|
-
L: 241,
|
|
3515
|
-
S: this,
|
|
3516
|
-
C: (f, a) => f(...a)
|
|
3517
|
-
});
|
|
3518
|
-
this._safeCloseConnection(connection);
|
|
3519
|
-
return;
|
|
3520
|
-
}
|
|
3521
|
-
for (const [topic, pendingCallback] of this._channelCreatedCallbacks.entries()) {
|
|
3522
|
-
pendingCallback.reject(error);
|
|
3523
|
-
this._transportChannels.delete(topic);
|
|
3524
|
-
}
|
|
3525
|
-
this._channelCreatedCallbacks.clear();
|
|
3526
|
-
for (const channel of this._transportChannels.values()) {
|
|
3527
|
-
channel.onConnectionError(error);
|
|
3528
|
-
}
|
|
3529
|
-
this._transportChannels.clear();
|
|
3530
|
-
this._safeCloseConnection();
|
|
3531
|
-
log13("connection aborted", {
|
|
3532
|
-
reason: error.message
|
|
3533
|
-
}, {
|
|
3334
|
+
async sendSignal({ proxyId, signal }) {
|
|
3335
|
+
invariant12(this.transports.has(proxyId), void 0, {
|
|
3534
3336
|
F: __dxlog_file14,
|
|
3535
|
-
L:
|
|
3337
|
+
L: 124,
|
|
3536
3338
|
S: this,
|
|
3537
|
-
|
|
3339
|
+
A: [
|
|
3340
|
+
"this.transports.has(proxyId)",
|
|
3341
|
+
""
|
|
3342
|
+
]
|
|
3538
3343
|
});
|
|
3344
|
+
await this.transports.get(proxyId).transport.onSignal(signal);
|
|
3539
3345
|
}
|
|
3540
|
-
|
|
3541
|
-
invariant12(this.
|
|
3346
|
+
async getDetails({ proxyId }) {
|
|
3347
|
+
invariant12(this.transports.has(proxyId), void 0, {
|
|
3542
3348
|
F: __dxlog_file14,
|
|
3543
|
-
L:
|
|
3349
|
+
L: 129,
|
|
3544
3350
|
S: this,
|
|
3545
3351
|
A: [
|
|
3546
|
-
"this.
|
|
3352
|
+
"this.transports.has(proxyId)",
|
|
3547
3353
|
""
|
|
3548
3354
|
]
|
|
3549
3355
|
});
|
|
3550
|
-
|
|
3551
|
-
this.
|
|
3552
|
-
|
|
3553
|
-
F: __dxlog_file14,
|
|
3554
|
-
L: 263,
|
|
3555
|
-
S: this,
|
|
3556
|
-
C: (f, a) => f(...a)
|
|
3557
|
-
});
|
|
3558
|
-
}
|
|
3356
|
+
return {
|
|
3357
|
+
details: await this.transports.get(proxyId).transport.getDetails()
|
|
3358
|
+
};
|
|
3559
3359
|
}
|
|
3560
|
-
async
|
|
3561
|
-
|
|
3562
|
-
if (!connection) {
|
|
3563
|
-
log13.warn("a signal ignored because the connection was closed", {
|
|
3564
|
-
type: signal.payload.data.type
|
|
3565
|
-
}, {
|
|
3566
|
-
F: __dxlog_file14,
|
|
3567
|
-
L: 271,
|
|
3568
|
-
S: this,
|
|
3569
|
-
C: (f, a) => f(...a)
|
|
3570
|
-
});
|
|
3571
|
-
return;
|
|
3572
|
-
}
|
|
3573
|
-
const data = signal.payload.data;
|
|
3574
|
-
switch (data.type) {
|
|
3575
|
-
case "offer": {
|
|
3576
|
-
await this._offerProcessingMutex.executeSynchronized(async () => {
|
|
3577
|
-
if (isRemoteDescriptionSet(connection, data)) {
|
|
3578
|
-
return;
|
|
3579
|
-
}
|
|
3580
|
-
if (connection.connectionState !== "new") {
|
|
3581
|
-
this._abortConnection(connection, new Error(`Received an offer in ${connection.connectionState}.`));
|
|
3582
|
-
return;
|
|
3583
|
-
}
|
|
3584
|
-
try {
|
|
3585
|
-
await connection.setRemoteDescription({
|
|
3586
|
-
type: data.type,
|
|
3587
|
-
sdp: data.sdp
|
|
3588
|
-
});
|
|
3589
|
-
const answer = await connection.createAnswer();
|
|
3590
|
-
await connection.setLocalDescription(answer);
|
|
3591
|
-
await this._sendDescription(connection, answer);
|
|
3592
|
-
this._onSessionNegotiated(connection);
|
|
3593
|
-
} catch (err) {
|
|
3594
|
-
this._abortConnection(connection, new Error("Error handling a remote offer.", {
|
|
3595
|
-
cause: err
|
|
3596
|
-
}));
|
|
3597
|
-
}
|
|
3598
|
-
});
|
|
3599
|
-
break;
|
|
3600
|
-
}
|
|
3601
|
-
case "answer":
|
|
3602
|
-
await this._offerProcessingMutex.executeSynchronized(async () => {
|
|
3603
|
-
try {
|
|
3604
|
-
if (isRemoteDescriptionSet(connection, data)) {
|
|
3605
|
-
return;
|
|
3606
|
-
}
|
|
3607
|
-
if (connection.signalingState !== "have-local-offer") {
|
|
3608
|
-
this._abortConnection(connection, new Error(`Unexpected answer from remote peer, signalingState was ${connection.signalingState}.`));
|
|
3609
|
-
return;
|
|
3610
|
-
}
|
|
3611
|
-
await connection.setRemoteDescription({
|
|
3612
|
-
type: data.type,
|
|
3613
|
-
sdp: data.sdp
|
|
3614
|
-
});
|
|
3615
|
-
this._onSessionNegotiated(connection);
|
|
3616
|
-
} catch (err) {
|
|
3617
|
-
this._abortConnection(connection, new Error("Error handling a remote answer.", {
|
|
3618
|
-
cause: err
|
|
3619
|
-
}));
|
|
3620
|
-
}
|
|
3621
|
-
});
|
|
3622
|
-
break;
|
|
3623
|
-
case "candidate":
|
|
3624
|
-
void this._processIceCandidate(connection, data.candidate);
|
|
3625
|
-
break;
|
|
3626
|
-
default:
|
|
3627
|
-
this._abortConnection(connection, new Error(`Unknown signal type ${data.type}.`));
|
|
3628
|
-
break;
|
|
3629
|
-
}
|
|
3630
|
-
log13("signal processed", void 0, {
|
|
3360
|
+
async getStats({ proxyId }) {
|
|
3361
|
+
invariant12(this.transports.has(proxyId), void 0, {
|
|
3631
3362
|
F: __dxlog_file14,
|
|
3632
|
-
L:
|
|
3363
|
+
L: 134,
|
|
3633
3364
|
S: this,
|
|
3634
|
-
|
|
3365
|
+
A: [
|
|
3366
|
+
"this.transports.has(proxyId)",
|
|
3367
|
+
""
|
|
3368
|
+
]
|
|
3635
3369
|
});
|
|
3370
|
+
return {
|
|
3371
|
+
stats: await this.transports.get(proxyId).transport.getStats()
|
|
3372
|
+
};
|
|
3636
3373
|
}
|
|
3637
|
-
async
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
if (connection === this._connection) {
|
|
3641
|
-
log13("adding ice candidate", {
|
|
3642
|
-
candidate
|
|
3643
|
-
}, {
|
|
3644
|
-
F: __dxlog_file14,
|
|
3645
|
-
L: 338,
|
|
3646
|
-
S: this,
|
|
3647
|
-
C: (f, a) => f(...a)
|
|
3648
|
-
});
|
|
3649
|
-
await connection.addIceCandidate(candidate);
|
|
3650
|
-
}
|
|
3651
|
-
} catch (err) {
|
|
3652
|
-
log13.catch(err, void 0, {
|
|
3653
|
-
F: __dxlog_file14,
|
|
3654
|
-
L: 342,
|
|
3655
|
-
S: this,
|
|
3656
|
-
C: (f, a) => f(...a)
|
|
3657
|
-
});
|
|
3658
|
-
}
|
|
3659
|
-
}
|
|
3660
|
-
_onSessionNegotiated(connection) {
|
|
3661
|
-
if (connection === this._connection) {
|
|
3662
|
-
log13("ready to process ice candidates", void 0, {
|
|
3663
|
-
F: __dxlog_file14,
|
|
3664
|
-
L: 348,
|
|
3665
|
-
S: this,
|
|
3666
|
-
C: (f, a) => f(...a)
|
|
3667
|
-
});
|
|
3668
|
-
this._readyForCandidates.wake();
|
|
3669
|
-
} else {
|
|
3670
|
-
log13.warn("session was negotiated after connection became inactive", void 0, {
|
|
3374
|
+
async sendData({ proxyId, payload }) {
|
|
3375
|
+
if (this.transports.get(proxyId)?.state !== "OPEN") {
|
|
3376
|
+
log13.debug("transport is closed", void 0, {
|
|
3671
3377
|
F: __dxlog_file14,
|
|
3672
|
-
L:
|
|
3378
|
+
L: 140,
|
|
3673
3379
|
S: this,
|
|
3674
3380
|
C: (f, a) => f(...a)
|
|
3675
3381
|
});
|
|
3676
3382
|
}
|
|
3677
|
-
|
|
3678
|
-
_onConnectionCallbackAfterClose(callback, connection) {
|
|
3679
|
-
log13.warn("callback invoked after a connection was destroyed, this is probably a bug", {
|
|
3680
|
-
callback,
|
|
3681
|
-
state: connection.connectionState
|
|
3682
|
-
}, {
|
|
3383
|
+
invariant12(this.transports.has(proxyId), void 0, {
|
|
3683
3384
|
F: __dxlog_file14,
|
|
3684
|
-
L:
|
|
3385
|
+
L: 142,
|
|
3685
3386
|
S: this,
|
|
3686
|
-
|
|
3387
|
+
A: [
|
|
3388
|
+
"this.transports.has(proxyId)",
|
|
3389
|
+
""
|
|
3390
|
+
]
|
|
3687
3391
|
});
|
|
3688
|
-
this.
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
connection?.close();
|
|
3694
|
-
} catch (err) {
|
|
3695
|
-
log13.catch(err, void 0, {
|
|
3696
|
-
F: __dxlog_file14,
|
|
3697
|
-
L: 368,
|
|
3698
|
-
S: this,
|
|
3699
|
-
C: (f, a) => f(...a)
|
|
3700
|
-
});
|
|
3701
|
-
}
|
|
3702
|
-
if (resetFields) {
|
|
3703
|
-
this._connection = void 0;
|
|
3704
|
-
this._dataChannels.clear();
|
|
3705
|
-
this._readyForCandidates.wake();
|
|
3706
|
-
void this._factory.onConnectionDestroyed().catch((err) => log13.catch(err, void 0, {
|
|
3707
|
-
F: __dxlog_file14,
|
|
3708
|
-
L: 374,
|
|
3709
|
-
S: this,
|
|
3710
|
-
C: (f, a) => f(...a)
|
|
3711
|
-
}));
|
|
3712
|
-
for (const [_, pendingCallback] of this._channelCreatedCallbacks.entries()) {
|
|
3713
|
-
pendingCallback.reject("Connection closed.");
|
|
3714
|
-
}
|
|
3715
|
-
this._channelCreatedCallbacks.clear();
|
|
3716
|
-
}
|
|
3717
|
-
}
|
|
3718
|
-
async _loadConnectionConfig() {
|
|
3719
|
-
const config = {
|
|
3720
|
-
...this._options.webrtcConfig
|
|
3721
|
-
};
|
|
3722
|
-
try {
|
|
3723
|
-
const providedIceServers = await this._options.iceProvider?.getIceServers() ?? [];
|
|
3724
|
-
if (providedIceServers.length > 0) {
|
|
3725
|
-
config.iceServers = [
|
|
3726
|
-
...config.iceServers ?? [],
|
|
3727
|
-
...providedIceServers
|
|
3728
|
-
];
|
|
3729
|
-
}
|
|
3730
|
-
} catch (error) {
|
|
3731
|
-
log13.catch(error, void 0, {
|
|
3732
|
-
F: __dxlog_file14,
|
|
3733
|
-
L: 390,
|
|
3734
|
-
S: this,
|
|
3735
|
-
C: (f, a) => f(...a)
|
|
3736
|
-
});
|
|
3737
|
-
}
|
|
3738
|
-
return config;
|
|
3739
|
-
}
|
|
3740
|
-
async _sendIceCandidate(candidate) {
|
|
3741
|
-
try {
|
|
3742
|
-
await this._options.sendSignal({
|
|
3743
|
-
payload: {
|
|
3744
|
-
data: {
|
|
3745
|
-
type: "candidate",
|
|
3746
|
-
candidate: {
|
|
3747
|
-
candidate: candidate.candidate,
|
|
3748
|
-
// These fields never seem to be not null, but connecting to Chrome doesn't work if they are.
|
|
3749
|
-
sdpMLineIndex: candidate.sdpMLineIndex ?? "0",
|
|
3750
|
-
sdpMid: candidate.sdpMid ?? "0"
|
|
3751
|
-
}
|
|
3752
|
-
}
|
|
3753
|
-
}
|
|
3754
|
-
});
|
|
3755
|
-
} catch (err) {
|
|
3756
|
-
log13.warn("signaling error", {
|
|
3757
|
-
err
|
|
3758
|
-
}, {
|
|
3759
|
-
F: __dxlog_file14,
|
|
3760
|
-
L: 411,
|
|
3761
|
-
S: this,
|
|
3762
|
-
C: (f, a) => f(...a)
|
|
3392
|
+
const state = this.transports.get(proxyId);
|
|
3393
|
+
const bufferHasSpace = state.stream.push(payload);
|
|
3394
|
+
if (!bufferHasSpace) {
|
|
3395
|
+
await new Promise((resolve) => {
|
|
3396
|
+
state.writeCallbacks.push(resolve);
|
|
3763
3397
|
});
|
|
3764
3398
|
}
|
|
3765
3399
|
}
|
|
3766
|
-
async
|
|
3767
|
-
|
|
3768
|
-
|
|
3400
|
+
async close({ proxyId }) {
|
|
3401
|
+
await this.transports.get(proxyId)?.transport.close();
|
|
3402
|
+
await this.transports.get(proxyId)?.stream.end();
|
|
3403
|
+
if (this.transports.get(proxyId)) {
|
|
3404
|
+
this.transports.get(proxyId).state = "CLOSED";
|
|
3769
3405
|
}
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
payload: {
|
|
3776
|
-
data
|
|
3777
|
-
}
|
|
3406
|
+
log13("Closed.", void 0, {
|
|
3407
|
+
F: __dxlog_file14,
|
|
3408
|
+
L: 158,
|
|
3409
|
+
S: this,
|
|
3410
|
+
C: (f, a) => f(...a)
|
|
3778
3411
|
});
|
|
3779
3412
|
}
|
|
3780
|
-
get _connectionInfo() {
|
|
3781
|
-
const connectionInfo = this._connection && {
|
|
3782
|
-
connectionState: this._connection.connectionState,
|
|
3783
|
-
iceConnectionState: this._connection.iceConnectionState,
|
|
3784
|
-
iceGatheringState: this._connection.iceGatheringState,
|
|
3785
|
-
signalingState: this._connection.signalingState,
|
|
3786
|
-
remoteDescription: this._connection.remoteDescription,
|
|
3787
|
-
localDescription: this._connection.localDescription
|
|
3788
|
-
};
|
|
3789
|
-
return {
|
|
3790
|
-
...connectionInfo,
|
|
3791
|
-
ts: Date.now(),
|
|
3792
|
-
remotePeerKey: this._options.remotePeerKey,
|
|
3793
|
-
channels: [
|
|
3794
|
-
...this._transportChannels.keys()
|
|
3795
|
-
].map((topic) => topic),
|
|
3796
|
-
config: this._connection?.getConfiguration()
|
|
3797
|
-
};
|
|
3798
|
-
}
|
|
3799
|
-
get _loggerContext() {
|
|
3800
|
-
return {
|
|
3801
|
-
ownPeerKey: this._options.ownPeerKey,
|
|
3802
|
-
remotePeerKey: this._options.remotePeerKey,
|
|
3803
|
-
initiator: this._initiator,
|
|
3804
|
-
channels: this._transportChannels.size
|
|
3805
|
-
};
|
|
3806
|
-
}
|
|
3807
|
-
};
|
|
3808
|
-
_ts_decorate6([
|
|
3809
|
-
synchronized5
|
|
3810
|
-
], RtcPeerConnection.prototype, "_openConnection", null);
|
|
3811
|
-
_ts_decorate6([
|
|
3812
|
-
synchronized5
|
|
3813
|
-
], RtcPeerConnection.prototype, "_lockAndAbort", null);
|
|
3814
|
-
_ts_decorate6([
|
|
3815
|
-
synchronized5
|
|
3816
|
-
], RtcPeerConnection.prototype, "_lockAndCloseConnection", null);
|
|
3817
|
-
_ts_decorate6([
|
|
3818
|
-
synchronized5
|
|
3819
|
-
], RtcPeerConnection.prototype, "onSignal", null);
|
|
3820
|
-
_ts_decorate6([
|
|
3821
|
-
trace4.info()
|
|
3822
|
-
], RtcPeerConnection.prototype, "_connectionInfo", null);
|
|
3823
|
-
_ts_decorate6([
|
|
3824
|
-
logInfo4
|
|
3825
|
-
], RtcPeerConnection.prototype, "_loggerContext", null);
|
|
3826
|
-
RtcPeerConnection = _ts_decorate6([
|
|
3827
|
-
trace4.resource()
|
|
3828
|
-
], RtcPeerConnection);
|
|
3829
|
-
var isRemoteDescriptionSet = (connection, data) => {
|
|
3830
|
-
if (!connection.remoteDescription?.type || connection.remoteDescription?.type !== data.type) {
|
|
3831
|
-
return false;
|
|
3832
|
-
}
|
|
3833
|
-
return areSdpEqual(connection.remoteDescription.sdp, data.sdp);
|
|
3834
|
-
};
|
|
3835
|
-
var createIceFailureError = (details) => {
|
|
3836
|
-
const candidateErrors = details.map(({ url, errorCode, errorText }) => `${errorCode} ${url}: ${errorText}`);
|
|
3837
|
-
return new ConnectivityError3(`ICE failed:
|
|
3838
|
-
${candidateErrors.join("\n")}`);
|
|
3839
3413
|
};
|
|
3840
3414
|
|
|
3841
|
-
// packages/core/mesh/network-manager/src/transport/
|
|
3842
|
-
var createRtcTransportFactory = (webrtcConfig, iceProvider) => {
|
|
3843
|
-
const connectionFactory = getRtcConnectionFactory();
|
|
3844
|
-
return {
|
|
3845
|
-
createTransport: (options) => {
|
|
3846
|
-
const connection = new RtcPeerConnection(connectionFactory, {
|
|
3847
|
-
ownPeerKey: options.ownPeerKey,
|
|
3848
|
-
remotePeerKey: options.remotePeerKey,
|
|
3849
|
-
sendSignal: options.sendSignal,
|
|
3850
|
-
webrtcConfig,
|
|
3851
|
-
iceProvider
|
|
3852
|
-
});
|
|
3853
|
-
return connection.createTransportChannel(options);
|
|
3854
|
-
}
|
|
3855
|
-
};
|
|
3856
|
-
};
|
|
3857
|
-
|
|
3858
|
-
// packages/core/mesh/network-manager/src/transport/webrtc/rtc-transport-proxy.ts
|
|
3415
|
+
// packages/core/mesh/network-manager/src/transport/simplepeer-transport-proxy.ts
|
|
3859
3416
|
import { Writable } from "@dxos/node-std/stream";
|
|
3860
|
-
import { Event as
|
|
3861
|
-
import {
|
|
3417
|
+
import { Event as Event9, scheduleTask as scheduleTask4 } from "@dxos/async";
|
|
3418
|
+
import { Context as Context6 } from "@dxos/context";
|
|
3862
3419
|
import { ErrorStream as ErrorStream5 } from "@dxos/debug";
|
|
3863
3420
|
import { invariant as invariant13 } from "@dxos/invariant";
|
|
3864
|
-
import { PublicKey as
|
|
3421
|
+
import { PublicKey as PublicKey12 } from "@dxos/keys";
|
|
3865
3422
|
import { log as log14 } from "@dxos/log";
|
|
3866
|
-
import { ConnectionResetError as
|
|
3867
|
-
import { ConnectionState as
|
|
3423
|
+
import { ConnectionResetError as ConnectionResetError3, TimeoutError as TimeoutError3, ProtocolError as ProtocolError3, ConnectivityError as ConnectivityError3, UnknownProtocolError as UnknownProtocolError3 } from "@dxos/protocols";
|
|
3424
|
+
import { ConnectionState as ConnectionState4 } from "@dxos/protocols/proto/dxos/mesh/bridge";
|
|
3868
3425
|
import { arrayToBuffer } from "@dxos/util";
|
|
3869
|
-
var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/
|
|
3426
|
+
var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/simplepeer-transport-proxy.ts";
|
|
3870
3427
|
var RPC_TIMEOUT = 1e4;
|
|
3871
|
-
var CLOSE_RPC_TIMEOUT = 3e3;
|
|
3872
3428
|
var RESP_MIN_THRESHOLD = 500;
|
|
3873
|
-
var
|
|
3429
|
+
var TIMEOUT_THRESHOLD = 10;
|
|
3430
|
+
var SimplePeerTransportProxy = class {
|
|
3874
3431
|
constructor(_options) {
|
|
3875
|
-
super();
|
|
3876
3432
|
this._options = _options;
|
|
3877
|
-
this._proxyId =
|
|
3878
|
-
this.
|
|
3879
|
-
|
|
3433
|
+
this._proxyId = PublicKey12.random();
|
|
3434
|
+
this._ctx = new Context6(void 0, {
|
|
3435
|
+
F: __dxlog_file15,
|
|
3436
|
+
L: 37
|
|
3437
|
+
});
|
|
3438
|
+
this._timeoutCount = 0;
|
|
3439
|
+
this.closed = new Event9();
|
|
3440
|
+
this.connected = new Event9();
|
|
3880
3441
|
this.errors = new ErrorStream5();
|
|
3442
|
+
this._closed = false;
|
|
3881
3443
|
}
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
this.errors.raise(error);
|
|
3896
|
-
return;
|
|
3897
|
-
}
|
|
3898
|
-
this._serviceStream = stream;
|
|
3899
|
-
stream.waitUntilReady().then(() => {
|
|
3900
|
-
stream.subscribe(async (event) => {
|
|
3901
|
-
log14("rtc transport proxy event", event, {
|
|
3444
|
+
get isOpen() {
|
|
3445
|
+
return !this._closed;
|
|
3446
|
+
}
|
|
3447
|
+
async open() {
|
|
3448
|
+
this._serviceStream = this._options.bridgeService.open({
|
|
3449
|
+
proxyId: this._proxyId,
|
|
3450
|
+
initiator: this._options.initiator
|
|
3451
|
+
}, {
|
|
3452
|
+
timeout: RPC_TIMEOUT
|
|
3453
|
+
});
|
|
3454
|
+
this._serviceStream.waitUntilReady().then(() => {
|
|
3455
|
+
this._serviceStream.subscribe(async (event) => {
|
|
3456
|
+
log14("SimplePeerTransportProxy: event", event, {
|
|
3902
3457
|
F: __dxlog_file15,
|
|
3903
3458
|
L: 66,
|
|
3904
3459
|
S: this,
|
|
@@ -3911,34 +3466,20 @@ var RtcTransportProxy = class extends Resource2 {
|
|
|
3911
3466
|
} else if (event.signal) {
|
|
3912
3467
|
await this._handleSignal(event.signal);
|
|
3913
3468
|
}
|
|
3914
|
-
}, (err) => {
|
|
3915
|
-
log14("rtc bridge stream closed", {
|
|
3916
|
-
err
|
|
3917
|
-
}, {
|
|
3918
|
-
F: __dxlog_file15,
|
|
3919
|
-
L: 76,
|
|
3920
|
-
S: this,
|
|
3921
|
-
C: (f, a) => f(...a)
|
|
3922
|
-
});
|
|
3923
|
-
if (err) {
|
|
3924
|
-
this._raiseIfOpen(err);
|
|
3925
|
-
} else {
|
|
3926
|
-
void this.close();
|
|
3927
|
-
}
|
|
3928
3469
|
});
|
|
3929
|
-
const
|
|
3470
|
+
const proxyStream = new Writable({
|
|
3930
3471
|
write: (chunk, _, callback) => {
|
|
3931
|
-
const
|
|
3472
|
+
const then = performance.now();
|
|
3932
3473
|
this._options.bridgeService.sendData({
|
|
3933
3474
|
proxyId: this._proxyId,
|
|
3934
3475
|
payload: chunk
|
|
3935
3476
|
}, {
|
|
3936
3477
|
timeout: RPC_TIMEOUT
|
|
3937
3478
|
}).then(() => {
|
|
3938
|
-
if (
|
|
3479
|
+
if (performance.now() - then > RESP_MIN_THRESHOLD) {
|
|
3939
3480
|
log14("slow response, delaying callback", void 0, {
|
|
3940
3481
|
F: __dxlog_file15,
|
|
3941
|
-
L:
|
|
3482
|
+
L: 90,
|
|
3942
3483
|
S: this,
|
|
3943
3484
|
C: (f, a) => f(...a)
|
|
3944
3485
|
});
|
|
@@ -3946,41 +3487,60 @@ var RtcTransportProxy = class extends Resource2 {
|
|
|
3946
3487
|
} else {
|
|
3947
3488
|
callback();
|
|
3948
3489
|
}
|
|
3490
|
+
this._timeoutCount = 0;
|
|
3949
3491
|
}, (err) => {
|
|
3950
|
-
|
|
3951
|
-
|
|
3492
|
+
if (err instanceof TimeoutError3 || err.constructor.name === "TimeoutError") {
|
|
3493
|
+
if (this._timeoutCount++ > TIMEOUT_THRESHOLD) {
|
|
3494
|
+
throw new TimeoutError3(`too many timeouts (${this._timeoutCount} > ${TIMEOUT_THRESHOLD}`);
|
|
3495
|
+
} else {
|
|
3496
|
+
log14("timeout error, but still invoking callback", void 0, {
|
|
3497
|
+
F: __dxlog_file15,
|
|
3498
|
+
L: 102,
|
|
3499
|
+
S: this,
|
|
3500
|
+
C: (f, a) => f(...a)
|
|
3501
|
+
});
|
|
3502
|
+
callback();
|
|
3503
|
+
}
|
|
3504
|
+
} else {
|
|
3505
|
+
log14.catch(err, void 0, {
|
|
3506
|
+
F: __dxlog_file15,
|
|
3507
|
+
L: 106,
|
|
3508
|
+
S: this,
|
|
3509
|
+
C: (f, a) => f(...a)
|
|
3510
|
+
});
|
|
3511
|
+
}
|
|
3952
3512
|
});
|
|
3953
3513
|
}
|
|
3954
3514
|
});
|
|
3955
|
-
|
|
3956
|
-
|
|
3515
|
+
proxyStream.on("error", (err) => {
|
|
3516
|
+
log14("proxystream error", {
|
|
3517
|
+
err
|
|
3518
|
+
}, {
|
|
3519
|
+
F: __dxlog_file15,
|
|
3520
|
+
L: 114,
|
|
3521
|
+
S: this,
|
|
3522
|
+
C: (f, a) => f(...a)
|
|
3523
|
+
});
|
|
3957
3524
|
});
|
|
3958
|
-
this._options.stream.pipe(
|
|
3959
|
-
}, (error) => {
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
});
|
|
3525
|
+
this._options.stream.pipe(proxyStream);
|
|
3526
|
+
}, (error) => log14.catch(error, void 0, {
|
|
3527
|
+
F: __dxlog_file15,
|
|
3528
|
+
L: 119,
|
|
3529
|
+
S: this,
|
|
3530
|
+
C: (f, a) => f(...a)
|
|
3531
|
+
}));
|
|
3966
3532
|
}
|
|
3967
|
-
async
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
} catch (err) {
|
|
3972
|
-
log14.catch(err, void 0, {
|
|
3973
|
-
F: __dxlog_file15,
|
|
3974
|
-
L: 128,
|
|
3975
|
-
S: this,
|
|
3976
|
-
C: (f, a) => f(...a)
|
|
3977
|
-
});
|
|
3533
|
+
async close() {
|
|
3534
|
+
await this._ctx.dispose();
|
|
3535
|
+
if (this._closed) {
|
|
3536
|
+
return;
|
|
3978
3537
|
}
|
|
3538
|
+
await this._serviceStream.close();
|
|
3979
3539
|
try {
|
|
3980
3540
|
await this._options.bridgeService.close({
|
|
3981
3541
|
proxyId: this._proxyId
|
|
3982
3542
|
}, {
|
|
3983
|
-
timeout:
|
|
3543
|
+
timeout: RPC_TIMEOUT
|
|
3984
3544
|
});
|
|
3985
3545
|
} catch (err) {
|
|
3986
3546
|
log14.catch(err, void 0, {
|
|
@@ -3991,6 +3551,7 @@ var RtcTransportProxy = class extends Resource2 {
|
|
|
3991
3551
|
});
|
|
3992
3552
|
}
|
|
3993
3553
|
this.closed.emit();
|
|
3554
|
+
this._closed = true;
|
|
3994
3555
|
}
|
|
3995
3556
|
async onSignal(signal) {
|
|
3996
3557
|
this._options.bridgeService.sendSignal({
|
|
@@ -3998,346 +3559,580 @@ var RtcTransportProxy = class extends Resource2 {
|
|
|
3998
3559
|
signal
|
|
3999
3560
|
}, {
|
|
4000
3561
|
timeout: RPC_TIMEOUT
|
|
4001
|
-
}).catch((err) => this.
|
|
3562
|
+
}).catch((err) => this.errors.raise(decodeError(err)));
|
|
4002
3563
|
}
|
|
4003
3564
|
async _handleConnection(connectionEvent) {
|
|
4004
3565
|
if (connectionEvent.error) {
|
|
4005
3566
|
this.errors.raise(decodeError(connectionEvent.error));
|
|
4006
|
-
return;
|
|
4007
3567
|
}
|
|
4008
3568
|
switch (connectionEvent.state) {
|
|
4009
|
-
case
|
|
3569
|
+
case ConnectionState4.CONNECTED: {
|
|
4010
3570
|
this.connected.emit();
|
|
4011
3571
|
break;
|
|
4012
3572
|
}
|
|
4013
|
-
case
|
|
3573
|
+
case ConnectionState4.CLOSED: {
|
|
4014
3574
|
await this.close();
|
|
4015
3575
|
break;
|
|
4016
3576
|
}
|
|
4017
3577
|
}
|
|
4018
3578
|
}
|
|
4019
3579
|
_handleData(dataEvent) {
|
|
4020
|
-
|
|
4021
|
-
this._options.stream.write(arrayToBuffer(dataEvent.payload));
|
|
4022
|
-
} catch (error) {
|
|
4023
|
-
this._raiseIfOpen(error);
|
|
4024
|
-
}
|
|
3580
|
+
this._options.stream.write(arrayToBuffer(dataEvent.payload));
|
|
4025
3581
|
}
|
|
4026
3582
|
async _handleSignal(signalEvent) {
|
|
4027
|
-
|
|
4028
|
-
await this._options.sendSignal(signalEvent.payload);
|
|
4029
|
-
} catch (error) {
|
|
4030
|
-
const type = signalEvent.payload.payload.data?.type;
|
|
4031
|
-
if (type === "offer" || type === "answer") {
|
|
4032
|
-
this._raiseIfOpen(new ConnectivityError4(`Session establishment failed: ${type} couldn't be sent.`));
|
|
4033
|
-
}
|
|
4034
|
-
}
|
|
3583
|
+
await this._options.sendSignal(signalEvent.payload);
|
|
4035
3584
|
}
|
|
4036
3585
|
async getDetails() {
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
});
|
|
4043
|
-
return response.details;
|
|
4044
|
-
} catch (err) {
|
|
4045
|
-
return "bridge-svc unreachable";
|
|
4046
|
-
}
|
|
3586
|
+
return (await this._options.bridgeService.getDetails({
|
|
3587
|
+
proxyId: this._proxyId
|
|
3588
|
+
}, {
|
|
3589
|
+
timeout: RPC_TIMEOUT
|
|
3590
|
+
})).details;
|
|
4047
3591
|
}
|
|
4048
3592
|
async getStats() {
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
3593
|
+
return (await this._options.bridgeService.getStats({
|
|
3594
|
+
proxyId: this._proxyId
|
|
3595
|
+
}, {
|
|
3596
|
+
timeout: RPC_TIMEOUT
|
|
3597
|
+
})).stats;
|
|
3598
|
+
}
|
|
3599
|
+
/**
|
|
3600
|
+
* Called when underlying proxy service becomes unavailable.
|
|
3601
|
+
*/
|
|
3602
|
+
// TODO(burdon): Option on close method.
|
|
3603
|
+
forceClose() {
|
|
3604
|
+
void this._serviceStream.close();
|
|
3605
|
+
this.closed.emit();
|
|
3606
|
+
this._closed = true;
|
|
3607
|
+
}
|
|
3608
|
+
};
|
|
3609
|
+
var SimplePeerTransportProxyFactory = class {
|
|
3610
|
+
constructor() {
|
|
3611
|
+
this._connections = /* @__PURE__ */ new Set();
|
|
3612
|
+
}
|
|
3613
|
+
/**
|
|
3614
|
+
* Sets the current BridgeService to be used to open connections.
|
|
3615
|
+
* Calling this method will close any existing connections.
|
|
3616
|
+
*/
|
|
3617
|
+
setBridgeService(bridgeService) {
|
|
3618
|
+
this._bridgeService = bridgeService;
|
|
3619
|
+
for (const connection of this._connections) {
|
|
3620
|
+
connection.forceClose();
|
|
3621
|
+
}
|
|
3622
|
+
return this;
|
|
3623
|
+
}
|
|
3624
|
+
createTransport(options) {
|
|
3625
|
+
invariant13(this._bridgeService, "SimplePeerTransportProxyFactory is not ready to open connections", {
|
|
3626
|
+
F: __dxlog_file15,
|
|
3627
|
+
L: 218,
|
|
3628
|
+
S: this,
|
|
3629
|
+
A: [
|
|
3630
|
+
"this._bridgeService",
|
|
3631
|
+
"'SimplePeerTransportProxyFactory is not ready to open connections'"
|
|
3632
|
+
]
|
|
3633
|
+
});
|
|
3634
|
+
const transport = new SimplePeerTransportProxy({
|
|
3635
|
+
...options,
|
|
3636
|
+
bridgeService: this._bridgeService
|
|
3637
|
+
});
|
|
3638
|
+
this._connections.add(transport);
|
|
3639
|
+
transport.closed.on(() => this._connections.delete(transport));
|
|
3640
|
+
return transport;
|
|
3641
|
+
}
|
|
3642
|
+
};
|
|
3643
|
+
var decodeError = (err) => {
|
|
3644
|
+
const message = typeof err === "string" ? err : err.message;
|
|
3645
|
+
if (message.includes("CONNECTION_RESET")) {
|
|
3646
|
+
return new ConnectionResetError3(message);
|
|
3647
|
+
} else if (message.includes("TIMEOUT")) {
|
|
3648
|
+
return new TimeoutError3(message);
|
|
3649
|
+
} else if (message.includes("PROTOCOL_ERROR")) {
|
|
3650
|
+
return new ProtocolError3(message);
|
|
3651
|
+
} else if (message.includes("CONNECTIVITY_ERROR")) {
|
|
3652
|
+
return new ConnectivityError3(message);
|
|
3653
|
+
} else if (message.includes("UNKNOWN_PROTOCOL_ERROR")) {
|
|
3654
|
+
return new UnknownProtocolError3(message);
|
|
3655
|
+
} else {
|
|
3656
|
+
return typeof err === "string" ? new Error(err) : err;
|
|
3657
|
+
}
|
|
3658
|
+
};
|
|
3659
|
+
|
|
3660
|
+
// packages/core/mesh/network-manager/src/transport/libdatachannel-transport.ts
|
|
3661
|
+
import { Duplex as Duplex2 } from "stream";
|
|
3662
|
+
import { Event as Event10, Trigger as Trigger3, synchronized as synchronized6 } from "@dxos/async";
|
|
3663
|
+
import { ErrorStream as ErrorStream6 } from "@dxos/debug";
|
|
3664
|
+
import { invariant as invariant14 } from "@dxos/invariant";
|
|
3665
|
+
import { log as log15 } from "@dxos/log";
|
|
3666
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
3667
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3668
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3669
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
3670
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3671
|
+
}
|
|
3672
|
+
var __dxlog_file16 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/libdatachannel-transport.ts";
|
|
3673
|
+
var DATACHANNEL_LABEL = "dxos.mesh.transport";
|
|
3674
|
+
var MAX_BUFFERED_AMOUNT = 64 * 1024;
|
|
3675
|
+
var MAX_MESSAGE_SIZE = 64 * 1024;
|
|
3676
|
+
var createLibDataChannelTransportFactory = (webrtcConfig, iceProvider) => {
|
|
3677
|
+
return {
|
|
3678
|
+
createTransport: (options) => new LibDataChannelTransport({
|
|
3679
|
+
...options,
|
|
3680
|
+
webrtcConfig,
|
|
3681
|
+
iceProvider
|
|
3682
|
+
})
|
|
3683
|
+
};
|
|
3684
|
+
};
|
|
3685
|
+
var LibDataChannelTransport = class _LibDataChannelTransport {
|
|
3686
|
+
static {
|
|
3687
|
+
this._instanceCount = 0;
|
|
3688
|
+
}
|
|
3689
|
+
constructor(_options) {
|
|
3690
|
+
this._options = _options;
|
|
3691
|
+
this._closed = false;
|
|
3692
|
+
this._connected = false;
|
|
3693
|
+
this._writeCallback = null;
|
|
3694
|
+
this._readyForCandidates = new Trigger3();
|
|
3695
|
+
this.closed = new Event10();
|
|
3696
|
+
this.connected = new Event10();
|
|
3697
|
+
this.errors = new ErrorStream6();
|
|
3698
|
+
}
|
|
3699
|
+
get isOpen() {
|
|
3700
|
+
return !!this._peer && !this._closed;
|
|
3701
|
+
}
|
|
3702
|
+
async open() {
|
|
3703
|
+
if (this._closed) {
|
|
3704
|
+
this.errors.raise(new Error("connection already closed"));
|
|
3705
|
+
}
|
|
3706
|
+
const { RTCPeerConnection } = (await importESM("node-datachannel/polyfill")).default;
|
|
3707
|
+
const providedIceServers = await this._options.iceProvider?.getIceServers();
|
|
3708
|
+
if (!this._options.webrtcConfig) {
|
|
3709
|
+
this._options.webrtcConfig = {};
|
|
3710
|
+
}
|
|
3711
|
+
this._options.webrtcConfig.iceServers = [
|
|
3712
|
+
...this._options.webrtcConfig.iceServers ?? [],
|
|
3713
|
+
...providedIceServers ?? []
|
|
3714
|
+
];
|
|
3715
|
+
this._peer = new RTCPeerConnection(this._options.webrtcConfig);
|
|
3716
|
+
this._peer.onicecandidateerror = (event) => {
|
|
3717
|
+
log15.error("peer.onicecandidateerror", {
|
|
3718
|
+
event
|
|
4052
3719
|
}, {
|
|
4053
|
-
|
|
3720
|
+
F: __dxlog_file16,
|
|
3721
|
+
L: 93,
|
|
3722
|
+
S: this,
|
|
3723
|
+
C: (f, a) => f(...a)
|
|
3724
|
+
});
|
|
3725
|
+
};
|
|
3726
|
+
this._peer.onconnectionstatechange = (event) => {
|
|
3727
|
+
log15.debug("peer.onconnectionstatechange", {
|
|
3728
|
+
event,
|
|
3729
|
+
peerConnectionState: this._peer?.connectionState,
|
|
3730
|
+
transportConnectionState: this._connected
|
|
3731
|
+
}, {
|
|
3732
|
+
F: __dxlog_file16,
|
|
3733
|
+
L: 97,
|
|
3734
|
+
S: this,
|
|
3735
|
+
C: (f, a) => f(...a)
|
|
3736
|
+
});
|
|
3737
|
+
};
|
|
3738
|
+
this._peer.onicecandidate = async (event) => {
|
|
3739
|
+
log15.debug("peer.onicecandidate", {
|
|
3740
|
+
event
|
|
3741
|
+
}, {
|
|
3742
|
+
F: __dxlog_file16,
|
|
3743
|
+
L: 107,
|
|
3744
|
+
S: this,
|
|
3745
|
+
C: (f, a) => f(...a)
|
|
3746
|
+
});
|
|
3747
|
+
if (event.candidate) {
|
|
3748
|
+
try {
|
|
3749
|
+
await this._options.sendSignal({
|
|
3750
|
+
payload: {
|
|
3751
|
+
data: {
|
|
3752
|
+
type: "candidate",
|
|
3753
|
+
candidate: {
|
|
3754
|
+
candidate: event.candidate.candidate,
|
|
3755
|
+
// These fields never seem to be not null, but connecting to Chrome doesn't work if they are.
|
|
3756
|
+
sdpMLineIndex: event.candidate.sdpMLineIndex ?? 0,
|
|
3757
|
+
sdpMid: event.candidate.sdpMid ?? 0
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
});
|
|
3762
|
+
} catch (err) {
|
|
3763
|
+
log15.info("signaling error", {
|
|
3764
|
+
err
|
|
3765
|
+
}, {
|
|
3766
|
+
F: __dxlog_file16,
|
|
3767
|
+
L: 124,
|
|
3768
|
+
S: this,
|
|
3769
|
+
C: (f, a) => f(...a)
|
|
3770
|
+
});
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3773
|
+
};
|
|
3774
|
+
if (this._options.initiator) {
|
|
3775
|
+
invariant14(this._peer, "not open", {
|
|
3776
|
+
F: __dxlog_file16,
|
|
3777
|
+
L: 130,
|
|
3778
|
+
S: this,
|
|
3779
|
+
A: [
|
|
3780
|
+
"this._peer",
|
|
3781
|
+
"'not open'"
|
|
3782
|
+
]
|
|
3783
|
+
});
|
|
3784
|
+
this._peer.createOffer().then(async (offer) => {
|
|
3785
|
+
if (this._closed) {
|
|
3786
|
+
return;
|
|
3787
|
+
}
|
|
3788
|
+
if (this._peer?.connectionState !== "connecting") {
|
|
3789
|
+
log15.error("peer not connecting", {
|
|
3790
|
+
peer: this._peer
|
|
3791
|
+
}, {
|
|
3792
|
+
F: __dxlog_file16,
|
|
3793
|
+
L: 141,
|
|
3794
|
+
S: this,
|
|
3795
|
+
C: (f, a) => f(...a)
|
|
3796
|
+
});
|
|
3797
|
+
this.errors.raise(new Error("invalid state: peer is initiator, but other peer not in state connecting"));
|
|
3798
|
+
}
|
|
3799
|
+
log15.debug("creating offer", {
|
|
3800
|
+
peer: this._peer,
|
|
3801
|
+
offer
|
|
3802
|
+
}, {
|
|
3803
|
+
F: __dxlog_file16,
|
|
3804
|
+
L: 145,
|
|
3805
|
+
S: this,
|
|
3806
|
+
C: (f, a) => f(...a)
|
|
3807
|
+
});
|
|
3808
|
+
await this._peer.setLocalDescription(offer);
|
|
3809
|
+
await this._options.sendSignal({
|
|
3810
|
+
payload: {
|
|
3811
|
+
data: {
|
|
3812
|
+
type: offer.type,
|
|
3813
|
+
sdp: offer.sdp
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
});
|
|
3817
|
+
}).catch((err) => {
|
|
3818
|
+
this.errors.raise(err);
|
|
3819
|
+
});
|
|
3820
|
+
this._handleChannel(this._peer.createDataChannel(DATACHANNEL_LABEL));
|
|
3821
|
+
log15.debug("created data channel", void 0, {
|
|
3822
|
+
F: __dxlog_file16,
|
|
3823
|
+
L: 155,
|
|
3824
|
+
S: this,
|
|
3825
|
+
C: (f, a) => f(...a)
|
|
4054
3826
|
});
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
3827
|
+
this._peer.ondatachannel = () => {
|
|
3828
|
+
this.errors.raise(new Error("unexpected ondatachannel event for initiator"));
|
|
3829
|
+
};
|
|
3830
|
+
} else {
|
|
3831
|
+
this._peer.ondatachannel = (event) => {
|
|
3832
|
+
log15.debug("peer.ondatachannel (non-initiator)", {
|
|
3833
|
+
event
|
|
3834
|
+
}, {
|
|
3835
|
+
F: __dxlog_file16,
|
|
3836
|
+
L: 161,
|
|
3837
|
+
S: this,
|
|
3838
|
+
C: (f, a) => f(...a)
|
|
3839
|
+
});
|
|
3840
|
+
if (event.channel.label !== DATACHANNEL_LABEL) {
|
|
3841
|
+
this.errors.raise(new Error(`unexpected channel label ${event.channel.label}`));
|
|
3842
|
+
}
|
|
3843
|
+
this._handleChannel(event.channel);
|
|
4063
3844
|
};
|
|
4064
3845
|
}
|
|
3846
|
+
_LibDataChannelTransport._instanceCount++;
|
|
4065
3847
|
}
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
log14.info("error swallowed because transport was closed", {
|
|
4071
|
-
message: error.message
|
|
4072
|
-
}, {
|
|
4073
|
-
F: __dxlog_file15,
|
|
4074
|
-
L: 215,
|
|
4075
|
-
S: this,
|
|
4076
|
-
C: (f, a) => f(...a)
|
|
4077
|
-
});
|
|
3848
|
+
async close() {
|
|
3849
|
+
await this._close();
|
|
3850
|
+
if (--_LibDataChannelTransport._instanceCount === 0) {
|
|
3851
|
+
(await importESM("node-datachannel")).cleanup();
|
|
4078
3852
|
}
|
|
4079
3853
|
}
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
3854
|
+
async _close() {
|
|
3855
|
+
if (this._closed) {
|
|
3856
|
+
return;
|
|
3857
|
+
}
|
|
3858
|
+
await this._disconnectStreams();
|
|
3859
|
+
try {
|
|
3860
|
+
this._peer?.close();
|
|
3861
|
+
} catch (err) {
|
|
3862
|
+
this.errors.raise(err);
|
|
3863
|
+
}
|
|
3864
|
+
this._peer = void 0;
|
|
3865
|
+
this._closed = true;
|
|
4085
3866
|
this.closed.emit();
|
|
4086
3867
|
}
|
|
4087
|
-
};
|
|
4088
|
-
var RtcTransportProxyFactory = class {
|
|
4089
|
-
constructor() {
|
|
4090
|
-
this._connections = /* @__PURE__ */ new Set();
|
|
4091
|
-
}
|
|
4092
3868
|
/**
|
|
4093
|
-
*
|
|
4094
|
-
* Calling this method will close any existing connections.
|
|
3869
|
+
* Handle data channel events.
|
|
4095
3870
|
*/
|
|
4096
|
-
|
|
4097
|
-
this.
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
}
|
|
4101
|
-
return this;
|
|
4102
|
-
}
|
|
4103
|
-
createTransport(options) {
|
|
4104
|
-
invariant13(this._bridgeService, "RtcTransportProxyFactory is not ready to open connections", {
|
|
4105
|
-
F: __dxlog_file15,
|
|
4106
|
-
L: 245,
|
|
4107
|
-
S: this,
|
|
4108
|
-
A: [
|
|
4109
|
-
"this._bridgeService",
|
|
4110
|
-
"'RtcTransportProxyFactory is not ready to open connections'"
|
|
4111
|
-
]
|
|
4112
|
-
});
|
|
4113
|
-
const transport = new RtcTransportProxy({
|
|
4114
|
-
...options,
|
|
4115
|
-
bridgeService: this._bridgeService
|
|
4116
|
-
});
|
|
4117
|
-
this._connections.add(transport);
|
|
4118
|
-
transport.closed.on(() => this._connections.delete(transport));
|
|
4119
|
-
return transport;
|
|
4120
|
-
}
|
|
4121
|
-
};
|
|
4122
|
-
var decodeError = (err) => {
|
|
4123
|
-
const message = typeof err === "string" ? err : err.message;
|
|
4124
|
-
if (message.includes("CONNECTION_RESET")) {
|
|
4125
|
-
return new ConnectionResetError2(message);
|
|
4126
|
-
} else if (message.includes("TIMEOUT")) {
|
|
4127
|
-
return new TimeoutError3(message);
|
|
4128
|
-
} else if (message.includes("CONNECTIVITY_ERROR")) {
|
|
4129
|
-
return new ConnectivityError4(message);
|
|
4130
|
-
} else {
|
|
4131
|
-
return typeof err === "string" ? new Error(err) : err;
|
|
4132
|
-
}
|
|
4133
|
-
};
|
|
4134
|
-
|
|
4135
|
-
// packages/core/mesh/network-manager/src/transport/webrtc/rtc-transport-service.ts
|
|
4136
|
-
import { Duplex as Duplex2 } from "@dxos/node-std/stream";
|
|
4137
|
-
import { Stream } from "@dxos/codec-protobuf";
|
|
4138
|
-
import { invariant as invariant14 } from "@dxos/invariant";
|
|
4139
|
-
import { PublicKey as PublicKey11 } from "@dxos/keys";
|
|
4140
|
-
import { log as log15 } from "@dxos/log";
|
|
4141
|
-
import { ConnectionState as ConnectionState4 } from "@dxos/protocols/proto/dxos/mesh/bridge";
|
|
4142
|
-
import { ComplexMap as ComplexMap8 } from "@dxos/util";
|
|
4143
|
-
var __dxlog_file16 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/webrtc/rtc-transport-service.ts";
|
|
4144
|
-
var RtcTransportService = class {
|
|
4145
|
-
constructor(webrtcConfig, iceProvider, _transportFactory = createRtcTransportFactory(webrtcConfig, iceProvider)) {
|
|
4146
|
-
this._transportFactory = _transportFactory;
|
|
4147
|
-
this._openTransports = new ComplexMap8(PublicKey11.hash);
|
|
4148
|
-
}
|
|
4149
|
-
hasOpenTransports() {
|
|
4150
|
-
return this._openTransports.size > 0;
|
|
4151
|
-
}
|
|
4152
|
-
open(request) {
|
|
4153
|
-
const existingTransport = this._openTransports.get(request.proxyId);
|
|
4154
|
-
if (existingTransport) {
|
|
4155
|
-
log15.error("requesting a new transport bridge for an existing proxy", void 0, {
|
|
3871
|
+
_handleChannel(dataChannel) {
|
|
3872
|
+
this._channel = dataChannel;
|
|
3873
|
+
this._channel.onopen = () => {
|
|
3874
|
+
log15.debug("channel.onopen", void 0, {
|
|
4156
3875
|
F: __dxlog_file16,
|
|
4157
|
-
L:
|
|
3876
|
+
L: 206,
|
|
4158
3877
|
S: this,
|
|
4159
3878
|
C: (f, a) => f(...a)
|
|
4160
3879
|
});
|
|
4161
|
-
|
|
4162
|
-
this._openTransports.delete(request.proxyId);
|
|
4163
|
-
}
|
|
4164
|
-
return new Stream(({ ready, next, close }) => {
|
|
4165
|
-
const pushNewState = createStateUpdater(next);
|
|
4166
|
-
const transportStream = new Duplex2({
|
|
3880
|
+
const duplex = new Duplex2({
|
|
4167
3881
|
read: () => {
|
|
4168
|
-
const callbacks = [
|
|
4169
|
-
...transportState.writeProcessedCallbacks
|
|
4170
|
-
];
|
|
4171
|
-
transportState.writeProcessedCallbacks.length = 0;
|
|
4172
|
-
callbacks.forEach((cb) => cb());
|
|
4173
3882
|
},
|
|
4174
|
-
write:
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
payload: signal
|
|
3883
|
+
write: async (chunk, encoding, callback) => {
|
|
3884
|
+
if (chunk.length > MAX_MESSAGE_SIZE) {
|
|
3885
|
+
this.errors.raise(new Error(`message too large: ${chunk.length} > ${MAX_MESSAGE_SIZE}`));
|
|
3886
|
+
}
|
|
3887
|
+
try {
|
|
3888
|
+
dataChannel.send(chunk);
|
|
3889
|
+
} catch (err) {
|
|
3890
|
+
this.errors.raise(err);
|
|
3891
|
+
await this._close();
|
|
3892
|
+
}
|
|
3893
|
+
if (this._channel.bufferedAmount > MAX_BUFFERED_AMOUNT) {
|
|
3894
|
+
if (this._writeCallback !== null) {
|
|
3895
|
+
log15.error("consumer trying to write before we are ready for more data", void 0, {
|
|
3896
|
+
F: __dxlog_file16,
|
|
3897
|
+
L: 223,
|
|
3898
|
+
S: this,
|
|
3899
|
+
C: (f, a) => f(...a)
|
|
3900
|
+
});
|
|
4193
3901
|
}
|
|
4194
|
-
|
|
3902
|
+
this._writeCallback = callback;
|
|
3903
|
+
} else {
|
|
3904
|
+
callback();
|
|
3905
|
+
}
|
|
4195
3906
|
}
|
|
4196
3907
|
});
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
transport.closed.on(async () => {
|
|
4211
|
-
pushNewState(ConnectionState4.CLOSED);
|
|
4212
|
-
void this._safeCloseTransport(transportState);
|
|
4213
|
-
close();
|
|
4214
|
-
});
|
|
4215
|
-
this._openTransports.set(request.proxyId, transportState);
|
|
4216
|
-
transport.open().catch(async (err) => {
|
|
4217
|
-
pushNewState(ConnectionState4.CLOSED, err);
|
|
4218
|
-
void this._safeCloseTransport(transportState);
|
|
4219
|
-
close(err);
|
|
3908
|
+
duplex.pipe(this._options.stream).pipe(duplex);
|
|
3909
|
+
this._stream = duplex;
|
|
3910
|
+
this._connected = true;
|
|
3911
|
+
this.connected.emit();
|
|
3912
|
+
};
|
|
3913
|
+
this._channel.onclose = async (err) => {
|
|
3914
|
+
log15.info("channel.onclose", {
|
|
3915
|
+
err
|
|
3916
|
+
}, {
|
|
3917
|
+
F: __dxlog_file16,
|
|
3918
|
+
L: 239,
|
|
3919
|
+
S: this,
|
|
3920
|
+
C: (f, a) => f(...a)
|
|
4220
3921
|
});
|
|
4221
|
-
|
|
4222
|
-
}
|
|
3922
|
+
await this._close();
|
|
3923
|
+
};
|
|
3924
|
+
this._channel.onerror = async (err) => {
|
|
3925
|
+
this.errors.raise(new Error("channel error: " + err.toString()));
|
|
3926
|
+
await this._close();
|
|
3927
|
+
};
|
|
3928
|
+
this._channel.onbufferedamountlow = () => {
|
|
3929
|
+
const cb = this._writeCallback;
|
|
3930
|
+
this._writeCallback = null;
|
|
3931
|
+
cb?.();
|
|
3932
|
+
};
|
|
3933
|
+
this._channel.onmessage = (event) => {
|
|
3934
|
+
let data = event.data;
|
|
3935
|
+
if (data instanceof ArrayBuffer) {
|
|
3936
|
+
data = Buffer2.from(data);
|
|
3937
|
+
}
|
|
3938
|
+
this._stream.push(data);
|
|
3939
|
+
};
|
|
4223
3940
|
}
|
|
4224
|
-
async
|
|
4225
|
-
|
|
4226
|
-
invariant14(transport, void 0, {
|
|
3941
|
+
async onSignal(signal) {
|
|
3942
|
+
invariant14(this._peer, "not open", {
|
|
4227
3943
|
F: __dxlog_file16,
|
|
4228
|
-
L:
|
|
3944
|
+
L: 265,
|
|
4229
3945
|
S: this,
|
|
4230
3946
|
A: [
|
|
4231
|
-
"
|
|
4232
|
-
""
|
|
3947
|
+
"this._peer",
|
|
3948
|
+
"'not open'"
|
|
4233
3949
|
]
|
|
4234
3950
|
});
|
|
4235
|
-
|
|
3951
|
+
try {
|
|
3952
|
+
const data = signal.payload.data;
|
|
3953
|
+
switch (data.type) {
|
|
3954
|
+
case "offer": {
|
|
3955
|
+
if (this._peer.connectionState !== "new") {
|
|
3956
|
+
log15.error("received offer but peer not in state new", {
|
|
3957
|
+
peer: this._peer
|
|
3958
|
+
}, {
|
|
3959
|
+
F: __dxlog_file16,
|
|
3960
|
+
L: 272,
|
|
3961
|
+
S: this,
|
|
3962
|
+
C: (f, a) => f(...a)
|
|
3963
|
+
});
|
|
3964
|
+
this.errors.raise(new Error("invalid signalling state: received offer when peer is not in state new"));
|
|
3965
|
+
break;
|
|
3966
|
+
}
|
|
3967
|
+
try {
|
|
3968
|
+
await this._peer.setRemoteDescription({
|
|
3969
|
+
type: data.type,
|
|
3970
|
+
sdp: data.sdp
|
|
3971
|
+
});
|
|
3972
|
+
const answer = await this._peer.createAnswer();
|
|
3973
|
+
await this._peer.setLocalDescription(answer);
|
|
3974
|
+
await this._options.sendSignal({
|
|
3975
|
+
payload: {
|
|
3976
|
+
data: {
|
|
3977
|
+
type: answer.type,
|
|
3978
|
+
sdp: answer.sdp
|
|
3979
|
+
}
|
|
3980
|
+
}
|
|
3981
|
+
});
|
|
3982
|
+
this._readyForCandidates.wake();
|
|
3983
|
+
} catch (err) {
|
|
3984
|
+
log15.error("cannot handle offer from signalling server", {
|
|
3985
|
+
err
|
|
3986
|
+
}, {
|
|
3987
|
+
F: __dxlog_file16,
|
|
3988
|
+
L: 284,
|
|
3989
|
+
S: this,
|
|
3990
|
+
C: (f, a) => f(...a)
|
|
3991
|
+
});
|
|
3992
|
+
this.errors.raise(new Error("error handling offer"));
|
|
3993
|
+
}
|
|
3994
|
+
break;
|
|
3995
|
+
}
|
|
3996
|
+
case "answer":
|
|
3997
|
+
try {
|
|
3998
|
+
await this._peer.setRemoteDescription({
|
|
3999
|
+
type: data.type,
|
|
4000
|
+
sdp: data.sdp
|
|
4001
|
+
});
|
|
4002
|
+
this._readyForCandidates.wake();
|
|
4003
|
+
} catch (err) {
|
|
4004
|
+
log15.error("cannot handle answer from signalling server", {
|
|
4005
|
+
err
|
|
4006
|
+
}, {
|
|
4007
|
+
F: __dxlog_file16,
|
|
4008
|
+
L: 295,
|
|
4009
|
+
S: this,
|
|
4010
|
+
C: (f, a) => f(...a)
|
|
4011
|
+
});
|
|
4012
|
+
this.errors.raise(new Error("error handling answer"));
|
|
4013
|
+
}
|
|
4014
|
+
break;
|
|
4015
|
+
case "candidate":
|
|
4016
|
+
await this._readyForCandidates.wait();
|
|
4017
|
+
await this._peer.addIceCandidate({
|
|
4018
|
+
candidate: data.candidate.candidate
|
|
4019
|
+
});
|
|
4020
|
+
break;
|
|
4021
|
+
default:
|
|
4022
|
+
log15.error("unhandled signal type", {
|
|
4023
|
+
type: data.type,
|
|
4024
|
+
signal
|
|
4025
|
+
}, {
|
|
4026
|
+
F: __dxlog_file16,
|
|
4027
|
+
L: 306,
|
|
4028
|
+
S: this,
|
|
4029
|
+
C: (f, a) => f(...a)
|
|
4030
|
+
});
|
|
4031
|
+
this.errors.raise(new Error(`unhandled signal type ${data.type}`));
|
|
4032
|
+
}
|
|
4033
|
+
} catch (err) {
|
|
4034
|
+
log15.catch(err, void 0, {
|
|
4035
|
+
F: __dxlog_file16,
|
|
4036
|
+
L: 310,
|
|
4037
|
+
S: this,
|
|
4038
|
+
C: (f, a) => f(...a)
|
|
4039
|
+
});
|
|
4040
|
+
}
|
|
4236
4041
|
}
|
|
4237
|
-
async getDetails(
|
|
4238
|
-
const
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4042
|
+
async getDetails() {
|
|
4043
|
+
const stats = await this._getStats();
|
|
4044
|
+
const rc = stats?.remoteCandidate;
|
|
4045
|
+
if (!rc) {
|
|
4046
|
+
return "unavailable";
|
|
4047
|
+
}
|
|
4048
|
+
if (rc.candidateType === "relay") {
|
|
4049
|
+
return `${rc.ip}:${rc.port} relay for ${rc.relatedAddress}:${rc.relatedPort}`;
|
|
4050
|
+
}
|
|
4051
|
+
return `${rc.ip}:${rc.port} ${rc.candidateType}`;
|
|
4052
|
+
}
|
|
4053
|
+
async getStats() {
|
|
4054
|
+
const stats = await this._getStats();
|
|
4055
|
+
if (!stats) {
|
|
4056
|
+
return {
|
|
4057
|
+
bytesSent: 0,
|
|
4058
|
+
bytesReceived: 0,
|
|
4059
|
+
packetsSent: 0,
|
|
4060
|
+
packetsReceived: 0,
|
|
4061
|
+
rawStats: {}
|
|
4062
|
+
};
|
|
4063
|
+
}
|
|
4248
4064
|
return {
|
|
4249
|
-
|
|
4065
|
+
bytesSent: stats.transport.bytesSent,
|
|
4066
|
+
bytesReceived: stats.transport.bytesReceived,
|
|
4067
|
+
packetsSent: 0,
|
|
4068
|
+
packetsReceived: 0,
|
|
4069
|
+
rawStats: stats.raw
|
|
4250
4070
|
};
|
|
4251
4071
|
}
|
|
4252
|
-
async
|
|
4253
|
-
|
|
4254
|
-
invariant14(transport, void 0, {
|
|
4072
|
+
async _getStats() {
|
|
4073
|
+
invariant14(this._peer, "not open", {
|
|
4255
4074
|
F: __dxlog_file16,
|
|
4256
|
-
L:
|
|
4075
|
+
L: 350,
|
|
4257
4076
|
S: this,
|
|
4258
4077
|
A: [
|
|
4259
|
-
"
|
|
4260
|
-
""
|
|
4078
|
+
"this._peer",
|
|
4079
|
+
"'not open'"
|
|
4261
4080
|
]
|
|
4262
4081
|
});
|
|
4082
|
+
const stats = await this._peer.getStats();
|
|
4083
|
+
const statsEntries = Array.from(stats.entries());
|
|
4084
|
+
const transport = statsEntries.filter((s) => s[1].type === "transport")[0][1];
|
|
4085
|
+
const candidatePair = statsEntries.filter((s) => s[0] === transport.selectedCandidatePairId);
|
|
4086
|
+
let selectedCandidatePair;
|
|
4087
|
+
let remoteCandidate;
|
|
4088
|
+
if (candidatePair.length > 0) {
|
|
4089
|
+
selectedCandidatePair = candidatePair[0][1];
|
|
4090
|
+
remoteCandidate = statsEntries.filter((s) => s[0] === selectedCandidatePair.remoteCandidateId)[0][1];
|
|
4091
|
+
}
|
|
4263
4092
|
return {
|
|
4264
|
-
|
|
4093
|
+
transport,
|
|
4094
|
+
selectedCandidatePair,
|
|
4095
|
+
remoteCandidate,
|
|
4096
|
+
raw: Object.fromEntries(stats)
|
|
4265
4097
|
};
|
|
4266
4098
|
}
|
|
4267
|
-
async
|
|
4268
|
-
|
|
4269
|
-
invariant14(transport, void 0, {
|
|
4270
|
-
F: __dxlog_file16,
|
|
4271
|
-
L: 142,
|
|
4272
|
-
S: this,
|
|
4273
|
-
A: [
|
|
4274
|
-
"transport",
|
|
4275
|
-
""
|
|
4276
|
-
]
|
|
4277
|
-
});
|
|
4278
|
-
const bufferHasSpace = transport.connectorStream.push(payload);
|
|
4279
|
-
if (!bufferHasSpace) {
|
|
4280
|
-
await new Promise((resolve) => {
|
|
4281
|
-
transport.writeProcessedCallbacks.push(resolve);
|
|
4282
|
-
});
|
|
4283
|
-
}
|
|
4099
|
+
async _disconnectStreams() {
|
|
4100
|
+
this._options.stream.unpipe?.(this._stream)?.unpipe?.(this._options.stream);
|
|
4284
4101
|
}
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4102
|
+
};
|
|
4103
|
+
_ts_decorate7([
|
|
4104
|
+
synchronized6
|
|
4105
|
+
], LibDataChannelTransport.prototype, "_close", null);
|
|
4106
|
+
var importESM = Function("path", "return import(path)");
|
|
4107
|
+
|
|
4108
|
+
// packages/core/mesh/network-manager/src/transport/tcp-transport.browser.ts
|
|
4109
|
+
import { Event as Event11 } from "@dxos/async";
|
|
4110
|
+
import { ErrorStream as ErrorStream7 } from "@dxos/debug";
|
|
4111
|
+
var TcpTransportFactory = {
|
|
4112
|
+
createTransport: () => new TcpTransport()
|
|
4113
|
+
};
|
|
4114
|
+
var TcpTransport = class {
|
|
4115
|
+
constructor() {
|
|
4116
|
+
this.closed = new Event11();
|
|
4117
|
+
this.connected = new Event11();
|
|
4118
|
+
this.errors = new ErrorStream7();
|
|
4292
4119
|
}
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
});
|
|
4309
|
-
}
|
|
4310
|
-
try {
|
|
4311
|
-
transport.connectorStream.end();
|
|
4312
|
-
} catch (error) {
|
|
4313
|
-
log15.warn("connectorStream close error", {
|
|
4314
|
-
message: error?.message
|
|
4315
|
-
}, {
|
|
4316
|
-
F: __dxlog_file16,
|
|
4317
|
-
L: 177,
|
|
4318
|
-
S: this,
|
|
4319
|
-
C: (f, a) => f(...a)
|
|
4320
|
-
});
|
|
4321
|
-
}
|
|
4322
|
-
log15("closed", void 0, {
|
|
4323
|
-
F: __dxlog_file16,
|
|
4324
|
-
L: 179,
|
|
4325
|
-
S: this,
|
|
4326
|
-
C: (f, a) => f(...a)
|
|
4327
|
-
});
|
|
4120
|
+
get isOpen() {
|
|
4121
|
+
return true;
|
|
4122
|
+
}
|
|
4123
|
+
async open() {
|
|
4124
|
+
}
|
|
4125
|
+
async close() {
|
|
4126
|
+
}
|
|
4127
|
+
async onSignal() {
|
|
4128
|
+
throw new Error("Method not implemented.");
|
|
4129
|
+
}
|
|
4130
|
+
async getStats() {
|
|
4131
|
+
throw new Error("Method not implemented.");
|
|
4132
|
+
}
|
|
4133
|
+
async getDetails() {
|
|
4134
|
+
throw new Error("Method not implemented.");
|
|
4328
4135
|
}
|
|
4329
|
-
};
|
|
4330
|
-
var createStateUpdater = (next) => {
|
|
4331
|
-
return (state, err) => {
|
|
4332
|
-
next({
|
|
4333
|
-
connection: {
|
|
4334
|
-
state,
|
|
4335
|
-
...err ? {
|
|
4336
|
-
error: err.message
|
|
4337
|
-
} : void 0
|
|
4338
|
-
}
|
|
4339
|
-
});
|
|
4340
|
-
};
|
|
4341
4136
|
};
|
|
4342
4137
|
|
|
4343
4138
|
// packages/core/mesh/network-manager/src/wire-protocol.ts
|
|
@@ -4365,6 +4160,7 @@ var createTeleportProtocolFactory = (onConnection, defaultParams) => {
|
|
|
4365
4160
|
};
|
|
4366
4161
|
|
|
4367
4162
|
export {
|
|
4163
|
+
process,
|
|
4368
4164
|
ConnectionState,
|
|
4369
4165
|
Connection,
|
|
4370
4166
|
createIceProvider,
|
|
@@ -4382,10 +4178,15 @@ export {
|
|
|
4382
4178
|
MemoryTransportFactory,
|
|
4383
4179
|
MemoryTransport,
|
|
4384
4180
|
TransportKind,
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4181
|
+
createSimplePeerTransportFactory,
|
|
4182
|
+
SimplePeerTransport,
|
|
4183
|
+
SimplePeerTransportService,
|
|
4184
|
+
SimplePeerTransportProxy,
|
|
4185
|
+
SimplePeerTransportProxyFactory,
|
|
4186
|
+
createLibDataChannelTransportFactory,
|
|
4187
|
+
LibDataChannelTransport,
|
|
4188
|
+
TcpTransportFactory,
|
|
4189
|
+
TcpTransport,
|
|
4389
4190
|
createTeleportProtocolFactory
|
|
4390
4191
|
};
|
|
4391
|
-
//# sourceMappingURL=chunk-
|
|
4192
|
+
//# sourceMappingURL=chunk-XYSYUN63.mjs.map
|