idoh
#![feature(doc_auto_cfg)]
#![feature(doc_cfg)]
mod post;
use std::sync::{
Arc,
atomic::{AtomicU8, Ordering},
};
pub use post::{Answer, DohError, post};
use defer_lite::defer;
use aok::{OK, Result};
use tracing::error;
use tokio::time::{Duration, sleep};
pub mod record_type {
pub const TXT: u16 = 16;
}
pub static DOH_LI: &[&str] = &[
"doh.pub/resolve", "dns.google/resolve",
"dns0.eu",
"cloudflare-dns.com/dns-query",
"doh.sb/dns-query",
"doh.360.cn/resolve",
"dns.nextdns.io",
"dns.twnic.tw/dns-query",
"dns.alidns.com/resolve",
];
pub async fn resolve<T: Send + 'static>(
name: impl AsRef<str>,
record_type: impl AsRef<str>,
extract: impl Fn(Vec<Answer>) -> Result<Option<T>> + Send + 'static + Clone,
) -> Result<T> {
let query = format!("?name={}&type={}", name.as_ref(), record_type.as_ref());
let (send, recv) = kanal::bounded_async(1);
let spawn = tokio::spawn(async move {
let ing = Arc::new(AtomicU8::new(DOH_LI.len() as _));
for doh in riter::iter(DOH_LI) {
let query = query.clone();
let send = send.clone();
let ing = ing.clone();
let extract = extract.clone();
tokio::spawn(async move {
let r = post(doh, &query).await;
let runing = ing.fetch_sub(1, Ordering::Relaxed);
macro_rules! send_err {
($err: expr) => {{
let err = $err;
error!("{runing} : {doh} {err}");
if runing == 1 {
xerr::log!(send.send(Err(err)).await);
}
}};
}
match r {
Ok(res) => match extract(res) {
Ok(res) => {
if let Some(res) = res {
let _ = send.send(Ok::<_, aok::Error>(res)).await;
}
}
Err(err) => send_err!(err),
},
Err(err) => {
send_err!(err);
}
}
OK
});
sleep(Duration::from_millis(700)).await;
}
});
defer! {
spawn.abort();
}
recv.recv().await?
}
About
This project is an open-source component of i18n.site ⋅ Internationalization Solution.
关于
本项目为 i18n.site ⋅ 国际化解决方案 的开源组件。