Skip to main content

s2n_quic_dc/msg/
cmsg.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use 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    // TODO calculate based on platform support
12    128
13};
14
15pub const DECODER_LEN: usize = {
16    // TODO calculate based on platform support
17    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        // assume we didn't get a GRO cmsg initially
32        self.segment_len = 0;
33
34        ensure!(!msg.msg_control.is_null());
35        ensure!(msg.msg_controllen > 0);
36
37        let iter = unsafe {
38            // SAFETY: the msghdr controllen should be aligned
39            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                    // ignore GSO settings when reading
53                    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}