@dxos/network-manager 0.1.0

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 (184) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/connection-log.d.ts +23 -0
  3. package/dist/src/connection-log.d.ts.map +1 -0
  4. package/dist/src/connection-log.js +98 -0
  5. package/dist/src/connection-log.js.map +1 -0
  6. package/dist/src/index.d.ts +9 -0
  7. package/dist/src/index.d.ts.map +1 -0
  8. package/dist/src/index.js +28 -0
  9. package/dist/src/index.js.map +1 -0
  10. package/dist/src/network-manager.d.ts +80 -0
  11. package/dist/src/network-manager.d.ts.map +1 -0
  12. package/dist/src/network-manager.js +123 -0
  13. package/dist/src/network-manager.js.map +1 -0
  14. package/dist/src/network-manager.test.d.ts +2 -0
  15. package/dist/src/network-manager.test.d.ts.map +1 -0
  16. package/dist/src/network-manager.test.js +621 -0
  17. package/dist/src/network-manager.test.js.map +1 -0
  18. package/dist/src/presence.test.d.ts +2 -0
  19. package/dist/src/presence.test.d.ts.map +1 -0
  20. package/dist/src/presence.test.js +60 -0
  21. package/dist/src/presence.test.js.map +1 -0
  22. package/dist/src/protocol-factory.d.ts +30 -0
  23. package/dist/src/protocol-factory.d.ts.map +1 -0
  24. package/dist/src/protocol-factory.js +64 -0
  25. package/dist/src/protocol-factory.js.map +1 -0
  26. package/dist/src/signal/index.d.ts +4 -0
  27. package/dist/src/signal/index.d.ts.map +1 -0
  28. package/dist/src/signal/index.js +23 -0
  29. package/dist/src/signal/index.js.map +1 -0
  30. package/dist/src/signal/integration.test.d.ts +2 -0
  31. package/dist/src/signal/integration.test.d.ts.map +1 -0
  32. package/dist/src/signal/integration.test.js +105 -0
  33. package/dist/src/signal/integration.test.js.map +1 -0
  34. package/dist/src/signal/message-router.d.ts +39 -0
  35. package/dist/src/signal/message-router.d.ts.map +1 -0
  36. package/dist/src/signal/message-router.js +135 -0
  37. package/dist/src/signal/message-router.js.map +1 -0
  38. package/dist/src/signal/message-router.test.d.ts +2 -0
  39. package/dist/src/signal/message-router.test.d.ts.map +1 -0
  40. package/dist/src/signal/message-router.test.js +211 -0
  41. package/dist/src/signal/message-router.test.js.map +1 -0
  42. package/dist/src/signal/signal-connection.d.ts +21 -0
  43. package/dist/src/signal/signal-connection.d.ts.map +1 -0
  44. package/dist/src/signal/signal-connection.js +6 -0
  45. package/dist/src/signal/signal-connection.js.map +1 -0
  46. package/dist/src/signal/signal-messaging.d.ts +34 -0
  47. package/dist/src/signal/signal-messaging.d.ts.map +1 -0
  48. package/dist/src/signal/signal-messaging.js +6 -0
  49. package/dist/src/signal/signal-messaging.js.map +1 -0
  50. package/dist/src/swarm/connection.d.ts +69 -0
  51. package/dist/src/swarm/connection.d.ts.map +1 -0
  52. package/dist/src/swarm/connection.js +187 -0
  53. package/dist/src/swarm/connection.js.map +1 -0
  54. package/dist/src/swarm/index.d.ts +4 -0
  55. package/dist/src/swarm/index.d.ts.map +1 -0
  56. package/dist/src/swarm/index.js +23 -0
  57. package/dist/src/swarm/index.js.map +1 -0
  58. package/dist/src/swarm/swarm-mapper.d.ts +30 -0
  59. package/dist/src/swarm/swarm-mapper.d.ts.map +1 -0
  60. package/dist/src/swarm/swarm-mapper.js +90 -0
  61. package/dist/src/swarm/swarm-mapper.js.map +1 -0
  62. package/dist/src/swarm/swarm.d.ts +64 -0
  63. package/dist/src/swarm/swarm.d.ts.map +1 -0
  64. package/dist/src/swarm/swarm.js +276 -0
  65. package/dist/src/swarm/swarm.js.map +1 -0
  66. package/dist/src/swarm/swarm.test.d.ts +2 -0
  67. package/dist/src/swarm/swarm.test.d.ts.map +1 -0
  68. package/dist/src/swarm/swarm.test.js +145 -0
  69. package/dist/src/swarm/swarm.test.js.map +1 -0
  70. package/dist/src/testing/index.d.ts +2 -0
  71. package/dist/src/testing/index.d.ts.map +1 -0
  72. package/dist/src/testing/index.js +21 -0
  73. package/dist/src/testing/index.js.map +1 -0
  74. package/dist/src/testing/test-protocol.d.ts +59 -0
  75. package/dist/src/testing/test-protocol.d.ts.map +1 -0
  76. package/dist/src/testing/test-protocol.js +140 -0
  77. package/dist/src/testing/test-protocol.js.map +1 -0
  78. package/dist/src/topology/fully-connected-topology.d.ts +11 -0
  79. package/dist/src/topology/fully-connected-topology.d.ts.map +1 -0
  80. package/dist/src/topology/fully-connected-topology.js +34 -0
  81. package/dist/src/topology/fully-connected-topology.js.map +1 -0
  82. package/dist/src/topology/index.d.ts +5 -0
  83. package/dist/src/topology/index.d.ts.map +1 -0
  84. package/dist/src/topology/index.js +24 -0
  85. package/dist/src/topology/index.js.map +1 -0
  86. package/dist/src/topology/mmst-topology.d.ts +31 -0
  87. package/dist/src/topology/mmst-topology.d.ts.map +1 -0
  88. package/dist/src/topology/mmst-topology.js +73 -0
  89. package/dist/src/topology/mmst-topology.js.map +1 -0
  90. package/dist/src/topology/star-topology.d.ts +13 -0
  91. package/dist/src/topology/star-topology.d.ts.map +1 -0
  92. package/dist/src/topology/star-topology.js +60 -0
  93. package/dist/src/topology/star-topology.js.map +1 -0
  94. package/dist/src/topology/topology.d.ts +56 -0
  95. package/dist/src/topology/topology.d.ts.map +1 -0
  96. package/dist/src/topology/topology.js +6 -0
  97. package/dist/src/topology/topology.js.map +1 -0
  98. package/dist/src/transport/index.d.ts +6 -0
  99. package/dist/src/transport/index.d.ts.map +1 -0
  100. package/dist/src/transport/index.js +25 -0
  101. package/dist/src/transport/index.js.map +1 -0
  102. package/dist/src/transport/memory-transport.d.ts +32 -0
  103. package/dist/src/transport/memory-transport.d.ts.map +1 -0
  104. package/dist/src/transport/memory-transport.js +98 -0
  105. package/dist/src/transport/memory-transport.js.map +1 -0
  106. package/dist/src/transport/memory-transport.test.d.ts +2 -0
  107. package/dist/src/transport/memory-transport.test.d.ts.map +1 -0
  108. package/dist/src/transport/memory-transport.test.js +84 -0
  109. package/dist/src/transport/memory-transport.test.js.map +1 -0
  110. package/dist/src/transport/transport.d.ts +38 -0
  111. package/dist/src/transport/transport.d.ts.map +1 -0
  112. package/dist/src/transport/transport.js +6 -0
  113. package/dist/src/transport/transport.js.map +1 -0
  114. package/dist/src/transport/webrtc-transport-proxy.d.ts +48 -0
  115. package/dist/src/transport/webrtc-transport-proxy.d.ts.map +1 -0
  116. package/dist/src/transport/webrtc-transport-proxy.js +139 -0
  117. package/dist/src/transport/webrtc-transport-proxy.js.map +1 -0
  118. package/dist/src/transport/webrtc-transport-proxy.test.d.ts +2 -0
  119. package/dist/src/transport/webrtc-transport-proxy.test.d.ts.map +1 -0
  120. package/dist/src/transport/webrtc-transport-proxy.test.js +245 -0
  121. package/dist/src/transport/webrtc-transport-proxy.test.js.map +1 -0
  122. package/dist/src/transport/webrtc-transport-service.d.ts +15 -0
  123. package/dist/src/transport/webrtc-transport-service.d.ts.map +1 -0
  124. package/dist/src/transport/webrtc-transport-service.js +97 -0
  125. package/dist/src/transport/webrtc-transport-service.js.map +1 -0
  126. package/dist/src/transport/webrtc-transport.d.ts +34 -0
  127. package/dist/src/transport/webrtc-transport.d.ts.map +1 -0
  128. package/dist/src/transport/webrtc-transport.js +100 -0
  129. package/dist/src/transport/webrtc-transport.js.map +1 -0
  130. package/dist/src/transport/webrtc-transport.test.d.ts +2 -0
  131. package/dist/src/transport/webrtc-transport.test.d.ts.map +1 -0
  132. package/dist/src/transport/webrtc-transport.test.js +80 -0
  133. package/dist/src/transport/webrtc-transport.test.js.map +1 -0
  134. package/dist/src/transport/webrtc.d.ts +6 -0
  135. package/dist/src/transport/webrtc.d.ts.map +1 -0
  136. package/dist/src/transport/webrtc.js +17 -0
  137. package/dist/src/transport/webrtc.js.map +1 -0
  138. package/dist/src/transport/wrtc-simple-peer.test.d.ts +2 -0
  139. package/dist/src/transport/wrtc-simple-peer.test.d.ts.map +1 -0
  140. package/dist/src/transport/wrtc-simple-peer.test.js +24 -0
  141. package/dist/src/transport/wrtc-simple-peer.test.js.map +1 -0
  142. package/dist/src/types.d.ts +6 -0
  143. package/dist/src/types.d.ts.map +1 -0
  144. package/dist/src/types.js +6 -0
  145. package/dist/src/types.js.map +1 -0
  146. package/package.json +58 -0
  147. package/src/connection-log.ts +102 -0
  148. package/src/globals.d.ts +7 -0
  149. package/src/index.ts +12 -0
  150. package/src/network-manager.test.ts +764 -0
  151. package/src/network-manager.ts +204 -0
  152. package/src/presence.test.ts +78 -0
  153. package/src/protocol-factory.ts +83 -0
  154. package/src/signal/index.ts +7 -0
  155. package/src/signal/integration.test.ts +129 -0
  156. package/src/signal/message-router.test.ts +274 -0
  157. package/src/signal/message-router.ts +200 -0
  158. package/src/signal/signal-connection.ts +20 -0
  159. package/src/signal/signal-messaging.ts +38 -0
  160. package/src/swarm/connection.ts +206 -0
  161. package/src/swarm/index.ts +7 -0
  162. package/src/swarm/swarm-mapper.ts +120 -0
  163. package/src/swarm/swarm.test.ts +192 -0
  164. package/src/swarm/swarm.ts +328 -0
  165. package/src/testing/index.ts +5 -0
  166. package/src/testing/test-protocol.ts +160 -0
  167. package/src/topology/fully-connected-topology.ts +38 -0
  168. package/src/topology/index.ts +8 -0
  169. package/src/topology/mmst-topology.ts +105 -0
  170. package/src/topology/star-topology.ts +67 -0
  171. package/src/topology/topology.ts +69 -0
  172. package/src/transport/index.ts +9 -0
  173. package/src/transport/memory-transport.test.ts +110 -0
  174. package/src/transport/memory-transport.ts +128 -0
  175. package/src/transport/transport.ts +47 -0
  176. package/src/transport/webrtc-transport-proxy.test.ts +290 -0
  177. package/src/transport/webrtc-transport-proxy.ts +167 -0
  178. package/src/transport/webrtc-transport-service.ts +115 -0
  179. package/src/transport/webrtc-transport.test.ts +112 -0
  180. package/src/transport/webrtc-transport.ts +122 -0
  181. package/src/transport/webrtc.ts +15 -0
  182. package/src/transport/wrtc-simple-peer.test.ts +24 -0
  183. package/src/types.ts +10 -0
  184. package/src/typings.d.ts +7 -0
@@ -0,0 +1,274 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ // @dxos/mocha platform=nodejs
6
+
7
+ import { expect } from 'earljs';
8
+ import { it, describe } from 'mocha';
9
+ import waitForExpect from 'wait-for-expect';
10
+
11
+ import { Awaited } from '@dxos/async';
12
+ import { PublicKey } from '@dxos/keys';
13
+ import { Messenger, WebsocketSignalManager } from '@dxos/messaging';
14
+ import { Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
15
+ import { createTestBroker } from '@dxos/signal';
16
+ import { afterTest } from '@dxos/testutils';
17
+
18
+ import { MessageRouter } from './message-router';
19
+ import { OfferMessage, SignalMessage } from './signal-messaging';
20
+
21
+ describe('MessageRouter', function () {
22
+ let topic: PublicKey;
23
+
24
+ let broker1: Awaited<ReturnType<typeof createTestBroker>>;
25
+
26
+ before(async function () {
27
+ broker1 = await createTestBroker();
28
+ });
29
+
30
+ beforeEach(function () {
31
+ topic = PublicKey.random();
32
+ });
33
+
34
+ after(function () {
35
+ broker1.stop();
36
+ });
37
+
38
+ const createSignalClientAndMessageRouter = async ({
39
+ signalApiUrl,
40
+ onSignal = (async () => {}) as any,
41
+ onOffer = async () => ({ accept: true }),
42
+ topic
43
+ }: {
44
+ signalApiUrl: string;
45
+ onSignal?: (msg: SignalMessage) => Promise<void>;
46
+ onOffer?: (msg: OfferMessage) => Promise<Answer>;
47
+ topic: PublicKey;
48
+ }) => {
49
+ const peerId = PublicKey.random();
50
+ const signalManager = new WebsocketSignalManager([signalApiUrl]);
51
+ afterTest(() => signalManager.destroy());
52
+
53
+ const messenger = new Messenger({ signalManager });
54
+ await messenger.listen({
55
+ peerId,
56
+ payloadType: 'dxos.mesh.swarm.SwarmMessage',
57
+ onMessage: async (message) => await router.receiveMessage(message)
58
+ });
59
+
60
+ const router: MessageRouter = new MessageRouter({
61
+ // todo(mykola): added catch to avoid not finished request.
62
+ sendMessage: async (message) => await messenger.sendMessage(message),
63
+ onSignal,
64
+ onOffer,
65
+ topic
66
+ });
67
+
68
+ return {
69
+ peerId,
70
+ signalManager,
71
+ router
72
+ };
73
+ };
74
+
75
+ it('signaling between 2 clients', async () => {
76
+ const received: SignalMessage[] = [];
77
+ const signalMock1 = async (msg: SignalMessage) => {
78
+ received.push(msg);
79
+ };
80
+ const { signalManager: signalManager1, peerId: peer1 } = await createSignalClientAndMessageRouter({
81
+ signalApiUrl: broker1.url(),
82
+ onSignal: signalMock1,
83
+ topic
84
+ });
85
+ const {
86
+ signalManager: signalManager2,
87
+ router: router2,
88
+ peerId: peer2
89
+ } = await createSignalClientAndMessageRouter({
90
+ signalApiUrl: broker1.url(),
91
+ topic
92
+ });
93
+
94
+ await signalManager1.join({ topic, peerId: peer1 });
95
+ await signalManager2.join({ topic, peerId: peer2 });
96
+
97
+ const msg: SignalMessage = {
98
+ author: peer2,
99
+ recipient: peer1,
100
+ sessionId: PublicKey.random(),
101
+ topic,
102
+ data: { signal: { json: JSON.stringify({ asd: 'asd' }) } }
103
+ };
104
+ await router2.signal(msg);
105
+
106
+ await waitForExpect(() => {
107
+ expect(received[0]).toBeAnObjectWith(msg);
108
+ }, 4_000);
109
+ }).timeout(5_000);
110
+
111
+ it('offer/answer', async () => {
112
+ const {
113
+ signalManager: signalManager1,
114
+ router: router1,
115
+ peerId: peer1
116
+ } = await createSignalClientAndMessageRouter({
117
+ signalApiUrl: broker1.url(),
118
+ onSignal: (async () => {}) as any,
119
+ onOffer: async () => ({ accept: true }),
120
+ topic
121
+ });
122
+ const { signalManager: signalManager2, peerId: peer2 } = await createSignalClientAndMessageRouter({
123
+ signalApiUrl: broker1.url(),
124
+ onSignal: (async () => {}) as any,
125
+ onOffer: async () => ({ accept: true }),
126
+ topic
127
+ });
128
+
129
+ await signalManager1.join({ topic, peerId: peer1 });
130
+ await signalManager2.join({ topic, peerId: peer2 });
131
+ const answer = await router1.offer({
132
+ author: peer1,
133
+ recipient: peer2,
134
+ sessionId: PublicKey.random(),
135
+ topic,
136
+ data: { offer: {} }
137
+ });
138
+ expect(answer.accept).toEqual(true);
139
+ }).timeout(5_000);
140
+
141
+ it('signaling between 3 clients', async () => {
142
+ const received1: SignalMessage[] = [];
143
+ const signalMock1 = async (msg: SignalMessage) => {
144
+ received1.push(msg);
145
+ };
146
+ const {
147
+ signalManager: signalManager1,
148
+ router: router1,
149
+ peerId: peer1
150
+ } = await createSignalClientAndMessageRouter({
151
+ signalApiUrl: broker1.url(),
152
+ onSignal: signalMock1,
153
+ onOffer: async () => ({ accept: true }),
154
+ topic
155
+ });
156
+ const received2: SignalMessage[] = [];
157
+ const signalMock2 = async (msg: SignalMessage) => {
158
+ received2.push(msg);
159
+ };
160
+ const {
161
+ signalManager: signalManager2,
162
+ router: router2,
163
+ peerId: peer2
164
+ } = await createSignalClientAndMessageRouter({
165
+ signalApiUrl: broker1.url(),
166
+ onSignal: signalMock2,
167
+ onOffer: async () => ({ accept: true }),
168
+ topic
169
+ });
170
+ const received3: SignalMessage[] = [];
171
+ const signalMock3 = async (msg: SignalMessage) => {
172
+ received3.push(msg);
173
+ };
174
+ const {
175
+ signalManager: signalManager3,
176
+ router: router3,
177
+ peerId: peer3
178
+ } = await createSignalClientAndMessageRouter({
179
+ signalApiUrl: broker1.url(),
180
+ onSignal: signalMock3,
181
+ onOffer: async () => ({ accept: true }),
182
+ topic
183
+ });
184
+
185
+ await signalManager1.join({ topic, peerId: peer1 });
186
+ await signalManager2.join({ topic, peerId: peer2 });
187
+ await signalManager3.join({ topic, peerId: peer3 });
188
+
189
+ // sending signal from peer1 to peer3.
190
+ const msg1to3: SignalMessage = {
191
+ author: peer1,
192
+ recipient: peer3,
193
+ sessionId: PublicKey.random(),
194
+ topic,
195
+ data: { signal: { json: '1to3' } }
196
+ };
197
+ await router1.signal(msg1to3);
198
+ await waitForExpect(() => {
199
+ expect(received3[0]).toBeAnObjectWith(msg1to3);
200
+ }, 4_000);
201
+
202
+ // sending signal from peer2 to peer3.
203
+ const msg2to3: SignalMessage = {
204
+ author: peer2,
205
+ recipient: peer3,
206
+ sessionId: PublicKey.random(),
207
+ topic,
208
+ data: { signal: { json: '2to3' } }
209
+ };
210
+ await router2.signal(msg2to3);
211
+ await waitForExpect(() => {
212
+ expect(received3[1]).toBeAnObjectWith(msg2to3);
213
+ }, 4_000);
214
+
215
+ // sending signal from peer3 to peer1.
216
+ const msg3to1: SignalMessage = {
217
+ author: peer3,
218
+ recipient: peer1,
219
+ sessionId: PublicKey.random(),
220
+ topic,
221
+ data: { signal: { json: '3to1' } }
222
+ };
223
+ await router3.signal(msg3to1);
224
+ await waitForExpect(() => {
225
+ expect(received1[0]).toBeAnObjectWith(msg3to1);
226
+ }, 4_000);
227
+ }).timeout(5_000);
228
+
229
+ it('two offers', async () => {
230
+ const {
231
+ signalManager: signalManager1,
232
+ router: router1,
233
+ peerId: peer1
234
+ } = await createSignalClientAndMessageRouter({
235
+ signalApiUrl: broker1.url(),
236
+ onSignal: (async () => {}) as any,
237
+ onOffer: async () => ({ accept: true }),
238
+ topic
239
+ });
240
+ const {
241
+ signalManager: signalManager2,
242
+ router: router2,
243
+ peerId: peer2
244
+ } = await createSignalClientAndMessageRouter({
245
+ signalApiUrl: broker1.url(),
246
+ onSignal: (async () => {}) as any,
247
+ onOffer: async () => ({ accept: true }),
248
+ topic
249
+ });
250
+
251
+ await signalManager1.join({ topic, peerId: peer1 });
252
+ await signalManager2.join({ topic, peerId: peer2 });
253
+
254
+ // sending offer from peer1 to peer2.
255
+ const answer1 = await router1.offer({
256
+ author: peer1,
257
+ recipient: peer2,
258
+ sessionId: PublicKey.random(),
259
+ topic,
260
+ data: { offer: {} }
261
+ });
262
+ expect(answer1.accept).toEqual(true);
263
+
264
+ // sending offer from peer2 to peer1.
265
+ const answer2 = await router2.offer({
266
+ author: peer2,
267
+ recipient: peer1,
268
+ sessionId: PublicKey.random(),
269
+ topic,
270
+ data: { offer: {} }
271
+ });
272
+ expect(answer2.accept).toEqual(true);
273
+ }).timeout(5_000);
274
+ });
@@ -0,0 +1,200 @@
1
+ //
2
+ // Copyright 2020 DXOS.org
3
+ //
4
+
5
+ import assert from 'assert';
6
+
7
+ import { Any } from '@dxos/codec-protobuf';
8
+ import { PublicKey } from '@dxos/keys';
9
+ import { log } from '@dxos/log';
10
+ import { schema } from '@dxos/protocols';
11
+ import { Answer, SwarmMessage } from '@dxos/protocols/proto/dxos/mesh/swarm';
12
+ import { ComplexMap, MakeOptional } from '@dxos/util';
13
+
14
+ import { OfferMessage, SignalMessage, SignalMessaging } from './signal-messaging';
15
+
16
+ interface OfferRecord {
17
+ resolve: (answer: Answer) => void;
18
+ reject: (error?: Error) => void;
19
+ }
20
+
21
+ interface MessageRouterOptions {
22
+ sendMessage: (params: { author: PublicKey; recipient: PublicKey; payload: Any }) => Promise<void>;
23
+ onOffer: (message: OfferMessage) => Promise<Answer>;
24
+ onSignal: (message: SignalMessage) => Promise<void>;
25
+ topic: PublicKey;
26
+ }
27
+
28
+ /**
29
+ * Adds offer/answer and signal interfaces.
30
+ */
31
+ export class MessageRouter implements SignalMessaging {
32
+ private readonly _onSignal: (message: SignalMessage) => Promise<void>;
33
+ private readonly _sendMessage: (msg: { author: PublicKey; recipient: PublicKey; payload: Any }) => Promise<void>;
34
+
35
+ private readonly _onOffer: (message: OfferMessage) => Promise<Answer>;
36
+ private readonly _topic: PublicKey;
37
+
38
+ private readonly _offerRecords: ComplexMap<PublicKey, OfferRecord> = new ComplexMap((key) => key.toHex());
39
+
40
+ constructor({ sendMessage, onSignal, onOffer, topic }: MessageRouterOptions) {
41
+ this._sendMessage = sendMessage;
42
+ this._onSignal = onSignal;
43
+ this._onOffer = onOffer;
44
+ this._topic = topic;
45
+ }
46
+
47
+ async receiveMessage({
48
+ author,
49
+ recipient,
50
+ payload
51
+ }: {
52
+ author: PublicKey;
53
+ recipient: PublicKey;
54
+ payload: Any;
55
+ }): Promise<void> {
56
+ if (payload.type_url !== 'dxos.mesh.swarm.SwarmMessage') {
57
+ // Ignore not swarm messages.
58
+ return;
59
+ }
60
+ const message: SwarmMessage = schema.getCodecForType('dxos.mesh.swarm.SwarmMessage').decode(payload.value);
61
+
62
+ if (!this._topic.equals(message.topic)) {
63
+ // Ignore messages from wrong topics.
64
+ return;
65
+ }
66
+
67
+ log('received', { from: author, to: recipient, msg: message });
68
+
69
+ if (message.data?.offer) {
70
+ await this._handleOffer({ author, recipient, message });
71
+ } else if (message.data?.answer) {
72
+ await this._resolveAnswers(message);
73
+ } else if (message.data?.signal) {
74
+ await this._handleSignal({ author, recipient, message });
75
+ }
76
+ }
77
+
78
+ async signal(message: SignalMessage): Promise<void> {
79
+ assert(message.data?.signal);
80
+ await this._sendReliableMessage({
81
+ author: message.author,
82
+ recipient: message.recipient,
83
+ message
84
+ });
85
+ }
86
+
87
+ async offer(message: OfferMessage): Promise<Answer> {
88
+ const networkMessage: SwarmMessage = {
89
+ ...message,
90
+ messageId: PublicKey.random()
91
+ };
92
+ return new Promise<Answer>((resolve, reject) => {
93
+ this._offerRecords.set(networkMessage.messageId!, { resolve, reject });
94
+ return this._sendReliableMessage({
95
+ author: message.author,
96
+ recipient: message.recipient,
97
+ message: networkMessage
98
+ });
99
+ });
100
+ }
101
+
102
+ private async _sendReliableMessage({
103
+ author,
104
+ recipient,
105
+ message
106
+ }: {
107
+ author: PublicKey;
108
+ recipient: PublicKey;
109
+ message: MakeOptional<SwarmMessage, 'messageId'>;
110
+ }): Promise<void> {
111
+ const networkMessage: SwarmMessage = {
112
+ ...message,
113
+ // Setting unique message_id if it not specified yet.
114
+ messageId: message.messageId ?? PublicKey.random()
115
+ };
116
+
117
+ log('sending', { from: author, to: recipient, msg: networkMessage });
118
+ await this._encodeAndSend({ author, recipient, message: networkMessage });
119
+ }
120
+
121
+ private async _encodeAndSend({
122
+ author,
123
+ recipient,
124
+ message
125
+ }: {
126
+ author: PublicKey;
127
+ recipient: PublicKey;
128
+ message: SwarmMessage;
129
+ }) {
130
+ await this._sendMessage({
131
+ author,
132
+ recipient,
133
+ payload: {
134
+ type_url: 'dxos.mesh.swarm.SwarmMessage',
135
+ value: schema.getCodecForType('dxos.mesh.swarm.SwarmMessage').encode(message)
136
+ }
137
+ });
138
+ }
139
+
140
+ private async _resolveAnswers(message: SwarmMessage): Promise<void> {
141
+ assert(message.data?.answer?.offerMessageId, 'No offerMessageId');
142
+ const offerRecord = this._offerRecords.get(message.data.answer.offerMessageId);
143
+ if (offerRecord) {
144
+ this._offerRecords.delete(message.data.answer.offerMessageId);
145
+ assert(message.data?.answer, 'No answer');
146
+ log('resolving', { answer: message.data.answer });
147
+ offerRecord.resolve(message.data.answer);
148
+ }
149
+ }
150
+
151
+ private async _handleOffer({
152
+ author,
153
+ recipient,
154
+ message
155
+ }: {
156
+ author: PublicKey;
157
+ recipient: PublicKey;
158
+ message: SwarmMessage;
159
+ }): Promise<void> {
160
+ assert(message.data.offer, 'No offer');
161
+ const offerMessage: OfferMessage = {
162
+ author,
163
+ recipient,
164
+ ...message,
165
+ data: { offer: message.data.offer }
166
+ };
167
+ const answer = await this._onOffer(offerMessage);
168
+ answer.offerMessageId = message.messageId;
169
+ await this._sendReliableMessage({
170
+ author: recipient,
171
+ recipient: author,
172
+ message: {
173
+ topic: message.topic,
174
+ sessionId: message.sessionId,
175
+ data: { answer }
176
+ }
177
+ });
178
+ }
179
+
180
+ private async _handleSignal({
181
+ author,
182
+ recipient,
183
+ message
184
+ }: {
185
+ author: PublicKey;
186
+ recipient: PublicKey;
187
+ message: SwarmMessage;
188
+ }): Promise<void> {
189
+ assert(message.messageId);
190
+ assert(message.data.signal, 'No Signal');
191
+ const signalMessage: SignalMessage = {
192
+ author,
193
+ recipient,
194
+ ...message,
195
+ data: { signal: message.data.signal }
196
+ };
197
+
198
+ await this._onSignal(signalMessage);
199
+ }
200
+ }
@@ -0,0 +1,20 @@
1
+ //
2
+ // Copyright 2020 DXOS.org
3
+ //
4
+
5
+ import { PublicKey } from '@dxos/keys';
6
+
7
+ /**
8
+ * Signal peer discovery interface.
9
+ */
10
+ export interface SignalConnection {
11
+ /**
12
+ * Join topic on signal network, to be discoverable by other peers.
13
+ */
14
+ join(params: { topic: PublicKey; peerId: PublicKey }): Promise<void>;
15
+
16
+ /**
17
+ * Leave topic on signal network, to stop being discoverable by other peers.
18
+ */
19
+ leave(params: { topic: PublicKey; peerId: PublicKey }): Promise<void>;
20
+ }
@@ -0,0 +1,38 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import { PublicKey } from '@dxos/keys';
6
+ import { Answer, Offer, Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
7
+
8
+ export interface OfferMessage {
9
+ author: PublicKey;
10
+ recipient: PublicKey;
11
+ topic: PublicKey;
12
+ sessionId: PublicKey;
13
+ data: { offer: Offer };
14
+ }
15
+
16
+ export interface SignalMessage {
17
+ author: PublicKey;
18
+ recipient: PublicKey;
19
+ topic: PublicKey;
20
+ sessionId: PublicKey;
21
+ data: { signal: Signal };
22
+ }
23
+
24
+ /**
25
+ * Signal peer messaging interface.
26
+ */
27
+
28
+ export interface SignalMessaging {
29
+ /**
30
+ * Offer/answer RPC.
31
+ */
32
+ offer(msg: OfferMessage): Promise<Answer>;
33
+
34
+ /**
35
+ * Reliably send a signal to a peer.
36
+ */
37
+ signal(msg: SignalMessage): Promise<void>;
38
+ }