1 use crate::hpack;
2 
3 use bytes::Bytes;
4 
5 use 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 /// ```
19 macro_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)]
30 mod tests {
31     #[test]
test_unpack_octets_4()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 
38 mod data;
39 mod go_away;
40 mod head;
41 mod headers;
42 mod ping;
43 mod priority;
44 mod reason;
45 mod reset;
46 mod settings;
47 mod stream_id;
48 mod util;
49 mod window_update;
50 
51 pub use self::data::Data;
52 pub use self::go_away::GoAway;
53 pub use self::head::{Head, Kind};
54 pub use self::headers::{
55     parse_u64, Continuation, Headers, Pseudo, PushPromise, PushPromiseHeaderError,
56 };
57 pub use self::ping::Ping;
58 pub use self::priority::{Priority, StreamDependency};
59 pub use self::reason::Reason;
60 pub use self::reset::Reset;
61 pub use self::settings::Settings;
62 pub use self::stream_id::{StreamId, StreamIdOverflow};
63 pub use self::window_update::WindowUpdate;
64 
65 #[cfg(feature = "unstable")]
66 pub use crate::hpack::BytesStr;
67 
68 // Re-export some constants
69 
70 pub use self::settings::{
71     DEFAULT_INITIAL_WINDOW_SIZE, DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE,
72     MAX_MAX_FRAME_SIZE,
73 };
74 
75 pub type FrameSize = u32;
76 
77 pub const HEADER_LEN: usize = 9;
78 
79 #[derive(Eq, PartialEq)]
80 pub 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 
92 impl<T> Frame<T> {
map<F, U>(self, f: F) -> Frame<U> where F: FnOnce(T) -> U,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 
113 impl<T> fmt::Debug for Frame<T> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result114     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)]
133 pub 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