`Gossipsub`'s substreams keep all connections alive after `idle_connection_timeout`
Summary
It seems gossipsub protocol keeps active substreams for connections that exists outside the gossip-mesh. As a result, connections remain alive even after idle_connection_timeout.
This functionality appears to have changed from version v0.52.0, where gossip kept connections alive only within the mesh. Commits with relevant updates: https://github.com/libp2p/rust-libp2p/commit/fafa6bc472f6fe9501c75be6a936df2cb37e053a and https://github.com/libp2p/rust-libp2p/commit/fcd410a56c86de3b34f4896d1447ef1da959947c
Expected behavior
Gossipsub protocol should keep connections alive, but exclusively for peers within the mesh
Actual behavior
Gossipsub protocol keeps all connections alive
Relevant log output
No response
Possible Solution
Ignore gossip substreams in the connection-keep-alive algorithm. Use libp2p_swarm::stream::Stream::ignore_for_keep_alive for gossip inbound and outbound substreams.
Version
0.53.1
Would you like to work on fixing this bug ?
Maybe
Hi @jxs, could you please provide feedback on this issue? Is it indeed a bug, or is this expected behavior? Also, does the proposed solution work for you?
Hi, and sorry for missing this!
Currently gossipsub only keeps the substream if it is in the mesh:
https://github.com/libp2p/rust-libp2p/blob/4dfc45bfec008405988edca2432c27ed5b93535f/protocols/gossipsub/src/handler.rs#L426-L428
which seems to be the opposite to what you refer on the issue right?
But I think all connections should be kept alive, as gossipsub publishes messages for peers not in the mesh.
Hi @jxs , looks like there was a misunderstanding.
Currently
gossipsubonly keeps the substream if it is in the mesh. Which seems to be the opposite to what you refer on the issue right?
I was specifically referring to open streams within the gossipsub connection handler (see: inbound_substream and outbound_substream).
These streams are created after successful negotiation and are never closed or dropped (I don't see any mechanism that closes them after idle-timeout for example). Because of this, the Keep-Alive Algorithm keeps connection indefinitely, as there are always active streams (see: keep-alive-algorithm).
The connection_keep_alive function you mentioned is only invoked when no active streams exist on the connection—which never happens, since the gossipsub handler keeps streams open indefinitely.
Questions:
-
Is it expected that the
gossipsubprotocol keeps all connections (both inside and outside the mesh) alive due to these active streams? - Would this behavior be considered a memory leak since the connection remains open until the remote party closes it?