use std::{
io,
net::{Ipv4Addr, SocketAddr, UdpSocket},
};
use crate::{hex::Hex, packet::decoder::MessageDecoder, Error};
use socket2::{Domain, Protocol, Socket, Type};
use crate::MDNS_BUFFER_SIZE;
pub struct SyncTap {
sock: UdpSocket,
}
impl SyncTap {
pub fn new() -> io::Result<Self> {
let sock = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?;
sock.set_reuse_address(true)?;
sock.bind(&"0.0.0.0:5353".parse::<SocketAddr>().unwrap().into())?;
let sock = UdpSocket::from(sock);
sock.join_multicast_v4(&"224.0.0.251".parse().unwrap(), &Ipv4Addr::UNSPECIFIED)?;
sock.set_multicast_loop_v4(true)?;
Ok(Self { sock })
}
pub fn listen(self) -> io::Result<()> {
loop {
let mut buf = [0; MDNS_BUFFER_SIZE];
let (len, addr) = self.sock.recv_from(&mut buf)?;
let buf = &buf[..len];
match self.process(addr, buf) {
Ok(()) => {}
Err(Error::Eof) if len == MDNS_BUFFER_SIZE => {
log::debug!("error: unexpected EOF. However, the receive buffer is filled completely; message truncation is likely");
}
Err(e) => {
log::warn!("failed to process incoming message: {:?}", e);
}
}
}
}
fn process(&self, addr: SocketAddr, msg: &[u8]) -> Result<(), Error> {
log::trace!("raw packet from {}: {} bytes {}", addr, msg.len(), Hex(msg));
let msg = MessageDecoder::new(msg)?;
msg.format(|args| log::debug!("{}", args))
}
}