Merge pull request #243 from status-im/185-idle-stream-abort

This commit is contained in:
Franck Royer 2021-07-27 16:42:02 +10:00 committed by GitHub
commit b61e7311af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 25 deletions

View File

@ -35,6 +35,7 @@
"ihave", "ihave",
"ihaves", "ihaves",
"ineed", "ineed",
"ipfs",
"iwant", "iwant",
"jdev", "jdev",
"keccak", "keccak",

View File

@ -25,6 +25,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- **Breaking**: Renamed `WakuRelay.(add|delete)PrivateDecryptionKey` to `WakuRelay.(add|delete)DecryptionKey` to make it clearer that it accepts both symmetric keys and asymmetric private keys. - **Breaking**: Renamed `WakuRelay.(add|delete)PrivateDecryptionKey` to `WakuRelay.(add|delete)DecryptionKey` to make it clearer that it accepts both symmetric keys and asymmetric private keys.
- Upgrade libp2p to 0.32.0. - Upgrade libp2p to 0.32.0.
- **Breaking**: Rename `keepAlive` option to `pingKeepAlive`.
- Introduced new `relayKeepAlive` option on `Waku` with a default to 59s to send ping messages over relay to ensure the relay stream stays open.
This is a workaround until [js-libp2p#744](https://github.com/libp2p/js-libp2p/issues/744) is done as there are issues when TCP(?) timeouts and the stream gets closed
([#185](https://github.com/status-im/js-waku/issues/185), [js-libp2p#939](https://github.com/libp2p/js-libp2p/issues/939))
### Fixed ### Fixed
- Align `WakuMessage` readme example with actual code behaviour. - Align `WakuMessage` readme example with actual code behaviour.

View File

@ -16,11 +16,16 @@ import { Multiaddr, multiaddr } from 'multiaddr';
import PeerId from 'peer-id'; import PeerId from 'peer-id';
import { WakuLightPush } from './waku_light_push'; import { WakuLightPush } from './waku_light_push';
import { WakuMessage } from './waku_message';
import { RelayCodecs, WakuRelay } from './waku_relay'; import { RelayCodecs, WakuRelay } from './waku_relay';
import { RelayPingContentTopic } from './waku_relay/constants';
import { StoreCodec, WakuStore } from './waku_store'; import { StoreCodec, WakuStore } from './waku_store';
const websocketsTransportKey = Websockets.prototype[Symbol.toStringTag]; const websocketsTransportKey = Websockets.prototype[Symbol.toStringTag];
const DefaultPingKeepAliveValueSecs = 0;
const DefaultRelayKeepAliveValueSecs = 5 * 60;
export interface CreateOptions { export interface CreateOptions {
/** /**
* The PubSub Topic to use. Defaults to {@link DefaultPubsubTopic}. * The PubSub Topic to use. Defaults to {@link DefaultPubsubTopic}.
@ -37,12 +42,19 @@ export interface CreateOptions {
*/ */
pubsubTopic?: string; pubsubTopic?: string;
/** /**
* Set keep alive frequency in seconds: Waku will send a ping request to each peer * Set keep alive frequency in seconds: Waku will send a `/ipfs/ping/1.0.0`
* after the set number of seconds. Set to 0 to disable the keep alive feature * request to each peer after the set number of seconds. Set to 0 to disable.
* *
* @default 0 * @default {@link DefaultPingKeepAliveValueSecs}
*/ */
keepAlive?: number; pingKeepAlive?: number;
/**
* 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;
/** /**
* You can pass options to the `Libp2p` instance used by {@link Waku} using the {@link CreateOptions.libp2p} property. * 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) * 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)
@ -67,7 +79,10 @@ export class Waku {
public store: WakuStore; public store: WakuStore;
public lightPush: WakuLightPush; public lightPush: WakuLightPush;
private keepAliveTimers: { private pingKeepAliveTimers: {
[peer: string]: ReturnType<typeof setInterval>;
};
private relayKeepAliveTimers: {
[peer: string]: ReturnType<typeof setInterval>; [peer: string]: ReturnType<typeof setInterval>;
}; };
@ -81,22 +96,21 @@ export class Waku {
this.relay = libp2p.pubsub as unknown as WakuRelay; this.relay = libp2p.pubsub as unknown as WakuRelay;
this.store = store; this.store = store;
this.lightPush = lightPush; this.lightPush = lightPush;
this.keepAliveTimers = {}; this.pingKeepAliveTimers = {};
this.relayKeepAliveTimers = {};
const keepAlive = options.keepAlive || 0; const pingKeepAlive =
options.pingKeepAlive || DefaultPingKeepAliveValueSecs;
const relayKeepAlive =
options.relayKeepAlive || DefaultRelayKeepAliveValueSecs;
if (keepAlive !== 0) {
libp2p.connectionManager.on('peer:connect', (connection: Connection) => { libp2p.connectionManager.on('peer:connect', (connection: Connection) => {
this.startKeepAlive(connection.remotePeer, keepAlive); this.startKeepAlive(connection.remotePeer, pingKeepAlive, relayKeepAlive);
}); });
libp2p.connectionManager.on( libp2p.connectionManager.on('peer:disconnect', (connection: Connection) => {
'peer:disconnect',
(connection: Connection) => {
this.stopKeepAlive(connection.remotePeer); this.stopKeepAlive(connection.remotePeer);
} });
);
}
} }
/** /**
@ -214,21 +228,42 @@ export class Waku {
return localMultiaddr + '/p2p/' + this.libp2p.peerId.toB58String(); return localMultiaddr + '/p2p/' + this.libp2p.peerId.toB58String();
} }
private startKeepAlive(peerId: PeerId, periodSecs: number): void { private startKeepAlive(
peerId: PeerId,
pingPeriodSecs: number,
relayPeriodSecs: number
): void {
// Just in case a timer already exist for this peer // Just in case a timer already exist for this peer
this.stopKeepAlive(peerId); this.stopKeepAlive(peerId);
const peerIdStr = peerId.toB58String(); const peerIdStr = peerId.toB58String();
this.keepAliveTimers[peerIdStr] = setInterval(() => {
if (pingPeriodSecs !== 0) {
this.pingKeepAliveTimers[peerIdStr] = setInterval(() => {
Ping(this.libp2p, peerId); Ping(this.libp2p, peerId);
}, periodSecs * 1000); }, pingPeriodSecs * 1000);
}
if (relayPeriodSecs !== 0) {
this.relayKeepAliveTimers[peerIdStr] = setInterval(() => {
WakuMessage.fromBytes(new Uint8Array(), {
contentTopic: RelayPingContentTopic,
}).then((wakuMsg) => this.relay.send(wakuMsg));
}, relayPeriodSecs * 1000);
}
} }
private stopKeepAlive(peerId: PeerId): void { private stopKeepAlive(peerId: PeerId): void {
const peerIdStr = peerId.toB58String(); const peerIdStr = peerId.toB58String();
if (this.keepAliveTimers[peerIdStr]) {
clearInterval(this.keepAliveTimers[peerIdStr]); if (this.pingKeepAliveTimers[peerIdStr]) {
delete this.keepAliveTimers[peerIdStr]; clearInterval(this.pingKeepAliveTimers[peerIdStr]);
delete this.pingKeepAliveTimers[peerIdStr];
}
if (this.relayKeepAliveTimers[peerIdStr]) {
clearInterval(this.relayKeepAliveTimers[peerIdStr]);
delete this.relayKeepAliveTimers[peerIdStr];
} }
} }
} }

View File

@ -14,6 +14,8 @@ export const RelayCodecs = [
*/ */
export const DefaultPubsubTopic = '/waku/2/default-waku/proto'; export const DefaultPubsubTopic = '/waku/2/default-waku/proto';
export const RelayPingContentTopic = '/relay-ping/1/ping/null';
/** /**
* RelayGossipFactor affects how many peers we will emit gossip to at each heartbeat. * RelayGossipFactor affects how many peers we will emit gossip to at each heartbeat.
* We will send gossip to RelayGossipFactor * (total number of non-mesh peers), or * We will send gossip to RelayGossipFactor * (total number of non-mesh peers), or