@dxos/network-manager 0.6.12 → 0.6.13-main.09887cd
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-XYSYUN63.mjs → chunk-MKIVP7G3.mjs} +1249 -1065
- package/dist/lib/browser/chunk-MKIVP7G3.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 +22 -32
- 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-4YAYC7WN.cjs → chunk-D6P7ACEM.cjs} +1262 -1205
- package/dist/lib/node/chunk-D6P7ACEM.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 +24 -34
- 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-22DA2US6.mjs +4373 -0
- package/dist/lib/node-esm/chunk-22DA2US6.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +50 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/testing/index.mjs +279 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- 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/network-manager.d.ts +2 -1
- package/dist/types/src/network-manager.d.ts.map +1 -1
- package/dist/types/src/signal/ice.d.ts.map +1 -1
- package/dist/types/src/signal/integration.node.test.d.ts +2 -0
- package/dist/types/src/signal/integration.node.test.d.ts.map +1 -0
- package/dist/types/src/signal/swarm-messenger.node.test.d.ts +2 -0
- package/dist/types/src/signal/swarm-messenger.node.test.d.ts.map +1 -0
- package/dist/types/src/swarm/connection.d.ts.map +1 -1
- package/dist/types/src/swarm/swarm.d.ts +1 -1
- package/dist/types/src/testing/test-builder.d.ts +2 -2
- package/dist/types/src/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/testing/test-wire-protocol.d.ts +1 -2
- package/dist/types/src/testing/test-wire-protocol.d.ts.map +1 -1
- package/dist/types/src/tests/basic-test-suite.d.ts.map +1 -1
- package/dist/types/src/tests/property-test-suite.d.ts.map +1 -1
- package/dist/types/src/tests/tcp-transport.node.test.d.ts +2 -0
- package/dist/types/src/tests/tcp-transport.node.test.d.ts.map +1 -0
- package/dist/types/src/tests/utils.d.ts.map +1 -1
- package/dist/types/src/transport/index.d.ts +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 +55 -30
- package/src/network-manager.ts +5 -13
- package/src/signal/ice.test.ts +1 -3
- package/src/signal/ice.ts +6 -1
- package/src/signal/{integration.test.ts → integration.node.test.ts} +9 -15
- package/src/signal/{swarm-messenger.test.ts → swarm-messenger.node.test.ts} +13 -23
- package/src/swarm/connection-limiter.test.ts +3 -6
- package/src/swarm/connection.test.ts +63 -38
- package/src/swarm/connection.ts +5 -5
- package/src/swarm/swarm.test.ts +10 -12
- package/src/swarm/swarm.ts +1 -1
- package/src/testing/test-builder.ts +13 -29
- package/src/testing/test-wire-protocol.ts +1 -4
- package/src/tests/basic-test-suite.ts +34 -33
- package/src/tests/memory-transport.test.ts +40 -42
- package/src/tests/property-test-suite.ts +21 -22
- package/src/tests/tcp-transport.node.test.ts +65 -0
- package/src/tests/utils.ts +3 -2
- package/src/tests/webrtc-transport.test.ts +9 -9
- 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/src/typings.d.ts +8 -2
- package/dist/lib/browser/chunk-XYSYUN63.mjs.map +0 -7
- package/dist/lib/node/chunk-4YAYC7WN.cjs.map +0 -7
- package/dist/types/src/signal/integration.test.d.ts +0 -2
- package/dist/types/src/signal/integration.test.d.ts.map +0 -1
- package/dist/types/src/signal/swarm-messenger.test.d.ts +0 -2
- package/dist/types/src/signal/swarm-messenger.test.d.ts.map +0 -1
- package/dist/types/src/tests/tcp-transport.test.d.ts +0 -2
- package/dist/types/src/tests/tcp-transport.test.d.ts.map +0 -1
- 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.test.d.ts +0 -2
- package/dist/types/src/transport/libdatachannel-transport.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.d.ts +0 -2
- package/dist/types/src/transport/simplepeer-simple-peer.d.ts.map +0 -1
- package/dist/types/src/transport/simplepeer-transport-proxy-test.d.ts +0 -2
- package/dist/types/src/transport/simplepeer-transport-proxy-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-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/globals.d.ts +0 -7
- package/src/tests/tcp-transport.test.ts +0 -67
- package/src/transport/libdatachannel-transport.test.ts +0 -100
- package/src/transport/libdatachannel-transport.ts +0 -376
- package/src/transport/memory-transport.test.ts +0 -74
- package/src/transport/simplepeer-simple-peer.ts +0 -26
- package/src/transport/simplepeer-transport-proxy-test.ts +0 -181
- 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 -61
- package/src/transport/simplepeer-transport.ts +0 -250
- package/src/transport/webrtc.ts +0 -15
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2021 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { TestStream } from '@dxos/async';
|
|
6
|
-
import { PublicKey } from '@dxos/keys';
|
|
7
|
-
import { afterTest, describe, test } from '@dxos/test';
|
|
8
|
-
import { range } from '@dxos/util';
|
|
9
|
-
|
|
10
|
-
import { MemoryTransport } from './memory-transport';
|
|
11
|
-
|
|
12
|
-
// TODO(burdon): Flaky test.
|
|
13
|
-
// Cannot log after tests are done. Did you forget to wait for something async in your test?
|
|
14
|
-
// Attempted to log "Ignoring unsupported ICE candidate.".
|
|
15
|
-
|
|
16
|
-
// TODO(burdon): Move to TestBuilder.
|
|
17
|
-
const createPair = async () => {
|
|
18
|
-
const topic = PublicKey.random();
|
|
19
|
-
const peer1Id = PublicKey.random();
|
|
20
|
-
const peer2Id = PublicKey.random();
|
|
21
|
-
|
|
22
|
-
const stream1 = new TestStream();
|
|
23
|
-
const connection1 = new MemoryTransport({
|
|
24
|
-
stream: stream1,
|
|
25
|
-
sendSignal: async (signal) => {
|
|
26
|
-
await connection2.onSignal(signal);
|
|
27
|
-
},
|
|
28
|
-
initiator: true,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
afterTest(() => connection1.close());
|
|
32
|
-
afterTest(() => connection1.errors.assertNoUnhandledErrors());
|
|
33
|
-
|
|
34
|
-
const stream2 = new TestStream();
|
|
35
|
-
const connection2 = new MemoryTransport({
|
|
36
|
-
stream: stream2,
|
|
37
|
-
sendSignal: async (signal) => {
|
|
38
|
-
await connection1.onSignal(signal);
|
|
39
|
-
},
|
|
40
|
-
initiator: false,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
afterTest(() => connection2.close());
|
|
44
|
-
afterTest(() => connection2.errors.assertNoUnhandledErrors());
|
|
45
|
-
|
|
46
|
-
await connection1.open();
|
|
47
|
-
await connection2.open();
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
connection1,
|
|
51
|
-
connection2,
|
|
52
|
-
stream1,
|
|
53
|
-
stream2,
|
|
54
|
-
peer1Id,
|
|
55
|
-
peer2Id,
|
|
56
|
-
topic,
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
describe('MemoryTransport', () => {
|
|
61
|
-
test('establish connection and send data through with protocol', async () => {
|
|
62
|
-
const { stream1, stream2 } = await createPair();
|
|
63
|
-
await TestStream.assertConnectivity(stream1, stream2);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test('10 pairs of peers connecting at the same time', async () => {
|
|
67
|
-
await Promise.all(
|
|
68
|
-
range(10).map(async () => {
|
|
69
|
-
const { stream1, stream2 } = await createPair();
|
|
70
|
-
await TestStream.assertConnectivity(stream1, stream2);
|
|
71
|
-
}),
|
|
72
|
-
);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2020 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
// @dxos/test platform=nodejs
|
|
6
|
-
|
|
7
|
-
import wrtc from '@koush/wrtc';
|
|
8
|
-
import SimplePeerConstructor from 'simple-peer';
|
|
9
|
-
|
|
10
|
-
import { sleep } from '@dxos/async';
|
|
11
|
-
import { describe, test } from '@dxos/test';
|
|
12
|
-
|
|
13
|
-
describe('Node WebRTC and simple-peer', () => {
|
|
14
|
-
// Simplest test that reproduces SIGABRT (mac) and SIGSEGV (linux) in wrtc.
|
|
15
|
-
test
|
|
16
|
-
.skip('open and close', async () => {
|
|
17
|
-
const peer = new SimplePeerConstructor({
|
|
18
|
-
initiator: true,
|
|
19
|
-
wrtc,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
await sleep(1);
|
|
23
|
-
await peer.destroy();
|
|
24
|
-
})
|
|
25
|
-
.timeout(3_000);
|
|
26
|
-
});
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2020 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
// @dxos/test platform=nodejs
|
|
6
|
-
|
|
7
|
-
import { TestStream } from '@dxos/async';
|
|
8
|
-
import { schema } from '@dxos/protocols/proto';
|
|
9
|
-
import { type BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';
|
|
10
|
-
import { type Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
|
|
11
|
-
import { createLinkedPorts, createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';
|
|
12
|
-
import { afterAll, afterTest, beforeAll, describe, test } from '@dxos/test';
|
|
13
|
-
|
|
14
|
-
import { SimplePeerTransportProxy } from './simplepeer-transport-proxy';
|
|
15
|
-
import { SimplePeerTransportService } from './simplepeer-transport-service';
|
|
16
|
-
|
|
17
|
-
describe('SimplePeerTransportProxy', () => {
|
|
18
|
-
const setupProxy = async ({
|
|
19
|
-
initiator = true,
|
|
20
|
-
stream = new TestStream(),
|
|
21
|
-
sendSignal = async () => {},
|
|
22
|
-
}: {
|
|
23
|
-
initiator?: boolean;
|
|
24
|
-
stream?: NodeJS.ReadWriteStream;
|
|
25
|
-
sendSignal?: (msg: Signal) => Promise<void>;
|
|
26
|
-
} = {}) => {
|
|
27
|
-
const [port1, port2] = createLinkedPorts();
|
|
28
|
-
|
|
29
|
-
// Starting BridgeService
|
|
30
|
-
const simplePeerTransportService: BridgeService = new SimplePeerTransportService();
|
|
31
|
-
|
|
32
|
-
// Starting BridgeService
|
|
33
|
-
const rpcService = createProtoRpcPeer({
|
|
34
|
-
requested: {},
|
|
35
|
-
exposed: {
|
|
36
|
-
BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
|
|
37
|
-
},
|
|
38
|
-
handlers: { BridgeService: simplePeerTransportService },
|
|
39
|
-
port: port1,
|
|
40
|
-
noHandshake: true,
|
|
41
|
-
encodingOptions: {
|
|
42
|
-
preserveAny: true,
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
await rpcService.open();
|
|
46
|
-
afterTest(() => rpcService.close());
|
|
47
|
-
|
|
48
|
-
// Starting RPC client
|
|
49
|
-
const rpcClient = createProtoRpcPeer({
|
|
50
|
-
requested: {
|
|
51
|
-
BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
|
|
52
|
-
},
|
|
53
|
-
port: port2,
|
|
54
|
-
noHandshake: true,
|
|
55
|
-
encodingOptions: {
|
|
56
|
-
preserveAny: true,
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
await rpcClient.open();
|
|
60
|
-
afterTest(() => rpcClient.close());
|
|
61
|
-
|
|
62
|
-
const simplePeerTransportProxy = new SimplePeerTransportProxy({
|
|
63
|
-
initiator,
|
|
64
|
-
stream,
|
|
65
|
-
sendSignal,
|
|
66
|
-
bridgeService: rpcClient.rpc.BridgeService,
|
|
67
|
-
});
|
|
68
|
-
await simplePeerTransportProxy.open();
|
|
69
|
-
afterTest(async () => await simplePeerTransportProxy.close());
|
|
70
|
-
|
|
71
|
-
return { simplePeerService: rpcService, SimplePeerTransportProxy: simplePeerTransportProxy };
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// This doesn't clean up correctly and crashes with SIGSEGV / SIGABRT at the end. Probably an issue with wrtc package.
|
|
75
|
-
test('open and close', async () => {
|
|
76
|
-
const { SimplePeerTransportProxy: connection } = await setupProxy();
|
|
77
|
-
|
|
78
|
-
const wait = connection.closed.waitForCount(1);
|
|
79
|
-
await connection.close();
|
|
80
|
-
await wait;
|
|
81
|
-
}).timeout(1_000);
|
|
82
|
-
|
|
83
|
-
test('establish connection and send data through with protocol', async () => {
|
|
84
|
-
const stream1 = new TestStream();
|
|
85
|
-
const { SimplePeerTransportProxy: connection1 } = await setupProxy({
|
|
86
|
-
initiator: true,
|
|
87
|
-
stream: stream1,
|
|
88
|
-
sendSignal: async (signal) => {
|
|
89
|
-
await connection2.onSignal(signal);
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
afterTest(() => connection1.errors.assertNoUnhandledErrors());
|
|
93
|
-
|
|
94
|
-
const stream2 = new TestStream();
|
|
95
|
-
const { SimplePeerTransportProxy: connection2 } = await setupProxy({
|
|
96
|
-
initiator: false,
|
|
97
|
-
stream: stream2,
|
|
98
|
-
sendSignal: async (signal) => {
|
|
99
|
-
await connection1.onSignal(signal);
|
|
100
|
-
},
|
|
101
|
-
});
|
|
102
|
-
afterTest(() => connection2.errors.assertNoUnhandledErrors());
|
|
103
|
-
|
|
104
|
-
await TestStream.assertConnectivity(stream1, stream2);
|
|
105
|
-
}).timeout(2_000);
|
|
106
|
-
|
|
107
|
-
describe('Multiplexing', () => {
|
|
108
|
-
let service: any;
|
|
109
|
-
let rpcClient: ProtoRpcPeer<{ BridgeService: BridgeService }>;
|
|
110
|
-
|
|
111
|
-
beforeAll(async () => {
|
|
112
|
-
const [port1, port2] = createLinkedPorts();
|
|
113
|
-
|
|
114
|
-
const simplePeerTransportService: BridgeService = new SimplePeerTransportService();
|
|
115
|
-
service = createProtoRpcPeer({
|
|
116
|
-
exposed: {
|
|
117
|
-
BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
|
|
118
|
-
},
|
|
119
|
-
handlers: { BridgeService: simplePeerTransportService },
|
|
120
|
-
port: port1,
|
|
121
|
-
noHandshake: true,
|
|
122
|
-
encodingOptions: {
|
|
123
|
-
preserveAny: true,
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
await service.open();
|
|
127
|
-
|
|
128
|
-
rpcClient = createProtoRpcPeer({
|
|
129
|
-
requested: {
|
|
130
|
-
BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
|
|
131
|
-
},
|
|
132
|
-
port: port2,
|
|
133
|
-
noHandshake: true,
|
|
134
|
-
encodingOptions: {
|
|
135
|
-
preserveAny: true,
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
await rpcClient.open();
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
afterAll(async () => {
|
|
142
|
-
await service?.close();
|
|
143
|
-
await rpcClient?.close();
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test('establish connection and send data through with protocol', async () => {
|
|
147
|
-
const stream1 = new TestStream();
|
|
148
|
-
const proxy1 = new SimplePeerTransportProxy({
|
|
149
|
-
initiator: true,
|
|
150
|
-
stream: stream1,
|
|
151
|
-
sendSignal: async (signal) => {
|
|
152
|
-
await proxy2.onSignal(signal);
|
|
153
|
-
},
|
|
154
|
-
bridgeService: rpcClient.rpc.BridgeService,
|
|
155
|
-
});
|
|
156
|
-
afterTest(async () => {
|
|
157
|
-
proxy1.errors.assertNoUnhandledErrors();
|
|
158
|
-
await proxy1.close();
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
const stream2 = new TestStream();
|
|
162
|
-
const proxy2 = new SimplePeerTransportProxy({
|
|
163
|
-
initiator: false,
|
|
164
|
-
stream: stream2,
|
|
165
|
-
sendSignal: async (signal) => {
|
|
166
|
-
await proxy1.onSignal(signal);
|
|
167
|
-
},
|
|
168
|
-
bridgeService: rpcClient.rpc.BridgeService,
|
|
169
|
-
});
|
|
170
|
-
afterTest(async () => {
|
|
171
|
-
proxy2.errors.assertNoUnhandledErrors();
|
|
172
|
-
await proxy2.close();
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
await proxy1.open();
|
|
176
|
-
await proxy2.open();
|
|
177
|
-
|
|
178
|
-
await TestStream.assertConnectivity(stream1, stream2);
|
|
179
|
-
}).timeout(3_000);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2022 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { Writable } from 'node:stream';
|
|
6
|
-
|
|
7
|
-
import { Event, scheduleTask } from '@dxos/async';
|
|
8
|
-
import { type Stream } from '@dxos/codec-protobuf';
|
|
9
|
-
import { Context } from '@dxos/context';
|
|
10
|
-
import { ErrorStream } from '@dxos/debug';
|
|
11
|
-
import { invariant } from '@dxos/invariant';
|
|
12
|
-
import { PublicKey } from '@dxos/keys';
|
|
13
|
-
import { log } from '@dxos/log';
|
|
14
|
-
import {
|
|
15
|
-
ConnectionResetError,
|
|
16
|
-
TimeoutError,
|
|
17
|
-
ProtocolError,
|
|
18
|
-
ConnectivityError,
|
|
19
|
-
UnknownProtocolError,
|
|
20
|
-
} from '@dxos/protocols';
|
|
21
|
-
import { ConnectionState, type BridgeEvent, type BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';
|
|
22
|
-
import { type Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
|
|
23
|
-
import { arrayToBuffer } from '@dxos/util';
|
|
24
|
-
|
|
25
|
-
import { type Transport, type TransportFactory, type TransportOptions, type TransportStats } from './transport';
|
|
26
|
-
|
|
27
|
-
const RPC_TIMEOUT = 10_000;
|
|
28
|
-
const RESP_MIN_THRESHOLD = 500;
|
|
29
|
-
const TIMEOUT_THRESHOLD = 10;
|
|
30
|
-
|
|
31
|
-
export type SimplePeerTransportProxyOptions = TransportOptions & {
|
|
32
|
-
bridgeService: BridgeService;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export class SimplePeerTransportProxy implements Transport {
|
|
36
|
-
private readonly _proxyId = PublicKey.random();
|
|
37
|
-
private readonly _ctx = new Context();
|
|
38
|
-
private _timeoutCount = 0;
|
|
39
|
-
|
|
40
|
-
readonly closed = new Event();
|
|
41
|
-
readonly connected = new Event();
|
|
42
|
-
readonly errors = new ErrorStream();
|
|
43
|
-
|
|
44
|
-
private _closed = false;
|
|
45
|
-
private _serviceStream!: Stream<BridgeEvent>;
|
|
46
|
-
|
|
47
|
-
constructor(private readonly _options: SimplePeerTransportProxyOptions) {}
|
|
48
|
-
|
|
49
|
-
get isOpen() {
|
|
50
|
-
// TODO(burdon): Open state?
|
|
51
|
-
return !this._closed;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async open() {
|
|
55
|
-
this._serviceStream = this._options.bridgeService.open(
|
|
56
|
-
{
|
|
57
|
-
proxyId: this._proxyId,
|
|
58
|
-
initiator: this._options.initiator,
|
|
59
|
-
},
|
|
60
|
-
{ timeout: RPC_TIMEOUT },
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
this._serviceStream.waitUntilReady().then(
|
|
64
|
-
() => {
|
|
65
|
-
this._serviceStream.subscribe(async (event: BridgeEvent) => {
|
|
66
|
-
log('SimplePeerTransportProxy: event', event);
|
|
67
|
-
if (event.connection) {
|
|
68
|
-
await this._handleConnection(event.connection);
|
|
69
|
-
} else if (event.data) {
|
|
70
|
-
this._handleData(event.data);
|
|
71
|
-
} else if (event.signal) {
|
|
72
|
-
await this._handleSignal(event.signal);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const proxyStream = new Writable({
|
|
77
|
-
write: (chunk, _, callback) => {
|
|
78
|
-
const then = performance.now();
|
|
79
|
-
this._options.bridgeService
|
|
80
|
-
.sendData(
|
|
81
|
-
{
|
|
82
|
-
proxyId: this._proxyId,
|
|
83
|
-
payload: chunk,
|
|
84
|
-
},
|
|
85
|
-
{ timeout: RPC_TIMEOUT },
|
|
86
|
-
)
|
|
87
|
-
.then(
|
|
88
|
-
() => {
|
|
89
|
-
if (performance.now() - then > RESP_MIN_THRESHOLD) {
|
|
90
|
-
log('slow response, delaying callback');
|
|
91
|
-
scheduleTask(this._ctx, () => callback(), RESP_MIN_THRESHOLD);
|
|
92
|
-
} else {
|
|
93
|
-
callback();
|
|
94
|
-
}
|
|
95
|
-
this._timeoutCount = 0;
|
|
96
|
-
},
|
|
97
|
-
(err: any) => {
|
|
98
|
-
if (err instanceof TimeoutError || err.constructor.name === 'TimeoutError') {
|
|
99
|
-
if (this._timeoutCount++ > TIMEOUT_THRESHOLD) {
|
|
100
|
-
throw new TimeoutError(`too many timeouts (${this._timeoutCount} > ${TIMEOUT_THRESHOLD}`);
|
|
101
|
-
} else {
|
|
102
|
-
log('timeout error, but still invoking callback');
|
|
103
|
-
callback();
|
|
104
|
-
}
|
|
105
|
-
} else {
|
|
106
|
-
log.catch(err);
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
);
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
proxyStream.on('error', (err) => {
|
|
114
|
-
log('proxystream error', { err });
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
this._options.stream.pipe(proxyStream);
|
|
118
|
-
},
|
|
119
|
-
(error) => log.catch(error),
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async close() {
|
|
124
|
-
await this._ctx.dispose();
|
|
125
|
-
if (this._closed) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
await this._serviceStream.close();
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
await this._options.bridgeService.close({ proxyId: this._proxyId }, { timeout: RPC_TIMEOUT });
|
|
133
|
-
} catch (err: any) {
|
|
134
|
-
log.catch(err);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
this.closed.emit();
|
|
138
|
-
this._closed = true;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async onSignal(signal: Signal) {
|
|
142
|
-
this._options.bridgeService
|
|
143
|
-
.sendSignal(
|
|
144
|
-
{
|
|
145
|
-
proxyId: this._proxyId,
|
|
146
|
-
signal,
|
|
147
|
-
},
|
|
148
|
-
{ timeout: RPC_TIMEOUT },
|
|
149
|
-
)
|
|
150
|
-
.catch((err) => this.errors.raise(decodeError(err)));
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
private async _handleConnection(connectionEvent: BridgeEvent.ConnectionEvent): Promise<void> {
|
|
154
|
-
if (connectionEvent.error) {
|
|
155
|
-
this.errors.raise(decodeError(connectionEvent.error));
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
switch (connectionEvent.state) {
|
|
159
|
-
case ConnectionState.CONNECTED: {
|
|
160
|
-
this.connected.emit();
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
case ConnectionState.CLOSED: {
|
|
164
|
-
await this.close();
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private _handleData(dataEvent: BridgeEvent.DataEvent) {
|
|
171
|
-
// NOTE: This must be a Buffer otherwise hypercore-protocol breaks.
|
|
172
|
-
this._options.stream.write(arrayToBuffer(dataEvent.payload));
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
private async _handleSignal(signalEvent: BridgeEvent.SignalEvent) {
|
|
176
|
-
await this._options.sendSignal(signalEvent.payload);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
async getDetails(): Promise<string> {
|
|
180
|
-
return (await this._options.bridgeService.getDetails({ proxyId: this._proxyId }, { timeout: RPC_TIMEOUT })).details;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async getStats(): Promise<TransportStats> {
|
|
184
|
-
return (await this._options.bridgeService.getStats({ proxyId: this._proxyId }, { timeout: RPC_TIMEOUT }))
|
|
185
|
-
.stats as TransportStats;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Called when underlying proxy service becomes unavailable.
|
|
190
|
-
*/
|
|
191
|
-
// TODO(burdon): Option on close method.
|
|
192
|
-
forceClose() {
|
|
193
|
-
void this._serviceStream.close();
|
|
194
|
-
this.closed.emit();
|
|
195
|
-
this._closed = true;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// TODO(burdon): Why is this named Proxy?
|
|
200
|
-
export class SimplePeerTransportProxyFactory implements TransportFactory {
|
|
201
|
-
private _bridgeService: BridgeService | undefined;
|
|
202
|
-
private _connections = new Set<SimplePeerTransportProxy>();
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Sets the current BridgeService to be used to open connections.
|
|
206
|
-
* Calling this method will close any existing connections.
|
|
207
|
-
*/
|
|
208
|
-
setBridgeService(bridgeService: BridgeService | undefined): this {
|
|
209
|
-
this._bridgeService = bridgeService;
|
|
210
|
-
for (const connection of this._connections) {
|
|
211
|
-
connection.forceClose();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return this;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
createTransport(options: TransportOptions): Transport {
|
|
218
|
-
invariant(this._bridgeService, 'SimplePeerTransportProxyFactory is not ready to open connections');
|
|
219
|
-
const transport = new SimplePeerTransportProxy({
|
|
220
|
-
...options,
|
|
221
|
-
bridgeService: this._bridgeService,
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
this._connections.add(transport);
|
|
225
|
-
transport.closed.on(() => this._connections.delete(transport));
|
|
226
|
-
return transport;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// TODO(nf): fix so Errors crossing RPC boundary preserve class
|
|
231
|
-
const decodeError = (err: Error | string) => {
|
|
232
|
-
const message = typeof err === 'string' ? err : err.message;
|
|
233
|
-
if (message.includes('CONNECTION_RESET')) {
|
|
234
|
-
return new ConnectionResetError(message);
|
|
235
|
-
} else if (message.includes('TIMEOUT')) {
|
|
236
|
-
return new TimeoutError(message);
|
|
237
|
-
} else if (message.includes('PROTOCOL_ERROR')) {
|
|
238
|
-
return new ProtocolError(message);
|
|
239
|
-
} else if (message.includes('CONNECTIVITY_ERROR')) {
|
|
240
|
-
return new ConnectivityError(message);
|
|
241
|
-
} else if (message.includes('UNKNOWN_PROTOCOL_ERROR')) {
|
|
242
|
-
return new UnknownProtocolError(message);
|
|
243
|
-
} else {
|
|
244
|
-
return typeof err === 'string' ? new Error(err) : err;
|
|
245
|
-
}
|
|
246
|
-
};
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2022 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { Duplex } from 'node:stream';
|
|
6
|
-
|
|
7
|
-
import { Stream } from '@dxos/codec-protobuf';
|
|
8
|
-
import { invariant } from '@dxos/invariant';
|
|
9
|
-
import { PublicKey } from '@dxos/keys';
|
|
10
|
-
import { log } from '@dxos/log';
|
|
11
|
-
import {
|
|
12
|
-
type BridgeService,
|
|
13
|
-
type ConnectionRequest,
|
|
14
|
-
type SignalRequest,
|
|
15
|
-
type DataRequest,
|
|
16
|
-
type BridgeEvent,
|
|
17
|
-
ConnectionState,
|
|
18
|
-
type CloseRequest,
|
|
19
|
-
type DetailsRequest,
|
|
20
|
-
type DetailsResponse,
|
|
21
|
-
type StatsRequest,
|
|
22
|
-
type StatsResponse,
|
|
23
|
-
} from '@dxos/protocols/proto/dxos/mesh/bridge';
|
|
24
|
-
import { ComplexMap } from '@dxos/util';
|
|
25
|
-
|
|
26
|
-
import { SimplePeerTransport } from './simplepeer-transport';
|
|
27
|
-
import { type IceProvider } from '../signal';
|
|
28
|
-
|
|
29
|
-
type TransportState = {
|
|
30
|
-
transport: SimplePeerTransport;
|
|
31
|
-
stream: Duplex;
|
|
32
|
-
writeCallbacks: (() => void)[];
|
|
33
|
-
state: 'OPEN' | 'CLOSED';
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export class SimplePeerTransportService implements BridgeService {
|
|
37
|
-
private readonly transports = new ComplexMap<PublicKey, TransportState>(PublicKey.hash);
|
|
38
|
-
|
|
39
|
-
constructor(
|
|
40
|
-
private readonly _webrtcConfig?: RTCConfiguration,
|
|
41
|
-
private readonly _iceProvider?: IceProvider,
|
|
42
|
-
) {}
|
|
43
|
-
|
|
44
|
-
open(request: ConnectionRequest): Stream<BridgeEvent> {
|
|
45
|
-
const rpcStream: Stream<BridgeEvent> = new Stream(({ ready, next, close }) => {
|
|
46
|
-
const duplex: Duplex = new Duplex({
|
|
47
|
-
read: () => {
|
|
48
|
-
const callbacks = [...transportState.writeCallbacks];
|
|
49
|
-
transportState.writeCallbacks.length = 0;
|
|
50
|
-
for (const cb of callbacks) {
|
|
51
|
-
cb();
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
write: function (chunk, _, callback) {
|
|
55
|
-
next({ data: { payload: chunk } });
|
|
56
|
-
callback();
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const transport = new SimplePeerTransport({
|
|
61
|
-
initiator: request.initiator,
|
|
62
|
-
stream: duplex,
|
|
63
|
-
webrtcConfig: this._webrtcConfig,
|
|
64
|
-
sendSignal: async (signal) => {
|
|
65
|
-
next({
|
|
66
|
-
signal: { payload: signal },
|
|
67
|
-
});
|
|
68
|
-
},
|
|
69
|
-
iceProvider: this._iceProvider,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// TODO(burdon): Async.
|
|
73
|
-
void transport.open();
|
|
74
|
-
|
|
75
|
-
next({
|
|
76
|
-
connection: {
|
|
77
|
-
state: ConnectionState.CONNECTING,
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
transport.connected.on(() => {
|
|
82
|
-
next({
|
|
83
|
-
connection: {
|
|
84
|
-
state: ConnectionState.CONNECTED,
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
transport.errors.handle((err) => {
|
|
90
|
-
next({
|
|
91
|
-
connection: {
|
|
92
|
-
state: ConnectionState.CLOSED,
|
|
93
|
-
error: err.toString(),
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
close(err);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
transport.closed.on(() => {
|
|
100
|
-
next({
|
|
101
|
-
connection: {
|
|
102
|
-
state: ConnectionState.CLOSED,
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
close();
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
const transportState: TransportState = {
|
|
109
|
-
transport,
|
|
110
|
-
stream: duplex,
|
|
111
|
-
writeCallbacks: [],
|
|
112
|
-
state: 'OPEN',
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
ready();
|
|
116
|
-
|
|
117
|
-
this.transports.set(request.proxyId, transportState);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
return rpcStream;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async sendSignal({ proxyId, signal }: SignalRequest): Promise<void> {
|
|
124
|
-
invariant(this.transports.has(proxyId));
|
|
125
|
-
await this.transports.get(proxyId)!.transport.onSignal(signal);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async getDetails({ proxyId }: DetailsRequest): Promise<DetailsResponse> {
|
|
129
|
-
invariant(this.transports.has(proxyId));
|
|
130
|
-
return { details: await this.transports.get(proxyId)!.transport.getDetails() };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async getStats({ proxyId }: StatsRequest): Promise<StatsResponse> {
|
|
134
|
-
invariant(this.transports.has(proxyId));
|
|
135
|
-
return { stats: await this.transports.get(proxyId)!.transport.getStats() };
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async sendData({ proxyId, payload }: DataRequest): Promise<void> {
|
|
139
|
-
if (this.transports.get(proxyId)?.state !== 'OPEN') {
|
|
140
|
-
log.debug('transport is closed');
|
|
141
|
-
}
|
|
142
|
-
invariant(this.transports.has(proxyId));
|
|
143
|
-
const state = this.transports.get(proxyId)!;
|
|
144
|
-
const bufferHasSpace = state.stream.push(payload);
|
|
145
|
-
if (!bufferHasSpace) {
|
|
146
|
-
await new Promise<void>((resolve) => {
|
|
147
|
-
state.writeCallbacks.push(resolve);
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async close({ proxyId }: CloseRequest) {
|
|
153
|
-
await this.transports.get(proxyId)?.transport.close();
|
|
154
|
-
await this.transports.get(proxyId)?.stream.end();
|
|
155
|
-
if (this.transports.get(proxyId)) {
|
|
156
|
-
this.transports.get(proxyId)!.state = 'CLOSED';
|
|
157
|
-
}
|
|
158
|
-
log('Closed.');
|
|
159
|
-
}
|
|
160
|
-
}
|