net_wire/http2/
headers.rs1use super::error::Http2ParseError;
2use super::frame::Http2Frame;
3use super::layout::{PADDED, padding_length, validate_frame, validate_padding};
4use super::priority::Http2Priority;
5use super::types::{Http2FrameType, Http2StreamId};
6
7const PRIORITY: u8 = 0x20;
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct Http2Headers<'a> {
12 frame: Http2Frame<'a>,
13 field_block_start: usize,
14 field_block_end: usize,
15 priority: Option<Http2Priority>,
16}
17
18impl<'a> Http2Headers<'a> {
19 pub(super) fn from_validated(
20 frame: Http2Frame<'a>,
21 padding_length: Option<u8>,
22 priority: Option<Http2Priority>,
23 ) -> Self {
24 let field_block_start =
25 usize::from(padding_length.is_some()) + 5 * usize::from(priority.is_some());
26 let field_block_end = frame.payload().len() - usize::from(padding_length.unwrap_or(0));
27 Self {
28 frame,
29 field_block_start,
30 field_block_end,
31 priority,
32 }
33 }
34
35 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
37 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
38 }
39
40 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
42 validate_frame(frame, Http2FrameType::HEADERS)?;
43 let payload = frame.payload();
44 let padded = frame.flags() & PADDED != 0;
45 if padded {
46 validate_padding(payload)?;
47 }
48 let padding_length = padding_length(frame);
49 let mut field_block_start = usize::from(padded);
50 let field_block_end = payload.len() - padding_length;
51 let priority = if frame.flags() & PRIORITY != 0 {
52 let available = field_block_end - field_block_start;
53 if available < 5 {
54 return Err(Http2ParseError::MalformedPayload {
55 required: 5,
56 available,
57 });
58 }
59 let priority = Http2Priority::parse(&payload[field_block_start..field_block_start + 5]);
60 field_block_start += 5;
61 Some(priority)
62 } else {
63 None
64 };
65 Ok(Self {
66 frame,
67 field_block_start,
68 field_block_end,
69 priority,
70 })
71 }
72
73 pub const fn frame(&self) -> Http2Frame<'a> {
75 self.frame
76 }
77
78 pub fn as_bytes(&self) -> &'a [u8] {
80 self.frame.as_bytes()
81 }
82
83 pub fn field_block_fragment(&self) -> &'a [u8] {
85 &self.frame.payload()[self.field_block_start..self.field_block_end]
86 }
87
88 pub fn padding(&self) -> &'a [u8] {
90 &self.frame.payload()[self.field_block_end..]
91 }
92
93 pub fn pad_length(&self) -> Option<u8> {
95 (self.frame.flags() & PADDED != 0).then(|| self.frame.payload()[0])
96 }
97
98 pub const fn priority(&self) -> Option<Http2Priority> {
100 self.priority
101 }
102}
103
104#[derive(Clone, Copy, Debug, Eq, PartialEq)]
106pub struct Http2PushPromise<'a> {
107 frame: Http2Frame<'a>,
108 field_block_start: usize,
109 field_block_end: usize,
110 promised_stream_id: Http2StreamId,
111}
112
113impl<'a> Http2PushPromise<'a> {
114 pub(super) fn from_validated(
115 frame: Http2Frame<'a>,
116 padding_length: Option<u8>,
117 promised_stream_id: Http2StreamId,
118 ) -> Self {
119 let field_block_start = usize::from(padding_length.is_some()) + 4;
120 let field_block_end = frame.payload().len() - usize::from(padding_length.unwrap_or(0));
121 Self {
122 frame,
123 field_block_start,
124 field_block_end,
125 promised_stream_id,
126 }
127 }
128
129 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
131 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
132 }
133
134 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
136 validate_frame(frame, Http2FrameType::PUSH_PROMISE)?;
137 let payload = frame.payload();
138 let padded = frame.flags() & PADDED != 0;
139 if padded {
140 validate_padding(payload)?;
141 }
142 let field_block_start = usize::from(padded);
143 let field_block_end = payload.len() - padding_length(frame);
144 let available = field_block_end - field_block_start;
145 if available < 4 {
146 return Err(Http2ParseError::MalformedPayload {
147 required: 4,
148 available,
149 });
150 }
151 let promised_stream_id = Http2StreamId::new(u32::from_be_bytes([
152 payload[field_block_start],
153 payload[field_block_start + 1],
154 payload[field_block_start + 2],
155 payload[field_block_start + 3],
156 ]));
157 if promised_stream_id.value() == 0 {
158 return Err(Http2ParseError::ZeroPromisedStreamId);
159 }
160 Ok(Self {
161 frame,
162 field_block_start: field_block_start + 4,
163 field_block_end,
164 promised_stream_id,
165 })
166 }
167
168 pub const fn frame(&self) -> Http2Frame<'a> {
170 self.frame
171 }
172
173 pub fn as_bytes(&self) -> &'a [u8] {
175 self.frame.as_bytes()
176 }
177
178 pub const fn promised_stream_id(&self) -> Http2StreamId {
180 self.promised_stream_id
181 }
182
183 pub fn field_block_fragment(&self) -> &'a [u8] {
185 &self.frame.payload()[self.field_block_start..self.field_block_end]
186 }
187
188 pub fn padding(&self) -> &'a [u8] {
190 &self.frame.payload()[self.field_block_end..]
191 }
192
193 pub fn pad_length(&self) -> Option<u8> {
195 (self.frame.flags() & PADDED != 0).then(|| self.frame.payload()[0])
196 }
197}
198
199#[derive(Clone, Copy, Debug, Eq, PartialEq)]
201pub struct Http2Continuation<'a> {
202 frame: Http2Frame<'a>,
203}
204
205impl<'a> Http2Continuation<'a> {
206 pub(super) fn from_validated(frame: Http2Frame<'a>) -> Self {
207 Self { frame }
208 }
209
210 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
212 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
213 }
214
215 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
217 validate_frame(frame, Http2FrameType::CONTINUATION)?;
218 Ok(Self { frame })
219 }
220
221 pub const fn frame(&self) -> Http2Frame<'a> {
223 self.frame
224 }
225
226 pub fn as_bytes(&self) -> &'a [u8] {
228 self.frame.as_bytes()
229 }
230
231 pub fn field_block_fragment(&self) -> &'a [u8] {
233 self.frame.payload()
234 }
235}