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