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, PartialEq, Eq)]
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    /// Headers frame contains too many headers
118    #[error("Headers frame contains too many headers")]
119    TooManyHeaders(StreamId),
120
121    /// An invalid setting value was provided
122    #[error("An invalid setting value was provided")]
123    InvalidSettingValue,
124
125    /// The payload length specified by the frame header was not the
126    /// value necessary for the specific frame type.
127    #[error(
128        "The payload length specified by the frame header was not the value necessary for the specific frame type"
129    )]
130    InvalidPayloadLength,
131
132    /// Received a payload with an ACK settings frame
133    #[error("Received a payload with an ACK settings frame")]
134    InvalidPayloadAckSettings,
135
136    /// An invalid stream identifier was provided.
137    ///
138    /// This is returned if a SETTINGS or PING frame is received with a stream
139    /// identifier other than zero.
140    #[error("An invalid stream identifier was provided")]
141    InvalidStreamId,
142
143    /// A request or response is malformed.
144    #[error("A request or response is malformed")]
145    MalformedMessage,
146
147    /// An invalid stream dependency ID was provided
148    ///
149    /// This is returned if a HEADERS or PRIORITY frame is received with an
150    /// invalid stream identifier.
151    #[error("An invalid stream dependency ID was provided")]
152    InvalidDependencyId,
153
154    /// An invalid preface
155    #[error("An invalid preface")]
156    InvalidPreface,
157
158    /// Unexpected push promise
159    #[error("Unexpected push promise")]
160    UnexpectedPushPromise,
161
162    /// Continuation related error
163    #[error("{0}")]
164    Continuation(#[from] FrameContinuationError),
165
166    /// Failed to perform HPACK decoding
167    #[error("{0}")]
168    Hpack(#[from] hpack::DecoderError),
169}
170
171#[derive(thiserror::Error, Debug, Copy, Clone, PartialEq, Eq)]
172pub enum FrameContinuationError {
173    /// Continuation frame is expected
174    #[error("Continuation frame is expected")]
175    Expected,
176
177    /// Continuation frame is unexpected
178    #[error("Continuation frame is unexpected")]
179    Unexpected,
180
181    /// Continuation frame's stream id is unexpected
182    #[error("Continuation frame's stream id is unexpected")]
183    UnknownStreamId,
184
185    /// Max left over size
186    #[error("Max left over size")]
187    MaxLeftoverSize,
188
189    /// Max count of Continuations
190    #[error("Max count of Continuations")]
191    MaxContinuations,
192
193    /// Malformed frame
194    #[error("Malformed frame")]
195    Malformed,
196}