async_dnssd/service/
enumerate_domains.rs

1use std::{
2	io,
3	os::raw::{
4		c_char,
5		c_void,
6	},
7	pin::Pin,
8	task::{
9		Context,
10		Poll,
11	},
12};
13
14use crate::{
15	cstr,
16	ffi,
17	inner,
18	interface::Interface,
19};
20
21type CallbackStream = crate::stream::ServiceStream<inner::OwnedService, EnumerateResult>;
22
23/// Whether to enumerate domains which are browsed or domains for which
24/// registrations can be made.
25#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
26pub enum Enumerate {
27	/// enumerate domains which can be browsed
28	BrowseDomains,
29	/// enumerate domains to register services/records on
30	RegistrationDomains,
31}
32
33impl From<Enumerate> for ffi::DNSServiceFlags {
34	fn from(e: Enumerate) -> Self {
35		match e {
36			Enumerate::BrowseDomains => ffi::FLAGS_BROWSE_DOMAINS,
37			Enumerate::RegistrationDomains => ffi::FLAGS_REGISTRATION_DOMAINS,
38		}
39	}
40}
41
42bitflags::bitflags! {
43	/// Flags for [`EnumerateDomains`](struct.EnumerateDomains.html)
44	#[derive(Default)]
45	pub struct EnumeratedFlags: ffi::DNSServiceFlags {
46		/// Indicates at least one more result is pending in the queue.  If
47		/// not set there still might be more results coming in the future.
48		///
49		/// See [`kDNSServiceFlagsMoreComing`](https://developer.apple.com/documentation/dnssd/1823436-anonymous/kdnsserviceflagsmorecoming).
50		const MORE_COMING = ffi::FLAGS_MORE_COMING;
51
52		/// Indicates the result is new.  If not set indicates the result
53		/// was removed.
54		///
55		/// See [`kDNSServiceFlagsAdd`](https://developer.apple.com/documentation/dnssd/1823436-anonymous/kdnsserviceflagsadd).
56		const ADD = ffi::FLAGS_ADD;
57
58		/// Indicates this is the default domain to search (always combined with `Add`).
59		///
60		/// See [`kDNSServiceFlagsDefault`](https://developer.apple.com/documentation/dnssd/1823436-anonymous/kdnsserviceflagsdefault).
61		const DEFAULT = ffi::FLAGS_DEFAULT;
62	}
63}
64
65/// Pending domain enumeration
66#[must_use = "streams do nothing unless polled"]
67pub struct EnumerateDomains {
68	stream: crate::fused_err_stream::FusedErrorStream<CallbackStream>,
69}
70
71impl EnumerateDomains {
72	pin_utils::unsafe_pinned!(stream: crate::fused_err_stream::FusedErrorStream<CallbackStream>);
73}
74
75impl futures_core::Stream for EnumerateDomains {
76	type Item = io::Result<EnumerateResult>;
77
78	fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
79		self.stream().poll_next(cx)
80	}
81}
82
83/// Domain enumeration result
84///
85/// See [DNSServiceDomainEnumReply](https://developer.apple.com/documentation/dnssd/dnsservicedomainenumreply).
86#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
87pub struct EnumerateResult {
88	/// flags
89	pub flags: EnumeratedFlags,
90	/// interface domain was found on
91	pub interface: Interface,
92	/// domain name
93	pub domain: String,
94}
95
96unsafe extern "C" fn enumerate_callback(
97	_sd_ref: ffi::DNSServiceRef,
98	flags: ffi::DNSServiceFlags,
99	interface_index: u32,
100	error_code: ffi::DNSServiceErrorType,
101	reply_domain: *const c_char,
102	context: *mut c_void,
103) {
104	CallbackStream::run_callback(context, error_code, || {
105		let reply_domain = cstr::from_cstr(reply_domain)?;
106
107		Ok(EnumerateResult {
108			flags: EnumeratedFlags::from_bits_truncate(flags),
109			interface: Interface::from_raw(interface_index),
110			domain: reply_domain.to_string(),
111		})
112	});
113}
114
115/// Enumerate domains that are recommended for registration or browsing
116///
117/// See [`DNSServiceEnumerateDomains`](https://developer.apple.com/documentation/dnssd/1804754-dnsserviceenumeratedomains).
118#[doc(alias = "DNSServiceEnumerateDomains")]
119pub fn enumerate_domains(enumerate: Enumerate, interface: Interface) -> EnumerateDomains {
120	crate::init();
121
122	let stream = CallbackStream::new(move |sender| {
123		inner::OwnedService::enumerate_domains(
124			enumerate.into(),
125			interface.into_raw(),
126			Some(enumerate_callback),
127			sender,
128		)
129	})
130	.into();
131
132	EnumerateDomains { stream }
133}