mirror of
https://github.com/n0-computer/noq.git
synced 2026-09-17 00:35:20 +00:00
refactor(quinn-udp): extract ControlMetadata helper
This commit is contained in:
committed by
Dirkjan Ochtman
parent
42de9dd2be
commit
4742a70e33
+40
-24
@@ -707,17 +707,42 @@ fn decode_recv<M: cmsg::MsgHdr<ControlMessage = libc::cmsghdr>>(
|
||||
len: usize,
|
||||
) -> io::Result<RecvMeta> {
|
||||
let name = unsafe { name.assume_init() };
|
||||
let mut ecn_bits = 0;
|
||||
let mut dst_ip = None;
|
||||
let mut interface_index = None;
|
||||
#[allow(unused_mut)] // only mutable on Linux
|
||||
let mut stride = len;
|
||||
let mut ctrl = ControlMetadata {
|
||||
ecn_bits: 0,
|
||||
dst_ip: None,
|
||||
interface_index: None,
|
||||
stride: len,
|
||||
};
|
||||
|
||||
let cmsg_iter = unsafe { cmsg::Iter::new(hdr) };
|
||||
for cmsg in cmsg_iter {
|
||||
ctrl.decode(cmsg);
|
||||
}
|
||||
|
||||
Ok(RecvMeta {
|
||||
len,
|
||||
stride: ctrl.stride,
|
||||
addr: decode_socket_addr(&name)?,
|
||||
ecn: EcnCodepoint::from_bits(ctrl.ecn_bits),
|
||||
dst_ip: ctrl.dst_ip,
|
||||
interface_index: ctrl.interface_index,
|
||||
})
|
||||
}
|
||||
|
||||
/// Metadata decoded from control messages
|
||||
struct ControlMetadata {
|
||||
ecn_bits: u8,
|
||||
dst_ip: Option<IpAddr>,
|
||||
interface_index: Option<u32>,
|
||||
stride: usize,
|
||||
}
|
||||
|
||||
impl ControlMetadata {
|
||||
/// Decodes a control message and updates the metadata state
|
||||
fn decode(&mut self, cmsg: &libc::cmsghdr) {
|
||||
match (cmsg.cmsg_level, cmsg.cmsg_type) {
|
||||
(libc::IPPROTO_IP, libc::IP_TOS) => unsafe {
|
||||
ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg);
|
||||
self.ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg);
|
||||
},
|
||||
// FreeBSD uses IP_RECVTOS here, and we can be liberal because cmsgs are opt-in.
|
||||
#[cfg(not(any(
|
||||
@@ -727,7 +752,7 @@ fn decode_recv<M: cmsg::MsgHdr<ControlMessage = libc::cmsghdr>>(
|
||||
solarish
|
||||
)))]
|
||||
(libc::IPPROTO_IP, libc::IP_RECVTOS) => unsafe {
|
||||
ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg);
|
||||
self.ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg);
|
||||
},
|
||||
(libc::IPPROTO_IPV6, libc::IPV6_TCLASS) => unsafe {
|
||||
// Temporary hack around broken macos ABI. Remove once upstream fixes it.
|
||||
@@ -736,45 +761,36 @@ fn decode_recv<M: cmsg::MsgHdr<ControlMessage = libc::cmsghdr>>(
|
||||
if cfg!(apple)
|
||||
&& cmsg.cmsg_len as usize == libc::CMSG_LEN(mem::size_of::<u8>() as _) as usize
|
||||
{
|
||||
ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg);
|
||||
self.ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg);
|
||||
} else {
|
||||
ecn_bits = cmsg::decode::<libc::c_int, libc::cmsghdr>(cmsg) as u8;
|
||||
self.ecn_bits = cmsg::decode::<libc::c_int, libc::cmsghdr>(cmsg) as u8;
|
||||
}
|
||||
},
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
(libc::IPPROTO_IP, libc::IP_PKTINFO) => {
|
||||
let pktinfo = unsafe { cmsg::decode::<libc::in_pktinfo, libc::cmsghdr>(cmsg) };
|
||||
dst_ip = Some(IpAddr::V4(Ipv4Addr::from(
|
||||
self.dst_ip = Some(IpAddr::V4(Ipv4Addr::from(
|
||||
pktinfo.ipi_addr.s_addr.to_ne_bytes(),
|
||||
)));
|
||||
interface_index = Some(pktinfo.ipi_ifindex as u32);
|
||||
self.interface_index = Some(pktinfo.ipi_ifindex as u32);
|
||||
}
|
||||
#[cfg(any(bsd, apple))]
|
||||
(libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
|
||||
let in_addr = unsafe { cmsg::decode::<libc::in_addr, libc::cmsghdr>(cmsg) };
|
||||
dst_ip = Some(IpAddr::V4(Ipv4Addr::from(in_addr.s_addr.to_ne_bytes())));
|
||||
self.dst_ip = Some(IpAddr::V4(Ipv4Addr::from(in_addr.s_addr.to_ne_bytes())));
|
||||
}
|
||||
(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
|
||||
let pktinfo = unsafe { cmsg::decode::<libc::in6_pktinfo, libc::cmsghdr>(cmsg) };
|
||||
dst_ip = Some(IpAddr::V6(Ipv6Addr::from(pktinfo.ipi6_addr.s6_addr)));
|
||||
interface_index = Some(pktinfo.ipi6_ifindex as u32);
|
||||
self.dst_ip = Some(IpAddr::V6(Ipv6Addr::from(pktinfo.ipi6_addr.s6_addr)));
|
||||
self.interface_index = Some(pktinfo.ipi6_ifindex as u32);
|
||||
}
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
(libc::SOL_UDP, libc::UDP_GRO) => unsafe {
|
||||
stride = cmsg::decode::<libc::c_int, libc::cmsghdr>(cmsg) as usize;
|
||||
self.stride = cmsg::decode::<libc::c_int, libc::cmsghdr>(cmsg) as usize;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(RecvMeta {
|
||||
len,
|
||||
stride,
|
||||
addr: decode_socket_addr(&name)?,
|
||||
ecn: EcnCodepoint::from_bits(ecn_bits),
|
||||
dst_ip,
|
||||
interface_index,
|
||||
})
|
||||
}
|
||||
|
||||
/// Decodes a `sockaddr_storage` into a `SocketAddr`
|
||||
|
||||
Reference in New Issue
Block a user