Skip to main content

huginn_net_http/http2/
frames.rs

1pub const HTTP2_CONNECTION_PREFACE: &[u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
2
3#[derive(Debug, Clone, PartialEq)]
4#[repr(u8)]
5pub enum Http2FrameType {
6    Data = 0x0,
7    Headers = 0x1,
8    Priority = 0x2,
9    RstStream = 0x3,
10    Settings = 0x4,
11    PushPromise = 0x5,
12    Ping = 0x6,
13    GoAway = 0x7,
14    WindowUpdate = 0x8,
15    Continuation = 0x9,
16    Unknown(u8),
17}
18
19impl From<u8> for Http2FrameType {
20    fn from(frame_type: u8) -> Self {
21        match frame_type {
22            0x0 => Http2FrameType::Data,
23            0x1 => Http2FrameType::Headers,
24            0x2 => Http2FrameType::Priority,
25            0x3 => Http2FrameType::RstStream,
26            0x4 => Http2FrameType::Settings,
27            0x5 => Http2FrameType::PushPromise,
28            0x6 => Http2FrameType::Ping,
29            0x7 => Http2FrameType::GoAway,
30            0x8 => Http2FrameType::WindowUpdate,
31            0x9 => Http2FrameType::Continuation,
32            other => Http2FrameType::Unknown(other),
33        }
34    }
35}
36
37#[derive(Debug, Clone)]
38pub struct Http2Frame {
39    pub frame_type: Http2FrameType,
40    pub stream_id: u32,
41    pub flags: u8,
42    pub payload: Vec<u8>,
43    pub length: u32,
44}
45
46impl Http2Frame {
47    /// Creates a new HTTP/2 frame
48    ///
49    /// # Parameters
50    /// - `frame_type_byte`: Raw frame type byte (0x0-0x9 for standard types)
51    /// - `flags`: Frame flags byte
52    /// - `stream_id`: Stream identifier
53    /// - `payload`: Frame payload data
54    ///
55    /// # Example
56    /// ```no_run
57    /// use huginn_net_http::Http2Frame;
58    ///
59    /// // Create a SETTINGS frame (type 0x4)
60    /// let frame = Http2Frame::new(0x4, 0x0, 0, vec![0x00, 0x03, 0x00, 0x00, 0x00, 0x64]);
61    /// ```
62    #[must_use]
63    pub fn new(frame_type_byte: u8, flags: u8, stream_id: u32, payload: Vec<u8>) -> Self {
64        let length = payload.len() as u32;
65        Self {
66            frame_type: Http2FrameType::from(frame_type_byte),
67            stream_id,
68            flags,
69            payload,
70            length,
71        }
72    }
73
74    /// Returns the total size of the frame in bytes (header + payload)
75    ///
76    /// HTTP/2 frames have a 9-byte header (3 bytes length + 1 byte type + 1 byte flags + 4 bytes stream ID)
77    /// followed by the payload.
78    ///
79    /// # Returns
80    /// The total size of the frame: 9 bytes (header) + payload length
81    ///
82    /// # Example
83    /// ```no_run
84    /// use huginn_net_http::Http2Frame;
85    ///
86    /// let frame = Http2Frame::new(0x4, 0x0, 0, vec![0x00, 0x03, 0x00, 0x00, 0x00, 0x64]);
87    /// assert_eq!(frame.total_size(), 9 + 6); // 9 bytes header + 6 bytes payload
88    /// ```
89    #[must_use]
90    pub fn total_size(&self) -> usize {
91        9_usize.saturating_add(self.length as usize)
92    }
93}