Skip to main content

ntex_h2/frame/
mod.rs

1use std::fmt;
2
3/// A helper macro that unpacks a sequence of 4 bytes found in the buffer with
4/// the given identifier, starting at the given offset, into the given integer
5/// type. Obviously, the integer type should be able to support at least 4
6/// bytes.
7///
8/// # Examples
9///
10/// ```ignore
11/// # // We ignore this doctest because the macro is not exported.
12/// let buf: [u8; 4] = [0, 0, 0, 1];
13/// assert_eq!(1u32, unpack_octets_4!(buf, 0, u32));
14/// ```
15macro_rules! unpack_octets_4 {
16    // TODO: Get rid of this macro
17    ($buf:expr, $offset:expr, $tip:ty) => {
18        (($buf[$offset + 0] as $tip) << 24)
19            | (($buf[$offset + 1] as $tip) << 16)
20            | (($buf[$offset + 2] as $tip) << 8)
21            | (($buf[$offset + 3] as $tip) << 0)
22    };
23}
24
25#[cfg(test)]
26mod tests {
27    #[test]
28    fn test_unpack_octets_4() {
29        let buf: [u8; 4] = [0, 0, 0, 1];
30        assert_eq!(1u32, unpack_octets_4!(buf, 0, u32));
31    }
32}
33
34mod data;
35mod go_away;
36mod head;
37mod headers;
38mod ping;
39mod priority;
40mod protocol;
41mod reason;
42mod reset;
43mod settings;
44mod stream_id;
45mod util;
46mod window_update;
47
48pub use self::data::Data;
49pub use self::go_away::GoAway;
50pub use self::head::{Head, Kind};
51pub use self::headers::{Headers, PseudoHeaders};
52pub use self::ping::Ping;
53pub use self::priority::{Priority, StreamDependency};
54pub use self::protocol::Protocol;
55pub use self::reason::Reason;
56pub use self::reset::Reset;
57pub use self::settings::Settings;
58pub use self::stream_id::{StreamId, StreamIdOverflow};
59pub use self::window_update::WindowUpdate;
60
61// Re-export some constants
62pub use self::settings::{
63    DEFAULT_INITIAL_WINDOW_SIZE, DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE,
64    MAX_INITIAL_WINDOW_SIZE, MAX_MAX_FRAME_SIZE,
65};
66
67use crate::hpack;
68
69pub type FrameSize = u32;
70pub type WindowSize = u32;
71
72pub const HEADER_LEN: usize = 9;
73
74#[derive(Clone)]
75pub enum Frame {
76    Data(Data),
77    Headers(Headers),
78    Priority(Priority),
79    Settings(Settings),
80    Ping(Ping),
81    GoAway(GoAway),
82    WindowUpdate(WindowUpdate),
83    Reset(Reset),
84}
85
86impl fmt::Debug for Frame {
87    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
88        match self {
89            Frame::Data(frame) => fmt::Debug::fmt(frame, fmt),
90            Frame::Headers(frame) => fmt::Debug::fmt(frame, fmt),
91            Frame::Priority(frame) => fmt::Debug::fmt(frame, fmt),
92            Frame::Settings(frame) => fmt::Debug::fmt(frame, fmt),
93            Frame::Ping(frame) => fmt::Debug::fmt(frame, fmt),
94            Frame::GoAway(frame) => fmt::Debug::fmt(frame, fmt),
95            Frame::WindowUpdate(frame) => fmt::Debug::fmt(frame, fmt),
96            Frame::Reset(frame) => fmt::Debug::fmt(frame, fmt),
97        }
98    }
99}
100
101/// Errors that can occur during parsing an HTTP/2 frame.
102#[derive(thiserror::Error, Debug, Copy, Clone, PartialEq, Eq)]
103pub enum FrameError {
104    /// A length value other than 8 was set on a PING message.
105    #[error("A length value other than 8 was set on a PING message")]
106    BadFrameSize,
107
108    /// Frame size exceeded
109    #[error("Frame size exceeded")]
110    MaxFrameSize,
111
112    /// The padding length was larger than the frame-header-specified
113    /// length of the payload.
114    #[error("The padding length was larger than the frame-header-specified length of the payload")]
115    TooMuchPadding,
116
117    /// An invalid setting value was provided
118    #[error("An invalid setting value was provided")]
119    InvalidSettingValue,
120
121    /// The payload length specified by the frame header was not the
122    /// value necessary for the specific frame type.
123    #[error(
124        "The payload length specified by the frame header was not the value necessary for the specific frame type"
125    )]
126    InvalidPayloadLength,
127
128    /// Received a payload with an ACK settings frame
129    #[error("Received a payload with an ACK settings frame")]
130    InvalidPayloadAckSettings,
131
132    /// An invalid stream identifier was provided.
133    ///
134    /// This is returned if a SETTINGS or PING frame is received with a stream
135    /// identifier other than zero.
136    #[error("An invalid stream identifier was provided")]
137    InvalidStreamId,
138
139    /// A request or response is malformed.
140    #[error("A request or response is malformed")]
141    MalformedMessage,
142
143    /// An invalid stream dependency ID was provided
144    ///
145    /// This is returned if a HEADERS or PRIORITY frame is received with an
146    /// invalid stream identifier.
147    #[error("An invalid stream dependency ID was provided")]
148    InvalidDependencyId,
149
150    /// An invalid preface
151    #[error("An invalid preface")]
152    InvalidPreface,
153
154    /// Unexpected push promise
155    #[error("Unexpected push promise")]
156    UnexpectedPushPromise,
157
158    /// Continuation related error
159    #[error("{0}")]
160    Continuation(#[from] FrameContinuationError),
161
162    /// Failed to perform HPACK decoding
163    #[error("{0}")]
164    Hpack(#[from] hpack::DecoderError),
165}
166
167#[derive(thiserror::Error, Debug, Copy, Clone, PartialEq, Eq)]
168pub enum FrameContinuationError {
169    /// Continuation frame is expected
170    #[error("Continuation frame is expected")]
171    Expected,
172
173    /// Continuation frame is unexpected
174    #[error("Continuation frame is unexpected")]
175    Unexpected,
176
177    /// Continuation frame's stream id is unexpected
178    #[error("Continuation frame's stream id is unexpected")]
179    UnknownStreamId,
180
181    /// Max left over size
182    #[error("Max left over size")]
183    MaxLeftoverSize,
184
185    /// Max count of Continuations
186    #[error("Max count of Continuations")]
187    MaxContinuations,
188
189    /// Malformed frame
190    #[error("Malformed frame")]
191    Malformed,
192}