1extern crate libc;
2
3use std::ptr::null;
4use std::ptr::null_mut;
5use std::ffi::CString;
6
7mod ffi {
8 use libc::c_void;
9 use libc::c_char;
10
11 pub enum DNSService {}
12 pub type DNSServiceRef = *mut DNSService;
13
14 #[repr(i32)]
15 #[allow(dead_code)]
16 #[derive(Copy,Clone,Debug,PartialEq,Eq)]
17 pub enum DNSServiceErrorType {
18 NoError = 0,
19 Unknown = -65537,
20 NoSuchName = -65538,
21 NoMemory = -65539,
22 BadParam = -65540,
23 BadReference = -65541,
24 BadState = -65542,
25 BadFlags = -65543,
26 Unsupported = -65544,
27 NotInitialized = -65545,
28 AlreadyRegistered = -65547,
29 NameConflict = -65548,
30 Invalid = -65549,
31 Firewall = -65550,
32 Incompatible = -65551,
33 BadInterfaceIndex = -65552,
34 Refused = -65553,
35 NoSuchRecord = -65554,
36 NoAuth = -65555,
37 NoSuchKey = -65556,
38 NATTraversal = -65557,
39 DoubleNAT = -65558,
40 BadTime = -65559,
41 BadSig = -65560,
42 BadKey = -65561,
43 Transient = -65562,
44 ServiceNotRunning = -65563,
45 NATPortMappingUnsupported = -65564,
46 NATPortMappingDisabled = -65565,
47 NoRouter = -65566,
48 PollingMode = -65567,
49 Timeout = -65568,
50 }
51
52 pub type DNSServiceFlags = u32;
53 pub type DNSServiceRegisterReply = Option<extern "C" fn(DNSServiceRef,
54 DNSServiceFlags,
55 DNSServiceErrorType,
56 *const c_char,
57 *const c_char,
58 *const c_char,
59 *mut c_void)
60 >;
61
62 extern "C" {
63 pub fn DNSServiceRegister(sdRef: *mut DNSServiceRef,
64 flags: DNSServiceFlags,
65 interfaceIndex: u32,
66 name: *const c_char,
67 regtype: *const c_char,
68 domain: *const c_char,
69 host: *const c_char,
70 port: u16,
71 txtLen: u16,
72 txtRecord: *const u8,
73 callBack: DNSServiceRegisterReply,
74 context: *mut c_void)
75 -> DNSServiceErrorType;
76
77 pub fn DNSServiceRefDeallocate(sdRef: DNSServiceRef);
78 }
79}
80
81#[derive(Debug)]
82pub struct DNSService {
83 sd_ref: ffi::DNSServiceRef,
84}
85
86#[derive(Debug)]
87pub struct DNSError(ffi::DNSServiceErrorType);
88
89impl std::fmt::Display for DNSError {
90 fn fmt(&self, format: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
91 write!(format, "DNS-SD Error: {:?}", self.0)
92 }
93}
94
95impl std::error::Error for DNSError {
96 fn description(&self) -> &str {
97 "DNS-SD Error"
98 }
99}
100
101impl DNSService {
102 pub fn register(name: Option<&str>,
103 regtype: &str,
104 domain: Option<&str>,
105 host: Option<&str>,
106 port: u16,
107 txt: &[&str])
108 -> std::result::Result<DNSService, DNSError> {
109 let mut sd_ref: ffi::DNSServiceRef = null_mut();
110
111 let txt_data: Vec<u8> = txt.into_iter()
112 .flat_map(|value| {
113 std::iter::once(value.len() as u8).chain(value.bytes())
114 })
115 .collect();
116
117 let name = name.map(|s| CString::new(s).unwrap());
118 let regtype = CString::new(regtype).unwrap();
119 let domain = domain.map(|s| CString::new(s).unwrap());
120 let host = host.map(|s| CString::new(s).unwrap());
121
122 let err = unsafe {
123 ffi::DNSServiceRegister(&mut sd_ref as *mut _,
124 0,
125 0,
126 name.as_ref().map_or(null(), |s| s.as_ptr()),
127 regtype.as_ptr(),
128 domain.as_ref().map_or(null(), |s| s.as_ptr()),
129 host.as_ref().map_or(null(), |s| s.as_ptr()),
130 port.to_be(),
131 txt_data.len() as u16,
132 if txt_data.is_empty() {
133 null()
134 } else {
135 txt_data.as_ptr()
136 },
137 None,
138 null_mut())
139 };
140
141 drop(name);
145 drop(regtype);
146 drop(domain);
147 drop(host);
148 drop(txt_data);
149
150 if err == ffi::DNSServiceErrorType::NoError {
151 Ok(DNSService { sd_ref: sd_ref })
152 } else {
153 Err(DNSError(err))
154 }
155 }
156}
157
158impl Drop for DNSService {
159 fn drop(&mut self) {
160 unsafe {
161 ffi::DNSServiceRefDeallocate(self.sd_ref);
162 }
163 }
164}