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); const DNS_QUERY_JITTER: Duration = Duration::from_secs(60 * 3); pub 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 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}