1use bytes::{Buf, BufMut, Bytes, BytesMut};
7
8pub const FRAME_HEADER_SIZE: usize = 9;
10
11pub const DEFAULT_MAX_FRAME_SIZE: u32 = 16384;
13
14pub const CONNECTION_PREFACE: &[u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19#[repr(u8)]
20pub enum FrameType {
21 Data = 0x0,
22 Headers = 0x1,
23 Priority = 0x2,
24 RstStream = 0x3,
25 Settings = 0x4,
26 PushPromise = 0x5,
27 Ping = 0x6,
28 GoAway = 0x7,
29 WindowUpdate = 0x8,
30 Continuation = 0x9,
31 Unknown(u8),
32}
33
34impl From<u8> for FrameType {
35 fn from(v: u8) -> Self {
36 match v {
37 0x0 => Self::Data,
38 0x1 => Self::Headers,
39 0x2 => Self::Priority,
40 0x3 => Self::RstStream,
41 0x4 => Self::Settings,
42 0x5 => Self::PushPromise,
43 0x6 => Self::Ping,
44 0x7 => Self::GoAway,
45 0x8 => Self::WindowUpdate,
46 0x9 => Self::Continuation,
47 other => Self::Unknown(other),
48 }
49 }
50}
51
52impl From<FrameType> for u8 {
53 fn from(ft: FrameType) -> u8 {
54 match ft {
55 FrameType::Data => 0x0,
56 FrameType::Headers => 0x1,
57 FrameType::Priority => 0x2,
58 FrameType::RstStream => 0x3,
59 FrameType::Settings => 0x4,
60 FrameType::PushPromise => 0x5,
61 FrameType::Ping => 0x6,
62 FrameType::GoAway => 0x7,
63 FrameType::WindowUpdate => 0x8,
64 FrameType::Continuation => 0x9,
65 FrameType::Unknown(v) => v,
66 }
67 }
68}
69
70pub mod flags {
72 pub const END_STREAM: u8 = 0x1;
73 pub const ACK: u8 = 0x1; pub const END_HEADERS: u8 = 0x4;
75 pub const PADDED: u8 = 0x8;
76 pub const PRIORITY: u8 = 0x20;
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq)]
81#[repr(u16)]
82pub enum SettingsId {
83 HeaderTableSize = 0x1,
84 EnablePush = 0x2,
85 MaxConcurrentStreams = 0x3,
86 InitialWindowSize = 0x4,
87 MaxFrameSize = 0x5,
88 MaxHeaderListSize = 0x6,
89}
90
91impl From<u16> for SettingsId {
92 fn from(v: u16) -> Self {
93 match v {
94 0x1 => Self::HeaderTableSize,
95 0x2 => Self::EnablePush,
96 0x3 => Self::MaxConcurrentStreams,
97 0x4 => Self::InitialWindowSize,
98 0x5 => Self::MaxFrameSize,
99 0x6 => Self::MaxHeaderListSize,
100 _ => Self::HeaderTableSize, }
102 }
103}
104
105impl From<SettingsId> for u16 {
106 fn from(id: SettingsId) -> Self {
107 id as u16
108 }
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113#[repr(u32)]
114pub enum ErrorCode {
115 NoError = 0x0,
116 ProtocolError = 0x1,
117 InternalError = 0x2,
118 FlowControlError = 0x3,
119 SettingsTimeout = 0x4,
120 StreamClosed = 0x5,
121 FrameSizeError = 0x6,
122 RefusedStream = 0x7,
123 Cancel = 0x8,
124 CompressionError = 0x9,
125 ConnectError = 0xa,
126 EnhanceYourCalm = 0xb,
127 InadequateSecurity = 0xc,
128 Http11Required = 0xd,
129}
130
131#[derive(Debug, Clone)]
133pub struct FrameHeader {
134 pub length: u32,
135 pub frame_type: FrameType,
136 pub flags: u8,
137 pub stream_id: u32,
138}
139
140impl FrameHeader {
141 pub fn parse(buf: &[u8]) -> Option<Self> {
144 if buf.len() < FRAME_HEADER_SIZE {
145 return None;
146 }
147
148 let length = ((buf[0] as u32) << 16) | ((buf[1] as u32) << 8) | (buf[2] as u32);
149 let frame_type = FrameType::from(buf[3]);
150 let flags = buf[4];
151
152 if (buf[5] & 0x80) != 0 {
155 return None; }
157
158 let stream_id = ((buf[5] as u32 & 0x7f) << 24)
159 | ((buf[6] as u32) << 16)
160 | ((buf[7] as u32) << 8)
161 | (buf[8] as u32);
162
163 Some(Self {
164 length,
165 frame_type,
166 flags,
167 stream_id,
168 })
169 }
170
171 pub fn serialize(&self, buf: &mut BytesMut) {
173 buf.put_u8((self.length >> 16) as u8);
175 buf.put_u8((self.length >> 8) as u8);
176 buf.put_u8(self.length as u8);
177 buf.put_u8(self.frame_type.into());
179 buf.put_u8(self.flags);
181 buf.put_u32(self.stream_id & 0x7fffffff);
184 }
185}
186
187#[derive(Debug, Clone)]
189pub struct SettingsFrame {
190 pub settings: Vec<(u16, u32)>,
194 pub ack: bool,
195}
196
197impl SettingsFrame {
198 pub fn new() -> Self {
200 Self {
201 settings: Vec::new(),
202 ack: false,
203 }
204 }
205
206 pub fn ack() -> Self {
208 Self {
209 settings: Vec::new(),
210 ack: true,
211 }
212 }
213
214 pub fn set<T: Into<u16>>(&mut self, id: T, value: u32) -> &mut Self {
216 self.settings.push((id.into(), value));
217 self
218 }
219
220 pub fn serialize(&self) -> BytesMut {
222 let payload_len = if self.ack { 0 } else { self.settings.len() * 6 };
223 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + payload_len);
224
225 let header = FrameHeader {
227 length: payload_len as u32,
228 frame_type: FrameType::Settings,
229 flags: if self.ack { flags::ACK } else { 0 },
230 stream_id: 0, };
232 header.serialize(&mut buf);
233
234 if !self.ack {
236 for (id, value) in &self.settings {
237 buf.put_u16(*id);
238 buf.put_u32(*value);
239 }
240 }
241
242 buf
243 }
244
245 pub fn parse(flags: u8, mut payload: Bytes) -> Self {
247 let ack = (flags & flags::ACK) != 0;
248 let mut settings = Vec::new();
249
250 while payload.remaining() >= 6 {
251 let id = payload.get_u16();
252 let value = payload.get_u32();
253 settings.push((id, value));
254 }
255
256 Self { settings, ack }
257 }
258}
259
260impl Default for SettingsFrame {
261 fn default() -> Self {
262 Self::new()
263 }
264}
265
266#[derive(Debug, Clone)]
268pub struct WindowUpdateFrame {
269 pub stream_id: u32,
270 pub increment: u32,
271}
272
273impl WindowUpdateFrame {
274 pub fn new(stream_id: u32, increment: u32) -> Self {
276 Self {
277 stream_id,
278 increment,
279 }
280 }
281
282 pub fn serialize(&self) -> BytesMut {
284 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + 4);
285
286 let header = FrameHeader {
287 length: 4,
288 frame_type: FrameType::WindowUpdate,
289 flags: 0,
290 stream_id: self.stream_id,
291 };
292 header.serialize(&mut buf);
293
294 buf.put_u32(self.increment & 0x7fffffff);
296
297 buf
298 }
299
300 pub fn parse(stream_id: u32, mut payload: Bytes) -> Option<Self> {
303 if payload.remaining() < 4 {
304 return None;
305 }
306 let increment_raw = payload.get_u32();
307 let increment = increment_raw & 0x7fffffff;
308
309 if increment == 0 {
312 return None;
313 }
314
315 Some(Self {
316 stream_id,
317 increment,
318 })
319 }
320}
321
322#[derive(Debug, Clone)]
324pub struct HeadersFrame {
325 pub stream_id: u32,
326 pub header_block: Bytes,
327 pub end_stream: bool,
328 pub end_headers: bool,
329 pub priority: Option<PriorityData>,
330}
331
332#[derive(Debug, Clone, Copy)]
334pub struct PriorityData {
335 pub exclusive: bool,
336 pub stream_dependency: u32,
337 pub weight: u8,
338}
339
340impl HeadersFrame {
341 pub fn new(stream_id: u32, header_block: Bytes) -> Self {
343 Self {
344 stream_id,
345 header_block,
346 end_stream: false,
347 end_headers: true,
348 priority: None,
349 }
350 }
351
352 pub fn end_stream(mut self, end: bool) -> Self {
354 self.end_stream = end;
355 self
356 }
357
358 pub fn with_priority(mut self, priority: PriorityData) -> Self {
360 self.priority = Some(priority);
361 self
362 }
363
364 pub fn end_headers(mut self, end: bool) -> Self {
366 self.end_headers = end;
367 self
368 }
369
370 pub fn serialize(&self) -> BytesMut {
374 let priority_len = if self.priority.is_some() { 5 } else { 0 };
375 let payload_len = priority_len + self.header_block.len();
376 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + payload_len);
377
378 let mut frame_flags = 0u8;
379 if self.end_stream {
380 frame_flags |= flags::END_STREAM;
381 }
382 if self.end_headers {
383 frame_flags |= flags::END_HEADERS;
384 }
385 if self.priority.is_some() {
386 frame_flags |= flags::PRIORITY;
387 }
388
389 let header = FrameHeader {
390 length: payload_len as u32,
391 frame_type: FrameType::Headers,
392 flags: frame_flags,
393 stream_id: self.stream_id,
394 };
395 header.serialize(&mut buf);
396
397 if let Some(priority) = &self.priority {
399 let dep = if priority.exclusive {
400 priority.stream_dependency | 0x80000000
401 } else {
402 priority.stream_dependency
403 };
404 buf.put_u32(dep);
405 buf.put_u8(priority.weight);
406 }
407
408 buf.extend_from_slice(&self.header_block);
410
411 buf
412 }
413
414 pub fn parse(stream_id: u32, flags: u8, mut payload: Bytes) -> Result<Self, String> {
417 if stream_id == 0 {
418 return Err("HEADERS frame must have non-zero stream ID".to_string());
419 }
420
421 let end_stream = (flags & flags::END_STREAM) != 0;
422 let end_headers = (flags & flags::END_HEADERS) != 0;
423 let padded = (flags & flags::PADDED) != 0;
424 let priority_flag = (flags & flags::PRIORITY) != 0;
425
426 let pad_len = if padded {
428 if payload.remaining() < 1 {
429 return Err("PADDED HEADERS frame missing padding length".to_string());
430 }
431 let pad_len = payload.get_u8() as usize;
432 if pad_len >= payload.remaining() {
433 return Err("Padding length exceeds payload size".to_string());
434 }
435 pad_len
436 } else {
437 0
438 };
439
440 let priority = if priority_flag {
442 if payload.remaining() < 5 {
443 return Err("HEADERS frame with PRIORITY flag missing priority data".to_string());
444 }
445 let dep_raw = payload.get_u32();
446 let exclusive = (dep_raw & 0x80000000) != 0;
447 let stream_dependency = dep_raw & 0x7fffffff;
448 let weight = payload.get_u8();
449 Some(PriorityData {
450 exclusive,
451 stream_dependency,
452 weight,
453 })
454 } else {
455 None
456 };
457
458 let header_block_len = payload.remaining() - pad_len;
460 if header_block_len == 0 {
461 return Err("HEADERS frame header block is empty".to_string());
462 }
463 let header_block = payload.copy_to_bytes(header_block_len);
464 payload.advance(pad_len);
466
467 Ok(Self {
468 stream_id,
469 header_block,
470 end_stream,
471 end_headers,
472 priority,
473 })
474 }
475}
476
477#[derive(Debug, Clone)]
479pub struct ContinuationFrame {
480 pub stream_id: u32,
481 pub flags: u8,
482 pub header_fragment: Bytes,
483}
484
485impl ContinuationFrame {
486 pub fn new(stream_id: u32, header_fragment: Bytes, end_headers: bool) -> Self {
488 let flags = if end_headers { flags::END_HEADERS } else { 0 };
489 Self {
490 stream_id,
491 flags,
492 header_fragment,
493 }
494 }
495
496 pub fn end_headers(&self) -> bool {
498 self.flags & flags::END_HEADERS != 0
499 }
500
501 pub fn serialize(&self) -> BytesMut {
503 let payload_len = self.header_fragment.len();
504 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + payload_len);
505
506 let header = FrameHeader {
507 length: payload_len as u32,
508 frame_type: FrameType::Continuation,
509 flags: self.flags,
510 stream_id: self.stream_id,
511 };
512 header.serialize(&mut buf);
513
514 buf.extend_from_slice(&self.header_fragment);
516
517 buf
518 }
519
520 pub fn parse(stream_id: u32, flags: u8, payload: Bytes) -> Result<Self, String> {
522 if stream_id == 0 {
523 return Err("CONTINUATION frame must have non-zero stream ID".to_string());
524 }
525
526 Ok(Self {
527 stream_id,
528 flags,
529 header_fragment: payload,
530 })
531 }
532}
533
534#[derive(Debug, Clone)]
536pub struct DataFrame {
537 pub stream_id: u32,
538 pub data: Bytes,
539 pub end_stream: bool,
540 pub padding_len: u8,
541}
542
543impl DataFrame {
544 pub fn new(stream_id: u32, data: Bytes) -> Self {
546 Self {
547 stream_id,
548 data,
549 end_stream: false,
550 padding_len: 0,
551 }
552 }
553
554 pub fn end_stream(mut self, end: bool) -> Self {
556 self.end_stream = end;
557 self
558 }
559
560 pub fn with_padding(mut self, padding_len: u8) -> Self {
562 self.padding_len = padding_len;
563 self
564 }
565
566 pub fn serialize(&self) -> BytesMut {
568 let payload_len = if self.padding_len > 0 {
569 1 + self.data.len() + self.padding_len as usize
571 } else {
572 self.data.len()
573 };
574
575 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + payload_len);
576
577 let mut frame_flags = if self.end_stream {
578 flags::END_STREAM
579 } else {
580 0
581 };
582 if self.padding_len > 0 {
583 frame_flags |= flags::PADDED;
584 }
585
586 let header = FrameHeader {
587 length: payload_len as u32,
588 frame_type: FrameType::Data,
589 flags: frame_flags,
590 stream_id: self.stream_id,
591 };
592 header.serialize(&mut buf);
593
594 if self.padding_len > 0 {
596 buf.put_u8(self.padding_len);
597 }
598
599 buf.extend_from_slice(&self.data);
601
602 if self.padding_len > 0 {
604 buf.extend_from_slice(&vec![0u8; self.padding_len as usize]);
605 }
606
607 buf
608 }
609
610 pub fn parse(stream_id: u32, flags: u8, mut payload: Bytes) -> Result<Self, String> {
613 if stream_id == 0 {
614 return Err("DATA frame must have non-zero stream ID".to_string());
615 }
616
617 let end_stream = (flags & flags::END_STREAM) != 0;
618 let padded = (flags & flags::PADDED) != 0;
619
620 let (data, padding_len) = if padded {
621 if payload.remaining() < 1 {
622 return Err("PADDED DATA frame missing padding length".to_string());
623 }
624 let pad_len = payload.get_u8() as usize;
625 if pad_len >= payload.remaining() {
626 return Err("Padding length exceeds payload size".to_string());
627 }
628 let data_len = payload.remaining() - pad_len;
629 let data = payload.copy_to_bytes(data_len);
630 payload.advance(pad_len);
632 (data, pad_len as u8)
633 } else {
634 (payload, 0)
635 };
636
637 Ok(Self {
638 stream_id,
639 data,
640 end_stream,
641 padding_len,
642 })
643 }
644}
645
646#[derive(Debug, Clone)]
648pub struct PingFrame {
649 pub ack: bool,
650 pub data: [u8; 8],
651}
652
653impl PingFrame {
654 pub fn new(data: [u8; 8]) -> Self {
656 Self { ack: false, data }
657 }
658
659 pub fn ack(data: [u8; 8]) -> Self {
661 Self { ack: true, data }
662 }
663
664 pub fn serialize(&self) -> BytesMut {
666 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + 8);
667
668 let header = FrameHeader {
669 length: 8,
670 frame_type: FrameType::Ping,
671 flags: if self.ack { flags::ACK } else { 0 },
672 stream_id: 0,
673 };
674 header.serialize(&mut buf);
675 buf.extend_from_slice(&self.data);
676
677 buf
678 }
679
680 pub fn parse(flags: u8, payload: &[u8]) -> Option<Self> {
682 if payload.len() != 8 {
683 return None;
684 }
685 let mut data = [0u8; 8];
686 data.copy_from_slice(payload);
687 Some(Self {
688 ack: (flags & flags::ACK) != 0,
689 data,
690 })
691 }
692}
693
694#[derive(Debug, Clone)]
696pub struct GoAwayFrame {
697 pub last_stream_id: u32,
698 pub error_code: ErrorCode,
699 pub debug_data: Bytes,
700}
701
702impl GoAwayFrame {
703 pub fn new(last_stream_id: u32, error_code: ErrorCode) -> Self {
705 Self {
706 last_stream_id,
707 error_code,
708 debug_data: Bytes::new(),
709 }
710 }
711
712 pub fn serialize(&self) -> BytesMut {
714 let payload_len = 8 + self.debug_data.len();
715 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + payload_len);
716
717 let header = FrameHeader {
718 length: payload_len as u32,
719 frame_type: FrameType::GoAway,
720 flags: 0,
721 stream_id: 0,
722 };
723 header.serialize(&mut buf);
724 buf.put_u32(self.last_stream_id & 0x7fffffff);
725 buf.put_u32(self.error_code as u32);
726 buf.extend_from_slice(&self.debug_data);
727
728 buf
729 }
730
731 pub fn parse(mut payload: Bytes) -> Option<Self> {
733 if payload.remaining() < 8 {
734 return None;
735 }
736 let last_stream_id = payload.get_u32() & 0x7fffffff;
737 let error_code_raw = payload.get_u32();
738 let error_code = match error_code_raw {
739 0x0 => ErrorCode::NoError,
740 0x1 => ErrorCode::ProtocolError,
741 0x2 => ErrorCode::InternalError,
742 0x3 => ErrorCode::FlowControlError,
743 0x4 => ErrorCode::SettingsTimeout,
744 0x5 => ErrorCode::StreamClosed,
745 0x6 => ErrorCode::FrameSizeError,
746 0x7 => ErrorCode::RefusedStream,
747 0x8 => ErrorCode::Cancel,
748 0x9 => ErrorCode::CompressionError,
749 0xa => ErrorCode::ConnectError,
750 0xb => ErrorCode::EnhanceYourCalm,
751 0xc => ErrorCode::InadequateSecurity,
752 0xd => ErrorCode::Http11Required,
753 _ => ErrorCode::ProtocolError,
754 };
755 let debug_data = payload.copy_to_bytes(payload.remaining());
756
757 Some(Self {
758 last_stream_id,
759 error_code,
760 debug_data,
761 })
762 }
763}
764
765#[derive(Debug, Clone)]
767pub struct PriorityFrame {
768 pub stream_id: u32,
769 pub exclusive: bool,
770 pub stream_dependency: u32,
771 pub weight: u8,
772}
773
774impl PriorityFrame {
775 pub fn new(stream_id: u32, stream_dependency: u32, weight: u8, exclusive: bool) -> Self {
777 Self {
778 stream_id,
779 exclusive,
780 stream_dependency,
781 weight,
782 }
783 }
784
785 pub fn serialize(&self) -> BytesMut {
787 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + 5);
788
789 let header = FrameHeader {
790 length: 5,
791 frame_type: FrameType::Priority,
792 flags: 0,
793 stream_id: self.stream_id,
794 };
795 header.serialize(&mut buf);
796
797 let dep = if self.exclusive {
798 self.stream_dependency | 0x80000000
799 } else {
800 self.stream_dependency
801 };
802 buf.put_u32(dep);
803 buf.put_u8(self.weight);
804
805 buf
806 }
807
808 pub fn parse(stream_id: u32, mut payload: Bytes) -> Result<Self, String> {
810 if stream_id == 0 {
811 return Err("PRIORITY frame must have non-zero stream ID".to_string());
812 }
813 if payload.remaining() < 5 {
814 return Err("PRIORITY frame payload too short".to_string());
815 }
816
817 let dep_raw = payload.get_u32();
818 let exclusive = (dep_raw & 0x80000000) != 0;
819 let stream_dependency = dep_raw & 0x7fffffff;
820 let weight = payload.get_u8();
821
822 if stream_dependency == stream_id {
824 return Err("PRIORITY frame stream cannot depend on itself".to_string());
825 }
826
827 Ok(Self {
828 stream_id,
829 exclusive,
830 stream_dependency,
831 weight,
832 })
833 }
834}
835
836#[derive(Debug, Clone)]
838pub struct PushPromiseFrame {
839 pub stream_id: u32,
840 pub promised_stream_id: u32,
841 pub header_block: Bytes,
842 pub end_headers: bool,
843}
844
845impl PushPromiseFrame {
846 pub fn new(stream_id: u32, promised_stream_id: u32, header_block: Bytes) -> Self {
848 Self {
849 stream_id,
850 promised_stream_id,
851 header_block,
852 end_headers: true,
853 }
854 }
855
856 pub fn end_headers(mut self, end: bool) -> Self {
858 self.end_headers = end;
859 self
860 }
861
862 pub fn serialize(&self) -> BytesMut {
864 let payload_len = 4 + self.header_block.len(); let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + payload_len);
866
867 let header = FrameHeader {
868 length: payload_len as u32,
869 frame_type: FrameType::PushPromise,
870 flags: if self.end_headers {
871 flags::END_HEADERS
872 } else {
873 0
874 },
875 stream_id: self.stream_id,
876 };
877 header.serialize(&mut buf);
878
879 buf.put_u32(self.promised_stream_id & 0x7fffffff);
881 buf.extend_from_slice(&self.header_block);
882
883 buf
884 }
885
886 pub fn parse(stream_id: u32, flags: u8, mut payload: Bytes) -> Result<Self, String> {
888 if stream_id == 0 {
889 return Err("PUSH_PROMISE frame must have non-zero stream ID".to_string());
890 }
891
892 let end_headers = (flags & flags::END_HEADERS) != 0;
893 let padded = (flags & flags::PADDED) != 0;
894
895 let pad_len = if padded {
897 if payload.remaining() < 1 {
898 return Err("PADDED PUSH_PROMISE frame missing padding length".to_string());
899 }
900 let pad_len = payload.get_u8() as usize;
901 if pad_len >= payload.remaining() {
902 return Err("Padding length exceeds payload size".to_string());
903 }
904 pad_len
905 } else {
906 0
907 };
908
909 if payload.remaining() < 4 {
911 return Err("PUSH_PROMISE frame missing promised stream ID".to_string());
912 }
913 let promised_stream_id_raw = payload.get_u32();
914 if (promised_stream_id_raw & 0x80000000) != 0 {
915 return Err("PUSH_PROMISE frame reserved bit set in promised stream ID".to_string());
916 }
917 let promised_stream_id = promised_stream_id_raw & 0x7fffffff;
918
919 let header_block_len = payload.remaining() - pad_len;
921 if header_block_len == 0 {
922 return Err("PUSH_PROMISE frame header block is empty".to_string());
923 }
924 let header_block = payload.copy_to_bytes(header_block_len);
925 payload.advance(pad_len);
927
928 Ok(Self {
929 stream_id,
930 promised_stream_id,
931 header_block,
932 end_headers,
933 })
934 }
935}
936
937#[derive(Debug, Clone)]
939pub struct RstStreamFrame {
940 pub stream_id: u32,
941 pub error_code: ErrorCode,
942}
943
944impl RstStreamFrame {
945 pub fn new(stream_id: u32, error_code: ErrorCode) -> Self {
947 Self {
948 stream_id,
949 error_code,
950 }
951 }
952
953 pub fn serialize(&self) -> BytesMut {
955 let mut buf = BytesMut::with_capacity(FRAME_HEADER_SIZE + 4);
956
957 let header = FrameHeader {
958 length: 4,
959 frame_type: FrameType::RstStream,
960 flags: 0,
961 stream_id: self.stream_id,
962 };
963 header.serialize(&mut buf);
964 buf.put_u32(self.error_code as u32);
965
966 buf
967 }
968
969 pub fn parse(stream_id: u32, mut payload: Bytes) -> Result<Self, String> {
971 if stream_id == 0 {
972 return Err("RST_STREAM frame must have non-zero stream ID".to_string());
973 }
974 if payload.remaining() < 4 {
975 return Err("RST_STREAM frame payload too short".to_string());
976 }
977
978 let error_code_raw = payload.get_u32();
979 let error_code = match error_code_raw {
980 0x0 => ErrorCode::NoError,
981 0x1 => ErrorCode::ProtocolError,
982 0x2 => ErrorCode::InternalError,
983 0x3 => ErrorCode::FlowControlError,
984 0x4 => ErrorCode::SettingsTimeout,
985 0x5 => ErrorCode::StreamClosed,
986 0x6 => ErrorCode::FrameSizeError,
987 0x7 => ErrorCode::RefusedStream,
988 0x8 => ErrorCode::Cancel,
989 0x9 => ErrorCode::CompressionError,
990 0xa => ErrorCode::ConnectError,
991 0xb => ErrorCode::EnhanceYourCalm,
992 0xc => ErrorCode::InadequateSecurity,
993 0xd => ErrorCode::Http11Required,
994 _ => ErrorCode::ProtocolError,
995 };
996
997 Ok(Self {
998 stream_id,
999 error_code,
1000 })
1001 }
1002}
1003
1004#[cfg(test)]
1005mod tests {
1006 use super::*;
1007
1008 #[test]
1009 fn test_settings_frame_serialization() {
1010 let mut settings = SettingsFrame::new();
1011 settings
1012 .set(SettingsId::HeaderTableSize, 65536)
1013 .set(SettingsId::MaxConcurrentStreams, 1000)
1014 .set(SettingsId::InitialWindowSize, 6291456);
1015
1016 let buf = settings.serialize();
1017
1018 assert_eq!(buf.len(), 27);
1020
1021 assert_eq!(buf[0..3], [0, 0, 18]); assert_eq!(buf[3], 0x4); assert_eq!(buf[4], 0); assert_eq!(buf[5..9], [0, 0, 0, 0]); }
1027
1028 #[test]
1029 fn test_settings_ack_frame() {
1030 let settings = SettingsFrame::ack();
1031 let buf = settings.serialize();
1032
1033 assert_eq!(buf.len(), 9); assert_eq!(buf[0..3], [0, 0, 0]); assert_eq!(buf[3], 0x4); assert_eq!(buf[4], 0x1); }
1038
1039 #[test]
1040 fn test_window_update_frame() {
1041 let frame = WindowUpdateFrame::new(0, 15663105);
1042 let buf = frame.serialize();
1043
1044 assert_eq!(buf.len(), 13); assert_eq!(buf[3], 0x8); }
1047
1048 #[test]
1049 fn test_frame_header_parse() {
1050 let bytes = [0, 0, 18, 0x4, 0, 0, 0, 0, 0];
1051 let header = FrameHeader::parse(&bytes).unwrap();
1052
1053 assert_eq!(header.length, 18);
1054 assert_eq!(header.frame_type, FrameType::Settings);
1055 assert_eq!(header.flags, 0);
1056 assert_eq!(header.stream_id, 0);
1057 }
1058}