Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
80e7fdd
Repeat ping request periodically
dharjeezy Jul 19, 2025
d6b3909
keep substream open by introducing stateful peer
dharjeezy Oct 6, 2025
9f8fe8c
use stream map for efficiency
dharjeezy Nov 29, 2025
f26e25c
separate inbound and outbound streams
dharjeezy Dec 14, 2025
9c535ed
fmt
dharjeezy Dec 14, 2025
2401ca7
review changes
dharjeezy Dec 24, 2025
fd0a305
review changes
dharjeezy Dec 24, 2025
b4e6a3b
nit
dharjeezy Jan 18, 2026
0b5f3c9
Merge branch 'master' of https://github.com/dharjeezy/litep2p into da…
dharjeezy Feb 21, 2026
4f32e97
include param
dharjeezy Feb 21, 2026
51792f5
Handle edge-cases and older (buggy) litep2p versions
dmitry-markin Feb 23, 2026
415029a
WIP: fix connection keep alive
dmitry-markin Feb 23, 2026
70c7848
Fix connection keep-alive for TCP transport
dmitry-markin Feb 24, 2026
fcbfc5a
Fix connection keep-alive for other transports
dmitry-markin Feb 24, 2026
d9529b3
Update tests
dmitry-markin Feb 24, 2026
a26c710
Merge remote-tracking branch 'upstream/master' into dami/repeat-reque…
dmitry-markin Feb 24, 2026
eda96c9
Improve docs
dmitry-markin Feb 25, 2026
70cdbee
More doc improvements
dmitry-markin Feb 25, 2026
ef230ed
Fix request-response timeout tests
dmitry-markin Feb 25, 2026
4070565
Apply review suggestions
dmitry-markin Feb 25, 2026
65b024d
Keep TCP connections with `SubstreamKeepAlive::Yes` substreams
dmitry-markin Feb 25, 2026
938fbe6
Keep other connections with `SubstreamKeepAlive::Yes` substreams alive
dmitry-markin Feb 25, 2026
e2151cd
minor: make clippy happy
dmitry-markin Feb 25, 2026
d388dca
minor: doc
dmitry-markin Feb 25, 2026
6b2e674
minor: doc
dmitry-markin Feb 25, 2026
838542f
minor: typo
dmitry-markin Feb 25, 2026
a6d81a1
Revert enabling all features by default
dmitry-markin Feb 25, 2026
622a349
Separate names for opening/lifetime permits
dmitry-markin Feb 26, 2026
b8d73cf
Make pings async
dmitry-markin Feb 26, 2026
2ab2bf7
Merge remote-tracking branch 'origin/master' into dm-ping-keep-alive
dmitry-markin Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/protocol/libp2p/ping/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::time::Duration;
use crate::{
codec::ProtocolCodec, protocol::libp2p::ping::PingEvent, types::protocol::ProtocolName,
DEFAULT_CHANNEL_SIZE,
Expand All @@ -36,6 +37,8 @@ const PING_PAYLOAD_SIZE: usize = 32;
/// Maximum PING failures.
const MAX_FAILURES: usize = 3;

pub const PING_INTERVAL: Duration = Duration::from_secs(15);

/// Ping configuration.
pub struct Config {
/// Protocol name.
Expand All @@ -49,6 +52,8 @@ pub struct Config {

/// TX channel for sending events to the user protocol.
pub(crate) tx_event: Sender<PingEvent>,

pub(crate) ping_interval: Duration,
}

impl Config {
Expand All @@ -61,6 +66,7 @@ impl Config {
(
Self {
tx_event,
ping_interval: PING_INTERVAL,
max_failures: MAX_FAILURES,
protocol: ProtocolName::from(PROTOCOL_NAME),
codec: ProtocolCodec::Identity(PING_PAYLOAD_SIZE),
Expand All @@ -80,6 +86,7 @@ pub struct ConfigBuilder {

/// Maximum failures before the peer is considered unreachable.
max_failures: usize,
ping_interval: Duration,
}

impl Default for ConfigBuilder {
Expand All @@ -92,6 +99,7 @@ impl ConfigBuilder {
/// Create new default [`Config`] which can be modified by the user.
pub fn new() -> Self {
Self {
ping_interval: PING_INTERVAL,
max_failures: MAX_FAILURES,
protocol: ProtocolName::from(PROTOCOL_NAME),
codec: ProtocolCodec::Identity(PING_PAYLOAD_SIZE),
Expand All @@ -104,13 +112,19 @@ impl ConfigBuilder {
self
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Is cargo doc check ignoring missings docs on public methods? We should also document this and state the defaults (same for above in public interfaces)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

litep2p doesn't have #![warn(missing_docs)] set. But this is for another PR :)

pub fn with_ping_interval(mut self, ping_interval: Duration) -> Self {
self.ping_interval = ping_interval;
self
}

/// Build [`Config`].
pub fn build(self) -> (Config, Box<dyn Stream<Item = PingEvent> + Send + Unpin>) {
let (tx_event, rx_event) = channel(DEFAULT_CHANNEL_SIZE);

(
Config {
tx_event,
ping_interval: self.ping_interval,
max_failures: self.max_failures,
protocol: self.protocol,
codec: self.codec,
Expand Down
20 changes: 18 additions & 2 deletions src/protocol/libp2p/ping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,16 @@ pub(crate) struct Ping {

/// Pending inbound substreams.
pending_inbound: FuturesUnordered<BoxFuture<'static, crate::Result<()>>>,

ping_interval: Duration,
}

impl Ping {
/// Create new [`Ping`] protocol.
pub fn new(service: TransportService, config: Config) -> Self {
Self {
service,
ping_interval: config.ping_interval,
tx: config.tx_event,
peers: HashSet::new(),
pending_outbound: FuturesUnordered::new(),
Expand All @@ -96,7 +99,6 @@ impl Ping {
fn on_connection_established(&mut self, peer: PeerId) -> crate::Result<()> {
tracing::trace!(target: LOG_TARGET, ?peer, "connection established");

self.service.open_substream(peer)?;
self.peers.insert(peer);

Ok(())
Expand Down Expand Up @@ -166,12 +168,13 @@ impl Ping {
/// Start [`Ping`] event loop.
pub async fn run(mut self) {
tracing::debug!(target: LOG_TARGET, "starting ping event loop");
let mut interval = tokio::time::interval(self.ping_interval);

loop {
tokio::select! {
event = self.service.next() => match event {
Some(TransportEvent::ConnectionEstablished { peer, .. }) => {
let _ = self.on_connection_established(peer);
self.on_connection_established(peer);
}
Some(TransportEvent::ConnectionClosed { peer }) => {
self.on_connection_closed(peer);
Expand All @@ -192,6 +195,19 @@ impl Ping {
Some(_) => {}
None => return,
},
_ = interval.tick() => {
for peer in &self.peers {
tracing::trace!(target: LOG_TARGET, ?peer, "sending ping");
if let Err(error) = self.service.open_substream(*peer) {
tracing::debug!(
target: LOG_TARGET,
?peer,
?error,
"failed to open substream for ping"
);
}
}
}
_event = self.pending_inbound.next(), if !self.pending_inbound.is_empty() => {}
event = self.pending_outbound.next(), if !self.pending_outbound.is_empty() => {
match event {
Expand Down
Loading