Skip to content

Commit

Permalink
H2 header fixes:
Browse files Browse the repository at this point in the history
- Separate hpack encoder and decoder for each ConnectionH2
- Filter out forbidden H2 headers in converter
- Remove kawa namespace prefix in pkawa

Signed-off-by: Eloi DEMOLIS <[email protected]>
  • Loading branch information
Wonshtrum committed Aug 28, 2023
1 parent 1cbca34 commit 8afa1ab
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 47 deletions.
35 changes: 20 additions & 15 deletions lib/src/protocol/mux/converter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use std::str::from_utf8_unchecked;

use kawa::{AsBuffer, Block, BlockConverter, Chunk, Flags, Kawa, Pair, StatusLine, Store};

use crate::protocol::http::parser::compare_no_case;

use super::{
parser::{FrameHeader, FrameType},
serializer::gen_frame_header,
Expand All @@ -14,7 +18,7 @@ pub struct H2BlockConverter<'a> {

impl<'a, T: AsBuffer> BlockConverter<T> for H2BlockConverter<'a> {
fn call(&mut self, block: Block, kawa: &mut Kawa<T>) {
let buffer = kawa.storage.mut_buffer();
let buffer = kawa.storage.buffer();
match block {
Block::StatusLine => match kawa.detached.status_line.pop() {
StatusLine::Request {
Expand Down Expand Up @@ -66,20 +70,21 @@ impl<'a, T: AsBuffer> BlockConverter<T> for H2BlockConverter<'a> {
}
Block::Header(Pair { key, val }) => {
{
// let key = key.data(kawa.storage.buffer());
// let val = val.data(kawa.storage.buffer());
// if compare_no_case(key, b"connection")
// || compare_no_case(key, b"host")
// || compare_no_case(key, b"http2-settings")
// || compare_no_case(key, b"keep-alive")
// || compare_no_case(key, b"proxy-connection")
// || compare_no_case(key, b"te") && !compare_no_case(val, b"trailers")
// || compare_no_case(key, b"trailer")
// || compare_no_case(key, b"transfer-encoding")
// || compare_no_case(key, b"upgrade")
// {
// return;
// }
let key = key.data(buffer);
let val = val.data(buffer);
if compare_no_case(key, b"connection")
|| compare_no_case(key, b"host")
|| compare_no_case(key, b"http2-settings")
|| compare_no_case(key, b"keep-alive")
|| compare_no_case(key, b"proxy-connection")
|| compare_no_case(key, b"te") && !compare_no_case(val, b"trailers")
|| compare_no_case(key, b"trailer")
|| compare_no_case(key, b"transfer-encoding")
|| compare_no_case(key, b"upgrade")
{
println!("Elided H2 header: {}", unsafe { from_utf8_unchecked(key) });
return;
}
}
self.encoder
.encode_header_into(
Expand Down
3 changes: 2 additions & 1 deletion lib/src/protocol/mux/h2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ impl Default for H2Settings {

pub struct ConnectionH2<Front: SocketHandler> {
pub decoder: hpack::Decoder<'static>,
pub encoder: hpack::Encoder<'static>,
pub expect: Option<(H2StreamId, usize)>,
pub position: Position,
pub readiness: Readiness,
Expand Down Expand Up @@ -263,7 +264,7 @@ impl<Front: SocketHandler> ConnectionH2<Front> {
(_, _) => {
let mut converter = converter::H2BlockConverter {
stream_id: 0,
encoder: unsafe { std::mem::transmute(&mut self.decoder) },
encoder: &mut self.encoder,
out: Vec::new(),
};
let mut want_write = false;
Expand Down
4 changes: 3 additions & 1 deletion lib/src/protocol/mux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl<Front: SocketHandler> Connection<Front> {
zero: kawa::Kawa::new(kawa::Kind::Request, kawa::Buffer::new(buffer)),
window: 1 << 16,
decoder: hpack::Decoder::new(),
encoder: hpack::Encoder::new(),
}))
}
pub fn new_h2_client(
Expand All @@ -130,6 +131,7 @@ impl<Front: SocketHandler> Connection<Front> {
zero: kawa::Kawa::new(kawa::Kind::Request, kawa::Buffer::new(buffer)),
window: 1 << 16,
decoder: hpack::Decoder::new(),
encoder: hpack::Encoder::new(),
}))
}

Expand Down Expand Up @@ -590,7 +592,7 @@ impl SessionState for Mux {
|| backend.readiness().filter_interest().is_error()
{
println!("{:?} {:?}", backend.readiness(), backend.socket());
return SessionResult::Close;
// return SessionResult::Close;
}
}

Expand Down
63 changes: 33 additions & 30 deletions lib/src/protocol/mux/pkawa.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::{io::Write, str::from_utf8_unchecked};

use kawa::h1::ParserCallbacks;
use kawa::{
h1::ParserCallbacks, repr::Slice, Block, BodySize, Flags, Kind, Pair, ParsingPhase, StatusLine,
Store, Version,
};

use crate::{pool::Checkout, protocol::http::parser::compare_no_case};

Expand All @@ -15,20 +18,20 @@ pub fn handle_header<C>(
) where
C: ParserCallbacks<Checkout>,
{
kawa.push_block(kawa::Block::StatusLine);
kawa.push_block(Block::StatusLine);
kawa.detached.status_line = match kawa.kind {
kawa::Kind::Request => {
let mut method = kawa::Store::Empty;
let mut authority = kawa::Store::Empty;
let mut path = kawa::Store::Empty;
let mut scheme = kawa::Store::Empty;
Kind::Request => {
let mut method = Store::Empty;
let mut authority = Store::Empty;
let mut path = Store::Empty;
let mut scheme = Store::Empty;
decoder
.decode_with_cb(input, |k, v| {
let start = kawa.storage.end as u32;
kawa.storage.write_all(&v).unwrap();
let len_key = k.len() as u32;
let len_val = v.len() as u32;
let val = kawa::Store::Slice(kawa::repr::Slice {
let val = Store::Slice(Slice {
start,
len: len_val,
});
Expand All @@ -45,14 +48,14 @@ pub fn handle_header<C>(
if compare_no_case(&k, b"content-length") {
let length =
unsafe { from_utf8_unchecked(&v).parse::<usize>().unwrap() };
kawa.body_size = kawa::BodySize::Length(length);
kawa.body_size = BodySize::Length(length);
}
kawa.storage.write_all(&k).unwrap();
let key = kawa::Store::Slice(kawa::repr::Slice {
let key = Store::Slice(Slice {
start: start + len_val,
len: len_key,
});
kawa.push_block(kawa::Block::Header(kawa::Pair { key, val }));
kawa.push_block(Block::Header(Pair { key, val }));
}
})
.unwrap();
Expand All @@ -68,24 +71,24 @@ pub fn handle_header<C>(
// )
// };
// println!("Reconstructed URI: {uri}");
kawa::StatusLine::Request {
version: kawa::Version::V20,
StatusLine::Request {
version: Version::V20,
method,
uri: path.clone(), //kawa::Store::from_string(uri),
uri: path.clone(), //Store::from_string(uri),
authority,
path,
}
}
kawa::Kind::Response => {
Kind::Response => {
let mut code = 0;
let mut status = kawa::Store::Empty;
let mut status = Store::Empty;
decoder
.decode_with_cb(input, |k, v| {
let start = kawa.storage.end as u32;
kawa.storage.write_all(&v).unwrap();
let len_key = k.len() as u32;
let len_val = v.len() as u32;
let val = kawa::Store::Slice(kawa::repr::Slice {
let val = Store::Slice(Slice {
start,
len: len_val,
});
Expand All @@ -100,19 +103,19 @@ pub fn handle_header<C>(
}
} else {
kawa.storage.write_all(&k).unwrap();
let key = kawa::Store::Slice(kawa::repr::Slice {
let key = Store::Slice(Slice {
start: start + len_val,
len: len_key,
});
kawa.push_block(kawa::Block::Header(kawa::Pair { key, val }));
kawa.push_block(Block::Header(Pair { key, val }));
}
})
.unwrap();
kawa::StatusLine::Response {
version: kawa::Version::V20,
StatusLine::Response {
version: Version::V20,
code,
status,
reason: kawa::Store::Empty,
reason: Store::Empty,
}
}
};
Expand All @@ -122,29 +125,29 @@ pub fn handle_header<C>(

callbacks.on_headers(kawa);

kawa.push_block(kawa::Block::Flags(kawa::Flags {
kawa.push_block(Block::Flags(Flags {
end_body: false,
end_chunk: false,
end_header: true,
end_stream: false,
}));

if end_stream {
kawa.push_block(kawa::Block::Flags(kawa::Flags {
kawa.push_block(Block::Flags(Flags {
end_body: true,
end_chunk: false,
end_header: false,
end_stream: true,
}));
kawa.body_size = kawa::BodySize::Length(0);
kawa.body_size = BodySize::Length(0);
}
kawa.parsing_phase = match kawa.body_size {
kawa::BodySize::Chunked => kawa::ParsingPhase::Chunks { first: true },
kawa::BodySize::Length(0) => kawa::ParsingPhase::Terminated,
kawa::BodySize::Length(_) => kawa::ParsingPhase::Body,
kawa::BodySize::Empty => {
BodySize::Chunked => ParsingPhase::Chunks { first: true },
BodySize::Length(0) => ParsingPhase::Terminated,
BodySize::Length(_) => ParsingPhase::Body,
BodySize::Empty => {
println!("HTTP is just the worst...");
kawa::ParsingPhase::Body
ParsingPhase::Body
}
};
}

0 comments on commit 8afa1ab

Please sign in to comment.