@dxos/network-manager 0.1.57-main.e87098f → 0.1.57

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 (95) hide show
  1. package/dist/lib/browser/{chunk-UAB4ONRL.mjs → chunk-UKMTAO4L.mjs} +553 -121
  2. package/dist/lib/browser/chunk-UKMTAO4L.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-YERMWDRB.mjs +24 -0
  4. package/dist/lib/browser/chunk-YERMWDRB.mjs.map +7 -0
  5. package/dist/lib/browser/index.browser-O53CPVK3.mjs +14 -0
  6. package/dist/lib/browser/index.browser-O53CPVK3.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +29 -13
  8. package/dist/lib/browser/meta.json +1 -1
  9. package/dist/lib/browser/testing/index.mjs +83 -38
  10. package/dist/lib/browser/testing/index.mjs.map +3 -3
  11. package/dist/lib/node/index.cjs +1048 -124
  12. package/dist/lib/node/index.cjs.map +4 -4
  13. package/dist/lib/node/meta.json +1 -1
  14. package/dist/lib/node/testing/index.cjs +1109 -151
  15. package/dist/lib/node/testing/index.cjs.map +4 -4
  16. package/dist/types/src/swarm/connection.d.ts +6 -0
  17. package/dist/types/src/swarm/connection.d.ts.map +1 -1
  18. package/dist/types/src/swarm/peer.d.ts.map +1 -1
  19. package/dist/types/src/testing/test-builder.d.ts +5 -2
  20. package/dist/types/src/testing/test-builder.d.ts.map +1 -1
  21. package/dist/types/src/transport/datachannel/index.browser.d.ts +15 -0
  22. package/dist/types/src/transport/datachannel/index.browser.d.ts.map +1 -0
  23. package/dist/types/src/transport/datachannel/index.d.ts +8 -0
  24. package/dist/types/src/transport/datachannel/index.d.ts.map +1 -0
  25. package/dist/types/src/transport/datachannel/rtc-data-channel.d.ts +29 -0
  26. package/dist/types/src/transport/datachannel/rtc-data-channel.d.ts.map +1 -0
  27. package/dist/types/src/transport/datachannel/rtc-events.d.ts +9 -0
  28. package/dist/types/src/transport/datachannel/rtc-events.d.ts.map +1 -0
  29. package/dist/types/src/transport/datachannel/rtc-ice-candidate.d.ts +22 -0
  30. package/dist/types/src/transport/datachannel/rtc-ice-candidate.d.ts.map +1 -0
  31. package/dist/types/src/transport/datachannel/rtc-peer-connection.d.ts +47 -0
  32. package/dist/types/src/transport/datachannel/rtc-peer-connection.d.ts.map +1 -0
  33. package/dist/types/src/transport/datachannel/rtc-peer-connection.test.d.ts +2 -0
  34. package/dist/types/src/transport/datachannel/rtc-peer-connection.test.d.ts.map +1 -0
  35. package/dist/types/src/transport/datachannel/rtc-session-description.d.ts +10 -0
  36. package/dist/types/src/transport/datachannel/rtc-session-description.d.ts.map +1 -0
  37. package/dist/types/src/transport/index.d.ts +5 -3
  38. package/dist/types/src/transport/index.d.ts.map +1 -1
  39. package/dist/types/src/transport/libdatachannel-transport.d.ts +35 -0
  40. package/dist/types/src/transport/libdatachannel-transport.d.ts.map +1 -0
  41. package/dist/types/src/transport/libdatachannel-transport.test.d.ts +2 -0
  42. package/dist/types/src/transport/libdatachannel-transport.test.d.ts.map +1 -0
  43. package/dist/types/src/transport/simplepeer-simple-peer.d.ts +2 -0
  44. package/dist/types/src/transport/simplepeer-simple-peer.d.ts.map +1 -0
  45. package/dist/types/src/transport/simplepeer-transport-proxy-test.d.ts +2 -0
  46. package/dist/types/src/transport/simplepeer-transport-proxy-test.d.ts.map +1 -0
  47. package/dist/types/src/transport/{webrtc-transport-proxy.d.ts → simplepeer-transport-proxy.d.ts} +5 -5
  48. package/dist/types/src/transport/simplepeer-transport-proxy.d.ts.map +1 -0
  49. package/dist/types/src/transport/{webrtc-transport-service.d.ts → simplepeer-transport-service.d.ts} +2 -2
  50. package/dist/types/src/transport/simplepeer-transport-service.d.ts.map +1 -0
  51. package/dist/types/src/transport/{webrtc-transport.d.ts → simplepeer-transport.d.ts} +8 -8
  52. package/dist/types/src/transport/simplepeer-transport.d.ts.map +1 -0
  53. package/dist/types/src/transport/simplepeer-transport.test.d.ts +2 -0
  54. package/dist/types/src/transport/simplepeer-transport.test.d.ts.map +1 -0
  55. package/dist/types/src/transport/transport.d.ts +6 -0
  56. package/dist/types/src/transport/transport.d.ts.map +1 -1
  57. package/dist/types/src/wire-protocol.d.ts +3 -2
  58. package/dist/types/src/wire-protocol.d.ts.map +1 -1
  59. package/package.json +25 -20
  60. package/src/connection-log.ts +1 -1
  61. package/src/swarm/connection.test.ts +8 -3
  62. package/src/swarm/connection.ts +58 -6
  63. package/src/swarm/peer.ts +4 -0
  64. package/src/swarm/swarm.test.ts +3 -2
  65. package/src/testing/test-builder.ts +72 -41
  66. package/src/transport/datachannel/README.md +2 -0
  67. package/src/transport/datachannel/index.browser.ts +8 -0
  68. package/src/transport/datachannel/index.ts +17 -0
  69. package/src/transport/datachannel/rtc-data-channel.ts +148 -0
  70. package/src/transport/datachannel/rtc-events.ts +23 -0
  71. package/src/transport/datachannel/rtc-ice-candidate.ts +54 -0
  72. package/src/transport/datachannel/rtc-peer-connection.test.ts +112 -0
  73. package/src/transport/datachannel/rtc-peer-connection.ts +347 -0
  74. package/src/transport/datachannel/rtc-session-description.ts +23 -0
  75. package/src/transport/index.ts +5 -3
  76. package/src/transport/libdatachannel-transport.test.ts +99 -0
  77. package/src/transport/libdatachannel-transport.ts +252 -0
  78. package/src/transport/{webrtc-transport-proxy.test.ts → simplepeer-transport-proxy-test.ts} +15 -15
  79. package/src/transport/{webrtc-transport-proxy.ts → simplepeer-transport-proxy.ts} +8 -8
  80. package/src/transport/{webrtc-transport-service.ts → simplepeer-transport-service.ts} +4 -4
  81. package/src/transport/{webrtc-transport.test.ts → simplepeer-transport.test.ts} +5 -5
  82. package/src/transport/{webrtc-transport.ts → simplepeer-transport.ts} +13 -27
  83. package/src/transport/transport.ts +7 -0
  84. package/src/wire-protocol.ts +8 -4
  85. package/dist/lib/browser/chunk-UAB4ONRL.mjs.map +0 -7
  86. package/dist/types/src/transport/webrtc-simple-peer.test.d.ts +0 -2
  87. package/dist/types/src/transport/webrtc-simple-peer.test.d.ts.map +0 -1
  88. package/dist/types/src/transport/webrtc-transport-proxy.d.ts.map +0 -1
  89. package/dist/types/src/transport/webrtc-transport-proxy.test.d.ts +0 -2
  90. package/dist/types/src/transport/webrtc-transport-proxy.test.d.ts.map +0 -1
  91. package/dist/types/src/transport/webrtc-transport-service.d.ts.map +0 -1
  92. package/dist/types/src/transport/webrtc-transport.d.ts.map +0 -1
  93. package/dist/types/src/transport/webrtc-transport.test.d.ts +0 -2
  94. package/dist/types/src/transport/webrtc-transport.test.d.ts.map +0 -1
  95. /package/src/transport/{webrtc-simple-peer.test.ts → simplepeer-simple-peer.ts} +0 -0
@@ -0,0 +1,252 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { Duplex } from 'stream';
6
+
7
+ import { Event, Trigger, synchronized } from '@dxos/async';
8
+ import { ErrorStream } from '@dxos/debug';
9
+ import { log } from '@dxos/log';
10
+ import { Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
11
+
12
+ import { type PeerConnection } from './datachannel/rtc-peer-connection';
13
+ import { Transport, TransportFactory } from './transport';
14
+
15
+ export type LibDataChannelTransportParams = {
16
+ initiator: boolean;
17
+ stream: NodeJS.ReadWriteStream;
18
+ webrtcConfig?: RTCConfiguration;
19
+ sendSignal: (signal: Signal) => Promise<void>;
20
+ };
21
+
22
+ const DATACHANNEL_LABEL = 'dxos.mesh.transport';
23
+ const MAX_BUFFERED_AMOUNT = 64 * 1024;
24
+
25
+ // https://viblast.com/blog/2015/2/5/webrtc-data-channel-message-size/
26
+ const MAX_MESSAGE_SIZE = 64 * 1024;
27
+
28
+ /**
29
+ * Transport
30
+ */
31
+ export class LibDataChannelTransport implements Transport {
32
+ private _closed = false;
33
+ readonly closed = new Event();
34
+ private _connected = false;
35
+ readonly connected = new Event();
36
+ readonly errors = new ErrorStream();
37
+ private readonly _peer: Promise<PeerConnection>;
38
+ private _channel!: RTCDataChannel;
39
+ private _stream!: Duplex;
40
+
41
+ private readonly _readyForCandidates = new Trigger();
42
+ private _writeCallback: (() => void) | null = null;
43
+
44
+ constructor(private readonly params: LibDataChannelTransportParams) {
45
+ this._peer = (async () => {
46
+ const { RTCPeerConnection: PeerConnection } = await import('./datachannel');
47
+ if (this._closed) {
48
+ this.errors.raise(new Error('connection already closed'));
49
+ }
50
+ const peer = new PeerConnection(params.webrtcConfig);
51
+
52
+ peer.onicecandidateerror = (event) => {
53
+ log.error('peer.onicecandidateerror', { event });
54
+ };
55
+
56
+ peer.onconnectionstatechange = (event) => {
57
+ log.debug('peer.onconnectionstatechange', {
58
+ event,
59
+ peerConnectionState: peer.connectionState,
60
+ transportConnectionState: this._connected,
61
+ });
62
+ // TODO(nf): throw error if datachannel does not connect after some time?
63
+ };
64
+
65
+ peer.onicecandidate = async (event) => {
66
+ log.debug('peer.onicecandidate', { event });
67
+ if (event.candidate) {
68
+ try {
69
+ await params.sendSignal({
70
+ payload: {
71
+ data: {
72
+ type: 'candidate',
73
+ candidate: {
74
+ candidate: event.candidate.candidate,
75
+ // these fields never seem to be not null, but connecting to Chrome doesn't work if they are
76
+ sdpMLineIndex: event.candidate.sdpMLineIndex ?? 0,
77
+ sdpMid: event.candidate.sdpMid ?? 0,
78
+ },
79
+ },
80
+ },
81
+ });
82
+ } catch (err) {
83
+ log.warn('signaling errror', { err });
84
+ }
85
+ }
86
+ };
87
+ if (params.initiator) {
88
+ peer
89
+ .createOffer()
90
+ .then(async (offer) => {
91
+ if (peer.connectionState !== 'connecting') {
92
+ log.error('i am initiator but peer not in state connecting', { peer });
93
+ this.errors.raise(new Error('invalid state: peer is initiator, but other peer not in state connecting'));
94
+ }
95
+ log.debug(`im the initiator, creating offer, peer is in state ${peer.connectionState}`, { offer });
96
+ await peer.setLocalDescription(offer);
97
+ await params.sendSignal({ payload: { data: { type: offer.type, sdp: offer.sdp } } });
98
+ return offer;
99
+ })
100
+ .catch((err) => {
101
+ this.errors.raise(err);
102
+ });
103
+ this.handleChannel(peer.createDataChannel(DATACHANNEL_LABEL));
104
+ log.debug('created data channel');
105
+ peer.ondatachannel = (event) => {
106
+ this.errors.raise(new Error('got ondatachannel when i am the initiator?'));
107
+ };
108
+ } else {
109
+ peer.ondatachannel = (event) => {
110
+ log.debug('peer.ondatachannel (non-initiator)', { event });
111
+ // TODO(nf): should the label contain some identifier?
112
+ if (event.channel.label !== DATACHANNEL_LABEL) {
113
+ this.errors.raise(new Error(`unexpected channel label ${event.channel.label}`));
114
+ }
115
+ this.handleChannel(event.channel);
116
+ };
117
+ }
118
+
119
+ return peer;
120
+ })();
121
+ }
122
+
123
+ private handleChannel(dataChannel: RTCDataChannel) {
124
+ this._channel = dataChannel;
125
+ this._channel.onopen = () => {
126
+ log.debug('dataChannel.onopen');
127
+ const duplex = new Duplex({
128
+ read: () => {},
129
+ write: (chunk, encoding, callback) => {
130
+ // todo wait to open
131
+
132
+ if (chunk.length > MAX_MESSAGE_SIZE) {
133
+ this.errors.raise(new Error(`message too large: ${chunk.length} > ${MAX_MESSAGE_SIZE}`));
134
+ }
135
+ dataChannel.send(chunk);
136
+
137
+ if (this._channel.bufferedAmount > MAX_BUFFERED_AMOUNT) {
138
+ if (this._writeCallback !== null) {
139
+ log.error("consumer trying to write before we're ready for more data");
140
+ }
141
+ this._writeCallback = callback;
142
+ } else {
143
+ callback();
144
+ }
145
+ },
146
+ });
147
+
148
+ duplex.pipe(this.params.stream).pipe(duplex);
149
+ this._stream = duplex;
150
+ this._connected = true;
151
+ this.connected.emit();
152
+ };
153
+
154
+ this._channel.onerror = async (err) => {
155
+ this.errors.raise(new Error('channel error: ' + err.toString()));
156
+ await this._close();
157
+ };
158
+ this._channel.onclose = async (err) => {
159
+ log.info('channel onclose', { err });
160
+ await this._close();
161
+ };
162
+ this._channel.onmessage = (event) => {
163
+ let data = event.data;
164
+ if (data instanceof ArrayBuffer) {
165
+ data = Buffer.from(data);
166
+ }
167
+ this._stream.push(data);
168
+ };
169
+
170
+ this._channel.onbufferedamountlow = () => {
171
+ const cb = this._writeCallback;
172
+ this._writeCallback = null;
173
+ cb?.();
174
+ };
175
+ }
176
+
177
+ @synchronized
178
+ private async _close() {
179
+ if (this._closed) {
180
+ return;
181
+ }
182
+ await this._disconnectStreams();
183
+ this._closed = true;
184
+ this.closed.emit();
185
+ }
186
+
187
+ signal(signal: Signal): void {
188
+ this._peer
189
+ .then(async (peer) => {
190
+ const data = signal.payload.data;
191
+ switch (data.type) {
192
+ case 'offer': {
193
+ if ((await this._peer).connectionState !== 'new') {
194
+ log.error('received offer but peer not in state new', { peer });
195
+ this.errors.raise(new Error('invalid signalling state: received offer when peer is not in state new'));
196
+ break;
197
+ }
198
+ try {
199
+ await peer.setRemoteDescription({ type: data.type, sdp: data.sdp });
200
+ const answer = await peer.createAnswer();
201
+ await peer.setLocalDescription(answer);
202
+ await this.params.sendSignal({ payload: { data: { type: answer.type, sdp: answer.sdp } } });
203
+ this._readyForCandidates.wake();
204
+ } catch (err) {
205
+ log.error("can't handle offer from signalling server", { err });
206
+ this.errors.raise(new Error('error handling offer'));
207
+ }
208
+ break;
209
+ }
210
+
211
+ case 'answer':
212
+ try {
213
+ await peer.setRemoteDescription({ type: data.type, sdp: data.sdp });
214
+ this._readyForCandidates.wake();
215
+ } catch (err) {
216
+ log.error("can't handle answer from signalling server", { err });
217
+ this.errors.raise(new Error('error handling answer'));
218
+ }
219
+ break;
220
+
221
+ case 'candidate':
222
+ await this._readyForCandidates.wait();
223
+ await peer.addIceCandidate({ candidate: data.candidate.candidate });
224
+ break;
225
+
226
+ default:
227
+ log.error('unhandled signal type', { type: data.type, signal });
228
+ this.errors.raise(new Error(`unhandled signal type ${data.type}`));
229
+ }
230
+ })
231
+ .catch((err) => {
232
+ log.catch(err);
233
+ });
234
+ }
235
+
236
+ // TODO(nf): add classmethod to call node-datachannel.cleanup() when all instances have been destroyed?
237
+ async destroy(): Promise<void> {
238
+ await this._close();
239
+ }
240
+
241
+ private async _disconnectStreams() {
242
+ this.params.stream.unpipe?.(this._stream)?.unpipe?.(this.params.stream);
243
+ }
244
+ }
245
+
246
+ export const createLibDataChannelTransportFactory = (webrtcConfig?: any): TransportFactory => ({
247
+ createTransport: (params) =>
248
+ new LibDataChannelTransport({
249
+ ...params,
250
+ webrtcConfig,
251
+ }),
252
+ });
@@ -11,10 +11,10 @@ import { Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
11
11
  import { createLinkedPorts, createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';
12
12
  import { afterAll, afterTest, beforeAll, describe, test } from '@dxos/test';
13
13
 
14
- import { WebRTCTransportProxy } from './webrtc-transport-proxy';
15
- import { WebRTCTransportService } from './webrtc-transport-service';
14
+ import { SimplePeerTransportProxy } from './simplepeer-transport-proxy';
15
+ import { SimplePeerTransportService } from './simplepeer-transport-service';
16
16
 
17
- describe('WebRTCTransportProxy', () => {
17
+ describe('SimplePeerTransportProxy', () => {
18
18
  const setupProxy = async ({
19
19
  initiator = true,
20
20
  stream = new TestStream(),
@@ -27,7 +27,7 @@ describe('WebRTCTransportProxy', () => {
27
27
  const [port1, port2] = createLinkedPorts();
28
28
 
29
29
  // Starting BridgeService
30
- const webRTCTransportService: BridgeService = new WebRTCTransportService();
30
+ const simplePeerTransportService: BridgeService = new SimplePeerTransportService();
31
31
 
32
32
  // Starting BridgeService
33
33
  const rpcService = createProtoRpcPeer({
@@ -35,7 +35,7 @@ describe('WebRTCTransportProxy', () => {
35
35
  exposed: {
36
36
  BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
37
37
  },
38
- handlers: { BridgeService: webRTCTransportService },
38
+ handlers: { BridgeService: simplePeerTransportService },
39
39
  port: port1,
40
40
  noHandshake: true,
41
41
  encodingOptions: {
@@ -59,20 +59,20 @@ describe('WebRTCTransportProxy', () => {
59
59
  await rpcClient.open();
60
60
  afterTest(() => rpcClient.close());
61
61
 
62
- const webRTCTransportProxy = new WebRTCTransportProxy({
62
+ const simplePeerTransportProxy = new SimplePeerTransportProxy({
63
63
  initiator,
64
64
  stream,
65
65
  sendSignal,
66
66
  bridgeService: rpcClient.rpc.BridgeService,
67
67
  });
68
- afterTest(async () => await webRTCTransportProxy.destroy());
68
+ afterTest(async () => await simplePeerTransportProxy.destroy());
69
69
 
70
- return { webRTCService: rpcService, webRTCTransportProxy };
70
+ return { simplePeerService: rpcService, SimplePeerTransportProxy: simplePeerTransportProxy };
71
71
  };
72
72
 
73
73
  // This doesn't clean up correctly and crashes with SIGSEGV / SIGABRT at the end. Probably an issue with wrtc package.
74
74
  test('open and close', async () => {
75
- const { webRTCTransportProxy: connection } = await setupProxy();
75
+ const { SimplePeerTransportProxy: connection } = await setupProxy();
76
76
 
77
77
  const wait = connection.closed.waitForCount(1);
78
78
  await connection.destroy();
@@ -81,7 +81,7 @@ describe('WebRTCTransportProxy', () => {
81
81
 
82
82
  test('establish connection and send data through with protocol', async () => {
83
83
  const stream1 = new TestStream();
84
- const { webRTCTransportProxy: connection1 } = await setupProxy({
84
+ const { SimplePeerTransportProxy: connection1 } = await setupProxy({
85
85
  initiator: true,
86
86
  stream: stream1,
87
87
  sendSignal: async (signal) => {
@@ -91,7 +91,7 @@ describe('WebRTCTransportProxy', () => {
91
91
  afterTest(() => connection1.errors.assertNoUnhandledErrors());
92
92
 
93
93
  const stream2 = new TestStream();
94
- const { webRTCTransportProxy: connection2 } = await setupProxy({
94
+ const { SimplePeerTransportProxy: connection2 } = await setupProxy({
95
95
  initiator: false,
96
96
  stream: stream2,
97
97
  sendSignal: async (signal) => {
@@ -109,12 +109,12 @@ describe('WebRTCTransportProxy', () => {
109
109
  beforeAll(async () => {
110
110
  const [port1, port2] = createLinkedPorts();
111
111
 
112
- const webRTCTransportService: BridgeService = new WebRTCTransportService();
112
+ const simplePeerTransportService: BridgeService = new SimplePeerTransportService();
113
113
  service = createProtoRpcPeer({
114
114
  exposed: {
115
115
  BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
116
116
  },
117
- handlers: { BridgeService: webRTCTransportService },
117
+ handlers: { BridgeService: simplePeerTransportService },
118
118
  port: port1,
119
119
  noHandshake: true,
120
120
  encodingOptions: {
@@ -143,7 +143,7 @@ describe('WebRTCTransportProxy', () => {
143
143
 
144
144
  test('establish connection and send data through with protocol', async () => {
145
145
  const stream1 = new TestStream();
146
- const proxy1 = new WebRTCTransportProxy({
146
+ const proxy1 = new SimplePeerTransportProxy({
147
147
  initiator: true,
148
148
  stream: stream1,
149
149
  sendSignal: async (signal) => {
@@ -157,7 +157,7 @@ describe('WebRTCTransportProxy', () => {
157
157
  });
158
158
 
159
159
  const stream2 = new TestStream();
160
- const proxy2 = new WebRTCTransportProxy({
160
+ const proxy2 = new SimplePeerTransportProxy({
161
161
  initiator: false,
162
162
  stream: stream2,
163
163
  sendSignal: async (signal) => {
@@ -17,7 +17,7 @@ import { arrayToBuffer } from '@dxos/util';
17
17
 
18
18
  import { Transport, TransportFactory, TransportOptions } from './transport';
19
19
 
20
- export type WebRTCTransportProxyParams = {
20
+ export type SimplePeerTransportProxyParams = {
21
21
  initiator: boolean;
22
22
  stream: NodeJS.ReadWriteStream;
23
23
  bridgeService: BridgeService;
@@ -25,7 +25,7 @@ export type WebRTCTransportProxyParams = {
25
25
  sendSignal: (signal: Signal) => Promise<void>;
26
26
  };
27
27
 
28
- export class WebRTCTransportProxy implements Transport {
28
+ export class SimplePeerTransportProxy implements Transport {
29
29
  private readonly _proxyId = PublicKey.random();
30
30
  private readonly _ctx = new Context();
31
31
 
@@ -38,7 +38,7 @@ export class WebRTCTransportProxy implements Transport {
38
38
 
39
39
  // prettier-ignore
40
40
  constructor(
41
- private readonly _params: WebRTCTransportProxyParams
41
+ private readonly _params: SimplePeerTransportProxyParams
42
42
  ) {
43
43
  this._serviceStream = this._params.bridgeService.open({
44
44
  proxyId: this._proxyId,
@@ -48,7 +48,7 @@ export class WebRTCTransportProxy implements Transport {
48
48
  this._serviceStream.waitUntilReady().then(
49
49
  () => {
50
50
  this._serviceStream.subscribe(async (event: BridgeEvent) => {
51
- log('WebRTCTransportProxy: event', event);
51
+ log('SimplePeerTransportProxy: event', event);
52
52
  if (event.connection) {
53
53
  await this._handleConnection(event.connection);
54
54
  } else if (event.data) {
@@ -142,9 +142,9 @@ export class WebRTCTransportProxy implements Transport {
142
142
  }
143
143
 
144
144
  // TODO(burdon): Why is this named Proxy?
145
- export class WebRTCTransportProxyFactory implements TransportFactory {
145
+ export class SimplePeerTransportProxyFactory implements TransportFactory {
146
146
  private _bridgeService: BridgeService | undefined;
147
- private _connections = new Set<WebRTCTransportProxy>();
147
+ private _connections = new Set<SimplePeerTransportProxy>();
148
148
 
149
149
  /**
150
150
  * Sets the current BridgeService to be used to open connections.
@@ -160,9 +160,9 @@ export class WebRTCTransportProxyFactory implements TransportFactory {
160
160
  }
161
161
 
162
162
  createTransport(options: TransportOptions): Transport {
163
- invariant(this._bridgeService, 'WebRTCTransportProxyFactory is not ready to open connections');
163
+ invariant(this._bridgeService, 'SimplePeerTransportProxyFactory is not ready to open connections');
164
164
 
165
- const transport = new WebRTCTransportProxy({
165
+ const transport = new SimplePeerTransportProxy({
166
166
  ...options,
167
167
  bridgeService: this._bridgeService,
168
168
  });
@@ -19,15 +19,15 @@ import {
19
19
  } from '@dxos/protocols/proto/dxos/mesh/bridge';
20
20
  import { ComplexMap } from '@dxos/util';
21
21
 
22
- import { WebRTCTransport } from './webrtc-transport';
22
+ import { SimplePeerTransport } from './simplepeer-transport';
23
23
 
24
24
  type TransportState = {
25
- transport: WebRTCTransport;
25
+ transport: SimplePeerTransport;
26
26
  stream: Duplex;
27
27
  writeCallbacks: (() => void)[];
28
28
  };
29
29
 
30
- export class WebRTCTransportService implements BridgeService {
30
+ export class SimplePeerTransportService implements BridgeService {
31
31
  private readonly transports = new ComplexMap<PublicKey, TransportState>(PublicKey.hash);
32
32
 
33
33
  // prettier-ignore
@@ -51,7 +51,7 @@ export class WebRTCTransportService implements BridgeService {
51
51
  },
52
52
  });
53
53
 
54
- const transport = new WebRTCTransport({
54
+ const transport = new SimplePeerTransport({
55
55
  initiator: request.initiator,
56
56
  stream: duplex,
57
57
  webrtcConfig: this._webrtcConfig,
@@ -7,12 +7,12 @@ import { Duplex } from 'stream';
7
7
  import { sleep, TestStream } from '@dxos/async';
8
8
  import { afterTest, describe, test } from '@dxos/test';
9
9
 
10
- import { WebRTCTransport } from './webrtc-transport';
10
+ import { SimplePeerTransport } from './simplepeer-transport';
11
11
 
12
- describe('WebRTCTransport', () => {
12
+ describe('SimplePeerTransport', () => {
13
13
  // This doesn't clean up correctly and crashes with SIGSEGV / SIGABRT at the end. Probably an issue with wrtc package.
14
14
  test('open and close', async () => {
15
- const connection = new WebRTCTransport({
15
+ const connection = new SimplePeerTransport({
16
16
  initiator: true,
17
17
  stream: new Duplex(),
18
18
  sendSignal: async () => {},
@@ -27,7 +27,7 @@ describe('WebRTCTransport', () => {
27
27
 
28
28
  test('establish connection and send data through with protocol', async () => {
29
29
  const stream1 = new TestStream();
30
- const connection1 = new WebRTCTransport({
30
+ const connection1 = new SimplePeerTransport({
31
31
  initiator: true,
32
32
  stream: stream1,
33
33
  sendSignal: async (signal) => {
@@ -39,7 +39,7 @@ describe('WebRTCTransport', () => {
39
39
  afterTest(() => connection1.errors.assertNoUnhandledErrors());
40
40
 
41
41
  const stream2 = new TestStream();
42
- const connection2 = new WebRTCTransport({
42
+ const connection2 = new SimplePeerTransport({
43
43
  initiator: false,
44
44
  stream: stream2,
45
45
  sendSignal: async (signal) => {
@@ -3,10 +3,10 @@
3
3
  //
4
4
 
5
5
  import SimplePeerConstructor, { Instance as SimplePeer } from 'simple-peer';
6
+ import invariant from 'tiny-invariant';
6
7
 
7
8
  import { Event } from '@dxos/async';
8
9
  import { ErrorStream, raise } from '@dxos/debug';
9
- import { invariant } from '@dxos/invariant';
10
10
  import { PublicKey } from '@dxos/keys';
11
11
  import { log } from '@dxos/log';
12
12
  import { trace } from '@dxos/protocols';
@@ -15,47 +15,34 @@ import { Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
15
15
  import { Transport, TransportFactory } from './transport';
16
16
  import { wrtc } from './webrtc';
17
17
 
18
- export type WebRTCTransportParams = {
18
+ export type SimplePeerTransportParams = {
19
19
  initiator: boolean;
20
- // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection
21
- webrtcConfig?: any;
22
20
  stream: NodeJS.ReadWriteStream;
23
- // TODO(burdon): Rename onSignal.
21
+ webrtcConfig?: any;
24
22
  sendSignal: (signal: Signal) => Promise<void>;
25
23
  };
26
24
 
27
- // TODO(burdon): Refs:
28
- // https://webrtc.github.io/samples
29
- // Simple peer discord.
30
-
31
25
  /**
32
- * Implements WebRTC transport using simple-peer (used by WebTorrent).
26
+ * Implements Transport for WebRTC. Uses simple-peer under the hood.
33
27
  */
34
- export class WebRTCTransport implements Transport {
35
- private readonly _instanceId = PublicKey.random().toHex();
28
+ export class SimplePeerTransport implements Transport {
36
29
  private readonly _peer: SimplePeer;
37
-
38
30
  private _closed = false;
31
+
39
32
  readonly closed = new Event();
40
33
  readonly connected = new Event();
41
34
  readonly errors = new ErrorStream();
42
35
 
43
- constructor(private readonly params: WebRTCTransportParams) {
36
+ private readonly _instanceId = PublicKey.random().toHex();
37
+
38
+ constructor(private readonly params: SimplePeerTransportParams) {
44
39
  log.trace('dxos.mesh.webrtc-transport.constructor', trace.begin({ id: this._instanceId }));
45
40
  log('created connection', params);
46
-
47
- // https://www.npmjs.com/package/simple-peer#api
48
- // NOTE: Set localStorage.debug = 'simple-peer*' to enable debug logging. (Or show verbose in Chrome).
49
- // View throughput via: chrome://webrtc-internals (data-channel)
50
41
  this._peer = new SimplePeerConstructor({
42
+ channelName: 'dxos.mesh.transport',
51
43
  initiator: this.params.initiator,
52
- config: this.params.webrtcConfig,
53
- // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel
54
- channelConfig: {
55
- protocol: 'dxos.mesh',
56
- },
57
- // Custom WebRTC implementation (for Node); otherwise get-browser-rtc.
58
44
  wrtc: SimplePeerConstructor.WEBRTC_SUPPORT ? undefined : wrtc ?? raise(new Error('wrtc not available')),
45
+ config: this.params.webrtcConfig,
59
46
  });
60
47
 
61
48
  this._peer.on('signal', async (data) => {
@@ -119,10 +106,9 @@ export class WebRTCTransport implements Transport {
119
106
  }
120
107
  }
121
108
 
122
- // TODO(dmaretskyi): Convert to class.
123
- export const createWebRTCTransportFactory = (webrtcConfig?: any): TransportFactory => ({
109
+ export const createSimplePeerTransportFactory = (webrtcConfig?: any): TransportFactory => ({
124
110
  createTransport: (params) =>
125
- new WebRTCTransport({
111
+ new SimplePeerTransport({
126
112
  ...params,
127
113
  webrtcConfig,
128
114
  }),
@@ -6,6 +6,13 @@ import { Event } from '@dxos/async';
6
6
  import { ErrorStream } from '@dxos/debug';
7
7
  import { Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
8
8
 
9
+ export enum TransportKind {
10
+ SIMPLE_PEER = 'SIMPLE_PEER',
11
+ LIBDATACHANNEL = 'LIBDATACHANNEL',
12
+ SIMPLE_PEER_PROXY = 'SIMPLE_PEER_PROXY',
13
+ MEMORY = 'MEMORY',
14
+ }
15
+
9
16
  /**
10
17
  * Abstraction over a P2P connection transport. Currently either WebRTC or in-memory.
11
18
  */
@@ -23,8 +23,9 @@ export type WireProtocolProvider = (params: WireProtocolParams) => WireProtocol;
23
23
  export interface WireProtocol {
24
24
  stream: Duplex;
25
25
 
26
- initialize(): Promise<void>;
27
- destroy(): Promise<void>;
26
+ open(): Promise<void>;
27
+ close(): Promise<void>;
28
+ abort(): Promise<void>;
28
29
  }
29
30
 
30
31
  /**
@@ -39,13 +40,16 @@ export const createTeleportProtocolFactory = (
39
40
  const teleport = new Teleport(params);
40
41
  return {
41
42
  stream: teleport.stream,
42
- initialize: async () => {
43
+ open: async () => {
43
44
  await teleport.open();
44
45
  await onConnection(teleport);
45
46
  },
46
- destroy: async () => {
47
+ close: async () => {
47
48
  await teleport.close();
48
49
  },
50
+ abort: async () => {
51
+ await teleport.abort();
52
+ },
49
53
  };
50
54
  };
51
55
  };