apt_swarm/p2p/
dns.rs

1use crate::errors::*;
2use crate::p2p;
3use crate::p2p::proto::{PeerAddr, SyncRequest};
4use std::convert::Infallible;
5use std::net::SocketAddr;
6use std::time::Duration;
7use tokio::sync::mpsc;
8use tokio::sync::mpsc::error::TrySendError;
9use tokio::time;
10
11pub const DNS_SEEDS: &[&str] = &["dnsseed.apt-swarm.orca.toys"];
12
13const DNS_DEBOUNCE: Duration = Duration::from_millis(100);
14const DNS_QUERY_COOLDOWN: Duration = Duration::from_secs(60 * 60); // 1h
15const DNS_QUERY_JITTER: Duration = Duration::from_secs(60 * 3); // 3min
16
17pub async fn resolve(dns: &str) -> Result<impl Iterator<Item = SocketAddr>> {
18    info!("Resolving dns name: {dns:?}");
19    let host = format!("{dns}:16169");
20    let stream = tokio::net::lookup_host(host.clone())
21        .await
22        .with_context(|| anyhow!("Failed to resolve: {host:?}"))?;
23    Ok(stream)
24}
25
26pub async fn spawn(dns: Vec<String>, peering_tx: mpsc::Sender<SyncRequest>) -> Result<Infallible> {
27    // briefly delay this in case we error out for some reason
28    tokio::time::sleep(DNS_DEBOUNCE).await;
29
30    loop {
31        for name in &dns {
32            match resolve(name).await {
33                Ok(addrs) => {
34                    let addrs = addrs.map(PeerAddr::Inet).collect();
35
36                    for addr in &addrs {
37                        debug!("Resolved dns name to address: {addr:?}");
38                    }
39
40                    let addr = SyncRequest { hint: None, addrs };
41                    if let Err(TrySendError::Full(addr)) = peering_tx.try_send(addr) {
42                        warn!("Discarding addr because peering backlog is full: {addr:?}");
43                    }
44                }
45                Err(err) => error!("Failed to query dns name {name:?}: {err:#}"),
46            }
47        }
48        time::sleep(DNS_QUERY_COOLDOWN).await;
49        p2p::random_jitter(DNS_QUERY_JITTER).await;
50    }
51}