1use super::super::control::{
4 Http2Goaway, Http2Ping, Http2PriorityFrame, Http2RstStream, Http2WindowIncrement,
5 Http2WindowUpdate,
6};
7use super::super::error::Http2BuildError;
8use super::super::frame::Http2Frame;
9use super::super::priority::Http2Priority;
10use super::super::settings::{Http2Setting, Http2Settings};
11use super::super::types::{Http2ErrorCode, Http2FrameType, Http2StreamId};
12use super::raw::{FRAME_HEADER_LENGTH, MAXIMUM_PAYLOAD, write_frame_envelope};
13
14pub struct Http2SettingsBuilder<'a, 'b> {
16 buffer: &'a mut [u8],
17 flags: u8,
18 settings: &'b [Http2Setting],
19}
20
21impl<'a, 'b> Http2SettingsBuilder<'a, 'b> {
22 pub fn new(buffer: &'a mut [u8], flags: u8, settings: &'b [Http2Setting]) -> Self {
24 Self {
25 buffer,
26 flags,
27 settings,
28 }
29 }
30
31 pub fn build(self) -> Result<Http2Settings<'a>, Http2BuildError> {
33 self.build_with_maximum(MAXIMUM_PAYLOAD)
34 }
35
36 pub fn build_with_maximum(
38 self,
39 maximum_payload: usize,
40 ) -> Result<Http2Settings<'a>, Http2BuildError> {
41 for setting in self.settings.iter().copied() {
42 if !setting.has_valid_intrinsic_value() {
43 return Err(Http2BuildError::InvalidSettingValue {
44 id: setting.id(),
45 value: setting.value(),
46 });
47 }
48 }
49 let payload_length =
50 self.settings
51 .len()
52 .checked_mul(6)
53 .ok_or(Http2BuildError::PayloadTooLarge {
54 maximum: maximum_payload.min(MAXIMUM_PAYLOAD),
55 actual: self.settings.len(),
56 })?;
57 if self.flags & 0x1 != 0 && payload_length != 0 {
58 return Err(Http2BuildError::SettingsAckPayload {
59 actual: payload_length,
60 });
61 }
62 let bytes = write_frame_envelope(
63 self.buffer,
64 payload_length,
65 Http2FrameType::SETTINGS,
66 self.flags,
67 Http2StreamId::new(0),
68 maximum_payload,
69 )?;
70 for (index, setting) in self.settings.iter().copied().enumerate() {
71 let offset = FRAME_HEADER_LENGTH + index * 6;
72 bytes[offset..offset + 2].copy_from_slice(&setting.id().raw().to_be_bytes());
73 bytes[offset + 2..offset + 6].copy_from_slice(&setting.value().to_be_bytes());
74 }
75 Ok(Http2Settings::from_validated(Http2Frame::from_validated(
76 bytes,
77 )))
78 }
79}
80
81pub struct Http2GoawayBuilder<'a, 'b> {
83 buffer: &'a mut [u8],
84 flags: u8,
85 last_stream_id: Http2StreamId,
86 error_code: Http2ErrorCode,
87 additional_debug_data: &'b [u8],
88}
89
90impl<'a, 'b> Http2GoawayBuilder<'a, 'b> {
91 pub fn new(
93 buffer: &'a mut [u8],
94 flags: u8,
95 last_stream_id: Http2StreamId,
96 error_code: Http2ErrorCode,
97 additional_debug_data: &'b [u8],
98 ) -> Self {
99 Self {
100 buffer,
101 flags,
102 last_stream_id,
103 error_code,
104 additional_debug_data,
105 }
106 }
107
108 pub fn build(self) -> Result<Http2Goaway<'a>, Http2BuildError> {
110 self.build_with_maximum(MAXIMUM_PAYLOAD)
111 }
112
113 pub fn build_with_maximum(
115 self,
116 maximum_payload: usize,
117 ) -> Result<Http2Goaway<'a>, Http2BuildError> {
118 if self.last_stream_id.has_reserved_bit() {
119 return Err(Http2BuildError::ReservedLastStreamId);
120 }
121 let payload_length = self.additional_debug_data.len().checked_add(8).ok_or(
122 Http2BuildError::PayloadTooLarge {
123 maximum: maximum_payload.min(MAXIMUM_PAYLOAD),
124 actual: self.additional_debug_data.len(),
125 },
126 )?;
127 let bytes = write_frame_envelope(
128 self.buffer,
129 payload_length,
130 Http2FrameType::GOAWAY,
131 self.flags,
132 Http2StreamId::new(0),
133 maximum_payload,
134 )?;
135 bytes[FRAME_HEADER_LENGTH..FRAME_HEADER_LENGTH + 4]
136 .copy_from_slice(&self.last_stream_id.raw().to_be_bytes());
137 bytes[FRAME_HEADER_LENGTH + 4..FRAME_HEADER_LENGTH + 8]
138 .copy_from_slice(&self.error_code.raw().to_be_bytes());
139 bytes[FRAME_HEADER_LENGTH + 8..].copy_from_slice(self.additional_debug_data);
140 Ok(Http2Goaway::from_validated(
141 Http2Frame::from_validated(bytes),
142 self.last_stream_id,
143 self.error_code,
144 ))
145 }
146}
147
148pub struct Http2PriorityFrameBuilder<'a> {
150 buffer: &'a mut [u8],
151 stream_id: Http2StreamId,
152 flags: u8,
153 priority: Http2Priority,
154}
155
156impl<'a> Http2PriorityFrameBuilder<'a> {
157 pub fn new(
159 buffer: &'a mut [u8],
160 stream_id: Http2StreamId,
161 flags: u8,
162 priority: Http2Priority,
163 ) -> Self {
164 Self {
165 buffer,
166 stream_id,
167 flags,
168 priority,
169 }
170 }
171
172 pub fn build(self) -> Result<Http2PriorityFrame<'a>, Http2BuildError> {
174 self.build_with_maximum(MAXIMUM_PAYLOAD)
175 }
176
177 pub fn build_with_maximum(
179 self,
180 maximum_payload: usize,
181 ) -> Result<Http2PriorityFrame<'a>, Http2BuildError> {
182 validate_required_stream_id(self.stream_id)?;
183 let bytes = write_frame_envelope(
184 self.buffer,
185 5,
186 Http2FrameType::PRIORITY,
187 self.flags,
188 self.stream_id,
189 maximum_payload,
190 )?;
191 bytes[FRAME_HEADER_LENGTH..FRAME_HEADER_LENGTH + 4]
192 .copy_from_slice(&self.priority.raw_dependency().to_be_bytes());
193 bytes[FRAME_HEADER_LENGTH + 4] = self.priority.weight();
194 Ok(Http2PriorityFrame::from_validated(
195 Http2Frame::from_validated(bytes),
196 self.priority,
197 ))
198 }
199}
200
201pub struct Http2RstStreamBuilder<'a> {
203 buffer: &'a mut [u8],
204 stream_id: Http2StreamId,
205 flags: u8,
206 error_code: Http2ErrorCode,
207}
208
209impl<'a> Http2RstStreamBuilder<'a> {
210 pub fn new(
212 buffer: &'a mut [u8],
213 stream_id: Http2StreamId,
214 flags: u8,
215 error_code: Http2ErrorCode,
216 ) -> Self {
217 Self {
218 buffer,
219 stream_id,
220 flags,
221 error_code,
222 }
223 }
224
225 pub fn build(self) -> Result<Http2RstStream<'a>, Http2BuildError> {
227 self.build_with_maximum(MAXIMUM_PAYLOAD)
228 }
229
230 pub fn build_with_maximum(
232 self,
233 maximum_payload: usize,
234 ) -> Result<Http2RstStream<'a>, Http2BuildError> {
235 validate_required_stream_id(self.stream_id)?;
236 let bytes = write_frame_envelope(
237 self.buffer,
238 4,
239 Http2FrameType::RST_STREAM,
240 self.flags,
241 self.stream_id,
242 maximum_payload,
243 )?;
244 bytes[FRAME_HEADER_LENGTH..].copy_from_slice(&self.error_code.raw().to_be_bytes());
245 Ok(Http2RstStream::from_validated(
246 Http2Frame::from_validated(bytes),
247 self.error_code,
248 ))
249 }
250}
251
252pub struct Http2PingBuilder<'a, 'b> {
254 buffer: &'a mut [u8],
255 flags: u8,
256 opaque_data: &'b [u8; 8],
257}
258
259impl<'a, 'b> Http2PingBuilder<'a, 'b> {
260 pub fn new(buffer: &'a mut [u8], flags: u8, opaque_data: &'b [u8; 8]) -> Self {
262 Self {
263 buffer,
264 flags,
265 opaque_data,
266 }
267 }
268
269 pub fn build(self) -> Result<Http2Ping<'a>, Http2BuildError> {
271 self.build_with_maximum(MAXIMUM_PAYLOAD)
272 }
273
274 pub fn build_with_maximum(
276 self,
277 maximum_payload: usize,
278 ) -> Result<Http2Ping<'a>, Http2BuildError> {
279 let bytes = write_frame_envelope(
280 self.buffer,
281 8,
282 Http2FrameType::PING,
283 self.flags,
284 Http2StreamId::new(0),
285 maximum_payload,
286 )?;
287 bytes[FRAME_HEADER_LENGTH..].copy_from_slice(self.opaque_data);
288 let opaque_data = bytes[FRAME_HEADER_LENGTH..].try_into().map_err(|_| {
289 Http2BuildError::BufferTooShort {
290 required: FRAME_HEADER_LENGTH + 8,
291 available: bytes.len(),
292 }
293 })?;
294 Ok(Http2Ping::from_validated(
295 Http2Frame::from_validated(bytes),
296 opaque_data,
297 ))
298 }
299}
300
301pub struct Http2WindowUpdateBuilder<'a> {
303 buffer: &'a mut [u8],
304 stream_id: Http2StreamId,
305 flags: u8,
306 increment: Http2WindowIncrement,
307}
308
309impl<'a> Http2WindowUpdateBuilder<'a> {
310 pub fn new(
312 buffer: &'a mut [u8],
313 stream_id: Http2StreamId,
314 flags: u8,
315 increment: Http2WindowIncrement,
316 ) -> Self {
317 Self {
318 buffer,
319 stream_id,
320 flags,
321 increment,
322 }
323 }
324
325 pub fn build(self) -> Result<Http2WindowUpdate<'a>, Http2BuildError> {
327 self.build_with_maximum(MAXIMUM_PAYLOAD)
328 }
329
330 pub fn build_with_maximum(
332 self,
333 maximum_payload: usize,
334 ) -> Result<Http2WindowUpdate<'a>, Http2BuildError> {
335 if self.stream_id.has_reserved_bit() {
336 return Err(Http2BuildError::ReservedStreamId);
337 }
338 if self.increment.has_reserved_bit() {
339 return Err(Http2BuildError::ReservedWindowIncrement);
340 }
341 if self.increment.value() == 0 {
342 return Err(Http2BuildError::ZeroWindowIncrement);
343 }
344 let bytes = write_frame_envelope(
345 self.buffer,
346 4,
347 Http2FrameType::WINDOW_UPDATE,
348 self.flags,
349 self.stream_id,
350 maximum_payload,
351 )?;
352 bytes[FRAME_HEADER_LENGTH..].copy_from_slice(&self.increment.raw().to_be_bytes());
353 Ok(Http2WindowUpdate::from_validated(
354 Http2Frame::from_validated(bytes),
355 self.increment,
356 ))
357 }
358}
359
360fn validate_required_stream_id(stream_id: Http2StreamId) -> Result<(), Http2BuildError> {
361 if stream_id.value() == 0 {
362 return Err(Http2BuildError::ZeroStreamId);
363 }
364 if stream_id.has_reserved_bit() {
365 return Err(Http2BuildError::ReservedStreamId);
366 }
367 Ok(())
368}