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
use std::{
net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
time::Duration,
};
use crate::{error::LunaticError, host_api};
#[derive(Debug)]
pub struct SocketAddrIterator {
id: u64,
}
impl SocketAddrIterator {
pub(crate) fn from(id: u64) -> Self {
Self { id }
}
}
impl Drop for SocketAddrIterator {
fn drop(&mut self) {
unsafe {
host_api::networking::drop_dns_iterator(self.id);
}
}
}
impl Iterator for SocketAddrIterator {
type Item = SocketAddr;
fn next(&mut self) -> Option<Self::Item> {
let mut addr_type: u32 = 0;
let mut addr: [u8; 16] = [0; 16];
let mut port: u16 = 0;
let mut flowinfo: u32 = 0;
let mut scope_id: u32 = 0;
let next = unsafe {
host_api::networking::resolve_next(
self.id,
&mut addr_type as *mut u32,
addr.as_mut_ptr(),
&mut port as *mut u16,
&mut flowinfo as *mut u32,
&mut scope_id as *mut u32,
)
};
if next == 0 {
match addr_type {
4 => {
let ip = Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3]);
let socket_addr = SocketAddrV4::new(ip, port);
Some(socket_addr.into())
}
6 => {
let ip = Ipv6Addr::from(addr);
let socket_addr = SocketAddrV6::new(ip, port, flowinfo, scope_id);
Some(socket_addr.into())
}
_ => unreachable!("A socket address can only be v4 or v6"),
}
} else {
None
}
}
}
pub fn resolve(name: &str) -> Result<SocketAddrIterator, LunaticError> {
resolve_timeout_(name, None)
}
pub fn resolve_timeout(name: &str, timeout: Duration) -> Result<SocketAddrIterator, LunaticError> {
resolve_timeout_(name, Some(timeout))
}
fn resolve_timeout_(
name: &str,
timeout: Option<Duration>,
) -> Result<SocketAddrIterator, LunaticError> {
let mut dns_iter_or_error_id: u64 = 0;
let timeout_ms = match timeout {
Some(timeout) => match timeout.as_millis() {
0 => 1,
other => other as u32,
},
None => 0,
};
let result = unsafe {
host_api::networking::resolve(
name.as_ptr(),
name.len(),
timeout_ms,
&mut dns_iter_or_error_id as *mut u64,
)
};
if result != 0 {
Err(LunaticError::from(dns_iter_or_error_id))
} else {
Ok(SocketAddrIterator {
id: dns_iter_or_error_id,
})
}
}