diff --git a/quinn-h3/src/proto/connection.rs b/quinn-h3/src/proto/connection.rs index 73d6bc93b..5bbd9c040 100644 --- a/quinn-h3/src/proto/connection.rs +++ b/quinn-h3/src/proto/connection.rs @@ -48,8 +48,7 @@ impl Connection { let mut decoder_table = DynamicTable::new(); decoder_table.set_max_blocked(settings.qpack_blocked_streams as usize)?; decoder_table - .inserter() - .set_max_mem_size(settings.qpack_max_table_capacity as usize)?; + .set_max_size(settings.qpack_max_table_capacity as usize)?; let mut pending_control = BytesMut::with_capacity(128); settings.encode(&mut pending_control); @@ -252,8 +251,7 @@ mod tests { let mut conn = Connection::default(); conn.encoder_table - .inserter() - .set_max_mem_size(2048) + .set_max_size(2048) .expect("set table size"); conn.encoder_table .set_max_blocked(12usize) @@ -309,8 +307,7 @@ mod tests { let mut client = Connection::default(); client .encoder_table - .inserter() - .set_max_mem_size(2048) + .set_max_size(2048) .expect("set table size"); client .encoder_table diff --git a/quinn-h3/src/qpack/decoder.rs b/quinn-h3/src/qpack/decoder.rs index 76f62cd5f..2e6b79f5e 100644 --- a/quinn-h3/src/qpack/decoder.rs +++ b/quinn-h3/src/qpack/decoder.rs @@ -122,7 +122,7 @@ pub fn on_encoder_recv( match instruction { Instruction::Insert(field) => table.put_field(field)?, Instruction::TableSizeUpdate(size) => { - table.set_max_mem_size(size)?; + table.set_max_size(size)?; } } } diff --git a/quinn-h3/src/qpack/dynamic.rs b/quinn-h3/src/qpack/dynamic.rs index 2ec9d9ebe..df5b9c206 100644 --- a/quinn-h3/src/qpack/dynamic.rs +++ b/quinn-h3/src/qpack/dynamic.rs @@ -67,24 +67,8 @@ pub struct DynamicTableInserter<'a> { } impl<'a> DynamicTableInserter<'a> { - pub fn set_max_mem_size(&mut self, size: usize) -> Result<(), Error> { - if size > SETTINGS_MAX_TABLE_CAPACITY_MAX { - return Err(Error::MaximumTableSizeTooLarge); - } - - if size >= self.table.mem_limit { - self.table.mem_limit = size; - return Ok(()); - } - - let required = self.table.mem_limit - size; - - if let Some(to_evict) = self.table.can_free(required)? { - self.table.evict(to_evict)?; - } - - self.table.mem_limit = size; - Ok(()) + pub fn set_max_size(&mut self, size: usize) -> Result<(), Error> { + self.table.set_max_size(size) } pub(super) fn put_field(&mut self, field: HeaderField) -> Result<(), Error> { @@ -150,8 +134,8 @@ impl<'a> Drop for DynamicTableEncoder<'a> { } impl<'a> DynamicTableEncoder<'a> { - pub(super) fn max_mem_size(&self) -> usize { - self.table.mem_limit + pub(super) fn max_size(&self) -> usize { + self.table.max_size } pub(super) fn base(&self) -> usize { @@ -323,8 +307,8 @@ pub enum DynamicInsertionResult { #[derive(Default)] pub struct DynamicTable { fields: VecDeque, - curr_mem_size: usize, - mem_limit: usize, + curr_size: usize, + max_size: usize, vas: VirtualAddressSpace, field_map: Option>, name_map: Option, usize>>, @@ -384,6 +368,26 @@ impl DynamicTable { Ok(()) } + pub fn set_max_size(&mut self, size: usize) -> Result<(), Error> { + if size > SETTINGS_MAX_TABLE_CAPACITY_MAX { + return Err(Error::MaximumTableSizeTooLarge); + } + + if size >= self.max_size { + self.max_size = size; + return Ok(()); + } + + let required = self.max_size - size; + + if let Some(to_evict) = self.can_free(required)? { + self.evict(to_evict)?; + } + + self.max_size = size; + Ok(()) + } + pub(super) fn total_inserted(&self) -> usize { self.vas.total_inserted() } @@ -402,7 +406,7 @@ impl DynamicTable { } fn put_field(&mut self, field: HeaderField) -> Result, Error> { - if self.mem_limit == 0 { + if self.max_size == 0 { return Ok(None); } @@ -413,7 +417,7 @@ impl DynamicTable { } } - self.curr_mem_size += field.mem_size(); + self.curr_size += field.mem_size(); self.fields.push_back(field); let absolute = self.vas.add(); @@ -423,7 +427,7 @@ impl DynamicTable { fn evict(&mut self, to_evict: usize) -> Result<(), Error> { for _ in 0..to_evict { let field = self.fields.pop_front().ok_or(Error::MaxTableSizeReached)?; //TODO better type - self.curr_mem_size -= field.mem_size(); + self.curr_size -= field.mem_size(); self.vas.drop(); @@ -447,16 +451,16 @@ impl DynamicTable { } fn can_free(&mut self, required: usize) -> Result, Error> { - if required > self.mem_limit { + if required > self.max_size { return Err(Error::MaxTableSizeReached); } - if self.mem_limit - self.curr_mem_size >= required { + if self.max_size - self.curr_size >= required { return Ok(Some(0)); } - let lower_bound = self.mem_limit - required; + let lower_bound = self.max_size - required; - let mut hypothetic_mem_size = self.curr_mem_size; + let mut hypothetic_mem_size = self.curr_size; let mut evictable = 0; for (idx, to_evict) in self.fields.iter().enumerate() { @@ -473,7 +477,7 @@ impl DynamicTable { hypothetic_mem_size -= to_evict.mem_size(); } - if required <= self.mem_limit - hypothetic_mem_size { + if required <= self.max_size - hypothetic_mem_size { Ok(Some(evictable)) } else { Ok(None) @@ -585,7 +589,7 @@ impl DynamicTable { } pub(super) fn max_mem_size(&self) -> usize { - self.mem_limit + self.max_size } } @@ -626,7 +630,7 @@ mod tests { table.inserter().put_field(field).unwrap(); } - assert_eq!(table.curr_mem_size, table_size); + assert_eq!(table.curr_size, table_size); } /** @@ -640,7 +644,7 @@ mod tests { fn test_try_set_too_large_maximum_table_size() { let mut table = build_table(); let invalid_size = SETTINGS_MAX_TABLE_CAPACITY_MAX + 10; - let res_change = table.inserter().set_max_mem_size(invalid_size); + let res_change = table.set_max_size(invalid_size); assert_eq!(res_change, Err(Error::MaximumTableSizeTooLarge)); } @@ -653,7 +657,7 @@ mod tests { #[test] fn test_maximum_table_size_can_reach_zero() { let mut table = build_table(); - let res_change = table.inserter().set_max_mem_size(0); + let res_change = table.set_max_size(0); assert!(res_change.is_ok()); assert_eq!(table.max_mem_size(), 0); } @@ -668,9 +672,7 @@ mod tests { #[test] fn test_maximum_table_size_can_reach_maximum() { let mut table = build_table(); - let res_change = table - .inserter() - .set_max_mem_size(SETTINGS_MAX_TABLE_CAPACITY_MAX); + let res_change = table.set_max_size(SETTINGS_MAX_TABLE_CAPACITY_MAX); assert!(res_change.is_ok()); assert_eq!(table.max_mem_size(), SETTINGS_MAX_TABLE_CAPACITY_MAX); } @@ -717,8 +719,8 @@ mod tests { let mut table = build_table(); let field = HeaderField::new("Name", "Value"); - table.inserter().put_field(field.clone()).unwrap(); - assert_eq!(table.curr_mem_size, field.mem_size()); + table.put_field(field.clone()).unwrap(); + assert_eq!(table.curr_size, field.mem_size()); } /** @@ -740,8 +742,8 @@ mod tests { .inserter() .put_field(HeaderField::new("Name-B", "Value-B")) .unwrap(); - let perfect_size = table.curr_mem_size; - assert!(table.inserter().set_max_mem_size(perfect_size).is_ok()); + let perfect_size = table.curr_size; + assert!(table.set_max_size(perfect_size).is_ok()); let field = HeaderField::new("Name-Large", "Value-Large"); table.inserter().put_field(field).unwrap(); @@ -767,8 +769,8 @@ mod tests { .inserter() .put_field(HeaderField::new("Name-A", "Value-A")) .unwrap(); - let perfect_size = table.curr_mem_size; - assert!(table.inserter().set_max_mem_size(perfect_size).is_ok()); + let perfect_size = table.curr_size; + assert!(table.set_max_size(perfect_size).is_ok()); let field = HeaderField::new("Name-Large", "Value-Large"); assert_eq!( @@ -802,7 +804,7 @@ mod tests { ); assert_eq!(table.fields.len(), 2); - table.inserter().set_max_mem_size(0).unwrap(); + table.set_max_size(0).unwrap(); assert_eq!(table.fields.len(), 0); } @@ -818,8 +820,8 @@ mod tests { HeaderField::new("Name-B", "Value-B"), ], ); - let perfect_size = table.curr_mem_size; - assert!(table.inserter().set_max_mem_size(perfect_size).is_ok()); + let perfect_size = table.curr_size; + assert!(table.set_max_size(perfect_size).is_ok()); insert_fields(&mut table, vec![HeaderField::new("Name-C", "Value-C")]); @@ -1034,7 +1036,7 @@ mod tests { #[test] fn cannot_insert_field_greater_than_total_size() { let mut table = build_table(); - table.inserter().set_max_mem_size(33).unwrap(); + table.set_max_size(33).unwrap(); let mut encoder = table.encoder(4); assert_eq!( encoder.insert(&HeaderField::new("foo", "bar")), @@ -1047,7 +1049,7 @@ mod tests { #[test] fn encoder_maps_are_cleaned_on_eviction() { let mut table = build_table(); - table.inserter().set_max_mem_size(64).unwrap(); + table.set_max_size(64).unwrap(); { let mut encoder = table.encoder(4); @@ -1083,7 +1085,7 @@ mod tests { #[test] fn encoder_can_evict_unreferenced() { let mut table = build_table(); - table.inserter().set_max_mem_size(63).unwrap(); + table.set_max_size(63).unwrap(); table.put_field(HeaderField::new("foo", "bar")).unwrap(); assert_eq!(table.fields.len(), 1); @@ -1223,7 +1225,7 @@ mod tests { #[test] fn encoder_does_not_evict_referenced() { let mut table = build_table(); - table.inserter().set_max_mem_size(95).unwrap(); + table.set_max_size(95).unwrap(); table.put_field(HeaderField::new("foo", "bar")).unwrap(); let stream_id = 42; diff --git a/quinn-h3/src/qpack/encoder.rs b/quinn-h3/src/qpack/encoder.rs index 25563e4eb..107b9b5c8 100644 --- a/quinn-h3/src/qpack/encoder.rs +++ b/quinn-h3/src/qpack/encoder.rs @@ -60,7 +60,7 @@ where required_ref, table.base(), table.total_inserted(), - table.max_mem_size(), + table.max_size(), ) .encode(block); block.put(block_buf); @@ -190,7 +190,7 @@ pub fn set_dynamic_table_size( encoder: &mut W, size: usize, ) -> Result<(), Error> { - table.inserter().set_max_mem_size(size)?; + table.set_max_size(size)?; DynamicTableSizeUpdate(size).encode(encoder); Ok(()) } @@ -230,7 +230,7 @@ mod tests { check: &dyn Fn(&mut Cursor<&mut Vec>, &mut Cursor<&mut Vec>), ) { let mut table = build_table(); - table.inserter().set_max_mem_size(TABLE_SIZE).unwrap(); + table.set_max_size(TABLE_SIZE).unwrap(); check_encode_field_table(&mut table, init_fields, field, 1, check); } @@ -330,7 +330,7 @@ mod tests { #[test] fn encode_literal() { let mut table = build_table(); - table.inserter().set_max_mem_size(0).unwrap(); + table.set_max_size(0).unwrap(); let field = HeaderField::new("foo", "bar"); check_encode_field_table(&mut table, &[], &[field], 1, &|mut b, e| { assert_eq!(Literal::decode(&mut b), Ok(Literal::new("foo", "bar"))); @@ -341,7 +341,7 @@ mod tests { #[test] fn encode_literal_nameref() { let mut table = build_table(); - table.inserter().set_max_mem_size(63).unwrap(); + table.set_max_size(63).unwrap(); let field = HeaderField::new("foo", "bar"); check_encode_field_table(&mut table, &[], &[field.clone()], 1, &|mut b, _| { @@ -368,7 +368,7 @@ mod tests { #[test] fn encode_literal_postbase_nameref() { let mut table = build_table(); - table.inserter().set_max_mem_size(63).unwrap(); + table.set_max_size(63).unwrap(); let field = HeaderField::new("foo", "bar"); check_encode_field_table( &mut table, diff --git a/quinn-h3/src/qpack/tests.rs b/quinn-h3/src/qpack/tests.rs index 2beab526c..c8765986e 100644 --- a/quinn-h3/src/qpack/tests.rs +++ b/quinn-h3/src/qpack/tests.rs @@ -11,14 +11,14 @@ pub mod helpers { pub fn build_table() -> DynamicTable { let mut table = DynamicTable::new(); - table.inserter().set_max_mem_size(TABLE_SIZE).unwrap(); + table.set_max_size(TABLE_SIZE).unwrap(); table.set_max_blocked(100).unwrap(); table } pub fn build_table_with_size(n_field: usize) -> DynamicTable { let mut table = DynamicTable::new(); - table.inserter().set_max_mem_size(TABLE_SIZE).unwrap(); + table.set_max_size(TABLE_SIZE).unwrap(); table.set_max_blocked(100).unwrap(); let mut inserter = table.inserter(); @@ -69,10 +69,10 @@ const TABLE_SIZE: usize = 4096; #[test] fn blocked_header() { let mut enc_table = DynamicTable::new(); - enc_table.inserter().set_max_mem_size(TABLE_SIZE).unwrap(); + enc_table.set_max_size(TABLE_SIZE).unwrap(); enc_table.set_max_blocked(100).unwrap(); let mut dec_table = DynamicTable::new(); - dec_table.inserter().set_max_mem_size(TABLE_SIZE).unwrap(); + dec_table.set_max_size(TABLE_SIZE).unwrap(); dec_table.set_max_blocked(100).unwrap(); let mut block_buf = vec![]; @@ -108,8 +108,8 @@ fn codec_table_size_0() { HeaderField::new("foo", "bar"), ]; - dec_table.inserter().set_max_mem_size(0).unwrap(); - enc_table.inserter().set_max_mem_size(0).unwrap(); + dec_table.set_max_size(0).unwrap(); + enc_table.set_max_size(0).unwrap(); encode( &mut enc_table.encoder(42), @@ -143,8 +143,8 @@ fn codec_table_full() { HeaderField::new("foo1", "bar1"), ]; - dec_table.inserter().set_max_mem_size(42).unwrap(); - enc_table.inserter().set_max_mem_size(42).unwrap(); + dec_table.set_max_size(42).unwrap(); + enc_table.set_max_size(42).unwrap(); encode( &mut enc_table.encoder(42),