1use std::fmt;
2use std::marker::PhantomData;
3use std::os::raw::{c_int, c_uchar, c_void};
4use std::ptr;
5use std::slice;
6
7use crate::error::{Error, Result};
8use crate::panic;
9use crate::utils::hostname_as_str;
10
11#[derive(Debug)]
13pub struct SOAResult {
14 soa_reply: *mut c_ares_sys::ares_soa_reply,
15 phantom: PhantomData<c_ares_sys::ares_soa_reply>,
16}
17
18impl SOAResult {
19 pub fn parse_from(data: &[u8]) -> Result<SOAResult> {
21 let mut soa_reply: *mut c_ares_sys::ares_soa_reply = ptr::null_mut();
22 let parse_status = unsafe {
23 c_ares_sys::ares_parse_soa_reply(data.as_ptr(), data.len() as c_int, &mut soa_reply)
24 };
25 if parse_status == c_ares_sys::ares_status_t::ARES_SUCCESS as i32 {
26 let result = SOAResult::new(soa_reply);
27 Ok(result)
28 } else {
29 Err(Error::from(parse_status))
30 }
31 }
32
33 fn new(soa_reply: *mut c_ares_sys::ares_soa_reply) -> Self {
34 SOAResult {
35 soa_reply,
36 phantom: PhantomData,
37 }
38 }
39
40 pub fn name_server(&self) -> &str {
42 unsafe { hostname_as_str((*self.soa_reply).nsname) }
43 }
44
45 pub fn hostmaster(&self) -> &str {
47 unsafe { hostname_as_str((*self.soa_reply).hostmaster) }
48 }
49
50 pub fn serial(&self) -> u32 {
52 unsafe { (*self.soa_reply).serial }
53 }
54
55 pub fn refresh(&self) -> u32 {
57 unsafe { (*self.soa_reply).refresh }
58 }
59
60 pub fn retry(&self) -> u32 {
62 unsafe { (*self.soa_reply).retry }
63 }
64
65 pub fn expire(&self) -> u32 {
67 unsafe { (*self.soa_reply).expire }
68 }
69
70 pub fn min_ttl(&self) -> u32 {
72 unsafe { (*self.soa_reply).minttl }
73 }
74}
75
76impl fmt::Display for SOAResult {
77 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
78 write!(fmt, "Name server: {}, ", self.name_server())?;
79 write!(fmt, "Hostmaster: {}, ", self.hostmaster())?;
80 write!(fmt, "Serial: {}, ", self.serial())?;
81 write!(fmt, "Refresh: {}, ", self.refresh())?;
82 write!(fmt, "Retry: {}, ", self.retry())?;
83 write!(fmt, "Expire: {}, ", self.expire())?;
84 write!(fmt, "Minimum time-to-live: {}", self.min_ttl())
85 }
86}
87
88impl Drop for SOAResult {
89 fn drop(&mut self) {
90 unsafe { c_ares_sys::ares_free_data(self.soa_reply.cast()) }
91 }
92}
93
94unsafe impl Send for SOAResult {}
95unsafe impl Sync for SOAResult {}
96
97pub(crate) unsafe extern "C" fn query_soa_callback<F>(
98 arg: *mut c_void,
99 status: c_int,
100 _timeouts: c_int,
101 abuf: *mut c_uchar,
102 alen: c_int,
103) where
104 F: FnOnce(Result<SOAResult>) + Send + 'static,
105{
106 ares_callback!(arg.cast::<F>(), status, abuf, alen, SOAResult::parse_from);
107}