From 01d5f45db67e03e748ace5a94f43781ac3b4c42d Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Thu, 30 Jun 2022 15:12:26 +0200 Subject: [PATCH] Reestablish peer connection on silent stream destruction (#288) --- packages/status-js/src/client/client.ts | 37 +++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/status-js/src/client/client.ts b/packages/status-js/src/client/client.ts index c586b74a..4fac0866 100644 --- a/packages/status-js/src/client/client.ts +++ b/packages/status-js/src/client/client.ts @@ -18,14 +18,32 @@ export interface ClientOptions { class Client { public waku: Waku public readonly wakuMessages: Set + /** + * Tracks open connections which had their streams silently destroyed + * and closes them so new connections can be automatically created. + * + * For example, in case of a websocket in browser which did not + * have its close event emitted. + * + * Note: Detection of the stream removal depends on active (by user) + * or pasive (with `Waku.relayKeepAlive`) message sending. + * + * Note: This is only a workaround (@see https://github.com/libp2p/js-libp2p/issues/939). + */ + #wakuDisconnectionTimer: ReturnType public account?: Account public community: Community - constructor(waku: Waku, options: ClientOptions) { + constructor( + waku: Waku, + wakuDisconnectionTimer: ReturnType, + options: ClientOptions + ) { // Waku this.waku = waku this.wakuMessages = new Set() + this.#wakuDisconnectionTimer = wakuDisconnectionTimer // Community this.community = new Community(this, options.publicKey) @@ -41,12 +59,26 @@ class Client { // '/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ', ], }, + relayKeepAlive: 15, libp2p: { config: { pubsub: { enabled: true, emitSelf: true } } }, }) await waku.waitForRemotePeer() + const wakuDisconnectionTimer = setInterval(async () => { + const connectionsToClose: Promise[] = [] + + for (const connections of waku.libp2p.connectionManager.connections.values()) { + for (const connection of connections) { + if (!connection.streams.length) { + connectionsToClose.push(connection.close()) + } + } + } + + await Promise.allSettled(connectionsToClose) + }, 10 * 1000) // Client - const client = new Client(waku, options) + const client = new Client(waku, wakuDisconnectionTimer, options) // Community await client.community.start() @@ -55,6 +87,7 @@ class Client { } public async stop() { + clearInterval(this.#wakuDisconnectionTimer) await this.waku.stop() }