Skip to main content

net_wire/quic/frame/
path.rs

1//! RFC 9000 PATH_CHALLENGE and PATH_RESPONSE frame parsing.
2
3use super::super::varint::QuicVarInt;
4use super::parse::{QuicFrameField, QuicFrameParseError};
5
6/// A checked borrowed RFC 9000 PATH_CHALLENGE frame view.
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct QuicPathChallengeFrame<'a> {
9    bytes: &'a [u8],
10    frame_type: QuicVarInt<'a>,
11    data: &'a [u8; 8],
12}
13
14impl<'a> QuicPathChallengeFrame<'a> {
15    /// Returns the exact encoded frame bytes.
16    pub const fn as_bytes(self) -> &'a [u8] {
17        self.bytes
18    }
19
20    /// Returns the exact encoded frame-type variable integer.
21    pub const fn frame_type(self) -> QuicVarInt<'a> {
22        self.frame_type
23    }
24
25    /// Returns the opaque path-validation data.
26    pub const fn data(self) -> &'a [u8; 8] {
27        self.data
28    }
29}
30
31/// A checked borrowed RFC 9000 PATH_RESPONSE frame view.
32#[derive(Clone, Copy, Debug, Eq, PartialEq)]
33pub struct QuicPathResponseFrame<'a> {
34    bytes: &'a [u8],
35    frame_type: QuicVarInt<'a>,
36    data: &'a [u8; 8],
37}
38
39impl<'a> QuicPathResponseFrame<'a> {
40    /// Returns the exact encoded frame bytes.
41    pub const fn as_bytes(self) -> &'a [u8] {
42        self.bytes
43    }
44
45    /// Returns the exact encoded frame-type variable integer.
46    pub const fn frame_type(self) -> QuicVarInt<'a> {
47        self.frame_type
48    }
49
50    /// Returns the opaque path-validation data.
51    pub const fn data(self) -> &'a [u8; 8] {
52        self.data
53    }
54}
55
56pub(super) fn parse_path_challenge<'a>(
57    bytes: &'a [u8],
58    frame_type: QuicVarInt<'a>,
59    offset: usize,
60) -> Result<(QuicPathChallengeFrame<'a>, &'a [u8]), QuicFrameParseError> {
61    let parsed = parse_path_data(bytes, frame_type, offset)?;
62    Ok((
63        QuicPathChallengeFrame {
64            bytes: parsed.bytes,
65            frame_type,
66            data: parsed.data,
67        },
68        parsed.suffix,
69    ))
70}
71
72pub(super) fn parse_path_response<'a>(
73    bytes: &'a [u8],
74    frame_type: QuicVarInt<'a>,
75    offset: usize,
76) -> Result<(QuicPathResponseFrame<'a>, &'a [u8]), QuicFrameParseError> {
77    let parsed = parse_path_data(bytes, frame_type, offset)?;
78    Ok((
79        QuicPathResponseFrame {
80            bytes: parsed.bytes,
81            frame_type,
82            data: parsed.data,
83        },
84        parsed.suffix,
85    ))
86}
87
88struct ParsedPathData<'a> {
89    bytes: &'a [u8],
90    data: &'a [u8; 8],
91    suffix: &'a [u8],
92}
93
94fn parse_path_data<'a>(
95    bytes: &'a [u8],
96    frame_type: QuicVarInt<'a>,
97    offset: usize,
98) -> Result<ParsedPathData<'a>, QuicFrameParseError> {
99    let data_start = frame_type.byte_len();
100    let input = &bytes[data_start..];
101    let Some((data, suffix)) = input.split_first_chunk::<8>() else {
102        return Err(QuicFrameParseError::IncompleteBytes {
103            field: QuicFrameField::PathData,
104            offset: offset + data_start,
105            required: 8,
106            available: input.len(),
107        });
108    };
109    let frame_len = bytes.len() - suffix.len();
110    Ok(ParsedPathData {
111        bytes: &bytes[..frame_len],
112        data,
113        suffix,
114    })
115}