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
112
113
114
115
116
117
118
119
120
121
122
123
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#[macro_use]
extern crate lazy_static;
use std::{
io,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket},
time::Duration,
};
use simple_dns::SimpleDnsError;
use socket2::{Domain, Protocol, SockAddr, Socket, Type};
use thiserror::Error;
pub mod conversion_utils;
mod dns_packet_receiver;
mod oneshot_resolver;
mod resource_record_manager;
mod service_discovery;
mod simple_responder;
pub use oneshot_resolver::OneShotMdnsResolver;
pub use service_discovery::{InstanceInformation, ServiceDiscovery};
pub use simple_responder::SimpleMdnsResponder;
const UNICAST_RESPONSE: bool = cfg!(not(test));
const MULTICAST_PORT: u16 = 5353;
const MULTICAST_ADDR_IPV4: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251);
const MULTICAST_ADDR_IPV6: Ipv6Addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0xFB);
lazy_static! {
pub(crate) static ref MULTICAST_IPV4_SOCKET: SocketAddr =
SocketAddr::new(IpAddr::V4(MULTICAST_ADDR_IPV4), MULTICAST_PORT);
pub(crate) static ref MULTICAST_IPV6_SOCKET: SocketAddr =
SocketAddr::new(IpAddr::V6(MULTICAST_ADDR_IPV6), MULTICAST_PORT);
}
#[derive(Debug, Error)]
pub enum SimpleMdnsError {
#[error("There was an error related to UDP socket")]
UdpSocketError(#[from] std::io::Error),
#[error("Failed to parse dns packet")]
DnsParsing(#[from] SimpleDnsError),
}
fn create_socket(addr: &SocketAddr) -> io::Result<Socket> {
let domain = if addr.is_ipv4() {
Domain::IPV4
} else {
Domain::IPV6
};
let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))?;
socket.set_read_timeout(Some(Duration::from_millis(100)))?;
socket.set_reuse_address(true)?;
#[cfg(not(windows))]
socket.set_reuse_port(true)?;
Ok(socket)
}
fn join_multicast(addr: &SocketAddr) -> io::Result<UdpSocket> {
let ip_addr = addr.ip();
let socket = create_socket(addr)?;
match ip_addr {
IpAddr::V4(ref mdns_v4) => {
socket.join_multicast_v4(mdns_v4, &Ipv4Addr::UNSPECIFIED)?;
}
IpAddr::V6(ref mdns_v6) => {
socket.join_multicast_v6(mdns_v6, 0)?;
socket.set_only_v6(true)?;
}
};
let socket = bind_multicast(socket, addr)?;
Ok(socket.into())
}
#[cfg(unix)]
fn bind_multicast(socket: Socket, addr: &SocketAddr) -> io::Result<Socket> {
socket.bind(&SockAddr::from(*addr))?;
Ok(socket)
}
#[cfg(windows)]
fn bind_multicast(socket: Socket, addr: &SocketAddr) -> io::Result<Socket> {
let addr = match addr {
SocketAddr::V4(addr) => {
SockAddr::from(SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), addr.port()))
}
SocketAddr::V6(addr) => {
SockAddr::from(SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), addr.port()))
}
};
socket.bind(&addr)?;
Ok(socket)
}
fn sender_socket(addr: &SocketAddr) -> io::Result<UdpSocket> {
let socket = create_socket(addr)?;
if addr.is_ipv4() {
socket.bind(&SockAddr::from(SocketAddr::new(
Ipv4Addr::UNSPECIFIED.into(),
0,
)))?;
} else {
socket.bind(&SockAddr::from(SocketAddr::new(
Ipv6Addr::UNSPECIFIED.into(),
0,
)))?;
}
Ok(socket.into())
}