Skip to content

Instantly share code, notes, and snippets.

@pusateri
Created September 4, 2018 12:27
Show Gist options
  • Save pusateri/df98511b88e9000f388d344a1f3db9e7 to your computer and use it in GitHub Desktop.
Save pusateri/df98511b88e9000f388d344a1f3db9e7 to your computer and use it in GitHub Desktop.
Join a multicast group using Rust with reuse addr & port
#[cfg(unix)]
fn bind_multicast(socket: &Socket, addr: &SocketAddr) -> io::Result<()> {
socket.bind(&socket2::SockAddr::from(*addr))
}
/// Returns a socket joined to the multicast address
fn join_multicast(
multicast_addr: &SocketAddr,
) -> Result<Option<std::net::UdpSocket>, io::Error> {
let ip_addr = multicast_addr.ip();
if !ip_addr.is_multicast() {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("expected multicast address for binding: {}", ip_addr),
));
}
let socket = match ip_addr {
IpAddr::V4(ref mdns_v4) => {
let socket = Socket::new(
Domain::ipv4(),
Type::dgram(),
Some(Protocol::udp()),
).expect("ipv4 dgram socket");
socket.join_multicast_v4(mdns_v4, &Ipv4Addr::new(0, 0, 0, 0)).expect("join_multicast_v4");
socket
}
IpAddr::V6(ref mdns_v6) => {
let socket = Socket::new(
Domain::ipv6(),
Type::dgram(),
Some(Protocol::udp()),
).expect("ipv6 dgram socket");
socket.set_only_v6(true)?;
socket.join_multicast_v6(mdns_v6, 0).expect("join_multicast_v6");
socket
}
};
socket.set_nonblocking(true).expect("nonblocking Error");
socket.set_reuse_address(true).expect("reuse addr Error");
#[cfg(unix)] // this is currently restricted to Unix's in socket2
socket.set_reuse_port(true).expect("reuse port Error");
bind_multicast(&socket, &multicast_addr).expect("bind Error");
Ok(Some(socket.into_udp_socket()))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment