async_dnssd/service/
mod.rs

1pub use self::{
2	browse::*,
3	connection::*,
4	enumerate_domains::*,
5	query_record::*,
6	records::Record,
7	register::*,
8	resolve::*,
9	resolve_host::*,
10};
11
12mod browse;
13mod connection;
14mod enumerate_domains;
15mod query_record;
16mod records;
17mod register;
18mod resolve;
19mod resolve_host;
20
21use crate::dns_consts::{
22	Class,
23	Type,
24};
25use std::os::raw::c_char;
26
27/// Purge record from cache
28///
29/// See [`DNSServiceReconfirmRecord`](https://developer.apple.com/documentation/dnssd/1804726-dnsservicereconfirmrecord).
30#[doc(alias = "DNSServiceReconfirmRecord")]
31pub fn reconfirm_record(
32	interface: crate::interface::Interface,
33	fullname: &str,
34	rr_type: Type,
35	rr_class: Class,
36	rdata: &[u8],
37) -> ::std::io::Result<()> {
38	crate::init();
39
40	let fullname = crate::cstr::CStr::from(&fullname)?;
41	crate::inner::reconfirm_record(
42		0, // no flags
43		interface.into_raw(),
44		&fullname,
45		rr_type,
46		rr_class,
47		rdata,
48	);
49
50	Ok(())
51}
52
53/// Full name consiting of (up to) three parts
54pub struct FullName<'a> {
55	/// (unescaped) service name (becomes single label in full name)
56	pub service: Option<&'a str>,
57	/// registration type (valid names don't need escaping)
58	pub reg_type: &'a str,
59	/// (escaped) domain name (most names don't need escaping)
60	pub domain: &'a str,
61}
62
63impl<'a> FullName<'a> {
64	/// Escape and concatenate all three parts to a full name
65	///
66	/// See [`DNSServiceConstructFullName`](https://developer.apple.com/documentation/dnssd/1804753-dnsserviceconstructfullname)
67	#[doc(alias = "DNSServiceConstructFullName")]
68	pub fn construct(&self) -> ::std::io::Result<String> {
69		use std::io;
70
71		let service = crate::cstr::NullableCStr::from(&self.service)?;
72		let reg_type = crate::cstr::CStr::from(&self.reg_type)?;
73		let domain = crate::cstr::CStr::from(&self.domain)?;
74
75		const SIZE: usize = crate::ffi::MAX_DOMAIN_NAME;
76		let mut buf: Vec<u8> = Vec::with_capacity(SIZE);
77		let result = unsafe {
78			crate::ffi::DNSServiceConstructFullName(
79				buf.as_mut_ptr() as *mut c_char,
80				service.as_ptr(),
81				reg_type.as_ptr(),
82				domain.as_ptr(),
83			)
84		};
85
86		if result != 0 {
87			// manual only mentions a single possible error (kDNSServiceErr_BadParam), so we use a static io::Error here for now
88			// TODO: convert to our normal `Error` type?
89			return Err(io::Error::new(io::ErrorKind::InvalidInput, "BadParam"));
90		}
91
92		// ensure NUL termination (MAX_DOMAIN_NAME includes space for trailing NUL, so content must fit)
93		buf.spare_capacity_mut()[SIZE - 1].write(0);
94		unsafe {
95			buf.set_len(libc::strlen(buf.as_ptr() as *const libc::c_char));
96		};
97
98		String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
99	}
100}