mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-21 05:41:33 +00:00
protocols/mdns: Add IPv6 support (#2161)
Signed-off-by: Emil Majchrzak <majchrzakemil@gitlab.com> Co-authored-by: Emil Majchrzak <majchrzakemil@gitlab.com> Co-authored-by: Max Inden <mail@max-inden.de>
This commit is contained in:
@ -18,12 +18,12 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::IPV4_MDNS_MULTICAST_ADDRESS;
|
||||
use crate::dns::{build_query, build_query_response, build_service_discovery_response};
|
||||
use crate::query::MdnsPacket;
|
||||
use async_io::{Async, Timer};
|
||||
use futures::prelude::*;
|
||||
use if_watch::{IfEvent, IfWatcher};
|
||||
use lazy_static::lazy_static;
|
||||
use libp2p_core::connection::ListenerId;
|
||||
use libp2p_core::{
|
||||
address_translation, multiaddr::Protocol, Multiaddr, PeerId,
|
||||
@ -38,18 +38,13 @@ use std::{
|
||||
cmp,
|
||||
collections::VecDeque,
|
||||
fmt, io, iter,
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket},
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket},
|
||||
pin::Pin,
|
||||
task::Context,
|
||||
task::Poll,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
static ref IPV4_MDNS_MULTICAST_ADDRESS: SocketAddr =
|
||||
SocketAddr::from((Ipv4Addr::new(224, 0, 0, 251), 5353));
|
||||
}
|
||||
|
||||
/// Configuration for mDNS.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MdnsConfig {
|
||||
@ -61,6 +56,8 @@ pub struct MdnsConfig {
|
||||
/// peer joins the network. Receiving an mdns packet resets the timer
|
||||
/// preventing unnecessary traffic.
|
||||
pub query_interval: Duration,
|
||||
/// IP address for multicast.
|
||||
pub multicast_addr: IpAddr,
|
||||
}
|
||||
|
||||
impl Default for MdnsConfig {
|
||||
@ -68,6 +65,7 @@ impl Default for MdnsConfig {
|
||||
Self {
|
||||
ttl: Duration::from_secs(6 * 60),
|
||||
query_interval: Duration::from_secs(5 * 60),
|
||||
multicast_addr: *IPV4_MDNS_MULTICAST_ADDRESS,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,24 +116,42 @@ pub struct Mdns {
|
||||
|
||||
/// Discovery timer.
|
||||
timeout: Timer,
|
||||
|
||||
// Multicast address.
|
||||
multicast_addr: IpAddr,
|
||||
}
|
||||
|
||||
impl Mdns {
|
||||
/// Builds a new `Mdns` behaviour.
|
||||
pub async fn new(config: MdnsConfig) -> io::Result<Self> {
|
||||
let recv_socket = {
|
||||
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(socket2::Protocol::UDP))?;
|
||||
socket.set_reuse_address(true)?;
|
||||
#[cfg(unix)]
|
||||
socket.set_reuse_port(true)?;
|
||||
socket.bind(&SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 5353).into())?;
|
||||
let socket = UdpSocket::from(socket);
|
||||
socket.set_multicast_loop_v4(true)?;
|
||||
socket.set_multicast_ttl_v4(255)?;
|
||||
Async::new(socket)?
|
||||
let recv_socket = match config.multicast_addr {
|
||||
IpAddr::V4(_) => {
|
||||
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(socket2::Protocol::UDP))?;
|
||||
socket.set_reuse_address(true)?;
|
||||
#[cfg(unix)]
|
||||
socket.set_reuse_port(true)?;
|
||||
socket.bind(&SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 5353).into())?;
|
||||
socket.set_multicast_loop_v4(true)?;
|
||||
socket.set_multicast_ttl_v4(255)?;
|
||||
Async::new(UdpSocket::from(socket))?
|
||||
}
|
||||
IpAddr::V6(_) => {
|
||||
let socket = Socket::new(Domain::IPV6, Type::DGRAM, Some(socket2::Protocol::UDP))?;
|
||||
socket.set_reuse_address(true)?;
|
||||
#[cfg(unix)]
|
||||
socket.set_reuse_port(true)?;
|
||||
socket.bind(&SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 5353).into())?;
|
||||
socket.set_multicast_loop_v6(true)?;
|
||||
Async::new(UdpSocket::from(socket))?
|
||||
}
|
||||
};
|
||||
let send_socket = {
|
||||
let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0))?;
|
||||
let addrs = [
|
||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
|
||||
SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0),
|
||||
];
|
||||
|
||||
let socket = std::net::UdpSocket::bind(&addrs[..])?;
|
||||
Async::new(socket)?
|
||||
};
|
||||
let if_watch = if_watch::IfWatcher::new().await?;
|
||||
@ -151,6 +167,7 @@ impl Mdns {
|
||||
query_interval: config.query_interval,
|
||||
ttl: config.ttl,
|
||||
timeout: Timer::interval(config.query_interval),
|
||||
multicast_addr: config.multicast_addr,
|
||||
})
|
||||
}
|
||||
|
||||
@ -279,20 +296,34 @@ impl NetworkBehaviour for Mdns {
|
||||
>,
|
||||
> {
|
||||
while let Poll::Ready(event) = Pin::new(&mut self.if_watch).poll(cx) {
|
||||
let multicast = From::from([224, 0, 0, 251]);
|
||||
let socket = self.recv_socket.get_ref();
|
||||
match event {
|
||||
Ok(IfEvent::Up(inet)) => {
|
||||
if inet.addr().is_loopback() {
|
||||
continue;
|
||||
}
|
||||
if let IpAddr::V4(addr) = inet.addr() {
|
||||
log::trace!("joining multicast on iface {}", addr);
|
||||
if let Err(err) = socket.join_multicast_v4(&multicast, &addr) {
|
||||
log::error!("join multicast failed: {}", err);
|
||||
} else {
|
||||
self.timeout
|
||||
.set_interval_at(Instant::now(), self.query_interval);
|
||||
match self.multicast_addr {
|
||||
IpAddr::V4(multicast) => {
|
||||
if let IpAddr::V4(addr) = inet.addr() {
|
||||
log::trace!("joining multicast on iface {}", addr);
|
||||
if let Err(err) = socket.join_multicast_v4(&multicast, &addr) {
|
||||
log::error!("join multicast failed: {}", err);
|
||||
} else {
|
||||
self.timeout
|
||||
.set_interval_at(Instant::now(), self.query_interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
IpAddr::V6(multicast) => {
|
||||
if let IpAddr::V6(addr) = inet.addr() {
|
||||
log::trace!("joining multicast on iface {}", addr);
|
||||
if let Err(err) = socket.join_multicast_v6(&multicast, 0) {
|
||||
log::error!("join multicast failed: {}", err);
|
||||
} else {
|
||||
self.timeout
|
||||
.set_interval_at(Instant::now(), self.query_interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -300,10 +331,22 @@ impl NetworkBehaviour for Mdns {
|
||||
if inet.addr().is_loopback() {
|
||||
continue;
|
||||
}
|
||||
if let IpAddr::V4(addr) = inet.addr() {
|
||||
log::trace!("leaving multicast on iface {}", addr);
|
||||
if let Err(err) = socket.leave_multicast_v4(&multicast, &addr) {
|
||||
log::error!("leave multicast failed: {}", err);
|
||||
match self.multicast_addr {
|
||||
IpAddr::V4(multicast) => {
|
||||
if let IpAddr::V4(addr) = inet.addr() {
|
||||
log::trace!("leaving multicast on iface {}", addr);
|
||||
if let Err(err) = socket.leave_multicast_v4(&multicast, &addr) {
|
||||
log::error!("leave multicast failed: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
IpAddr::V6(multicast) => {
|
||||
if let IpAddr::V6(addr) = inet.addr() {
|
||||
log::trace!("leaving multicast on iface {}", addr);
|
||||
if let Err(err) = socket.leave_multicast_v6(&multicast, 0) {
|
||||
log::error!("leave multicast failed: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,7 +375,7 @@ impl NetworkBehaviour for Mdns {
|
||||
if let Some(packet) = self.send_buffer.pop_front() {
|
||||
match self
|
||||
.send_socket
|
||||
.send_to(&packet, *IPV4_MDNS_MULTICAST_ADDRESS)
|
||||
.send_to(&packet, SocketAddr::new(self.multicast_addr, 5353))
|
||||
.now_or_never()
|
||||
{
|
||||
Some(Ok(_)) => {}
|
||||
|
Reference in New Issue
Block a user