Skip to main content

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, PseudoId, PseudoOrder, PseudoOrderBuilder,
56    PushPromise, PushPromiseHeaderError,
57};
58pub use self::ping::Ping;
59pub use self::priority::{Priority, StreamDependency};
60pub use self::reason::Reason;
61pub use self::reset::Reset;
62pub use self::settings::{Setting, SettingId, Settings, SettingsOrder, SettingsOrderBuilder};
63pub use self::stream_id::{StreamId, StreamIdOverflow};
64pub use self::window_update::WindowUpdate;
65
66#[cfg(feature = "unstable")]
67pub use crate::hpack::BytesStr;
68
69// Re-export some constants
70
71pub use self::settings::{
72    DEFAULT_INITIAL_WINDOW_SIZE, DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE,
73    MAX_MAX_FRAME_SIZE,
74};
75
76pub type FrameSize = u32;
77
78pub const HEADER_LEN: usize = 9;
79
80#[derive(Eq, PartialEq)]
81pub enum Frame<T = Bytes> {
82    Data(Data<T>),
83    Headers(Headers),
84    Priority(Priority),
85    PushPromise(PushPromise),
86    Settings(Settings),
87    Ping(Ping),
88    GoAway(GoAway),
89    WindowUpdate(WindowUpdate),
90    Reset(Reset),
91}
92
93impl<T> Frame<T> {
94    pub fn map<F, U>(self, f: F) -> Frame<U>
95    where
96        F: FnOnce(T) -> U,
97    {
98        use self::Frame::*;
99
100        match self {
101            Data(frame) => frame.map(f).into(),
102            Headers(frame) => frame.into(),
103            Priority(frame) => frame.into(),
104            PushPromise(frame) => frame.into(),
105            Settings(frame) => frame.into(),
106            Ping(frame) => frame.into(),
107            GoAway(frame) => frame.into(),
108            WindowUpdate(frame) => frame.into(),
109            Reset(frame) => frame.into(),
110        }
111    }
112}
113
114impl<T> fmt::Debug for Frame<T> {
115    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
116        use self::Frame::*;
117
118        match *self {
119            Data(ref frame) => fmt::Debug::fmt(frame, fmt),
120            Headers(ref frame) => fmt::Debug::fmt(frame, fmt),
121            Priority(ref frame) => fmt::Debug::fmt(frame, fmt),
122            PushPromise(ref frame) => fmt::Debug::fmt(frame, fmt),
123            Settings(ref frame) => fmt::Debug::fmt(frame, fmt),
124            Ping(ref frame) => fmt::Debug::fmt(frame, fmt),
125            GoAway(ref frame) => fmt::Debug::fmt(frame, fmt),
126            WindowUpdate(ref frame) => fmt::Debug::fmt(frame, fmt),
127            Reset(ref frame) => fmt::Debug::fmt(frame, fmt),
128        }
129    }
130}
131
132/// Errors that can occur during parsing an HTTP/2 frame.
133#[derive(Debug, Clone, PartialEq, Eq)]
134pub enum Error {
135    /// A length value other than 8 was set on a PING message.
136    BadFrameSize,
137
138    /// The padding length was larger than the frame-header-specified
139    /// length of the payload.
140    TooMuchPadding,
141
142    /// An invalid setting value was provided
143    InvalidSettingValue,
144
145    /// An invalid window update value
146    InvalidWindowUpdateValue,
147
148    /// The payload length specified by the frame header was not the
149    /// value necessary for the specific frame type.
150    InvalidPayloadLength,
151
152    /// Received a payload with an ACK settings frame
153    InvalidPayloadAckSettings,
154
155    /// An invalid stream identifier was provided.
156    ///
157    /// This is returned if a SETTINGS or PING frame is received with a stream
158    /// identifier other than zero.
159    InvalidStreamId,
160
161    /// A request or response is malformed.
162    MalformedMessage,
163
164    /// An invalid stream dependency ID was provided
165    ///
166    /// This is returned if a HEADERS or PRIORITY frame is received with an
167    /// invalid stream identifier.
168    InvalidDependencyId,
169
170    /// Failed to perform HPACK decoding
171    Hpack(hpack::DecoderError),
172}