@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.
Files changed (128) hide show
  1. package/dist/lib/browser/chunk-GW3YM55A.mjs +14 -0
  2. package/dist/lib/browser/chunk-GW3YM55A.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-NMDGRINN.mjs → chunk-YOKKEU6T.mjs} +1216 -1037
  4. package/dist/lib/browser/chunk-YOKKEU6T.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +10 -19
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/testing/index.mjs +18 -27
  8. package/dist/lib/browser/testing/index.mjs.map +3 -3
  9. package/dist/lib/browser/transport/tcp/index.mjs +39 -0
  10. package/dist/lib/browser/transport/tcp/index.mjs.map +7 -0
  11. package/dist/lib/node/{chunk-4K3JQNY3.cjs → chunk-7ZWQLO5T.cjs} +1229 -1177
  12. package/dist/lib/node/chunk-7ZWQLO5T.cjs.map +7 -0
  13. package/dist/lib/node/index.cjs +27 -37
  14. package/dist/lib/node/index.cjs.map +2 -2
  15. package/dist/lib/node/meta.json +1 -1
  16. package/dist/lib/node/testing/index.cjs +20 -29
  17. package/dist/lib/node/testing/index.cjs.map +3 -3
  18. package/dist/lib/node/transport/tcp/index.cjs +191 -0
  19. package/dist/lib/node/transport/tcp/index.cjs.map +7 -0
  20. package/dist/lib/node-esm/{chunk-X2RY5LSM.mjs → chunk-4VO725JT.mjs} +1249 -1185
  21. package/dist/lib/node-esm/chunk-4VO725JT.mjs.map +7 -0
  22. package/dist/lib/node-esm/index.mjs +10 -19
  23. package/dist/lib/node-esm/meta.json +1 -1
  24. package/dist/lib/node-esm/testing/index.mjs +16 -26
  25. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  26. package/dist/lib/node-esm/transport/tcp/index.mjs +159 -0
  27. package/dist/lib/node-esm/transport/tcp/index.mjs.map +7 -0
  28. package/dist/types/src/swarm/connection.d.ts.map +1 -1
  29. package/dist/types/src/swarm/swarm.d.ts +1 -1
  30. package/dist/types/src/testing/test-builder.d.ts +2 -2
  31. package/dist/types/src/testing/test-builder.d.ts.map +1 -1
  32. package/dist/types/src/transport/index.d.ts +1 -5
  33. package/dist/types/src/transport/index.d.ts.map +1 -1
  34. package/dist/types/src/transport/memory-transport.d.ts +2 -2
  35. package/dist/types/src/transport/memory-transport.d.ts.map +1 -1
  36. package/dist/types/src/transport/tcp/index.d.ts +2 -0
  37. package/dist/types/src/transport/tcp/index.d.ts.map +1 -0
  38. package/dist/types/src/transport/{tcp-transport.browser.d.ts → tcp/tcp-transport.browser.d.ts} +3 -3
  39. package/dist/types/src/transport/tcp/tcp-transport.browser.d.ts.map +1 -0
  40. package/dist/types/src/transport/{tcp-transport.d.ts → tcp/tcp-transport.d.ts} +3 -3
  41. package/dist/types/src/transport/tcp/tcp-transport.d.ts.map +1 -0
  42. package/dist/types/src/transport/transport.d.ts +7 -6
  43. package/dist/types/src/transport/transport.d.ts.map +1 -1
  44. package/dist/types/src/transport/webrtc/index.d.ts +4 -0
  45. package/dist/types/src/transport/webrtc/index.d.ts.map +1 -0
  46. package/dist/types/src/transport/webrtc/rtc-connection-factory.d.ts +14 -0
  47. package/dist/types/src/transport/webrtc/rtc-connection-factory.d.ts.map +1 -0
  48. package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts +68 -0
  49. package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts.map +1 -0
  50. package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts +33 -0
  51. package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts.map +1 -0
  52. package/dist/types/src/transport/webrtc/rtc-transport-channel.test.d.ts +2 -0
  53. package/dist/types/src/transport/webrtc/rtc-transport-channel.test.d.ts.map +1 -0
  54. package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts +4 -0
  55. package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts.map +1 -0
  56. package/dist/types/src/transport/{simplepeer-transport-proxy.d.ts → webrtc/rtc-transport-proxy.d.ts} +10 -12
  57. package/dist/types/src/transport/webrtc/rtc-transport-proxy.d.ts.map +1 -0
  58. package/dist/types/src/transport/webrtc/rtc-transport-proxy.test.d.ts +2 -0
  59. package/dist/types/src/transport/webrtc/rtc-transport-proxy.test.d.ts.map +1 -0
  60. package/dist/types/src/transport/{simplepeer-transport-service.d.ts → webrtc/rtc-transport-service.d.ts} +9 -7
  61. package/dist/types/src/transport/webrtc/rtc-transport-service.d.ts.map +1 -0
  62. package/dist/types/src/transport/webrtc/rtc-transport-stats.d.ts +4 -0
  63. package/dist/types/src/transport/webrtc/rtc-transport-stats.d.ts.map +1 -0
  64. package/dist/types/src/transport/webrtc/rtc-transport.test.d.ts +2 -0
  65. package/dist/types/src/transport/webrtc/rtc-transport.test.d.ts.map +1 -0
  66. package/dist/types/src/transport/webrtc/test-utils.d.ts +5 -0
  67. package/dist/types/src/transport/webrtc/test-utils.d.ts.map +1 -0
  68. package/dist/types/src/transport/webrtc/utils.d.ts +3 -0
  69. package/dist/types/src/transport/webrtc/utils.d.ts.map +1 -0
  70. package/package.json +44 -20
  71. package/src/signal/swarm-messenger.node.test.ts +1 -1
  72. package/src/swarm/connection.test.ts +61 -37
  73. package/src/swarm/connection.ts +5 -5
  74. package/src/swarm/swarm.test.ts +2 -3
  75. package/src/swarm/swarm.ts +1 -1
  76. package/src/testing/test-builder.ts +12 -28
  77. package/src/transport/index.ts +1 -5
  78. package/src/transport/memory-transport.ts +2 -0
  79. package/src/transport/tcp/index.ts +5 -0
  80. package/src/transport/{tcp-transport.browser.ts → tcp/tcp-transport.browser.ts} +7 -3
  81. package/src/transport/{tcp-transport.ts → tcp/tcp-transport.ts} +3 -1
  82. package/src/transport/transport.ts +8 -7
  83. package/src/transport/webrtc/index.ts +7 -0
  84. package/src/transport/webrtc/rtc-connection-factory.ts +82 -0
  85. package/src/transport/webrtc/rtc-peer-connection.ts +472 -0
  86. package/src/transport/webrtc/rtc-transport-channel.test.ts +176 -0
  87. package/src/transport/webrtc/rtc-transport-channel.ts +195 -0
  88. package/src/transport/webrtc/rtc-transport-factory.ts +28 -0
  89. package/src/transport/webrtc/rtc-transport-proxy.test.ts +413 -0
  90. package/src/transport/webrtc/rtc-transport-proxy.ts +264 -0
  91. package/src/transport/webrtc/rtc-transport-service.ts +192 -0
  92. package/src/transport/webrtc/rtc-transport-stats.ts +67 -0
  93. package/src/transport/webrtc/rtc-transport.test.ts +198 -0
  94. package/src/transport/webrtc/test-utils.ts +22 -0
  95. package/src/transport/webrtc/utils.ts +36 -0
  96. package/dist/lib/browser/chunk-NMDGRINN.mjs.map +0 -7
  97. package/dist/lib/node/chunk-4K3JQNY3.cjs.map +0 -7
  98. package/dist/lib/node-esm/chunk-X2RY5LSM.mjs.map +0 -7
  99. package/dist/types/src/transport/libdatachannel-transport.d.ts +0 -42
  100. package/dist/types/src/transport/libdatachannel-transport.d.ts.map +0 -1
  101. package/dist/types/src/transport/libdatachannel-transport.node.test.d.ts +0 -2
  102. package/dist/types/src/transport/libdatachannel-transport.node.test.d.ts.map +0 -1
  103. package/dist/types/src/transport/memory-transport.test.d.ts +0 -2
  104. package/dist/types/src/transport/memory-transport.test.d.ts.map +0 -1
  105. package/dist/types/src/transport/simplepeer-simple-peer.node.test.d.ts +0 -2
  106. package/dist/types/src/transport/simplepeer-simple-peer.node.test.d.ts.map +0 -1
  107. package/dist/types/src/transport/simplepeer-transport-proxy.d.ts.map +0 -1
  108. package/dist/types/src/transport/simplepeer-transport-proxy.node.test.d.ts +0 -2
  109. package/dist/types/src/transport/simplepeer-transport-proxy.node.test.d.ts.map +0 -1
  110. package/dist/types/src/transport/simplepeer-transport-service.d.ts.map +0 -1
  111. package/dist/types/src/transport/simplepeer-transport.d.ts +0 -36
  112. package/dist/types/src/transport/simplepeer-transport.d.ts.map +0 -1
  113. package/dist/types/src/transport/simplepeer-transport.test.d.ts +0 -2
  114. package/dist/types/src/transport/simplepeer-transport.test.d.ts.map +0 -1
  115. package/dist/types/src/transport/tcp-transport.browser.d.ts.map +0 -1
  116. package/dist/types/src/transport/tcp-transport.d.ts.map +0 -1
  117. package/dist/types/src/transport/webrtc.d.ts +0 -6
  118. package/dist/types/src/transport/webrtc.d.ts.map +0 -1
  119. package/src/transport/libdatachannel-transport.node.test.ts +0 -91
  120. package/src/transport/libdatachannel-transport.ts +0 -372
  121. package/src/transport/memory-transport.test.ts +0 -75
  122. package/src/transport/simplepeer-simple-peer.node.test.ts +0 -22
  123. package/src/transport/simplepeer-transport-proxy.node.test.ts +0 -180
  124. package/src/transport/simplepeer-transport-proxy.ts +0 -246
  125. package/src/transport/simplepeer-transport-service.ts +0 -160
  126. package/src/transport/simplepeer-transport.test.ts +0 -57
  127. package/src/transport/simplepeer-transport.ts +0 -250
  128. package/src/transport/webrtc.ts +0 -15
@@ -1,180 +0,0 @@
1
- //
2
- // Copyright 2020 DXOS.org
3
- //
4
-
5
- import { afterAll, onTestFinished, beforeAll, describe, test } from 'vitest';
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
-
13
- import { SimplePeerTransportProxy } from './simplepeer-transport-proxy';
14
- import { SimplePeerTransportService } from './simplepeer-transport-service';
15
-
16
- describe('SimplePeerTransportProxy', () => {
17
- const setupProxy = async ({
18
- initiator = true,
19
- stream = new TestStream(),
20
- sendSignal = async () => {},
21
- }: {
22
- initiator?: boolean;
23
- stream?: NodeJS.ReadWriteStream;
24
- sendSignal?: (msg: Signal) => Promise<void>;
25
- } = {}) => {
26
- const [port1, port2] = createLinkedPorts();
27
-
28
- // Starting BridgeService
29
- const simplePeerTransportService: BridgeService = new SimplePeerTransportService();
30
-
31
- // Starting BridgeService
32
- const rpcService = createProtoRpcPeer({
33
- requested: {},
34
- exposed: {
35
- BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
36
- },
37
- handlers: { BridgeService: simplePeerTransportService },
38
- port: port1,
39
- noHandshake: true,
40
- encodingOptions: {
41
- preserveAny: true,
42
- },
43
- });
44
- await rpcService.open();
45
- onTestFinished(() => rpcService.close());
46
-
47
- // Starting RPC client
48
- const rpcClient = createProtoRpcPeer({
49
- requested: {
50
- BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
51
- },
52
- port: port2,
53
- noHandshake: true,
54
- encodingOptions: {
55
- preserveAny: true,
56
- },
57
- });
58
- await rpcClient.open();
59
- onTestFinished(() => rpcClient.close());
60
-
61
- const simplePeerTransportProxy = new SimplePeerTransportProxy({
62
- initiator,
63
- stream,
64
- sendSignal,
65
- bridgeService: rpcClient.rpc.BridgeService,
66
- });
67
- await simplePeerTransportProxy.open();
68
- onTestFinished(async () => await simplePeerTransportProxy.close());
69
-
70
- return { simplePeerService: rpcService, SimplePeerTransportProxy: simplePeerTransportProxy };
71
- };
72
-
73
- // This doesn't clean up correctly and crashes with SIGSEGV / SIGABRT at the end. Probably an issue with wrtc package.
74
- test('open and close', { timeout: 1_000 }, async () => {
75
- const { SimplePeerTransportProxy: connection } = await setupProxy();
76
-
77
- const wait = connection.closed.waitForCount(1);
78
- await connection.close();
79
- await wait;
80
- });
81
-
82
- test('establish connection and send data through with protocol', { timeout: 2_000 }, async () => {
83
- const stream1 = new TestStream();
84
- const { SimplePeerTransportProxy: connection1 } = await setupProxy({
85
- initiator: true,
86
- stream: stream1,
87
- sendSignal: async (signal) => {
88
- await connection2.onSignal(signal);
89
- },
90
- });
91
- onTestFinished(() => connection1.errors.assertNoUnhandledErrors());
92
-
93
- const stream2 = new TestStream();
94
- const { SimplePeerTransportProxy: connection2 } = await setupProxy({
95
- initiator: false,
96
- stream: stream2,
97
- sendSignal: async (signal) => {
98
- await connection1.onSignal(signal);
99
- },
100
- });
101
- onTestFinished(() => connection2.errors.assertNoUnhandledErrors());
102
-
103
- await TestStream.assertConnectivity(stream1, stream2);
104
- });
105
-
106
- describe('Multiplexing', () => {
107
- let service: any;
108
- let rpcClient: ProtoRpcPeer<{ BridgeService: BridgeService }>;
109
-
110
- beforeAll(async () => {
111
- const [port1, port2] = createLinkedPorts();
112
-
113
- const simplePeerTransportService: BridgeService = new SimplePeerTransportService();
114
- service = createProtoRpcPeer({
115
- exposed: {
116
- BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
117
- },
118
- handlers: { BridgeService: simplePeerTransportService },
119
- port: port1,
120
- noHandshake: true,
121
- encodingOptions: {
122
- preserveAny: true,
123
- },
124
- });
125
- await service.open();
126
-
127
- rpcClient = createProtoRpcPeer({
128
- requested: {
129
- BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
130
- },
131
- port: port2,
132
- noHandshake: true,
133
- encodingOptions: {
134
- preserveAny: true,
135
- },
136
- });
137
- await rpcClient.open();
138
- });
139
-
140
- afterAll(async () => {
141
- await service?.close();
142
- await rpcClient?.close();
143
- });
144
-
145
- test('establish connection and send data through with protocol', { timeout: 3_000 }, async () => {
146
- const stream1 = new TestStream();
147
- const proxy1 = new SimplePeerTransportProxy({
148
- initiator: true,
149
- stream: stream1,
150
- sendSignal: async (signal) => {
151
- await proxy2.onSignal(signal);
152
- },
153
- bridgeService: rpcClient.rpc.BridgeService,
154
- });
155
- onTestFinished(async () => {
156
- proxy1.errors.assertNoUnhandledErrors();
157
- await proxy1.close();
158
- });
159
-
160
- const stream2 = new TestStream();
161
- const proxy2 = new SimplePeerTransportProxy({
162
- initiator: false,
163
- stream: stream2,
164
- sendSignal: async (signal) => {
165
- await proxy1.onSignal(signal);
166
- },
167
- bridgeService: rpcClient.rpc.BridgeService,
168
- });
169
- onTestFinished(async () => {
170
- proxy2.errors.assertNoUnhandledErrors();
171
- await proxy2.close();
172
- });
173
-
174
- await proxy1.open();
175
- await proxy2.open();
176
-
177
- await TestStream.assertConnectivity(stream1, stream2);
178
- });
179
- });
180
- });
@@ -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
- }
@@ -1,57 +0,0 @@
1
- //
2
- // Copyright 2020 DXOS.org
3
- //
4
-
5
- import { Duplex } from 'node:stream';
6
- import { onTestFinished, describe, test } from 'vitest';
7
-
8
- import { sleep, TestStream } from '@dxos/async';
9
-
10
- import { SimplePeerTransport } from './simplepeer-transport';
11
-
12
- describe('SimplePeerTransport', () => {
13
- // This doesn't clean up correctly and crashes with SIGSEGV / SIGABRT at the end. Probably an issue with wrtc package.
14
- test('open and close', { timeout: 1_000 }, async () => {
15
- const connection = new SimplePeerTransport({
16
- initiator: true,
17
- stream: new Duplex(),
18
- sendSignal: async () => {},
19
- });
20
-
21
- await connection.open();
22
- const wait = connection.closed.waitForCount(1);
23
- await connection.close();
24
- await wait;
25
- });
26
-
27
- test('establish connection and send data through with protocol', { timeout: 2_000 }, async () => {
28
- const stream1 = new TestStream();
29
- const connection1 = new SimplePeerTransport({
30
- initiator: true,
31
- stream: stream1,
32
- sendSignal: async (signal) => {
33
- await sleep(10);
34
- await connection2.onSignal(signal);
35
- },
36
- });
37
- onTestFinished(() => connection1.close());
38
- onTestFinished(() => connection1.errors.assertNoUnhandledErrors());
39
-
40
- const stream2 = new TestStream();
41
- const connection2 = new SimplePeerTransport({
42
- initiator: false,
43
- stream: stream2,
44
- sendSignal: async (signal) => {
45
- await sleep(10);
46
- await connection1.onSignal(signal);
47
- },
48
- });
49
- onTestFinished(() => connection2.close());
50
- onTestFinished(() => connection2.errors.assertNoUnhandledErrors());
51
-
52
- await connection1.open();
53
- await connection2.open();
54
-
55
- await TestStream.assertConnectivity(stream1, stream2);
56
- });
57
- });