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