@streamr/trackerless-network 102.0.0-beta.0 → 102.0.0-beta.2

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 (231) hide show
  1. package/dist/generated/google/protobuf/any.js.map +1 -0
  2. package/dist/generated/google/protobuf/empty.js.map +1 -0
  3. package/dist/generated/google/protobuf/timestamp.js.map +1 -0
  4. package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.client.d.ts +9 -0
  5. package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.client.js +7 -0
  6. package/dist/generated/packages/dht/protos/DhtRpc.client.js.map +1 -0
  7. package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.d.ts +32 -8
  8. package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.js +23 -7
  9. package/dist/generated/packages/dht/protos/DhtRpc.js.map +1 -0
  10. package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.server.d.ts +5 -0
  11. package/dist/generated/packages/dht/protos/DhtRpc.server.js.map +1 -0
  12. package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
  13. package/dist/generated/packages/trackerless-network/protos/NetworkRpc.client.js.map +1 -0
  14. package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.d.ts +3 -3
  15. package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.js +1 -1
  16. package/dist/generated/packages/trackerless-network/protos/NetworkRpc.js.map +1 -0
  17. package/dist/generated/packages/trackerless-network/protos/NetworkRpc.server.js.map +1 -0
  18. package/dist/package.json +9 -10
  19. package/dist/src/NetworkNode.d.ts +4 -3
  20. package/dist/src/NetworkNode.js.map +1 -1
  21. package/dist/src/NetworkStack.d.ts +2 -2
  22. package/dist/src/NetworkStack.js +4 -4
  23. package/dist/src/NetworkStack.js.map +1 -1
  24. package/dist/src/exports.d.ts +3 -2
  25. package/dist/src/exports.js +3 -2
  26. package/dist/src/exports.js.map +1 -1
  27. package/dist/src/logic/ContentDeliveryLayerNode.d.ts +2 -1
  28. package/dist/src/logic/ContentDeliveryLayerNode.js +5 -5
  29. package/dist/src/logic/ContentDeliveryLayerNode.js.map +1 -1
  30. package/dist/src/logic/ContentDeliveryManager.d.ts +2 -1
  31. package/dist/src/logic/ContentDeliveryManager.js +2 -1
  32. package/dist/src/logic/ContentDeliveryManager.js.map +1 -1
  33. package/dist/src/logic/ContentDeliveryRpcLocal.d.ts +3 -3
  34. package/dist/src/logic/ContentDeliveryRpcLocal.js +1 -1
  35. package/dist/src/logic/ContentDeliveryRpcLocal.js.map +1 -1
  36. package/dist/src/logic/ContentDeliveryRpcRemote.d.ts +2 -2
  37. package/dist/src/logic/ControlLayerNode.d.ts +1 -1
  38. package/dist/src/logic/DiscoveryLayerNode.d.ts +3 -3
  39. package/dist/src/logic/DuplicateMessageDetector.js +1 -1
  40. package/dist/src/logic/DuplicateMessageDetector.js.map +1 -1
  41. package/dist/src/logic/PeerDescriptorStoreManager.d.ts +1 -1
  42. package/dist/src/logic/PeerDescriptorStoreManager.js +1 -1
  43. package/dist/src/logic/PeerDescriptorStoreManager.js.map +1 -1
  44. package/dist/src/logic/inspect/InspectSession.d.ts +2 -2
  45. package/dist/src/logic/inspect/InspectSession.js +2 -2
  46. package/dist/src/logic/inspect/InspectSession.js.map +1 -1
  47. package/dist/src/logic/inspect/Inspector.d.ts +1 -1
  48. package/dist/src/logic/inspect/Inspector.js +1 -1
  49. package/dist/src/logic/inspect/Inspector.js.map +1 -1
  50. package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.d.ts +2 -2
  51. package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.d.ts +2 -2
  52. package/dist/src/logic/neighbor-discovery/Handshaker.js +2 -2
  53. package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
  54. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js +2 -2
  55. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
  56. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.d.ts +2 -2
  57. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js +1 -1
  58. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -1
  59. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.d.ts +1 -1
  60. package/dist/src/logic/node-info/NodeInfoClient.d.ts +1 -1
  61. package/dist/src/logic/node-info/NodeInfoClient.js +1 -1
  62. package/dist/src/logic/node-info/NodeInfoClient.js.map +1 -1
  63. package/dist/src/logic/node-info/NodeInfoRpcLocal.d.ts +2 -2
  64. package/dist/src/logic/node-info/NodeInfoRpcLocal.js +1 -1
  65. package/dist/src/logic/node-info/NodeInfoRpcLocal.js.map +1 -1
  66. package/dist/src/logic/node-info/NodeInfoRpcRemote.d.ts +2 -2
  67. package/dist/src/logic/propagation/Propagation.d.ts +1 -1
  68. package/dist/src/logic/propagation/PropagationTaskStore.d.ts +1 -1
  69. package/dist/src/logic/proxy/ProxyClient.d.ts +1 -2
  70. package/dist/src/logic/proxy/ProxyClient.js +2 -3
  71. package/dist/src/logic/proxy/ProxyClient.js.map +1 -1
  72. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.d.ts +2 -2
  73. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js +4 -4
  74. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js.map +1 -1
  75. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.d.ts +2 -2
  76. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.js +1 -1
  77. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.d.ts +4 -4
  78. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js +1 -1
  79. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js.map +1 -1
  80. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.d.ts +1 -1
  81. package/dist/src/logic/utils.d.ts +1 -1
  82. package/dist/src/logic/utils.js +2 -2
  83. package/dist/src/logic/utils.js.map +1 -1
  84. package/dist/src/types.d.ts +6 -0
  85. package/dist/src/types.js +3 -0
  86. package/dist/src/types.js.map +1 -0
  87. package/dist/test/benchmark/first-message.js +2 -2
  88. package/dist/test/benchmark/first-message.js.map +1 -1
  89. package/dist/test/utils/utils.d.ts +2 -2
  90. package/dist/test/utils/utils.js +5 -4
  91. package/dist/test/utils/utils.js.map +1 -1
  92. package/jest.config.ts +13 -0
  93. package/package.json +9 -10
  94. package/proto.sh +2 -2
  95. package/protos/NetworkRpc.proto +2 -3
  96. package/.eslintignore +0 -7
  97. package/.eslintrc +0 -3
  98. package/dist/src/proto/google/protobuf/any.js.map +0 -1
  99. package/dist/src/proto/google/protobuf/empty.js.map +0 -1
  100. package/dist/src/proto/google/protobuf/timestamp.js.map +0 -1
  101. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +0 -1
  102. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +0 -1
  103. package/dist/src/proto/packages/dht/protos/DhtRpc.server.js.map +0 -1
  104. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js.map +0 -1
  105. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js.map +0 -1
  106. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +0 -1
  107. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.js.map +0 -1
  108. package/jest.config.js +0 -8
  109. package/src/NetworkNode.ts +0 -141
  110. package/src/NetworkStack.ts +0 -198
  111. package/src/exports.ts +0 -16
  112. package/src/logic/ContentDeliveryLayerNode.ts +0 -424
  113. package/src/logic/ContentDeliveryManager.ts +0 -399
  114. package/src/logic/ContentDeliveryRpcLocal.ts +0 -48
  115. package/src/logic/ContentDeliveryRpcRemote.ts +0 -44
  116. package/src/logic/ControlLayerNode.ts +0 -17
  117. package/src/logic/DiscoveryLayerNode.ts +0 -30
  118. package/src/logic/DuplicateMessageDetector.ts +0 -167
  119. package/src/logic/ExternalNetworkRpc.ts +0 -42
  120. package/src/logic/NodeList.ts +0 -114
  121. package/src/logic/PeerDescriptorStoreManager.ts +0 -96
  122. package/src/logic/StreamPartNetworkSplitAvoidance.ts +0 -90
  123. package/src/logic/StreamPartReconnect.ts +0 -38
  124. package/src/logic/createContentDeliveryLayerNode.ts +0 -130
  125. package/src/logic/formStreamPartDeliveryServiceId.ts +0 -7
  126. package/src/logic/inspect/InspectSession.ts +0 -54
  127. package/src/logic/inspect/Inspector.ts +0 -100
  128. package/src/logic/neighbor-discovery/HandshakeRpcLocal.ts +0 -138
  129. package/src/logic/neighbor-discovery/HandshakeRpcRemote.ts +0 -66
  130. package/src/logic/neighbor-discovery/Handshaker.ts +0 -215
  131. package/src/logic/neighbor-discovery/NeighborFinder.ts +0 -77
  132. package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +0 -69
  133. package/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.ts +0 -75
  134. package/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.ts +0 -35
  135. package/src/logic/node-info/NodeInfoClient.ts +0 -23
  136. package/src/logic/node-info/NodeInfoRpcLocal.ts +0 -28
  137. package/src/logic/node-info/NodeInfoRpcRemote.ts +0 -11
  138. package/src/logic/propagation/FifoMapWithTTL.ts +0 -116
  139. package/src/logic/propagation/Propagation.ts +0 -84
  140. package/src/logic/propagation/PropagationTaskStore.ts +0 -41
  141. package/src/logic/proxy/ProxyClient.ts +0 -287
  142. package/src/logic/proxy/ProxyConnectionRpcLocal.ts +0 -106
  143. package/src/logic/proxy/ProxyConnectionRpcRemote.ts +0 -26
  144. package/src/logic/temporary-connection/TemporaryConnectionRpcLocal.ts +0 -73
  145. package/src/logic/temporary-connection/TemporaryConnectionRpcRemote.ts +0 -29
  146. package/src/logic/utils.ts +0 -18
  147. package/src/proto/google/protobuf/any.ts +0 -326
  148. package/src/proto/google/protobuf/empty.ts +0 -81
  149. package/src/proto/google/protobuf/timestamp.ts +0 -287
  150. package/src/proto/packages/dht/protos/DhtRpc.client.ts +0 -407
  151. package/src/proto/packages/dht/protos/DhtRpc.server.ts +0 -160
  152. package/src/proto/packages/dht/protos/DhtRpc.ts +0 -1244
  153. package/src/proto/packages/proto-rpc/protos/ProtoRpc.ts +0 -108
  154. package/src/proto/packages/trackerless-network/protos/NetworkRpc.client.ts +0 -218
  155. package/src/proto/packages/trackerless-network/protos/NetworkRpc.server.ts +0 -85
  156. package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +0 -783
  157. package/test/benchmark/StreamPartIdDataKeyDistribution.test.ts +0 -60
  158. package/test/benchmark/first-message.ts +0 -169
  159. package/test/end-to-end/content-delivery-layer-node-with-real-connections.test.ts +0 -160
  160. package/test/end-to-end/external-network-rpc.test.ts +0 -67
  161. package/test/end-to-end/inspect.test.ts +0 -124
  162. package/test/end-to-end/proxy-and-full-node.test.ts +0 -143
  163. package/test/end-to-end/proxy-connections.test.ts +0 -228
  164. package/test/end-to-end/proxy-key-exchange.test.ts +0 -126
  165. package/test/end-to-end/webrtc-full-node-network.test.ts +0 -85
  166. package/test/end-to-end/websocket-full-node-network.test.ts +0 -84
  167. package/test/integration/ContentDeliveryLayerNode-Layer1Node-Latencies.test.ts +0 -139
  168. package/test/integration/ContentDeliveryLayerNode-Layer1Node.test.ts +0 -162
  169. package/test/integration/ContentDeliveryManager.test.ts +0 -157
  170. package/test/integration/ContentDeliveryRpcRemote.test.ts +0 -100
  171. package/test/integration/HandshakeRpcRemote.test.ts +0 -79
  172. package/test/integration/Handshakes.test.ts +0 -176
  173. package/test/integration/Inspect.test.ts +0 -89
  174. package/test/integration/NeighborUpdateRpcRemote.test.ts +0 -82
  175. package/test/integration/NetworkNode.test.ts +0 -115
  176. package/test/integration/NetworkRpc.test.ts +0 -52
  177. package/test/integration/NetworkStack.test.ts +0 -72
  178. package/test/integration/NodeInfoRpc.test.ts +0 -109
  179. package/test/integration/Propagation.test.ts +0 -76
  180. package/test/integration/joining-streams-on-offline-peers.test.ts +0 -82
  181. package/test/integration/stream-without-default-entrypoints.test.ts +0 -128
  182. package/test/integration/streamEntryPointReplacing.test.ts +0 -97
  183. package/test/types/global.d.ts +0 -2
  184. package/test/unit/ContentDeliveryLayerNode.test.ts +0 -112
  185. package/test/unit/ContentDeliveryManager.test.ts +0 -95
  186. package/test/unit/ContentDeliveryRpcLocal.test.ts +0 -60
  187. package/test/unit/DuplicateMessageDetector.test.ts +0 -192
  188. package/test/unit/ExternalNetworkRpc.test.ts +0 -48
  189. package/test/unit/FifoMapWithTtl.test.ts +0 -253
  190. package/test/unit/HandshakeRpcLocal.test.ts +0 -168
  191. package/test/unit/Handshaker.test.ts +0 -69
  192. package/test/unit/InspectSession.test.ts +0 -80
  193. package/test/unit/Inspector.test.ts +0 -51
  194. package/test/unit/NeighborFinder.test.ts +0 -51
  195. package/test/unit/NeighborUpdateRpcLocal.test.ts +0 -139
  196. package/test/unit/NetworkNode.test.ts +0 -42
  197. package/test/unit/NodeList.test.ts +0 -164
  198. package/test/unit/NumberPair.test.ts +0 -22
  199. package/test/unit/PeerDescriptorStoreManager.test.ts +0 -103
  200. package/test/unit/Propagation.test.ts +0 -151
  201. package/test/unit/ProxyConnectionRpcRemote.test.ts +0 -39
  202. package/test/unit/StreamPartIDDataKey.test.ts +0 -12
  203. package/test/unit/StreamPartNetworkSplitAvoidance.test.ts +0 -31
  204. package/test/unit/StreamPartReconnect.test.ts +0 -30
  205. package/test/unit/TemporaryConnectionRpcLocal.test.ts +0 -38
  206. package/test/utils/fake/FakePeerDescriptorStoreManager.ts +0 -29
  207. package/test/utils/mock/MockConnectionsView.ts +0 -18
  208. package/test/utils/mock/MockControlLayerNode.ts +0 -78
  209. package/test/utils/mock/MockDiscoveryLayerNode.ts +0 -60
  210. package/test/utils/mock/MockHandshaker.ts +0 -17
  211. package/test/utils/mock/MockNeighborFinder.ts +0 -20
  212. package/test/utils/mock/MockNeighborUpdateManager.ts +0 -21
  213. package/test/utils/mock/MockTransport.ts +0 -30
  214. package/test/utils/utils.ts +0 -143
  215. package/tsconfig.browser.json +0 -12
  216. package/tsconfig.jest.json +0 -16
  217. package/tsconfig.json +0 -3
  218. package/tsconfig.node.json +0 -16
  219. /package/dist/{src/proto → generated}/google/protobuf/any.d.ts +0 -0
  220. /package/dist/{src/proto → generated}/google/protobuf/any.js +0 -0
  221. /package/dist/{src/proto → generated}/google/protobuf/empty.d.ts +0 -0
  222. /package/dist/{src/proto → generated}/google/protobuf/empty.js +0 -0
  223. /package/dist/{src/proto → generated}/google/protobuf/timestamp.d.ts +0 -0
  224. /package/dist/{src/proto → generated}/google/protobuf/timestamp.js +0 -0
  225. /package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.server.js +0 -0
  226. /package/dist/{src/proto → generated}/packages/proto-rpc/protos/ProtoRpc.d.ts +0 -0
  227. /package/dist/{src/proto → generated}/packages/proto-rpc/protos/ProtoRpc.js +0 -0
  228. /package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.client.d.ts +0 -0
  229. /package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.client.js +0 -0
  230. /package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.server.d.ts +0 -0
  231. /package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.server.js +0 -0
@@ -1,167 +0,0 @@
1
- /**
2
- * Represent a pair of numbers (a,b). Ordering between two pairs is defined as
3
- * follows. First compare first numbers. Compare second numbers if first are
4
- * equal.
5
- */
6
- export class NumberPair {
7
- private readonly a
8
- private readonly b
9
-
10
- constructor(a: number, b: number) {
11
- this.a = a
12
- this.b = b
13
- }
14
-
15
- greaterThanOrEqual(otherPair: NumberPair): boolean {
16
- return this.greaterThan(otherPair) || this.equalTo(otherPair)
17
- }
18
-
19
- greaterThan(otherPair: NumberPair): boolean {
20
- return this.compareTo(otherPair) === 1
21
- }
22
-
23
- equalTo(otherPair: NumberPair): boolean {
24
- return this.compareTo(otherPair) === 0
25
- }
26
-
27
- private compareTo(otherPair: NumberPair): number {
28
- if (this.a > otherPair.a) {
29
- return 1
30
- }
31
- if (this.a < otherPair.a) {
32
- return -1
33
- }
34
- if (this.b > otherPair.b) {
35
- return 1
36
- }
37
- if (this.b < otherPair.b) {
38
- return -1
39
- }
40
- return 0
41
- }
42
-
43
- toString(): string {
44
- return `${this.a}|${this.b}`
45
- }
46
- }
47
-
48
- export class InvalidNumberingError extends Error {
49
- constructor() {
50
- super('pre-condition: previousNumber < number')
51
- }
52
- }
53
-
54
- export class GapMisMatchError extends Error {
55
- constructor(state: string, previousNumber: NumberPair, number: NumberPair) {
56
- super('pre-condition: gap overlap in given numbers:'
57
- + ` previousNumber=${previousNumber.toString()}, number=${number.toString()}, state=${state}`)
58
- }
59
- }
60
-
61
- /**
62
- *
63
- * Keeps track of a stream's message numbers and reports already seen numbers
64
- * as duplicates.
65
- *
66
- * Leverages the fact that message are assigned numbers from a strictly
67
- * increasing integer sequence for lowered space complexity. For example,
68
- * if we know that all messages up to number N have been seen, we can only
69
- * store the number N to provide message identity check. This is because
70
- * anything less than N can be deemed a duplicate.
71
- *
72
- * Messages arriving out-of-order makes this a bit harder since gaps form.
73
- * Most of the code in this class is built to deal with this complexity.
74
- * Basically, we need to keep track of which intervals [N,M] could still
75
- * contain unseen messages. We should also remove intervals after we are sure
76
- * that they contain no unseen messages.
77
- *
78
- * In addition to the above, there needs to be a limit to the number of
79
- * intervals we store, as it could well be that some messages never
80
- * arrive. The strategy is to start removing the lowest numbered
81
- * intervals when storage limits are hit.
82
- *
83
- */
84
- export class DuplicateMessageDetector {
85
- private readonly maxGapCount: number
86
- private readonly gaps: Array<[NumberPair, NumberPair]>
87
-
88
- constructor(maxGapCount = 10000) {
89
- this.maxGapCount = maxGapCount
90
- this.gaps = [] // ascending order of half-closed intervals (x,y] representing gaps that contain unseen message(s)
91
- }
92
-
93
- /**
94
- * returns true if number has not yet been seen (i.e. is not a duplicate)
95
- */
96
- markAndCheck(previousNumber: NumberPair | null, number: NumberPair): boolean | never {
97
- if (previousNumber && previousNumber.greaterThanOrEqual(number)) {
98
- throw new InvalidNumberingError()
99
- }
100
-
101
- if (this.gaps.length === 0) {
102
- this.gaps.push([number, new NumberPair(Infinity, Infinity)])
103
- return true
104
- }
105
-
106
- // Handle special case where previousNumber is not provided. Only
107
- // minimal duplicate detection is provided (comparing against latest
108
- // known message number).
109
- if (previousNumber === null) {
110
- if (number.greaterThan(this.gaps[this.gaps.length - 1][0])) {
111
- this.gaps[this.gaps.length - 1][0] = number
112
- return true
113
- }
114
- return false
115
- }
116
-
117
- for (let i = this.gaps.length - 1; i >= 0; --i) {
118
- const [lowerBound, upperBound] = this.gaps[i] // invariant: upperBound > lowerBound
119
-
120
- // implies number > upperBound (would've been handled in previous iteration if gap exists)
121
- if (previousNumber.greaterThanOrEqual(upperBound)) {
122
- return false
123
- }
124
- if (previousNumber.greaterThanOrEqual(lowerBound)) {
125
- if (number.greaterThan(upperBound)) {
126
- throw new GapMisMatchError(this.toString(), previousNumber, number)
127
- }
128
- if (previousNumber.equalTo(lowerBound)) {
129
- if (number.equalTo(upperBound)) {
130
- this.gaps.splice(i, 1)
131
- } else {
132
- this.gaps[i] = [number, upperBound]
133
- }
134
- } else if (number.equalTo(upperBound)) {
135
- this.gaps[i] = [lowerBound, previousNumber]
136
- } else {
137
- this.gaps.splice(i, 1, [lowerBound, previousNumber], [number, upperBound])
138
- }
139
-
140
- // invariants after:
141
- // - gaps are in ascending order
142
- // - the intersection between any two gaps is empty
143
- // - there are no gaps that define the empty set
144
- // - last gap is [n, Infinity]
145
- // - anything not covered by a gap is considered seen
146
-
147
- this.dropLowestGapIfOverMaxGapCount()
148
- return true
149
- }
150
- if (number.greaterThan(lowerBound)) {
151
- throw new GapMisMatchError(this.toString(), previousNumber, number)
152
- }
153
- }
154
- return false
155
- }
156
-
157
- private dropLowestGapIfOverMaxGapCount(): void {
158
- // invariant: this.gaps.length <= this.maxGapCount + 1
159
- if (this.gaps.length > this.maxGapCount) {
160
- this.gaps.shift()
161
- }
162
- }
163
-
164
- toString(): string {
165
- return this.gaps.map(([lower, upper]) => `(${lower.toString()}, ${upper.toString()}]`).join(', ')
166
- }
167
- }
@@ -1,42 +0,0 @@
1
- import { IMessageType } from '@protobuf-ts/runtime'
2
- import { ServerCallContext, ServiceInfo } from '@protobuf-ts/runtime-rpc'
3
- import { ITransport, ListeningRpcCommunicator } from '@streamr/dht'
4
- import { ClassType, ClientTransport, ProtoRpcClient, toProtoRpcClient } from '@streamr/proto-rpc'
5
-
6
- export const SERVICE_ID = 'external-network-service'
7
-
8
- export type ExternalRpcClient = ServiceInfo & ClassType
9
- // eslint-disable-next-line @typescript-eslint/prefer-function-type, @typescript-eslint/consistent-type-definitions
10
- export type ExternalRpcClientClass<T extends ExternalRpcClient> = { new (clientTransport: ClientTransport): T }
11
-
12
- export class ExternalNetworkRpc {
13
-
14
- private readonly rpcCommunicator: ListeningRpcCommunicator
15
-
16
- constructor(transport: ITransport) {
17
- this.rpcCommunicator = new ListeningRpcCommunicator(SERVICE_ID, transport)
18
- }
19
-
20
- registerRpcMethod<
21
- RequestClass extends IMessageType<RequestType>,
22
- ResponseClass extends IMessageType<ResponseType>,
23
- RequestType extends object,
24
- ResponseType extends object
25
- >(
26
- request: RequestClass,
27
- response: ResponseClass,
28
- name: string,
29
- fn: (req: RequestType, context: ServerCallContext) => Promise<ResponseType>
30
- ): void {
31
- this.rpcCommunicator.registerRpcMethod(request, response, name, fn)
32
- }
33
-
34
- createRpcClient<T extends ExternalRpcClient>(clientClass: ExternalRpcClientClass<T>): ProtoRpcClient<T> {
35
- return toProtoRpcClient(new clientClass(this.rpcCommunicator.getRpcClientTransport()))
36
- }
37
-
38
- destroy(): void {
39
- this.rpcCommunicator.destroy()
40
- }
41
-
42
- }
@@ -1,114 +0,0 @@
1
- import { DhtAddress, toNodeId } from '@streamr/dht'
2
- import { sample } from 'lodash'
3
- import { ContentDeliveryRpcRemote } from './ContentDeliveryRpcRemote'
4
- import { EventEmitter } from 'eventemitter3'
5
-
6
- export interface Events {
7
- nodeAdded: (id: DhtAddress, remote: ContentDeliveryRpcRemote) => void
8
- nodeRemoved: (id: DhtAddress, remote: ContentDeliveryRpcRemote) => void
9
- }
10
-
11
- const getValuesOfIncludedKeys = (
12
- nodes: Map<DhtAddress, ContentDeliveryRpcRemote>,
13
- exclude: DhtAddress[],
14
- wsOnly = false
15
- ): ContentDeliveryRpcRemote[] => {
16
- const values = wsOnly
17
- ? Array.from(nodes.entries()).filter(([_, node]) => node.getPeerDescriptor().websocket !== undefined)
18
- : Array.from(nodes.entries())
19
- return values
20
- .filter(([id]) => !exclude.includes(id))
21
- .map(([_id, node]) => node)
22
- }
23
-
24
- // The items in the list are in the insertion order
25
-
26
- export class NodeList extends EventEmitter<Events> {
27
- private readonly nodes: Map<DhtAddress, ContentDeliveryRpcRemote>
28
- private readonly limit: number
29
- private ownId: DhtAddress
30
-
31
- constructor(ownId: DhtAddress, limit: number) {
32
- super()
33
- this.nodes = new Map()
34
- this.limit = limit
35
- this.ownId = ownId
36
- }
37
-
38
- add(remote: ContentDeliveryRpcRemote): void {
39
- const nodeId = toNodeId(remote.getPeerDescriptor())
40
- if ((this.ownId !== nodeId) && (this.nodes.size < this.limit)) {
41
- const isExistingNode = this.nodes.has(nodeId)
42
- this.nodes.set(nodeId, remote)
43
-
44
- if (!isExistingNode) {
45
- this.emit('nodeAdded', nodeId, remote)
46
- }
47
- }
48
- }
49
-
50
- remove(nodeId: DhtAddress): void {
51
- if (this.nodes.has(nodeId)) {
52
- const remote = this.nodes.get(nodeId)!
53
- this.nodes.delete(nodeId)
54
- this.emit('nodeRemoved', nodeId, remote)
55
- }
56
- }
57
-
58
- has(nodeId: DhtAddress): boolean {
59
- return this.nodes.has(nodeId)
60
- }
61
-
62
- // Replace nodes does not emit nodeRemoved events, use with caution
63
- replaceAll(neighbors: ContentDeliveryRpcRemote[]): void {
64
- this.nodes.clear()
65
- const limited = neighbors.splice(0, this.limit)
66
- limited.forEach((remote) => {
67
- this.add(remote)
68
- })
69
- }
70
-
71
- getIds(): DhtAddress[] {
72
- return Array.from(this.nodes.keys())
73
- }
74
-
75
- get(id: DhtAddress): ContentDeliveryRpcRemote | undefined {
76
- return this.nodes.get(id)
77
- }
78
-
79
- size(exclude: DhtAddress[] = []): number {
80
- return Array.from(this.nodes.keys()).filter((node) => !exclude.includes(node)).length
81
- }
82
-
83
- getRandom(exclude: DhtAddress[]): ContentDeliveryRpcRemote | undefined {
84
- return sample(getValuesOfIncludedKeys(this.nodes, exclude))
85
- }
86
-
87
- getFirst(exclude: DhtAddress[], wsOnly = false): ContentDeliveryRpcRemote | undefined {
88
- const included = getValuesOfIncludedKeys(this.nodes, exclude, wsOnly)
89
- return included[0]
90
- }
91
-
92
- getFirstAndLast(exclude: DhtAddress[]): ContentDeliveryRpcRemote[] {
93
- const included = getValuesOfIncludedKeys(this.nodes, exclude)
94
- if (included.length === 0) {
95
- return []
96
- }
97
- return included.length > 1 ? [this.getFirst(exclude)!, this.getLast(exclude)!] : [this.getFirst(exclude)!]
98
- }
99
-
100
- getLast(exclude: DhtAddress[]): ContentDeliveryRpcRemote | undefined {
101
- const included = getValuesOfIncludedKeys(this.nodes, exclude)
102
- return included[included.length - 1]
103
- }
104
-
105
- getAll(): ContentDeliveryRpcRemote[] {
106
- return Array.from(this.nodes.values())
107
- }
108
-
109
- stop(): void {
110
- this.nodes.forEach((node) => this.remove(toNodeId(node.getPeerDescriptor())))
111
- this.removeAllListeners()
112
- }
113
-
114
- }
@@ -1,96 +0,0 @@
1
- import {
2
- DataEntry,
3
- DhtAddress,
4
- PeerDescriptor,
5
- areEqualPeerDescriptors
6
- } from '@streamr/dht'
7
- import { Logger, scheduleAtInterval } from '@streamr/utils'
8
- import { Any } from '../proto/google/protobuf/any'
9
-
10
- const parsePeerDescriptor = (dataEntries: DataEntry[]): PeerDescriptor[] => {
11
- return dataEntries.filter((entry) => !entry.deleted).map((entry) => Any.unpack(entry.data!, PeerDescriptor))
12
- }
13
-
14
- const logger = new Logger(module)
15
-
16
- export const MAX_NODE_COUNT = 8
17
-
18
- interface PeerDescriptorStoreManagerOptions {
19
- key: DhtAddress
20
- localPeerDescriptor: PeerDescriptor
21
- storeInterval?: number
22
- fetchDataFromDht: (key: DhtAddress) => Promise<DataEntry[]>
23
- storeDataToDht: (key: DhtAddress, data: Any) => Promise<PeerDescriptor[]>
24
- deleteDataFromDht: (key: DhtAddress, waitForCompletion: boolean) => Promise<void>
25
- }
26
-
27
- /**
28
- * For each key there is usually 0-MAX_NODE_COUNT PeerDescriptors stored in the DHT. If there are fewer node,
29
- * the peer descriptor of the local node is stored to the DHT.
30
- */
31
- export class PeerDescriptorStoreManager {
32
-
33
- private readonly abortController: AbortController
34
- private readonly options: PeerDescriptorStoreManagerOptions
35
- private isLocalNodeStored_ = false
36
-
37
- constructor(options: PeerDescriptorStoreManagerOptions) {
38
- this.options = options
39
- this.abortController = new AbortController()
40
- }
41
-
42
- async fetchNodes(): Promise<PeerDescriptor[]> {
43
- logger.trace('Fetch data', { key: this.options.key })
44
- try {
45
- const result = await this.options.fetchDataFromDht(this.options.key)
46
- return parsePeerDescriptor(result)
47
- } catch {
48
- return []
49
- }
50
- }
51
-
52
- async storeAndKeepLocalNode(): Promise<void> {
53
- if (this.abortController.signal.aborted) {
54
- return
55
- }
56
- // eslint-disable-next-line no-underscore-dangle
57
- this.isLocalNodeStored_ = true
58
- await this.storeLocalNode()
59
- await this.keepLocalNode()
60
- }
61
-
62
- private async storeLocalNode(): Promise<void> {
63
- const localPeerDescriptor = this.options.localPeerDescriptor
64
- const dataToStore = Any.pack(localPeerDescriptor, PeerDescriptor)
65
- try {
66
- await this.options.storeDataToDht(this.options.key, dataToStore)
67
- } catch {
68
- logger.warn('Failed to store local node', { key: this.options.key })
69
- }
70
- }
71
-
72
- private async keepLocalNode(): Promise<void> {
73
- await scheduleAtInterval(async () => {
74
- logger.trace('Attempting to keep local node', { key: this.options.key })
75
- try {
76
- const discovered = await this.fetchNodes()
77
- if (discovered.length < MAX_NODE_COUNT
78
- || discovered.some((peerDescriptor) => areEqualPeerDescriptors(peerDescriptor, this.options.localPeerDescriptor))) {
79
- await this.storeLocalNode()
80
- }
81
- } catch {
82
- logger.debug('Failed to keep local node', { key: this.options.key })
83
- }
84
- }, this.options.storeInterval ?? 60000, false, this.abortController.signal)
85
- }
86
-
87
- public isLocalNodeStored(): boolean {
88
- // eslint-disable-next-line no-underscore-dangle
89
- return this.isLocalNodeStored_
90
- }
91
-
92
- async destroy(): Promise<void> {
93
- this.abortController.abort()
94
- await this.options.deleteDataFromDht(this.options.key, false)
95
- }
96
- }
@@ -1,90 +0,0 @@
1
- import { areEqualPeerDescriptors, DhtAddress, toNodeId, PeerDescriptor } from '@streamr/dht'
2
- import { Logger, wait } from '@streamr/utils'
3
- import { DiscoveryLayerNode } from './DiscoveryLayerNode'
4
-
5
- /*
6
- * Tries to find new neighbors if we currently have less than MIN_NEIGHBOR_COUNT neigbors. It does so by
7
- * rejoining the stream's control layer network.
8
- *
9
- * This way we can avoid some network split scenarios. The functionality is most relevant for small stream
10
- * networks.
11
- */
12
-
13
- const logger = new Logger(module)
14
-
15
- const exponentialRunOff = async (
16
- task: () => Promise<void>,
17
- description: string,
18
- abortSignal: AbortSignal,
19
- baseDelay = 500,
20
- maxAttempts = 6
21
- ): Promise<void> => {
22
- for (let i = 1; i <= maxAttempts; i++) {
23
- if (abortSignal.aborted) {
24
- return
25
- }
26
- const factor = 2 ** i
27
- const delay = baseDelay * factor
28
- try {
29
- await task()
30
- } catch {
31
- logger.trace(`${description} failed, retrying in ${delay} ms`)
32
- }
33
- try { // Abort controller throws unexpected errors in destroy?
34
- await wait(delay, abortSignal)
35
- } catch (err) {
36
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
37
- logger.trace(`${err}`) // TODO Do we need logging?
38
- }
39
- }
40
- }
41
-
42
- export const MIN_NEIGHBOR_COUNT = 4
43
-
44
- export interface StreamPartNetworkSplitAvoidanceOptions {
45
- discoveryLayerNode: DiscoveryLayerNode
46
- discoverEntryPoints: (excludedNodes?: Set<DhtAddress>) => Promise<PeerDescriptor[]>
47
- exponentialRunOfBaseDelay?: number
48
- }
49
-
50
- export class StreamPartNetworkSplitAvoidance {
51
-
52
- private readonly abortController: AbortController
53
- private readonly options: StreamPartNetworkSplitAvoidanceOptions
54
- private readonly excludedNodes: Set<DhtAddress> = new Set()
55
- private running = false
56
-
57
- constructor(options: StreamPartNetworkSplitAvoidanceOptions) {
58
- this.options = options
59
- this.abortController = new AbortController()
60
- }
61
-
62
- public async avoidNetworkSplit(): Promise<void> {
63
- this.running = true
64
- await exponentialRunOff(async () => {
65
- const discoveredEntrypoints = await this.options.discoverEntryPoints()
66
- const filteredEntryPoints = discoveredEntrypoints.filter((peer) => !this.excludedNodes.has(toNodeId(peer)))
67
- await this.options.discoveryLayerNode.joinDht(filteredEntryPoints, false, false)
68
- if (this.options.discoveryLayerNode.getNeighborCount() < MIN_NEIGHBOR_COUNT) {
69
- // Filter out nodes that are not neighbors as those nodes are assumed to be offline
70
- const newExcludes = filteredEntryPoints
71
- .filter((peer) => !this.options.discoveryLayerNode.getNeighbors()
72
- .some((neighbor) => areEqualPeerDescriptors(neighbor, peer)))
73
- .map((peer) => toNodeId(peer))
74
- newExcludes.forEach((node) => this.excludedNodes.add(node))
75
- throw new Error(`Network split is still possible`)
76
- }
77
- }, 'avoid network split', this.abortController.signal, this.options.exponentialRunOfBaseDelay)
78
- this.running = false
79
- this.excludedNodes.clear()
80
- logger.trace(`Network split avoided`)
81
- }
82
-
83
- public isRunning(): boolean {
84
- return this.running
85
- }
86
-
87
- destroy(): void {
88
- this.abortController.abort()
89
- }
90
- }
@@ -1,38 +0,0 @@
1
- import { scheduleAtInterval } from '@streamr/utils'
2
- import { MAX_NODE_COUNT, PeerDescriptorStoreManager } from './PeerDescriptorStoreManager'
3
- import { DiscoveryLayerNode } from './DiscoveryLayerNode'
4
-
5
- const DEFAULT_RECONNECT_INTERVAL = 30 * 1000
6
- export class StreamPartReconnect {
7
- private abortController?: AbortController
8
- private readonly discoveryLayerNode: DiscoveryLayerNode
9
- private readonly peerDescriptorStoreManager: PeerDescriptorStoreManager
10
-
11
- constructor(discoveryLayerNode: DiscoveryLayerNode, peerDescriptorStoreManager: PeerDescriptorStoreManager) {
12
- this.discoveryLayerNode = discoveryLayerNode
13
- this.peerDescriptorStoreManager = peerDescriptorStoreManager
14
- }
15
-
16
- async reconnect(timeout = DEFAULT_RECONNECT_INTERVAL): Promise<void> {
17
- this.abortController = new AbortController()
18
- await scheduleAtInterval(async () => {
19
- const entryPoints = await this.peerDescriptorStoreManager.fetchNodes()
20
- await this.discoveryLayerNode.joinDht(entryPoints)
21
- // Is is necessary to store the node as an entry point here?
22
- if (!this.peerDescriptorStoreManager.isLocalNodeStored() && entryPoints.length < MAX_NODE_COUNT) {
23
- await this.peerDescriptorStoreManager.storeAndKeepLocalNode()
24
- }
25
- if (this.discoveryLayerNode.getNeighborCount() > 0) {
26
- this.abortController!.abort()
27
- }
28
- }, timeout, true, this.abortController.signal)
29
- }
30
-
31
- isRunning(): boolean {
32
- return this.abortController ? !this.abortController.signal.aborted : false
33
- }
34
-
35
- destroy(): void {
36
- this.abortController?.abort()
37
- }
38
- }
@@ -1,130 +0,0 @@
1
- import { DhtAddress, ListeningRpcCommunicator, toNodeId } from '@streamr/dht'
2
- import { Handshaker } from './neighbor-discovery/Handshaker'
3
- import { NeighborFinder } from './neighbor-discovery/NeighborFinder'
4
- import { NeighborUpdateManager } from './neighbor-discovery/NeighborUpdateManager'
5
- import { StrictContentDeliveryLayerNodeOptions, ContentDeliveryLayerNode } from './ContentDeliveryLayerNode'
6
- import { NodeList } from './NodeList'
7
- import { Propagation } from './propagation/Propagation'
8
- import { StreamMessage } from '../proto/packages/trackerless-network/protos/NetworkRpc'
9
- import type { MarkOptional } from 'ts-essentials'
10
- import { ProxyConnectionRpcLocal } from './proxy/ProxyConnectionRpcLocal'
11
- import { Inspector } from './inspect/Inspector'
12
- import { TemporaryConnectionRpcLocal } from './temporary-connection/TemporaryConnectionRpcLocal'
13
- import { formStreamPartContentDeliveryServiceId } from './formStreamPartDeliveryServiceId'
14
-
15
- type ContentDeliveryLayerNodeOptions = MarkOptional<StrictContentDeliveryLayerNodeOptions,
16
- 'nearbyNodeView' | 'randomNodeView' | 'neighbors' | 'leftNodeView' | 'rightNodeView' | 'propagation'
17
- | 'handshaker' | 'neighborFinder' | 'neighborUpdateManager' | 'neighborTargetCount'
18
- | 'rpcCommunicator' | 'nodeViewSize'
19
- | 'inspector' | 'temporaryConnectionRpcLocal'> & {
20
- maxContactCount?: number
21
- minPropagationTargets?: number
22
- acceptProxyConnections?: boolean
23
- neighborUpdateInterval?: number
24
- }
25
-
26
- const createConfigWithDefaults = (options: ContentDeliveryLayerNodeOptions): StrictContentDeliveryLayerNodeOptions => {
27
- const ownNodeId = toNodeId(options.localPeerDescriptor)
28
- const rpcCommunicator = options.rpcCommunicator ?? new ListeningRpcCommunicator(
29
- formStreamPartContentDeliveryServiceId(options.streamPartId),
30
- options.transport
31
- )
32
- const neighborTargetCount = options.neighborTargetCount ?? 4
33
- const maxContactCount = options.maxContactCount ?? 20
34
- const minPropagationTargets = options.minPropagationTargets ?? 2
35
- const acceptProxyConnections = options.acceptProxyConnections ?? false
36
- const neighborUpdateInterval = options.neighborUpdateInterval ?? 10000
37
- const neighbors = options.neighbors ?? new NodeList(ownNodeId, maxContactCount)
38
- const leftNodeView = options.leftNodeView ?? new NodeList(ownNodeId, maxContactCount)
39
- const rightNodeView = options.rightNodeView ?? new NodeList(ownNodeId, maxContactCount)
40
- const nearbyNodeView = options.nearbyNodeView ?? new NodeList(ownNodeId, maxContactCount)
41
- const randomNodeView = options.randomNodeView ?? new NodeList(ownNodeId, maxContactCount)
42
- const ongoingHandshakes = new Set<DhtAddress>()
43
-
44
- const temporaryConnectionRpcLocal = new TemporaryConnectionRpcLocal({
45
- rpcCommunicator,
46
- localPeerDescriptor: options.localPeerDescriptor,
47
- streamPartId: options.streamPartId,
48
- connectionLocker: options.connectionLocker
49
- })
50
- const proxyConnectionRpcLocal = acceptProxyConnections ? new ProxyConnectionRpcLocal({
51
- localPeerDescriptor: options.localPeerDescriptor,
52
- streamPartId: options.streamPartId,
53
- rpcCommunicator
54
- }) : undefined
55
- const propagation = options.propagation ?? new Propagation({
56
- minPropagationTargets,
57
- sendToNeighbor: async (neighborId: DhtAddress, msg: StreamMessage): Promise<void> => {
58
- const remote = neighbors.get(neighborId) ?? temporaryConnectionRpcLocal.getNodes().get(neighborId)
59
- const proxyConnection = proxyConnectionRpcLocal?.getConnection(neighborId)
60
- if (remote) {
61
- await remote.sendStreamMessage(msg)
62
- } else if (proxyConnection) {
63
- await proxyConnection.remote.sendStreamMessage(msg)
64
- } else {
65
- throw new Error('Propagation target not found')
66
- }
67
- }
68
- })
69
- const handshaker = options.handshaker ?? new Handshaker({
70
- localPeerDescriptor: options.localPeerDescriptor,
71
- streamPartId: options.streamPartId,
72
- rpcCommunicator,
73
- neighbors,
74
- leftNodeView,
75
- rightNodeView,
76
- nearbyNodeView,
77
- randomNodeView,
78
- maxNeighborCount: neighborTargetCount,
79
- rpcRequestTimeout: options.rpcRequestTimeout,
80
- ongoingHandshakes
81
- })
82
- const neighborFinder = options.neighborFinder ?? new NeighborFinder({
83
- neighbors,
84
- leftNodeView,
85
- rightNodeView,
86
- nearbyNodeView,
87
- randomNodeView,
88
- doFindNeighbors: (excludedIds) => handshaker.attemptHandshakesOnContacts(excludedIds),
89
- minCount: neighborTargetCount
90
- })
91
- const neighborUpdateManager = options.neighborUpdateManager ?? new NeighborUpdateManager({
92
- neighbors,
93
- nearbyNodeView,
94
- localPeerDescriptor: options.localPeerDescriptor,
95
- neighborFinder,
96
- streamPartId: options.streamPartId,
97
- rpcCommunicator,
98
- neighborUpdateInterval,
99
- neighborTargetCount,
100
- ongoingHandshakes
101
- })
102
- const inspector = options.inspector ?? new Inspector({
103
- localPeerDescriptor: options.localPeerDescriptor,
104
- rpcCommunicator,
105
- streamPartId: options.streamPartId,
106
- connectionLocker: options.connectionLocker
107
- })
108
- return {
109
- ...options,
110
- neighbors,
111
- leftNodeView,
112
- rightNodeView,
113
- nearbyNodeView,
114
- randomNodeView,
115
- rpcCommunicator,
116
- handshaker,
117
- neighborFinder,
118
- neighborUpdateManager,
119
- propagation,
120
- neighborTargetCount,
121
- nodeViewSize: maxContactCount,
122
- proxyConnectionRpcLocal,
123
- inspector,
124
- temporaryConnectionRpcLocal
125
- }
126
- }
127
-
128
- export const createContentDeliveryLayerNode = (options: ContentDeliveryLayerNodeOptions): ContentDeliveryLayerNode => {
129
- return new ContentDeliveryLayerNode(createConfigWithDefaults(options))
130
- }
@@ -1,7 +0,0 @@
1
- import { ServiceID } from '@streamr/dht'
2
- import { StreamPartID } from '@streamr/utils'
3
-
4
- export const formStreamPartContentDeliveryServiceId = (streamPartId: StreamPartID): ServiceID => {
5
- // could be "content-delivery" instead of "delivery", but that is a breaking change
6
- return `stream-part-delivery-${streamPartId}`
7
- }