1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3mod dot;
4mod error;
5
6use std::net::{IpAddr, Ipv4Addr};
7
8pub use dot::Dot;
9pub use error::{Error, Result};
10use hipstr::HipStr;
11use idns::Answer;
12pub use idns::QType;
13
14#[derive(Debug, Clone)]
16pub struct HostIp {
17 pub host: HipStr<'static>,
18 pub ip: IpAddr,
19}
20
21impl idns::Query for Dot {
22 type Error = Error;
23
24 async fn answer_li(&self, qtype: QType, name: &str) -> Result<Option<Vec<Answer>>> {
25 self.query(name, qtype).await
26 }
27}
28
29pub const fn host_ip(host: &'static str, a: u8, b: u8, c: u8, d: u8) -> HostIp {
31 HostIp {
32 host: HipStr::borrowed(host),
33 ip: IpAddr::V4(Ipv4Addr::new(a, b, c, d)),
34 }
35}
36
37pub mod dns {
39 pub const CLOUDFLARE: &str = "cloudflare-dns.com";
40 pub const GOOGLE: &str = "dns.google";
41 pub const QUAD9: &str = "dns.quad9.net";
42 pub const DNS360: &str = "dot.360.cn";
44 pub const TWNIC: &str = "101.101.101.101";
46 pub const IIJ: &str = "public.dns.iij.jp";
48 pub const ALIDNS: &str = "dns.alidns.com";
50 pub const DNSPOD: &str = "dot.pub";
52}
53
54pub fn dot_li(li: &[HostIp]) -> Vec<Dot> {
56 li.iter().map(|s| Dot::new(s.clone())).collect()
57}
58
59pub const DOT_LI: &[HostIp] = &[
61 host_ip(dns::CLOUDFLARE, 1, 1, 1, 1),
62 host_ip(dns::CLOUDFLARE, 1, 0, 0, 1),
63 host_ip(dns::GOOGLE, 8, 8, 8, 8),
64 host_ip(dns::GOOGLE, 8, 8, 4, 4),
65 host_ip(dns::QUAD9, 9, 9, 9, 9),
66 host_ip(dns::DNS360, 101, 226, 4, 6),
68 host_ip(dns::DNS360, 218, 30, 118, 6),
69 host_ip(dns::TWNIC, 101, 101, 101, 101),
71 host_ip(dns::IIJ, 103, 2, 57, 5),
73 ];
80
81#[cfg(feature = "static")]
82#[static_init::dynamic(lazy)]
83pub static DOT: idns::DnsRace<Dot> = idns::DnsRace::new(dot_li(DOT_LI));