1use super::error::Http2ParseError;
2use super::frame::Http2Frame;
3use super::layout::{validate_exact_payload, validate_frame, validate_type, validate_zero_stream};
4use super::priority::Http2Priority;
5use super::types::{Http2ErrorCode, Http2FrameType, Http2StreamId};
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct Http2Goaway<'a> {
10 frame: Http2Frame<'a>,
11 last_stream_id: Http2StreamId,
12 error_code: Http2ErrorCode,
13}
14
15impl<'a> Http2Goaway<'a> {
16 pub(super) fn from_validated(
17 frame: Http2Frame<'a>,
18 last_stream_id: Http2StreamId,
19 error_code: Http2ErrorCode,
20 ) -> Self {
21 Self {
22 frame,
23 last_stream_id,
24 error_code,
25 }
26 }
27
28 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
30 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
31 }
32
33 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
35 validate_type(frame, Http2FrameType::GOAWAY)?;
36 validate_zero_stream(frame)?;
37 let payload = frame.payload();
38 if payload.len() < 8 {
39 return Err(Http2ParseError::MalformedPayload {
40 required: 8,
41 available: payload.len(),
42 });
43 }
44 Ok(Self {
45 last_stream_id: Http2StreamId::new(u32::from_be_bytes([
46 payload[0], payload[1], payload[2], payload[3],
47 ])),
48 error_code: Http2ErrorCode::new(u32::from_be_bytes([
49 payload[4], payload[5], payload[6], payload[7],
50 ])),
51 frame,
52 })
53 }
54
55 pub const fn frame(&self) -> Http2Frame<'a> {
57 self.frame
58 }
59
60 pub fn as_bytes(&self) -> &'a [u8] {
62 self.frame.as_bytes()
63 }
64
65 pub const fn last_stream_id(&self) -> Http2StreamId {
67 self.last_stream_id
68 }
69
70 pub const fn error_code(&self) -> Http2ErrorCode {
72 self.error_code
73 }
74
75 pub fn additional_debug_data(&self) -> &'a [u8] {
77 &self.frame.payload()[8..]
78 }
79}
80
81#[repr(transparent)]
83#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
84pub struct Http2WindowIncrement(u32);
85
86impl Http2WindowIncrement {
87 pub const fn new(raw: u32) -> Self {
89 Self(raw)
90 }
91
92 fn parse(bytes: &[u8]) -> Self {
93 Self(u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
94 }
95
96 pub const fn raw(self) -> u32 {
98 self.0
99 }
100
101 pub const fn value(self) -> u32 {
103 self.0 & 0x7fff_ffff
104 }
105
106 pub const fn has_reserved_bit(self) -> bool {
108 self.0 & 0x8000_0000 != 0
109 }
110}
111
112#[derive(Clone, Copy, Debug, Eq, PartialEq)]
114pub struct Http2PriorityFrame<'a> {
115 frame: Http2Frame<'a>,
116 priority: Http2Priority,
117}
118
119impl<'a> Http2PriorityFrame<'a> {
120 pub(super) fn from_validated(frame: Http2Frame<'a>, priority: Http2Priority) -> Self {
121 Self { frame, priority }
122 }
123
124 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
126 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
127 }
128
129 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
131 validate_frame(frame, Http2FrameType::PRIORITY)?;
132 validate_exact_payload(frame, 5)?;
133 Ok(Self {
134 priority: Http2Priority::parse(frame.payload()),
135 frame,
136 })
137 }
138
139 pub const fn frame(&self) -> Http2Frame<'a> {
141 self.frame
142 }
143 pub fn as_bytes(&self) -> &'a [u8] {
145 self.frame.as_bytes()
146 }
147 pub const fn priority(&self) -> Http2Priority {
149 self.priority
150 }
151}
152
153#[derive(Clone, Copy, Debug, Eq, PartialEq)]
155pub struct Http2RstStream<'a> {
156 frame: Http2Frame<'a>,
157 error_code: Http2ErrorCode,
158}
159
160impl<'a> Http2RstStream<'a> {
161 pub(super) fn from_validated(frame: Http2Frame<'a>, error_code: Http2ErrorCode) -> Self {
162 Self { frame, error_code }
163 }
164
165 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
167 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
168 }
169
170 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
172 validate_frame(frame, Http2FrameType::RST_STREAM)?;
173 validate_exact_payload(frame, 4)?;
174 let payload = frame.payload();
175 Ok(Self {
176 error_code: Http2ErrorCode::new(u32::from_be_bytes([
177 payload[0], payload[1], payload[2], payload[3],
178 ])),
179 frame,
180 })
181 }
182
183 pub const fn frame(&self) -> Http2Frame<'a> {
185 self.frame
186 }
187 pub fn as_bytes(&self) -> &'a [u8] {
189 self.frame.as_bytes()
190 }
191 pub const fn error_code(&self) -> Http2ErrorCode {
193 self.error_code
194 }
195}
196
197#[derive(Clone, Copy, Debug, Eq, PartialEq)]
199pub struct Http2Ping<'a> {
200 frame: Http2Frame<'a>,
201 opaque_data: &'a [u8; 8],
202}
203
204impl<'a> Http2Ping<'a> {
205 pub(super) fn from_validated(frame: Http2Frame<'a>, opaque_data: &'a [u8; 8]) -> Self {
206 Self { frame, opaque_data }
207 }
208
209 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
211 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
212 }
213
214 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
216 validate_type(frame, Http2FrameType::PING)?;
217 validate_zero_stream(frame)?;
218 validate_exact_payload(frame, 8)?;
219 let payload = frame.payload();
220 let opaque_data = payload
221 .try_into()
222 .map_err(|_| Http2ParseError::FrameSizeMismatch {
223 expected: 8,
224 actual: payload.len(),
225 })?;
226 Ok(Self { frame, opaque_data })
227 }
228
229 pub const fn frame(&self) -> Http2Frame<'a> {
231 self.frame
232 }
233 pub fn as_bytes(&self) -> &'a [u8] {
235 self.frame.as_bytes()
236 }
237 pub const fn opaque_data(&self) -> &'a [u8; 8] {
239 self.opaque_data
240 }
241 pub fn is_ack(&self) -> bool {
243 self.frame.flags() & 0x1 != 0
244 }
245}
246
247#[derive(Clone, Copy, Debug, Eq, PartialEq)]
249pub struct Http2WindowUpdate<'a> {
250 frame: Http2Frame<'a>,
251 increment: Http2WindowIncrement,
252}
253
254impl<'a> Http2WindowUpdate<'a> {
255 pub(super) fn from_validated(frame: Http2Frame<'a>, increment: Http2WindowIncrement) -> Self {
256 Self { frame, increment }
257 }
258
259 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
261 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
262 }
263
264 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
266 validate_type(frame, Http2FrameType::WINDOW_UPDATE)?;
267 validate_exact_payload(frame, 4)?;
268 let increment = Http2WindowIncrement::parse(frame.payload());
269 if increment.value() == 0 {
270 return Err(Http2ParseError::ZeroWindowIncrement);
271 }
272 Ok(Self { frame, increment })
273 }
274
275 pub const fn frame(&self) -> Http2Frame<'a> {
277 self.frame
278 }
279 pub fn as_bytes(&self) -> &'a [u8] {
281 self.frame.as_bytes()
282 }
283 pub const fn increment(&self) -> Http2WindowIncrement {
285 self.increment
286 }
287}