From d7959009790a422ebb17d4c4ab1d9be3d48dc511 Mon Sep 17 00:00:00 2001 From: tv Date: Wed, 28 Oct 2026 17:38:16 +0100 Subject: list libp2p relays in document --- src/swarm/members.rs | 32 ++++++++++++++++++++++++++++++++ src/swarm/topology.rs | 1 + 2 files changed, 33 insertions(+) (limited to 'src/swarm') diff --git a/src/swarm/members.rs b/src/swarm/members.rs index c2edd01..3bfb9cf 100644 --- a/src/swarm/members.rs +++ b/src/swarm/members.rs @@ -146,6 +146,27 @@ pub(crate) fn learn_addresses(state: &AppState, doc: &AutoCommit) { } } +/// Relays listed for the swarm, at most this many. +const MAX_RELAYS: usize = 32; + +/// The relays listed for the swarm under `_continuum/relays` (by `--protocol-writers`): +/// addresses (`libp2p:`, with or without the relay's peer ID) of relays that +/// aren't members, e.g. nodes that only relay. Every member's transport may +/// pick them (`Transport::learn_relays`), after the relays it is configured with. +pub(crate) fn relays(doc: &AutoCommit) -> Vec { + match store::read_path(doc, &meta::path(&[meta::RELAYS])) { + Ok(Some(JsonValue::Array(items))) => items + .into_iter() + .filter_map(|item| match item { + JsonValue::String(address) => Some(address), + _ => None, + }) + .take(MAX_RELAYS) + .collect(), + _ => Vec::new(), + } +} + fn alive_path(pk: &str) -> Vec { let mut path = member_path(pk); path.push("alive".to_owned()); @@ -302,6 +323,17 @@ mod tests { ); } + #[test] + fn listed_relays() { + let mut doc = AutoCommit::new(); + assert!(relays(&doc).is_empty()); + let relay = "libp2p:/ip6/fd00::1/tcp/9661"; + store::write_path(&mut doc, &meta::path(&[meta::RELAYS]), &json!([relay, 7])).unwrap(); + assert_eq!(relays(&doc), [relay]); // Anything but text is ignored. + store::write_path(&mut doc, &meta::path(&[meta::RELAYS]), &json!(relay)).unwrap(); + assert!(relays(&doc).is_empty()); // Not a list. + } + #[test] fn renewal_interval() { let day = Duration::from_secs(24 * 3600); diff --git a/src/swarm/topology.rs b/src/swarm/topology.rs index 1e4f5b9..1d98637 100644 --- a/src/swarm/topology.rs +++ b/src/swarm/topology.rs @@ -163,6 +163,7 @@ pub(crate) async fn refresh(state: &AppState) -> Option { let replica = state.doc.read().await; members::learn_addresses(state, &replica.doc); set_aliases(state, members::aliases(&replica.doc)); + state.transport.learn_relays(&members::relays(&replica.doc)); let current = members::members(&replica.doc); // Those that said they are alive within the electorate window. let alive: BTreeSet = members::electorate( -- cgit v1.3.1