1 use 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 /// ```rust
15 /// let buf: [u8; 4] = [0, 0, 0, 1];
16 /// assert_eq!(1u32, unpack_octets_4!(buf, 0, u32));
17 /// ```
18 #[macro_escape]
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 mod data;
30 mod go_away;
31 mod head;
32 mod headers;
33 mod ping;
34 mod priority;
35 mod reason;
36 mod reset;
37 mod settings;
38 mod stream_id;
39 mod util;
40 mod window_update;
41 
42 pub use self::data::Data;
43 pub use self::go_away::GoAway;
44 pub use self::head::{Head, Kind};
45 pub use self::headers::{Continuation, Headers, Pseudo, PushPromise};
46 pub use self::ping::Ping;
47 pub use self::priority::{Priority, StreamDependency};
48 pub use self::reason::Reason;
49 pub use self::reset::Reset;
50 pub use self::settings::Settings;
51 pub use self::stream_id::{StreamId, StreamIdOverflow};
52 pub use self::window_update::WindowUpdate;
53 
54 // Re-export some constants
55 
56 pub use self::settings::{
57     DEFAULT_INITIAL_WINDOW_SIZE,
58     DEFAULT_MAX_FRAME_SIZE,
59     DEFAULT_SETTINGS_HEADER_TABLE_SIZE,
60     MAX_INITIAL_WINDOW_SIZE,
61     MAX_MAX_FRAME_SIZE,
62 };
63 
64 pub type FrameSize = u32;
65 
66 pub const HEADER_LEN: usize = 9;
67 
68 #[derive(Eq, PartialEq)]
69 pub enum Frame<T = Bytes> {
70     Data(Data<T>),
71     Headers(Headers),
72     Priority(Priority),
73     PushPromise(PushPromise),
74     Settings(Settings),
75     Ping(Ping),
76     GoAway(GoAway),
77     WindowUpdate(WindowUpdate),
78     Reset(Reset),
79 }
80 
81 impl<T> Frame<T> {
map<F, U>(self, f: F) -> Frame<U> where F: FnOnce(T) -> U,82     pub fn map<F, U>(self, f: F) -> Frame<U>
83     where
84         F: FnOnce(T) -> U,
85     {
86         use self::Frame::*;
87 
88         match self {
89             Data(frame) => frame.map(f).into(),
90             Headers(frame) => frame.into(),
91             Priority(frame) => frame.into(),
92             PushPromise(frame) => frame.into(),
93             Settings(frame) => frame.into(),
94             Ping(frame) => frame.into(),
95             GoAway(frame) => frame.into(),
96             WindowUpdate(frame) => frame.into(),
97             Reset(frame) => frame.into(),
98         }
99     }
100 }
101 
102 impl<T> fmt::Debug for Frame<T> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result103     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
104         use self::Frame::*;
105 
106         match *self {
107             Data(ref frame) => write!(fmt, "Frame::Data({:?})", frame),
108             Headers(ref frame) => write!(fmt, "Frame::Headers({:?})", frame),
109             Priority(ref frame) => write!(fmt, "Frame::Priority({:?})", frame),
110             PushPromise(ref frame) => write!(fmt, "Frame::PushPromise({:?})", frame),
111             Settings(ref frame) => write!(fmt, "Frame::Settings({:?})", frame),
112             Ping(ref frame) => write!(fmt, "Frame::Ping({:?})", frame),
113             GoAway(ref frame) => write!(fmt, "Frame::GoAway({:?})", frame),
114             WindowUpdate(ref frame) => write!(fmt, "Frame::WindowUpdate({:?})", frame),
115             Reset(ref frame) => write!(fmt, "Frame::Reset({:?})", frame),
116         }
117     }
118 }
119 
120 /// Errors that can occur during parsing an HTTP/2 frame.
121 #[derive(Debug, Clone, PartialEq, Eq)]
122 pub enum Error {
123     /// A length value other than 8 was set on a PING message.
124     BadFrameSize,
125 
126     /// The padding length was larger than the frame-header-specified
127     /// length of the payload.
128     TooMuchPadding,
129 
130     /// An invalid setting value was provided
131     InvalidSettingValue,
132 
133     /// An invalid window update value
134     InvalidWindowUpdateValue,
135 
136     /// The payload length specified by the frame header was not the
137     /// value necessary for the specific frame type.
138     InvalidPayloadLength,
139 
140     /// Received a payload with an ACK settings frame
141     InvalidPayloadAckSettings,
142 
143     /// An invalid stream identifier was provided.
144     ///
145     /// This is returned if a SETTINGS or PING frame is received with a stream
146     /// identifier other than zero.
147     InvalidStreamId,
148 
149     /// A request or response is malformed.
150     MalformedMessage,
151 
152     /// An invalid stream dependency ID was provided
153     ///
154     /// This is returned if a HEADERS or PRIORITY frame is received with an
155     /// invalid stream identifier.
156     InvalidDependencyId,
157 
158     /// Failed to perform HPACK decoding
159     Hpack(hpack::DecoderError),
160 }
161