1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use futures::sync::mpsc;
use futures::{self,Async};
use std::os::raw::{c_void,c_char};
use std::io;
use tokio_core::reactor::{Handle,Remote};
use cstr;
use error::Error;
use evented::EventedDNSService;
use ffi;
use interface::Interface;
use raw;
use remote::GetRemote;
use stream::ServiceStream;
pub struct Resolve(ServiceStream<ResolveResult>);
impl futures::Stream for Resolve {
type Item = ResolveResult;
type Error = io::Error;
fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
self.0.poll()
}
}
impl GetRemote for Resolve {
fn remote(&self) -> &Remote {
self.0.remote()
}
}
#[derive(Clone,PartialEq,Eq,PartialOrd,Ord,Hash,Debug)]
pub struct ResolveResult{
pub interface: Interface,
pub fullname: String,
pub host_target: String,
pub port: u16,
pub txt: Vec<u8>,
}
extern "C" fn resolve_callback(
_sd_ref: ffi::DNSServiceRef,
_flags: ffi::DNSServiceFlags,
interface_index: u32,
error_code: ffi::DNSServiceErrorType,
fullname: *const c_char,
host_target: *const c_char,
port: u16,
txt_len: u16,
txt_record: *const u8,
context: *mut c_void
) {
let sender = context as *mut mpsc::UnboundedSender<io::Result<ResolveResult>>;
let sender : &mpsc::UnboundedSender<io::Result<ResolveResult>> = unsafe { &*sender };
let data = Error::from(error_code).map_err(io::Error::from).and_then(|_| {
let fullname = unsafe { cstr::from_cstr(fullname) }?;
let host_target = unsafe { cstr::from_cstr(host_target) }?;
let txt = unsafe { ::std::slice::from_raw_parts(txt_record, txt_len as usize) };
Ok(ResolveResult{
interface: Interface::from_raw(interface_index),
fullname: fullname.to_string(),
host_target: host_target.to_string(),
port: u16::from_be(port),
txt: txt.into(),
})
});
sender.send(data).unwrap();
}
pub fn resolve(
interface: Interface,
name: &str,
reg_type: &str,
domain: &str,
handle: &Handle
) -> io::Result<Resolve> {
let name = cstr::CStr::from(&name)?;
let reg_type = cstr::CStr::from(®_type)?;
let domain = cstr::CStr::from(&domain)?;
Ok(Resolve(ServiceStream::new(move |sender|
EventedDNSService::new(
raw::DNSService::resolve(
0,
interface.into_raw(),
&name,
®_type,
&domain,
Some(resolve_callback),
sender as *mut c_void,
)?,
handle
)
)?))
}