2022-02-04 03:12:00 +00:00
|
|
|
import { bytes } from "@chainsafe/libp2p-noise/dist/src/@types/basic";
|
|
|
|
import { Noise } from "@chainsafe/libp2p-noise/dist/src/noise";
|
|
|
|
import debug from "debug";
|
|
|
|
import Libp2p, { Connection, Libp2pModules, Libp2pOptions } from "libp2p";
|
|
|
|
import Libp2pBootstrap from "libp2p-bootstrap";
|
|
|
|
import { MuxedStream } from "libp2p-interfaces/dist/src/stream-muxer/types";
|
2021-07-14 02:25:23 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
// @ts-ignore: No types available
|
2022-02-04 03:12:00 +00:00
|
|
|
import Mplex from "libp2p-mplex";
|
2021-07-14 02:25:23 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
// @ts-ignore: No types available
|
2022-02-04 03:12:00 +00:00
|
|
|
import Websockets from "libp2p-websockets";
|
2021-07-14 02:25:23 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
// @ts-ignore: No types available
|
2022-02-04 03:12:00 +00:00
|
|
|
import filters from "libp2p-websockets/src/filters";
|
|
|
|
import PingService from "libp2p/src/ping";
|
|
|
|
import { Multiaddr, multiaddr } from "multiaddr";
|
|
|
|
import PeerId from "peer-id";
|
|
|
|
|
|
|
|
import { Bootstrap, BootstrapOptions } from "./discovery";
|
|
|
|
import { LightPushCodec, WakuLightPush } from "./waku_light_push";
|
|
|
|
import { DecryptionMethod, WakuMessage } from "./waku_message";
|
|
|
|
import { RelayCodecs, WakuRelay } from "./waku_relay";
|
|
|
|
import { RelayPingContentTopic } from "./waku_relay/constants";
|
|
|
|
import { StoreCodec, WakuStore } from "./waku_store";
|
2021-03-19 03:40:16 +00:00
|
|
|
|
2021-06-08 12:01:48 +00:00
|
|
|
const websocketsTransportKey = Websockets.prototype[Symbol.toStringTag];
|
2021-04-22 00:39:05 +00:00
|
|
|
|
2021-08-11 00:34:42 +00:00
|
|
|
export const DefaultPingKeepAliveValueSecs = 0;
|
|
|
|
export const DefaultRelayKeepAliveValueSecs = 5 * 60;
|
2021-07-27 05:55:11 +00:00
|
|
|
|
2021-08-19 04:12:24 +00:00
|
|
|
/**
|
|
|
|
* DefaultPubSubTopic is the default gossipsub topic to use for Waku.
|
|
|
|
*/
|
2022-02-04 03:12:00 +00:00
|
|
|
export const DefaultPubSubTopic = "/waku/2/default-waku/proto";
|
2021-08-19 04:12:24 +00:00
|
|
|
|
2022-02-04 03:12:00 +00:00
|
|
|
const dbg = debug("waku:waku");
|
2021-08-10 01:32:14 +00:00
|
|
|
|
2022-01-30 10:56:21 +00:00
|
|
|
export enum Protocols {
|
2022-02-04 03:12:00 +00:00
|
|
|
Relay = "relay",
|
|
|
|
Store = "store",
|
|
|
|
LightPush = "lightpush",
|
2022-01-30 10:56:21 +00:00
|
|
|
}
|
|
|
|
|
2021-06-08 12:01:48 +00:00
|
|
|
export interface CreateOptions {
|
2021-06-09 02:25:56 +00:00
|
|
|
/**
|
2021-08-19 04:12:24 +00:00
|
|
|
* The PubSub Topic to use. Defaults to {@link DefaultPubSubTopic}.
|
2021-06-09 02:25:56 +00:00
|
|
|
*
|
|
|
|
* One and only one pubsub topic is used by Waku. This is used by:
|
|
|
|
* - WakuRelay to receive, route and send messages,
|
|
|
|
* - WakuLightPush to send messages,
|
|
|
|
* - WakuStore to retrieve messages.
|
|
|
|
*
|
|
|
|
* The usage of the default pubsub topic is recommended.
|
|
|
|
* See [Waku v2 Topic Usage Recommendations](https://rfc.vac.dev/spec/23/) for details.
|
|
|
|
*
|
2021-08-19 04:12:24 +00:00
|
|
|
* @default {@link DefaultPubSubTopic}
|
2021-06-09 02:25:56 +00:00
|
|
|
*/
|
2021-08-20 00:12:19 +00:00
|
|
|
pubSubTopic?: string;
|
2021-06-18 06:48:16 +00:00
|
|
|
/**
|
2021-07-22 06:34:27 +00:00
|
|
|
* Set keep alive frequency in seconds: Waku will send a `/ipfs/ping/1.0.0`
|
|
|
|
* request to each peer after the set number of seconds. Set to 0 to disable.
|
2021-06-18 06:48:16 +00:00
|
|
|
*
|
2021-07-27 05:55:11 +00:00
|
|
|
* @default {@link DefaultPingKeepAliveValueSecs}
|
2021-06-18 06:48:16 +00:00
|
|
|
*/
|
2021-07-22 06:34:27 +00:00
|
|
|
pingKeepAlive?: number;
|
2021-07-27 05:55:11 +00:00
|
|
|
/**
|
|
|
|
* Set keep alive frequency in seconds: Waku will send a ping message over
|
|
|
|
* relay to each peer after the set number of seconds. Set to 0 to disable.
|
|
|
|
*
|
|
|
|
* @default {@link DefaultRelayKeepAliveValueSecs}
|
|
|
|
*/
|
|
|
|
relayKeepAlive?: number;
|
2021-06-08 12:01:48 +00:00
|
|
|
/**
|
|
|
|
* You can pass options to the `Libp2p` instance used by {@link Waku} using the {@link CreateOptions.libp2p} property.
|
|
|
|
* This property is the same type than the one passed to [`Libp2p.create`](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#create)
|
|
|
|
* apart that we made the `modules` property optional and partial,
|
|
|
|
* allowing its omission and letting Waku set good defaults.
|
|
|
|
* Notes that some values are overridden by {@link Waku} to ensure it implements the Waku protocol.
|
|
|
|
*/
|
2022-02-04 03:12:00 +00:00
|
|
|
libp2p?: Omit<Libp2pOptions & import("libp2p").CreateOptions, "modules"> & {
|
2021-06-08 12:01:48 +00:00
|
|
|
modules?: Partial<Libp2pModules>;
|
|
|
|
};
|
|
|
|
/**
|
|
|
|
* Byte array used as key for the noise protocol used for connection encryption
|
|
|
|
* by [`Libp2p.create`](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#create)
|
|
|
|
* This is only used for test purposes to not run out of entropy during CI runs.
|
|
|
|
*/
|
|
|
|
staticNoiseKey?: bytes;
|
2021-08-10 01:32:14 +00:00
|
|
|
/**
|
|
|
|
* Use libp2p-bootstrap to discover and connect to new nodes.
|
|
|
|
*
|
2022-01-13 03:28:45 +00:00
|
|
|
* See [[BootstrapOptions]] for available parameters.
|
2021-08-10 01:32:14 +00:00
|
|
|
*
|
|
|
|
* Note: It overrides any other peerDiscovery modules that may have been set via
|
|
|
|
* {@link CreateOptions.libp2p}.
|
|
|
|
*/
|
2022-01-13 03:28:45 +00:00
|
|
|
bootstrap?: BootstrapOptions;
|
2021-09-01 05:02:28 +00:00
|
|
|
decryptionKeys?: Array<Uint8Array | string>;
|
2021-06-08 12:01:48 +00:00
|
|
|
}
|
2021-03-29 02:56:17 +00:00
|
|
|
|
2021-05-10 05:26:14 +00:00
|
|
|
export class Waku {
|
2021-04-16 01:25:08 +00:00
|
|
|
public libp2p: Libp2p;
|
|
|
|
public relay: WakuRelay;
|
|
|
|
public store: WakuStore;
|
2021-05-19 01:00:43 +00:00
|
|
|
public lightPush: WakuLightPush;
|
2021-04-16 01:25:08 +00:00
|
|
|
|
2021-07-22 06:34:27 +00:00
|
|
|
private pingKeepAliveTimers: {
|
2021-06-18 06:48:16 +00:00
|
|
|
[peer: string]: ReturnType<typeof setInterval>;
|
|
|
|
};
|
2021-07-27 05:55:11 +00:00
|
|
|
private relayKeepAliveTimers: {
|
|
|
|
[peer: string]: ReturnType<typeof setInterval>;
|
|
|
|
};
|
2021-06-18 06:48:16 +00:00
|
|
|
|
2021-05-19 01:00:43 +00:00
|
|
|
private constructor(
|
2021-06-18 06:48:16 +00:00
|
|
|
options: CreateOptions,
|
2021-05-19 01:00:43 +00:00
|
|
|
libp2p: Libp2p,
|
|
|
|
store: WakuStore,
|
|
|
|
lightPush: WakuLightPush
|
|
|
|
) {
|
2021-04-16 01:25:08 +00:00
|
|
|
this.libp2p = libp2p;
|
2021-06-21 06:37:31 +00:00
|
|
|
this.relay = libp2p.pubsub as unknown as WakuRelay;
|
2021-04-16 01:25:08 +00:00
|
|
|
this.store = store;
|
2021-05-19 01:00:43 +00:00
|
|
|
this.lightPush = lightPush;
|
2021-07-22 06:34:27 +00:00
|
|
|
this.pingKeepAliveTimers = {};
|
2021-07-27 05:55:11 +00:00
|
|
|
this.relayKeepAliveTimers = {};
|
2021-06-18 06:48:16 +00:00
|
|
|
|
2021-07-27 05:55:11 +00:00
|
|
|
const pingKeepAlive =
|
|
|
|
options.pingKeepAlive || DefaultPingKeepAliveValueSecs;
|
|
|
|
const relayKeepAlive =
|
|
|
|
options.relayKeepAlive || DefaultRelayKeepAliveValueSecs;
|
2021-06-18 06:48:16 +00:00
|
|
|
|
2022-02-04 03:12:00 +00:00
|
|
|
libp2p.connectionManager.on("peer:connect", (connection: Connection) => {
|
2021-07-27 05:55:11 +00:00
|
|
|
this.startKeepAlive(connection.remotePeer, pingKeepAlive, relayKeepAlive);
|
|
|
|
});
|
2021-06-18 06:48:16 +00:00
|
|
|
|
2022-02-04 03:12:00 +00:00
|
|
|
libp2p.connectionManager.on("peer:disconnect", (connection: Connection) => {
|
2021-07-27 05:55:11 +00:00
|
|
|
this.stopKeepAlive(connection.remotePeer);
|
|
|
|
});
|
2021-09-01 05:02:28 +00:00
|
|
|
|
2022-01-17 03:11:05 +00:00
|
|
|
options?.decryptionKeys?.forEach((key) => {
|
|
|
|
this.addDecryptionKey(key);
|
|
|
|
});
|
2021-04-16 01:25:08 +00:00
|
|
|
}
|
2021-03-19 03:40:16 +00:00
|
|
|
|
2021-03-22 11:16:12 +00:00
|
|
|
/**
|
|
|
|
* Create new waku node
|
2021-05-13 01:49:20 +00:00
|
|
|
*
|
|
|
|
* @param options Takes the same options than `Libp2p`.
|
2021-03-22 11:16:12 +00:00
|
|
|
*/
|
2021-06-08 12:01:48 +00:00
|
|
|
static async create(options?: CreateOptions): Promise<Waku> {
|
|
|
|
// Get an object in case options or libp2p are undefined
|
|
|
|
const libp2pOpts = Object.assign({}, options?.libp2p);
|
2021-03-29 02:56:17 +00:00
|
|
|
|
2021-06-08 12:01:48 +00:00
|
|
|
// Default for Websocket filter is `all`:
|
|
|
|
// Returns all TCP and DNS based addresses, both with ws or wss.
|
|
|
|
libp2pOpts.config = Object.assign(
|
2021-04-22 04:47:43 +00:00
|
|
|
{
|
|
|
|
transport: {
|
2021-06-08 12:01:48 +00:00
|
|
|
[websocketsTransportKey]: {
|
2021-04-22 04:47:43 +00:00
|
|
|
filter: filters.all,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-06-08 12:01:48 +00:00
|
|
|
options?.libp2p?.config
|
2021-04-22 04:47:43 +00:00
|
|
|
);
|
|
|
|
|
2021-06-09 02:25:56 +00:00
|
|
|
// Pass pubsub topic to relay
|
2021-08-20 00:12:19 +00:00
|
|
|
if (options?.pubSubTopic) {
|
2021-06-09 02:25:56 +00:00
|
|
|
libp2pOpts.config.pubsub = Object.assign(
|
2021-08-20 00:12:19 +00:00
|
|
|
{ pubSubTopic: options.pubSubTopic },
|
2021-06-09 02:25:56 +00:00
|
|
|
libp2pOpts.config.pubsub
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-06-08 12:01:48 +00:00
|
|
|
libp2pOpts.modules = Object.assign({}, options?.libp2p?.modules);
|
2021-04-22 04:47:43 +00:00
|
|
|
|
2021-06-08 12:01:48 +00:00
|
|
|
// Default transport for libp2p is Websockets
|
|
|
|
libp2pOpts.modules = Object.assign(
|
|
|
|
{
|
|
|
|
transport: [Websockets],
|
2021-03-19 03:40:16 +00:00
|
|
|
},
|
2021-06-08 12:01:48 +00:00
|
|
|
options?.libp2p?.modules
|
|
|
|
);
|
|
|
|
|
|
|
|
// streamMuxer, connection encryption and pubsub are overridden
|
|
|
|
// as those are the only ones currently supported by Waku nodes.
|
|
|
|
libp2pOpts.modules = Object.assign(libp2pOpts.modules, {
|
|
|
|
streamMuxer: [Mplex],
|
|
|
|
connEncryption: [new Noise(options?.staticNoiseKey)],
|
|
|
|
pubsub: WakuRelay,
|
2021-03-19 03:40:16 +00:00
|
|
|
});
|
|
|
|
|
2021-08-10 01:32:14 +00:00
|
|
|
if (options?.bootstrap) {
|
2022-01-13 05:04:57 +00:00
|
|
|
const bootstrap = new Bootstrap(options?.bootstrap);
|
2021-08-10 01:32:14 +00:00
|
|
|
|
2022-01-13 05:04:57 +00:00
|
|
|
if (bootstrap.getBootstrapPeers !== undefined) {
|
2021-08-10 01:32:14 +00:00
|
|
|
try {
|
2022-01-13 05:04:57 +00:00
|
|
|
const list = await bootstrap.getBootstrapPeers();
|
2021-08-10 01:32:14 +00:00
|
|
|
|
2021-09-21 04:22:23 +00:00
|
|
|
// Note: this overrides any other peer discover
|
|
|
|
libp2pOpts.modules = Object.assign(libp2pOpts.modules, {
|
2022-01-13 05:03:07 +00:00
|
|
|
peerDiscovery: [Libp2pBootstrap],
|
2021-09-21 04:22:23 +00:00
|
|
|
});
|
|
|
|
|
2021-08-10 01:32:14 +00:00
|
|
|
libp2pOpts.config.peerDiscovery = {
|
2022-01-13 05:03:07 +00:00
|
|
|
[Libp2pBootstrap.tag]: {
|
2021-08-10 01:32:14 +00:00
|
|
|
list,
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
} catch (e) {
|
2022-02-04 03:12:00 +00:00
|
|
|
dbg("Failed to retrieve bootstrap nodes", e);
|
2021-08-10 01:32:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-08 12:01:48 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
// @ts-ignore: modules property is correctly set thanks to voodoo
|
|
|
|
const libp2p = await Libp2p.create(libp2pOpts);
|
|
|
|
|
2021-06-09 02:25:56 +00:00
|
|
|
const wakuStore = new WakuStore(libp2p, {
|
2021-08-20 00:12:19 +00:00
|
|
|
pubSubTopic: options?.pubSubTopic,
|
2021-06-09 02:25:56 +00:00
|
|
|
});
|
2021-05-19 01:00:43 +00:00
|
|
|
const wakuLightPush = new WakuLightPush(libp2p);
|
2021-04-07 01:04:30 +00:00
|
|
|
|
2021-03-19 03:40:16 +00:00
|
|
|
await libp2p.start();
|
|
|
|
|
2021-06-18 06:48:16 +00:00
|
|
|
return new Waku(options ? options : {}, libp2p, wakuStore, wakuLightPush);
|
2021-03-19 03:40:16 +00:00
|
|
|
}
|
2021-03-19 05:07:56 +00:00
|
|
|
|
2021-03-23 00:14:51 +00:00
|
|
|
/**
|
2021-04-07 01:04:30 +00:00
|
|
|
* Dials to the provided peer.
|
2021-05-13 01:47:03 +00:00
|
|
|
*
|
2021-03-23 00:14:51 +00:00
|
|
|
* @param peer The peer to dial
|
|
|
|
*/
|
2021-06-21 06:37:31 +00:00
|
|
|
async dial(peer: PeerId | Multiaddr | string): Promise<{
|
2021-07-14 01:38:59 +00:00
|
|
|
stream: MuxedStream;
|
2021-05-03 05:52:38 +00:00
|
|
|
protocol: string;
|
|
|
|
}> {
|
2021-07-21 05:15:11 +00:00
|
|
|
return this.libp2p.dialProtocol(peer, [StoreCodec].concat(RelayCodecs));
|
2021-03-23 00:14:51 +00:00
|
|
|
}
|
|
|
|
|
2021-05-13 01:47:03 +00:00
|
|
|
/**
|
|
|
|
* Add peer to address book, it will be auto-dialed in the background.
|
|
|
|
*/
|
|
|
|
addPeerToAddressBook(
|
|
|
|
peerId: PeerId | string,
|
|
|
|
multiaddrs: Multiaddr[] | string[]
|
|
|
|
): void {
|
|
|
|
let peer;
|
2022-02-04 03:12:00 +00:00
|
|
|
if (typeof peerId === "string") {
|
2021-05-13 01:47:03 +00:00
|
|
|
peer = PeerId.createFromB58String(peerId);
|
|
|
|
} else {
|
|
|
|
peer = peerId;
|
|
|
|
}
|
|
|
|
const addresses = multiaddrs.map((addr: Multiaddr | string) => {
|
2022-02-04 03:12:00 +00:00
|
|
|
if (typeof addr === "string") {
|
2021-05-13 01:47:03 +00:00
|
|
|
return multiaddr(addr);
|
|
|
|
} else {
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.libp2p.peerStore.addressBook.set(peer, addresses);
|
2021-03-23 00:14:51 +00:00
|
|
|
}
|
|
|
|
|
2021-05-03 05:52:38 +00:00
|
|
|
async stop(): Promise<void> {
|
|
|
|
return this.libp2p.stop();
|
2021-03-19 05:07:56 +00:00
|
|
|
}
|
2021-04-06 01:06:10 +00:00
|
|
|
|
2021-09-01 05:02:28 +00:00
|
|
|
/**
|
|
|
|
* Register a decryption key to attempt decryption of messages received via
|
|
|
|
* [[WakuRelay]] and [[WakuStore]]. This can either be a private key for
|
|
|
|
* asymmetric encryption or a symmetric key.
|
|
|
|
*
|
|
|
|
* Strings must be in hex format.
|
|
|
|
*/
|
2022-01-17 03:11:05 +00:00
|
|
|
addDecryptionKey(
|
|
|
|
key: Uint8Array | string,
|
|
|
|
options?: { method?: DecryptionMethod; contentTopics?: string[] }
|
|
|
|
): void {
|
|
|
|
this.relay.addDecryptionKey(key, options);
|
|
|
|
this.store.addDecryptionKey(key, options);
|
2021-09-01 05:02:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete a decryption key that was used to attempt decryption of messages
|
|
|
|
* received via [[WakuRelay]] or [[WakuStore]].
|
|
|
|
*
|
|
|
|
* Strings must be in hex format.
|
|
|
|
*/
|
|
|
|
deleteDecryptionKey(key: Uint8Array | string): void {
|
|
|
|
this.relay.deleteDecryptionKey(key);
|
|
|
|
this.store.deleteDecryptionKey(key);
|
|
|
|
}
|
|
|
|
|
2021-04-06 01:06:10 +00:00
|
|
|
/**
|
|
|
|
* Return the local multiaddr with peer id on which libp2p is listening.
|
|
|
|
* @throws if libp2p is not listening on localhost
|
|
|
|
*/
|
|
|
|
getLocalMultiaddrWithID(): string {
|
|
|
|
const localMultiaddr = this.libp2p.multiaddrs.find((addr) =>
|
|
|
|
addr.toString().match(/127\.0\.0\.1/)
|
|
|
|
);
|
2022-02-04 03:12:00 +00:00
|
|
|
if (!localMultiaddr || localMultiaddr.toString() === "") {
|
|
|
|
throw "Not listening on localhost";
|
2021-04-06 01:06:10 +00:00
|
|
|
}
|
2022-02-04 03:12:00 +00:00
|
|
|
return localMultiaddr + "/p2p/" + this.libp2p.peerId.toB58String();
|
2021-04-06 01:06:10 +00:00
|
|
|
}
|
2021-06-18 06:48:16 +00:00
|
|
|
|
2021-09-02 05:01:52 +00:00
|
|
|
/**
|
2022-01-30 10:56:21 +00:00
|
|
|
* Wait for a remote peer to be ready given the passed protocols.
|
|
|
|
* Useful when using the [[CreateOptions.bootstrap]] with [[Waku.create]].
|
|
|
|
*
|
|
|
|
* @default Remote peer must have Waku Store and Waku Relay enabled.
|
2021-09-02 05:01:52 +00:00
|
|
|
*/
|
2022-01-30 10:56:21 +00:00
|
|
|
async waitForRemotePeer(protocols?: Protocols[]): Promise<void> {
|
|
|
|
const desiredProtocols = protocols ?? [Protocols.Relay, Protocols.Store];
|
|
|
|
|
|
|
|
const promises = [];
|
|
|
|
|
|
|
|
if (desiredProtocols.includes(Protocols.Relay)) {
|
2022-01-30 23:30:25 +00:00
|
|
|
const peers = this.relay.getPeers();
|
2022-01-30 10:56:21 +00:00
|
|
|
|
2022-01-30 23:30:25 +00:00
|
|
|
if (peers.size == 0) {
|
|
|
|
// No peer yet available, wait for a subscription
|
|
|
|
const promise = new Promise<void>((resolve) => {
|
2022-02-04 03:12:00 +00:00
|
|
|
this.libp2p.pubsub.once("pubsub:subscription-change", () => {
|
2022-01-31 04:30:49 +00:00
|
|
|
// Remote peer subscribed to topic, now wait for a heartbeat
|
|
|
|
// so that the mesh is updated and the remote peer added to it
|
2022-02-04 03:12:00 +00:00
|
|
|
this.libp2p.pubsub.once("gossipsub:heartbeat", resolve);
|
2022-01-30 23:30:25 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
promises.push(promise);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (desiredProtocols.includes(Protocols.Store)) {
|
2022-02-02 04:12:08 +00:00
|
|
|
let storePeerFound = false;
|
2022-01-30 10:56:21 +00:00
|
|
|
|
2022-02-02 04:12:08 +00:00
|
|
|
for await (const _peer of this.store.peers) {
|
|
|
|
storePeerFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!storePeerFound) {
|
2022-01-30 10:56:21 +00:00
|
|
|
// No peer available for this protocol, waiting to connect to one.
|
|
|
|
const promise = new Promise<void>((resolve) => {
|
|
|
|
this.libp2p.peerStore.on(
|
2022-02-04 03:12:00 +00:00
|
|
|
"change:protocols",
|
2022-01-30 10:56:21 +00:00
|
|
|
({ protocols: connectedPeerProtocols }) => {
|
2022-01-30 23:30:25 +00:00
|
|
|
if (connectedPeerProtocols.includes(StoreCodec)) {
|
2022-02-04 03:12:00 +00:00
|
|
|
dbg("Resolving for", StoreCodec, connectedPeerProtocols);
|
2022-01-30 23:30:25 +00:00
|
|
|
resolve();
|
|
|
|
}
|
2022-01-30 10:56:21 +00:00
|
|
|
}
|
2021-09-02 05:01:52 +00:00
|
|
|
);
|
|
|
|
});
|
2022-01-30 10:56:21 +00:00
|
|
|
promises.push(promise);
|
|
|
|
}
|
2022-01-30 23:30:25 +00:00
|
|
|
}
|
2022-01-30 10:56:21 +00:00
|
|
|
|
2022-01-30 23:30:25 +00:00
|
|
|
if (desiredProtocols.includes(Protocols.LightPush)) {
|
2022-02-02 04:12:08 +00:00
|
|
|
let lightPushPeerFound = false;
|
2022-01-30 10:56:21 +00:00
|
|
|
|
2022-02-02 04:12:08 +00:00
|
|
|
for await (const _peer of this.lightPush.peers) {
|
|
|
|
lightPushPeerFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!lightPushPeerFound) {
|
2022-01-30 23:30:25 +00:00
|
|
|
// No peer available for this protocol, waiting to connect to one.
|
|
|
|
const promise = new Promise<void>((resolve) => {
|
|
|
|
this.libp2p.peerStore.on(
|
2022-02-04 03:12:00 +00:00
|
|
|
"change:protocols",
|
2022-01-30 23:30:25 +00:00
|
|
|
({ protocols: connectedPeerProtocols }) => {
|
|
|
|
if (connectedPeerProtocols.includes(LightPushCodec)) {
|
2022-02-04 03:12:00 +00:00
|
|
|
dbg("Resolving for", LightPushCodec, connectedPeerProtocols);
|
2022-01-30 23:30:25 +00:00
|
|
|
resolve();
|
2022-01-30 10:56:21 +00:00
|
|
|
}
|
2022-01-30 23:30:25 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2022-01-30 10:56:21 +00:00
|
|
|
|
2022-01-30 23:30:25 +00:00
|
|
|
promises.push(promise);
|
2022-01-30 10:56:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
await Promise.all(promises);
|
2021-09-02 05:01:52 +00:00
|
|
|
}
|
|
|
|
|
2021-07-27 05:55:11 +00:00
|
|
|
private startKeepAlive(
|
|
|
|
peerId: PeerId,
|
|
|
|
pingPeriodSecs: number,
|
|
|
|
relayPeriodSecs: number
|
|
|
|
): void {
|
2021-06-20 23:46:41 +00:00
|
|
|
// Just in case a timer already exist for this peer
|
2021-07-27 05:55:11 +00:00
|
|
|
this.stopKeepAlive(peerId);
|
2021-06-18 06:48:16 +00:00
|
|
|
|
|
|
|
const peerIdStr = peerId.toB58String();
|
2021-07-27 05:55:11 +00:00
|
|
|
|
|
|
|
if (pingPeriodSecs !== 0) {
|
2022-02-02 04:12:08 +00:00
|
|
|
const pingService = new PingService(this.libp2p);
|
2021-07-27 05:55:11 +00:00
|
|
|
this.pingKeepAliveTimers[peerIdStr] = setInterval(() => {
|
2022-02-02 04:12:08 +00:00
|
|
|
pingService.ping(peerId).catch((e) => {
|
|
|
|
dbg(`Ping failed (${peerIdStr})`, e);
|
|
|
|
});
|
2021-07-27 05:55:11 +00:00
|
|
|
}, pingPeriodSecs * 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (relayPeriodSecs !== 0) {
|
|
|
|
this.relayKeepAliveTimers[peerIdStr] = setInterval(() => {
|
2021-07-28 01:19:24 +00:00
|
|
|
WakuMessage.fromBytes(new Uint8Array(), RelayPingContentTopic).then(
|
|
|
|
(wakuMsg) => this.relay.send(wakuMsg)
|
|
|
|
);
|
2021-07-27 05:55:11 +00:00
|
|
|
}, relayPeriodSecs * 1000);
|
|
|
|
}
|
2021-06-18 06:48:16 +00:00
|
|
|
}
|
|
|
|
|
2021-07-27 05:55:11 +00:00
|
|
|
private stopKeepAlive(peerId: PeerId): void {
|
2021-06-18 06:48:16 +00:00
|
|
|
const peerIdStr = peerId.toB58String();
|
2021-07-27 05:55:11 +00:00
|
|
|
|
2021-07-22 06:34:27 +00:00
|
|
|
if (this.pingKeepAliveTimers[peerIdStr]) {
|
|
|
|
clearInterval(this.pingKeepAliveTimers[peerIdStr]);
|
|
|
|
delete this.pingKeepAliveTimers[peerIdStr];
|
2021-06-18 06:48:16 +00:00
|
|
|
}
|
2021-07-27 05:55:11 +00:00
|
|
|
|
|
|
|
if (this.relayKeepAliveTimers[peerIdStr]) {
|
|
|
|
clearInterval(this.relayKeepAliveTimers[peerIdStr]);
|
|
|
|
delete this.relayKeepAliveTimers[peerIdStr];
|
|
|
|
}
|
2021-06-18 06:48:16 +00:00
|
|
|
}
|
2021-03-19 03:40:16 +00:00
|
|
|
}
|