Skip to content

Commit

Permalink
feat(pkarr): support max_chain_depth configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuhvi committed Feb 6, 2025
1 parent 6425746 commit 45f3052
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 15 deletions.
8 changes: 6 additions & 2 deletions pkarr/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,22 @@ use crate::{Cache, CacheKey, InMemoryCache};
use crate::{PublicKey, SignedPacket};

#[derive(Debug)]
pub struct Inner {
pub(crate) struct Inner {
minimum_ttl: u32,
maximum_ttl: u32,
cache: Option<Arc<dyn Cache>>,
#[cfg(dht)]
dht: Option<Dht>,
#[cfg(relays)]
relays: Option<RelaysClient>,
#[cfg(feature = "endpoints")]
pub(crate) max_recursion_depth: u8,
}

/// Pkarr client for publishing and resolving [SignedPacket]s over
/// [mainline] Dht and/or [Relays](https://pkarr.org/relays).
#[derive(Clone, Debug)]
pub struct Client(Arc<Inner>);
pub struct Client(pub(crate) Arc<Inner>);

impl Client {
pub(crate) fn new(config: Config) -> Result<Client, BuildError> {
Expand Down Expand Up @@ -109,6 +111,8 @@ impl Client {
dht,
#[cfg(relays)]
relays,
#[cfg(feature = "endpoints")]
max_recursion_depth: config.max_recursion_depth,
}));

Ok(client)
Expand Down
21 changes: 21 additions & 0 deletions pkarr/src/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use crate::{Cache, DEFAULT_CACHE_SIZE, DEFAULT_MAXIMUM_TTL, DEFAULT_MINIMUM_TTL}

use crate::{errors::BuildError, Client};

#[cfg(feature = "endpoints")]
pub const DEFAULT_MAX_RECURSION_DEPTH: u8 = 7;

#[cfg(dht)]
pub const DEFAULT_REQUEST_TIMEOUT: Duration = mainline::DEFAULT_REQUEST_TIMEOUT;
#[cfg(not(dht))]
Expand Down Expand Up @@ -44,6 +47,9 @@ pub(crate) struct Config {
///
/// Defaults to [DEFAULT_REQUEST_TIMEOUT]
pub request_timeout: Duration,

#[cfg(feature = "endpoints")]
pub max_recursion_depth: u8,
}

impl Default for Config {
Expand All @@ -68,6 +74,9 @@ impl Default for Config {
),

request_timeout: DEFAULT_REQUEST_TIMEOUT,

#[cfg(feature = "endpoints")]
max_recursion_depth: DEFAULT_MAX_RECURSION_DEPTH,
}
}
}
Expand Down Expand Up @@ -249,6 +258,18 @@ impl ClientBuilder {
self
}

#[cfg(feature = "endpoints")]
/// Sets the maximum depth of recursion in [Endpoints](https://pkarr.org/endpoints) resolution.
///
/// Similar to `bind9`'s [opiton](https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-max-recursion-depth)
///
/// Defaults to `7`
pub fn max_recursion_depth(&mut self, max_recursion_depth: u8) -> &mut Self {
self.0.max_recursion_depth = max_recursion_depth;

self
}

pub fn build(&self) -> Result<Client, BuildError> {
Client::new(self.0.clone())
}
Expand Down
16 changes: 4 additions & 12 deletions pkarr/src/extra/endpoints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ use genawaiter::sync::Gen;

use crate::PublicKey;

const DEFAULT_MAX_CHAIN_LENGTH: u8 = 3;

impl crate::Client {
/// Returns an async stream of [HTTPS][crate::dns::rdata::RData::HTTPS] [Endpoint]s
pub fn resolve_https_endpoints<'a>(
Expand Down Expand Up @@ -72,11 +70,6 @@ impl crate::Client {
https: bool,
) -> impl Stream<Item = Endpoint> + 'a {
Gen::new(|co| async move {
// TODO: cache the result of this function?
// TODO: test load balancing
// TODO: test failover
// TODO: custom max_chain_length

let mut depth = 0;
let mut stack: Vec<Endpoint> = Vec::new();

Expand All @@ -94,7 +87,7 @@ impl crate::Client {
// Attempt to resolve the domain as a public key.
match PublicKey::try_from(current) {
Ok(tld) => match self.resolve(&tld).await {
Some(signed_packet) if depth < DEFAULT_MAX_CHAIN_LENGTH => {
Some(signed_packet) if depth < self.0.max_recursion_depth => {
depth += 1;
let endpoints = Endpoint::parse(&signed_packet, current, https);

Expand All @@ -105,7 +98,7 @@ impl crate::Client {

stack.extend(endpoints);
}
_ => break, // Stop on resolution failure or chain length exceeded.
_ => break, // Stop on resolution failure or recursion depth exceeded.
},
// Yield if the domain is not pointing to another Pkarr TLD domain.
Err(_) => co.yield_(next).await,
Expand Down Expand Up @@ -141,8 +134,6 @@ mod tests {

use mainline::Testnet;

// TODO: test SVCB too.

fn generate_subtree(
client: Client,
depth: u8,
Expand Down Expand Up @@ -271,11 +262,12 @@ mod tests {
}

#[tokio::test]
async fn max_chain_exceeded() {
async fn max_recursion_exceeded() {
let testnet = Testnet::new(3).unwrap();
let client = Client::builder()
.no_default_network()
.bootstrap(&testnet.bootstrap)
.max_recursion_depth(3)
.build()
.unwrap();

Expand Down
7 changes: 6 additions & 1 deletion pkarr/src/extra/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,14 @@ impl ServerCertVerifier for CertVerifier {

let qname = host_name.to_str();

// Resolve HTTPS endpoints and hope that the cached SignedPackets didn't chance
// Resolve HTTPS endpoints and hope that the cached SignedPackets didn't change
// since the last time we resolved endpoints to establish the connection in the
// first place.
//
// This won't be neccessary if Reqwest enabled us to createa rustls configuration
// per connection.
//
// TODO: update this Reqwest enabled this.
let stream = self.0.resolve_https_endpoints(&qname);
pin!(stream);
for endpoint in block_on(stream) {
Expand Down

0 comments on commit 45f3052

Please sign in to comment.