use std::net::IpAddr;
use std::sync::Arc;
use crate::common::RecordSOA;
use crate::error::*;
use crate::common::{QType, DnsRdata};
use super::query::QDns;
use super::{QuerySetup, ResolveConfig};
pub
fn resolve_fqdn<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<IpAddr>>
where C: AsRef<str>
{
let dns =
QDns
::make_a_aaaa_request(custom_resolv, fqdn.as_ref(), QuerySetup::default())?;
let res = dns.query();
let mut iplist: Vec<IpAddr> = vec![];
let recs = res.get_result()?;
for dnsr in recs.into_iter()
{
for resp in dnsr.into_iter()
{
match resp.borrow_rdata()
{
DnsRdata::A(ip) =>
iplist.push(IpAddr::from(ip.ip)),
DnsRdata::AAAA( ip ) =>
iplist.push(IpAddr::from(ip.ip)),
_ => continue,
}
}
}
return Ok(iplist);
}
pub
fn resolve_mx<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<String>>
where C: AsRef<str>
{
let mut dns_req =
QDns::make_empty(custom_resolv, QuerySetup::default())?;
dns_req.add_request(QType::MX, fqdn.as_ref());
let res = dns_req.query();
let mut mxlist: Vec<(u16, String)> = Vec::new();
let recs = res.get_result()?;
for dnsr in recs.into_iter()
{
for resp in dnsr.into_iter()
{
match resp.borrow_rdata()
{
DnsRdata::MX(mx) =>
{
let idx = mxlist.binary_search_by_key(&mx.preference, |x| x.0).map_or_else(|v| v, |f| f);
mxlist.insert(idx, (mx.preference, mx.exchange));
},
_ => continue,
}
}
}
return Ok(mxlist.into_iter().map( |(_, ip)| ip).collect());
}
pub
fn resolve_soa<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<RecordSOA>>
where C: AsRef<str>
{
let mut dns_req =
QDns::make_empty(custom_resolv, QuerySetup::default())?;
dns_req.add_request(QType::SOA, fqdn.as_ref());
let res = dns_req.query();
let mut soa_list: Vec<RecordSOA> = Vec::new();
let recs = res.get_result()?;
for dnsr in recs.into_iter()
{
for resp in dnsr.into_iter()
{
match resp.borrow_rdata()
{
DnsRdata::SOA(soa) =>
soa_list.push(soa),
_ => continue,
}
}
}
return Ok(soa_list);
}
pub
fn resolve_reverse<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<String>>
where C: AsRef<str>
{
let mut dns_req =
QDns::make_empty(custom_resolv, QuerySetup::default())?;
dns_req.add_request(QType::PTR, fqdn.as_ref());
let res = dns_req.query();
let recs = res.get_result()?;
let mut ptr_list: Vec<String> = Vec::new();
for dnsr in recs.into_iter()
{
for resp in dnsr.into_iter()
{
match resp.borrow_rdata()
{
DnsRdata::PTR(ptr) =>
ptr_list.push(ptr.fqdn),
_ => continue,
}
}
}
return Ok(ptr_list);
}
#[cfg(test)]
mod tests
{
use crate::sync::request::{resolve_fqdn, resolve_mx};
#[test]
fn test_mx_resolve()
{
let mx_doms = resolve_mx("protonmail.com", None);
assert_eq!(mx_doms.is_err(), false);
let mx_doms = mx_doms.unwrap();
let mut index = 0;
for di in mx_doms
{
match index
{
0 => assert_eq!(di.as_str(), "mail.protonmail.ch"),
1 => assert_eq!(di.as_str(), "mailsec.protonmail.ch"),
_ => panic!("test is required to be modified")
}
index += 1;
println!("{}", di);
}
}
#[test]
fn test_a_aaaa_resolve()
{
let a_aaaa = resolve_fqdn("protonmail.com", None);
assert_eq!(a_aaaa.is_ok(), true);
let a_aaaa = a_aaaa.unwrap();
for di in a_aaaa
{
println!("{}", di);
}
}
}