1use hpack::Encoder;
2
3pub enum FrameType {
4 DATA = 0x00,
5 HEADERS = 0x01,
6 PRIORITY = 0x02,
7 RSTSTREAM = 0x03,
8 SETTINGS = 0x04,
9 PUSHPROMISE = 0x05,
10 PING = 0x06,
11 GOAWAY = 0x07,
12 WINDOWUPDATE = 0x08,
13 CONTINUATION = 0x09,
14}
15
16impl TryFrom<u8> for FrameType {
17 type Error = &'static str;
18
19 fn try_from(value: u8) -> Result<Self, Self::Error> {
20 match value {
21 0x00 => Ok(FrameType::DATA),
22 0x01 => Ok(FrameType::HEADERS),
23 0x02 => Ok(FrameType::PRIORITY),
24 0x03 => Ok(FrameType::RSTSTREAM),
25 0x04 => Ok(FrameType::SETTINGS),
26 0x05 => Ok(FrameType::PUSHPROMISE),
27 0x06 => Ok(FrameType::PING),
28 0x07 => Ok(FrameType::GOAWAY),
29 0x08 => Ok(FrameType::WINDOWUPDATE),
30 0x09 => Ok(FrameType::CONTINUATION),
31 _ => Err("Invalid frame type"),
32 }
33 }
34}
35
36impl TryInto<u8> for FrameType {
37 type Error = &'static str;
38
39 fn try_into(self) -> Result<u8, Self::Error> {
40 match self {
41 FrameType::DATA => Ok(0x00),
42 FrameType::HEADERS => Ok(0x01),
43 FrameType::PRIORITY => Ok(0x02),
44 FrameType::RSTSTREAM => Ok(0x03),
45 FrameType::SETTINGS => Ok(0x04),
46 FrameType::PUSHPROMISE => Ok(0x05),
47 FrameType::PING => Ok(0x06),
48 FrameType::GOAWAY => Ok(0x07),
49 FrameType::WINDOWUPDATE => Ok(0x08),
50 FrameType::CONTINUATION => Ok(0x09),
51 }
52 }
53}
54
55pub enum FrameFlags {
56 ENDSTREAM = 0x01,
57 ENDHEADERS = 0x04,
58 PADDED = 0x08,
59 PRIORITY = 0x20,
60 NONE = 0x00,
61}
62
63impl TryFrom<u8> for FrameFlags {
64 type Error = &'static str;
65
66 fn try_from(value: u8) -> Result<Self, Self::Error> {
67 match value {
68 0x01 => Ok(FrameFlags::ENDSTREAM),
69 0x04 => Ok(FrameFlags::ENDHEADERS),
70 0x08 => Ok(FrameFlags::PADDED),
71 0x20 => Ok(FrameFlags::PRIORITY),
72 _ => Ok(FrameFlags::NONE),
73 }
74 }
75}
76
77impl TryInto<u8> for FrameFlags {
78 type Error = &'static str;
79
80 fn try_into(self) -> Result<u8, Self::Error> {
81 match self {
82 FrameFlags::ENDSTREAM => Ok(0x01),
83 FrameFlags::ENDHEADERS => Ok(0x04),
84 FrameFlags::PADDED => Ok(0x08),
85 FrameFlags::PRIORITY => Ok(0x20),
86 FrameFlags::NONE => Ok(0x00),
87 }
88 }
89}
90
91pub struct FrameWriter {
92 pub frame_type: FrameType,
93 pub flags: FrameFlags,
94 pub stream_id: u32,
95 pub payload_len: u32,
96 pub payload: Vec<u8>,
97}
98
99impl FrameWriter {
100 pub fn new(frame_type: FrameType, flags: FrameFlags, stream_id: u32, payload: Vec<u8>) -> Self {
101 FrameWriter {
102 frame_type,
103 flags,
104 stream_id,
105 payload_len: payload.len() as u32,
106 payload,
107 }
108 }
109
110 pub fn new_frame_writer(
111 frame_type: FrameType,
112 flags: FrameFlags,
113 stream_id: u32
114 ) -> Result<Self, Box<dyn std::error::Error>> {
115 let mut headers = FrameHeaders::new();
116 headers.add_header(":method".to_string(), "GET".to_string());
117 headers.add_header(":path".to_string(), "/".to_string());
118 headers.add_header(":scheme".to_string(), "https".to_string());
119 headers.add_header(":authority".to_string(), "example.com".to_string());
120
121 let payload = headers.serialize();
122
123 Ok(FrameWriter {
126 frame_type,
127 flags,
128 stream_id,
129 payload_len: payload.len() as u32,
130 payload: payload,
131 })
132 }
133
134 pub fn serialize(self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
155 let mut serialized = Vec::with_capacity(9 + (self.payload_len as usize));
156
157 serialized.extend_from_slice(&self.payload_len.to_be_bytes()[1..]);
158 serialized.push(FrameType::try_into(self.frame_type)?);
159 serialized.push(FrameFlags::try_into(self.flags)?);
160 serialized.extend_from_slice(
161 &[
162 (self.stream_id >> 24) as u8,
163 (self.stream_id >> 16) as u8,
164 (self.stream_id >> 8) as u8,
165 self.stream_id as u8,
166 ]
167 );
168 serialized.extend_from_slice(&self.payload);
170
171 Ok(serialized)
172 }
173}
174
175pub struct FrameReader {
176 pub frame_type: FrameType,
177 pub flags: FrameFlags,
178 pub stream_id: u32,
179 pub payload_len: u32,
180 pub payload: Vec<u8>,
181}
182
183impl FrameReader {
184 pub async fn read_frame(buf: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
189 let payload_len = ((buf[0] as u32) << 16) | ((buf[1] as u32) << 8) | (buf[2] as u32);
190
191 if buf.len() < 9 + (payload_len as usize) {
192 return Err("Buffer too small".into());
193 }
194
195 let frame_type = FrameType::try_from(buf[3])?;
196 let flags = FrameFlags::try_from(buf[4])?;
197 let stream_id = u32::from_be_bytes([buf[5], buf[6], buf[7], buf[8]]) & 0x7fff_ffff;
198 let payload = buf[9..9 + (payload_len as usize)].to_vec();
199
200 Ok(FrameReader {
201 frame_type,
202 flags,
203 stream_id,
204 payload_len,
205 payload,
206 })
207 }
208
209 pub async fn parse_settings_payload(&self) -> Vec<Setting> {
210 let payload = &self.payload;
211
212 if self.payload_len == 0 {
213 return Vec::new();
214 }
215
216 let mut i = 0;
217 let mut settings = Vec::new();
218 while i < payload.len() {
219 if i + 6 > payload.len() {
220 break;
221 }
222
223 let id = u16::from_be_bytes([payload[i], payload[i + 1]]);
224 let value = u32::from_be_bytes([
225 payload[i + 2],
226 payload[i + 3],
227 payload[i + 4],
228 payload[i + 5],
229 ]);
230
231 settings.push(Setting::new(id, value));
232
233 i += 6;
234 }
235
236 settings
237 }
238}
239
240pub struct HeadersBuilder {
241 headers: Vec<(String, String)>,
242}
243
244impl HeadersBuilder {
245 pub fn new() -> Self {
246 HeadersBuilder { headers: Vec::new() }
247 }
248
249 pub fn add_header(mut self, name: String, value: String) -> Self {
250 self.headers.push((name, value));
251 self
252 }
253
254 pub fn build(
255 self,
256 stream_id: u32
257 ) -> Result<FrameWriter, Box<dyn std::error::Error>> {
259 let headers = FrameHeaders::from_pairs(self.headers);
260 let payload = headers.serialize();
261
262 Ok(FrameWriter::new(FrameType::HEADERS, FrameFlags::ENDHEADERS, stream_id, payload))
263 }
264}
265
266pub struct FrameHeaders {
267 headers: Vec<(String, String)>,
268}
269
270impl FrameHeaders {
271 pub fn new() -> Self {
272 FrameHeaders { headers: Vec::new() }
273 }
274
275 pub fn from_pairs(headers: Vec<(String, String)>) -> Self {
276 FrameHeaders { headers }
277 }
278
279 pub fn add_header(&mut self, name: String, value: String) {
280 self.headers.push((name, value));
281 }
282
283 pub fn serialize(&self) -> Vec<u8> {
284 let mut encoder = Encoder::new();
285 let headers: Vec<(&[u8], &[u8])> = self.headers
286 .iter()
287 .map(|(name, value)| (name.as_bytes(), value.as_bytes()))
288 .collect();
289 encoder.encode(headers)
290 }
291}
292
293pub struct Setting {
294 pub id: u16,
295 pub value: u32,
296}
297
298impl Setting {
299 pub fn new(id: u16, value: u32) -> Self {
300 Setting { id, value }
301 }
302}
303
304pub struct Settings {
305 pub max_concurrent_streams: Setting,
306 pub initial_window_size: Setting,
307 pub max_frame_size: Setting,
308 pub max_header_list_size: Setting,
309}
310
311impl Settings {
312 pub async fn new() -> Self {
313 Settings {
314 max_concurrent_streams: Setting::new(0x03, 100),
315 initial_window_size: Setting::new(0x04, 65535),
316 max_frame_size: Setting::new(0x05, 16384),
317 max_header_list_size: Setting::new(0x06, 262144),
318 }
319 }
320
321 pub async fn serialize(&self) -> Vec<u8> {
322 let mut payload = Vec::new();
323
324 for setting in [
325 &self.max_concurrent_streams,
326 &self.initial_window_size,
327 &self.max_frame_size,
328 &self.max_header_list_size,
329 ] {
330 payload.extend_from_slice(&setting.id.to_be_bytes());
331 payload.extend_from_slice(&setting.value.to_be_bytes());
332 }
333
334 let mut serialized = Vec::with_capacity(9 + payload.len());
335
336 serialized.extend_from_slice(&(payload.len() as u32).to_be_bytes()[1..]);
337 serialized.extend_from_slice(&[4, 0]);
338 serialized.extend_from_slice(&(0u32).to_be_bytes());
339 serialized.extend_from_slice(&payload);
342
343 serialized
344 }
345}