@dxos/network-manager 0.1.13 → 0.1.14

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 (256) hide show
  1. package/dist/lib/browser/index.mjs +2126 -0
  2. package/dist/lib/browser/index.mjs.map +7 -0
  3. package/dist/lib/browser/meta.json +1 -0
  4. package/dist/lib/browser/testing/index.mjs +2196 -0
  5. package/dist/lib/browser/testing/index.mjs.map +7 -0
  6. package/dist/lib/node/index.cjs +2173 -0
  7. package/dist/lib/node/index.cjs.map +7 -0
  8. package/dist/lib/node/meta.json +1 -0
  9. package/dist/lib/node/testing/index.cjs +2225 -0
  10. package/dist/lib/node/testing/index.cjs.map +7 -0
  11. package/dist/{src → types/src}/connection-log.d.ts +0 -0
  12. package/dist/types/src/connection-log.d.ts.map +1 -0
  13. package/dist/{src → types/src}/index.d.ts +1 -0
  14. package/dist/types/src/index.d.ts.map +1 -0
  15. package/dist/{src → types/src}/network-manager.d.ts +9 -11
  16. package/dist/types/src/network-manager.d.ts.map +1 -0
  17. package/dist/{src → types/src}/protocol-factory.d.ts +11 -5
  18. package/dist/types/src/protocol-factory.d.ts.map +1 -0
  19. package/dist/{src → types/src}/signal/index.d.ts +0 -0
  20. package/dist/types/src/signal/index.d.ts.map +1 -0
  21. package/dist/{src → types/src}/signal/integration.test.d.ts +0 -0
  22. package/dist/types/src/signal/integration.test.d.ts.map +1 -0
  23. package/dist/{src → types/src}/signal/message-router.d.ts +0 -0
  24. package/dist/types/src/signal/message-router.d.ts.map +1 -0
  25. package/dist/{src → types/src}/signal/message-router.test.d.ts +0 -0
  26. package/dist/types/src/signal/message-router.test.d.ts.map +1 -0
  27. package/dist/{src → types/src}/signal/signal-connection.d.ts +0 -0
  28. package/dist/types/src/signal/signal-connection.d.ts.map +1 -0
  29. package/dist/{src → types/src}/signal/signal-messenger.d.ts +0 -0
  30. package/dist/types/src/signal/signal-messenger.d.ts.map +1 -0
  31. package/dist/{src → types/src}/swarm/connection.d.ts +5 -17
  32. package/dist/types/src/swarm/connection.d.ts.map +1 -0
  33. package/dist/{src → types/src}/swarm/index.d.ts +0 -0
  34. package/dist/types/src/swarm/index.d.ts.map +1 -0
  35. package/dist/types/src/swarm/peer.d.ts +70 -0
  36. package/dist/types/src/swarm/peer.d.ts.map +1 -0
  37. package/dist/{src → types/src}/swarm/swarm-mapper.d.ts +1 -1
  38. package/dist/types/src/swarm/swarm-mapper.d.ts.map +1 -0
  39. package/dist/{src → types/src}/swarm/swarm.d.ts +4 -8
  40. package/dist/types/src/swarm/swarm.d.ts.map +1 -0
  41. package/dist/{src → types/src}/swarm/swarm.test.d.ts +0 -0
  42. package/dist/types/src/swarm/swarm.test.d.ts.map +1 -0
  43. package/dist/{src → types/src}/testing/index.d.ts +0 -0
  44. package/dist/types/src/testing/index.d.ts.map +1 -0
  45. package/dist/{src → types/src}/testing/test-builder.d.ts +1 -1
  46. package/dist/types/src/testing/test-builder.d.ts.map +1 -0
  47. package/dist/{src → types/src}/testing/test-protocol.d.ts +2 -2
  48. package/dist/types/src/testing/test-protocol.d.ts.map +1 -0
  49. package/dist/{src → types/src}/tests/basic-test-suite.d.ts +0 -0
  50. package/dist/types/src/tests/basic-test-suite.d.ts.map +1 -0
  51. package/dist/{src → types/src}/tests/memory-transport.test.d.ts +0 -0
  52. package/dist/types/src/tests/memory-transport.test.d.ts.map +1 -0
  53. package/dist/{src → types/src}/tests/presence.test.d.ts +0 -0
  54. package/dist/types/src/tests/presence.test.d.ts.map +1 -0
  55. package/dist/{src → types/src}/tests/property-test-suite.d.ts +0 -0
  56. package/dist/types/src/tests/property-test-suite.d.ts.map +1 -0
  57. package/dist/{src → types/src}/tests/utils.d.ts +0 -0
  58. package/dist/types/src/tests/utils.d.ts.map +1 -0
  59. package/dist/{src → types/src}/tests/webrtc-transport.test.d.ts +0 -0
  60. package/dist/types/src/tests/webrtc-transport.test.d.ts.map +1 -0
  61. package/dist/{src → types/src}/topology/fully-connected-topology.d.ts +0 -0
  62. package/dist/types/src/topology/fully-connected-topology.d.ts.map +1 -0
  63. package/dist/{src → types/src}/topology/index.d.ts +0 -0
  64. package/dist/types/src/topology/index.d.ts.map +1 -0
  65. package/dist/{src → types/src}/topology/mmst-topology.d.ts +0 -0
  66. package/dist/types/src/topology/mmst-topology.d.ts.map +1 -0
  67. package/dist/{src → types/src}/topology/star-topology.d.ts +0 -0
  68. package/dist/types/src/topology/star-topology.d.ts.map +1 -0
  69. package/dist/{src → types/src}/topology/topology.d.ts +0 -0
  70. package/dist/types/src/topology/topology.d.ts.map +1 -0
  71. package/dist/{src → types/src}/transport/index.d.ts +0 -0
  72. package/dist/types/src/transport/index.d.ts.map +1 -0
  73. package/dist/{src → types/src}/transport/memory-transport.d.ts +0 -0
  74. package/dist/types/src/transport/memory-transport.d.ts.map +1 -0
  75. package/dist/{src → types/src}/transport/memory-transport.test.d.ts +0 -0
  76. package/dist/types/src/transport/memory-transport.test.d.ts.map +1 -0
  77. package/dist/{src → types/src}/transport/transport.d.ts +1 -1
  78. package/dist/types/src/transport/transport.d.ts.map +1 -0
  79. package/dist/{src → types/src}/transport/webrtc-simple-peer.test.d.ts +0 -0
  80. package/dist/types/src/transport/webrtc-simple-peer.test.d.ts.map +1 -0
  81. package/dist/{src → types/src}/transport/webrtc-transport-proxy.d.ts +1 -1
  82. package/dist/types/src/transport/webrtc-transport-proxy.d.ts.map +1 -0
  83. package/dist/{src → types/src}/transport/webrtc-transport-proxy.test.d.ts +0 -0
  84. package/dist/types/src/transport/webrtc-transport-proxy.test.d.ts.map +1 -0
  85. package/dist/{src → types/src}/transport/webrtc-transport-service.d.ts +0 -0
  86. package/dist/types/src/transport/webrtc-transport-service.d.ts.map +1 -0
  87. package/dist/{src → types/src}/transport/webrtc-transport.d.ts +1 -1
  88. package/dist/types/src/transport/webrtc-transport.d.ts.map +1 -0
  89. package/dist/{src → types/src}/transport/webrtc-transport.test.d.ts +0 -0
  90. package/dist/types/src/transport/webrtc-transport.test.d.ts.map +1 -0
  91. package/dist/{src → types/src}/transport/webrtc.d.ts +0 -0
  92. package/dist/types/src/transport/webrtc.d.ts.map +1 -0
  93. package/dist/types/src/types.d.ts +6 -0
  94. package/dist/types/src/types.d.ts.map +1 -0
  95. package/dist/types/src/wire-protocol.d.ts +37 -0
  96. package/dist/types/src/wire-protocol.d.ts.map +1 -0
  97. package/package.json +24 -22
  98. package/src/connection-log.ts +8 -8
  99. package/src/globals.d.ts +1 -1
  100. package/src/index.ts +1 -0
  101. package/src/network-manager.ts +14 -5
  102. package/src/protocol-factory.ts +7 -4
  103. package/src/signal/integration.test.ts +8 -7
  104. package/src/signal/message-router.test.ts +14 -15
  105. package/src/signal/message-router.ts +1 -1
  106. package/src/swarm/connection.ts +11 -55
  107. package/src/swarm/peer.ts +119 -30
  108. package/src/swarm/swarm.test.ts +9 -8
  109. package/src/swarm/swarm.ts +97 -116
  110. package/src/testing/test-builder.ts +4 -1
  111. package/src/testing/test-protocol.ts +1 -1
  112. package/src/tests/basic-test-suite.ts +7 -6
  113. package/src/tests/memory-transport.test.ts +1 -1
  114. package/src/tests/presence.test.ts +5 -4
  115. package/src/tests/property-test-suite.ts +4 -3
  116. package/src/tests/utils.ts +1 -1
  117. package/src/tests/webrtc-transport.test.ts +2 -2
  118. package/src/transport/memory-transport.test.ts +4 -4
  119. package/src/transport/memory-transport.ts +5 -5
  120. package/src/transport/webrtc-simple-peer.test.ts +13 -10
  121. package/src/transport/webrtc-transport-proxy.test.ts +9 -13
  122. package/src/transport/webrtc-transport-proxy.ts +1 -1
  123. package/src/transport/webrtc-transport-service.ts +2 -2
  124. package/src/transport/webrtc-transport.test.ts +4 -4
  125. package/src/transport/webrtc-transport.ts +3 -3
  126. package/src/wire-protocol.ts +75 -0
  127. package/testing.d.ts +1 -1
  128. package/testing.js +1 -1
  129. package/dist/src/connection-log.d.ts.map +0 -1
  130. package/dist/src/connection-log.js +0 -98
  131. package/dist/src/connection-log.js.map +0 -1
  132. package/dist/src/index.d.ts.map +0 -1
  133. package/dist/src/index.js +0 -28
  134. package/dist/src/index.js.map +0 -1
  135. package/dist/src/network-manager.d.ts.map +0 -1
  136. package/dist/src/network-manager.js +0 -118
  137. package/dist/src/network-manager.js.map +0 -1
  138. package/dist/src/protocol-factory.d.ts.map +0 -1
  139. package/dist/src/protocol-factory.js +0 -66
  140. package/dist/src/protocol-factory.js.map +0 -1
  141. package/dist/src/signal/index.d.ts.map +0 -1
  142. package/dist/src/signal/index.js +0 -23
  143. package/dist/src/signal/index.js.map +0 -1
  144. package/dist/src/signal/integration.test.d.ts.map +0 -1
  145. package/dist/src/signal/integration.test.js +0 -105
  146. package/dist/src/signal/integration.test.js.map +0 -1
  147. package/dist/src/signal/message-router.d.ts.map +0 -1
  148. package/dist/src/signal/message-router.js +0 -135
  149. package/dist/src/signal/message-router.js.map +0 -1
  150. package/dist/src/signal/message-router.test.d.ts.map +0 -1
  151. package/dist/src/signal/message-router.test.js +0 -211
  152. package/dist/src/signal/message-router.test.js.map +0 -1
  153. package/dist/src/signal/signal-connection.d.ts.map +0 -1
  154. package/dist/src/signal/signal-connection.js +0 -6
  155. package/dist/src/signal/signal-connection.js.map +0 -1
  156. package/dist/src/signal/signal-messenger.d.ts.map +0 -1
  157. package/dist/src/signal/signal-messenger.js +0 -6
  158. package/dist/src/signal/signal-messenger.js.map +0 -1
  159. package/dist/src/swarm/connection.d.ts.map +0 -1
  160. package/dist/src/swarm/connection.js +0 -204
  161. package/dist/src/swarm/connection.js.map +0 -1
  162. package/dist/src/swarm/index.d.ts.map +0 -1
  163. package/dist/src/swarm/index.js +0 -23
  164. package/dist/src/swarm/index.js.map +0 -1
  165. package/dist/src/swarm/peer.d.ts +0 -45
  166. package/dist/src/swarm/peer.d.ts.map +0 -1
  167. package/dist/src/swarm/peer.js +0 -113
  168. package/dist/src/swarm/peer.js.map +0 -1
  169. package/dist/src/swarm/swarm-mapper.d.ts.map +0 -1
  170. package/dist/src/swarm/swarm-mapper.js +0 -92
  171. package/dist/src/swarm/swarm-mapper.js.map +0 -1
  172. package/dist/src/swarm/swarm.d.ts.map +0 -1
  173. package/dist/src/swarm/swarm.js +0 -305
  174. package/dist/src/swarm/swarm.js.map +0 -1
  175. package/dist/src/swarm/swarm.test.d.ts.map +0 -1
  176. package/dist/src/swarm/swarm.test.js +0 -135
  177. package/dist/src/swarm/swarm.test.js.map +0 -1
  178. package/dist/src/testing/index.d.ts.map +0 -1
  179. package/dist/src/testing/index.js +0 -22
  180. package/dist/src/testing/index.js.map +0 -1
  181. package/dist/src/testing/test-builder.d.ts.map +0 -1
  182. package/dist/src/testing/test-builder.js +0 -145
  183. package/dist/src/testing/test-builder.js.map +0 -1
  184. package/dist/src/testing/test-protocol.d.ts.map +0 -1
  185. package/dist/src/testing/test-protocol.js +0 -143
  186. package/dist/src/testing/test-protocol.js.map +0 -1
  187. package/dist/src/tests/basic-test-suite.d.ts.map +0 -1
  188. package/dist/src/tests/basic-test-suite.js +0 -142
  189. package/dist/src/tests/basic-test-suite.js.map +0 -1
  190. package/dist/src/tests/memory-transport.test.d.ts.map +0 -1
  191. package/dist/src/tests/memory-transport.test.js +0 -12
  192. package/dist/src/tests/memory-transport.test.js.map +0 -1
  193. package/dist/src/tests/presence.test.d.ts.map +0 -1
  194. package/dist/src/tests/presence.test.js +0 -61
  195. package/dist/src/tests/presence.test.js.map +0 -1
  196. package/dist/src/tests/property-test-suite.d.ts.map +0 -1
  197. package/dist/src/tests/property-test-suite.js +0 -203
  198. package/dist/src/tests/property-test-suite.js.map +0 -1
  199. package/dist/src/tests/utils.d.ts.map +0 -1
  200. package/dist/src/tests/utils.js +0 -76
  201. package/dist/src/tests/utils.js.map +0 -1
  202. package/dist/src/tests/webrtc-transport.test.d.ts.map +0 -1
  203. package/dist/src/tests/webrtc-transport.test.js +0 -16
  204. package/dist/src/tests/webrtc-transport.test.js.map +0 -1
  205. package/dist/src/topology/fully-connected-topology.d.ts.map +0 -1
  206. package/dist/src/topology/fully-connected-topology.js +0 -35
  207. package/dist/src/topology/fully-connected-topology.js.map +0 -1
  208. package/dist/src/topology/index.d.ts.map +0 -1
  209. package/dist/src/topology/index.js +0 -24
  210. package/dist/src/topology/index.js.map +0 -1
  211. package/dist/src/topology/mmst-topology.d.ts.map +0 -1
  212. package/dist/src/topology/mmst-topology.js +0 -73
  213. package/dist/src/topology/mmst-topology.js.map +0 -1
  214. package/dist/src/topology/star-topology.d.ts.map +0 -1
  215. package/dist/src/topology/star-topology.js +0 -60
  216. package/dist/src/topology/star-topology.js.map +0 -1
  217. package/dist/src/topology/topology.d.ts.map +0 -1
  218. package/dist/src/topology/topology.js +0 -6
  219. package/dist/src/topology/topology.js.map +0 -1
  220. package/dist/src/transport/index.d.ts.map +0 -1
  221. package/dist/src/transport/index.js +0 -25
  222. package/dist/src/transport/index.js.map +0 -1
  223. package/dist/src/transport/memory-transport.d.ts.map +0 -1
  224. package/dist/src/transport/memory-transport.js +0 -138
  225. package/dist/src/transport/memory-transport.js.map +0 -1
  226. package/dist/src/transport/memory-transport.test.d.ts.map +0 -1
  227. package/dist/src/transport/memory-transport.test.js +0 -96
  228. package/dist/src/transport/memory-transport.test.js.map +0 -1
  229. package/dist/src/transport/transport.d.ts.map +0 -1
  230. package/dist/src/transport/transport.js +0 -6
  231. package/dist/src/transport/transport.js.map +0 -1
  232. package/dist/src/transport/webrtc-simple-peer.test.d.ts.map +0 -1
  233. package/dist/src/transport/webrtc-simple-peer.test.js +0 -24
  234. package/dist/src/transport/webrtc-simple-peer.test.js.map +0 -1
  235. package/dist/src/transport/webrtc-transport-proxy.d.ts.map +0 -1
  236. package/dist/src/transport/webrtc-transport-proxy.js +0 -139
  237. package/dist/src/transport/webrtc-transport-proxy.js.map +0 -1
  238. package/dist/src/transport/webrtc-transport-proxy.test.d.ts.map +0 -1
  239. package/dist/src/transport/webrtc-transport-proxy.test.js +0 -219
  240. package/dist/src/transport/webrtc-transport-proxy.test.js.map +0 -1
  241. package/dist/src/transport/webrtc-transport-service.d.ts.map +0 -1
  242. package/dist/src/transport/webrtc-transport-service.js +0 -93
  243. package/dist/src/transport/webrtc-transport-service.js.map +0 -1
  244. package/dist/src/transport/webrtc-transport.d.ts.map +0 -1
  245. package/dist/src/transport/webrtc-transport.js +0 -77
  246. package/dist/src/transport/webrtc-transport.js.map +0 -1
  247. package/dist/src/transport/webrtc-transport.test.d.ts.map +0 -1
  248. package/dist/src/transport/webrtc-transport.test.js +0 -91
  249. package/dist/src/transport/webrtc-transport.test.js.map +0 -1
  250. package/dist/src/transport/webrtc.d.ts.map +0 -1
  251. package/dist/src/transport/webrtc.js +0 -17
  252. package/dist/src/transport/webrtc.js.map +0 -1
  253. package/dist/src/types.d.ts +0 -6
  254. package/dist/src/types.d.ts.map +0 -1
  255. package/dist/src/types.js +0 -6
  256. package/dist/src/types.js.map +0 -1
@@ -7,7 +7,6 @@ import assert from 'node:assert';
7
7
  import { Event } from '@dxos/async';
8
8
  import { PublicKey } from '@dxos/keys';
9
9
  import { log } from '@dxos/log';
10
- import { Protocol } from '@dxos/mesh-protocol';
11
10
  import { Messenger, SignalManager } from '@dxos/messaging';
12
11
  import { ComplexMap } from '@dxos/util';
13
12
 
@@ -16,9 +15,11 @@ import { SignalConnection } from './signal';
16
15
  import { Swarm, SwarmMapper } from './swarm';
17
16
  import { Topology } from './topology';
18
17
  import { TransportFactory } from './transport';
18
+ import { WireProtocolProvider } from './wire-protocol';
19
19
 
20
- export type ProtocolProvider = (opts: { channel: Buffer; initiator: boolean }) => Protocol;
21
-
20
+ /**
21
+ * Represents a single connection to a remote peer.
22
+ */
22
23
  export type SwarmConnection = {
23
24
  close(): Promise<void>;
24
25
  };
@@ -38,7 +39,7 @@ export type SwarmOptions = {
38
39
  /**
39
40
  * Protocol to use for every connection.
40
41
  */
41
- protocol: ProtocolProvider;
42
+ protocolProvider: WireProtocolProvider;
42
43
 
43
44
  /**
44
45
  * Requested topology. Must be a new instance for every swarm.
@@ -48,6 +49,7 @@ export type SwarmOptions = {
48
49
  /**
49
50
  * Presence plugin for network mapping, if exists.
50
51
  */
52
+ // TODO(dmaretskyi): Remove this dependency.
51
53
  presence?: any;
52
54
 
53
55
  /**
@@ -134,7 +136,14 @@ export class NetworkManager {
134
136
  * Join the swarm.
135
137
  */
136
138
  // TODO(burdon): Join/Open? Swarm abstraction?
137
- async joinSwarm({ topic, peerId, topology, protocol, presence, label }: SwarmOptions): Promise<SwarmConnection> {
139
+ async joinSwarm({
140
+ topic,
141
+ peerId,
142
+ topology,
143
+ protocolProvider: protocol,
144
+ presence,
145
+ label
146
+ }: SwarmOptions): Promise<SwarmConnection> {
138
147
  assert(PublicKey.isPublicKey(topic));
139
148
  assert(PublicKey.isPublicKey(peerId));
140
149
  assert(topology);
@@ -9,14 +9,17 @@ import { PublicKey } from '@dxos/keys';
9
9
  import { log } from '@dxos/log';
10
10
  import { Extension, Protocol } from '@dxos/mesh-protocol';
11
11
 
12
- import { ProtocolProvider } from './network-manager';
13
-
14
12
  interface ProtocolFactoryOptions {
15
13
  plugins: any[];
16
14
  getTopics: () => Buffer[];
17
15
  session: Record<string, any>;
18
16
  }
19
17
 
18
+ /**
19
+ * @deprecated Replaced by WireProtocolProvider.
20
+ */
21
+ export type MeshProtocolProvider = (params: { channel: Buffer; initiator: boolean }) => Protocol;
22
+
20
23
  /**
21
24
  * Returns a function that takes a channel parameter, returns a Protocol object
22
25
  * with its context set to channel, plugins from plugins parameter and session
@@ -30,7 +33,7 @@ export const protocolFactory = ({
30
33
  session = {},
31
34
  plugins = [],
32
35
  getTopics
33
- }: ProtocolFactoryOptions): ProtocolProvider => {
36
+ }: ProtocolFactoryOptions): MeshProtocolProvider => {
34
37
  assert(getTopics);
35
38
 
36
39
  // eslint-disable-next-line no-unused-vars
@@ -76,7 +79,7 @@ export const transportProtocolProvider = (
76
79
  rendezvousKey: Buffer,
77
80
  peerId: Buffer,
78
81
  protocolPlugin: any
79
- ): ProtocolProvider => {
82
+ ): MeshProtocolProvider => {
80
83
  return protocolFactory({
81
84
  getTopics: () => [rendezvousKey],
82
85
  session: { peerId: PublicKey.stringify(peerId) },
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- // @dxos/mocha platform=nodejs
5
+ // @dxos/test platform=nodejs
6
6
 
7
7
  import { expect } from 'earljs';
8
8
  import waitForExpect from 'wait-for-expect';
@@ -10,18 +10,19 @@ import waitForExpect from 'wait-for-expect';
10
10
  import { PublicKey } from '@dxos/keys';
11
11
  import { WebsocketSignalManager } from '@dxos/messaging';
12
12
  import { createTestBroker, TestBroker } from '@dxos/signal';
13
+ import { afterAll, beforeAll, describe, test } from '@dxos/test';
13
14
 
14
15
  import { MessageRouter } from './message-router';
15
16
  import { SignalMessage } from './signal-messenger';
16
17
 
17
- describe('Signal Integration Test', function () {
18
+ describe('Signal Integration Test', () => {
18
19
  let broker: TestBroker;
19
20
 
20
- before(async function () {
21
+ beforeAll(async () => {
21
22
  broker = await createTestBroker();
22
23
  });
23
24
 
24
- after(function () {
25
+ afterAll(() => {
25
26
  broker.stop();
26
27
  });
27
28
 
@@ -47,7 +48,7 @@ describe('Signal Integration Test', function () {
47
48
  };
48
49
  };
49
50
 
50
- it('two peers connecting', async function () {
51
+ test('two peers connecting', async () => {
51
52
  const peer1 = PublicKey.random();
52
53
  const peer2 = PublicKey.random();
53
54
  const topic = PublicKey.random();
@@ -99,7 +100,7 @@ describe('Signal Integration Test', function () {
99
100
  recipient: peer2,
100
101
  sessionId: PublicKey.random(),
101
102
  data: {
102
- signal: { json: JSON.stringify({ foo: 'bar' }) }
103
+ signal: { payload: { message: 'Hello world!' } }
103
104
  }
104
105
  };
105
106
  await peerNetworking1.messageRouter.signal(message);
@@ -116,7 +117,7 @@ describe('Signal Integration Test', function () {
116
117
  recipient: peer1,
117
118
  sessionId: PublicKey.random(),
118
119
  data: {
119
- signal: { json: JSON.stringify({ foo: 'bar' }) }
120
+ signal: { payload: { foo: 'bar' } }
120
121
  }
121
122
  };
122
123
  await peerNetworking2.messageRouter.signal(message);
@@ -2,10 +2,9 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- // @dxos/mocha platform=nodejs
5
+ // @dxos/test platform=nodejs
6
6
 
7
7
  import { expect } from 'earljs';
8
- import { it, describe } from 'mocha';
9
8
  import waitForExpect from 'wait-for-expect';
10
9
 
11
10
  import { Awaited } from '@dxos/async';
@@ -13,25 +12,25 @@ import { PublicKey } from '@dxos/keys';
13
12
  import { Messenger, WebsocketSignalManager } from '@dxos/messaging';
14
13
  import { Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
15
14
  import { createTestBroker } from '@dxos/signal';
16
- import { afterTest } from '@dxos/testutils';
15
+ import { afterAll, beforeAll, describe, test, afterTest } from '@dxos/test';
17
16
 
18
17
  import { MessageRouter } from './message-router';
19
18
  import { OfferMessage, SignalMessage } from './signal-messenger';
20
19
 
21
- describe('MessageRouter', function () {
20
+ describe('MessageRouter', () => {
22
21
  let topic: PublicKey;
23
22
 
24
23
  let broker1: Awaited<ReturnType<typeof createTestBroker>>;
25
24
 
26
- before(async function () {
25
+ beforeAll(async () => {
27
26
  broker1 = await createTestBroker();
28
27
  });
29
28
 
30
- beforeEach(function () {
29
+ beforeEach(() => {
31
30
  topic = PublicKey.random();
32
31
  });
33
32
 
34
- after(function () {
33
+ afterAll(() => {
35
34
  broker1.stop();
36
35
  });
37
36
 
@@ -72,7 +71,7 @@ describe('MessageRouter', function () {
72
71
  };
73
72
  };
74
73
 
75
- it('signaling between 2 clients', async () => {
74
+ test('signaling between 2 clients', async () => {
76
75
  const received: SignalMessage[] = [];
77
76
  const signalMock1 = async (msg: SignalMessage) => {
78
77
  received.push(msg);
@@ -99,7 +98,7 @@ describe('MessageRouter', function () {
99
98
  recipient: peer1,
100
99
  sessionId: PublicKey.random(),
101
100
  topic,
102
- data: { signal: { json: JSON.stringify({ asd: 'asd' }) } }
101
+ data: { signal: { payload: { msg: 'Some info' } } }
103
102
  };
104
103
  await router2.signal(msg);
105
104
 
@@ -108,7 +107,7 @@ describe('MessageRouter', function () {
108
107
  }, 4_000);
109
108
  }).timeout(5_000);
110
109
 
111
- it('offer/answer', async () => {
110
+ test('offer/answer', async () => {
112
111
  const {
113
112
  signalManager: signalManager1,
114
113
  router: router1,
@@ -138,7 +137,7 @@ describe('MessageRouter', function () {
138
137
  expect(answer.accept).toEqual(true);
139
138
  }).timeout(5_000);
140
139
 
141
- it('signaling between 3 clients', async () => {
140
+ test('signaling between 3 clients', async () => {
142
141
  const received1: SignalMessage[] = [];
143
142
  const signalMock1 = async (msg: SignalMessage) => {
144
143
  received1.push(msg);
@@ -192,7 +191,7 @@ describe('MessageRouter', function () {
192
191
  recipient: peer3,
193
192
  sessionId: PublicKey.random(),
194
193
  topic,
195
- data: { signal: { json: '1to3' } }
194
+ data: { signal: { payload: { msg: '1to3' } } }
196
195
  };
197
196
  await router1.signal(msg1to3);
198
197
  await waitForExpect(() => {
@@ -205,7 +204,7 @@ describe('MessageRouter', function () {
205
204
  recipient: peer3,
206
205
  sessionId: PublicKey.random(),
207
206
  topic,
208
- data: { signal: { json: '2to3' } }
207
+ data: { signal: { payload: { msg: '2to3' } } }
209
208
  };
210
209
  await router2.signal(msg2to3);
211
210
  await waitForExpect(() => {
@@ -218,7 +217,7 @@ describe('MessageRouter', function () {
218
217
  recipient: peer1,
219
218
  sessionId: PublicKey.random(),
220
219
  topic,
221
- data: { signal: { json: '3to1' } }
220
+ data: { signal: { payload: { msg: '3to1' } } }
222
221
  };
223
222
  await router3.signal(msg3to1);
224
223
  await waitForExpect(() => {
@@ -226,7 +225,7 @@ describe('MessageRouter', function () {
226
225
  }, 4_000);
227
226
  }).timeout(5_000);
228
227
 
229
- it('two offers', async () => {
228
+ test('two offers', async () => {
230
229
  const {
231
230
  signalManager: signalManager1,
232
231
  router: router1,
@@ -2,7 +2,7 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
 
7
7
  import { Any } from '@dxos/codec-protobuf';
8
8
  import { PublicKey } from '@dxos/keys';
@@ -8,11 +8,11 @@ import { Event, synchronized } from '@dxos/async';
8
8
  import { ErrorStream } from '@dxos/debug';
9
9
  import { PublicKey } from '@dxos/keys';
10
10
  import { log } from '@dxos/log';
11
- import { Protocol } from '@dxos/mesh-protocol';
12
11
  import { Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
13
12
 
14
13
  import { SignalMessage, SignalMessenger } from '../signal';
15
14
  import { Transport, TransportFactory } from '../transport';
15
+ import { WireProtocol } from '../wire-protocol';
16
16
 
17
17
  /**
18
18
  * State machine for each connection.
@@ -25,25 +25,10 @@ export enum ConnectionState {
25
25
  INITIAL = 'INITIAL',
26
26
 
27
27
  /**
28
- * Originating a connection.
29
- */
30
- INITIATING_CONNECTION = 'INITIATING_CONNECTION',
31
-
32
- /**
33
- * Waiting for a connection to be originated from the remote peer.
28
+ * Trying to establish connection.
34
29
  */
35
30
  CONNECTING = 'CONNECTING',
36
31
 
37
- /**
38
- * Peer rejected offer.
39
- */
40
- ACCEPTED = 'ACCEPTED',
41
-
42
- /**
43
- * Peer rejected offer.
44
- */
45
- REJECTED = 'REJECTED',
46
-
47
32
  /**
48
33
  * Connection is established.
49
34
  */
@@ -57,6 +42,7 @@ export enum ConnectionState {
57
42
 
58
43
  /**
59
44
  * Represents a connection to a remote peer.
45
+ * Owns a transport paired together with a wire-protocol.
60
46
  */
61
47
  export class Connection {
62
48
  private _state: ConnectionState = ConnectionState.INITIAL;
@@ -73,7 +59,7 @@ export class Connection {
73
59
  public readonly sessionId: PublicKey,
74
60
  public readonly initiator: boolean,
75
61
  private readonly _signalMessaging: SignalMessenger,
76
- private readonly _protocol: Protocol,
62
+ private readonly _protocol: WireProtocol,
77
63
  private readonly _transportFactory: TransportFactory
78
64
  ) {}
79
65
 
@@ -89,48 +75,18 @@ export class Connection {
89
75
  return this._protocol;
90
76
  }
91
77
 
92
- // TODO(burdon): Make async.
93
- initiate() {
94
- this._signalMessaging
95
- .offer({
96
- author: this.ownId,
97
- recipient: this.remoteId,
98
- sessionId: this.sessionId,
99
- topic: this.topic,
100
- data: { offer: {} }
101
- })
102
- .then((answer) => {
103
- log('received', { answer, topic: this.topic, ownId: this.ownId, remoteId: this.remoteId });
104
- if (this.state !== ConnectionState.INITIAL) {
105
- log('ignoring response');
106
- return;
107
- }
108
-
109
- if (answer.accept) {
110
- try {
111
- this.openConnection();
112
- } catch (err: any) {
113
- this.errors.raise(err);
114
- }
115
- } else {
116
- // If the peer rejected our connection remove it from the set of candidates.
117
- this._changeState(ConnectionState.REJECTED);
118
- }
119
-
120
- this._changeState(ConnectionState.ACCEPTED);
121
- })
122
- .catch((err) => {
123
- this.errors.raise(err);
124
- });
125
- }
126
-
127
78
  /**
128
79
  * Create an underlying transport and prepares it for the connection.
129
80
  */
130
81
  // TODO(burdon): Make async?
131
82
  openConnection() {
132
83
  assert(this._state === ConnectionState.INITIAL, 'Invalid state.');
133
- this._changeState(this.initiator ? ConnectionState.INITIATING_CONNECTION : ConnectionState.CONNECTING);
84
+ this._changeState(ConnectionState.CONNECTING);
85
+
86
+ // TODO(dmaretskyi): Initialize only after the transport has established connection.
87
+ this._protocol.initialize().catch((err) => {
88
+ this.errors.raise(err);
89
+ });
134
90
 
135
91
  assert(!this._transport);
136
92
  this._transport = this._transportFactory.createTransport({
@@ -176,7 +132,7 @@ export class Connection {
176
132
 
177
133
  try {
178
134
  // Gracefully close the stream flushing any unsent data packets.
179
- await this._protocol.close();
135
+ await this._protocol.destroy();
180
136
  } catch (err: any) {
181
137
  log.catch(err);
182
138
  }
package/src/swarm/peer.ts CHANGED
@@ -2,18 +2,24 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
 
7
7
  import { synchronized } from '@dxos/async';
8
8
  import { PublicKey } from '@dxos/keys';
9
9
  import { log } from '@dxos/log';
10
- import { Protocol } from '@dxos/mesh-protocol';
10
+ import { Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
11
11
 
12
- import { SignalMessage, SignalMessenger } from '../signal';
12
+ import { OfferMessage, SignalMessage, SignalMessenger } from '../signal';
13
13
  import { TransportFactory } from '../transport';
14
+ import { WireProtocolProvider } from '../wire-protocol';
14
15
  import { Connection, ConnectionState } from './connection';
15
16
 
16
17
  interface PeerCallbacks {
18
+ /**
19
+ * Connection attempt initiated.
20
+ */
21
+ onInitiated: (connection: Connection) => void;
22
+
17
23
  /**
18
24
  * Connection opened.
19
25
  */
@@ -33,8 +39,17 @@ interface PeerCallbacks {
33
39
  * Peer rejected our offer to connect.
34
40
  */
35
41
  onRejected: () => void;
42
+
43
+ /**
44
+ * Returns true if the remote peer's offer should be accepted.
45
+ */
46
+ onOffer: (remoteId: PublicKey) => Promise<boolean>;
36
47
  }
37
48
 
49
+ /**
50
+ * State of remote peer during the lifetime of a swarm connection.
51
+ * Can open and close multiple connections to the remote peer.
52
+ */
38
53
  export class Peer {
39
54
  public connection?: Connection;
40
55
 
@@ -43,25 +58,109 @@ export class Peer {
43
58
  */
44
59
  public advertizing = false;
45
60
 
61
+ public initiating = false;
62
+
46
63
  constructor(
47
64
  public readonly id: PublicKey,
48
65
  public readonly topic: PublicKey,
49
66
  public readonly localPeerId: PublicKey,
67
+ private readonly _signalMessaging: SignalMessenger,
68
+ private readonly _protocolProvider: WireProtocolProvider,
69
+ private readonly _transportFactory: TransportFactory,
50
70
  private readonly _callbacks: PeerCallbacks
51
71
  ) {}
52
72
 
73
+ /**
74
+ * Respond to remote offer.
75
+ */
76
+ async onOffer(message: OfferMessage): Promise<Answer> {
77
+ const remoteId = message.author;
78
+
79
+ // Check if we are already trying to connect to that peer.
80
+ if (this.connection || this.initiating) {
81
+ // Peer with the highest Id closes its connection, and accepts remote peer's offer.
82
+ if (remoteId.toHex() < this.localPeerId.toHex()) {
83
+ log.info("closing local connection and accepting remote peer's offer", {
84
+ id: this.id,
85
+ topic: this.topic,
86
+ peerId: this.localPeerId
87
+ });
88
+
89
+ if (this.connection) {
90
+ // Close our connection and accept remote peer's connection.
91
+ await this.closeConnection();
92
+ }
93
+ } else {
94
+ // Continue with our origination attempt, the remote peer will close it's connection and accept ours.
95
+ return { accept: false };
96
+ }
97
+ }
98
+
99
+ if (await this._callbacks.onOffer(remoteId)) {
100
+ if (!this.connection) {
101
+ // Connection might have been already established.
102
+ assert(message.sessionId);
103
+ const connection = this._createConnection(false, message.sessionId);
104
+ try {
105
+ connection.openConnection();
106
+ } catch (err: any) {
107
+ log.warn('connection error', { topic: this.topic, peerId: this.localPeerId, remoteId: this.id, err });
108
+ // Calls `onStateChange` with CLOSED state.
109
+ await this.closeConnection();
110
+ }
111
+
112
+ return { accept: true };
113
+ }
114
+ }
115
+ return { accept: false };
116
+ }
117
+
118
+ /**
119
+ * Initiate a connection to the remote peer.
120
+ */
121
+ async initiateConnection() {
122
+ assert(!this.initiating, 'Initiation in progress.');
123
+ assert(!this.connection, 'Already connected.');
124
+ const sessionId = PublicKey.random();
125
+ log('initiating...', { id: this.id, topic: this.topic, peerId: this.id, sessionId });
126
+ const connection = this._createConnection(true, sessionId);
127
+ this.initiating = true;
128
+
129
+ try {
130
+ const answer = await this._signalMessaging.offer({
131
+ author: this.localPeerId,
132
+ recipient: this.id,
133
+ sessionId,
134
+ topic: this.topic,
135
+ data: { offer: {} }
136
+ });
137
+ log('received', { answer, topic: this.topic, ownId: this.localPeerId, remoteId: this.id });
138
+ if (connection.state !== ConnectionState.INITIAL) {
139
+ log('ignoring response');
140
+ return;
141
+ }
142
+
143
+ if (!answer.accept) {
144
+ this._callbacks.onRejected();
145
+ return;
146
+ }
147
+ connection.openConnection();
148
+ this._callbacks.onAccepted();
149
+ } catch (err: any) {
150
+ log.warn('initiation error', { topic: this.topic, peerId: this.localPeerId, remoteId: this.id, err });
151
+ // Calls `onStateChange` with CLOSED state.
152
+ await this.closeConnection();
153
+ throw err;
154
+ } finally {
155
+ this.initiating = false;
156
+ }
157
+ }
158
+
53
159
  /**
54
160
  * Create new connection.
55
161
  * Either we're initiating a connection or creating one in response to an offer from the other peer.
56
162
  */
57
- createConnection(
58
- // TODO(dmaretskyi): Move into constructor?
59
- signalMessaging: SignalMessenger,
60
- initiator: boolean,
61
- sessionId: PublicKey,
62
- protocol: Protocol,
63
- transportFactory: TransportFactory
64
- ) {
163
+ private _createConnection(initiator: boolean, sessionId: PublicKey) {
65
164
  log('creating connection', {
66
165
  topic: this.topic,
67
166
  peerId: this.localPeerId,
@@ -70,16 +169,19 @@ export class Peer {
70
169
  sessionId
71
170
  });
72
171
  assert(!this.connection, 'Already connected.');
172
+
73
173
  const connection = new Connection(
74
174
  this.topic,
75
175
  this.localPeerId,
76
176
  this.id,
77
177
  sessionId,
78
178
  initiator,
79
- signalMessaging,
80
- protocol,
81
- transportFactory
179
+ this._signalMessaging,
180
+ // TODO(dmaretskyi): Init only when connection is established.
181
+ this._protocolProvider({ initiator, localPeerId: this.localPeerId, remotePeerId: this.id, topic: this.topic }),
182
+ this._transportFactory
82
183
  );
184
+ this._callbacks.onInitiated(connection);
83
185
  connection.stateChanged.on((state) => {
84
186
  switch (state) {
85
187
  case ConnectionState.CONNECTED: {
@@ -87,16 +189,6 @@ export class Peer {
87
189
  break;
88
190
  }
89
191
 
90
- case ConnectionState.REJECTED: {
91
- this._callbacks.onRejected();
92
- break;
93
- }
94
-
95
- case ConnectionState.ACCEPTED: {
96
- this._callbacks.onAccepted();
97
- break;
98
- }
99
-
100
192
  case ConnectionState.CLOSED: {
101
193
  log('connection closed', { topic: this.topic, peerId: this.localPeerId, remoteId: this.id, initiator });
102
194
  assert(this.connection === connection, 'Connection mismatch (race condition).');
@@ -128,12 +220,9 @@ export class Peer {
128
220
  const connection = this.connection;
129
221
  log('closing...', { peerId: this.id, sessionId: connection.sessionId });
130
222
 
131
- try {
132
- // Triggers `onStateChange` callback which will clean up the connection.
133
- await connection.close();
134
- } catch (err) {
135
- log.catch(err);
136
- }
223
+ // Triggers `onStateChange` callback which will clean up the connection.
224
+ // Won't throw.
225
+ await connection.close();
137
226
 
138
227
  log('closed', { peerId: this.id, sessionId: connection.sessionId });
139
228
  }
@@ -2,7 +2,7 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- // @dxos/mocha platform=nodejs
5
+ // @dxos/test platform=nodejs
6
6
 
7
7
  import { expect } from 'earljs';
8
8
  import waitForExpect from 'wait-for-expect';
@@ -11,18 +11,19 @@ import { sleep, asyncTimeout } from '@dxos/async';
11
11
  import { PublicKey } from '@dxos/keys';
12
12
  import { log } from '@dxos/log';
13
13
  import { MemorySignalManager, MemorySignalManagerContext, Messenger } from '@dxos/messaging';
14
- import { afterTest } from '@dxos/testutils';
14
+ import { beforeEach, describe, test, afterTest } from '@dxos/test';
15
15
 
16
16
  import { TestProtocolPlugin, testProtocolProvider } from '../testing';
17
17
  import { FullyConnectedTopology } from '../topology';
18
18
  import { createWebRTCTransportFactory } from '../transport';
19
+ import { adaptProtocolProvider } from '../wire-protocol';
19
20
  import { Swarm } from './swarm';
20
21
 
21
- describe('Swarm', function () {
22
+ describe('Swarm', () => {
22
23
  const context = new MemorySignalManagerContext();
23
24
  let signalManager: MemorySignalManager;
24
25
 
25
- beforeEach(function () {
26
+ beforeEach(() => {
26
27
  signalManager = new MemorySignalManager(context);
27
28
  afterTest(() => signalManager.destroy());
28
29
  });
@@ -33,7 +34,7 @@ describe('Swarm', function () {
33
34
  topic,
34
35
  peerId,
35
36
  new FullyConnectedTopology(),
36
- testProtocolProvider(topic.asBuffer(), peerId, plugin),
37
+ adaptProtocolProvider(testProtocolProvider(topic.asBuffer(), peerId, plugin)),
37
38
  new Messenger({ signalManager }),
38
39
  createWebRTCTransportFactory(),
39
40
  undefined
@@ -46,7 +47,7 @@ describe('Swarm', function () {
46
47
  return { swarm, plugin };
47
48
  };
48
49
 
49
- it('connects two peers in a swarm', async function () {
50
+ test('connects two peers in a swarm', async () => {
50
51
  const topic = PublicKey.random();
51
52
  const peerId1 = PublicKey.random();
52
53
  const peerId2 = PublicKey.random();
@@ -95,7 +96,7 @@ describe('Swarm', function () {
95
96
  });
96
97
  }).timeout(5_000);
97
98
 
98
- it('two peers try to originate connections to each other simultaneously', async function () {
99
+ test('two peers try to originate connections to each other simultaneously', async () => {
99
100
  const topic = PublicKey.random();
100
101
  const peerId1 = PublicKey.random();
101
102
  const peerId2 = PublicKey.random();
@@ -125,7 +126,7 @@ describe('Swarm', function () {
125
126
  await connectPromises;
126
127
  }).timeout(5_000);
127
128
 
128
- it('second peer discovered after delay', async function () {
129
+ test('second peer discovered after delay', async () => {
129
130
  const topic = PublicKey.random();
130
131
  const peerId1 = PublicKey.random();
131
132
  const peerId2 = PublicKey.random();