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: Data) => frame.map(f).into(),
101 Headers(frame: Headers) => frame.into(),
102 Priority(frame: Priority) => frame.into(),
103 PushPromise(frame: PushPromise) => frame.into(),
104 Settings(frame: Settings) => frame.into(),
105 Ping(frame: Ping) => frame.into(),
106 GoAway(frame: GoAway) => frame.into(),
107 WindowUpdate(frame: WindowUpdate) => frame.into(),
108 Reset(frame: Reset) => 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: &Data) => fmt::Debug::fmt(self:frame, f:fmt),
119 Headers(ref frame: &Headers) => fmt::Debug::fmt(self:frame, f:fmt),
120 Priority(ref frame: &Priority) => fmt::Debug::fmt(self:frame, f:fmt),
121 PushPromise(ref frame: &PushPromise) => fmt::Debug::fmt(self:frame, f:fmt),
122 Settings(ref frame: &Settings) => fmt::Debug::fmt(self:frame, f:fmt),
123 Ping(ref frame: &Ping) => fmt::Debug::fmt(self:frame, f:fmt),
124 GoAway(ref frame: &GoAway) => fmt::Debug::fmt(self:frame, f:fmt),
125 WindowUpdate(ref frame: &WindowUpdate) => fmt::Debug::fmt(self:frame, f:fmt),
126 Reset(ref frame: &Reset) => fmt::Debug::fmt(self:frame, f: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}
172