1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::fmt;
use std::mem;
use std::net::Ipv4Addr;
use std::os::raw::{
c_int,
c_uchar,
c_void,
};
use std::ptr;
use std::slice;
use c_ares_sys;
use itertools::Itertools;
use error::{
Error,
Result,
};
use panic;
use types::MAX_ADDRTTLS;
use utils:: ipv4_from_in_addr;
#[derive(Clone, Copy)]
pub struct AResults {
naddrttls: usize,
addrttls: [c_ares_sys::ares_addrttl; MAX_ADDRTTLS],
}
#[derive(Clone, Copy)]
pub struct AResult<'a> {
addrttl: &'a c_ares_sys::ares_addrttl,
}
impl AResults {
pub fn parse_from(data: &[u8]) -> Result<AResults> {
let mut results: AResults = AResults {
naddrttls: MAX_ADDRTTLS,
addrttls: unsafe { mem::uninitialized() },
};
let parse_status = unsafe {
c_ares_sys::ares_parse_a_reply(
data.as_ptr(),
data.len() as c_int,
ptr::null_mut(),
results.addrttls.as_mut_ptr(),
&mut results.naddrttls as *mut _ as *mut c_int)
};
if parse_status == c_ares_sys::ARES_SUCCESS {
Ok(results)
} else {
Err(Error::from(parse_status))
}
}
pub fn iter(&self) -> AResultsIter {
AResultsIter { addrttls: self.addrttls[0 .. self.naddrttls].iter() }
}
}
impl fmt::Display for AResults {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let results = self.iter().format("}, {");
write!(fmt, "[{{{}}}]", results)?;
Ok(())
}
}
#[derive(Clone)]
pub struct AResultsIter<'a> {
addrttls: slice::Iter<'a, c_ares_sys::ares_addrttl>,
}
impl<'a> Iterator for AResultsIter<'a> {
type Item = AResult<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.addrttls.next().map(|addrttl| AResult { addrttl: addrttl })
}
}
impl<'a> IntoIterator for &'a AResults {
type Item = AResult<'a>;
type IntoIter = AResultsIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> AResult<'a> {
pub fn ipv4(&self) -> Ipv4Addr {
ipv4_from_in_addr(&self.addrttl.ipaddr)
}
pub fn ttl(&self) -> i32 {
self.addrttl.ttl as i32
}
}
impl<'a> fmt::Display for AResult<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "IPv4: {}, ", self.ipv4())?;
write!(fmt, "TTL: {}", self.ttl())?;
Ok(())
}
}
pub unsafe extern "C" fn query_a_callback<F>(
arg: *mut c_void,
status: c_int,
_timeouts: c_int,
abuf: *mut c_uchar,
alen: c_int)
where F: FnOnce(Result<AResults>) + Send + 'static {
panic::catch(|| {
let result = if status == c_ares_sys::ARES_SUCCESS {
let data = slice::from_raw_parts(abuf, alen as usize);
AResults::parse_from(data)
} else {
Err(Error::from(status))
};
let handler = Box::from_raw(arg as *mut F);
handler(result);
});
}