net_wire/quic/frame/
crypto.rs1use super::super::varint::QuicVarInt;
4use super::parse::{QuicFrameField, QuicFrameParseError};
5
6const MAX_CRYPTO_RANGE_END: u64 = (1 << 62) - 1;
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub struct QuicCryptoFrame<'a> {
11 bytes: &'a [u8],
12 frame_type: QuicVarInt<'a>,
13 offset: QuicVarInt<'a>,
14 length: QuicVarInt<'a>,
15 crypto_data: &'a [u8],
16}
17
18impl<'a> QuicCryptoFrame<'a> {
19 pub const fn as_bytes(self) -> &'a [u8] {
21 self.bytes
22 }
23
24 pub const fn frame_type(self) -> QuicVarInt<'a> {
26 self.frame_type
27 }
28
29 pub const fn offset(self) -> QuicVarInt<'a> {
31 self.offset
32 }
33
34 pub const fn length(self) -> QuicVarInt<'a> {
36 self.length
37 }
38
39 pub const fn crypto_data(self) -> &'a [u8] {
41 self.crypto_data
42 }
43}
44
45pub(super) fn parse_crypto<'a>(
46 bytes: &'a [u8],
47 frame_type: QuicVarInt<'a>,
48 offset: usize,
49) -> Result<(QuicCryptoFrame<'a>, &'a [u8]), QuicFrameParseError> {
50 let offset_start = frame_type.byte_len();
51 let offset_offset = offset + offset_start;
52 let crypto_offset =
53 QuicVarInt::parse(&bytes[offset_start..]).map_err(|error| QuicFrameParseError::Field {
54 field: QuicFrameField::CryptoOffset,
55 offset: offset_offset,
56 error,
57 })?;
58
59 let length_start = offset_start + crypto_offset.byte_len();
60 let length_offset = offset + length_start;
61 let length =
62 QuicVarInt::parse(&bytes[length_start..]).map_err(|error| QuicFrameParseError::Field {
63 field: QuicFrameField::CryptoLength,
64 offset: length_offset,
65 error,
66 })?;
67
68 let range_end = crypto_offset.value().checked_add(length.value());
69 if range_end.is_none_or(|end| end > MAX_CRYPTO_RANGE_END) {
70 return Err(QuicFrameParseError::FieldRangeOutOfRange {
71 field: QuicFrameField::CryptoOffset,
72 offset: offset_offset,
73 start: crypto_offset.value(),
74 length: length.value(),
75 maximum: MAX_CRYPTO_RANGE_END,
76 });
77 }
78
79 let length_value = length.value();
80 let length_usize =
81 usize::try_from(length_value).map_err(|_| QuicFrameParseError::LengthNotRepresentable {
82 field: QuicFrameField::CryptoLength,
83 offset: length_offset,
84 value: length_value,
85 })?;
86 let data_start = length_start + length.byte_len();
88 let data_offset = offset + data_start;
89 let data_end =
90 data_start
91 .checked_add(length_usize)
92 .ok_or(QuicFrameParseError::LengthOverflow {
93 field: QuicFrameField::CryptoData,
94 offset: data_offset,
95 length: length_usize,
96 })?;
97 let available = bytes.len() - data_start;
98 if available < length_usize {
99 return Err(QuicFrameParseError::IncompleteBytes {
100 field: QuicFrameField::CryptoData,
101 offset: data_offset,
102 required: length_usize,
103 available,
104 });
105 }
106
107 Ok((
108 QuicCryptoFrame {
109 bytes: &bytes[..data_end],
110 frame_type,
111 offset: crypto_offset,
112 length,
113 crypto_data: &bytes[data_start..data_end],
114 },
115 &bytes[data_end..],
116 ))
117}