use std::{
io,
os::raw::{
c_char,
c_void,
},
pin::Pin,
task::{
Context,
Poll,
},
};
use crate::{
cstr,
ffi,
inner,
interface::Interface,
};
type CallbackStream = crate::stream::ServiceStream<inner::OwnedService, EnumerateResult>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Enumerate {
BrowseDomains,
RegistrationDomains,
}
impl From<Enumerate> for ffi::DNSServiceFlags {
fn from(e: Enumerate) -> Self {
match e {
Enumerate::BrowseDomains => ffi::FLAGS_BROWSE_DOMAINS,
Enumerate::RegistrationDomains => ffi::FLAGS_REGISTRATION_DOMAINS,
}
}
}
bitflags::bitflags! {
#[derive(Default)]
pub struct EnumeratedFlags: ffi::DNSServiceFlags {
const MORE_COMING = ffi::FLAGS_MORE_COMING;
const ADD = ffi::FLAGS_ADD;
const DEFAULT = ffi::FLAGS_DEFAULT;
}
}
#[must_use = "streams do nothing unless polled"]
pub struct EnumerateDomains {
stream: crate::fused_err_stream::FusedErrorStream<CallbackStream>,
}
impl EnumerateDomains {
pin_utils::unsafe_pinned!(stream: crate::fused_err_stream::FusedErrorStream<CallbackStream>);
}
impl futures_core::Stream for EnumerateDomains {
type Item = io::Result<EnumerateResult>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.stream().poll_next(cx)
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct EnumerateResult {
pub flags: EnumeratedFlags,
pub interface: Interface,
pub domain: String,
}
unsafe extern "C" fn enumerate_callback(
_sd_ref: ffi::DNSServiceRef,
flags: ffi::DNSServiceFlags,
interface_index: u32,
error_code: ffi::DNSServiceErrorType,
reply_domain: *const c_char,
context: *mut c_void,
) {
CallbackStream::run_callback(context, error_code, || {
let reply_domain = cstr::from_cstr(reply_domain)?;
Ok(EnumerateResult {
flags: EnumeratedFlags::from_bits_truncate(flags),
interface: Interface::from_raw(interface_index),
domain: reply_domain.to_string(),
})
});
}
#[doc(alias = "DNSServiceEnumerateDomains")]
pub fn enumerate_domains(enumerate: Enumerate, interface: Interface) -> EnumerateDomains {
crate::init();
let stream = CallbackStream::new(move |sender| {
inner::OwnedService::enumerate_domains(
enumerate.into(),
interface.into_raw(),
Some(enumerate_callback),
sender,
)
})
.into();
EnumerateDomains { stream }
}