From bdf1ffc6ee7cff7269dc4e563ae37874feddef55 Mon Sep 17 00:00:00 2001 From: stammw Date: Mon, 21 Jan 2019 07:31:53 +0100 Subject: [PATCH] QPACK: decoder instructions --- quinn-h3/src/qpack/decoder.rs | 30 ++++----- quinn-h3/src/qpack/encoder.rs | 4 +- quinn-h3/src/qpack/stream.rs | 111 ++++++++++++++++++++++++++++++---- 3 files changed, 115 insertions(+), 30 deletions(-) diff --git a/quinn-h3/src/qpack/decoder.rs b/quinn-h3/src/qpack/decoder.rs index c02cc2678..8124c4938 100644 --- a/quinn-h3/src/qpack/decoder.rs +++ b/quinn-h3/src/qpack/decoder.rs @@ -17,8 +17,8 @@ use super::bloc::{ LiteralWithPostBaseNameRef, }; use super::stream::{ - Duplicate, DynamicTableSizeUpdate, InsertWithNameRef, InsertWithoutNameRef, InstructionType, - TableSizeSync, + Duplicate, DynamicTableSizeUpdate, EncoderInstruction, InsertCountIncrement, InsertWithNameRef, + InsertWithoutNameRef, }; use super::ParseError; @@ -119,7 +119,7 @@ pub fn on_encoder_recv( if table.total_inserted() != inserted_on_start { //TODO RENAME - TableSizeSync { + InsertCountIncrement { insert_count: table.total_inserted() - inserted_on_start, } .encode(write); @@ -138,18 +138,18 @@ fn parse_instruction( let mut buf = Cursor::new(read.bytes()); let first = buf.bytes()[0]; - let instruction = match InstructionType::decode(first) { - InstructionType::Unknown => return Err(Error::UnknownPrefix), - InstructionType::DynamicTableSizeUpdate => { + let instruction = match EncoderInstruction::decode(first) { + EncoderInstruction::Unknown => return Err(Error::UnknownPrefix), + EncoderInstruction::DynamicTableSizeUpdate => { DynamicTableSizeUpdate::decode(&mut buf)?.map(|x| Instruction::TableSizeUpdate(x.size)) } - InstructionType::InsertWithoutNameRef => InsertWithoutNameRef::decode(&mut buf)? + EncoderInstruction::InsertWithoutNameRef => InsertWithoutNameRef::decode(&mut buf)? .map(|x| Instruction::Insert(HeaderField::new(x.name, x.value))), - InstructionType::Duplicate => match Duplicate::decode(&mut buf)? { + EncoderInstruction::Duplicate => match Duplicate::decode(&mut buf)? { Some(Duplicate(index)) => Some(Instruction::Insert(table.get_relative(index)?.clone())), None => None, }, - InstructionType::InsertWithNameRef => match InsertWithNameRef::decode(&mut buf)? { + EncoderInstruction::InsertWithNameRef => match InsertWithNameRef::decode(&mut buf)? { Some(InsertWithNameRef::Static { index, value }) => Some(Instruction::Insert( StaticTable::get(index)?.with_value(value), )), @@ -249,8 +249,8 @@ mod tests { let mut dec_cursor = Cursor::new(&dec); assert_eq!( - TableSizeSync::decode(&mut dec_cursor), - Ok(Some(TableSizeSync { insert_count: 1 })) + InsertCountIncrement::decode(&mut dec_cursor), + Ok(Some(InsertCountIncrement { insert_count: 1 })) ); } @@ -317,8 +317,8 @@ mod tests { let mut dec_cursor = Cursor::new(&dec); assert_eq!( - TableSizeSync::decode(&mut dec_cursor), - Ok(Some(TableSizeSync { insert_count: 1 })) + InsertCountIncrement::decode(&mut dec_cursor), + Ok(Some(InsertCountIncrement { insert_count: 1 })) ); } @@ -351,8 +351,8 @@ mod tests { let mut dec_cursor = Cursor::new(&dec); assert_eq!( - TableSizeSync::decode(&mut dec_cursor), - Ok(Some(TableSizeSync { insert_count: 1 })) + InsertCountIncrement::decode(&mut dec_cursor), + Ok(Some(InsertCountIncrement { insert_count: 1 })) ); } diff --git a/quinn-h3/src/qpack/encoder.rs b/quinn-h3/src/qpack/encoder.rs index 02a8a3e01..7bcdf01a8 100644 --- a/quinn-h3/src/qpack/encoder.rs +++ b/quinn-h3/src/qpack/encoder.rs @@ -16,8 +16,8 @@ use super::bloc::{ }; use super::prefix_string::Error as StringError; use super::stream::{ - Duplicate, DynamicTableSizeUpdate, InsertWithNameRef, InsertWithoutNameRef, InstructionType, - TableSizeSync, + Duplicate, DynamicTableSizeUpdate, EncoderInstruction, InsertCountIncrement, InsertWithNameRef, + InsertWithoutNameRef, }; use super::table::{ DynamicInsertionResult, DynamicLookupResult, DynamicTable, DynamicTableEncoder, diff --git a/quinn-h3/src/qpack/stream.rs b/quinn-h3/src/qpack/stream.rs index ec334a811..81cef6aad 100644 --- a/quinn-h3/src/qpack/stream.rs +++ b/quinn-h3/src/qpack/stream.rs @@ -7,7 +7,7 @@ use super::prefix_string::{self, Error as StringError}; use super::table::field::HeaderField; use super::ParseError; -pub enum InstructionType { +pub enum EncoderInstruction { InsertWithNameRef, InsertWithoutNameRef, Duplicate, @@ -15,18 +15,18 @@ pub enum InstructionType { Unknown, } -impl InstructionType { +impl EncoderInstruction { pub fn decode(first: u8) -> Self { if first & 0b1000_0000 != 0 { - InstructionType::InsertWithNameRef + EncoderInstruction::InsertWithNameRef } else if first & 0b0100_0000 == 0b0100_0000 { - InstructionType::InsertWithoutNameRef + EncoderInstruction::InsertWithoutNameRef } else if first & 0b1110_0000 == 0 { - InstructionType::Duplicate + EncoderInstruction::Duplicate } else if first & 0b0010_0000 == 0b0010_0000 { - InstructionType::DynamicTableSizeUpdate + EncoderInstruction::DynamicTableSizeUpdate } else { - InstructionType::Unknown + EncoderInstruction::Unknown } } } @@ -164,11 +164,33 @@ impl DynamicTableSizeUpdate { } #[derive(Debug, PartialEq)] -pub struct TableSizeSync { +pub enum DecoderInstruciton { + InsertCountIncrement, + HeaderAck, + StreamCancel, + Unknown, +} + +impl DecoderInstruciton { + pub fn decode(first: u8) -> Self { + if first & 0b1100_0000 == 0 { + DecoderInstruciton::InsertCountIncrement + } else if first & 0b1000_0000 != 0 { + DecoderInstruciton::HeaderAck + } else if first & 0b0100_0000 == 0b0100_0000 { + DecoderInstruciton::StreamCancel + } else { + DecoderInstruciton::Unknown + } + } +} + +#[derive(Debug, PartialEq)] +pub struct InsertCountIncrement { pub insert_count: usize, } -impl TableSizeSync { +impl InsertCountIncrement { pub fn decode(buf: &mut R) -> Result, ParseError> { let insert_count = match prefix_int::decode(6, buf) { Ok((0b00, x)) => x, @@ -176,7 +198,7 @@ impl TableSizeSync { Err(IntError::UnexpectedEnd) => return Ok(None), Err(e) => return Err(e.into()), }; - Ok(Some(TableSizeSync { insert_count })) + Ok(Some(InsertCountIncrement { insert_count })) } pub fn encode(&self, buf: &mut W) { @@ -184,6 +206,48 @@ impl TableSizeSync { } } +#[derive(Debug, PartialEq)] +pub struct HeaderAck { + pub stream_id: u64, +} + +impl HeaderAck { + pub fn decode(buf: &mut R) -> Result, ParseError> { + let stream_id = match prefix_int::decode(7, buf) { + Ok((0b1, x)) => x as u64, + Ok((f, _)) => return Err(ParseError::InvalidPrefix(f)), + Err(IntError::UnexpectedEnd) => return Ok(None), + Err(e) => return Err(e.into()), + }; + Ok(Some(HeaderAck { stream_id })) + } + + pub fn encode(&self, buf: &mut W) { + prefix_int::encode(7, 0b1, self.stream_id as usize, buf); + } +} + +#[derive(Debug, PartialEq)] +pub struct StreamCancel { + pub stream_id: u64, +} + +impl StreamCancel { + pub fn decode(buf: &mut R) -> Result, ParseError> { + let stream_id = match prefix_int::decode(6, buf) { + Ok((0b01, x)) => x as u64, + Ok((f, _)) => return Err(ParseError::InvalidPrefix(f)), + Err(IntError::UnexpectedEnd) => return Ok(None), + Err(e) => return Err(e.into()), + }; + Ok(Some(StreamCancel { stream_id })) + } + + pub fn encode(&self, buf: &mut W) { + prefix_int::encode(6, 0b01, self.stream_id as usize, buf); + } +} + #[cfg(test)] mod test { use super::*; @@ -231,11 +295,32 @@ mod test { } #[test] - fn table_size_sync() { - let instruction = TableSizeSync { insert_count: 42 }; + fn insert_count_increment() { + let instruction = InsertCountIncrement { insert_count: 42 }; let mut buf = vec![]; instruction.encode(&mut buf); let mut read = Cursor::new(&buf); - assert_eq!(TableSizeSync::decode(&mut read), Ok(Some(instruction))); + assert_eq!( + InsertCountIncrement::decode(&mut read), + Ok(Some(instruction)) + ); + } + + #[test] + fn header_ack() { + let instruction = HeaderAck { stream_id: 42 }; + let mut buf = vec![]; + instruction.encode(&mut buf); + let mut read = Cursor::new(&buf); + assert_eq!(HeaderAck::decode(&mut read), Ok(Some(instruction))); + } + + #[test] + fn stream_cancel() { + let instruction = StreamCancel { stream_id: 42 }; + let mut buf = vec![]; + instruction.encode(&mut buf); + let mut read = Cursor::new(&buf); + assert_eq!(StreamCancel::decode(&mut read), Ok(Some(instruction))); } }