@dxos/network-manager 2.33.9-dev.7d11f506 → 2.33.9-dev.9bbef4e2

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 (158) hide show
  1. package/dist/src/network-manager.blueprint-test.d.ts +3 -1
  2. package/dist/src/network-manager.blueprint-test.d.ts.map +1 -1
  3. package/dist/src/network-manager.blueprint-test.js +46 -17
  4. package/dist/src/network-manager.blueprint-test.js.map +1 -1
  5. package/dist/src/network-manager.browser-test.js +1 -1
  6. package/dist/src/network-manager.browser-test.js.map +1 -1
  7. package/dist/src/network-manager.d.ts.map +1 -1
  8. package/dist/src/network-manager.js +13 -12
  9. package/dist/src/network-manager.js.map +1 -1
  10. package/dist/src/network-manager.test.js +5 -4
  11. package/dist/src/network-manager.test.js.map +1 -1
  12. package/dist/src/proto/gen/dxos/credentials.d.ts +39 -0
  13. package/dist/src/proto/gen/dxos/credentials.d.ts.map +1 -1
  14. package/dist/src/proto/gen/dxos/halo/keys.d.ts +44 -2
  15. package/dist/src/proto/gen/dxos/halo/keys.d.ts.map +1 -1
  16. package/dist/src/proto/gen/dxos/halo/keys.js +4 -0
  17. package/dist/src/proto/gen/dxos/halo/keys.js.map +1 -1
  18. package/dist/src/proto/gen/dxos/mesh/signal.d.ts +74 -16
  19. package/dist/src/proto/gen/dxos/mesh/signal.d.ts.map +1 -1
  20. package/dist/src/proto/gen/dxos/mesh/signalMessage.d.ts +79 -0
  21. package/dist/src/proto/gen/dxos/mesh/signalMessage.d.ts.map +1 -0
  22. package/dist/src/proto/gen/dxos/mesh/signalMessage.js +3 -0
  23. package/dist/src/proto/gen/dxos/mesh/signalMessage.js.map +1 -0
  24. package/dist/src/proto/gen/google/protobuf.d.ts +8 -2
  25. package/dist/src/proto/gen/google/protobuf.d.ts.map +1 -1
  26. package/dist/src/proto/gen/index.d.ts +17 -4
  27. package/dist/src/proto/gen/index.d.ts.map +1 -1
  28. package/dist/src/proto/gen/index.js +1 -1
  29. package/dist/src/proto/gen/index.js.map +1 -1
  30. package/dist/src/proto/substitutions.d.ts +4 -0
  31. package/dist/src/proto/substitutions.d.ts.map +1 -1
  32. package/dist/src/proto/substitutions.js +3 -1
  33. package/dist/src/proto/substitutions.js.map +1 -1
  34. package/dist/src/protocol-factory.js +3 -3
  35. package/dist/src/protocol-factory.js.map +1 -1
  36. package/dist/src/signal/in-memory-signal-manager.d.ts +7 -7
  37. package/dist/src/signal/in-memory-signal-manager.d.ts.map +1 -1
  38. package/dist/src/signal/in-memory-signal-manager.js +34 -13
  39. package/dist/src/signal/in-memory-signal-manager.js.map +1 -1
  40. package/dist/src/signal/index.d.ts +1 -2
  41. package/dist/src/signal/index.d.ts.map +1 -1
  42. package/dist/src/signal/index.js +1 -2
  43. package/dist/src/signal/index.js.map +1 -1
  44. package/dist/src/signal/integration.test.d.ts +2 -0
  45. package/dist/src/signal/integration.test.d.ts.map +1 -0
  46. package/dist/src/signal/integration.test.js +102 -0
  47. package/dist/src/signal/integration.test.js.map +1 -0
  48. package/dist/src/signal/message-router.d.ts +20 -8
  49. package/dist/src/signal/message-router.d.ts.map +1 -1
  50. package/dist/src/signal/message-router.js +96 -17
  51. package/dist/src/signal/message-router.js.map +1 -1
  52. package/dist/src/signal/message-router.test.js +125 -22
  53. package/dist/src/signal/message-router.test.js.map +1 -1
  54. package/dist/src/signal/signal-client.d.ts +33 -17
  55. package/dist/src/signal/signal-client.d.ts.map +1 -1
  56. package/dist/src/signal/signal-client.js +102 -82
  57. package/dist/src/signal/signal-client.js.map +1 -1
  58. package/dist/src/signal/signal-client.test.js +60 -75
  59. package/dist/src/signal/signal-client.test.js.map +1 -1
  60. package/dist/src/signal/{websocket-signal-manager.d.ts → signal-manager-impl.d.ts} +13 -11
  61. package/dist/src/signal/signal-manager-impl.d.ts.map +1 -0
  62. package/dist/src/signal/signal-manager-impl.js +151 -0
  63. package/dist/src/signal/signal-manager-impl.js.map +1 -0
  64. package/dist/src/signal/signal-manager.d.ts +12 -11
  65. package/dist/src/signal/signal-manager.d.ts.map +1 -1
  66. package/dist/src/signal/signal-rpc-client.d.ts +19 -0
  67. package/dist/src/signal/signal-rpc-client.d.ts.map +1 -0
  68. package/dist/src/signal/signal-rpc-client.js +108 -0
  69. package/dist/src/signal/signal-rpc-client.js.map +1 -0
  70. package/dist/src/signal/signal-rpc-client.test.d.ts +2 -0
  71. package/dist/src/signal/signal-rpc-client.test.d.ts.map +1 -0
  72. package/dist/src/signal/signal-rpc-client.test.js +74 -0
  73. package/dist/src/signal/signal-rpc-client.test.js.map +1 -0
  74. package/dist/src/swarm/connection.d.ts +3 -3
  75. package/dist/src/swarm/connection.d.ts.map +1 -1
  76. package/dist/src/swarm/connection.js +8 -11
  77. package/dist/src/swarm/connection.js.map +1 -1
  78. package/dist/src/swarm/swarm.d.ts +6 -7
  79. package/dist/src/swarm/swarm.d.ts.map +1 -1
  80. package/dist/src/swarm/swarm.js +29 -25
  81. package/dist/src/swarm/swarm.js.map +1 -1
  82. package/dist/src/swarm/swarm.test.js +156 -115
  83. package/dist/src/swarm/swarm.test.js.map +1 -1
  84. package/dist/src/testing/test-protocol.d.ts.map +1 -1
  85. package/dist/src/testing/test-protocol.js +3 -3
  86. package/dist/src/testing/test-protocol.js.map +1 -1
  87. package/dist/src/topology/fully-connected-topology.d.ts +0 -1
  88. package/dist/src/topology/fully-connected-topology.d.ts.map +1 -1
  89. package/dist/src/topology/fully-connected-topology.js +4 -9
  90. package/dist/src/topology/fully-connected-topology.js.map +1 -1
  91. package/dist/src/topology/mmst-topology.d.ts +0 -1
  92. package/dist/src/topology/mmst-topology.d.ts.map +1 -1
  93. package/dist/src/topology/mmst-topology.js +6 -11
  94. package/dist/src/topology/mmst-topology.js.map +1 -1
  95. package/dist/src/topology/star-topology.d.ts +0 -1
  96. package/dist/src/topology/star-topology.d.ts.map +1 -1
  97. package/dist/src/topology/star-topology.js +5 -10
  98. package/dist/src/topology/star-topology.js.map +1 -1
  99. package/dist/src/topology/topology.d.ts +0 -6
  100. package/dist/src/topology/topology.d.ts.map +1 -1
  101. package/dist/src/transport/in-memory-transport.d.ts +2 -2
  102. package/dist/src/transport/in-memory-transport.d.ts.map +1 -1
  103. package/dist/src/transport/in-memory-transport.js +2 -2
  104. package/dist/src/transport/in-memory-transport.js.map +1 -1
  105. package/dist/src/transport/transport.d.ts +3 -3
  106. package/dist/src/transport/transport.d.ts.map +1 -1
  107. package/dist/src/transport/webrtc-transport.d.ts +3 -3
  108. package/dist/src/transport/webrtc-transport.d.ts.map +1 -1
  109. package/dist/src/transport/webrtc-transport.js +3 -3
  110. package/dist/src/transport/webrtc-transport.js.map +1 -1
  111. package/dist/tests-setup.js +1 -1
  112. package/dist/tsconfig.tsbuildinfo +1 -1
  113. package/package.json +17 -12
  114. package/src/network-manager.blueprint-test.ts +57 -22
  115. package/src/network-manager.browser-test.ts +1 -1
  116. package/src/network-manager.test.ts +8 -7
  117. package/src/network-manager.ts +10 -10
  118. package/src/proto/defs/dxos/mesh/signal.proto +54 -23
  119. package/src/proto/defs/dxos/mesh/signalMessage.proto +51 -0
  120. package/src/proto/gen/dxos/credentials.ts +40 -0
  121. package/src/proto/gen/dxos/halo/keys.ts +45 -2
  122. package/src/proto/gen/dxos/mesh/signal.ts +73 -16
  123. package/src/proto/gen/dxos/mesh/signalMessage.ts +83 -0
  124. package/src/proto/gen/google/protobuf.ts +9 -2
  125. package/src/proto/gen/index.ts +18 -5
  126. package/src/proto/substitutions.ts +3 -1
  127. package/src/protocol-factory.ts +1 -1
  128. package/src/signal/in-memory-signal-manager.ts +38 -13
  129. package/src/signal/index.ts +1 -2
  130. package/src/signal/integration.test.ts +117 -0
  131. package/src/signal/message-router.test.ts +169 -58
  132. package/src/signal/message-router.ts +120 -27
  133. package/src/signal/signal-client.test.ts +70 -90
  134. package/src/signal/signal-client.ts +120 -87
  135. package/src/signal/signal-manager-impl.ts +166 -0
  136. package/src/signal/signal-manager.ts +12 -12
  137. package/src/signal/signal-rpc-client.test.ts +86 -0
  138. package/src/signal/signal-rpc-client.ts +121 -0
  139. package/src/swarm/connection.ts +6 -9
  140. package/src/swarm/swarm.test.ts +208 -167
  141. package/src/swarm/swarm.ts +26 -22
  142. package/src/testing/test-protocol.ts +1 -1
  143. package/src/topology/fully-connected-topology.ts +2 -10
  144. package/src/topology/mmst-topology.ts +2 -10
  145. package/src/topology/star-topology.ts +2 -8
  146. package/src/topology/topology.ts +0 -7
  147. package/src/transport/in-memory-transport.ts +3 -3
  148. package/src/transport/transport.ts +3 -3
  149. package/src/transport/webrtc-transport.ts +4 -4
  150. package/dist/src/signal/websocket-rpc.d.ts +0 -30
  151. package/dist/src/signal/websocket-rpc.d.ts.map +0 -1
  152. package/dist/src/signal/websocket-rpc.js +0 -203
  153. package/dist/src/signal/websocket-rpc.js.map +0 -1
  154. package/dist/src/signal/websocket-signal-manager.d.ts.map +0 -1
  155. package/dist/src/signal/websocket-signal-manager.js +0 -134
  156. package/dist/src/signal/websocket-signal-manager.js.map +0 -1
  157. package/src/signal/websocket-rpc.ts +0 -208
  158. package/src/signal/websocket-signal-manager.ts +0 -158
@@ -0,0 +1,166 @@
1
+ //
2
+ // Copyright 2020 DXOS.org
3
+ //
4
+
5
+ import debug from 'debug';
6
+ import assert from 'node:assert';
7
+
8
+ import { Event, synchronized } from '@dxos/async';
9
+ import { PublicKey } from '@dxos/protocols';
10
+ import { ComplexMap } from '@dxos/util';
11
+
12
+ import { SwarmEvent } from '../proto/gen/dxos/mesh/signal';
13
+ import { SignalMessage } from '../proto/gen/dxos/mesh/signalMessage';
14
+ import { SignalApi } from './signal-api';
15
+ import { SignalClient } from './signal-client';
16
+ import { SignalManager } from './signal-manager';
17
+
18
+ const log = debug('dxos:network-manager:signal-manager-impl');
19
+
20
+ export class SignalManagerImpl implements SignalManager {
21
+ private readonly _servers = new Map<string, SignalClient>();
22
+
23
+ /** Topics joined: topic => peerId */
24
+ private readonly _topicsJoined = new ComplexMap<PublicKey, PublicKey>(topic => topic.toHex());
25
+ /** host => topic => peerId */
26
+ private readonly _topicsJoinedPerSignal = new Map<string, ComplexMap<PublicKey, PublicKey>>();
27
+
28
+ private _reconciling?: boolean = false;
29
+ private _reconcileTimeoutId?: NodeJS.Timeout;
30
+ private _destroyed = false;
31
+
32
+ readonly statusChanged = new Event<SignalApi.Status[]>();
33
+ readonly commandTrace = new Event<SignalApi.CommandTrace>();
34
+ readonly swarmEvent = new Event<[topic: PublicKey, swarmEvent: SwarmEvent]>();
35
+ readonly onMessage = new Event<SignalMessage>();
36
+
37
+ constructor (
38
+ private readonly _hosts: string[]
39
+ ) {
40
+ log(`Created WebsocketSignalManager with signal servers: ${_hosts}`);
41
+ assert(_hosts.length === 1, 'Only a single signaling server connection is supported');
42
+ for (const host of this._hosts) {
43
+ const server = new SignalClient(
44
+ host,
45
+ async msg => this.onMessage.emit(msg)
46
+ );
47
+ // TODO(mykola): Add subscription group
48
+ server.swarmEvent.on(data => this.swarmEvent.emit(data));
49
+ server.statusChanged.on(() => this.statusChanged.emit(this.getStatus()));
50
+
51
+ this._servers.set(host, server);
52
+ server.commandTrace.on(trace => this.commandTrace.emit(trace));
53
+ this._topicsJoinedPerSignal.set(host, new ComplexMap(x => x.toHex()));
54
+ }
55
+ }
56
+
57
+ getStatus (): SignalApi.Status[] {
58
+ return Array.from(this._servers.values()).map(server => server.getStatus());
59
+ }
60
+
61
+ join (topic: PublicKey, peerId: PublicKey) {
62
+ assert(!this._topicsJoined.has(topic), `Topic ${topic} is already joined`);
63
+ log(`Join ${topic} ${peerId}`);
64
+ this._topicsJoined.set(topic, peerId);
65
+ this._scheduleReconcile();
66
+ }
67
+
68
+ leave (topic: PublicKey, peerId: PublicKey) {
69
+ assert(!!this._topicsJoined.has(topic), `Topic ${topic} was not joined`);
70
+ log(`Leave ${topic} ${peerId}`);
71
+ this._topicsJoined.delete(topic);
72
+ this._scheduleReconcile();
73
+ }
74
+
75
+ private _scheduleReconcile () {
76
+ if (this._destroyed) {
77
+ return;
78
+ }
79
+
80
+ if (!this._reconciling) {
81
+ this._reconciling = true;
82
+ this._reconcileJoinedTopics().then(
83
+ () => {
84
+ this._reconciling = false;
85
+ },
86
+ err => {
87
+ this._reconciling = false;
88
+ log(`Error while reconciling: ${err}`);
89
+ this._reconcileLater();
90
+ }
91
+ );
92
+ } else {
93
+ this._reconcileLater();
94
+ }
95
+ }
96
+
97
+ private _reconcileLater () {
98
+ if (this._destroyed) {
99
+ return;
100
+ }
101
+
102
+ if (!this._reconcileTimeoutId) {
103
+ this._reconcileTimeoutId = setTimeout(async () => this._scheduleReconcile(), 3000);
104
+ }
105
+ }
106
+
107
+ @synchronized
108
+ private async _reconcileJoinedTopics () {
109
+ // TODO(mykola): Handle reconnects to SS. Maybe move map of joined topics to signal-client.
110
+ log('Reconciling..');
111
+ for (const [host, server] of this._servers) {
112
+ const actualJoinedTopics = this._topicsJoinedPerSignal.get(host)!;
113
+
114
+ // Leave swarms
115
+ for (const [topic, actualPeerId] of actualJoinedTopics) {
116
+ try {
117
+ const desiredPeerId = this._topicsJoined.get(topic);
118
+ if (!desiredPeerId || !desiredPeerId.equals(actualPeerId)) {
119
+ await server.leave(topic, actualPeerId);
120
+ actualJoinedTopics.delete(topic);
121
+ }
122
+ } catch (err) {
123
+ log(`Error leaving swarm: ${err}`);
124
+ this._scheduleReconcile();
125
+ }
126
+ }
127
+
128
+ // Join swarms
129
+ for (const [topic, desiredPeerId] of this._topicsJoined) {
130
+ try {
131
+ const actualPeerId = actualJoinedTopics.get(topic);
132
+ if (!actualPeerId) {
133
+ await server.join(topic, desiredPeerId);
134
+ actualJoinedTopics.set(topic, desiredPeerId);
135
+ } else {
136
+ if (!actualPeerId.equals(desiredPeerId)) {
137
+ throw new Error(`Joined with peerId different from desired: ${JSON.stringify({ actualPeerId, desiredPeerId })}`);
138
+ }
139
+ }
140
+ } catch (err) {
141
+ log(`Error joining swarm: ${err}`);
142
+ this._scheduleReconcile();
143
+ }
144
+ }
145
+ }
146
+ log('Done reconciling..');
147
+ this._reconciling = false;
148
+ }
149
+
150
+ async message (msg: SignalMessage) {
151
+ log(`Signal ${msg.remoteId}`);
152
+ for (const server of this._servers.values()) {
153
+ server.signal(msg).catch(err => {
154
+ log(`Error signaling: ${err}`);
155
+ });
156
+ }
157
+ }
158
+
159
+ async destroy () {
160
+ this._destroyed = true;
161
+ if (this._reconcileTimeoutId) {
162
+ clearTimeout(this._reconcileTimeoutId);
163
+ }
164
+ await Promise.all(Array.from(this._servers.values()).map(server => server.close()));
165
+ }
166
+ }
@@ -5,18 +5,14 @@
5
5
  import { Event } from '@dxos/async';
6
6
  import { PublicKey } from '@dxos/protocols';
7
7
 
8
- import { Answer, Message } from '../proto/gen/dxos/mesh/signal';
8
+ import { SwarmEvent } from '../proto/gen/dxos/mesh/signal';
9
+ import { Answer, SignalMessage } from '../proto/gen/dxos/mesh/signalMessage';
9
10
  import { SignalApi } from './signal-api';
10
11
 
11
12
  /**
12
13
  * Signal peer discovery interface.
13
14
  */
14
15
  export interface SignalConnection {
15
- /**
16
- * Find peers (triggers async event).
17
- */
18
- lookup (topic: PublicKey): void
19
-
20
16
  /**
21
17
  * Join topic on signal network, to be discoverable by other peers.
22
18
  */
@@ -35,20 +31,24 @@ export interface SignalMessaging {
35
31
  /**
36
32
  * Offer/answer RPC.
37
33
  */
38
- offer (msg: Message): Promise<Answer>
34
+ offer (msg: SignalMessage): Promise<Answer>
39
35
 
40
36
  /**
41
- * Send message to peer.
37
+ * Reliably send a signal to a peer.
42
38
  */
43
- signal (msg: Message): Promise<void>
39
+ signal (msg: SignalMessage): Promise<void>
44
40
  }
45
41
 
46
- export interface SignalManager extends SignalConnection, SignalMessaging {
42
+ export interface SignalManager extends SignalConnection {
47
43
  statusChanged: Event<SignalApi.Status[]>
48
44
  commandTrace: Event<SignalApi.CommandTrace>
49
- peerCandidatesChanged: Event<[topic: PublicKey, candidates: PublicKey[]]>
50
- onSignal: Event<Message>
45
+ swarmEvent: Event<[topic: PublicKey, swarmEvent: SwarmEvent]>
46
+ onMessage: Event<SignalMessage>
51
47
 
52
48
  getStatus (): SignalApi.Status[]
53
49
  destroy(): Promise<void>
50
+ /**
51
+ * Send message to peer.
52
+ */
53
+ message (msg: SignalMessage): Promise<void>
54
54
  }
@@ -0,0 +1,86 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+ import { expect } from 'earljs';
5
+
6
+ import { Any } from '@dxos/codec-protobuf';
7
+ import { PublicKey } from '@dxos/protocols';
8
+ import { createTestBroker, TestBroker } from '@dxos/signal';
9
+
10
+ import { Message, SwarmEvent } from '../proto/gen/dxos/mesh/signal';
11
+ import { SignalRPCClient } from './signal-rpc-client';
12
+
13
+ describe('SignalRPCClient', () => {
14
+ let broker: TestBroker;
15
+
16
+ before(async () => {
17
+ broker = await createTestBroker();
18
+ });
19
+
20
+ after(() => {
21
+ broker.stop();
22
+ });
23
+
24
+ const setup = async () => {
25
+ const client = new SignalRPCClient(broker.url());
26
+ return client;
27
+ };
28
+
29
+ it('signal between 2 peers', async () => {
30
+ const client1 = await setup();
31
+ const client2 = await setup();
32
+
33
+ const peerId1 = PublicKey.random();
34
+ const peerId2 = PublicKey.random();
35
+
36
+ const stream1 = await client1.receiveMessages(peerId1);
37
+ const message: Any = {
38
+ 'type_url': 'test',
39
+ value: Uint8Array.from([1, 2, 3])
40
+ };
41
+
42
+ await client2.sendMessage(peerId2, peerId1, message);
43
+
44
+ const received: Message = await new Promise(resolve => {
45
+ stream1.subscribe(message => {
46
+ resolve(message);
47
+ }, (error) => {
48
+ if (error) {
49
+ console.log(error);
50
+ throw error;
51
+ }
52
+ });
53
+ });
54
+ expect(received.author).toEqual(peerId2.asUint8Array());
55
+ stream1.close();
56
+ }).timeout(10000);
57
+
58
+ it('join', async () => {
59
+ const client1 = await setup();
60
+ const client2 = await setup();
61
+
62
+ const peerId1 = PublicKey.random();
63
+ const peerId2 = PublicKey.random();
64
+ const topic = PublicKey.random();
65
+
66
+ const stream1 = await client1.join(topic, peerId1);
67
+ const promise = new Promise<SwarmEvent>(resolve => {
68
+ stream1.subscribe((event: SwarmEvent) => {
69
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
70
+ if (peerId2.equals(event.peerAvailable?.peer!)) {
71
+ resolve(event);
72
+ }
73
+ }, (error) => {
74
+ if (error) {
75
+ console.log(error);
76
+ throw error;
77
+ }
78
+ });
79
+ });
80
+ const stream2 = await client2.join(topic, peerId2);
81
+
82
+ expect((await promise).peerAvailable?.peer).toEqual(peerId2.asBuffer());
83
+ stream1.close();
84
+ stream2.close();
85
+ }).timeout(10000);
86
+ });
@@ -0,0 +1,121 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import debug from 'debug';
6
+ import WebSocket from 'isomorphic-ws';
7
+
8
+ import { Trigger, Event } from '@dxos/async';
9
+ import { Any, Stream } from '@dxos/codec-protobuf';
10
+ import { PublicKey } from '@dxos/protocols';
11
+ import { createBundledRpcClient, ProtoRpcClient } from '@dxos/rpc';
12
+
13
+ import { schema } from '../proto/gen';
14
+ import { Message, Signal } from '../proto/gen/dxos/mesh/signal';
15
+ interface Services {
16
+ Signal: Signal
17
+ }
18
+
19
+ const log = debug('dxos:network-manager:signal-rpc-client');
20
+
21
+ export class SignalRPCClient {
22
+ private readonly _socket: WebSocket
23
+ private readonly _rpc: ProtoRpcClient<Services>
24
+ private readonly _connectTrigger = new Trigger();
25
+
26
+ readonly connected = new Event();
27
+ readonly disconnected = new Event();
28
+ readonly error = new Event<Error>();
29
+
30
+ constructor (
31
+ private readonly _url: string
32
+ ) {
33
+ this._socket = new WebSocket(this._url);
34
+ this._socket.onopen = async () => {
35
+ try {
36
+ await this._rpc.open();
37
+ log(`RPC open ${this._url}`);
38
+ this.connected.emit();
39
+ this._connectTrigger.wake();
40
+ } catch (err: any) {
41
+ this.error.emit(err);
42
+ }
43
+ };
44
+
45
+ this._socket.onclose = async () => {
46
+ log(`Disconnected ${this._url}`);
47
+ this.disconnected.emit();
48
+ try {
49
+ await this._rpc.close();
50
+ } catch (err: any) {
51
+ this.error.emit(err);
52
+ }
53
+ };
54
+
55
+ this._socket.onerror = (e: WebSocket.ErrorEvent) => {
56
+ log(`Signal socket error ${this._url} ${e.message}`);
57
+ this.error.emit(e.error ?? new Error(e.message));
58
+ };
59
+
60
+ this._rpc = createBundledRpcClient(
61
+ {
62
+ Signal: schema.getService('dxos.mesh.signal.Signal')
63
+ },
64
+ {
65
+ noHandshake: true,
66
+ port: {
67
+ send: msg => {
68
+ this._socket.send(msg);
69
+ },
70
+ subscribe: cb => {
71
+ this._socket.onmessage = async (msg: WebSocket.MessageEvent) => {
72
+ if (typeof Blob !== 'undefined' && msg.data instanceof Blob) {
73
+ cb(Buffer.from(await msg.data.arrayBuffer()));
74
+ } else {
75
+ cb(msg.data as any);
76
+ }
77
+ };
78
+ }
79
+ }
80
+ }
81
+ );
82
+ }
83
+
84
+ async join (topic: PublicKey, peerId: PublicKey) {
85
+ log('join', topic, peerId);
86
+ await this._connectTrigger.wait();
87
+ const swarmStream = this._rpc.rpc.Signal.join({
88
+ swarm: topic.asUint8Array(),
89
+ peer: peerId.asUint8Array()
90
+ });
91
+ await swarmStream.waitUntilReady();
92
+ return swarmStream;
93
+ }
94
+
95
+ async receiveMessages (peerId: PublicKey): Promise<Stream<Message>> {
96
+ await this._connectTrigger.wait();
97
+ const messageStream = this._rpc.rpc.Signal.receiveMessages({
98
+ peer: peerId.asUint8Array()
99
+ });
100
+ await messageStream.waitUntilReady();
101
+ return messageStream;
102
+ }
103
+
104
+ async sendMessage (author: PublicKey, recipient: PublicKey, message: Any) {
105
+ log('sendMessage', author, recipient, message);
106
+ await this._connectTrigger.wait();
107
+ await this._rpc.rpc.Signal.sendMessage({
108
+ author: author.asUint8Array(),
109
+ recipient: recipient.asUint8Array(),
110
+ payload: message
111
+ });
112
+ }
113
+
114
+ async close () {
115
+ try {
116
+ await this._rpc.close();
117
+ } finally {
118
+ this._socket.close();
119
+ }
120
+ }
121
+ }
@@ -2,15 +2,15 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  import { Event, synchronized } from '@dxos/async';
9
9
  import { ErrorStream } from '@dxos/debug';
10
10
  import { Protocol } from '@dxos/mesh-protocol';
11
11
  import { PublicKey } from '@dxos/protocols';
12
12
 
13
- import { Message } from '../proto/gen/dxos/mesh/signal';
13
+ import { SignalMessage } from '../proto/gen/dxos/mesh/signalMessage';
14
14
  import { Transport, TransportFactory } from '../transport';
15
15
 
16
16
  const log = debug('dxos:network-manager:swarm:connection');
@@ -51,7 +51,7 @@ export enum ConnectionState {
51
51
  export class Connection {
52
52
  private _state: ConnectionState = ConnectionState.INITIAL;
53
53
  private _transport: Transport | undefined;
54
- private _bufferedSignals: Message[] = [];
54
+ private _bufferedSignals: SignalMessage[] = [];
55
55
 
56
56
  readonly stateChanged = new Event<ConnectionState>();
57
57
  readonly errors = new ErrorStream();
@@ -62,7 +62,7 @@ export class Connection {
62
62
  public readonly remoteId: PublicKey,
63
63
  public readonly sessionId: PublicKey,
64
64
  public readonly initiator: boolean,
65
- private readonly _sendSignal: (msg: Message) => Promise<void>,
65
+ private readonly _sendSignal: (msg: SignalMessage) => Promise<void>,
66
66
  private readonly _protocol: Protocol,
67
67
  private readonly _transportFactory: TransportFactory
68
68
  ) {}
@@ -116,16 +116,13 @@ export class Connection {
116
116
  this._bufferedSignals = [];
117
117
  }
118
118
 
119
- async signal (msg: Message) {
119
+ async signal (msg: SignalMessage) {
120
120
  assert(msg.sessionId);
121
121
  if (!msg.sessionId.equals(this.sessionId)) {
122
122
  log('Dropping signal for incorrect session id.');
123
123
  return;
124
124
  }
125
- assert(msg.data);
126
- if (msg.data.offer && this._state === ConnectionState.INITIATING_CONNECTION) {
127
- throw new Error('Invalid state: Cannot send offer to an initiating peer.');
128
- }
125
+ assert(msg.data.signal);
129
126
  assert(msg.id?.equals(this.remoteId));
130
127
  assert(msg.remoteId?.equals(this.ownId));
131
128