diff options
| author | tv <tv@krebsco.de> | 2026-11-07 22:35:10 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-07 22:35:10 +0100 |
| commit | 0e03a77bcb1d39f1fbda23d8e704ac40302afb93 (patch) | |
| tree | 79245416e9721cdccb1b6879b8f1cfc43629cc74 /src/transport | |
| parent | c016fc783ff29e9069a446e17876046df64760a8 (diff) | |
dashboard: without LINKS; LINKS removed
The dashboard reads every member's links from the members themselves;
LINKS and LINKS_REPLY, swarm::links and their wire tags go (wire
version bumped). Nodes the browser can't reach are drawn from what the
reachable ones measure.
Auth plan M3.
Diffstat (limited to 'src/transport')
| -rw-r--r-- | src/transport/mod.rs | 97 | ||||
| -rw-r--r-- | src/transport/paths.rs | 2 | ||||
| -rw-r--r-- | src/transport/traffic.rs | 11 | ||||
| -rw-r--r-- | src/transport/wire.rs | 49 |
4 files changed, 4 insertions, 155 deletions
diff --git a/src/transport/mod.rs b/src/transport/mod.rs index 8cbf412..f5b2db1 100644 --- a/src/transport/mod.rs +++ b/src/transport/mod.rs @@ -238,11 +238,6 @@ pub(crate) enum ParsedMessage { nonce: u64, at: crate::clock::UnixMillis, }, - /// Asks a member how it is linked to its peers, for a map of the swarm - /// (`swarm::links`). - Links(LinksRequest), - /// Answers a LINKS. - LinksReply(LinksReply), /// Asks whether the recipient reaches a member (`swarm::working_links`). Probe(ProbeRequest), /// Answers a PROBE. @@ -397,8 +392,6 @@ pub(crate) enum MessageKind { Me, Ping, Pong, - Links, - LinksReply, Probe, ProbeReply, Prune, @@ -421,8 +414,6 @@ impl ParsedMessage { ParsedMessage::Me(_) => MessageKind::Me, ParsedMessage::Ping(_) => MessageKind::Ping, ParsedMessage::Pong { .. } => MessageKind::Pong, - ParsedMessage::Links(_) => MessageKind::Links, - ParsedMessage::LinksReply(_) => MessageKind::LinksReply, ParsedMessage::Probe(_) => MessageKind::Probe, ParsedMessage::ProbeReply(_) => MessageKind::ProbeReply, ParsedMessage::Prune(_) => MessageKind::Prune, @@ -446,8 +437,6 @@ impl ParsedMessage { Some((status.epoch, status.epoch_seq)) } ParsedMessage::Blob(blob) => Some((blob.epoch, blob.epoch_seq)), - ParsedMessage::Links(request) => Some((request.epoch, request.epoch_seq)), - ParsedMessage::LinksReply(reply) => Some((reply.epoch, reply.epoch_seq)), ParsedMessage::Probe(request) => Some((request.epoch, request.epoch_seq)), ParsedMessage::ProbeReply(reply) => Some((reply.epoch, reply.epoch_seq)), ParsedMessage::Prune(link) | ParsedMessage::Graft(link) => { @@ -530,92 +519,6 @@ pub(crate) struct ProbeReply { pub(crate) reached: Option<bool>, } -/// LINKS: what a member is asked for a map of the swarm (`swarm::links`). -#[derive(Debug, Clone, Serialize, Deserialize)] -pub(crate) struct LinksRequest { - #[serde(with = "crate::transport::wire::codec::epoch")] - pub(crate) epoch: Epoch, - /// See `SyncEnvelope::epoch_seq`. - pub(crate) epoch_seq: u32, - /// Repeated in the reply: which request it answers. - pub(crate) nonce: u64, - /// For this long (seconds), a LINKS_REPLY again whenever the links change (a - /// subscription; the next LINKS renews it). 0: this reply only, and a subscription - /// ends (a relayed one runs out instead). - pub(crate) subscribe_secs: u32, - /// Members the receiver is to ask on the sender's behalf, which the sender can't - /// reach, passing their links on (relayed, `swarm::links`); none: the receiver's own. - pub(crate) of: Vec<String>, - /// How long relayed links may be held to send several in one LINKS_REPLY, by the - /// receiver and the hops after it together (milliseconds; `swarm::links`). - pub(crate) batch_ms: u32, - /// How many more nodes a relayed request may go through, after the receiver. - pub(crate) hops: u8, -} - -/// LINKS_REPLY: how the sender is linked to its neighbours, as it measures them. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub(crate) struct LinksReply { - #[serde(with = "crate::transport::wire::codec::epoch")] - pub(crate) epoch: Epoch, - /// See `SyncEnvelope::epoch_seq`. - pub(crate) epoch_seq: u32, - /// The request's. - pub(crate) nonce: u64, - /// The sender's own, if asked for; at most `swarm::links::MAX_LINKS`. - pub(crate) links: Vec<Link>, - /// Other members' links, passed on (`LinksRequest::of`). - pub(crate) relayed: Vec<RelayedLinks>, -} - -/// A member's links as a LINKS_REPLY passes them on. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub(crate) struct RelayedLinks { - pub(crate) member: String, - /// How long ago the member reported them (milliseconds). - pub(crate) age_ms: u32, - /// The member's epoch, as its LINKS_REPLY said (`LinksReply::epoch`): a dashboard - /// shows who entered a new one, swarm-wide. - #[serde(with = "crate::transport::wire::codec::epoch")] - pub(crate) epoch: Epoch, - pub(crate) links: Vec<Link>, -} - -/// One of a member's links, in a LINKS_REPLY. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub(crate) struct Link { - /// The peer's node ID. - pub(crate) peer: String, - /// The transport its messages go over now (the scheme of the path in use), if any. - pub(crate) transport: Option<String>, - /// Only through a relay (libp2p). - pub(crate) relayed: bool, - /// The path in use is down: none to the peer answers (`paths`), whatever its - /// connection was. - pub(crate) down: bool, - /// The round trip on that path, in microseconds, if measured. - pub(crate) rtt_us: Option<u32>, - /// Silent for long (`peers.md`, dormancy). - pub(crate) dormant: bool, - /// The peer's other transports (`swarm::links::MAX_OTHERS` at most): where else - /// it proved itself, those paths up. - pub(crate) others: Vec<OtherPath>, - /// How far the peer's clock is ahead of the member's (`paths::ClockOffset`), if - /// measured: with every member's, a map of the swarm shows whose clock is off. - pub(crate) clock: Option<paths::ClockOffset>, -} - -/// A transport of a link besides the one in use, in a LINKS_REPLY. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub(crate) struct OtherPath { - /// Its scheme (`mycelium`, `libp2p`, `tor`). - pub(crate) transport: String, - /// The round trip of its fastest path, in microseconds, if any is measured. - pub(crate) rtt_us: Option<u32>, - /// Only through a relay (libp2p): no direct connection at any of its paths. - pub(crate) relayed: bool, -} - #[derive(Clone, Serialize, Deserialize)] pub(crate) struct HelloRequest { /// The sender's swarm, if it knows it (a new node doesn't yet). A receiver in diff --git a/src/transport/paths.rs b/src/transport/paths.rs index aca0684..844a897 100644 --- a/src/transport/paths.rs +++ b/src/transport/paths.rs @@ -209,7 +209,7 @@ impl Table { /// `usable`, with each one's place in the configured order, best first (as /// `Paths::rank` says). With `sending`, for a message about to go: they count as /// used (`ACTIVE_FOR`), and the one in use may change for a faster one. Without, a - /// look at the choice as it stands, changing nothing (`/peers`, figures, LINKS). + /// look at the choice as it stands, changing nothing (`/peers`, figures, the dashboard's links). fn rank( &mut self, mut usable: Vec<(String, usize)>, diff --git a/src/transport/traffic.rs b/src/transport/traffic.rs index 8220041..13ca9fa 100644 --- a/src/transport/traffic.rs +++ b/src/transport/traffic.rs @@ -51,8 +51,6 @@ pub(crate) struct ByKind { pub(crate) identity: Counter, /// PING and PONG (`transport::paths`), counted by the paths layer under the address. pub(crate) paths: Counter, - /// LINKS and LINKS_REPLY (`swarm::links`). - pub(crate) links: Counter, /// PROBE and PROBE_REPLY (`swarm::working_links`). pub(crate) probe: Counter, /// PRUNE and GRAFT (`swarm::plumtree`). @@ -72,7 +70,6 @@ impl ByKind { MessageKind::Blob, MessageKind::Who, MessageKind::Ping, - MessageKind::Links, MessageKind::Probe, MessageKind::Prune, MessageKind::Neighbour, @@ -92,7 +89,6 @@ impl ByKind { MessageKind::Blob => &self.blob, MessageKind::Who | MessageKind::Me => &self.identity, MessageKind::Ping | MessageKind::Pong => &self.paths, - MessageKind::Links | MessageKind::LinksReply => &self.links, MessageKind::Probe | MessageKind::ProbeReply => &self.probe, MessageKind::Prune | MessageKind::Graft => &self.plumtree, MessageKind::Neighbour | MessageKind::NeighbourReply | MessageKind::Disconnect => { @@ -111,7 +107,6 @@ impl ByKind { MessageKind::Blob => &mut self.blob, MessageKind::Who | MessageKind::Me => &mut self.identity, MessageKind::Ping | MessageKind::Pong => &mut self.paths, - MessageKind::Links | MessageKind::LinksReply => &mut self.links, MessageKind::Probe | MessageKind::ProbeReply => &mut self.probe, MessageKind::Prune | MessageKind::Graft => &mut self.plumtree, MessageKind::Neighbour | MessageKind::NeighbourReply | MessageKind::Disconnect => { @@ -199,7 +194,7 @@ pub(crate) struct Logged { /// What ties `message`, with `peer`, to other messages: a PING and its PONG (the /// nonce alone: a PING may go to an address and its PONG come back up from the node -/// there, `paths`), a LINKS and its replies (the nonce), a HELLO and its replies (the run of the +/// there, `paths`), a HELLO and its replies (the run of the /// node that sent the HELLO, which the reply echoes), a blob's requests and answers, from /// any peer (its ID), and a delta offered in a SYNC with the blob it is fetched as. None /// for the rest (a STATUS and its reply carry nothing of the kind). @@ -209,8 +204,6 @@ fn related(peer: &str, message: &ParsedMessage) -> Option<String> { ParsedMessage::Ping(nonce) | ParsedMessage::Pong { nonce, .. } => { format!("ping {nonce}") } - ParsedMessage::Links(request) => format!("links {peer} {}", request.nonce), - ParsedMessage::LinksReply(reply) => format!("links {peer} {}", reply.nonce), ParsedMessage::Probe(request) => format!("probe {peer} {}", request.nonce), ParsedMessage::ProbeReply(reply) => format!("probe {peer} {}", reply.nonce), ParsedMessage::Hello(hello) => format!("hello {peer} {}", Hex(&hello.run_id)), @@ -321,8 +314,6 @@ fn names(kind: MessageKind) -> (&'static str, &'static str) { MessageKind::Me => ("ME", "identity"), MessageKind::Ping => ("PING", "paths"), MessageKind::Pong => ("PONG", "paths"), - MessageKind::Links => ("LINKS", "links"), - MessageKind::LinksReply => ("LINKS_REPLY", "links"), MessageKind::Probe => ("PROBE", "probe"), MessageKind::ProbeReply => ("PROBE_REPLY", "probe"), MessageKind::Prune => ("PRUNE", "plumtree"), diff --git a/src/transport/wire.rs b/src/transport/wire.rs index 0733d9c..8ead9b0 100644 --- a/src/transport/wire.rs +++ b/src/transport/wire.rs @@ -14,7 +14,7 @@ use super::{EncodedMessage, MessageKind, ParsedMessage}; /// The wire format's version, the first byte of every payload. Bump it with every change /// to a message type or a codec (`golden_bytes` fails then). -pub(crate) const VERSION: u8 = 38; +pub(crate) const VERSION: u8 = 39; /// What the second byte of a payload says. fn tag(kind: MessageKind) -> u8 { @@ -29,8 +29,6 @@ fn tag(kind: MessageKind) -> u8 { MessageKind::Me => 7, MessageKind::Ping => 8, MessageKind::Pong => 9, - MessageKind::Links => 10, - MessageKind::LinksReply => 11, MessageKind::Probe => 12, MessageKind::ProbeReply => 13, MessageKind::Prune => 14, @@ -90,8 +88,6 @@ pub(crate) fn encode(message: &ParsedMessage) -> Result<Vec<u8>, WireError> { } ParsedMessage::Ping(nonce) => rmp_serde::encode::write(&mut payload, nonce)?, ParsedMessage::Pong { nonce, at } => rmp_serde::encode::write(&mut payload, &(nonce, at))?, - ParsedMessage::Links(request) => rmp_serde::encode::write(&mut payload, request)?, - ParsedMessage::LinksReply(reply) => rmp_serde::encode::write(&mut payload, reply)?, ParsedMessage::Probe(request) => rmp_serde::encode::write(&mut payload, request)?, ParsedMessage::ProbeReply(reply) => rmp_serde::encode::write(&mut payload, reply)?, ParsedMessage::Prune(link) | ParsedMessage::Graft(link) => { @@ -166,10 +162,6 @@ pub(crate) fn decode(payload: &[u8]) -> Result<ParsedMessage, WireError> { } else if is(MessageKind::Pong) { let (nonce, at) = rmp_serde::from_slice(body)?; ParsedMessage::Pong { nonce, at } - } else if is(MessageKind::Links) { - ParsedMessage::Links(rmp_serde::from_slice(body)?) - } else if is(MessageKind::LinksReply) { - ParsedMessage::LinksReply(rmp_serde::from_slice(body)?) } else if is(MessageKind::Probe) { ParsedMessage::Probe(rmp_serde::from_slice(body)?) } else if is(MessageKind::ProbeReply) { @@ -504,43 +496,6 @@ pub(crate) fn samples() -> Vec<ParsedMessage> { nonce: u64::MAX, at: crate::clock::UnixMillis(5), }, - ParsedMessage::Links(crate::transport::LinksRequest { - epoch, - epoch_seq: 1, - nonce: 3, - subscribe_secs: 60, - of: vec!["q".into()], - batch_ms: 250, - hops: 2, - }), - ParsedMessage::LinksReply(crate::transport::LinksReply { - epoch, - epoch_seq: 1, - nonce: 3, - links: vec![crate::transport::Link { - peer: "p".into(), - transport: Some("libp2p".into()), - relayed: true, - down: false, - rtt_us: Some(1500), - dormant: false, - others: vec![crate::transport::OtherPath { - transport: "mycelium".into(), - rtt_us: None, - relayed: false, - }], - clock: Some(crate::transport::paths::ClockOffset { - offset_ms: -2_500, - within_ms: 40, - }), - }], - relayed: vec![crate::transport::RelayedLinks { - member: "q".into(), - age_ms: 1200, - epoch, - links: Vec::new(), - }], - }), ParsedMessage::Probe(crate::transport::ProbeRequest { epoch, epoch_seq: 1, @@ -610,7 +565,7 @@ mod tests { #[test] fn every_kind_round_trips() { let samples = samples(); - assert_eq!(samples.len(), 19, "a kind is missing from `samples`"); + assert_eq!(samples.len(), 17, "a kind is missing from `samples`"); for message in samples { let bytes = encode(&message).unwrap(); let decoded = decode(&bytes).unwrap(); |
