use libc::msghdr;
use s2n_quic_core::{ensure, inet::ExplicitCongestionNotification};
use s2n_quic_platform::{features, message::cmsg};
pub use cmsg::*;
pub const ENCODER_LEN: usize = {
128
};
pub const DECODER_LEN: usize = {
128
};
pub const MAX_GRO_SEGMENTS: usize = features::gro::MAX_SEGMENTS;
#[derive(Debug, Default, PartialEq, Eq)]
pub struct Receiver {
ecn: ExplicitCongestionNotification,
segment_len: u16,
}
impl Receiver {
#[inline]
pub fn with_msg(&mut self, msg: &msghdr) {
self.segment_len = 0;
ensure!(!msg.msg_control.is_null());
ensure!(msg.msg_controllen > 0);
let iter = unsafe {
cmsg::decode::Iter::from_msghdr(msg)
};
for (cmsg, value) in iter {
match (cmsg.cmsg_level, cmsg.cmsg_type) {
(level, ty) if features::tos::is_match(level, ty) => {
if let Some(ecn) = features::tos::decode(value) {
let ecn = {
let ecn = ecn as u8;
ExplicitCongestionNotification::new(ecn)
};
self.ecn = ecn;
} else {
continue;
}
}
(level, ty) if features::gso::is_match(level, ty) => {
continue;
}
(level, ty) if features::gro::is_match(level, ty) => {
if let Some(segment_size) =
unsafe { cmsg::decode::value_from_bytes::<features::gro::Cmsg>(value) }
{
self.segment_len = segment_size as _;
} else {
continue;
}
}
_ => {
continue;
}
}
}
}
#[inline]
pub fn ecn(&self) -> ExplicitCongestionNotification {
self.ecn
}
#[inline]
pub fn set_ecn(&mut self, ecn: ExplicitCongestionNotification) {
self.ecn = ecn;
}
#[inline]
pub fn segment_len(&self) -> u16 {
self.segment_len
}
#[inline]
pub fn set_segment_len(&mut self, len: u16) {
self.segment_len = len;
}
#[inline]
pub fn take_segment_len(&mut self) -> u16 {
core::mem::replace(&mut self.segment_len, 0)
}
}