before retainer

This commit is contained in:
Severin Buhler
2024-02-07 19:18:56 +01:00
parent aee562e375
commit 2c2883215c
5 changed files with 56 additions and 45 deletions

7
Cargo.lock generated
View File

@@ -120,6 +120,12 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "anyhow"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]] [[package]]
name = "assert_approx_eq" name = "assert_approx_eq"
version = "1.1.0" version = "1.1.0"
@@ -1158,6 +1164,7 @@ name = "pkdns"
version = "0.2.2" version = "0.2.2"
dependencies = [ dependencies = [
"any-dns", "any-dns",
"anyhow",
"async-trait", "async-trait",
"chrono", "chrono",
"clap", "clap",

View File

@@ -9,7 +9,7 @@ edition = "2021"
ctrlc = "3.4.2" ctrlc = "3.4.2"
simple-dns = "0.6.0" simple-dns = "0.6.0"
pknames_core = "0.1.1" pknames_core = "0.1.1"
pkarr = "1.0.4" pkarr = { version = "1.0.4", features = ["dht", "async"]}
zbase32 = "0.1.2" zbase32 = "0.1.2"
ttl_cache = "0.5.1" ttl_cache = "0.5.1"
clap = "4.4.18" clap = "4.4.18"
@@ -17,3 +17,4 @@ any-dns = "0.2.1"
chrono = "0.4.33" chrono = "0.4.33"
tokio = { version = "1.36.0", features = ["full"] } tokio = { version = "1.36.0", features = ["full"] }
async-trait = "0.1.77" async-trait = "0.1.77"
anyhow = "1.0.79"

View File

@@ -23,12 +23,10 @@ impl MyHandler {
} }
#[async_trait] #[async_trait]
impl CustomHandler for MyHandler { impl CustomHandler for MyHandler {
async fn lookup( async fn lookup(&mut self,query: &Vec<u8>, _socket: DnsSocket) -> Result<Vec<u8>, CustomHandlerError> {
&mut self, let result = self.pkarr.resolve(query).await;
query: &Vec<u8>,
_socket: DnsSocket, match result {
) -> std::prelude::v1::Result<Vec<u8>, CustomHandlerError> {
match self.pkarr.resolve(query) {
Ok(reply) => Ok(reply), Ok(reply) => Ok(reply),
Err(_) => Err(CustomHandlerError::Unhandled), Err(_) => Err(CustomHandlerError::Unhandled),
} }

View File

@@ -1,7 +1,7 @@
use std::{ use std::{
error::Error,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use anyhow::anyhow;
use crate::{packet_lookup::resolve_query, pkarr_cache::PkarrPacketTtlCache}; use crate::{packet_lookup::resolve_query, pkarr_cache::PkarrPacketTtlCache};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
@@ -49,20 +49,21 @@ impl PkarrResolver {
trying.ok() trying.ok()
} }
fn resolve_pubkey_respect_cache(&mut self, pubkey: &PublicKey) -> Option<Vec<u8>> { async fn resolve_pubkey_respect_cache(&mut self, pubkey: &PublicKey) -> Option<Vec<u8>> {
let mut cache = self.cache.lock().unwrap(); let cache = self.cache.lock().unwrap();
let cached_opt = cache.get(pubkey); let cached_opt = cache.get(pubkey);
if cached_opt.is_some() { if cached_opt.is_some() {
let reply_bytes = cached_opt.unwrap(); let reply_bytes = cached_opt.unwrap();
return Some(reply_bytes); return Some(reply_bytes);
}; };
let packet_option = self.client.resolve(pubkey.clone()); let packet_option = self.client.resolve(pubkey.clone()).await;
if packet_option.is_none() { if packet_option.is_none() {
return None; return None;
}; };
let signed_packet = packet_option.unwrap(); let signed_packet = packet_option.unwrap();
let reply_bytes = signed_packet.packet().build_bytes_vec_compressed().unwrap(); let reply_bytes = signed_packet.packet().build_bytes_vec_compressed().unwrap();
let mut cache = self.cache.lock().unwrap();
cache.add(pubkey.clone(), reply_bytes.clone()); cache.add(pubkey.clone(), reply_bytes.clone());
Some(reply_bytes) Some(reply_bytes)
} }
@@ -70,29 +71,29 @@ impl PkarrResolver {
/** /**
* Resolves a domain with pkarr. * Resolves a domain with pkarr.
*/ */
pub fn resolve(&mut self, query: &Vec<u8>) -> std::prelude::v1::Result<Vec<u8>, Box<dyn Error>> { pub async fn resolve(&mut self, query: &Vec<u8>) -> std::prelude::v1::Result<Vec<u8>, anyhow::Error> {
let request = Packet::parse(query)?; let request = Packet::parse(query)?;
let question_opt = request.questions.first(); let question_opt = request.questions.first();
if question_opt.is_none() { if question_opt.is_none() {
return Err("Missing question".into()); return Err(anyhow!("Missing question"));
} }
let question = question_opt.unwrap(); let question = question_opt.unwrap();
let labels = question.qname.get_labels(); let labels = question.qname.get_labels();
if labels.len() == 0 { if labels.len() == 0 {
return Err("No label in question.qname.".into()); return Err(anyhow!("No label in question.qname."));
}; };
let raw_pubkey = labels.last().unwrap().to_string(); let raw_pubkey = labels.last().unwrap().to_string();
let parsed_option = Self::parse_pkarr_uri(&raw_pubkey); let parsed_option = Self::parse_pkarr_uri(&raw_pubkey);
if parsed_option.is_none() { if parsed_option.is_none() {
return Err("Invalid pkarr pubkey".into()); return Err(anyhow!("Invalid pkarr pubkey"));
} }
let pubkey = parsed_option.unwrap(); let pubkey = parsed_option.unwrap();
let packet_option = self.resolve_pubkey_respect_cache(&pubkey); let packet_option = self.resolve_pubkey_respect_cache(&pubkey).await;
if packet_option.is_none() { if packet_option.is_none() {
return Err("No pkarr packet found for pubkey".into()); return Err(anyhow!("No pkarr packet found for pubkey"));
} }
let pkarr_packet = packet_option.unwrap(); let pkarr_packet = packet_option.unwrap();
let pkarr_packet = Packet::parse(&pkarr_packet).unwrap(); let pkarr_packet = Packet::parse(&pkarr_packet).unwrap();
@@ -123,7 +124,7 @@ mod tests {
keypair keypair
} }
fn publish_record() { async fn publish_record() {
let keypair = get_test_keypair(); let keypair = get_test_keypair();
// let uri = keypair.to_uri_string(); // let uri = keypair.to_uri_string();
// println!("Publish packet with pubkey {}", uri); // println!("Publish packet with pubkey {}", uri);
@@ -147,13 +148,13 @@ mod tests {
let signed_packet = SignedPacket::from_packet(&keypair, &packet).unwrap(); let signed_packet = SignedPacket::from_packet(&keypair, &packet).unwrap();
let client = PkarrClient::new(); let client = PkarrClient::new();
let result = client.publish(&signed_packet); let result = client.publish(&signed_packet).await;
result.expect("Should have published."); result.expect("Should have published.");
} }
#[test] #[tokio::test]
fn query_domain() { async fn query_domain() {
publish_record(); publish_record().await;
let keypair = get_test_keypair(); let keypair = get_test_keypair();
let domain = format!("pknames.p2p.{}", keypair.to_z32()); let domain = format!("pknames.p2p.{}", keypair.to_z32());
@@ -168,7 +169,7 @@ mod tests {
query.questions.push(question); query.questions.push(question);
let mut resolver = PkarrResolver::new(0); let mut resolver = PkarrResolver::new(0);
let result = resolver.resolve(&query.build_bytes_vec_compressed().unwrap()); let result = resolver.resolve(&query.build_bytes_vec_compressed().unwrap()).await;
assert!(result.is_ok()); assert!(result.is_ok());
let reply_bytes = result.unwrap(); let reply_bytes = result.unwrap();
let reply = Packet::parse(&reply_bytes).unwrap(); let reply = Packet::parse(&reply_bytes).unwrap();
@@ -179,9 +180,9 @@ mod tests {
assert_eq!(answer.rdata.type_code(), pkarr::dns::TYPE::A); assert_eq!(answer.rdata.type_code(), pkarr::dns::TYPE::A);
} }
#[test] #[tokio::test]
fn query_pubkey() { async fn query_pubkey() {
publish_record(); publish_record().await;
let keypair = get_test_keypair(); let keypair = get_test_keypair();
let domain = keypair.to_z32(); let domain = keypair.to_z32();
@@ -195,7 +196,7 @@ mod tests {
); );
query.questions.push(question); query.questions.push(question);
let mut resolver = PkarrResolver::new(0); let mut resolver = PkarrResolver::new(0);
let result = resolver.resolve(&query.build_bytes_vec_compressed().unwrap()); let result = resolver.resolve(&query.build_bytes_vec_compressed().unwrap()).await;
assert!(result.is_ok()); assert!(result.is_ok());
let reply_bytes = result.unwrap(); let reply_bytes = result.unwrap();
let reply = Packet::parse(&reply_bytes).unwrap(); let reply = Packet::parse(&reply_bytes).unwrap();
@@ -206,8 +207,8 @@ mod tests {
assert_eq!(answer.rdata.type_code(), pkarr::dns::TYPE::A); assert_eq!(answer.rdata.type_code(), pkarr::dns::TYPE::A);
} }
#[test] #[tokio::test]
fn query_invalid_pubkey() { async fn query_invalid_pubkey() {
let domain = "invalid_pubkey"; let domain = "invalid_pubkey";
let name = Name::new(&domain).unwrap(); let name = Name::new(&domain).unwrap();
let mut query = Packet::new_query(0); let mut query = Packet::new_query(0);
@@ -219,7 +220,7 @@ mod tests {
); );
query.questions.push(question); query.questions.push(question);
let mut resolver = PkarrResolver::new(0); let mut resolver = PkarrResolver::new(0);
let result = resolver.resolve(&query.build_bytes_vec_compressed().unwrap()); let result = resolver.resolve(&query.build_bytes_vec_compressed().unwrap()).await;
assert!(result.is_err()); assert!(result.is_err());
// println!("{}", result.unwrap_err()); // println!("{}", result.unwrap_err());
} }
@@ -239,20 +240,20 @@ mod tests {
assert!(trying.is_err()); assert!(trying.is_err());
} }
#[test] #[tokio::test]
fn pkarr_invalid_packet1() { async fn pkarr_invalid_packet1() {
let pubkey = PkarrResolver::parse_pkarr_uri("7fmjpcuuzf54hw18bsgi3zihzyh4awseeuq5tmojefaezjbd64cy").unwrap(); let pubkey = PkarrResolver::parse_pkarr_uri("7fmjpcuuzf54hw18bsgi3zihzyh4awseeuq5tmojefaezjbd64cy").unwrap();
let mut resolver = PkarrResolver::new(0); let mut resolver = PkarrResolver::new(0);
let _result = resolver.resolve_pubkey_respect_cache(&pubkey); let _result = resolver.resolve_pubkey_respect_cache(&pubkey).await;
// assert!(result.is_some()); // assert!(result.is_some());
} }
#[test] #[tokio::test]
fn pkarr_invalid_packet2() { async fn pkarr_invalid_packet2() {
let pubkey = PkarrResolver::parse_pkarr_uri("7fmjpcuuzf54hw18bsgi3zihzyh4awseeuq5tmojefaezjbd64cy").unwrap(); let pubkey = PkarrResolver::parse_pkarr_uri("7fmjpcuuzf54hw18bsgi3zihzyh4awseeuq5tmojefaezjbd64cy").unwrap();
let client = PkarrClient::new(); let client = PkarrClient::new();
let signed_packet = client.resolve(pubkey).unwrap(); let signed_packet = client.resolve(pubkey).await.unwrap();
println!("Timestamp {}", signed_packet.chrono_timestamp()); println!("Timestamp {}", signed_packet.chrono_timestamp());
let reply_bytes = signed_packet.packet().build_bytes_vec_compressed().unwrap(); let reply_bytes = signed_packet.packet().build_bytes_vec_compressed().unwrap();
Packet::parse(&reply_bytes).unwrap(); Packet::parse(&reply_bytes).unwrap();

View File

@@ -1,6 +1,10 @@
use crate::pkarr_resolver::PkarrResolver; use crate::pkarr_resolver::PkarrResolver;
use pkarr::dns::{Name, Packet}; use pkarr::dns::{Name, Packet};
use pknames_core::resolve::resolve_standalone; use pknames_core::resolve::resolve_standalone;
use anyhow::anyhow;
#[derive(Clone)] #[derive(Clone)]
pub struct PknamesResolver { pub struct PknamesResolver {
@@ -20,10 +24,10 @@ impl PknamesResolver {
* Resolve a regular pknames domain into a pkarr domain. * Resolve a regular pknames domain into a pkarr domain.
* Example: `pknames.p2p` -> `pknames.p2p.7fmjpcuuzf54hw18bsgi3zihzyh4awseeuq5tmojefaezjbd64cy`. * Example: `pknames.p2p` -> `pknames.p2p.7fmjpcuuzf54hw18bsgi3zihzyh4awseeuq5tmojefaezjbd64cy`.
*/ */
fn predict_pknames_domain(&self, domain: &str) -> Result<String, Box<dyn std::error::Error>> { fn predict_pknames_domain(&self, domain: &str) -> Result<String, anyhow::Error> {
let result = resolve_standalone(&domain, &self.config_dir_path); let result = resolve_standalone(&domain, &self.config_dir_path);
if result.is_err() { if result.is_err() {
return Err("Neither pkarr nor pknames domain.".into()); return Err(anyhow!("Neither pkarr nor pknames domain."));
}; };
let predictions = result.unwrap(); let predictions = result.unwrap();
@@ -36,10 +40,10 @@ impl PknamesResolver {
Ok(full_domain) Ok(full_domain)
} }
pub fn resolve(&mut self, query: &Vec<u8>) -> std::prelude::v1::Result<Vec<u8>, Box<dyn std::error::Error>> { pub async fn resolve(&mut self, query: &Vec<u8>) -> std::prelude::v1::Result<Vec<u8>, anyhow::Error> {
let original_query = Packet::parse(query)?; let original_query = Packet::parse(query)?;
let pkarr_result = self.pkarr.resolve(&query.clone()); let pkarr_result = self.pkarr.resolve(&query.clone()).await;
if pkarr_result.is_ok() { if pkarr_result.is_ok() {
return pkarr_result; // It was a pkarr hostname return pkarr_result; // It was a pkarr hostname
} }
@@ -47,7 +51,7 @@ impl PknamesResolver {
let question = original_query let question = original_query
.questions .questions
.first() .first()
.ok_or("Query does not include a question.")?; .ok_or(anyhow!("Query does not include a question."))?;
let domain = question.qname.to_string(); let domain = question.qname.to_string();
let pkarr_domain = self.predict_pknames_domain(&domain)?; let pkarr_domain = self.predict_pknames_domain(&domain)?;
@@ -55,7 +59,7 @@ impl PknamesResolver {
let mut pkarr_query = original_query.clone(); let mut pkarr_query = original_query.clone();
pkarr_query.questions[0].qname = qname; pkarr_query.questions[0].qname = qname;
let pkarr_query = pkarr_query.build_bytes_vec_compressed().unwrap(); let pkarr_query = pkarr_query.build_bytes_vec_compressed().unwrap();
let pkarr_reply = self.pkarr.resolve(&pkarr_query)?; let pkarr_reply = self.pkarr.resolve(&pkarr_query).await?;
let pkarr_reply = Packet::parse(&pkarr_reply).unwrap(); let pkarr_reply = Packet::parse(&pkarr_reply).unwrap();
let mut reply = original_query.clone().into_reply(); let mut reply = original_query.clone().into_reply();
@@ -74,8 +78,8 @@ mod tests {
use super::PknamesResolver; use super::PknamesResolver;
#[test] #[tokio::test]
fn query_pubkey() { async fn query_pubkey() {
let mut pknames = PknamesResolver::new(1, "~/.pknames"); let mut pknames = PknamesResolver::new(1, "~/.pknames");
let mut query = Packet::new_query(0); let mut query = Packet::new_query(0);
@@ -89,7 +93,7 @@ mod tests {
query.questions.push(question); query.questions.push(question);
let query_bytes = query.build_bytes_vec_compressed().unwrap(); let query_bytes = query.build_bytes_vec_compressed().unwrap();
let result = pknames.resolve(&query_bytes); let result = pknames.resolve(&query_bytes).await;
if result.is_err() { if result.is_err() {
eprintln!("{:?}", result.unwrap_err()); eprintln!("{:?}", result.unwrap_err());
assert!(false); assert!(false);