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        use self::Frame::*;
89
90        match *self {
91            Data(ref frame) => fmt::Debug::fmt(frame, fmt),
92            Headers(ref frame) => fmt::Debug::fmt(frame, fmt),
93            Priority(ref frame) => fmt::Debug::fmt(frame, fmt),
94            Settings(ref frame) => fmt::Debug::fmt(frame, fmt),
95            Ping(ref frame) => fmt::Debug::fmt(frame, fmt),
96            GoAway(ref frame) => fmt::Debug::fmt(frame, fmt),
97            WindowUpdate(ref frame) => fmt::Debug::fmt(frame, fmt),
98            Reset(ref frame) => fmt::Debug::fmt(frame, fmt),
99        }
100    }
101}
102
103/// Errors that can occur during parsing an HTTP/2 frame.
104#[derive(thiserror::Error, Debug, Copy, Clone, PartialEq, Eq)]
105pub enum FrameError {
106    /// A length value other than 8 was set on a PING message.
107    #[error("A length value other than 8 was set on a PING message")]
108    BadFrameSize,
109
110    /// Frame size exceeded
111    #[error("Frame size exceeded")]
112    MaxFrameSize,
113
114    /// The padding length was larger than the frame-header-specified
115    /// length of the payload.
116    #[error("The padding length was larger than the frame-header-specified length of the payload")]
117    TooMuchPadding,
118
119    /// An invalid setting value was provided
120    #[error("An invalid setting value was provided")]
121    InvalidSettingValue,
122
123    /// The payload length specified by the frame header was not the
124    /// value necessary for the specific frame type.
125    #[error(
126        "The payload length specified by the frame header was not the value necessary for the specific frame type"
127    )]
128    InvalidPayloadLength,
129
130    /// Received a payload with an ACK settings frame
131    #[error("Received a payload with an ACK settings frame")]
132    InvalidPayloadAckSettings,
133
134    /// An invalid stream identifier was provided.
135    ///
136    /// This is returned if a SETTINGS or PING frame is received with a stream
137    /// identifier other than zero.
138    #[error("An invalid stream identifier was provided")]
139    InvalidStreamId,
140
141    /// A request or response is malformed.
142    #[error("A request or response is malformed")]
143    MalformedMessage,
144
145    /// An invalid stream dependency ID was provided
146    ///
147    /// This is returned if a HEADERS or PRIORITY frame is received with an
148    /// invalid stream identifier.
149    #[error("An invalid stream dependency ID was provided")]
150    InvalidDependencyId,
151
152    /// An invalid preface
153    #[error("An invalid preface")]
154    InvalidPreface,
155
156    /// Unexpected push promise
157    #[error("Unexpected push promise")]
158    UnexpectedPushPromise,
159
160    /// Continuation related error
161    #[error("{0}")]
162    Continuation(#[from] FrameContinuationError),
163
164    /// Failed to perform HPACK decoding
165    #[error("{0}")]
166    Hpack(#[from] hpack::DecoderError),
167}
168
169#[derive(thiserror::Error, Debug, Copy, Clone, PartialEq, Eq)]
170pub enum FrameContinuationError {
171    /// Continuation frame is expected
172    #[error("Continuation frame is expected")]
173    Expected,
174
175    /// Continuation frame is unexpected
176    #[error("Continuation frame is unexpected")]
177    Unexpected,
178
179    /// Continuation frame's stream id is unexpected
180    #[error("Continuation frame's stream id is unexpected")]
181    UnknownStreamId,
182
183    /// Max left over size
184    #[error("Max left over size")]
185    MaxLeftoverSize,
186
187    /// Max count of Continuations
188    #[error("Max count of Continuations")]
189    MaxContinuations,
190
191    /// Malformed frame
192    #[error("Malformed frame")]
193    Malformed,
194}