@waku/core 0.0.21 → 0.0.23
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/CHANGELOG.md +48 -0
- package/bundle/base_protocol-84d9b670.js +1198 -0
- package/bundle/index.js +1163 -1281
- package/bundle/lib/base_protocol.js +2 -116
- package/bundle/lib/message/version_0.js +1 -1
- package/bundle/lib/predefined_bootstrap_nodes.js +6 -6
- package/bundle/{version_0-86411fdf.js → version_0-74b4b9db.js} +875 -794
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.d.ts +18 -5
- package/dist/lib/base_protocol.js +25 -8
- package/dist/lib/base_protocol.js.map +1 -1
- package/dist/lib/connection_manager.d.ts +3 -5
- package/dist/lib/connection_manager.js +53 -45
- package/dist/lib/connection_manager.js.map +1 -1
- package/dist/lib/filter/filter_rpc.js +4 -4
- package/dist/lib/filter/index.d.ts +4 -0
- package/dist/lib/filter/index.js +24 -27
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/filterPeers.d.ts +10 -0
- package/dist/lib/filterPeers.js +31 -0
- package/dist/lib/filterPeers.js.map +1 -0
- package/dist/lib/keep_alive_manager.d.ts +4 -6
- package/dist/lib/keep_alive_manager.js +27 -8
- package/dist/lib/keep_alive_manager.js.map +1 -1
- package/dist/lib/light_push/index.js +62 -33
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/light_push/push_rpc.js +2 -2
- package/dist/lib/message/version_0.d.ts +1 -1
- package/dist/lib/message/version_0.js +3 -3
- package/dist/lib/message/version_0.js.map +1 -1
- package/dist/lib/predefined_bootstrap_nodes.js +6 -6
- package/dist/lib/store/history_rpc.js +3 -3
- package/dist/lib/store/index.d.ts +0 -5
- package/dist/lib/store/index.js +54 -37
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/stream_manager.d.ts +15 -0
- package/dist/lib/stream_manager.js +53 -0
- package/dist/lib/stream_manager.js.map +1 -0
- package/dist/lib/to_proto_message.js +1 -1
- package/dist/lib/waku.d.ts +2 -2
- package/dist/lib/waku.js +1 -1
- package/package.json +16 -22
- package/src/index.ts +7 -13
- package/src/lib/base_protocol.ts +49 -18
- package/src/lib/connection_manager.ts +82 -66
- package/src/lib/filter/filter_rpc.ts +4 -4
- package/src/lib/filter/index.ts +32 -39
- package/src/lib/filterPeers.ts +43 -0
- package/src/lib/keep_alive_manager.ts +34 -14
- package/src/lib/light_push/index.ts +103 -47
- package/src/lib/light_push/push_rpc.ts +2 -2
- package/src/lib/message/version_0.ts +8 -5
- package/src/lib/predefined_bootstrap_nodes.ts +7 -7
- package/src/lib/store/history_rpc.ts +4 -4
- package/src/lib/store/index.ts +70 -51
- package/src/lib/stream_manager.ts +69 -0
- package/src/lib/to_proto_message.ts +1 -1
- package/src/lib/wait_for_remote_peer.ts +1 -1
- package/src/lib/waku.ts +3 -3
@@ -1,18 +1,20 @@
|
|
1
|
-
import type { PeerId } from "@libp2p/interface
|
2
|
-
import type { PeerInfo } from "@libp2p/interface
|
3
|
-
import type { Peer } from "@libp2p/interface
|
1
|
+
import type { PeerId } from "@libp2p/interface/peer-id";
|
2
|
+
import type { PeerInfo } from "@libp2p/interface/peer-info";
|
3
|
+
import type { Peer } from "@libp2p/interface/peer-store";
|
4
4
|
import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events";
|
5
5
|
import {
|
6
6
|
ConnectionManagerOptions,
|
7
7
|
EPeersByDiscoveryEvents,
|
8
|
+
IConnectionManager,
|
8
9
|
IPeersByDiscoveryEvents,
|
9
10
|
IRelay,
|
10
|
-
|
11
|
+
KeepAliveOptions,
|
12
|
+
PeersByDiscoveryResult
|
11
13
|
} from "@waku/interfaces";
|
12
14
|
import { Libp2p, Tags } from "@waku/interfaces";
|
13
15
|
import debug from "debug";
|
14
16
|
|
15
|
-
import { KeepAliveManager
|
17
|
+
import { KeepAliveManager } from "./keep_alive_manager.js";
|
16
18
|
|
17
19
|
const log = debug("waku:connection-manager");
|
18
20
|
|
@@ -20,7 +22,10 @@ export const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
|
|
20
22
|
export const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
|
21
23
|
export const DEFAULT_MAX_PARALLEL_DIALS = 3;
|
22
24
|
|
23
|
-
export class ConnectionManager
|
25
|
+
export class ConnectionManager
|
26
|
+
extends EventEmitter<IPeersByDiscoveryEvents>
|
27
|
+
implements IConnectionManager
|
28
|
+
{
|
24
29
|
private static instances = new Map<string, ConnectionManager>();
|
25
30
|
private keepAliveManager: KeepAliveManager;
|
26
31
|
private options: ConnectionManagerOptions;
|
@@ -87,12 +92,12 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
|
|
87
92
|
return {
|
88
93
|
DISCOVERED: {
|
89
94
|
[Tags.BOOTSTRAP]: peersDiscoveredByBootstrap,
|
90
|
-
[Tags.PEER_EXCHANGE]: peersDiscoveredByPeerExchange
|
95
|
+
[Tags.PEER_EXCHANGE]: peersDiscoveredByPeerExchange
|
91
96
|
},
|
92
97
|
CONNECTED: {
|
93
98
|
[Tags.BOOTSTRAP]: peersConnectedByBootstrap,
|
94
|
-
[Tags.PEER_EXCHANGE]: peersConnectedByPeerExchange
|
95
|
-
}
|
99
|
+
[Tags.PEER_EXCHANGE]: peersConnectedByPeerExchange
|
100
|
+
}
|
96
101
|
};
|
97
102
|
}
|
98
103
|
|
@@ -108,7 +113,7 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
|
|
108
113
|
maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER,
|
109
114
|
maxBootstrapPeersAllowed: DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED,
|
110
115
|
maxParallelDials: DEFAULT_MAX_PARALLEL_DIALS,
|
111
|
-
...options
|
116
|
+
...options
|
112
117
|
};
|
113
118
|
|
114
119
|
this.keepAliveManager = new KeepAliveManager(keepAliveOptions, relay);
|
@@ -169,55 +174,71 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
|
|
169
174
|
private async dialPeer(peerId: PeerId): Promise<void> {
|
170
175
|
this.currentActiveDialCount += 1;
|
171
176
|
let dialAttempt = 0;
|
172
|
-
while (dialAttempt
|
177
|
+
while (dialAttempt < this.options.maxDialAttemptsForPeer) {
|
173
178
|
try {
|
174
|
-
log(`Dialing peer ${peerId.toString()}`);
|
179
|
+
log(`Dialing peer ${peerId.toString()} on attempt ${dialAttempt + 1}`);
|
175
180
|
await this.libp2p.dial(peerId);
|
176
181
|
|
177
182
|
const tags = await this.getTagNamesForPeer(peerId);
|
178
183
|
// add tag to connection describing discovery mechanism
|
179
184
|
// don't add duplicate tags
|
180
|
-
this.libp2p
|
181
|
-
.
|
182
|
-
|
183
|
-
(conn) => (conn.tags = Array.from(new Set([...conn.tags, ...tags])))
|
184
|
-
);
|
185
|
+
this.libp2p.getConnections(peerId).forEach((conn) => {
|
186
|
+
conn.tags = Array.from(new Set([...conn.tags, ...tags]));
|
187
|
+
});
|
185
188
|
|
186
189
|
this.dialAttemptsForPeer.delete(peerId.toString());
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
190
|
+
// Dialing succeeded, break the loop
|
191
|
+
break;
|
192
|
+
} catch (error) {
|
193
|
+
if (error instanceof AggregateError) {
|
194
|
+
// Handle AggregateError
|
195
|
+
log(`Error dialing peer ${peerId.toString()} - ${error.errors}`);
|
196
|
+
} else {
|
197
|
+
// Handle generic error
|
198
|
+
log(
|
199
|
+
`Error dialing peer ${peerId.toString()} - ${
|
200
|
+
(error as any).message
|
201
|
+
}`
|
202
|
+
);
|
203
|
+
}
|
191
204
|
this.dialErrorsForPeer.set(peerId.toString(), error);
|
192
|
-
log(`Error dialing peer ${peerId.toString()} - ${error.errors}`);
|
193
|
-
|
194
|
-
dialAttempt = this.dialAttemptsForPeer.get(peerId.toString()) ?? 1;
|
195
|
-
this.dialAttemptsForPeer.set(peerId.toString(), dialAttempt + 1);
|
196
205
|
|
197
|
-
|
198
|
-
|
199
|
-
}
|
206
|
+
dialAttempt++;
|
207
|
+
this.dialAttemptsForPeer.set(peerId.toString(), dialAttempt);
|
200
208
|
}
|
201
209
|
}
|
202
210
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
211
|
+
// Always decrease the active dial count and process the dial queue
|
212
|
+
this.currentActiveDialCount--;
|
213
|
+
this.processDialQueue();
|
214
|
+
|
215
|
+
// If max dial attempts reached and dialing failed, delete the peer
|
216
|
+
if (dialAttempt === this.options.maxDialAttemptsForPeer) {
|
217
|
+
try {
|
218
|
+
const error = this.dialErrorsForPeer.get(peerId.toString());
|
219
|
+
|
220
|
+
let errorMessage;
|
221
|
+
if (error instanceof AggregateError) {
|
222
|
+
errorMessage = JSON.stringify(error.errors[0]);
|
223
|
+
} else {
|
224
|
+
errorMessage = error.message;
|
225
|
+
}
|
226
|
+
|
227
|
+
log(
|
228
|
+
`Deleting undialable peer ${peerId.toString()} from peer store. Error: ${errorMessage}`
|
229
|
+
);
|
230
|
+
|
231
|
+
this.dialErrorsForPeer.delete(peerId.toString());
|
232
|
+
await this.libp2p.peerStore.delete(peerId);
|
233
|
+
} catch (error) {
|
234
|
+
throw new Error(
|
235
|
+
`Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`
|
236
|
+
);
|
237
|
+
}
|
217
238
|
}
|
218
239
|
}
|
219
240
|
|
220
|
-
async dropConnection(peerId: PeerId): Promise<void> {
|
241
|
+
private async dropConnection(peerId: PeerId): Promise<void> {
|
221
242
|
try {
|
222
243
|
this.keepAliveManager.stop(peerId);
|
223
244
|
await this.libp2p.hangUp(peerId);
|
@@ -297,25 +318,16 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
|
|
297
318
|
Tags.BOOTSTRAP
|
298
319
|
);
|
299
320
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
)
|
309
|
-
|
310
|
-
this.dispatchEvent(
|
311
|
-
new CustomEvent<PeerId>(
|
312
|
-
EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE,
|
313
|
-
{
|
314
|
-
detail: peerId,
|
315
|
-
}
|
316
|
-
)
|
317
|
-
);
|
318
|
-
}
|
321
|
+
this.dispatchEvent(
|
322
|
+
new CustomEvent<PeerId>(
|
323
|
+
isBootstrap
|
324
|
+
? EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP
|
325
|
+
: EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE,
|
326
|
+
{
|
327
|
+
detail: peerId
|
328
|
+
}
|
329
|
+
)
|
330
|
+
);
|
319
331
|
|
320
332
|
try {
|
321
333
|
await this.attemptDial(peerId);
|
@@ -328,7 +340,11 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
|
|
328
340
|
void (async () => {
|
329
341
|
const peerId = evt.detail;
|
330
342
|
|
331
|
-
this.keepAliveManager.start(
|
343
|
+
this.keepAliveManager.start(
|
344
|
+
peerId,
|
345
|
+
this.libp2p.services.ping,
|
346
|
+
this.libp2p.peerStore
|
347
|
+
);
|
332
348
|
|
333
349
|
const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(
|
334
350
|
Tags.BOOTSTRAP
|
@@ -349,7 +365,7 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
|
|
349
365
|
new CustomEvent<PeerId>(
|
350
366
|
EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP,
|
351
367
|
{
|
352
|
-
detail: peerId
|
368
|
+
detail: peerId
|
353
369
|
}
|
354
370
|
)
|
355
371
|
);
|
@@ -359,7 +375,7 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
|
|
359
375
|
new CustomEvent<PeerId>(
|
360
376
|
EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE,
|
361
377
|
{
|
362
|
-
detail: peerId
|
378
|
+
detail: peerId
|
363
379
|
}
|
364
380
|
)
|
365
381
|
);
|
@@ -370,7 +386,7 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
|
|
370
386
|
return (evt: CustomEvent<PeerId>): void => {
|
371
387
|
this.keepAliveManager.stop(evt.detail);
|
372
388
|
};
|
373
|
-
}
|
389
|
+
}
|
374
390
|
};
|
375
391
|
|
376
392
|
/**
|
@@ -42,7 +42,7 @@ export class FilterSubscribeRpc {
|
|
42
42
|
filterSubscribeType:
|
43
43
|
proto.FilterSubscribeRequest.FilterSubscribeType.SUBSCRIBE,
|
44
44
|
pubsubTopic,
|
45
|
-
contentTopics
|
45
|
+
contentTopics
|
46
46
|
});
|
47
47
|
}
|
48
48
|
|
@@ -55,7 +55,7 @@ export class FilterSubscribeRpc {
|
|
55
55
|
filterSubscribeType:
|
56
56
|
proto.FilterSubscribeRequest.FilterSubscribeType.UNSUBSCRIBE,
|
57
57
|
pubsubTopic,
|
58
|
-
contentTopics
|
58
|
+
contentTopics
|
59
59
|
});
|
60
60
|
}
|
61
61
|
|
@@ -65,7 +65,7 @@ export class FilterSubscribeRpc {
|
|
65
65
|
filterSubscribeType:
|
66
66
|
proto.FilterSubscribeRequest.FilterSubscribeType.UNSUBSCRIBE_ALL,
|
67
67
|
pubsubTopic,
|
68
|
-
contentTopics: []
|
68
|
+
contentTopics: []
|
69
69
|
});
|
70
70
|
}
|
71
71
|
|
@@ -75,7 +75,7 @@ export class FilterSubscribeRpc {
|
|
75
75
|
filterSubscribeType:
|
76
76
|
proto.FilterSubscribeRequest.FilterSubscribeType.SUBSCRIBER_PING,
|
77
77
|
pubsubTopic: "",
|
78
|
-
contentTopics: []
|
78
|
+
contentTopics: []
|
79
79
|
});
|
80
80
|
}
|
81
81
|
|
package/src/lib/filter/index.ts
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
import { Stream } from "@libp2p/interface
|
2
|
-
import type {
|
3
|
-
import type {
|
4
|
-
import type { IncomingStreamData } from "@libp2p/interface-registrar";
|
1
|
+
import { Stream } from "@libp2p/interface/connection";
|
2
|
+
import type { Peer } from "@libp2p/interface/peer-store";
|
3
|
+
import type { IncomingStreamData } from "@libp2p/interface-internal/registrar";
|
5
4
|
import type {
|
6
5
|
Callback,
|
7
6
|
ContentTopic,
|
@@ -14,9 +13,8 @@ import type {
|
|
14
13
|
Libp2p,
|
15
14
|
PeerIdStr,
|
16
15
|
ProtocolCreateOptions,
|
17
|
-
ProtocolOptions,
|
18
16
|
PubSubTopic,
|
19
|
-
Unsubscribe
|
17
|
+
Unsubscribe
|
20
18
|
} from "@waku/interfaces";
|
21
19
|
import { WakuMessage } from "@waku/proto";
|
22
20
|
import { groupByContentTopic, toAsyncIterator } from "@waku/utils";
|
@@ -31,7 +29,7 @@ import { DefaultPubSubTopic } from "../constants.js";
|
|
31
29
|
import {
|
32
30
|
FilterPushRpc,
|
33
31
|
FilterSubscribeResponse,
|
34
|
-
FilterSubscribeRpc
|
32
|
+
FilterSubscribeRpc
|
35
33
|
} from "./filter_rpc.js";
|
36
34
|
|
37
35
|
const log = debug("waku:filter:v2");
|
@@ -41,9 +39,9 @@ type SubscriptionCallback<T extends IDecodedMessage> = {
|
|
41
39
|
callback: Callback<T>;
|
42
40
|
};
|
43
41
|
|
44
|
-
const FilterCodecs = {
|
42
|
+
export const FilterCodecs = {
|
45
43
|
SUBSCRIBE: "/vac/waku/filter-subscribe/2.0.0-beta1",
|
46
|
-
PUSH: "/vac/waku/filter-push/2.0.0-beta1"
|
44
|
+
PUSH: "/vac/waku/filter-push/2.0.0-beta1"
|
47
45
|
};
|
48
46
|
|
49
47
|
class Subscription {
|
@@ -125,7 +123,7 @@ class Subscription {
|
|
125
123
|
// Decoder that decode to different implementations of `IDecodedMessage`
|
126
124
|
const subscriptionCallback = {
|
127
125
|
decoders,
|
128
|
-
callback
|
126
|
+
callback
|
129
127
|
} as unknown as SubscriptionCallback<IDecodedMessage>;
|
130
128
|
|
131
129
|
// The callback and decoder may override previous values, this is on
|
@@ -228,6 +226,7 @@ class Subscription {
|
|
228
226
|
class Filter extends BaseProtocol implements IReceiver {
|
229
227
|
private readonly options: ProtocolCreateOptions;
|
230
228
|
private activeSubscriptions = new Map<string, Subscription>();
|
229
|
+
private readonly NUM_PEERS_PROTOCOL = 1;
|
231
230
|
|
232
231
|
private getActiveSubscription(
|
233
232
|
pubSubTopic: PubSubTopic,
|
@@ -257,31 +256,32 @@ class Filter extends BaseProtocol implements IReceiver {
|
|
257
256
|
this.options = options ?? {};
|
258
257
|
}
|
259
258
|
|
260
|
-
async createSubscription(
|
261
|
-
pubSubTopic?: string,
|
262
|
-
peerId?: PeerId
|
263
|
-
): Promise<Subscription> {
|
259
|
+
async createSubscription(pubSubTopic?: string): Promise<Subscription> {
|
264
260
|
const _pubSubTopic =
|
265
261
|
pubSubTopic ?? this.options.pubSubTopic ?? DefaultPubSubTopic;
|
266
262
|
|
267
|
-
const peer =
|
263
|
+
const peer = (
|
264
|
+
await this.getPeers({
|
265
|
+
maxBootstrapPeers: 1,
|
266
|
+
numPeers: this.NUM_PEERS_PROTOCOL
|
267
|
+
})
|
268
|
+
)[0];
|
268
269
|
|
269
270
|
const subscription =
|
270
271
|
this.getActiveSubscription(_pubSubTopic, peer.id.toString()) ??
|
271
272
|
this.setActiveSubscription(
|
272
273
|
_pubSubTopic,
|
273
274
|
peer.id.toString(),
|
274
|
-
new Subscription(_pubSubTopic, peer, this.
|
275
|
+
new Subscription(_pubSubTopic, peer, this.getStream.bind(this, peer))
|
275
276
|
);
|
276
277
|
|
277
278
|
return subscription;
|
278
279
|
}
|
279
280
|
|
280
281
|
public toSubscriptionIterator<T extends IDecodedMessage>(
|
281
|
-
decoders: IDecoder<T> | IDecoder<T>[]
|
282
|
-
opts?: ProtocolOptions | undefined
|
282
|
+
decoders: IDecoder<T> | IDecoder<T>[]
|
283
283
|
): Promise<IAsyncIterator<T>> {
|
284
|
-
return toAsyncIterator(this, decoders
|
284
|
+
return toAsyncIterator(this, decoders);
|
285
285
|
}
|
286
286
|
|
287
287
|
/**
|
@@ -301,10 +301,9 @@ class Filter extends BaseProtocol implements IReceiver {
|
|
301
301
|
*/
|
302
302
|
async subscribe<T extends IDecodedMessage>(
|
303
303
|
decoders: IDecoder<T> | IDecoder<T>[],
|
304
|
-
callback: Callback<T
|
305
|
-
opts?: ProtocolOptions
|
304
|
+
callback: Callback<T>
|
306
305
|
): Promise<Unsubscribe> {
|
307
|
-
const subscription = await this.createSubscription(
|
306
|
+
const subscription = await this.createSubscription();
|
308
307
|
|
309
308
|
await subscription.subscribe(decoders, callback);
|
310
309
|
|
@@ -384,23 +383,17 @@ async function pushMessage<T extends IDecodedMessage>(
|
|
384
383
|
return;
|
385
384
|
}
|
386
385
|
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
if (didDecodeMsg) break;
|
393
|
-
const decoded = await dec.fromProtoObj(
|
394
|
-
pubSubTopic,
|
395
|
-
message as IProtoMessage
|
386
|
+
try {
|
387
|
+
const decodePromises = decoders.map((dec) =>
|
388
|
+
dec
|
389
|
+
.fromProtoObj(pubSubTopic, message as IProtoMessage)
|
390
|
+
.then((decoded) => decoded || Promise.reject("Decoding failed"))
|
396
391
|
);
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
didDecodeMsg = Boolean(decoded);
|
404
|
-
await callback(decoded);
|
392
|
+
|
393
|
+
const decodedMessage = await Promise.any(decodePromises);
|
394
|
+
|
395
|
+
await callback(decodedMessage);
|
396
|
+
} catch (e) {
|
397
|
+
log("Error decoding message", e);
|
405
398
|
}
|
406
399
|
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { Peer } from "@libp2p/interface/peer-store";
|
2
|
+
import { Tags } from "@waku/interfaces";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Retrieves a list of peers based on the specified criteria.
|
6
|
+
*
|
7
|
+
* @param peers - The list of peers to filter from.
|
8
|
+
* @param numPeers - The total number of peers to retrieve. If 0, all peers are returned.
|
9
|
+
* @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
|
10
|
+
* @returns A Promise that resolves to an array of peers based on the specified criteria.
|
11
|
+
*/
|
12
|
+
export async function filterPeers(
|
13
|
+
peers: Peer[],
|
14
|
+
numPeers: number,
|
15
|
+
maxBootstrapPeers: number
|
16
|
+
): Promise<Peer[]> {
|
17
|
+
// Collect the bootstrap peers up to the specified maximum
|
18
|
+
const bootstrapPeers = peers
|
19
|
+
.filter((peer) => peer.tags.has(Tags.BOOTSTRAP))
|
20
|
+
.slice(0, maxBootstrapPeers);
|
21
|
+
|
22
|
+
// Collect non-bootstrap peers
|
23
|
+
const nonBootstrapPeers = peers.filter(
|
24
|
+
(peer) => !peer.tags.has(Tags.BOOTSTRAP)
|
25
|
+
);
|
26
|
+
|
27
|
+
// If numPeers is 0, return all peers
|
28
|
+
if (numPeers === 0) {
|
29
|
+
return [...bootstrapPeers, ...nonBootstrapPeers];
|
30
|
+
}
|
31
|
+
|
32
|
+
// Initialize the list of selected peers with the bootstrap peers
|
33
|
+
const selectedPeers: Peer[] = [...bootstrapPeers];
|
34
|
+
|
35
|
+
// Fill up to numPeers with remaining random peers if needed
|
36
|
+
while (selectedPeers.length < numPeers && nonBootstrapPeers.length > 0) {
|
37
|
+
const randomIndex = Math.floor(Math.random() * nonBootstrapPeers.length);
|
38
|
+
const randomPeer = nonBootstrapPeers.splice(randomIndex, 1)[0];
|
39
|
+
selectedPeers.push(randomPeer);
|
40
|
+
}
|
41
|
+
|
42
|
+
return selectedPeers;
|
43
|
+
}
|
@@ -1,18 +1,16 @@
|
|
1
|
-
import type { PeerId } from "@libp2p/interface
|
1
|
+
import type { PeerId } from "@libp2p/interface/peer-id";
|
2
|
+
import type { PeerStore } from "@libp2p/interface/peer-store";
|
2
3
|
import type { IRelay } from "@waku/interfaces";
|
4
|
+
import type { KeepAliveOptions } from "@waku/interfaces";
|
5
|
+
import { utf8ToBytes } from "@waku/utils/bytes";
|
3
6
|
import debug from "debug";
|
4
7
|
import type { PingService } from "libp2p/ping";
|
5
8
|
|
6
|
-
import { createEncoder } from "
|
9
|
+
import { createEncoder } from "./message/version_0.js";
|
7
10
|
|
8
11
|
export const RelayPingContentTopic = "/relay-ping/1/ping/null";
|
9
12
|
const log = debug("waku:keep-alive");
|
10
13
|
|
11
|
-
export interface KeepAliveOptions {
|
12
|
-
pingKeepAlive: number;
|
13
|
-
relayKeepAlive: number;
|
14
|
-
}
|
15
|
-
|
16
14
|
export class KeepAliveManager {
|
17
15
|
private pingKeepAliveTimers: Map<string, ReturnType<typeof setInterval>>;
|
18
16
|
private relayKeepAliveTimers: Map<PeerId, ReturnType<typeof setInterval>>;
|
@@ -26,8 +24,12 @@ export class KeepAliveManager {
|
|
26
24
|
this.relay = relay;
|
27
25
|
}
|
28
26
|
|
29
|
-
public start(
|
30
|
-
|
27
|
+
public start(
|
28
|
+
peerId: PeerId,
|
29
|
+
libp2pPing: PingService,
|
30
|
+
peerStore: PeerStore
|
31
|
+
): void {
|
32
|
+
// Just in case a timer already exists for this peer
|
31
33
|
this.stop(peerId);
|
32
34
|
|
33
35
|
const { pingKeepAlive: pingPeriodSecs, relayKeepAlive: relayPeriodSecs } =
|
@@ -37,10 +39,28 @@ export class KeepAliveManager {
|
|
37
39
|
|
38
40
|
if (pingPeriodSecs !== 0) {
|
39
41
|
const interval = setInterval(() => {
|
40
|
-
|
41
|
-
|
42
|
-
|
42
|
+
void (async () => {
|
43
|
+
try {
|
44
|
+
// ping the peer for keep alive
|
45
|
+
// also update the peer store with the latency
|
46
|
+
const ping = await libp2pPing.ping(peerId);
|
47
|
+
log(`Ping succeeded (${peerIdStr})`, ping);
|
48
|
+
|
49
|
+
try {
|
50
|
+
await peerStore.patch(peerId, {
|
51
|
+
metadata: {
|
52
|
+
ping: utf8ToBytes(ping.toString())
|
53
|
+
}
|
54
|
+
});
|
55
|
+
} catch (e) {
|
56
|
+
log("Failed to update ping", e);
|
57
|
+
}
|
58
|
+
} catch (e) {
|
59
|
+
log(`Ping failed (${peerIdStr})`, e);
|
60
|
+
}
|
61
|
+
})();
|
43
62
|
}, pingPeriodSecs * 1000);
|
63
|
+
|
44
64
|
this.pingKeepAliveTimers.set(peerIdStr, interval);
|
45
65
|
}
|
46
66
|
|
@@ -48,7 +68,7 @@ export class KeepAliveManager {
|
|
48
68
|
if (relay && relayPeriodSecs !== 0) {
|
49
69
|
const encoder = createEncoder({
|
50
70
|
contentTopic: RelayPingContentTopic,
|
51
|
-
ephemeral: true
|
71
|
+
ephemeral: true
|
52
72
|
});
|
53
73
|
const interval = setInterval(() => {
|
54
74
|
log("Sending Waku Relay ping message");
|
@@ -77,7 +97,7 @@ export class KeepAliveManager {
|
|
77
97
|
public stopAll(): void {
|
78
98
|
for (const timer of [
|
79
99
|
...Object.values(this.pingKeepAliveTimers),
|
80
|
-
...Object.values(this.relayKeepAliveTimers)
|
100
|
+
...Object.values(this.relayKeepAliveTimers)
|
81
101
|
]) {
|
82
102
|
clearInterval(timer);
|
83
103
|
}
|