@streamr/trackerless-network 100.0.0-testnet-three.3 → 100.0.0-testnet-three.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/dist/package.json +55 -0
- package/dist/src/NetworkNode.js.map +1 -1
- package/dist/src/NetworkStack.js +7 -2
- package/dist/src/NetworkStack.js.map +1 -1
- package/dist/src/exports.d.ts +2 -1
- package/dist/src/exports.js +4 -1
- package/dist/src/exports.js.map +1 -1
- package/dist/src/logic/createRandomGraphNode.js +5 -2
- package/dist/src/logic/createRandomGraphNode.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/Handshaker.d.ts +1 -1
- package/dist/src/logic/neighbor-discovery/Handshaker.js +17 -15
- package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.d.ts +2 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.d.ts +2 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -1
- package/dist/src/logic/node-info/NodeInfoRpcLocal.js +3 -1
- package/dist/src/logic/node-info/NodeInfoRpcLocal.js.map +1 -1
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.d.ts +4 -0
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js +2 -1
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +1 -1
- package/package.json +6 -6
- package/protos/NetworkRpc.proto +1 -0
- package/src/NetworkNode.ts +1 -1
- package/src/NetworkStack.ts +9 -3
- package/src/exports.ts +2 -1
- package/src/logic/createRandomGraphNode.ts +5 -2
- package/src/logic/neighbor-discovery/Handshaker.ts +20 -15
- package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +2 -1
- package/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.ts +3 -2
- package/src/logic/node-info/NodeInfoRpcLocal.ts +3 -1
- package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +6 -1
- package/test/end-to-end/inspect.test.ts +3 -3
- package/test/end-to-end/proxy-and-full-node.test.ts +12 -12
- package/test/end-to-end/proxy-connections.test.ts +7 -7
- package/test/end-to-end/proxy-key-exchange.test.ts +5 -5
- package/test/end-to-end/webrtc-full-node-network.test.ts +6 -6
- package/test/end-to-end/websocket-full-node-network.test.ts +6 -6
- package/test/integration/Handshakes.test.ts +2 -1
- package/test/integration/NetworkStack.test.ts +2 -2
- package/test/integration/NodeInfoRpc.test.ts +2 -1
- package/test/unit/GroupKeyResponseTranslator.test.ts +1 -1
- package/test/unit/Handshaker.test.ts +2 -1
- package/test/unit/NeighborUpdateRpcLocal.test.ts +16 -2
- package/tsconfig.jest.json +2 -1
- package/tsconfig.node.json +2 -1
package/protos/NetworkRpc.proto
CHANGED
package/src/NetworkNode.ts
CHANGED
|
@@ -73,7 +73,7 @@ export class NetworkNode {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
setStreamPartEntryPoints(streamPartId: StreamPartID, contactPeerDescriptors: PeerDescriptor[]): void {
|
|
76
|
-
this.stack.getStreamrNode()
|
|
76
|
+
this.stack.getStreamrNode().setStreamPartEntryPoints(streamPartId, contactPeerDescriptors)
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
removeMessageListener(cb: (msg: StreamMessage) => void): void {
|
package/src/NetworkStack.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConnectionManager, DhtNode, DhtNodeOptions, ListeningRpcCommunicator, PeerDescriptor, areEqualPeerDescriptors } from '@streamr/dht'
|
|
2
2
|
import { StreamrNode, StreamrNodeConfig } from './logic/StreamrNode'
|
|
3
|
-
import { MetricsContext, waitForCondition } from '@streamr/utils'
|
|
3
|
+
import { Logger, MetricsContext, waitForCondition } from '@streamr/utils'
|
|
4
4
|
import { StreamID, StreamPartID, toStreamPartID } from '@streamr/protocol'
|
|
5
5
|
import { NodeInfoResponse, ProxyDirection, StreamMessage, StreamMessageType } from './proto/packages/trackerless-network/protos/NetworkRpc'
|
|
6
6
|
import { Layer0Node } from './logic/Layer0Node'
|
|
@@ -14,6 +14,8 @@ export interface NetworkOptions {
|
|
|
14
14
|
metricsContext?: MetricsContext
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
const logger = new Logger(module)
|
|
18
|
+
|
|
17
19
|
const instances: NetworkStack[] = []
|
|
18
20
|
const stopInstances = async () => {
|
|
19
21
|
// make a clone so that it is ok for each instance.stop() to remove itself from the list (at line 139)
|
|
@@ -23,9 +25,13 @@ const stopInstances = async () => {
|
|
|
23
25
|
}
|
|
24
26
|
const EXIT_EVENTS = [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `unhandledRejection`, `SIGTERM`]
|
|
25
27
|
EXIT_EVENTS.forEach((event) => {
|
|
26
|
-
process.on(event, async () => {
|
|
28
|
+
process.on(event, async (eventArg) => {
|
|
29
|
+
const isError = (event === 'uncaughtException') || (event === 'unhandledRejection')
|
|
30
|
+
if (isError) {
|
|
31
|
+
logger.error(`exit event: ${event}`, eventArg)
|
|
32
|
+
}
|
|
27
33
|
await stopInstances()
|
|
28
|
-
process.exit()
|
|
34
|
+
process.exit(isError ? 1 : 0)
|
|
29
35
|
})
|
|
30
36
|
})
|
|
31
37
|
declare let window: any
|
package/src/exports.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { NetworkStack, NetworkOptions } from './NetworkStack'
|
|
2
2
|
export { NetworkNode, createNetworkNode } from './NetworkNode'
|
|
3
3
|
export { StreamrNodeConfig } from './logic/StreamrNode'
|
|
4
|
-
export { ProxyDirection } from './proto/packages/trackerless-network/protos/NetworkRpc'
|
|
4
|
+
export { ProxyDirection, NodeInfoResponse } from './proto/packages/trackerless-network/protos/NetworkRpc'
|
|
5
|
+
export { streamPartIdToDataKey } from './logic/EntryPointDiscovery'
|
|
5
6
|
export {
|
|
6
7
|
convertStreamMessageToBytes,
|
|
7
8
|
convertBytesToStreamMessage
|
|
@@ -37,6 +37,7 @@ const createConfigWithDefaults = (config: RandomGraphNodeConfig): StrictRandomGr
|
|
|
37
37
|
const nearbyNodeView = config.nearbyNodeView ?? new NodeList(ownNodeId, maxContactCount)
|
|
38
38
|
const randomNodeView = config.randomNodeView ?? new NodeList(ownNodeId, maxContactCount)
|
|
39
39
|
const neighbors = config.neighbors ?? new NodeList(ownNodeId, maxContactCount)
|
|
40
|
+
const ongoingHandshakes = new Set<DhtAddress>()
|
|
40
41
|
|
|
41
42
|
const temporaryConnectionRpcLocal = new TemporaryConnectionRpcLocal({
|
|
42
43
|
rpcCommunicator,
|
|
@@ -70,7 +71,8 @@ const createConfigWithDefaults = (config: RandomGraphNodeConfig): StrictRandomGr
|
|
|
70
71
|
randomNodeView,
|
|
71
72
|
neighbors,
|
|
72
73
|
maxNeighborCount: neighborTargetCount,
|
|
73
|
-
rpcRequestTimeout: config.rpcRequestTimeout
|
|
74
|
+
rpcRequestTimeout: config.rpcRequestTimeout,
|
|
75
|
+
ongoingHandshakes
|
|
74
76
|
})
|
|
75
77
|
const neighborFinder = config.neighborFinder ?? new NeighborFinder({
|
|
76
78
|
neighbors,
|
|
@@ -87,7 +89,8 @@ const createConfigWithDefaults = (config: RandomGraphNodeConfig): StrictRandomGr
|
|
|
87
89
|
rpcCommunicator,
|
|
88
90
|
neighborUpdateInterval,
|
|
89
91
|
neighborTargetCount,
|
|
90
|
-
connectionLocker: config.connectionLocker
|
|
92
|
+
connectionLocker: config.connectionLocker,
|
|
93
|
+
ongoingHandshakes
|
|
91
94
|
})
|
|
92
95
|
const inspector = config.inspector ?? new Inspector({
|
|
93
96
|
localPeerDescriptor: config.localPeerDescriptor,
|
|
@@ -25,6 +25,7 @@ interface HandshakerConfig {
|
|
|
25
25
|
randomNodeView: NodeList
|
|
26
26
|
rpcCommunicator: ListeningRpcCommunicator
|
|
27
27
|
maxNeighborCount: number
|
|
28
|
+
ongoingHandshakes: Set<DhtAddress>
|
|
28
29
|
rpcRequestTimeout?: number
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -34,7 +35,6 @@ const PARALLEL_HANDSHAKE_COUNT = 2
|
|
|
34
35
|
|
|
35
36
|
export class Handshaker {
|
|
36
37
|
|
|
37
|
-
private readonly ongoingHandshakes: Set<DhtAddress> = new Set()
|
|
38
38
|
private config: HandshakerConfig
|
|
39
39
|
private readonly rpcLocal: IHandshakeRpc
|
|
40
40
|
|
|
@@ -44,7 +44,7 @@ export class Handshaker {
|
|
|
44
44
|
streamPartId: this.config.streamPartId,
|
|
45
45
|
neighbors: this.config.neighbors,
|
|
46
46
|
connectionLocker: this.config.connectionLocker,
|
|
47
|
-
ongoingHandshakes: this.ongoingHandshakes,
|
|
47
|
+
ongoingHandshakes: this.config.ongoingHandshakes,
|
|
48
48
|
ongoingInterleaves: new Set(),
|
|
49
49
|
maxNeighborCount: this.config.maxNeighborCount,
|
|
50
50
|
handshakeWithInterleaving: (target: PeerDescriptor, senderId: DhtAddress) => this.handshakeWithInterleaving(target, senderId),
|
|
@@ -59,10 +59,10 @@ export class Handshaker {
|
|
|
59
59
|
|
|
60
60
|
async attemptHandshakesOnContacts(excludedIds: DhtAddress[]): Promise<DhtAddress[]> {
|
|
61
61
|
// TODO use config option or named constant? or why the value 2?
|
|
62
|
-
if (this.config.neighbors.size() + this.ongoingHandshakes.size < this.config.maxNeighborCount - 2) {
|
|
62
|
+
if (this.config.neighbors.size() + this.config.ongoingHandshakes.size < this.config.maxNeighborCount - 2) {
|
|
63
63
|
logger.trace(`Attempting parallel handshakes with ${PARALLEL_HANDSHAKE_COUNT} targets`)
|
|
64
64
|
return this.selectParallelTargetsAndHandshake(excludedIds)
|
|
65
|
-
} else if (this.config.neighbors.size() + this.ongoingHandshakes.size < this.config.maxNeighborCount) {
|
|
65
|
+
} else if (this.config.neighbors.size() + this.config.ongoingHandshakes.size < this.config.maxNeighborCount) {
|
|
66
66
|
logger.trace(`Attempting handshake with new target`)
|
|
67
67
|
return this.selectNewTargetAndHandshake(excludedIds)
|
|
68
68
|
}
|
|
@@ -72,17 +72,22 @@ export class Handshaker {
|
|
|
72
72
|
private async selectParallelTargetsAndHandshake(excludedIds: DhtAddress[]): Promise<DhtAddress[]> {
|
|
73
73
|
const exclude = excludedIds.concat(this.config.neighbors.getIds())
|
|
74
74
|
const neighbors = this.selectParallelTargets(exclude)
|
|
75
|
-
neighbors.forEach((contact) => this.ongoingHandshakes.add(getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())))
|
|
75
|
+
neighbors.forEach((contact) => this.config.ongoingHandshakes.add(getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())))
|
|
76
76
|
return this.doParallelHandshakes(neighbors, exclude)
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
private selectParallelTargets(excludedIds: DhtAddress[]): HandshakeRpcRemote[] {
|
|
80
80
|
const neighbors = this.config.nearbyNodeView.getFirstAndLast(excludedIds)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
const getExcludedFromRandomView = () => [
|
|
82
|
+
...excludedIds,
|
|
83
|
+
...neighbors.map((neighbor) => getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor()))
|
|
84
|
+
]
|
|
85
|
+
while (
|
|
86
|
+
neighbors.length < PARALLEL_HANDSHAKE_COUNT
|
|
87
|
+
&& this.config.randomNodeView.size(getExcludedFromRandomView()) > 0
|
|
88
|
+
) {
|
|
89
|
+
const random = this.config.randomNodeView.getRandom(getExcludedFromRandomView())!
|
|
90
|
+
neighbors.push(random)
|
|
86
91
|
}
|
|
87
92
|
return neighbors.map((neighbor) => this.createRpcRemote(neighbor.getPeerDescriptor()))
|
|
88
93
|
}
|
|
@@ -118,7 +123,7 @@ export class Handshaker {
|
|
|
118
123
|
|
|
119
124
|
private async handshakeWithTarget(neighbor: HandshakeRpcRemote, concurrentNodeId?: DhtAddress): Promise<boolean> {
|
|
120
125
|
const targetNodeId = getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor())
|
|
121
|
-
this.ongoingHandshakes.add(targetNodeId)
|
|
126
|
+
this.config.ongoingHandshakes.add(targetNodeId)
|
|
122
127
|
const result = await neighbor.handshake(
|
|
123
128
|
this.config.streamPartId,
|
|
124
129
|
this.config.neighbors.getIds(),
|
|
@@ -131,14 +136,14 @@ export class Handshaker {
|
|
|
131
136
|
if (result.interleaveTargetDescriptor) {
|
|
132
137
|
await this.handshakeWithInterleaving(result.interleaveTargetDescriptor, targetNodeId)
|
|
133
138
|
}
|
|
134
|
-
this.ongoingHandshakes.delete(targetNodeId)
|
|
139
|
+
this.config.ongoingHandshakes.delete(targetNodeId)
|
|
135
140
|
return result.accepted
|
|
136
141
|
}
|
|
137
142
|
|
|
138
143
|
private async handshakeWithInterleaving(target: PeerDescriptor, interleaveSourceId: DhtAddress): Promise<boolean> {
|
|
139
144
|
const neighbor = this.createRpcRemote(target)
|
|
140
145
|
const targetNodeId = getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor())
|
|
141
|
-
this.ongoingHandshakes.add(targetNodeId)
|
|
146
|
+
this.config.ongoingHandshakes.add(targetNodeId)
|
|
142
147
|
const result = await neighbor.handshake(
|
|
143
148
|
this.config.streamPartId,
|
|
144
149
|
this.config.neighbors.getIds(),
|
|
@@ -149,7 +154,7 @@ export class Handshaker {
|
|
|
149
154
|
this.config.neighbors.add(this.createDeliveryRpcRemote(neighbor.getPeerDescriptor()))
|
|
150
155
|
this.config.connectionLocker.lockConnection(neighbor.getPeerDescriptor(), this.config.streamPartId)
|
|
151
156
|
}
|
|
152
|
-
this.ongoingHandshakes.delete(targetNodeId)
|
|
157
|
+
this.config.ongoingHandshakes.delete(targetNodeId)
|
|
153
158
|
return result.accepted
|
|
154
159
|
}
|
|
155
160
|
|
|
@@ -174,7 +179,7 @@ export class Handshaker {
|
|
|
174
179
|
}
|
|
175
180
|
|
|
176
181
|
getOngoingHandshakes(): Set<DhtAddress> {
|
|
177
|
-
return this.ongoingHandshakes
|
|
182
|
+
return this.config.ongoingHandshakes
|
|
178
183
|
}
|
|
179
184
|
|
|
180
185
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NeighborUpdate } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
|
|
2
|
-
import { ConnectionLocker, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
2
|
+
import { ConnectionLocker, DhtAddress, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
3
3
|
import { NeighborUpdateRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
|
|
4
4
|
import { Logger, scheduleAtInterval } from '@streamr/utils'
|
|
5
5
|
import { NeighborFinder } from './NeighborFinder'
|
|
@@ -18,6 +18,7 @@ interface NeighborUpdateManagerConfig {
|
|
|
18
18
|
rpcCommunicator: ListeningRpcCommunicator
|
|
19
19
|
neighborUpdateInterval: number
|
|
20
20
|
neighborTargetCount: number
|
|
21
|
+
ongoingHandshakes: Set<DhtAddress>
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const logger = new Logger(module)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
|
|
2
|
-
import { ConnectionLocker, DhtCallContext, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
2
|
+
import { ConnectionLocker, DhtAddress, DhtCallContext, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
3
3
|
import { NeighborUpdate } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
|
|
4
4
|
import { DeliveryRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
|
|
5
5
|
import { INeighborUpdateRpc } from '../../proto/packages/trackerless-network/protos/NetworkRpc.server'
|
|
@@ -17,6 +17,7 @@ interface NeighborUpdateRpcLocalConfig {
|
|
|
17
17
|
connectionLocker: ConnectionLocker
|
|
18
18
|
rpcCommunicator: ListeningRpcCommunicator
|
|
19
19
|
neighborTargetCount: number
|
|
20
|
+
ongoingHandshakes: Set<DhtAddress>
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export class NeighborUpdateRpcLocal implements INeighborUpdateRpc {
|
|
@@ -56,7 +57,7 @@ export class NeighborUpdateRpcLocal implements INeighborUpdateRpc {
|
|
|
56
57
|
const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
|
|
57
58
|
const senderId = getNodeIdFromPeerDescriptor(senderPeerDescriptor)
|
|
58
59
|
this.updateContacts(message.neighborDescriptors)
|
|
59
|
-
if (!this.config.neighbors.has(senderId)) {
|
|
60
|
+
if (!this.config.neighbors.has(senderId) && !this.config.ongoingHandshakes.has(senderId)) {
|
|
60
61
|
return this.createResponse(true)
|
|
61
62
|
} else {
|
|
62
63
|
const isOverNeighborCount = this.config.neighbors.size() > this.config.neighborTargetCount
|
|
@@ -2,6 +2,7 @@ import { NodeInfoRequest, NodeInfoResponse } from '../../proto/packages/trackerl
|
|
|
2
2
|
import { INodeInfoRpc } from '../../proto/packages/trackerless-network/protos/NetworkRpc.server'
|
|
3
3
|
import { NetworkStack } from '../../NetworkStack'
|
|
4
4
|
import { ListeningRpcCommunicator } from '@streamr/dht'
|
|
5
|
+
import { version as localVersion } from '../../../package.json'
|
|
5
6
|
|
|
6
7
|
export const NODE_INFO_RPC_SERVICE_ID = 'system/node-info-rpc'
|
|
7
8
|
|
|
@@ -28,7 +29,8 @@ export class NodeInfoRpcLocal implements INodeInfoRpc {
|
|
|
28
29
|
connections: this.stack.getLayer0Node().getConnections(),
|
|
29
30
|
neighbors: this.stack.getLayer0Node().getNeighbors()
|
|
30
31
|
},
|
|
31
|
-
streamPartitions: this.stack.getStreamrNode().getNodeInfo()
|
|
32
|
+
streamPartitions: this.stack.getStreamrNode().getNodeInfo(),
|
|
33
|
+
version: localVersion
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -329,6 +329,10 @@ export interface NodeInfoResponse {
|
|
|
329
329
|
* @generated from protobuf field: optional ControlLayerInfo controlLayer = 3;
|
|
330
330
|
*/
|
|
331
331
|
controlLayer?: ControlLayerInfo;
|
|
332
|
+
/**
|
|
333
|
+
* @generated from protobuf field: string version = 4;
|
|
334
|
+
*/
|
|
335
|
+
version: string;
|
|
332
336
|
}
|
|
333
337
|
/**
|
|
334
338
|
* @generated from protobuf enum StreamMessageType
|
|
@@ -673,7 +677,8 @@ class NodeInfoResponse$Type extends MessageType<NodeInfoResponse> {
|
|
|
673
677
|
super("NodeInfoResponse", [
|
|
674
678
|
{ no: 1, name: "peerDescriptor", kind: "message", T: () => PeerDescriptor },
|
|
675
679
|
{ no: 2, name: "streamPartitions", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => StreamPartitionInfo },
|
|
676
|
-
{ no: 3, name: "controlLayer", kind: "message", T: () => ControlLayerInfo }
|
|
680
|
+
{ no: 3, name: "controlLayer", kind: "message", T: () => ControlLayerInfo },
|
|
681
|
+
{ no: 4, name: "version", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
|
677
682
|
]);
|
|
678
683
|
}
|
|
679
684
|
}
|
|
@@ -96,9 +96,9 @@ describe('inspect', () => {
|
|
|
96
96
|
await inspectedNode.start()
|
|
97
97
|
await inspectorNode.start()
|
|
98
98
|
|
|
99
|
-
publisherNode.stack.getStreamrNode()
|
|
100
|
-
inspectedNode.stack.getStreamrNode()
|
|
101
|
-
inspectorNode.stack.getStreamrNode()
|
|
99
|
+
publisherNode.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
|
|
100
|
+
inspectedNode.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
|
|
101
|
+
inspectorNode.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
|
|
102
102
|
|
|
103
103
|
await waitForCondition(() =>
|
|
104
104
|
publisherNode.stack.getStreamrNode().getNeighbors(STREAM_PART_ID).length === 2
|
|
@@ -65,11 +65,11 @@ describe('proxy and full node', () => {
|
|
|
65
65
|
}
|
|
66
66
|
})
|
|
67
67
|
await proxyNode.start()
|
|
68
|
-
proxyNode.stack.getStreamrNode()
|
|
69
|
-
proxyNode.stack.getStreamrNode()
|
|
70
|
-
proxyNode.stack.getStreamrNode()
|
|
71
|
-
proxyNode.stack.getStreamrNode()
|
|
72
|
-
proxyNode.stack.getStreamrNode()
|
|
68
|
+
proxyNode.stack.getStreamrNode().joinStreamPart(proxiedStreamPart)
|
|
69
|
+
proxyNode.stack.getStreamrNode().joinStreamPart(regularStreamPart1)
|
|
70
|
+
proxyNode.stack.getStreamrNode().joinStreamPart(regularStreamPart2)
|
|
71
|
+
proxyNode.stack.getStreamrNode().joinStreamPart(regularStreamPart3)
|
|
72
|
+
proxyNode.stack.getStreamrNode().joinStreamPart(regularStreamPart4)
|
|
73
73
|
|
|
74
74
|
proxiedNode = createNetworkNode({
|
|
75
75
|
layer0: {
|
|
@@ -90,14 +90,14 @@ describe('proxy and full node', () => {
|
|
|
90
90
|
expect(proxiedNode.stack.getLayer0Node().hasJoined()).toBe(false)
|
|
91
91
|
|
|
92
92
|
await Promise.all([
|
|
93
|
-
waitForEvent3(proxyNode.stack.getStreamrNode()
|
|
93
|
+
waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage'),
|
|
94
94
|
proxiedNode.broadcast(createMessage(regularStreamPart1))
|
|
95
95
|
])
|
|
96
96
|
|
|
97
97
|
expect(proxiedNode.stack.getLayer0Node().hasJoined()).toBe(true)
|
|
98
98
|
|
|
99
99
|
await Promise.all([
|
|
100
|
-
waitForEvent3(proxyNode.stack.getStreamrNode()
|
|
100
|
+
waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage'),
|
|
101
101
|
proxiedNode.broadcast(createMessage(proxiedStreamPart))
|
|
102
102
|
])
|
|
103
103
|
|
|
@@ -110,13 +110,13 @@ describe('proxy and full node', () => {
|
|
|
110
110
|
expect(proxiedNode.stack.getLayer0Node().hasJoined()).toBe(false)
|
|
111
111
|
|
|
112
112
|
await Promise.all([
|
|
113
|
-
waitForEvent3(proxyNode.stack.getStreamrNode()
|
|
113
|
+
waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage', 5000,
|
|
114
114
|
(streamMessage: InternalStreamMessage) => streamMessage.messageId!.streamId === StreamPartIDUtils.getStreamID(regularStreamPart1)),
|
|
115
|
-
waitForEvent3(proxyNode.stack.getStreamrNode()
|
|
115
|
+
waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage', 5000,
|
|
116
116
|
(streamMessage: InternalStreamMessage) => streamMessage.messageId!.streamId === StreamPartIDUtils.getStreamID(regularStreamPart2)),
|
|
117
|
-
waitForEvent3(proxyNode.stack.getStreamrNode()
|
|
117
|
+
waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage', 5000,
|
|
118
118
|
(streamMessage: InternalStreamMessage) => streamMessage.messageId!.streamId === StreamPartIDUtils.getStreamID(regularStreamPart3)),
|
|
119
|
-
waitForEvent3(proxyNode.stack.getStreamrNode()
|
|
119
|
+
waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage', 5000,
|
|
120
120
|
(streamMessage: InternalStreamMessage) => streamMessage.messageId!.streamId === StreamPartIDUtils.getStreamID(regularStreamPart4)),
|
|
121
121
|
proxiedNode.broadcast(createMessage(regularStreamPart1)),
|
|
122
122
|
proxiedNode.broadcast(createMessage(regularStreamPart2)),
|
|
@@ -127,7 +127,7 @@ describe('proxy and full node', () => {
|
|
|
127
127
|
expect(proxiedNode.stack.getLayer0Node().hasJoined()).toBe(true)
|
|
128
128
|
|
|
129
129
|
await Promise.all([
|
|
130
|
-
waitForEvent3(proxyNode.stack.getStreamrNode()
|
|
130
|
+
waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage'),
|
|
131
131
|
proxiedNode.broadcast(createMessage(proxiedStreamPart))
|
|
132
132
|
])
|
|
133
133
|
|
|
@@ -46,14 +46,14 @@ describe('Proxy connections', () => {
|
|
|
46
46
|
let proxiedNode: NetworkNode
|
|
47
47
|
|
|
48
48
|
const hasConnectionFromProxy = (proxyNode: NetworkNode): boolean => {
|
|
49
|
-
const delivery = proxyNode.stack.getStreamrNode()
|
|
49
|
+
const delivery = proxyNode.stack.getStreamrNode().getStreamPartDelivery(STREAM_PART_ID)
|
|
50
50
|
return (delivery !== undefined)
|
|
51
51
|
? ((delivery as { node: RandomGraphNode }).node).hasProxyConnection(proxiedNode.getNodeId())
|
|
52
52
|
: false
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const hasConnectionToProxy = (proxyNodeId: DhtAddress, direction: ProxyDirection): boolean => {
|
|
56
|
-
const client = (proxiedNode.stack.getStreamrNode()
|
|
56
|
+
const client = (proxiedNode.stack.getStreamrNode().getStreamPartDelivery(STREAM_PART_ID) as { client: ProxyClient }).client
|
|
57
57
|
return client.hasConnection(proxyNodeId, direction)
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -77,7 +77,7 @@ describe('Proxy connections', () => {
|
|
|
77
77
|
})
|
|
78
78
|
await proxyNode1.start()
|
|
79
79
|
proxyNode1.setStreamPartEntryPoints(STREAM_PART_ID, [proxyNodeDescriptor1])
|
|
80
|
-
proxyNode1.stack.getStreamrNode()
|
|
80
|
+
proxyNode1.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
|
|
81
81
|
proxyNode2 = createNetworkNode({
|
|
82
82
|
layer0: {
|
|
83
83
|
entryPoints: [proxyNodeDescriptor1],
|
|
@@ -90,7 +90,7 @@ describe('Proxy connections', () => {
|
|
|
90
90
|
})
|
|
91
91
|
await proxyNode2.start()
|
|
92
92
|
proxyNode2.setStreamPartEntryPoints(STREAM_PART_ID, [proxyNodeDescriptor1])
|
|
93
|
-
proxyNode2.stack.getStreamrNode()
|
|
93
|
+
proxyNode2.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
|
|
94
94
|
proxiedNode = createNetworkNode({
|
|
95
95
|
layer0: {
|
|
96
96
|
entryPoints: [proxyNode1.getPeerDescriptor()],
|
|
@@ -109,7 +109,7 @@ describe('Proxy connections', () => {
|
|
|
109
109
|
it('happy path publishing', async () => {
|
|
110
110
|
await proxiedNode.setProxies(STREAM_PART_ID, [proxyNode1.getPeerDescriptor()], ProxyDirection.PUBLISH, PROXIED_NODE_USER_ID, 1)
|
|
111
111
|
await Promise.all([
|
|
112
|
-
waitForEvent3(proxyNode1.stack.getStreamrNode()
|
|
112
|
+
waitForEvent3(proxyNode1.stack.getStreamrNode() as any, 'newMessage'),
|
|
113
113
|
proxiedNode.broadcast(MESSAGE)
|
|
114
114
|
])
|
|
115
115
|
})
|
|
@@ -117,7 +117,7 @@ describe('Proxy connections', () => {
|
|
|
117
117
|
it('happy path subscribing', async () => {
|
|
118
118
|
await proxiedNode.setProxies(STREAM_PART_ID, [proxyNode1.getPeerDescriptor()], ProxyDirection.SUBSCRIBE, PROXIED_NODE_USER_ID, 1)
|
|
119
119
|
await Promise.all([
|
|
120
|
-
waitForEvent3(proxiedNode.stack.getStreamrNode()
|
|
120
|
+
waitForEvent3(proxiedNode.stack.getStreamrNode() as any, 'newMessage'),
|
|
121
121
|
proxyNode1.broadcast(MESSAGE)
|
|
122
122
|
])
|
|
123
123
|
})
|
|
@@ -196,7 +196,7 @@ describe('Proxy connections', () => {
|
|
|
196
196
|
await proxyNode1.leave(STREAM_PART_ID)
|
|
197
197
|
await waitForCondition(() => hasConnectionToProxy(proxyNode1.getNodeId(), ProxyDirection.SUBSCRIBE))
|
|
198
198
|
expect(hasConnectionFromProxy(proxyNode1)).toBe(false)
|
|
199
|
-
proxyNode1.stack.getStreamrNode()
|
|
199
|
+
proxyNode1.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
|
|
200
200
|
await waitForCondition(() => hasConnectionToProxy(proxyNode1.getNodeId(), ProxyDirection.SUBSCRIBE), 25000)
|
|
201
201
|
// TODO why wait is needed?
|
|
202
202
|
await wait(100)
|
|
@@ -44,10 +44,10 @@ describe('proxy group key exchange', () => {
|
|
|
44
44
|
})
|
|
45
45
|
await proxyNode.start()
|
|
46
46
|
proxyNode.setStreamPartEntryPoints(STREAM_PART_ID, [proxyNodeDescriptor])
|
|
47
|
-
proxyNode.stack.getStreamrNode()
|
|
47
|
+
proxyNode.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
|
|
48
48
|
publisher = createNetworkNode({
|
|
49
49
|
layer0: {
|
|
50
|
-
entryPoints: [
|
|
50
|
+
entryPoints: [proxyNodeDescriptor],
|
|
51
51
|
peerDescriptor: publisherDescriptor,
|
|
52
52
|
}
|
|
53
53
|
})
|
|
@@ -55,7 +55,7 @@ describe('proxy group key exchange', () => {
|
|
|
55
55
|
|
|
56
56
|
subscriber = createNetworkNode({
|
|
57
57
|
layer0: {
|
|
58
|
-
entryPoints: [
|
|
58
|
+
entryPoints: [proxyNodeDescriptor],
|
|
59
59
|
peerDescriptor: subscriberDescriptor,
|
|
60
60
|
}
|
|
61
61
|
})
|
|
@@ -98,7 +98,7 @@ describe('proxy group key exchange', () => {
|
|
|
98
98
|
})
|
|
99
99
|
|
|
100
100
|
await Promise.all([
|
|
101
|
-
waitForEvent3(publisher.stack.getStreamrNode()
|
|
101
|
+
waitForEvent3(publisher.stack.getStreamrNode() as any, 'newMessage'),
|
|
102
102
|
subscriber.broadcast(request)
|
|
103
103
|
])
|
|
104
104
|
})
|
|
@@ -130,7 +130,7 @@ describe('proxy group key exchange', () => {
|
|
|
130
130
|
})
|
|
131
131
|
|
|
132
132
|
await Promise.all([
|
|
133
|
-
waitForEvent3(subscriber.stack.getStreamrNode()
|
|
133
|
+
waitForEvent3(subscriber.stack.getStreamrNode() as any, 'newMessage'),
|
|
134
134
|
publisher.broadcast(response)
|
|
135
135
|
])
|
|
136
136
|
})
|
|
@@ -33,8 +33,8 @@ describe('Full node network with WebRTC connections', () => {
|
|
|
33
33
|
}
|
|
34
34
|
})
|
|
35
35
|
await entryPoint.start()
|
|
36
|
-
entryPoint.getStreamrNode()
|
|
37
|
-
entryPoint.getStreamrNode()
|
|
36
|
+
entryPoint.getStreamrNode().setStreamPartEntryPoints(streamPartId, [epPeerDescriptor])
|
|
37
|
+
entryPoint.getStreamrNode().joinStreamPart(streamPartId)
|
|
38
38
|
|
|
39
39
|
await Promise.all(range(NUM_OF_NODES).map(async () => {
|
|
40
40
|
const peerDescriptor = createMockPeerDescriptor()
|
|
@@ -62,15 +62,15 @@ describe('Full node network with WebRTC connections', () => {
|
|
|
62
62
|
it('happy path', async () => {
|
|
63
63
|
await Promise.all(nodes.map((node) =>
|
|
64
64
|
waitForCondition(() => {
|
|
65
|
-
return node.getStreamrNode()
|
|
65
|
+
return node.getStreamrNode().getNeighbors(streamPartId).length >= 3
|
|
66
66
|
}
|
|
67
67
|
, 30000)
|
|
68
68
|
))
|
|
69
69
|
let receivedMessageCount = 0
|
|
70
70
|
const successIds: string[] = []
|
|
71
71
|
nodes.forEach((node) => {
|
|
72
|
-
node.getStreamrNode()
|
|
73
|
-
successIds.push(getNodeIdFromPeerDescriptor(node.getStreamrNode()
|
|
72
|
+
node.getStreamrNode().on('newMessage', () => {
|
|
73
|
+
successIds.push(getNodeIdFromPeerDescriptor(node.getStreamrNode().getPeerDescriptor()))
|
|
74
74
|
receivedMessageCount += 1
|
|
75
75
|
})
|
|
76
76
|
})
|
|
@@ -79,7 +79,7 @@ describe('Full node network with WebRTC connections', () => {
|
|
|
79
79
|
streamPartId,
|
|
80
80
|
randomEthereumAddress()
|
|
81
81
|
)
|
|
82
|
-
entryPoint.getStreamrNode()
|
|
82
|
+
entryPoint.getStreamrNode().broadcast(msg)
|
|
83
83
|
await waitForCondition(() => receivedMessageCount === NUM_OF_NODES)
|
|
84
84
|
}, 120000)
|
|
85
85
|
|
|
@@ -30,8 +30,8 @@ describe('Full node network with WebSocket connections only', () => {
|
|
|
30
30
|
}
|
|
31
31
|
})
|
|
32
32
|
await entryPoint.start()
|
|
33
|
-
entryPoint.getStreamrNode()
|
|
34
|
-
entryPoint.getStreamrNode()
|
|
33
|
+
entryPoint.getStreamrNode().setStreamPartEntryPoints(streamPartId, [epPeerDescriptor])
|
|
34
|
+
entryPoint.getStreamrNode().joinStreamPart(streamPartId)
|
|
35
35
|
|
|
36
36
|
await Promise.all(range(NUM_OF_NODES).map(async (i) => {
|
|
37
37
|
const node = new NetworkStack({
|
|
@@ -60,15 +60,15 @@ describe('Full node network with WebSocket connections only', () => {
|
|
|
60
60
|
it('happy path', async () => {
|
|
61
61
|
await Promise.all(nodes.map((node) =>
|
|
62
62
|
waitForCondition(() => {
|
|
63
|
-
return node.getStreamrNode()
|
|
63
|
+
return node.getStreamrNode().getNeighbors(streamPartId).length >= 4
|
|
64
64
|
}
|
|
65
65
|
, 30000)
|
|
66
66
|
))
|
|
67
67
|
let receivedMessageCount = 0
|
|
68
68
|
const successIds: string[] = []
|
|
69
69
|
nodes.forEach((node) => {
|
|
70
|
-
node.getStreamrNode()
|
|
71
|
-
successIds.push(getNodeIdFromPeerDescriptor(node.getStreamrNode()
|
|
70
|
+
node.getStreamrNode().on('newMessage', () => {
|
|
71
|
+
successIds.push(getNodeIdFromPeerDescriptor(node.getStreamrNode().getPeerDescriptor()))
|
|
72
72
|
receivedMessageCount += 1
|
|
73
73
|
})
|
|
74
74
|
})
|
|
@@ -78,7 +78,7 @@ describe('Full node network with WebSocket connections only', () => {
|
|
|
78
78
|
streamPartId,
|
|
79
79
|
randomEthereumAddress()
|
|
80
80
|
)
|
|
81
|
-
entryPoint.getStreamrNode()
|
|
81
|
+
entryPoint.getStreamrNode().broadcast(msg)
|
|
82
82
|
await waitForCondition(() => receivedMessageCount === NUM_OF_NODES)
|
|
83
83
|
}, 220000)
|
|
84
84
|
|
|
@@ -34,9 +34,9 @@ describe('NetworkStack', () => {
|
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
await stack1.start()
|
|
37
|
-
stack1.getStreamrNode()
|
|
37
|
+
stack1.getStreamrNode().setStreamPartEntryPoints(STREAM_PART_ID, [epDescriptor])
|
|
38
38
|
await stack2.start()
|
|
39
|
-
stack2.getStreamrNode()
|
|
39
|
+
stack2.getStreamrNode().setStreamPartEntryPoints(STREAM_PART_ID, [epDescriptor])
|
|
40
40
|
})
|
|
41
41
|
|
|
42
42
|
afterEach(async () => {
|
|
@@ -95,7 +95,8 @@ describe('NetworkStack NodeInfoRpc', () => {
|
|
|
95
95
|
controlLayerNeighbors: [normalizePeerDescriptor(otherPeerDescriptor)],
|
|
96
96
|
deliveryLayerNeighbors: [normalizePeerDescriptor(otherPeerDescriptor)]
|
|
97
97
|
}
|
|
98
|
-
]
|
|
98
|
+
],
|
|
99
|
+
version: expect.any(String)
|
|
99
100
|
})
|
|
100
101
|
expect(result.streamPartitions.length).toEqual(2)
|
|
101
102
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ListeningRpcCommunicator, getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
1
|
+
import { DhtAddress, ListeningRpcCommunicator, getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
2
2
|
import { NeighborFinder } from '../../src/logic/neighbor-discovery/NeighborFinder'
|
|
3
3
|
import { NeighborUpdateRpcLocal } from '../../src/logic/neighbor-discovery/NeighborUpdateRpcLocal'
|
|
4
4
|
import { createMockPeerDescriptor } from '../utils/utils'
|
|
@@ -20,6 +20,7 @@ describe('NeighborUpdateRpcLocal', () => {
|
|
|
20
20
|
let nearbyNodeView: NodeList
|
|
21
21
|
let neighborFinder: NeighborFinder
|
|
22
22
|
let rpcCommunicator: ListeningRpcCommunicator
|
|
23
|
+
let ongoingHandshakes: Set<DhtAddress>
|
|
23
24
|
|
|
24
25
|
const addNeighbors = (count: number) => {
|
|
25
26
|
for (let i = 0; i < count; i++) {
|
|
@@ -42,6 +43,7 @@ describe('NeighborUpdateRpcLocal', () => {
|
|
|
42
43
|
const connectionLocker = {
|
|
43
44
|
unlockConnection: jest.fn()
|
|
44
45
|
} as any
|
|
46
|
+
ongoingHandshakes = new Set()
|
|
45
47
|
|
|
46
48
|
rpcLocal = new NeighborUpdateRpcLocal({
|
|
47
49
|
localPeerDescriptor,
|
|
@@ -51,7 +53,8 @@ describe('NeighborUpdateRpcLocal', () => {
|
|
|
51
53
|
streamPartId,
|
|
52
54
|
rpcCommunicator,
|
|
53
55
|
neighborTargetCount,
|
|
54
|
-
connectionLocker
|
|
56
|
+
connectionLocker,
|
|
57
|
+
ongoingHandshakes
|
|
55
58
|
})
|
|
56
59
|
})
|
|
57
60
|
|
|
@@ -126,4 +129,15 @@ describe('NeighborUpdateRpcLocal', () => {
|
|
|
126
129
|
expect(neighbors.has(getNodeIdFromPeerDescriptor(caller))).toEqual(false)
|
|
127
130
|
})
|
|
128
131
|
|
|
132
|
+
it('does not ask to be removed if there is an ongoing handshake to the caller', async () => {
|
|
133
|
+
const caller = createMockPeerDescriptor()
|
|
134
|
+
ongoingHandshakes.add(getNodeIdFromPeerDescriptor(caller))
|
|
135
|
+
const res = await rpcLocal.neighborUpdate({
|
|
136
|
+
streamPartId,
|
|
137
|
+
neighborDescriptors: [localPeerDescriptor],
|
|
138
|
+
removeMe: false
|
|
139
|
+
}, { incomingSourceDescriptor: caller } as any)
|
|
140
|
+
expect(res.removeMe).toEqual(false)
|
|
141
|
+
})
|
|
142
|
+
|
|
129
143
|
})
|