s2n_quic_core/frame/
padding.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::frame::Tag;
5use s2n_codec::{decoder_parameterized_value, Encoder, EncoderValue};
6
7//= https://www.rfc-editor.org/rfc/rfc9000#section-19.1
8//# A PADDING frame (type=0x00) has no semantic value.  PADDING frames
9//# can be used to increase the size of a packet.  Padding can be used to
10//# increase an Initial packet to the minimum required size or to provide
11//# protection against traffic analysis for protected packets.
12
13macro_rules! padding_tag {
14    () => {
15        0x00u8
16    };
17}
18
19//= https://www.rfc-editor.org/rfc/rfc9000#section-19.1
20//# PADDING Frame {
21//#   Type (i) = 0x00,
22//# }
23
24#[derive(Copy, Clone, Debug, PartialEq, Eq)]
25pub struct Padding {
26    pub length: usize,
27}
28
29impl Padding {
30    /// The maximum padding allowed. When placed at the end of the packet
31    /// all of the remaining bytes will be consumed.
32    pub const MAX: Self = Self { length: usize::MAX };
33
34    pub const fn tag(self) -> u8 {
35        padding_tag!()
36    }
37}
38
39decoder_parameterized_value!(
40    impl<'a> Padding {
41        fn decode(_tag: Tag, buffer: Buffer) -> Result<Self> {
42            let mut length = 0;
43            while buffer
44                .peek_byte(length)
45                .map(|v| v == padding_tag!())
46                .unwrap_or(false)
47            {
48                length += 1;
49            }
50
51            let buffer = buffer.skip(length).expect("padding already verified");
52
53            // add one for tag itself - this needs to come after the skip, as the
54            // tag has already been read.
55            length += 1;
56
57            let frame = Padding { length };
58
59            Ok((frame, buffer))
60        }
61    }
62);
63
64impl EncoderValue for Padding {
65    fn encode<E: Encoder>(&self, encoder: &mut E) {
66        encoder.write_repeated(self.length, 0)
67    }
68}