From 9f9bba83f8d2d26d0c746f8ea7cade814ae315e1 Mon Sep 17 00:00:00 2001 From: nazeh Date: Tue, 17 Dec 2024 14:03:26 +0300 Subject: [PATCH] fix(pkarr): return cached packet in case the DHT resolved no more recent ones --- pkarr/src/client.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/pkarr/src/client.rs b/pkarr/src/client.rs index c61d5e3..115947f 100644 --- a/pkarr/src/client.rs +++ b/pkarr/src/client.rs @@ -286,7 +286,7 @@ impl PkarrClient { debug!(expires_in, "Have expired signed_packet in cache."); } else { - debug!("Cache mess"); + debug!("Cache miss"); } self.sender @@ -368,6 +368,16 @@ fn run( // === Drop senders to done queries === for id in &report.done_get_queries { + // Send cached signed packet one more time in case none of the incoming + // packets were more recent than cache. + if let Some(senders) = senders.get(id) { + if let Some(signed_packet) = cache.get_read_only(id) { + for sender in senders { + let _ = sender.send(signed_packet.clone()); + } + } + } + senders.remove(id); } @@ -459,6 +469,8 @@ pub enum ActorMessage { #[cfg(test)] mod tests { + use std::time::Duration; + use mainline::Testnet; use super::*; @@ -580,4 +592,49 @@ mod tests { .join() .unwrap(); } + + #[test] + fn ttl_0_test() { + let testnet = Testnet::new(10); + + let client = PkarrClient::builder() + .dht_settings(DhtSettings { + bootstrap: Some(testnet.bootstrap), + request_timeout: Some(Duration::from_millis(50)), + server: None, + port: None, + }) + .maximum_ttl(0) + .build() + .unwrap(); + + let keypair = Keypair::random(); + let mut packet = dns::Packet::new_reply(0); + packet.answers.push(dns::ResourceRecord::new( + dns::Name::new("foo").unwrap(), + dns::CLASS::IN, + 30, + dns::rdata::RData::TXT("bar".try_into().unwrap()), + )); + + let signed_packet = SignedPacket::from_packet(&keypair, &packet).unwrap(); + + client.publish(&signed_packet).unwrap(); + + // First Call + let resolved = client + .resolve(&signed_packet.public_key()) + .unwrap() + .unwrap(); + + assert_eq!(resolved.encoded_packet(), signed_packet.encoded_packet()); + + thread::sleep(Duration::from_millis(10)); + + let second = client + .resolve(&signed_packet.public_key()) + .unwrap() + .unwrap(); + assert_eq!(second.encoded_packet(), signed_packet.encoded_packet()); + } }