1use super::super::data::Http2Data;
4use super::super::error::Http2BuildError;
5use super::super::frame::Http2Frame;
6use super::super::headers::{Http2Continuation, Http2Headers, Http2PushPromise};
7use super::super::priority::Http2Priority;
8use super::super::types::{Http2FrameType, Http2StreamId};
9use super::raw::{FRAME_HEADER_LENGTH, MAXIMUM_PAYLOAD, write_frame_envelope};
10
11const DATA_PADDED: u8 = 0x08;
12const HEADERS_PRIORITY: u8 = 0x20;
13const PUSH_PROMISE_PADDED: u8 = 0x08;
14
15pub struct Http2DataBuilder<'a, 'b> {
17 buffer: &'a mut [u8],
18 stream_id: Http2StreamId,
19 flags: u8,
20 data: &'b [u8],
21 padding_length: Option<u8>,
22}
23
24impl<'a, 'b> Http2DataBuilder<'a, 'b> {
25 pub fn new(
27 buffer: &'a mut [u8],
28 stream_id: Http2StreamId,
29 flags: u8,
30 data: &'b [u8],
31 padding_length: Option<u8>,
32 ) -> Self {
33 Self {
34 buffer,
35 stream_id,
36 flags,
37 data,
38 padding_length,
39 }
40 }
41
42 pub fn build(self) -> Result<Http2Data<'a>, Http2BuildError> {
44 self.build_with_maximum(MAXIMUM_PAYLOAD)
45 }
46
47 pub fn build_with_maximum(
49 self,
50 maximum_payload: usize,
51 ) -> Result<Http2Data<'a>, Http2BuildError> {
52 if self.flags & DATA_PADDED != 0 {
53 return Err(Http2BuildError::DataPaddedFlagSet);
54 }
55 validate_stream_id(self.stream_id)?;
56 let padding_length = self.padding_length;
57 let flags = self.flags
58 | if padding_length.is_some() {
59 DATA_PADDED
60 } else {
61 0
62 };
63 let payload_length = self
64 .data
65 .len()
66 .checked_add(usize::from(padding_length.is_some()))
67 .and_then(|length| length.checked_add(usize::from(padding_length.unwrap_or(0))))
68 .ok_or(Http2BuildError::PayloadTooLarge {
69 maximum: maximum_payload.min(MAXIMUM_PAYLOAD),
70 actual: self.data.len(),
71 })?;
72 let bytes = write_frame_envelope(
73 self.buffer,
74 payload_length,
75 Http2FrameType::DATA,
76 flags,
77 self.stream_id,
78 maximum_payload,
79 )?;
80 let mut offset = FRAME_HEADER_LENGTH;
81 if let Some(padding_length) = padding_length {
82 bytes[offset] = padding_length;
83 offset += 1;
84 }
85 let data_end = offset + self.data.len();
86 bytes[offset..data_end].copy_from_slice(self.data);
87 bytes[data_end..].fill(0);
88 Ok(Http2Data::from_validated(
89 Http2Frame::from_validated(bytes),
90 padding_length,
91 ))
92 }
93}
94
95pub struct Http2HeadersBuilder<'a, 'b> {
97 buffer: &'a mut [u8],
98 stream_id: Http2StreamId,
99 flags: u8,
100 field_block_fragment: &'b [u8],
101 priority: Option<Http2Priority>,
102 padding_length: Option<u8>,
103}
104
105impl<'a, 'b> Http2HeadersBuilder<'a, 'b> {
106 pub fn new(
108 buffer: &'a mut [u8],
109 stream_id: Http2StreamId,
110 flags: u8,
111 field_block_fragment: &'b [u8],
112 priority: Option<Http2Priority>,
113 padding_length: Option<u8>,
114 ) -> Self {
115 Self {
116 buffer,
117 stream_id,
118 flags,
119 field_block_fragment,
120 priority,
121 padding_length,
122 }
123 }
124
125 pub fn build(self) -> Result<Http2Headers<'a>, Http2BuildError> {
127 self.build_with_maximum(MAXIMUM_PAYLOAD)
128 }
129
130 pub fn build_with_maximum(
132 self,
133 maximum_payload: usize,
134 ) -> Result<Http2Headers<'a>, Http2BuildError> {
135 if self.flags & DATA_PADDED != 0 {
136 return Err(Http2BuildError::HeadersPaddedFlagSet);
137 }
138 if self.flags & HEADERS_PRIORITY != 0 {
139 return Err(Http2BuildError::HeadersPriorityFlagSet);
140 }
141 validate_stream_id(self.stream_id)?;
142 let flags = self.flags
143 | if self.padding_length.is_some() {
144 DATA_PADDED
145 } else {
146 0
147 }
148 | if self.priority.is_some() {
149 HEADERS_PRIORITY
150 } else {
151 0
152 };
153 let payload_length = self
154 .field_block_fragment
155 .len()
156 .checked_add(5 * usize::from(self.priority.is_some()))
157 .and_then(|length| length.checked_add(usize::from(self.padding_length.is_some())))
158 .and_then(|length| length.checked_add(usize::from(self.padding_length.unwrap_or(0))))
159 .ok_or(Http2BuildError::PayloadTooLarge {
160 maximum: maximum_payload.min(MAXIMUM_PAYLOAD),
161 actual: self.field_block_fragment.len(),
162 })?;
163 let bytes = write_frame_envelope(
164 self.buffer,
165 payload_length,
166 Http2FrameType::HEADERS,
167 flags,
168 self.stream_id,
169 maximum_payload,
170 )?;
171 let mut offset = FRAME_HEADER_LENGTH;
172 if let Some(padding_length) = self.padding_length {
173 bytes[offset] = padding_length;
174 offset += 1;
175 }
176 if let Some(priority) = self.priority {
177 bytes[offset..offset + 4].copy_from_slice(&priority.raw_dependency().to_be_bytes());
178 bytes[offset + 4] = priority.weight();
179 offset += 5;
180 }
181 let fragment_end = offset + self.field_block_fragment.len();
182 bytes[offset..fragment_end].copy_from_slice(self.field_block_fragment);
183 bytes[fragment_end..].fill(0);
184 Ok(Http2Headers::from_validated(
185 Http2Frame::from_validated(bytes),
186 self.padding_length,
187 self.priority,
188 ))
189 }
190}
191
192pub struct Http2PushPromiseBuilder<'a, 'b> {
194 buffer: &'a mut [u8],
195 stream_id: Http2StreamId,
196 flags: u8,
197 promised_stream_id: Http2StreamId,
198 field_block_fragment: &'b [u8],
199 padding_length: Option<u8>,
200}
201
202impl<'a, 'b> Http2PushPromiseBuilder<'a, 'b> {
203 pub fn new(
205 buffer: &'a mut [u8],
206 stream_id: Http2StreamId,
207 flags: u8,
208 promised_stream_id: Http2StreamId,
209 field_block_fragment: &'b [u8],
210 padding_length: Option<u8>,
211 ) -> Self {
212 Self {
213 buffer,
214 stream_id,
215 flags,
216 promised_stream_id,
217 field_block_fragment,
218 padding_length,
219 }
220 }
221
222 pub fn build(self) -> Result<Http2PushPromise<'a>, Http2BuildError> {
224 self.build_with_maximum(MAXIMUM_PAYLOAD)
225 }
226
227 pub fn build_with_maximum(
229 self,
230 maximum_payload: usize,
231 ) -> Result<Http2PushPromise<'a>, Http2BuildError> {
232 if self.flags & PUSH_PROMISE_PADDED != 0 {
233 return Err(Http2BuildError::PushPromisePaddedFlagSet);
234 }
235 if self.promised_stream_id.value() == 0 {
236 return Err(Http2BuildError::ZeroPromisedStreamId);
237 }
238 if self.promised_stream_id.has_reserved_bit() {
239 return Err(Http2BuildError::ReservedPromisedStreamId);
240 }
241 validate_stream_id(self.stream_id)?;
242 let flags = self.flags
243 | if self.padding_length.is_some() {
244 PUSH_PROMISE_PADDED
245 } else {
246 0
247 };
248 let payload_length = self
249 .field_block_fragment
250 .len()
251 .checked_add(4)
252 .and_then(|length| length.checked_add(usize::from(self.padding_length.is_some())))
253 .and_then(|length| length.checked_add(usize::from(self.padding_length.unwrap_or(0))))
254 .ok_or(Http2BuildError::PayloadTooLarge {
255 maximum: maximum_payload.min(MAXIMUM_PAYLOAD),
256 actual: self.field_block_fragment.len(),
257 })?;
258 let bytes = write_frame_envelope(
259 self.buffer,
260 payload_length,
261 Http2FrameType::PUSH_PROMISE,
262 flags,
263 self.stream_id,
264 maximum_payload,
265 )?;
266 let mut offset = FRAME_HEADER_LENGTH;
267 if let Some(padding_length) = self.padding_length {
268 bytes[offset] = padding_length;
269 offset += 1;
270 }
271 bytes[offset..offset + 4].copy_from_slice(&self.promised_stream_id.raw().to_be_bytes());
272 offset += 4;
273 let fragment_end = offset + self.field_block_fragment.len();
274 bytes[offset..fragment_end].copy_from_slice(self.field_block_fragment);
275 bytes[fragment_end..].fill(0);
276 Ok(Http2PushPromise::from_validated(
277 Http2Frame::from_validated(bytes),
278 self.padding_length,
279 self.promised_stream_id,
280 ))
281 }
282}
283
284pub struct Http2ContinuationBuilder<'a, 'b> {
286 buffer: &'a mut [u8],
287 stream_id: Http2StreamId,
288 flags: u8,
289 field_block_fragment: &'b [u8],
290}
291
292impl<'a, 'b> Http2ContinuationBuilder<'a, 'b> {
293 pub fn new(
295 buffer: &'a mut [u8],
296 stream_id: Http2StreamId,
297 flags: u8,
298 field_block_fragment: &'b [u8],
299 ) -> Self {
300 Self {
301 buffer,
302 stream_id,
303 flags,
304 field_block_fragment,
305 }
306 }
307
308 pub fn build(self) -> Result<Http2Continuation<'a>, Http2BuildError> {
310 self.build_with_maximum(MAXIMUM_PAYLOAD)
311 }
312
313 pub fn build_with_maximum(
315 self,
316 maximum_payload: usize,
317 ) -> Result<Http2Continuation<'a>, Http2BuildError> {
318 validate_stream_id(self.stream_id)?;
319 let bytes = write_frame_envelope(
320 self.buffer,
321 self.field_block_fragment.len(),
322 Http2FrameType::CONTINUATION,
323 self.flags,
324 self.stream_id,
325 maximum_payload,
326 )?;
327 bytes[FRAME_HEADER_LENGTH..].copy_from_slice(self.field_block_fragment);
328 Ok(Http2Continuation::from_validated(
329 Http2Frame::from_validated(bytes),
330 ))
331 }
332}
333
334fn validate_stream_id(stream_id: Http2StreamId) -> Result<(), Http2BuildError> {
335 if stream_id.value() == 0 {
336 return Err(Http2BuildError::ZeroStreamId);
337 }
338 if stream_id.has_reserved_bit() {
339 return Err(Http2BuildError::ReservedStreamId);
340 }
341 Ok(())
342}