@dxos/network-manager 2.33.5-dev.ebc105f7 → 2.33.5

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 (92) hide show
  1. package/dist/browser-mocha/bundle.js +415 -281
  2. package/dist/src/index.js +5 -1
  3. package/dist/src/index.js.map +1 -1
  4. package/dist/src/network-manager.blueprint-test.js +5 -1
  5. package/dist/src/network-manager.blueprint-test.js.map +1 -1
  6. package/dist/src/network-manager.d.ts +1 -1
  7. package/dist/src/network-manager.d.ts.map +1 -1
  8. package/dist/src/network-manager.js +19 -17
  9. package/dist/src/network-manager.js.map +1 -1
  10. package/dist/src/signal/in-memory-signal-manager.d.ts +2 -2
  11. package/dist/src/signal/in-memory-signal-manager.d.ts.map +1 -1
  12. package/dist/src/signal/in-memory-signal-manager.js +2 -1
  13. package/dist/src/signal/in-memory-signal-manager.js.map +1 -1
  14. package/dist/src/signal/index.d.ts +2 -1
  15. package/dist/src/signal/index.d.ts.map +1 -1
  16. package/dist/src/signal/index.js +7 -2
  17. package/dist/src/signal/index.js.map +1 -1
  18. package/dist/src/signal/signal-api.d.ts +8 -66
  19. package/dist/src/signal/signal-api.d.ts.map +1 -1
  20. package/dist/src/signal/signal-api.js +2 -190
  21. package/dist/src/signal/signal-api.js.map +1 -1
  22. package/dist/src/signal/signal-client.d.ts +54 -0
  23. package/dist/src/signal/signal-client.d.ts.map +1 -0
  24. package/dist/src/signal/signal-client.js +198 -0
  25. package/dist/src/signal/signal-client.js.map +1 -0
  26. package/dist/src/signal/signal-client.test.d.ts +2 -0
  27. package/dist/src/signal/signal-client.test.d.ts.map +1 -0
  28. package/dist/src/signal/{signal-api.test.js → signal-client.test.js} +27 -27
  29. package/dist/src/signal/signal-client.test.js.map +1 -0
  30. package/dist/src/signal/{interface.d.ts → signal-manager.d.ts} +16 -5
  31. package/dist/src/signal/signal-manager.d.ts.map +1 -0
  32. package/dist/src/signal/{interface.js → signal-manager.js} +1 -1
  33. package/dist/src/signal/signal-manager.js.map +1 -0
  34. package/dist/src/signal/websocket-rpc.d.ts.map +1 -1
  35. package/dist/src/signal/websocket-rpc.js.map +1 -1
  36. package/dist/src/signal/websocket-signal-manager.d.ts +4 -4
  37. package/dist/src/signal/websocket-signal-manager.d.ts.map +1 -1
  38. package/dist/src/signal/websocket-signal-manager.js +4 -6
  39. package/dist/src/signal/websocket-signal-manager.js.map +1 -1
  40. package/dist/src/swarm/connection.d.ts +4 -1
  41. package/dist/src/swarm/connection.d.ts.map +1 -1
  42. package/dist/src/swarm/connection.js +6 -3
  43. package/dist/src/swarm/connection.js.map +1 -1
  44. package/dist/src/swarm/index.js +5 -1
  45. package/dist/src/swarm/index.js.map +1 -1
  46. package/dist/src/swarm/swarm.d.ts +4 -6
  47. package/dist/src/swarm/swarm.d.ts.map +1 -1
  48. package/dist/src/swarm/swarm.js +11 -12
  49. package/dist/src/swarm/swarm.js.map +1 -1
  50. package/dist/src/swarm/swarm.test.js +17 -14
  51. package/dist/src/swarm/swarm.test.js.map +1 -1
  52. package/dist/src/testing/test-protocol.d.ts +1 -0
  53. package/dist/src/testing/test-protocol.d.ts.map +1 -1
  54. package/dist/src/topology/index.js +5 -1
  55. package/dist/src/topology/index.js.map +1 -1
  56. package/dist/src/transport/in-memory-transport.d.ts +1 -1
  57. package/dist/src/transport/in-memory-transport.d.ts.map +1 -1
  58. package/dist/src/transport/in-memory-transport.js +2 -2
  59. package/dist/src/transport/in-memory-transport.js.map +1 -1
  60. package/dist/src/transport/index.js +5 -1
  61. package/dist/src/transport/index.js.map +1 -1
  62. package/dist/src/transport/transport.d.ts +1 -1
  63. package/dist/src/transport/transport.d.ts.map +1 -1
  64. package/dist/src/transport/webrtc-transport.d.ts +4 -4
  65. package/dist/src/transport/webrtc-transport.d.ts.map +1 -1
  66. package/dist/src/transport/webrtc-transport.js +8 -7
  67. package/dist/src/transport/webrtc-transport.js.map +1 -1
  68. package/dist/src/transport/webrtc-transport.test.js +4 -4
  69. package/dist/tsconfig.tsbuildinfo +1 -1
  70. package/package.json +13 -13
  71. package/src/network-manager.ts +23 -23
  72. package/src/signal/in-memory-signal-manager.ts +6 -5
  73. package/src/signal/index.ts +2 -1
  74. package/src/signal/signal-api.ts +13 -246
  75. package/src/signal/{signal-api.test.ts → signal-client.test.ts} +27 -26
  76. package/src/signal/signal-client.ts +235 -0
  77. package/src/signal/signal-manager.ts +39 -0
  78. package/src/signal/websocket-rpc.ts +3 -6
  79. package/src/signal/websocket-signal-manager.ts +11 -15
  80. package/src/swarm/connection.ts +7 -6
  81. package/src/swarm/swarm.test.ts +32 -25
  82. package/src/swarm/swarm.ts +16 -15
  83. package/src/transport/in-memory-transport.ts +2 -2
  84. package/src/transport/transport.ts +13 -17
  85. package/src/transport/webrtc-transport.test.ts +5 -5
  86. package/src/transport/webrtc-transport.ts +6 -5
  87. package/dist/src/signal/interface.d.ts.map +0 -1
  88. package/dist/src/signal/interface.js.map +0 -1
  89. package/dist/src/signal/signal-api.test.d.ts +0 -2
  90. package/dist/src/signal/signal-api.test.d.ts.map +0 -1
  91. package/dist/src/signal/signal-api.test.js.map +0 -1
  92. package/src/signal/interface.ts +0 -32
@@ -15,7 +15,7 @@ import { ConnectionLog } from './connection-log';
15
15
  import { InMemorySignalManager, SignalManager, SignalApi, WebsocketSignalManager } from './signal';
16
16
  import { Swarm, SwarmMapper } from './swarm';
17
17
  import { Topology } from './topology';
18
- import { createWebRtcTransportFactory, inMemoryTransportFactory } from './transport';
18
+ import { createWebRTCTransportFactory, inMemoryTransportFactory } from './transport';
19
19
 
20
20
  export type ProtocolProvider = (opts: { channel: Buffer, initiator: boolean}) => Protocol;
21
21
 
@@ -37,7 +37,7 @@ export class NetworkManager {
37
37
  private readonly _ice?: any[];
38
38
  private readonly _swarms = new ComplexMap<PublicKey, Swarm>(key => key.toHex());
39
39
  private readonly _maps = new ComplexMap<PublicKey, SwarmMapper>(key => key.toHex());
40
- private readonly _signal: SignalManager;
40
+ private readonly _signalManager: SignalManager;
41
41
  private readonly _connectionLog?: ConnectionLog;
42
42
 
43
43
  public readonly topicsUpdated = new Event<void>();
@@ -47,13 +47,15 @@ export class NetworkManager {
47
47
 
48
48
  const onOffer = async (message: SignalApi.SignalMessage) =>
49
49
  await this._swarms.get(message.topic)?.onOffer(message) ?? { accept: false };
50
- this._signal = options.signal
50
+
51
+ this._signalManager = options.signal
51
52
  ? new WebsocketSignalManager(options.signal, onOffer)
52
53
  : new InMemorySignalManager(onOffer);
53
54
 
54
- this._signal.peerCandidatesChanged.on(([topic, candidates]) =>
55
- this._swarms.get(topic)?.onPeerCandidatesChanged(candidates));
56
- this._signal.onSignal.on(msg => this._swarms.get(msg.topic)?.onSignal(msg));
55
+ this._signalManager.peerCandidatesChanged
56
+ .on(([topic, candidates]) => this._swarms.get(topic)?.onPeerCandidatesChanged(candidates));
57
+ this._signalManager.onSignal
58
+ .on(msg => this._swarms.get(msg.topic)?.onSignal(msg));
57
59
 
58
60
  if (options.log) {
59
61
  this._connectionLog = new ConnectionLog();
@@ -61,9 +63,10 @@ export class NetworkManager {
61
63
  }
62
64
 
63
65
  get signal () {
64
- return this._signal;
66
+ return this._signalManager;
65
67
  }
66
68
 
69
+ // TODO(burdon): Reconcile with "discoveryKey".
67
70
  get topics () {
68
71
  return Array.from(this._swarms.keys());
69
72
  }
@@ -82,12 +85,12 @@ export class NetworkManager {
82
85
 
83
86
  joinProtocolSwarm (options: SwarmOptions) {
84
87
  // TODO(burdon): Use TS to constrain properties.
85
- assert(typeof options === 'object', 'Incorrect arguments format.');
88
+ assert(typeof options === 'object');
86
89
  const { topic, peerId, topology, protocol, presence } = options;
87
- assert(PublicKey.isPublicKey(topic), 'Incorrect arguments format.');
88
- assert(PublicKey.isPublicKey(peerId), 'Incorrect arguments format.');
89
- assert(topology, 'Incorrect arguments format.');
90
- assert(typeof protocol === 'function', 'Incorrect arguments format.');
90
+ assert(PublicKey.isPublicKey(topic));
91
+ assert(PublicKey.isPublicKey(peerId));
92
+ assert(topology);
93
+ assert(typeof protocol === 'function');
91
94
 
92
95
  log(`Join ${options.topic} as ${options.peerId} with ${options.topology.toString()} topology.`);
93
96
  if (this._swarms.has(topic)) {
@@ -95,21 +98,17 @@ export class NetworkManager {
95
98
  GreetingCommandPlugin.EXTENSION_NAME, ERR_GREET_ALREADY_CONNECTED_TO_SWARM, `Already connected to swarm ${topic}`);
96
99
  }
97
100
 
101
+ // TODO(burdon): Require factory (i.e., don't make InMemorySignalManager by default).
98
102
  // TODO(burdon): Bundle common transport related classes.
99
- const transportFactory = this._signal instanceof InMemorySignalManager
100
- ? inMemoryTransportFactory : createWebRtcTransportFactory({ iceServers: this._ice });
103
+ const transportFactory = this._signalManager instanceof InMemorySignalManager
104
+ ? inMemoryTransportFactory : createWebRTCTransportFactory({ iceServers: this._ice });
101
105
 
102
106
  const swarm = new Swarm(
103
107
  topic,
104
108
  peerId,
105
109
  topology,
106
110
  protocol,
107
-
108
- // TODO(burdon): Merge.
109
- async offer => this._signal.offer(offer),
110
- async msg => this._signal.signal(msg),
111
- () => this._signal.lookup(topic),
112
-
111
+ this._signalManager,
113
112
  transportFactory,
114
113
  options.label
115
114
  );
@@ -119,7 +118,7 @@ export class NetworkManager {
119
118
  });
120
119
 
121
120
  this._swarms.set(topic, swarm);
122
- this._signal.join(topic, peerId);
121
+ this._signalManager.join(topic, peerId);
123
122
  this._maps.set(topic, new SwarmMapper(swarm, presence));
124
123
 
125
124
  this.topicsUpdated.emit();
@@ -139,7 +138,7 @@ export class NetworkManager {
139
138
  const map = this._maps.get(topic)!;
140
139
  const swarm = this._swarms.get(topic)!;
141
140
 
142
- this._signal.leave(topic, swarm.ownPeerId);
141
+ this._signalManager.leave(topic, swarm.ownPeerId);
143
142
 
144
143
  map.destroy();
145
144
  this._maps.delete(topic);
@@ -168,7 +167,7 @@ export class NetworkManager {
168
167
  });
169
168
  }
170
169
 
171
- await this._signal.destroy();
170
+ await this._signalManager.destroy();
172
171
  }
173
172
  }
174
173
 
@@ -177,6 +176,7 @@ export interface SwarmOptions {
177
176
  * Swarm topic.
178
177
  */
179
178
  topic: PublicKey,
179
+
180
180
  /**
181
181
  * This node's peer id.
182
182
  */
@@ -8,16 +8,13 @@ import { Event } from '@dxos/async';
8
8
  import { PublicKey } from '@dxos/crypto';
9
9
  import { ComplexMap, ComplexSet } from '@dxos/util';
10
10
 
11
- import { SignalManager } from './interface';
12
11
  import { SignalApi } from './signal-api';
12
+ import { SignalManager } from './signal-manager';
13
13
 
14
14
  export class InMemorySignalManager implements SignalManager {
15
15
  readonly statusChanged = new Event<SignalApi.Status[]>();
16
-
17
16
  readonly commandTrace = new Event<SignalApi.CommandTrace>();
18
-
19
17
  readonly peerCandidatesChanged = new Event<[topic: PublicKey, candidates: PublicKey[]]>()
20
-
21
18
  readonly onSignal = new Event<SignalApi.SignalMessage>();
22
19
 
23
20
  constructor (
@@ -32,6 +29,7 @@ export class InMemorySignalManager implements SignalManager {
32
29
  if (!state.swarms.has(topic)) {
33
30
  state.swarms.set(topic, new ComplexSet(x => x.toHex()));
34
31
  }
32
+
35
33
  state.swarms.get(topic)!.add(peerId);
36
34
  state.connections.set(peerId, this);
37
35
 
@@ -42,6 +40,7 @@ export class InMemorySignalManager implements SignalManager {
42
40
  if (!state.swarms.has(topic)) {
43
41
  state.swarms.set(topic, new ComplexSet(x => x.toHex()));
44
42
  }
43
+
45
44
  state.swarms.get(topic)!.delete(peerId);
46
45
  }
47
46
 
@@ -54,7 +53,7 @@ export class InMemorySignalManager implements SignalManager {
54
53
  return state.connections.get(msg.remoteId)!._onOffer(msg);
55
54
  }
56
55
 
57
- signal (msg: SignalApi.SignalMessage) {
56
+ async signal (msg: SignalApi.SignalMessage) {
58
57
  assert(state.connections.get(msg.remoteId), 'Peer not connected');
59
58
  state.connections.get(msg.remoteId)!.onSignal.emit(msg);
60
59
  }
@@ -62,10 +61,12 @@ export class InMemorySignalManager implements SignalManager {
62
61
  async destroy () {}
63
62
  }
64
63
 
64
+ // TODO(burdon): Remove global singleton.
65
65
  // This is global state for the in-memory signal manager.
66
66
  const state = {
67
67
  // Mapping from topic to set of peers.
68
68
  swarms: new ComplexMap<PublicKey, ComplexSet<PublicKey>>(x => x.toHex()),
69
+
69
70
  // Map of connections for each peer for signaling.
70
71
  connections: new ComplexMap<PublicKey, InMemorySignalManager>(x => x.toHex())
71
72
  };
@@ -3,7 +3,8 @@
3
3
  //
4
4
 
5
5
  export * from './in-memory-signal-manager';
6
- export * from './interface';
7
6
  export * from './signal-api';
7
+ export * from './signal-client';
8
+ export * from './signal-manager';
8
9
  export * from './websocket-rpc';
9
10
  export * from './websocket-signal-manager';
@@ -2,235 +2,11 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import debug from 'debug';
6
5
  import { SignalData } from 'simple-peer';
7
6
 
8
- import { Event } from '@dxos/async';
9
7
  import { PublicKey } from '@dxos/crypto';
10
8
 
11
- import { WebsocketRpc } from './websocket-rpc';
12
-
13
- const log = debug('dxos:network-manager:signal-api');
14
-
15
- const DEFAULT_RECONNECT_TIMEOUT = 1000;
16
-
17
- /**
18
- * Establishes a websocket connection to signal server and provides RPC methods.
19
- */
20
- export class SignalApi {
21
- private _state = SignalApi.State.CONNECTING;
22
-
23
- private _lastError?: Error;
24
-
25
- /**
26
- * Number of milliseconds after which the connection will be attempted again in case of error.
27
- */
28
- private _reconnectAfter = DEFAULT_RECONNECT_TIMEOUT;
29
-
30
- /**
31
- * Timestamp of when the connection attempt was began.
32
- */
33
- private _connectionStarted = Date.now();
34
-
35
- /**
36
- * Timestamp of last state change.
37
- */
38
- private _lastStateChange = Date.now();
39
-
40
- private _reconnectIntervalId?: NodeJS.Timeout;
41
-
42
- private _client!: WebsocketRpc;
43
-
44
- private _clientCleanup: (() => void)[] = [];
45
-
46
- readonly statusChanged = new Event<SignalApi.Status>();
47
-
48
- readonly commandTrace = new Event<SignalApi.CommandTrace>();
49
-
50
- /**
51
- * @param _host Signal server websocket URL.
52
- * @param _onOffer See `SignalApi.offer`.
53
- * @param _onSignal See `SignalApi.signal`.
54
- */
55
- constructor (
56
- private readonly _host: string,
57
- private readonly _onOffer: (message: SignalApi.SignalMessage) => Promise<SignalApi.Answer>,
58
- private readonly _onSignal: (message: SignalApi.SignalMessage) => Promise<void>
59
- ) {
60
- this._setState(SignalApi.State.CONNECTING);
61
- this._createClient();
62
- }
63
-
64
- private _setState (newState: SignalApi.State) {
65
- this._state = newState;
66
- this._lastStateChange = Date.now();
67
- log(`Signal state changed ${JSON.stringify(this.getStatus())}`);
68
- this.statusChanged.emit(this.getStatus());
69
- }
70
-
71
- private _createClient () {
72
- this._connectionStarted = Date.now();
73
- try {
74
- this._client = new WebsocketRpc(this._host);
75
- } catch (error: any) {
76
- if (this._state === SignalApi.State.RE_CONNECTING) {
77
- this._reconnectAfter *= 2;
78
- }
79
-
80
- this._lastError = error;
81
- this._setState(SignalApi.State.DISCONNECTED);
82
-
83
- this._reconnect();
84
- }
85
- this._client.addHandler('offer', (message: any) => this._onOffer({
86
- id: PublicKey.from(message.id),
87
- remoteId: PublicKey.from(message.remoteId),
88
- topic: PublicKey.from(message.topic),
89
- sessionId: PublicKey.from(message.sessionId),
90
- data: message.data
91
- }));
92
- this._client.subscribe('signal', (msg: SignalApi.SignalMessage) => this._onSignal({
93
- id: PublicKey.from(msg.id),
94
- remoteId: PublicKey.from(msg.remoteId),
95
- topic: PublicKey.from(msg.topic),
96
- sessionId: PublicKey.from(msg.sessionId),
97
- data: msg.data
98
- }));
99
-
100
- this._clientCleanup.push(this._client.connected.on(() => {
101
- log('Socket connected');
102
- this._lastError = undefined;
103
- this._reconnectAfter = DEFAULT_RECONNECT_TIMEOUT;
104
- this._setState(SignalApi.State.CONNECTED);
105
- }));
106
- this._clientCleanup.push(this._client.error.on(error => {
107
- log(`Socket error: ${error.message}`);
108
- if (this._state === SignalApi.State.CLOSED) {
109
- return;
110
- }
111
-
112
- if (this._state === SignalApi.State.RE_CONNECTING) {
113
- this._reconnectAfter *= 2;
114
- }
115
-
116
- this._lastError = error;
117
- this._setState(SignalApi.State.DISCONNECTED);
118
-
119
- this._reconnect();
120
- }));
121
- this._clientCleanup.push(this._client.disconnected.on(() => {
122
- log('Socket disconnected');
123
- // This is also called in case of error, but we already have disconnected the socket on error, so no need to do anything here.
124
- if (this._state !== SignalApi.State.CONNECTING && this._state !== SignalApi.State.RE_CONNECTING) {
125
- return;
126
- }
127
-
128
- if (this._state === SignalApi.State.RE_CONNECTING) {
129
- this._reconnectAfter *= 2;
130
- }
131
-
132
- this._setState(SignalApi.State.DISCONNECTED);
133
-
134
- this._reconnect();
135
- }));
136
- this._clientCleanup.push(this._client.commandTrace.on(trace => this.commandTrace.emit(trace)));
137
- }
138
-
139
- private _reconnect () {
140
- if (this._reconnectIntervalId !== undefined) {
141
- console.error('Signal api already reconnecting.');
142
- return;
143
- }
144
- if (this._state === SignalApi.State.CLOSED) {
145
- return;
146
- }
147
-
148
- this._reconnectIntervalId = setTimeout(() => {
149
- this._reconnectIntervalId = undefined;
150
-
151
- this._clientCleanup.forEach(cb => cb());
152
- this._clientCleanup = [];
153
-
154
- // Close client if it wasn't already closed.
155
- this._client.close().catch(() => {});
156
-
157
- this._setState(SignalApi.State.RE_CONNECTING);
158
- this._createClient();
159
- }, this._reconnectAfter);
160
- }
161
-
162
- async close () {
163
- this._clientCleanup.forEach(cb => cb());
164
- this._clientCleanup = [];
165
-
166
- if (this._reconnectIntervalId !== undefined) {
167
- clearTimeout(this._reconnectIntervalId);
168
- }
169
-
170
- await this._client.close();
171
- this._setState(SignalApi.State.CLOSED);
172
- }
173
-
174
- getStatus (): SignalApi.Status {
175
- return {
176
- host: this._host,
177
- state: this._state,
178
- error: this._lastError?.message,
179
- reconnectIn: this._reconnectAfter,
180
- connectionStarted: this._connectionStarted,
181
- lastStateChange: this._lastStateChange
182
- };
183
- }
184
-
185
- async join (topic: PublicKey, peerId: PublicKey): Promise<PublicKey[]> {
186
- const peers: Buffer[] = await this._client.call('join', {
187
- id: peerId.asBuffer(),
188
- topic: topic.asBuffer()
189
- });
190
- return peers.map(id => PublicKey.from(id));
191
- }
192
-
193
- async leave (topic: PublicKey, peerId: PublicKey): Promise<void> {
194
- await this._client.call('leave', {
195
- id: peerId.asBuffer(),
196
- topic: topic.asBuffer()
197
- });
198
- }
199
-
200
- async lookup (topic: PublicKey): Promise<PublicKey[]> {
201
- const peers: Buffer[] = await this._client.call('lookup', {
202
- topic: topic.asBuffer()
203
- });
204
- return peers.map(id => PublicKey.from(id));
205
- }
206
-
207
- /**
208
- * Routes an offer to the other peer's _onOffer callback.
209
- * @returns Other peer's _onOffer callback return value.
210
- */
211
- async offer (payload: SignalApi.SignalMessage): Promise<SignalApi.Answer> {
212
- return this._client.call('offer', {
213
- id: payload.id.asBuffer(),
214
- remoteId: payload.remoteId.asBuffer(),
215
- topic: payload.topic.asBuffer(),
216
- sessionId: payload.sessionId.asBuffer(),
217
- data: payload.data
218
- });
219
- }
220
-
221
- /**
222
- * Routes an offer to the other peer's _onSignal callback.
223
- */
224
- async signal (payload: SignalApi.SignalMessage): Promise<void> {
225
- return this._client.emit('signal', {
226
- id: payload.id.asBuffer(),
227
- remoteId: payload.remoteId.asBuffer(),
228
- topic: payload.topic.asBuffer(),
229
- sessionId: payload.sessionId.asBuffer(),
230
- data: payload.data
231
- });
232
- }
233
- }
9
+ // TODO(burdon): Define message types as protobuf.
234
10
 
235
11
  export namespace SignalApi {
236
12
  export enum State {
@@ -247,19 +23,19 @@ export namespace SignalApi {
247
23
  DISCONNECTED = 'DISCONNECTED',
248
24
 
249
25
  /** Socket was closed. */
250
- CLOSED = 'CLOSED',
26
+ CLOSED = 'CLOSED'
251
27
  }
252
28
 
253
- export interface Status {
254
- host: string,
255
- state: State,
29
+ export type Status = {
30
+ host: string
31
+ state: State
256
32
  error?: string
257
- reconnectIn: number,
33
+ reconnectIn: number
258
34
  connectionStarted: number
259
35
  lastStateChange: number
260
36
  }
261
37
 
262
- export interface CommandTrace {
38
+ export type CommandTrace = {
263
39
  messageId: string
264
40
  host: string
265
41
  incoming: boolean
@@ -270,24 +46,15 @@ export namespace SignalApi {
270
46
  error?: string
271
47
  }
272
48
 
273
- // TODO(marik-d): Define more concrete types for offer/answer.
274
- export interface SignalMessage {
275
- id: PublicKey
276
- remoteId: PublicKey,
277
- topic: PublicKey,
278
- sessionId: PublicKey,
279
- data: SignalData,
280
- }
281
-
282
- export interface OfferMessage {
49
+ export type SignalMessage = {
283
50
  id: PublicKey
284
- remoteId: PublicKey,
285
- topic: PublicKey,
286
- sessionId: PublicKey,
287
- data: SignalData,
51
+ remoteId: PublicKey
52
+ topic: PublicKey
53
+ sessionId: PublicKey
54
+ data: SignalData
288
55
  }
289
56
 
290
- export interface Answer {
57
+ export type Answer = {
291
58
  accept: boolean
292
59
  }
293
60
  }
@@ -12,25 +12,26 @@ import { createTestBroker } from '@dxos/signal';
12
12
  import { randomInt } from '@dxos/util';
13
13
 
14
14
  import { SignalApi } from './signal-api';
15
+ import { SignalClient } from './signal-client';
15
16
 
16
17
  describe('SignalApi', () => {
17
18
  let topic: PublicKey;
18
19
  let peer1: PublicKey;
19
20
  let peer2: PublicKey;
20
- let api: SignalApi;
21
- let api2: SignalApi;
21
+ let api1: SignalClient;
22
+ let api2: SignalClient;
22
23
 
23
- let broker: Awaited<ReturnType<typeof createTestBroker>>;
24
- const signalApiPort = randomInt(10000, 50000);
25
- const signalApiUrl = 'http://0.0.0.0:' + signalApiPort;
24
+ let broker1: Awaited<ReturnType<typeof createTestBroker>>;
25
+ const signalApiPort1 = randomInt(10000, 50000);
26
+ const signalApiUrl1 = 'http://0.0.0.0:' + signalApiPort1;
26
27
 
27
28
  // code let broker2: ReturnType<typeof createBroker>;
28
29
  const signalApiPort2 = randomInt(10000, 50000);
29
30
  const signalApiUrl2 = 'http://0.0.0.0:' + signalApiPort2;
30
31
 
31
32
  before(async () => {
32
- broker = await createTestBroker(signalApiPort);
33
- // code broker2 = await createTestBroker(signalApiPort2);
33
+ broker1 = await createTestBroker(signalApiPort1);
34
+ // broker2 = await createTestBroker(signalApiPort2);
34
35
  });
35
36
 
36
37
  beforeEach(() => {
@@ -41,27 +42,27 @@ describe('SignalApi', () => {
41
42
 
42
43
  after(async function () {
43
44
  this.timeout(0);
44
- await api.close();
45
- await broker.stop();
45
+ await api1.close();
46
+ await broker1.stop();
46
47
  // code await broker2.stop();
47
48
  });
48
49
 
49
50
  test('join', async () => {
50
- api = new SignalApi(signalApiUrl, (async () => {}) as any, async () => {});
51
+ api1 = new SignalClient(signalApiUrl1, (async () => {}) as any, async () => {});
51
52
 
52
- const join = await api.join(topic, peer1);
53
+ const join = await api1.join(topic, peer1);
53
54
  expect(join).toEqual([peer1]);
54
55
 
55
- const join2 = await api.join(topic, peer2);
56
+ const join2 = await api1.join(topic, peer2);
56
57
  expect(join2).toEqual([peer1, peer2]);
57
58
  }).timeout(1_000);
58
59
 
59
60
  test('offer', async () => {
60
61
  const offerMock = mockFn<(msg: SignalApi.SignalMessage) => Promise<SignalApi.Answer>>()
61
62
  .resolvesTo({ accept: true });
62
- api = new SignalApi(signalApiUrl, offerMock, async () => {});
63
+ api1 = new SignalClient(signalApiUrl1, offerMock, async () => {});
63
64
 
64
- await api.join(topic, peer1);
65
+ await api1.join(topic, peer1);
65
66
 
66
67
  const offer: SignalApi.SignalMessage = {
67
68
  data: { foo: 'bar' } as any,
@@ -70,7 +71,7 @@ describe('SignalApi', () => {
70
71
  sessionId: PublicKey.random(),
71
72
  topic
72
73
  };
73
- const offerResult = await api.offer(offer);
74
+ const offerResult = await api1.offer(offer);
74
75
  expect(offerResult).toEqual({ accept: true });
75
76
  expect(offerMock).toHaveBeenCalledWith([offer]);
76
77
  }).timeout(5_000);
@@ -78,9 +79,9 @@ describe('SignalApi', () => {
78
79
  test('signal', async () => {
79
80
  const signalMock = mockFn<(msg: SignalApi.SignalMessage) => Promise<void>>()
80
81
  .resolvesTo();
81
- api = new SignalApi(signalApiUrl, (async () => {}) as any, signalMock);
82
+ api1 = new SignalClient(signalApiUrl1, (async () => {}) as any, signalMock);
82
83
 
83
- await api.join(topic, peer1);
84
+ await api1.join(topic, peer1);
84
85
 
85
86
  const msg: SignalApi.SignalMessage = {
86
87
  id: peer2,
@@ -89,7 +90,7 @@ describe('SignalApi', () => {
89
90
  topic,
90
91
  data: { foo: 'bar' } as any
91
92
  };
92
- await api.signal(msg);
93
+ await api1.signal(msg);
93
94
 
94
95
  await waitForExpect(() => {
95
96
  expect(signalMock).toHaveBeenCalledWith([msg]);
@@ -98,10 +99,10 @@ describe('SignalApi', () => {
98
99
 
99
100
  test.skip('join across multiple signal servers', async () => {
100
101
  // This feature is not implemented yet.
101
- api = new SignalApi(signalApiUrl, (async () => {}) as any, async () => {});
102
- api2 = new SignalApi(signalApiUrl2, (async () => {}) as any, async () => {});
102
+ api1 = new SignalClient(signalApiUrl1, (async () => {}) as any, async () => {});
103
+ api2 = new SignalClient(signalApiUrl2, (async () => {}) as any, async () => {});
103
104
 
104
- await api.join(topic, peer1);
105
+ await api1.join(topic, peer1);
105
106
  await api2.join(topic, peer2);
106
107
 
107
108
  await waitForExpect(async () => {
@@ -110,7 +111,7 @@ describe('SignalApi', () => {
110
111
  }, 4_000);
111
112
 
112
113
  await waitForExpect(async () => {
113
- const peers = await api.lookup(topic);
114
+ const peers = await api1.lookup(topic);
114
115
  expect(peers.length).toEqual(2);
115
116
  }, 4_000);
116
117
  }).timeout(5_000);
@@ -122,10 +123,10 @@ describe('SignalApi', () => {
122
123
  const signalMock = mockFn<(msg: SignalApi.SignalMessage) => Promise<void>>()
123
124
  .resolvesTo();
124
125
 
125
- api = new SignalApi(signalApiUrl, offerMock, async () => {});
126
- api2 = new SignalApi(signalApiUrl2, (async () => {}) as any, signalMock);
126
+ api1 = new SignalClient(signalApiUrl1, offerMock, async () => {});
127
+ api2 = new SignalClient(signalApiUrl2, (async () => {}) as any, signalMock);
127
128
 
128
- await api.join(topic, peer1);
129
+ await api1.join(topic, peer1);
129
130
  await sleep(3000);
130
131
  await api2.join(topic, peer2);
131
132
 
@@ -146,7 +147,7 @@ describe('SignalApi', () => {
146
147
  topic,
147
148
  data: { foo: 'bar' } as any
148
149
  };
149
- await api.signal(msg);
150
+ await api1.signal(msg);
150
151
 
151
152
  await waitForExpect(() => {
152
153
  expect(signalMock).toHaveBeenCalledWith([msg]);