s2n_quic_core/frame/
mod.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4#![forbid(unsafe_code)]
5
6use crate::{
7    event,
8    frame::{ack_elicitation::AckElicitable, congestion_controlled::CongestionControlled},
9    varint::VarInt,
10};
11use core::fmt;
12use s2n_codec::{
13    DecoderBuffer, DecoderBufferMut, DecoderBufferMutResult, DecoderError,
14    DecoderParameterizedValueMut, DecoderValueMut, Encoder, EncoderValue,
15};
16
17pub mod ack_elicitation;
18pub mod congestion_controlled;
19pub mod path_validation;
20
21#[cfg(test)]
22mod tests;
23
24//= https://www.rfc-editor.org/rfc/rfc9000#section-19
25//# As described in Section 12.4, packets contain one or more frames.
26//# This section describes the format and semantics of the core QUIC
27//# frame types.
28
29pub(crate) type Tag = u8;
30pub(crate) type ExtensionTag = VarInt;
31
32pub type FrameRef<'a> = Frame<'a, ack::AckRangesDecoder<'a>, DecoderBuffer<'a>>;
33pub type FrameMut<'a> = Frame<'a, ack::AckRangesDecoder<'a>, DecoderBufferMut<'a>>;
34
35pub trait FrameTrait: AckElicitable + CongestionControlled + path_validation::Probing {}
36
37/// Implement FrameTrait for all types that implement the required subtraits
38impl<T: AckElicitable + CongestionControlled + path_validation::Probing> FrameTrait for T {}
39
40macro_rules! frames {
41    ($ack:ident, $data:ident | $($([$tag_macro:ident])? $(extension[$extension_tag_macro:ident])? => $module:ident, $handler:ident, $ty:ident $([$($generics:tt)+])?;)*) => {
42        $(
43            #[macro_use]
44            pub mod $module;
45            pub use $module::$ty;
46        )*
47
48        pub type RemainingBuffer<'a> = Option<DecoderBufferMut<'a>>;
49
50        #[derive(Debug, PartialEq, Eq)]
51        pub enum Frame<'a, $ack, $data> {
52            $(
53                $ty($module::$ty $(<$($generics)*>)?),
54            )*
55        }
56
57        impl<'a, $ack, $data> event::IntoEvent<event::builder::Frame> for &Frame<'a, $ack, $data>
58        where
59            $ack: crate::frame::ack::AckRanges,
60            $data: EncoderValue,
61        {
62            #[inline]
63            fn into_event(self) -> event::builder::Frame {
64                match self {
65                    $(
66                        Frame::$ty(inner) => inner.into_event(),
67                    )*
68                }
69            }
70        }
71
72        impl<'a, $ack, $data> ack_elicitation::AckElicitable for Frame<'a, $ack, $data> {
73            #[inline]
74            fn ack_elicitation(&self) -> ack_elicitation::AckElicitation {
75                match self {
76                    $(
77                        Frame::$ty(frame) => frame.ack_elicitation(),
78                    )*
79                }
80            }
81        }
82
83        impl<'a, $ack, $data> path_validation::Probing for Frame<'a, $ack, $data> {
84            #[inline]
85            fn path_validation(&self) -> path_validation::Probe {
86                match self {
87                    $(
88                        Frame::$ty(frame) => frame.path_validation(),
89                    )*
90                }
91            }
92        }
93
94        $(
95            impl<'a, $ack, $data> From<$module::$ty $(<$($generics)*>)?> for Frame<'a, $ack, $data> {
96                #[inline]
97                fn from(v: $module::$ty $(<$($generics)*>)?)  -> Frame<'a, $ack, $data> {
98                    Frame::$ty(v)
99                }
100            }
101        )*
102
103        impl<'a, $ack, $data: DecoderValueMut<'a>> DecoderValueMut<'a> for Frame<'a, $ack, $data>
104        where ack::Ack<$ack>: DecoderParameterizedValueMut<'a, Parameter = Tag> {
105            #[inline]
106            fn decode_mut(buffer: DecoderBufferMut<'a>) -> DecoderBufferMutResult<'a, Self> {
107                BasicFrameDecoder.decode_frame(buffer)
108            }
109        }
110
111        impl<'a, $ack: ack::AckRanges, $data: EncoderValue> EncoderValue for Frame<'a, $ack, $data> {
112            #[inline]
113            fn encode<E: Encoder>(&self, buffer: &mut E)  {
114                match self {
115                    $(
116                        Frame::$ty(frame) => buffer.encode(frame),
117                    )*
118                }
119            }
120        }
121
122        struct BasicFrameDecoder;
123
124        impl<'a, $ack, $data: DecoderValueMut<'a>> FrameDecoder<'a, $ack, $data> for BasicFrameDecoder
125        where ack::Ack<$ack>: DecoderParameterizedValueMut<'a, Parameter = Tag> {
126            type Output = Frame<'a, $ack, $data>;
127
128            $(
129                #[inline]
130                fn $handler(&mut self, frame: $module::$ty $(<$($generics)*>)?) -> Result<Self::Output, DecoderError> {
131                    Ok(Frame::$ty(frame))
132                }
133            )*
134        }
135
136        pub trait FrameDecoder<'a, $ack, $data: DecoderValueMut<'a>>
137        where ack::Ack<$ack>: DecoderParameterizedValueMut<'a, Parameter = Tag> {
138            type Output;
139
140            $(
141                fn $handler(&mut self, frame: $module::$ty $(<$($generics)*>)?) -> Result<Self::Output, DecoderError>;
142            )*
143
144            #[inline]
145            fn handle_extension_frame(&mut self, buffer: DecoderBufferMut<'a>) -> DecoderBufferMutResult<'a, Self::Output> {
146                let (tag, buffer) = buffer.decode::<ExtensionTag>()?;
147
148                match tag.as_u64() {
149                    $(
150                        $(
151                            $extension_tag_macro!() => {
152                                let (frame, buffer) = buffer.decode_parameterized(tag)?;
153                                let output = self.$handler(frame)?;
154                                Ok((output, buffer))
155                            },
156                        )?
157                    )*
158                    _ => {
159                        let _ = buffer;
160                        Err(DecoderError::InvariantViolation("invalid frame"))
161                    }
162                }
163            }
164
165            #[inline]
166            fn decode_frame(
167                &mut self,
168                buffer: DecoderBufferMut<'a>,
169            ) -> DecoderBufferMutResult<'a, Self::Output> {
170                let tag = buffer.peek_byte(0)?;
171                match tag {
172                    // Make sure the single byte frame tags fit into a small variable-integer
173                    // otherwise fallback to extension selection
174                    0b0100_0000..=0xff => self.handle_extension_frame(buffer),
175                    $(
176                        $(
177                            $tag_macro!() => {
178                                let buffer = buffer.skip(core::mem::size_of::<Tag>())?;
179                                let (frame, buffer) = buffer.decode_parameterized(tag)?;
180                                let output = self.$handler(frame)?;
181                                Ok((output, buffer))
182                            },
183                        )?
184                    )*
185                    _ => self.handle_extension_frame(buffer),
186                }
187            }
188        }
189
190        #[cfg(test)]
191        mod snapshots {
192            use super::*;
193            use s2n_codec::assert_codec_round_trip_sample_file;
194
195            $(
196                #[test]
197                fn $module() {
198                    assert_codec_round_trip_sample_file!(FrameMut, concat!(
199                        "src/frame/test_samples/",
200                        stringify!($module),
201                        ".bin"
202                    ));
203                }
204            )*
205        }
206    };
207}
208
209// This implements a codec for a frame that contains simple
210// values that don't vary based on the tag
211macro_rules! simple_frame_codec {
212    ($name:ident {
213        $(
214            $field:ident
215        ),*
216    }, $tag:expr) => {
217        s2n_codec::decoder_parameterized_value!(
218            impl<'a> $name {
219                fn decode(_tag: crate::frame::Tag, buffer: Buffer) -> Result<Self> {
220                    $(
221                        let ($field, buffer) = buffer.decode()?;
222                    )*
223
224                    let frame = $name { $($field),* };
225
226                    Ok((frame, buffer))
227                }
228            }
229        );
230
231        impl s2n_codec::EncoderValue for $name {
232            #[inline]
233            fn encode<E: s2n_codec::Encoder>(&self, buffer: &mut E) {
234                buffer.encode(&$tag);
235                $(
236                    buffer.encode(&self.$field);
237                )*
238            }
239        }
240    };
241}
242
243frames! {
244    AckRanges, Data |
245    [padding_tag] => padding, handle_padding_frame, Padding;
246    [ping_tag] => ping, handle_ping_frame, Ping;
247    [ack_tag] => ack, handle_ack_frame, Ack[AckRanges];
248    [reset_stream_tag] => reset_stream, handle_reset_stream_frame, ResetStream;
249    [stop_sending_tag] => stop_sending, handle_stop_sending_frame, StopSending;
250    [crypto_tag] => crypto, handle_crypto_frame, Crypto[Data];
251    [new_token_tag] => new_token, handle_new_token_frame, NewToken['a];
252    [stream_tag] => stream, handle_stream_frame, Stream[Data];
253    [max_data_tag] => max_data, handle_max_data_frame, MaxData;
254    [max_stream_data_tag] => max_stream_data, handle_max_stream_data_frame, MaxStreamData;
255    [max_streams_tag] => max_streams, handle_max_streams_frame, MaxStreams;
256    [data_blocked_tag] => data_blocked, handle_data_blocked_frame, DataBlocked;
257    [stream_data_blocked_tag] => stream_data_blocked, handle_stream_data_blocked_frame, StreamDataBlocked;
258    [streams_blocked_tag] => streams_blocked, handle_streams_blocked_frame, StreamsBlocked;
259    [new_connection_id_tag] => new_connection_id, handle_new_connection_id_frame, NewConnectionId['a];
260    [retire_connection_id_tag] => retire_connection_id, handle_retire_connection_id_frame, RetireConnectionId;
261    [path_challenge_tag] => path_challenge, handle_path_challenge_frame, PathChallenge['a];
262    [path_response_tag] => path_response, handle_path_response_frame, PathResponse['a];
263    [connection_close_tag] => connection_close, handle_connection_close_frame, ConnectionClose['a];
264    [handshake_done_tag] => handshake_done, handle_handshake_done_frame, HandshakeDone;
265    [datagram_tag] => datagram, handle_datagram_frame, Datagram[Data];
266    extension[dc_stateless_reset_tokens_tag] => dc_stateless_reset_tokens, handle_dc_stateless_reset_tokens_frame, DcStatelessResetTokens['a];
267}
268
269#[derive(Clone, Copy, Debug, Default)]
270/// Indicates the packet will not fit into the provided capacity
271pub struct FitError;
272
273impl fmt::Display for FitError {
274    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275        write!(f, "the frame could not fit into the provided capacity")
276    }
277}