summaryrefslogtreecommitdiffstats
path: root/rust/src/http2/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/http2/parser.rs')
-rw-r--r--rust/src/http2/parser.rs61
1 files changed, 32 insertions, 29 deletions
diff --git a/rust/src/http2/parser.rs b/rust/src/http2/parser.rs
index adabeb2..1a46437 100644
--- a/rust/src/http2/parser.rs
+++ b/rust/src/http2/parser.rs
@@ -30,6 +30,7 @@ use nom7::sequence::tuple;
use nom7::{Err, IResult};
use std::fmt;
use std::str::FromStr;
+use std::rc::Rc;
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, FromPrimitive, Debug)]
@@ -295,8 +296,8 @@ fn http2_frame_header_static(n: u64, dyn_headers: &HTTP2DynTable) -> Option<HTTP
};
if !name.is_empty() {
return Some(HTTP2FrameHeaderBlock {
- name: name.as_bytes().to_vec(),
- value: value.as_bytes().to_vec(),
+ name: Rc::new(name.as_bytes().to_vec()),
+ value: Rc::new(value.as_bytes().to_vec()),
error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess,
sizeupdate: 0,
});
@@ -304,23 +305,23 @@ fn http2_frame_header_static(n: u64, dyn_headers: &HTTP2DynTable) -> Option<HTTP
//use dynamic table
if n == 0 {
return Some(HTTP2FrameHeaderBlock {
- name: Vec::new(),
- value: Vec::new(),
+ name: Rc::new(Vec::new()),
+ value: Rc::new(Vec::new()),
error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIndex0,
sizeupdate: 0,
});
} else if dyn_headers.table.len() + HTTP2_STATIC_HEADERS_NUMBER < n as usize {
return Some(HTTP2FrameHeaderBlock {
- name: Vec::new(),
- value: Vec::new(),
+ name: Rc::new(Vec::new()),
+ value: Rc::new(Vec::new()),
error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeNotIndexed,
sizeupdate: 0,
});
} else {
let indyn = dyn_headers.table.len() - (n as usize - HTTP2_STATIC_HEADERS_NUMBER);
let headcopy = HTTP2FrameHeaderBlock {
- name: dyn_headers.table[indyn].name.to_vec(),
- value: dyn_headers.table[indyn].value.to_vec(),
+ name: dyn_headers.table[indyn].name.clone(),
+ value: dyn_headers.table[indyn].value.clone(),
error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess,
sizeupdate: 0,
};
@@ -348,8 +349,10 @@ impl fmt::Display for HTTP2HeaderDecodeStatus {
#[derive(Clone, Debug)]
pub struct HTTP2FrameHeaderBlock {
- pub name: Vec<u8>,
- pub value: Vec<u8>,
+ // Use Rc reference counted so that indexed headers do not get copied.
+ // Otherwise, this leads to quadratic complexity in memory occupation.
+ pub name: Rc<Vec<u8>>,
+ pub value: Rc<Vec<u8>>,
pub error: HTTP2HeaderDecodeStatus,
pub sizeupdate: u64,
}
@@ -391,7 +394,7 @@ fn http2_parse_headers_block_literal_common<'a>(
) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
let (i3, name, error) = if index == 0 {
match http2_parse_headers_block_string(input) {
- Ok((r, n)) => Ok((r, n, HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess)),
+ Ok((r, n)) => Ok((r, Rc::new(n), HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess)),
Err(e) => Err(e),
}
} else {
@@ -403,7 +406,7 @@ fn http2_parse_headers_block_literal_common<'a>(
)),
None => Ok((
input,
- Vec::new(),
+ Rc::new(Vec::new()),
HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeNotIndexed,
)),
}
@@ -413,7 +416,7 @@ fn http2_parse_headers_block_literal_common<'a>(
i4,
HTTP2FrameHeaderBlock {
name,
- value,
+ value: Rc::new(value),
error,
sizeupdate: 0,
},
@@ -435,8 +438,8 @@ fn http2_parse_headers_block_literal_incindex<'a>(
match r {
Ok((r, head)) => {
let headcopy = HTTP2FrameHeaderBlock {
- name: head.name.to_vec(),
- value: head.value.to_vec(),
+ name: head.name.clone(),
+ value: head.value.clone(),
error: head.error,
sizeupdate: 0,
};
@@ -556,8 +559,8 @@ fn http2_parse_headers_block_dynamic_size<'a>(
return Ok((
i3,
HTTP2FrameHeaderBlock {
- name: Vec::new(),
- value: Vec::new(),
+ name: Rc::new(Vec::new()),
+ value: Rc::new(Vec::new()),
error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate,
sizeupdate: maxsize2,
},
@@ -614,8 +617,8 @@ fn http2_parse_headers_blocks<'a>(
// if we error from http2_parse_var_uint, we keep the first parsed headers
if err.code == ErrorKind::LengthValue {
blocks.push(HTTP2FrameHeaderBlock {
- name: Vec::new(),
- value: Vec::new(),
+ name: Rc::new(Vec::new()),
+ value: Rc::new(Vec::new()),
error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIntegerOverflow,
sizeupdate: 0,
});
@@ -765,8 +768,8 @@ mod tests {
match r0 {
Ok((remainder, hd)) => {
// Check the first message.
- assert_eq!(hd.name, ":method".as_bytes().to_vec());
- assert_eq!(hd.value, "GET".as_bytes().to_vec());
+ assert_eq!(hd.name, ":method".as_bytes().to_vec().into());
+ assert_eq!(hd.value, "GET".as_bytes().to_vec().into());
// And we should have no bytes left.
assert_eq!(remainder.len(), 0);
}
@@ -782,8 +785,8 @@ mod tests {
match r1 {
Ok((remainder, hd)) => {
// Check the first message.
- assert_eq!(hd.name, "accept".as_bytes().to_vec());
- assert_eq!(hd.value, "*/*".as_bytes().to_vec());
+ assert_eq!(hd.name, "accept".as_bytes().to_vec().into());
+ assert_eq!(hd.value, "*/*".as_bytes().to_vec().into());
// And we should have no bytes left.
assert_eq!(remainder.len(), 0);
assert_eq!(dynh.table.len(), 1);
@@ -802,8 +805,8 @@ mod tests {
match result {
Ok((remainder, hd)) => {
// Check the first message.
- assert_eq!(hd.name, ":authority".as_bytes().to_vec());
- assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec());
+ assert_eq!(hd.name, ":authority".as_bytes().to_vec().into());
+ assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec().into());
// And we should have no bytes left.
assert_eq!(remainder.len(), 0);
assert_eq!(dynh.table.len(), 2);
@@ -820,8 +823,8 @@ mod tests {
match r3 {
Ok((remainder, hd)) => {
// same as before
- assert_eq!(hd.name, ":authority".as_bytes().to_vec());
- assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec());
+ assert_eq!(hd.name, ":authority".as_bytes().to_vec().into());
+ assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec().into());
// And we should have no bytes left.
assert_eq!(remainder.len(), 0);
assert_eq!(dynh.table.len(), 2);
@@ -856,8 +859,8 @@ mod tests {
match r2 {
Ok((remainder, hd)) => {
// Check the first message.
- assert_eq!(hd.name, ":path".as_bytes().to_vec());
- assert_eq!(hd.value, "/doc/manual/html/index.html".as_bytes().to_vec());
+ assert_eq!(hd.name, ":path".as_bytes().to_vec().into());
+ assert_eq!(hd.value, "/doc/manual/html/index.html".as_bytes().to_vec().into());
// And we should have no bytes left.
assert_eq!(remainder.len(), 0);
assert_eq!(dynh.table.len(), 2);