net_wire/quic/frame/
connection_close.rs1use super::super::varint::QuicVarInt;
4use super::parse::{QuicFrameField, QuicFrameParseError};
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct QuicConnectionCloseFrame<'a> {
9 bytes: &'a [u8],
10 frame_type: QuicVarInt<'a>,
11 error_code: QuicVarInt<'a>,
12 triggering_frame_type: Option<QuicVarInt<'a>>,
13 reason_phrase_length: QuicVarInt<'a>,
14 reason_phrase: &'a [u8],
15}
16
17impl<'a> QuicConnectionCloseFrame<'a> {
18 pub const fn as_bytes(self) -> &'a [u8] {
20 self.bytes
21 }
22
23 pub const fn frame_type(self) -> QuicVarInt<'a> {
25 self.frame_type
26 }
27
28 pub const fn error_code(self) -> QuicVarInt<'a> {
30 self.error_code
31 }
32
33 pub const fn triggering_frame_type(self) -> Option<QuicVarInt<'a>> {
35 self.triggering_frame_type
36 }
37
38 pub const fn reason_phrase_length(self) -> QuicVarInt<'a> {
40 self.reason_phrase_length
41 }
42
43 pub const fn reason_phrase(self) -> &'a [u8] {
45 self.reason_phrase
46 }
47}
48
49pub(super) fn parse_connection_close<'a>(
50 bytes: &'a [u8],
51 frame_type: QuicVarInt<'a>,
52 offset: usize,
53) -> Result<(QuicConnectionCloseFrame<'a>, &'a [u8]), QuicFrameParseError> {
54 let mut start = frame_type.byte_len();
55 let error_code = parse_field(
56 bytes,
57 start,
58 offset,
59 QuicFrameField::ConnectionCloseErrorCode,
60 )?;
61 start += error_code.byte_len();
62
63 let triggering_frame_type = if frame_type.value() == 0x1c {
64 let triggering_frame_type =
65 parse_field(bytes, start, offset, QuicFrameField::TriggeringFrameType)?;
66 start += triggering_frame_type.byte_len();
67 Some(triggering_frame_type)
68 } else {
69 None
70 };
71
72 let reason_phrase_length =
73 parse_field(bytes, start, offset, QuicFrameField::ReasonPhraseLength)?;
74 start += reason_phrase_length.byte_len();
75 let reason_length_value = reason_phrase_length.value();
76 let reason_length = usize::try_from(reason_length_value).map_err(|_| {
77 QuicFrameParseError::LengthNotRepresentable {
78 field: QuicFrameField::ReasonPhraseLength,
79 offset: offset + start - reason_phrase_length.byte_len(),
80 value: reason_length_value,
81 }
82 })?;
83 let reason_offset = offset + start;
84 let end = start
85 .checked_add(reason_length)
86 .ok_or(QuicFrameParseError::LengthOverflow {
87 field: QuicFrameField::ReasonPhrase,
88 offset: reason_offset,
89 length: reason_length,
90 })?;
91 let available = bytes.len() - start;
92 if available < reason_length {
93 return Err(QuicFrameParseError::IncompleteBytes {
94 field: QuicFrameField::ReasonPhrase,
95 offset: reason_offset,
96 required: reason_length,
97 available,
98 });
99 }
100
101 Ok((
102 QuicConnectionCloseFrame {
103 bytes: &bytes[..end],
104 frame_type,
105 error_code,
106 triggering_frame_type,
107 reason_phrase_length,
108 reason_phrase: &bytes[start..end],
109 },
110 &bytes[end..],
111 ))
112}
113
114fn parse_field<'a>(
115 bytes: &'a [u8],
116 start: usize,
117 offset: usize,
118 field: QuicFrameField,
119) -> Result<QuicVarInt<'a>, QuicFrameParseError> {
120 QuicVarInt::parse(&bytes[start..]).map_err(|error| QuicFrameParseError::Field {
121 field,
122 offset: offset + start,
123 error,
124 })
125}