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}