diff options
Diffstat (limited to 'src/transport/identity.rs')
| -rw-r--r-- | src/transport/identity.rs | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/src/transport/identity.rs b/src/transport/identity.rs index af0fe74..17c7795 100644 --- a/src/transport/identity.rs +++ b/src/transport/identity.rs @@ -38,9 +38,11 @@ use tracing::{debug, info}; use crate::identity::{self, NodeKey}; use crate::locks::MutexExt; +use crate::transport::stats::{IdentityCounts, IdentityStats, TransportStats}; use crate::transport::traffic::Traffic; use crate::transport::{ - EncodedMessage, HandlerFn, IdentityProof, MessageHandler, MessageKind, ParsedMessage, Transport, + Destination, EncodedMessage, HandlerFn, IdentityProof, MessageHandler, MessageKind, + ParsedMessage, Transport, }; pub(crate) const WHO_LABEL: &[u8] = b"continuum/who/1"; @@ -132,6 +134,8 @@ struct Book { asked: HashMap<String, Instant>, /// Seeds being resolved: who waits for a ME from where. waiting: HashMap<String, Vec<oneshot::Sender<String>>>, + /// Since start (`stats`). + counts: IdentityCounts, } /// The scheme of `address`. @@ -151,6 +155,7 @@ impl Book { if *slot != address { let previous = std::mem::replace(slot, address.to_owned()); self.at.remove(&previous); + self.counts.address_changes += 1; } } else { addresses.push(address.to_owned()); @@ -185,6 +190,25 @@ impl Book { } } + /// What the books hold now, and the counts. + fn stats(&self) -> IdentityStats { + let mut proven = std::collections::BTreeMap::new(); + for addresses in self.proven.values() { + for address in addresses { + *proven.entry(scheme_of(address).to_owned()).or_insert(0) += 1; + } + } + IdentityStats { + proven, + hinted: self + .hints + .keys() + .filter(|node| !self.proven.contains_key(*node)) + .count(), + counts: self.counts, + } + } + /// Whether to ask `address` WHO now (always, if `force`), noting that it was asked. fn ask(&mut self, address: &str, now: Instant, force: bool) -> bool { if !force @@ -294,6 +318,7 @@ impl Shared { ) -> Option<String> { let message = signed(label, address, &link.own_address()); if !identity::verify(&proof.key, &message, &proof.signature) { + self.lock().counts.proofs_rejected += 1; debug!(from = %address, "Ignoring an identity proof that doesn't hold"); return None; } @@ -379,6 +404,7 @@ impl Shared { match node { Some(node) => handler(node, message, payload_len).await, None => { + self.lock().counts.dropped_unproven += 1; debug!( from = %address, kind = ?message.kind(), @@ -512,6 +538,38 @@ impl Transport for IdentityTransport { .collect() } + /// The address `encode` picks, and the transport's connection there. + fn destination(&self, peer: &str) -> Option<Destination> { + let address = self.shared.destination(peer)?; + let proven = self + .shared + .lock() + .proven + .get(peer) + .is_some_and(|addresses| addresses.contains(&address)); + let connection = self + .shared + .split(&address) + .and_then(|(link, target)| link.inner.connection(&target)); + Some(Destination { + address, + proven, + connection, + }) + } + + /// The identity layer's, and each transport's. + fn stats(&self) -> TransportStats { + let mut stats = TransportStats { + identity: Some(self.shared.lock().stats()), + ..TransportStats::default() + }; + for link in &self.shared.links { + stats.merge(link.inner.stats()); + } + stats + } + /// Each transport's, with its scheme. fn discovered_seeds(&self) -> Vec<String> { self.shared @@ -594,9 +652,12 @@ impl Transport for IdentityTransport { info!(seed = %seed, node = %node, "Seed is node"); Ok(node) } - _ => Err(anyhow!( - "no node answered at {address} within {RESOLVE_TIMEOUT:?}" - )), + _ => { + self.shared.lock().counts.seeds_unanswered += 1; + Err(anyhow!( + "no node answered at {address} within {RESOLVE_TIMEOUT:?}" + )) + } } } @@ -617,7 +678,7 @@ impl Transport for IdentityTransport { async fn send_encoded(&self, message: &EncodedMessage) -> Result<()> { let hints = { - let book = self.shared.lock(); + let mut book = self.shared.lock(); let proven = book .proven .get(&message.peer) @@ -625,6 +686,7 @@ impl Transport for IdentityTransport { if proven { None } else { + book.counts.refused_unproven += 1; Some(book.hints.get(&message.peer).cloned().unwrap_or_default()) } }; @@ -721,6 +783,11 @@ mod tests { assert!(book.bind("s:y", "n2", now)); assert_eq!(book.proven["n1"], ["t:x"]); assert_eq!(book.at["s:y"].0, "n2"); + // Only n1's move from s:x to s:y changed an address. + assert_eq!(book.counts.address_changes, 1); + let stats = book.stats(); + assert_eq!(stats.proven["s"], 1); + assert_eq!(stats.proven["t"], 1); } #[test] |
