c_ares/
soa.rs

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/// The result of a successful SOA lookup.
12#[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    /// Obtain an `SOAResult` from the response to an SOA lookup.
20    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    /// Returns the name server from this `SOAResult`.
41    pub fn name_server(&self) -> &str {
42        unsafe { hostname_as_str((*self.soa_reply).nsname) }
43    }
44
45    /// Returns the hostmaster from this `SOAResult`.
46    pub fn hostmaster(&self) -> &str {
47        unsafe { hostname_as_str((*self.soa_reply).hostmaster) }
48    }
49
50    /// Returns the serial number from this `SOAResult`.
51    pub fn serial(&self) -> u32 {
52        unsafe { (*self.soa_reply).serial }
53    }
54
55    /// Returns the refresh time from this `SOAResult`.
56    pub fn refresh(&self) -> u32 {
57        unsafe { (*self.soa_reply).refresh }
58    }
59
60    /// Returns the retry time from this `SOAResult`.
61    pub fn retry(&self) -> u32 {
62        unsafe { (*self.soa_reply).retry }
63    }
64
65    /// Returns the expire time from this `SOAResult`.
66    pub fn expire(&self) -> u32 {
67        unsafe { (*self.soa_reply).expire }
68    }
69
70    /// Returns the minimum time-to-live from this `SOAResult`.
71    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}