1 /* Copyright (C) 2020 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18 use super::huffman;
19 use crate::http2::http2::{HTTP2DynTable, HTTP2_MAX_TABLESIZE};
20 use nom::character::complete::digit1;
21 use nom::combinator::rest;
22 use nom::error::ErrorKind;
23 use nom::number::streaming::{be_u16, be_u32, be_u8};
24 use nom::Err;
25 use nom::IResult;
26 use std::fmt;
27 use std::str::FromStr;
28
29 #[repr(u8)]
30 #[derive(Clone, Copy, PartialEq, FromPrimitive, Debug)]
31 pub enum HTTP2FrameType {
32 DATA = 0,
33 HEADERS = 1,
34 PRIORITY = 2,
35 RSTSTREAM = 3,
36 SETTINGS = 4,
37 PUSHPROMISE = 5,
38 PING = 6,
39 GOAWAY = 7,
40 WINDOWUPDATE = 8,
41 CONTINUATION = 9,
42 }
43
44 impl fmt::Display for HTTP2FrameType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result45 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46 write!(f, "{:?}", self)
47 }
48 }
49
50 impl std::str::FromStr for HTTP2FrameType {
51 type Err = String;
52
from_str(s: &str) -> Result<Self, Self::Err>53 fn from_str(s: &str) -> Result<Self, Self::Err> {
54 let su = s.to_uppercase();
55 let su_slice: &str = &*su;
56 match su_slice {
57 "DATA" => Ok(HTTP2FrameType::DATA),
58 "HEADERS" => Ok(HTTP2FrameType::HEADERS),
59 "PRIORITY" => Ok(HTTP2FrameType::PRIORITY),
60 "RSTSTREAM" => Ok(HTTP2FrameType::RSTSTREAM),
61 "SETTINGS" => Ok(HTTP2FrameType::SETTINGS),
62 "PUSHPROMISE" => Ok(HTTP2FrameType::PUSHPROMISE),
63 "PING" => Ok(HTTP2FrameType::PING),
64 "GOAWAY" => Ok(HTTP2FrameType::GOAWAY),
65 "WINDOWUPDATE" => Ok(HTTP2FrameType::WINDOWUPDATE),
66 "CONTINUATION" => Ok(HTTP2FrameType::CONTINUATION),
67 _ => Err(format!("'{}' is not a valid value for HTTP2FrameType", s)),
68 }
69 }
70 }
71
72 #[derive(PartialEq, Debug)]
73 pub struct HTTP2FrameHeader {
74 //we could add detection on (GOAWAY) additional data
75 pub length: u32,
76 pub ftype: u8,
77 pub flags: u8,
78 pub reserved: u8,
79 pub stream_id: u32,
80 }
81
82 named!(pub http2_parse_frame_header<HTTP2FrameHeader>,
83 do_parse!(
84 length: bits!( take_bits!(24u32) ) >>
85 ftype: be_u8 >>
86 flags: be_u8 >>
87 stream_id: bits!( tuple!( take_bits!(1u8),
88 take_bits!(31u32) ) ) >>
89 (HTTP2FrameHeader{length, ftype, flags,
90 reserved:stream_id.0,
91 stream_id:stream_id.1})
92 )
93 );
94
95 #[repr(u32)]
96 #[derive(Clone, Copy, PartialEq, FromPrimitive, Debug)]
97 pub enum HTTP2ErrorCode {
98 NOERROR = 0,
99 PROTOCOLERROR = 1,
100 INTERNALERROR = 2,
101 FLOWCONTROLERROR = 3,
102 SETTINGSTIMEOUT = 4,
103 STREAMCLOSED = 5,
104 FRAMESIZEERROR = 6,
105 REFUSEDSTREAM = 7,
106 CANCEL = 8,
107 COMPRESSIONERROR = 9,
108 CONNECTERROR = 10,
109 ENHANCEYOURCALM = 11,
110 INADEQUATESECURITY = 12,
111 HTTP11REQUIRED = 13,
112 }
113
114 impl fmt::Display for HTTP2ErrorCode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 write!(f, "{:?}", self)
117 }
118 }
119
120 impl std::str::FromStr for HTTP2ErrorCode {
121 type Err = String;
122
from_str(s: &str) -> Result<Self, Self::Err>123 fn from_str(s: &str) -> Result<Self, Self::Err> {
124 let su = s.to_uppercase();
125 let su_slice: &str = &*su;
126 match su_slice {
127 "NO_ERROR" => Ok(HTTP2ErrorCode::NOERROR),
128 "PROTOCOL_ERROR" => Ok(HTTP2ErrorCode::PROTOCOLERROR),
129 "FLOW_CONTROL_ERROR" => Ok(HTTP2ErrorCode::FLOWCONTROLERROR),
130 "SETTINGS_TIMEOUT" => Ok(HTTP2ErrorCode::SETTINGSTIMEOUT),
131 "STREAM_CLOSED" => Ok(HTTP2ErrorCode::STREAMCLOSED),
132 "FRAME_SIZE_ERROR" => Ok(HTTP2ErrorCode::FRAMESIZEERROR),
133 "REFUSED_STREAM" => Ok(HTTP2ErrorCode::REFUSEDSTREAM),
134 "CANCEL" => Ok(HTTP2ErrorCode::CANCEL),
135 "COMPRESSION_ERROR" => Ok(HTTP2ErrorCode::COMPRESSIONERROR),
136 "CONNECT_ERROR" => Ok(HTTP2ErrorCode::CONNECTERROR),
137 "ENHANCE_YOUR_CALM" => Ok(HTTP2ErrorCode::ENHANCEYOURCALM),
138 "INADEQUATE_SECURITY" => Ok(HTTP2ErrorCode::INADEQUATESECURITY),
139 "HTTP_1_1_REQUIRED" => Ok(HTTP2ErrorCode::HTTP11REQUIRED),
140 _ => Err(format!("'{}' is not a valid value for HTTP2ErrorCode", s)),
141 }
142 }
143 }
144
145 #[derive(Clone, Copy, Debug)]
146 pub struct HTTP2FrameGoAway {
147 pub errorcode: u32, //HTTP2ErrorCode
148 }
149
150 named!(pub http2_parse_frame_goaway<HTTP2FrameGoAway>,
151 do_parse!(
152 errorcode: be_u32 >>
153 (HTTP2FrameGoAway{errorcode})
154 )
155 );
156
157 #[derive(Clone, Copy, Debug)]
158 pub struct HTTP2FrameRstStream {
159 pub errorcode: u32, ////HTTP2ErrorCode
160 }
161
162 named!(pub http2_parse_frame_rststream<HTTP2FrameRstStream>,
163 do_parse!(
164 errorcode: be_u32 >>
165 (HTTP2FrameRstStream{errorcode})
166 )
167 );
168
169 #[derive(Clone, Copy, Debug)]
170 pub struct HTTP2FramePriority {
171 pub exclusive: u8,
172 pub dependency: u32,
173 pub weight: u8,
174 }
175
176 named!(pub http2_parse_frame_priority<HTTP2FramePriority>,
177 do_parse!(
178 sid: bits!( tuple!( take_bits!(1u8),
179 take_bits!(31u32) ) ) >>
180 weight: be_u8 >>
181 (HTTP2FramePriority{exclusive:sid.0, dependency:sid.1, weight})
182 )
183 );
184
185 #[derive(Clone, Copy, Debug)]
186 pub struct HTTP2FrameWindowUpdate {
187 pub reserved: u8,
188 pub sizeinc: u32,
189 }
190
191 named!(pub http2_parse_frame_windowupdate<HTTP2FrameWindowUpdate>,
192 do_parse!(
193 sizeinc: bits!( tuple!( take_bits!(1u8),
194 take_bits!(31u32) ) ) >>
195 (HTTP2FrameWindowUpdate{reserved:sizeinc.0, sizeinc:sizeinc.1})
196 )
197 );
198
199 #[derive(Clone, Copy, Debug)]
200 pub struct HTTP2FrameHeadersPriority {
201 pub exclusive: u8,
202 pub dependency: u32,
203 pub weight: u8,
204 }
205
206 named!(pub http2_parse_headers_priority<HTTP2FrameHeadersPriority>,
207 do_parse!(
208 sid: bits!( tuple!( take_bits!(1u8),
209 take_bits!(31u32) ) ) >>
210 weight: be_u8 >>
211 (HTTP2FrameHeadersPriority{exclusive:sid.0, dependency:sid.1, weight})
212 )
213 );
214
215 pub const HTTP2_STATIC_HEADERS_NUMBER: usize = 61;
216
http2_frame_header_static(n: u64, dyn_headers: &HTTP2DynTable) -> Option<HTTP2FrameHeaderBlock>217 fn http2_frame_header_static(n: u64, dyn_headers: &HTTP2DynTable) -> Option<HTTP2FrameHeaderBlock> {
218 let (name, value) = match n {
219 1 => (":authority", ""),
220 2 => (":method", "GET"),
221 3 => (":method", "POST"),
222 4 => (":path", "/"),
223 5 => (":path", "/index.html"),
224 6 => (":scheme", "http"),
225 7 => (":scheme", "https"),
226 8 => (":status", "200"),
227 9 => (":status", "204"),
228 10 => (":status", "206"),
229 11 => (":status", "304"),
230 12 => (":status", "400"),
231 13 => (":status", "404"),
232 14 => (":status", "500"),
233 15 => ("accept-charset", ""),
234 16 => ("accept-encoding", "gzip, deflate"),
235 17 => ("accept-language", ""),
236 18 => ("accept-ranges", ""),
237 19 => ("accept", ""),
238 20 => ("access-control-allow-origin", ""),
239 21 => ("age", ""),
240 22 => ("allow", ""),
241 23 => ("authorization", ""),
242 24 => ("cache-control", ""),
243 25 => ("content-disposition", ""),
244 26 => ("content-encoding", ""),
245 27 => ("content-language", ""),
246 28 => ("content-length", ""),
247 29 => ("content-location", ""),
248 30 => ("content-range", ""),
249 31 => ("content-type", ""),
250 32 => ("cookie", ""),
251 33 => ("date", ""),
252 34 => ("etag", ""),
253 35 => ("expect", ""),
254 36 => ("expires", ""),
255 37 => ("from", ""),
256 38 => ("host", ""),
257 39 => ("if-match", ""),
258 40 => ("if-modified-since", ""),
259 41 => ("if-none-match", ""),
260 42 => ("if-range", ""),
261 43 => ("if-unmodified-since", ""),
262 44 => ("last-modified", ""),
263 45 => ("link", ""),
264 46 => ("location", ""),
265 47 => ("max-forwards", ""),
266 48 => ("proxy-authenticate", ""),
267 49 => ("proxy-authorization", ""),
268 50 => ("range", ""),
269 51 => ("referer", ""),
270 52 => ("refresh", ""),
271 53 => ("retry-after", ""),
272 54 => ("server", ""),
273 55 => ("set-cookie", ""),
274 56 => ("strict-transport-security", ""),
275 57 => ("transfer-encoding", ""),
276 58 => ("user-agent", ""),
277 59 => ("vary", ""),
278 60 => ("via", ""),
279 61 => ("www-authenticate", ""),
280 _ => ("", ""),
281 };
282 if name.len() > 0 {
283 return Some(HTTP2FrameHeaderBlock {
284 name: name.as_bytes().to_vec(),
285 value: value.as_bytes().to_vec(),
286 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess,
287 sizeupdate: 0,
288 });
289 } else {
290 //use dynamic table
291 if n == 0 {
292 return Some(HTTP2FrameHeaderBlock {
293 name: Vec::new(),
294 value: Vec::new(),
295 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIndex0,
296 sizeupdate: 0,
297 });
298 } else if dyn_headers.table.len() + HTTP2_STATIC_HEADERS_NUMBER < n as usize {
299 return Some(HTTP2FrameHeaderBlock {
300 name: Vec::new(),
301 value: Vec::new(),
302 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeNotIndexed,
303 sizeupdate: 0,
304 });
305 } else {
306 let indyn = dyn_headers.table.len() - (n as usize - HTTP2_STATIC_HEADERS_NUMBER);
307 let headcopy = HTTP2FrameHeaderBlock {
308 name: dyn_headers.table[indyn].name.to_vec(),
309 value: dyn_headers.table[indyn].value.to_vec(),
310 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess,
311 sizeupdate: 0,
312 };
313 return Some(headcopy);
314 }
315 }
316 }
317
318 #[repr(u8)]
319 #[derive(Copy, Clone, PartialOrd, PartialEq, Debug)]
320 pub enum HTTP2HeaderDecodeStatus {
321 HTTP2HeaderDecodeSuccess = 0,
322 HTTP2HeaderDecodeSizeUpdate = 1,
323 HTTP2HeaderDecodeError = 0x80,
324 HTTP2HeaderDecodeNotIndexed = 0x81,
325 HTTP2HeaderDecodeIntegerOverflow = 0x82,
326 HTTP2HeaderDecodeIndex0 = 0x83,
327 }
328
329 impl fmt::Display for HTTP2HeaderDecodeStatus {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result330 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
331 write!(f, "{:?}", self)
332 }
333 }
334
335 #[derive(Clone, Debug)]
336 pub struct HTTP2FrameHeaderBlock {
337 pub name: Vec<u8>,
338 pub value: Vec<u8>,
339 pub error: HTTP2HeaderDecodeStatus,
340 pub sizeupdate: u64,
341 }
342
http2_parse_headers_block_indexed<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>343 fn http2_parse_headers_block_indexed<'a>(
344 input: &'a [u8], dyn_headers: &HTTP2DynTable,
345 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
346 fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
347 bits!(
348 input,
349 complete!(tuple!(
350 verify!(take_bits!(1u8), |&x| x == 1),
351 take_bits!(7u8)
352 ))
353 )
354 }
355 let (i2, indexed) = parser(input)?;
356 let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0x7F)?;
357 if indexreal == 0 && indexed.1 == 0x7F {
358 return Err(Err::Error((i3, ErrorKind::LengthValue)));
359 }
360 match http2_frame_header_static(indexreal, dyn_headers) {
361 Some(h) => Ok((i3, h)),
362 _ => Err(Err::Error((i3, ErrorKind::MapOpt))),
363 }
364 }
365
http2_parse_headers_block_string(input: &[u8]) -> IResult<&[u8], Vec<u8>>366 fn http2_parse_headers_block_string(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
367 fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
368 bits!(input, tuple!(take_bits!(1u8), take_bits!(7u8)))
369 }
370 let (i1, huffslen) = parser(input)?;
371 let (i2, stringlen) = http2_parse_var_uint(i1, huffslen.1 as u64, 0x7F)?;
372 if stringlen == 0 && huffslen.1 == 0x7F {
373 return Err(Err::Error((i2, ErrorKind::LengthValue)));
374 }
375 let (i3, data) = take!(i2, stringlen as usize)?;
376 if huffslen.0 == 0 {
377 return Ok((i3, data.to_vec()));
378 } else {
379 let (_, val) = bits!(data, many0!(huffman::http2_decode_huffman))?;
380 return Ok((i3, val));
381 }
382 }
383
http2_parse_headers_block_literal_common<'a>( input: &'a [u8], index: u64, dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>384 fn http2_parse_headers_block_literal_common<'a>(
385 input: &'a [u8], index: u64, dyn_headers: &HTTP2DynTable,
386 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
387 let (i3, name, error) = if index == 0 {
388 match http2_parse_headers_block_string(input) {
389 Ok((r, n)) => Ok((r, n, HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess)),
390 Err(e) => Err(e),
391 }
392 } else {
393 match http2_frame_header_static(index, dyn_headers) {
394 Some(x) => Ok((
395 input,
396 x.name,
397 HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess,
398 )),
399 None => Ok((
400 input,
401 Vec::new(),
402 HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeNotIndexed,
403 )),
404 }
405 }?;
406 let (i4, value) = http2_parse_headers_block_string(i3)?;
407 return Ok((
408 i4,
409 HTTP2FrameHeaderBlock {
410 name,
411 value,
412 error,
413 sizeupdate: 0,
414 },
415 ));
416 }
417
http2_parse_headers_block_literal_incindex<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>418 fn http2_parse_headers_block_literal_incindex<'a>(
419 input: &'a [u8], dyn_headers: &mut HTTP2DynTable,
420 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
421 fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
422 bits!(
423 input,
424 complete!(tuple!(
425 verify!(take_bits!(2u8), |&x| x == 1),
426 take_bits!(6u8)
427 ))
428 )
429 }
430 let (i2, indexed) = parser(input)?;
431 let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0x3F)?;
432 if indexreal == 0 && indexed.1 == 0x3F {
433 return Err(Err::Error((i3, ErrorKind::LengthValue)));
434 }
435 let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers);
436 match r {
437 Ok((r, head)) => {
438 let headcopy = HTTP2FrameHeaderBlock {
439 name: head.name.to_vec(),
440 value: head.value.to_vec(),
441 error: head.error,
442 sizeupdate: 0,
443 };
444 if head.error == HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess {
445 dyn_headers.current_size += 32 + headcopy.name.len() + headcopy.value.len();
446 //in case of overflow, best effort is to keep first headers
447 if dyn_headers.overflow > 0 {
448 if dyn_headers.overflow == 1 {
449 if dyn_headers.current_size <= (HTTP2_MAX_TABLESIZE as usize) {
450 //overflow had not yet happened
451 dyn_headers.table.push(headcopy);
452 } else if dyn_headers.current_size > dyn_headers.max_size {
453 //overflow happens, we cannot replace evicted headers
454 dyn_headers.overflow = 2;
455 }
456 }
457 } else {
458 dyn_headers.table.push(headcopy);
459 }
460 while dyn_headers.current_size > dyn_headers.max_size && dyn_headers.table.len() > 0
461 {
462 dyn_headers.current_size -=
463 32 + dyn_headers.table[0].name.len() + dyn_headers.table[0].value.len();
464 dyn_headers.table.remove(0);
465 }
466 }
467 return Ok((r, head));
468 }
469 Err(e) => {
470 return Err(e);
471 }
472 }
473 }
474
http2_parse_headers_block_literal_noindex<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>475 fn http2_parse_headers_block_literal_noindex<'a>(
476 input: &'a [u8], dyn_headers: &HTTP2DynTable,
477 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
478 fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
479 bits!(
480 input,
481 complete!(tuple!(
482 verify!(take_bits!(4u8), |&x| x == 0),
483 take_bits!(4u8)
484 ))
485 )
486 }
487 let (i2, indexed) = parser(input)?;
488 let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0xF)?;
489 if indexreal == 0 && indexed.1 == 0xF {
490 return Err(Err::Error((i3, ErrorKind::LengthValue)));
491 }
492 let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers);
493 return r;
494 }
495
http2_parse_headers_block_literal_neverindex<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>496 fn http2_parse_headers_block_literal_neverindex<'a>(
497 input: &'a [u8], dyn_headers: &HTTP2DynTable,
498 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
499 fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
500 bits!(
501 input,
502 complete!(tuple!(
503 verify!(take_bits!(4u8), |&x| x == 1),
504 take_bits!(4u8)
505 ))
506 )
507 }
508 let (i2, indexed) = parser(input)?;
509 let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0xF)?;
510 if indexreal == 0 && indexed.1 == 0xF {
511 return Err(Err::Error((i3, ErrorKind::LengthValue)));
512 }
513 let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers);
514 return r;
515 }
516
http2_parse_var_uint(input: &[u8], value: u64, max: u64) -> IResult<&[u8], u64>517 fn http2_parse_var_uint(input: &[u8], value: u64, max: u64) -> IResult<&[u8], u64> {
518 if value < max {
519 return Ok((input, value));
520 }
521 let (i2, varia) = take_while!(input, |ch| (ch & 0x80) != 0)?;
522 let (i3, finalv) = be_u8(i2)?;
523 if varia.len() > 9 || (varia.len() == 9 && finalv > 1) {
524 // this will overflow u64
525 return Ok((i3, 0));
526 }
527 let mut varval = max;
528 for i in 0..varia.len() {
529 varval += ((varia[i] & 0x7F) as u64) << (7 * i);
530 }
531 varval += (finalv as u64) << (7 * varia.len());
532 if varval < max {
533 // this has overflown u64
534 return Ok((i3, 0));
535 }
536 return Ok((i3, varval));
537 }
538
http2_parse_headers_block_dynamic_size<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>539 fn http2_parse_headers_block_dynamic_size<'a>(
540 input: &'a [u8], dyn_headers: &mut HTTP2DynTable,
541 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
542 fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
543 bits!(
544 input,
545 complete!(tuple!(
546 verify!(take_bits!(3u8), |&x| x == 1),
547 take_bits!(5u8)
548 ))
549 )
550 }
551 let (i2, maxsize) = parser(input)?;
552 let (i3, maxsize2) = http2_parse_var_uint(i2, maxsize.1 as u64, 0x1F)?;
553 if maxsize2 == 0 && maxsize.1 == 0x1F {
554 return Ok((
555 i3,
556 HTTP2FrameHeaderBlock {
557 name: Vec::new(),
558 value: Vec::new(),
559 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIntegerOverflow,
560 sizeupdate: 0,
561 },
562 ));
563 }
564 if (maxsize2 as usize) < dyn_headers.max_size {
565 //dyn_headers.max_size is updated later with all headers
566 //may evict entries
567 while dyn_headers.current_size > (maxsize2 as usize) && dyn_headers.table.len() > 0 {
568 // we check dyn_headers.table as we may be in best effort
569 // because the previous maxsize was too big for us to retain all the headers
570 dyn_headers.current_size -=
571 32 + dyn_headers.table[0].name.len() + dyn_headers.table[0].value.len();
572 dyn_headers.table.remove(0);
573 }
574 }
575 return Ok((
576 i3,
577 HTTP2FrameHeaderBlock {
578 name: Vec::new(),
579 value: Vec::new(),
580 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate,
581 sizeupdate: maxsize2,
582 },
583 ));
584 }
585
http2_parse_headers_block<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>586 fn http2_parse_headers_block<'a>(
587 input: &'a [u8], dyn_headers: &mut HTTP2DynTable,
588 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
589 //caller garantees o have at least one byte
590 if input[0] & 0x80 != 0 {
591 return http2_parse_headers_block_indexed(input, dyn_headers);
592 } else if input[0] & 0x40 != 0 {
593 return http2_parse_headers_block_literal_incindex(input, dyn_headers);
594 } else if input[0] & 0x20 != 0 {
595 return http2_parse_headers_block_dynamic_size(input, dyn_headers);
596 } else if input[0] & 0x10 != 0 {
597 return http2_parse_headers_block_literal_neverindex(input, dyn_headers);
598 } else {
599 return http2_parse_headers_block_literal_noindex(input, dyn_headers);
600 }
601 }
602
603 #[derive(Clone, Debug)]
604 pub struct HTTP2FrameHeaders {
605 pub padlength: Option<u8>,
606 pub priority: Option<HTTP2FrameHeadersPriority>,
607 pub blocks: Vec<HTTP2FrameHeaderBlock>,
608 }
609
610 //end stream
611 pub const HTTP2_FLAG_HEADER_EOS: u8 = 0x1;
612 pub const HTTP2_FLAG_HEADER_END_HEADERS: u8 = 0x4;
613 const HTTP2_FLAG_HEADER_PADDED: u8 = 0x8;
614 const HTTP2_FLAG_HEADER_PRIORITY: u8 = 0x20;
615
http2_parse_frame_headers<'a>( input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaders>616 pub fn http2_parse_frame_headers<'a>(
617 input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable,
618 ) -> IResult<&'a [u8], HTTP2FrameHeaders> {
619 let (i2, padlength) = cond!(input, flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)?;
620 let (mut i3, priority) = cond!(
621 i2,
622 flags & HTTP2_FLAG_HEADER_PRIORITY != 0,
623 http2_parse_headers_priority
624 )?;
625 let mut blocks = Vec::new();
626 while i3.len() > 0 {
627 match http2_parse_headers_block(i3, dyn_headers) {
628 Ok((rem, b)) => {
629 blocks.push(b);
630 debug_validate_bug_on!(i3.len() == rem.len());
631 if i3.len() == rem.len() {
632 //infinite loop
633 return Err(Err::Error((input, ErrorKind::Eof)));
634 }
635 i3 = rem;
636 }
637 Err(x) => {
638 return Err(x);
639 }
640 }
641 }
642 return Ok((
643 i3,
644 HTTP2FrameHeaders {
645 padlength,
646 priority,
647 blocks,
648 },
649 ));
650 }
651
652 #[derive(Clone, Debug)]
653 pub struct HTTP2FramePushPromise {
654 pub padlength: Option<u8>,
655 pub reserved: u8,
656 pub stream_id: u32,
657 pub blocks: Vec<HTTP2FrameHeaderBlock>,
658 }
659
http2_parse_frame_push_promise<'a>( input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FramePushPromise>660 pub fn http2_parse_frame_push_promise<'a>(
661 input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable,
662 ) -> IResult<&'a [u8], HTTP2FramePushPromise> {
663 let (i2, padlength) = cond!(input, flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)?;
664 let (mut i3, stream_id) = bits!(i2, tuple!(take_bits!(1u8), take_bits!(31u32)))?;
665 let mut blocks = Vec::new();
666 while i3.len() > 0 {
667 match http2_parse_headers_block(i3, dyn_headers) {
668 Ok((rem, b)) => {
669 blocks.push(b);
670 debug_validate_bug_on!(i3.len() == rem.len());
671 if i3.len() == rem.len() {
672 //infinite loop
673 return Err(Err::Error((input, ErrorKind::Eof)));
674 }
675 i3 = rem;
676 }
677 Err(x) => {
678 return Err(x);
679 }
680 }
681 }
682 return Ok((
683 i3,
684 HTTP2FramePushPromise {
685 padlength,
686 reserved: stream_id.0,
687 stream_id: stream_id.1,
688 blocks,
689 },
690 ));
691 }
692
693 #[derive(Clone, Debug)]
694 pub struct HTTP2FrameContinuation {
695 pub blocks: Vec<HTTP2FrameHeaderBlock>,
696 }
697
http2_parse_frame_continuation<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameContinuation>698 pub fn http2_parse_frame_continuation<'a>(
699 input: &'a [u8], dyn_headers: &mut HTTP2DynTable,
700 ) -> IResult<&'a [u8], HTTP2FrameContinuation> {
701 let mut i3 = input;
702 let mut blocks = Vec::new();
703 while i3.len() > 0 {
704 match http2_parse_headers_block(i3, dyn_headers) {
705 Ok((rem, b)) => {
706 blocks.push(b);
707 debug_validate_bug_on!(i3.len() == rem.len());
708 if i3.len() == rem.len() {
709 //infinite loop
710 return Err(Err::Error((input, ErrorKind::Eof)));
711 }
712 i3 = rem;
713 }
714 Err(x) => {
715 return Err(x);
716 }
717 }
718 }
719 return Ok((i3, HTTP2FrameContinuation { blocks }));
720 }
721
722 #[repr(u16)]
723 #[derive(Clone, Copy, PartialEq, FromPrimitive, Debug)]
724 pub enum HTTP2SettingsId {
725 SETTINGSHEADERTABLESIZE = 1,
726 SETTINGSENABLEPUSH = 2,
727 SETTINGSMAXCONCURRENTSTREAMS = 3,
728 SETTINGSINITIALWINDOWSIZE = 4,
729 SETTINGSMAXFRAMESIZE = 5,
730 SETTINGSMAXHEADERLISTSIZE = 6,
731 }
732
733 impl fmt::Display for HTTP2SettingsId {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result734 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
735 write!(f, "{:?}", self)
736 }
737 }
738
739 impl std::str::FromStr for HTTP2SettingsId {
740 type Err = String;
741
from_str(s: &str) -> Result<Self, Self::Err>742 fn from_str(s: &str) -> Result<Self, Self::Err> {
743 let su = s.to_uppercase();
744 let su_slice: &str = &*su;
745 match su_slice {
746 "SETTINGS_HEADER_TABLE_SIZE" => Ok(HTTP2SettingsId::SETTINGSHEADERTABLESIZE),
747 "SETTINGS_ENABLE_PUSH" => Ok(HTTP2SettingsId::SETTINGSENABLEPUSH),
748 "SETTINGS_MAX_CONCURRENT_STREAMS" => Ok(HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS),
749 "SETTINGS_INITIAL_WINDOW_SIZE" => Ok(HTTP2SettingsId::SETTINGSINITIALWINDOWSIZE),
750 "SETTINGS_MAX_FRAME_SIZE" => Ok(HTTP2SettingsId::SETTINGSMAXFRAMESIZE),
751 "SETTINGS_MAX_HEADER_LIST_SIZE" => Ok(HTTP2SettingsId::SETTINGSMAXHEADERLISTSIZE),
752 _ => Err(format!("'{}' is not a valid value for HTTP2SettingsId", s)),
753 }
754 }
755 }
756
757 //TODOask move elsewhere generic with DetectU64Data and such
758 #[derive(PartialEq, Debug)]
759 pub enum DetectUintMode {
760 DetectUintModeEqual,
761 DetectUintModeLt,
762 DetectUintModeGt,
763 DetectUintModeRange,
764 }
765
766 pub struct DetectU32Data {
767 pub value: u32,
768 pub valrange: u32,
769 pub mode: DetectUintMode,
770 }
771
772 pub struct DetectHTTP2settingsSigCtx {
773 pub id: HTTP2SettingsId, //identifier
774 pub value: Option<DetectU32Data>, //optional value
775 }
776
777 named!(detect_parse_u32_start_equal<&str,DetectU32Data>,
778 do_parse!(
779 opt!( is_a!( " " ) ) >>
780 opt! (tag!("=") ) >>
781 opt!( is_a!( " " ) ) >>
782 value : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
783 (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeEqual})
784 )
785 );
786
787 named!(detect_parse_u32_start_interval<&str,DetectU32Data>,
788 do_parse!(
789 opt!( is_a!( " " ) ) >>
790 value : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
791 opt!( is_a!( " " ) ) >>
792 tag!("-") >>
793 opt!( is_a!( " " ) ) >>
794 valrange : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
795 (DetectU32Data{value, valrange, mode:DetectUintMode::DetectUintModeRange})
796 )
797 );
798
799 named!(detect_parse_u32_start_lesser<&str,DetectU32Data>,
800 do_parse!(
801 opt!( is_a!( " " ) ) >>
802 tag!("<") >>
803 opt!( is_a!( " " ) ) >>
804 value : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
805 (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeLt})
806 )
807 );
808
809 named!(detect_parse_u32_start_greater<&str,DetectU32Data>,
810 do_parse!(
811 opt!( is_a!( " " ) ) >>
812 tag!(">") >>
813 opt!( is_a!( " " ) ) >>
814 value : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
815 (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeGt})
816 )
817 );
818
819 named!(detect_parse_u32<&str,DetectU32Data>,
820 do_parse!(
821 u32 : alt! (
822 detect_parse_u32_start_lesser |
823 detect_parse_u32_start_greater |
824 complete!( detect_parse_u32_start_interval ) |
825 detect_parse_u32_start_equal
826 ) >>
827 (u32)
828 )
829 );
830
831 named!(pub http2_parse_settingsctx<&str,DetectHTTP2settingsSigCtx>,
832 do_parse!(
833 opt!( is_a!( " " ) ) >>
834 id: map_opt!( alt! ( complete!( is_not!( " <>=" ) ) | rest ),
835 |s: &str| HTTP2SettingsId::from_str(s).ok() ) >>
836 value: opt!( complete!( detect_parse_u32 ) ) >>
837 (DetectHTTP2settingsSigCtx{id, value})
838 )
839 );
840
841 pub struct DetectU64Data {
842 pub value: u64,
843 pub valrange: u64,
844 pub mode: DetectUintMode,
845 }
846
847 named!(detect_parse_u64_start_equal<&str,DetectU64Data>,
848 do_parse!(
849 opt!( is_a!( " " ) ) >>
850 opt! (tag!("=") ) >>
851 opt!( is_a!( " " ) ) >>
852 value : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
853 (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeEqual})
854 )
855 );
856
857 named!(detect_parse_u64_start_interval<&str,DetectU64Data>,
858 do_parse!(
859 opt!( is_a!( " " ) ) >>
860 value : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
861 opt!( is_a!( " " ) ) >>
862 tag!("-") >>
863 opt!( is_a!( " " ) ) >>
864 valrange : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
865 (DetectU64Data{value, valrange, mode:DetectUintMode::DetectUintModeRange})
866 )
867 );
868
869 named!(detect_parse_u64_start_lesser<&str,DetectU64Data>,
870 do_parse!(
871 opt!( is_a!( " " ) ) >>
872 tag!("<") >>
873 opt!( is_a!( " " ) ) >>
874 value : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
875 (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeLt})
876 )
877 );
878
879 named!(detect_parse_u64_start_greater<&str,DetectU64Data>,
880 do_parse!(
881 opt!( is_a!( " " ) ) >>
882 tag!(">") >>
883 opt!( is_a!( " " ) ) >>
884 value : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
885 (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeGt})
886 )
887 );
888
889 named!(pub detect_parse_u64<&str,DetectU64Data>,
890 do_parse!(
891 u64 : alt! (
892 detect_parse_u64_start_lesser |
893 detect_parse_u64_start_greater |
894 complete!( detect_parse_u64_start_interval ) |
895 detect_parse_u64_start_equal
896 ) >>
897 (u64)
898 )
899 );
900
901 #[derive(Clone, Copy, Debug)]
902 pub struct HTTP2FrameSettings {
903 pub id: HTTP2SettingsId,
904 pub value: u32,
905 }
906
907 named!(
908 http2_parse_frame_setting<HTTP2FrameSettings>,
909 do_parse!(
910 id: map_opt!(be_u16, num::FromPrimitive::from_u16)
911 >> value: be_u32
912 >> (HTTP2FrameSettings { id, value })
913 )
914 );
915
916 named!(pub http2_parse_frame_settings<Vec<HTTP2FrameSettings>>,
917 many0!( complete!(http2_parse_frame_setting) )
918 );
919
920 #[cfg(test)]
921 mod tests {
922
923 use super::*;
924
925 #[test]
test_http2_parse_header()926 fn test_http2_parse_header() {
927 let buf0: &[u8] = &[0x82];
928 let mut dynh = HTTP2DynTable::new();
929 let r0 = http2_parse_headers_block(buf0, &mut dynh);
930 match r0 {
931 Ok((remainder, hd)) => {
932 // Check the first message.
933 assert_eq!(hd.name, ":method".as_bytes().to_vec());
934 assert_eq!(hd.value, "GET".as_bytes().to_vec());
935 // And we should have no bytes left.
936 assert_eq!(remainder.len(), 0);
937 }
938 Err(Err::Incomplete(_)) => {
939 panic!("Result should not have been incomplete.");
940 }
941 Err(Err::Error(err)) | Err(Err::Failure(err)) => {
942 panic!("Result should not be an error: {:?}.", err);
943 }
944 }
945 let buf1: &[u8] = &[0x53, 0x03, 0x2A, 0x2F, 0x2A];
946 let r1 = http2_parse_headers_block(buf1, &mut dynh);
947 match r1 {
948 Ok((remainder, hd)) => {
949 // Check the first message.
950 assert_eq!(hd.name, "accept".as_bytes().to_vec());
951 assert_eq!(hd.value, "*/*".as_bytes().to_vec());
952 // And we should have no bytes left.
953 assert_eq!(remainder.len(), 0);
954 assert_eq!(dynh.table.len(), 1);
955 }
956 Err(Err::Incomplete(_)) => {
957 panic!("Result should not have been incomplete.");
958 }
959 Err(Err::Error(err)) | Err(Err::Failure(err)) => {
960 panic!("Result should not be an error: {:?}.", err);
961 }
962 }
963 let buf: &[u8] = &[
964 0x41, 0x8a, 0xa0, 0xe4, 0x1d, 0x13, 0x9d, 0x09, 0xb8, 0xc8, 0x00, 0x0f,
965 ];
966 let result = http2_parse_headers_block(buf, &mut dynh);
967 match result {
968 Ok((remainder, hd)) => {
969 // Check the first message.
970 assert_eq!(hd.name, ":authority".as_bytes().to_vec());
971 assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec());
972 // And we should have no bytes left.
973 assert_eq!(remainder.len(), 0);
974 assert_eq!(dynh.table.len(), 2);
975 }
976 Err(Err::Incomplete(_)) => {
977 panic!("Result should not have been incomplete.");
978 }
979 Err(Err::Error(err)) | Err(Err::Failure(err)) => {
980 panic!("Result should not be an error: {:?}.", err);
981 }
982 }
983 let buf3: &[u8] = &[0xbe];
984 let r3 = http2_parse_headers_block(buf3, &mut dynh);
985 match r3 {
986 Ok((remainder, hd)) => {
987 // same as before
988 assert_eq!(hd.name, ":authority".as_bytes().to_vec());
989 assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec());
990 // And we should have no bytes left.
991 assert_eq!(remainder.len(), 0);
992 assert_eq!(dynh.table.len(), 2);
993 }
994 Err(Err::Incomplete(_)) => {
995 panic!("Result should not have been incomplete.");
996 }
997 Err(Err::Error(err)) | Err(Err::Failure(err)) => {
998 panic!("Result should not be an error: {:?}.", err);
999 }
1000 }
1001 let buf4: &[u8] = &[0x80];
1002 let r4 = http2_parse_headers_block(buf4, &mut dynh);
1003 match r4 {
1004 Ok((remainder, hd)) => {
1005 assert_eq!(hd.error, HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIndex0);
1006 assert_eq!(remainder.len(), 0);
1007 assert_eq!(dynh.table.len(), 2);
1008 }
1009 Err(Err::Incomplete(_)) => {
1010 panic!("Result should not have been incomplete.");
1011 }
1012 Err(Err::Error(err)) | Err(Err::Failure(err)) => {
1013 panic!("Result should not be an error: {:?}.", err);
1014 }
1015 }
1016 let buf2: &[u8] = &[
1017 0x04, 0x94, 0x62, 0x43, 0x91, 0x8a, 0x47, 0x55, 0xa3, 0xa1, 0x89, 0xd3, 0x4d, 0x0c,
1018 0x1a, 0xa9, 0x0b, 0xe5, 0x79, 0xd3, 0x4d, 0x1f,
1019 ];
1020 let r2 = http2_parse_headers_block(buf2, &mut dynh);
1021 match r2 {
1022 Ok((remainder, hd)) => {
1023 // Check the first message.
1024 assert_eq!(hd.name, ":path".as_bytes().to_vec());
1025 assert_eq!(hd.value, "/doc/manual/html/index.html".as_bytes().to_vec());
1026 // And we should have no bytes left.
1027 assert_eq!(remainder.len(), 0);
1028 assert_eq!(dynh.table.len(), 2);
1029 }
1030 Err(Err::Incomplete(_)) => {
1031 panic!("Result should not have been incomplete.");
1032 }
1033 Err(Err::Error(err)) | Err(Err::Failure(err)) => {
1034 panic!("Result should not be an error: {:?}.", err);
1035 }
1036 }
1037 }
1038
1039 /// Simple test of some valid data.
1040 #[test]
test_http2_parse_settingsctx()1041 fn test_http2_parse_settingsctx() {
1042 let s = "SETTINGS_ENABLE_PUSH";
1043 let r = http2_parse_settingsctx(s);
1044 match r {
1045 Ok((rem, ctx)) => {
1046 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSENABLEPUSH);
1047 match ctx.value {
1048 Some(_) => {
1049 panic!("Unexpected value");
1050 }
1051 None => {}
1052 }
1053 assert_eq!(rem.len(), 0);
1054 }
1055 Err(e) => {
1056 panic!("Result should not be an error {:?}.", e);
1057 }
1058 }
1059
1060 //spaces in the end
1061 let s1 = "SETTINGS_ENABLE_PUSH ";
1062 let r1 = http2_parse_settingsctx(s1);
1063 match r1 {
1064 Ok((rem, ctx)) => {
1065 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSENABLEPUSH);
1066 match ctx.value {
1067 Some(_) => {
1068 panic!("Unexpected value");
1069 }
1070 None => {}
1071 }
1072 assert_eq!(rem.len(), 1);
1073 }
1074 Err(e) => {
1075 panic!("Result should not be an error {:?}.", e);
1076 }
1077 }
1078
1079 let s2 = "SETTINGS_MAX_CONCURRENT_STREAMS 42";
1080 let r2 = http2_parse_settingsctx(s2);
1081 match r2 {
1082 Ok((rem, ctx)) => {
1083 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
1084 match ctx.value {
1085 Some(ctxval) => {
1086 assert_eq!(ctxval.value, 42);
1087 }
1088 None => {
1089 panic!("No value");
1090 }
1091 }
1092 assert_eq!(rem.len(), 0);
1093 }
1094 Err(e) => {
1095 panic!("Result should not be an error {:?}.", e);
1096 }
1097 }
1098
1099 let s3 = "SETTINGS_MAX_CONCURRENT_STREAMS 42-68";
1100 let r3 = http2_parse_settingsctx(s3);
1101 match r3 {
1102 Ok((rem, ctx)) => {
1103 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
1104 match ctx.value {
1105 Some(ctxval) => {
1106 assert_eq!(ctxval.value, 42);
1107 assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeRange);
1108 assert_eq!(ctxval.valrange, 68);
1109 }
1110 None => {
1111 panic!("No value");
1112 }
1113 }
1114 assert_eq!(rem.len(), 0);
1115 }
1116 Err(e) => {
1117 panic!("Result should not be an error {:?}.", e);
1118 }
1119 }
1120
1121 let s4 = "SETTINGS_MAX_CONCURRENT_STREAMS<54";
1122 let r4 = http2_parse_settingsctx(s4);
1123 match r4 {
1124 Ok((rem, ctx)) => {
1125 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
1126 match ctx.value {
1127 Some(ctxval) => {
1128 assert_eq!(ctxval.value, 54);
1129 assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeLt);
1130 }
1131 None => {
1132 panic!("No value");
1133 }
1134 }
1135 assert_eq!(rem.len(), 0);
1136 }
1137 Err(e) => {
1138 panic!("Result should not be an error {:?}.", e);
1139 }
1140 }
1141
1142 let s5 = "SETTINGS_MAX_CONCURRENT_STREAMS > 76";
1143 let r5 = http2_parse_settingsctx(s5);
1144 match r5 {
1145 Ok((rem, ctx)) => {
1146 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
1147 match ctx.value {
1148 Some(ctxval) => {
1149 assert_eq!(ctxval.value, 76);
1150 assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeGt);
1151 }
1152 None => {
1153 panic!("No value");
1154 }
1155 }
1156 assert_eq!(rem.len(), 0);
1157 }
1158 Err(e) => {
1159 panic!("Result should not be an error {:?}.", e);
1160 }
1161 }
1162 }
1163
1164 #[test]
test_http2_parse_headers_block_string()1165 fn test_http2_parse_headers_block_string() {
1166 let buf: &[u8] = &[0x01, 0xFF];
1167 let r = http2_parse_headers_block_string(buf);
1168 match r {
1169 Ok((remainder, _)) => {
1170 assert_eq!(remainder.len(), 0);
1171 }
1172 Err(Err::Error(err)) | Err(Err::Failure(err)) => {
1173 panic!("Result should not be an error: {:?}.", err);
1174 }
1175 _ => {
1176 panic!("Result should have been ok");
1177 }
1178 }
1179 let buf2: &[u8] = &[0x83, 0xFF, 0xFF, 0xEA];
1180 let r2 = http2_parse_headers_block_string(buf2);
1181 match r2 {
1182 Ok((remainder, _)) => {
1183 assert_eq!(remainder.len(), 0);
1184 }
1185 _ => {
1186 panic!("Result should have been ok");
1187 }
1188 }
1189 }
1190
1191 #[test]
test_http2_parse_frame_header()1192 fn test_http2_parse_frame_header() {
1193 let buf: &[u8] = &[
1194 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1195 0x64,
1196 ];
1197 let result = http2_parse_frame_header(buf);
1198 match result {
1199 Ok((remainder, frame)) => {
1200 // Check the first message.
1201 assert_eq!(frame.length, 6);
1202 assert_eq!(frame.ftype, HTTP2FrameType::SETTINGS as u8);
1203 assert_eq!(frame.flags, 0);
1204 assert_eq!(frame.reserved, 0);
1205 assert_eq!(frame.stream_id, 0);
1206
1207 // And we should have 6 bytes left.
1208 assert_eq!(remainder.len(), 6);
1209 }
1210 Err(Err::Incomplete(_)) => {
1211 panic!("Result should not have been incomplete.");
1212 }
1213 Err(Err::Error(err)) | Err(Err::Failure(err)) => {
1214 panic!("Result should not be an error: {:?}.", err);
1215 }
1216 }
1217 }
1218 }
1219