1use libc::msghdr;
5use s2n_quic_core::{ensure, inet::ExplicitCongestionNotification};
6use s2n_quic_platform::{features, message::cmsg};
7
8pub use cmsg::*;
9
10pub const ENCODER_LEN: usize = {
11 128
13};
14
15pub const DECODER_LEN: usize = {
16 128
18};
19
20pub const MAX_GRO_SEGMENTS: usize = features::gro::MAX_SEGMENTS;
21
22#[derive(Debug, Default, PartialEq, Eq)]
23pub struct Receiver {
24 ecn: ExplicitCongestionNotification,
25 segment_len: u16,
26}
27
28impl Receiver {
29 #[inline]
30 pub fn with_msg(&mut self, msg: &msghdr) {
31 self.segment_len = 0;
33
34 ensure!(!msg.msg_control.is_null());
35 ensure!(msg.msg_controllen > 0);
36
37 let iter = unsafe {
38 cmsg::decode::Iter::from_msghdr(msg)
40 };
41
42 for (cmsg, value) in iter {
43 match (cmsg.cmsg_level, cmsg.cmsg_type) {
44 (level, ty) if features::tos::is_match(level, ty) => {
45 if let Some(ecn) = features::tos::decode(value) {
46 self.ecn = ecn;
47 } else {
48 continue;
49 }
50 }
51 (level, ty) if features::gso::is_match(level, ty) => {
52 continue;
54 }
55 (level, ty) if features::gro::is_match(level, ty) => {
56 if let Some(segment_size) =
57 unsafe { cmsg::decode::value_from_bytes::<features::gro::Cmsg>(value) }
58 {
59 self.segment_len = segment_size as _;
60 } else {
61 continue;
62 }
63 }
64 _ => {
65 continue;
66 }
67 }
68 }
69 }
70
71 #[inline]
72 pub fn ecn(&self) -> ExplicitCongestionNotification {
73 self.ecn
74 }
75
76 #[inline]
77 pub fn set_ecn(&mut self, ecn: ExplicitCongestionNotification) {
78 self.ecn = ecn;
79 }
80
81 #[inline]
82 pub fn segment_len(&self) -> u16 {
83 self.segment_len
84 }
85
86 #[inline]
87 pub fn set_segment_len(&mut self, len: u16) {
88 self.segment_len = len;
89 }
90
91 #[inline]
92 pub fn take_segment_len(&mut self) -> u16 {
93 core::mem::replace(&mut self.segment_len, 0)
94 }
95}