h2/frame/
mod.rs

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