1use std::convert::From;
2
3use nom::{
4 bytes::streaming::{tag, take},
5 combinator::{complete, map, map_opt},
6 error::{ErrorKind, ParseError},
7 multi::many0,
8 number::streaming::{be_u16, be_u24, be_u32, be_u8},
9 sequence::tuple,
10 Err, HexDisplay, IResult, Offset,
11};
12
13#[derive(Clone, Debug, PartialEq)]
14pub struct FrameHeader {
15 pub payload_len: u32,
16 pub frame_type: FrameType,
17 pub flags: u8,
18 pub stream_id: u32,
19}
20
21#[derive(Clone, Debug, PartialEq)]
22pub enum FrameType {
23 Data,
24 Headers,
25 Priority,
26 RstStream,
27 Settings,
28 PushPromise,
29 Ping,
30 GoAway,
31 WindowUpdate,
32 Continuation,
33}
34
35#[derive(Clone, Debug, PartialEq)]
53pub struct Error<'a> {
54 pub input: &'a [u8],
55 pub error: InnerError,
56}
57
58#[derive(Clone, Debug, PartialEq)]
59pub enum InnerError {
60 Nom(ErrorKind),
61 NoError,
62 ProtocolError,
63 InternalError,
64 FlowControlError,
65 SettingsTimeout,
66 StreamClosed,
67 FrameSizeError,
68 RefusedStream,
69 Cancel,
70 CompressionError,
71 ConnectError,
72 EnhanceYourCalm,
73 InadequateSecurity,
74 HTTP11Required,
75}
76
77impl<'a> Error<'a> {
78 pub fn new(input: &'a [u8], error: InnerError) -> Error<'a> {
79 Error { input, error }
80 }
81}
82
83impl<'a> ParseError<&'a [u8]> for Error<'a> {
84 fn from_error_kind(input: &'a [u8], kind: ErrorKind) -> Self {
85 Error {
86 input,
87 error: InnerError::Nom(kind),
88 }
89 }
90
91 fn append(input: &'a [u8], kind: ErrorKind, other: Self) -> Self {
92 Error {
93 input,
94 error: InnerError::Nom(kind),
95 }
96 }
97}
98
99impl<'a> From<(&'a [u8], ErrorKind)> for Error<'a> {
100 fn from((input, kind): (&'a [u8], ErrorKind)) -> Self {
101 Error {
102 input,
103 error: InnerError::Nom(kind),
104 }
105 }
106}
107
108pub fn preface(i: &[u8]) -> IResult<&[u8], &[u8]> {
109 tag(b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")(i)
110}
111
112pub fn frame_header(input: &[u8]) -> IResult<&[u8], FrameHeader, Error> {
129 let (i1, payload_len) = be_u24(input)?;
130 let (i2, frame_type) = map_opt(be_u8, convert_frame_type)(i1)?;
131 let (i3, flags) = be_u8(i2)?;
132 let (i4, stream_id) = be_u32(i3)?;
133
134 Ok((
135 i4,
136 FrameHeader {
137 payload_len,
138 frame_type,
139 flags,
140 stream_id,
141 },
142 ))
143}
144
145fn convert_frame_type(t: u8) -> Option<FrameType> {
146 info!("got frame type: {}", t);
147 match t {
148 0 => Some(FrameType::Data),
149 1 => Some(FrameType::Headers),
150 2 => Some(FrameType::Priority),
151 3 => Some(FrameType::RstStream),
152 4 => Some(FrameType::Settings),
153 5 => Some(FrameType::PushPromise),
154 6 => Some(FrameType::Ping),
155 7 => Some(FrameType::GoAway),
156 8 => Some(FrameType::WindowUpdate),
157 9 => Some(FrameType::Continuation),
158 _ => None,
159 }
160}
161
162#[derive(Clone, Debug, PartialEq)]
163pub enum Frame<'a> {
164 Data(Data<'a>),
165 Headers(Headers<'a>),
166 Priority,
167 RstStream(RstStream),
168 Settings(Settings),
169 PushPromise,
170 Ping(Ping),
171 GoAway,
172 WindowUpdate(WindowUpdate),
173 Continuation,
174}
175
176impl<'a> Frame<'a> {
177 pub fn is_stream_specific(&self) -> bool {
178 match self {
179 Frame::Data(_)
180 | Frame::Headers(_)
181 | Frame::Priority
182 | Frame::RstStream(_)
183 | Frame::PushPromise
184 | Frame::Continuation => true,
185 Frame::Settings(_) | Frame::Ping(_) | Frame::GoAway => false,
186 Frame::WindowUpdate(w) => w.stream_id != 0,
187 }
188 }
189
190 pub fn stream_id(&self) -> u32 {
191 match self {
192 Frame::Data(d) => d.stream_id,
193 Frame::Headers(h) => h.stream_id,
194 Frame::Priority => unimplemented!(),
195 Frame::RstStream(r) => r.stream_id,
196 Frame::PushPromise => unimplemented!(),
197 Frame::Continuation => unimplemented!(),
198 Frame::Settings(_) | Frame::Ping(_) | Frame::GoAway => 0,
199 Frame::WindowUpdate(w) => w.stream_id,
200 }
201 }
202}
203
204pub fn frame<'a>(input: &'a [u8], max_frame_size: u32) -> IResult<&'a [u8], Frame<'a>, Error<'a>> {
205 let (i, header) = frame_header(input)?;
206
207 info!("got frame header: {:?}", header);
208
209 if header.payload_len > max_frame_size {
210 return Err(Err::Failure(Error::new(input, InnerError::FrameSizeError)));
211 }
212
213 let valid_stream_id = match header.frame_type {
214 FrameType::Data
215 | FrameType::Headers
216 | FrameType::Priority
217 | FrameType::RstStream
218 | FrameType::PushPromise
219 | FrameType::Continuation => header.stream_id != 0,
220 FrameType::Settings | FrameType::Ping | FrameType::GoAway => header.stream_id == 0,
221 FrameType::WindowUpdate => true,
222 };
223
224 if !valid_stream_id {
225 return Err(Err::Failure(Error::new(input, InnerError::ProtocolError)));
226 }
227
228 let f = match header.frame_type {
229 FrameType::Data => data_frame(i, &header)?,
230 FrameType::Headers => headers_frame(i, &header)?,
231 FrameType::Priority => {
232 if header.payload_len != 5 {
233 return Err(Err::Failure(Error::new(input, InnerError::FrameSizeError)));
234 }
235 unimplemented!();
236 }
237 FrameType::RstStream => {
238 if header.payload_len != 4 {
239 return Err(Err::Failure(Error::new(input, InnerError::FrameSizeError)));
240 }
241 rst_stream_frame(i, &header)?
242 }
243 FrameType::PushPromise => {
244 unimplemented!();
245 }
246 FrameType::Continuation => {
247 unimplemented!();
248 }
249 FrameType::Settings => {
250 if header.payload_len % 6 != 0 {
251 return Err(Err::Failure(Error::new(input, InnerError::FrameSizeError)));
252 }
253 settings_frame(i, &header)?
254 }
255 FrameType::Ping => {
256 if header.payload_len != 8 {
257 return Err(Err::Failure(Error::new(input, InnerError::FrameSizeError)));
258 }
259 ping_frame(i, &header)?
260 }
261 FrameType::GoAway => {
262 unimplemented!();
263 }
264 FrameType::WindowUpdate => {
265 if header.payload_len != 4 {
266 return Err(Err::Failure(Error::new(input, InnerError::FrameSizeError)));
267 }
268 window_update_frame(i, &header)?
269 }
270 };
271
272 Ok(f)
273}
274
275#[derive(Clone, Debug, PartialEq)]
276pub struct Data<'a> {
277 pub stream_id: u32,
278 pub payload: &'a [u8],
279 pub end_stream: bool,
280}
281
282pub fn data_frame<'a, 'b>(
283 input: &'a [u8],
284 header: &'b FrameHeader,
285) -> IResult<&'a [u8], Frame<'a>, Error<'a>> {
286 let (remaining, i) = take(header.payload_len)(input)?;
287
288 let (i1, pad_length) = if header.flags & 0x8 != 0 {
289 let (i, pad_length) = be_u8(i)?;
290 (i, Some(pad_length))
291 } else {
292 (i, None)
293 };
294
295 if pad_length.is_some() && i1.len() <= pad_length.unwrap() as usize {
296 return Err(Err::Failure(Error::new(input, InnerError::ProtocolError)));
297 }
298
299 let (_, payload) = take(i1.len() - pad_length.unwrap_or(0) as usize)(i1)?;
300
301 Ok((
302 remaining,
303 Frame::Data(Data {
304 stream_id: header.stream_id,
305 payload,
306 end_stream: header.flags & 0x1 != 0,
307 }),
308 ))
309}
310
311#[derive(Clone, Debug, PartialEq)]
312pub struct Headers<'a> {
313 pub stream_id: u32,
314 pub stream_dependency: Option<StreamDependency>,
315 pub weight: Option<u8>,
316 pub header_block_fragment: &'a [u8],
317 pub end_stream: bool,
318 pub end_headers: bool,
319 pub priority: bool,
320}
321
322#[derive(Clone, Debug, PartialEq)]
323pub struct StreamDependency {
324 pub exclusive: bool,
325 pub stream_id: u32,
326}
327
328pub fn headers_frame<'a, 'b>(
329 input: &'a [u8],
330 header: &'b FrameHeader,
331) -> IResult<&'a [u8], Frame<'a>, Error<'a>> {
332 let (remaining, i) = take(header.payload_len)(input)?;
333
334 let (i1, pad_length) = if header.flags & 0x8 != 0 {
335 let (i, pad_length) = be_u8(i)?;
336 (i, Some(pad_length))
337 } else {
338 (i, None)
339 };
340
341 let (i2, stream_dependency) = if header.flags & 0x20 != 0 {
342 let (i, stream) = map(be_u32, |i| StreamDependency {
343 exclusive: i & 0x8000 != 0,
344 stream_id: i & 0x7FFF,
345 })(i1)?;
346 (i, Some(stream))
347 } else {
348 (i1, None)
349 };
350
351 let (i3, weight) = if header.flags & 0x20 != 0 {
352 let (i, weight) = be_u8(i2)?;
353 (i, Some(weight))
354 } else {
355 (i2, None)
356 };
357
358 if pad_length.is_some() && i3.len() <= pad_length.unwrap() as usize {
359 return Err(Err::Failure(Error::new(input, InnerError::ProtocolError)));
360 }
361
362 let (_, header_block_fragment) = take(i3.len() - pad_length.unwrap_or(0) as usize)(i3)?;
363
364 Ok((
365 remaining,
366 Frame::Headers(Headers {
367 stream_id: header.stream_id,
368 stream_dependency,
369 weight,
370 header_block_fragment,
371 end_stream: header.flags & 0x1 != 0,
372 end_headers: header.flags & 0x4 != 0,
373 priority: header.flags & 0x20 != 0,
374 }),
375 ))
376}
377
378#[derive(Clone, Debug, PartialEq)]
379pub struct RstStream {
380 pub stream_id: u32,
381 pub error_code: u32,
382}
383
384pub fn rst_stream_frame<'a, 'b>(
385 input: &'a [u8],
386 header: &'b FrameHeader,
387) -> IResult<&'a [u8], Frame<'a>, Error<'a>> {
388 let (i, error_code) = be_u32(input)?;
389 Ok((
390 i,
391 Frame::RstStream(RstStream {
392 stream_id: header.stream_id,
393 error_code,
394 }),
395 ))
396}
397
398#[derive(Clone, Debug, PartialEq)]
399pub struct Settings {
400 pub settings: Vec<Setting>,
401}
402
403#[derive(Clone, Debug, PartialEq)]
404pub struct Setting {
405 pub identifier: u16,
406 pub value: u32,
407}
408
409pub fn settings_frame<'a, 'b>(
410 input: &'a [u8],
411 header: &'b FrameHeader,
412) -> IResult<&'a [u8], Frame<'a>, Error<'a>> {
413 let (i, data) = take(header.payload_len)(input)?;
414
415 let (_, settings) = many0(map(
416 complete(tuple((be_u16, be_u32))),
417 |(identifier, value)| Setting { identifier, value },
418 ))(data)?;
419
420 Ok((i, Frame::Settings(Settings { settings })))
421}
422
423#[derive(Clone, Debug, PartialEq)]
424pub struct Ping {
425 pub payload: [u8; 8],
426}
427
428pub fn ping_frame<'a, 'b>(
429 input: &'a [u8],
430 header: &'b FrameHeader,
431) -> IResult<&'a [u8], Frame<'a>, Error<'a>> {
432 let (i, data) = take(8usize)(input)?;
433
434 let mut p = Ping { payload: [0; 8] };
435
436 for i in 0..8 {
437 p.payload[i] = data[i];
438 }
439
440 Ok((i, Frame::Ping(p)))
441}
442
443#[derive(Clone, Debug, PartialEq)]
444pub struct WindowUpdate {
445 pub stream_id: u32,
446 pub increment: u32,
447}
448
449pub fn window_update_frame<'a, 'b>(
450 input: &'a [u8],
451 header: &'b FrameHeader,
452) -> IResult<&'a [u8], Frame<'a>, Error<'a>> {
453 let (i, increment) = be_u32(input)?;
454 let increment = increment & 0x7FFF;
455
456 if increment == 0 {
458 return Err(Err::Failure(Error::new(input, InnerError::ProtocolError)));
459 }
460
461 Ok((
462 i,
463 Frame::WindowUpdate(WindowUpdate {
464 stream_id: header.stream_id,
465 increment,
466 }),
467 ))
468}
469
470#[macro_export]
471macro_rules! map_err(
472 (__impl $i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
473 ($submac!($i, $($args)*)).map_err(|e| {
474 $g(e)
475 })
476 );
477);