diff options
Diffstat (limited to 'src/h3/frame.rs')
-rw-r--r-- | src/h3/frame.rs | 152 |
1 files changed, 135 insertions, 17 deletions
diff --git a/src/h3/frame.rs b/src/h3/frame.rs index 46b802d..76160fe 100644 --- a/src/h3/frame.rs +++ b/src/h3/frame.rs @@ -42,12 +42,13 @@ pub const PRIORITY_UPDATE_FRAME_PUSH_TYPE_ID: u64 = 0xF0701; pub const SETTINGS_QPACK_MAX_TABLE_CAPACITY: u64 = 0x1; pub const SETTINGS_MAX_FIELD_SECTION_SIZE: u64 = 0x6; pub const SETTINGS_QPACK_BLOCKED_STREAMS: u64 = 0x7; +pub const SETTINGS_ENABLE_CONNECT_PROTOCOL: u64 = 0x8; pub const SETTINGS_H3_DATAGRAM: u64 = 0x276; // Permit between 16 maximally-encoded and 128 minimally-encoded SETTINGS. const MAX_SETTINGS_PAYLOAD_SIZE: usize = 256; -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Eq)] pub enum Frame { Data { payload: Vec<u8>, @@ -65,6 +66,7 @@ pub enum Frame { max_field_section_size: Option<u64>, qpack_max_table_capacity: Option<u64>, qpack_blocked_streams: Option<u64>, + connect_protocol_enabled: Option<u64>, h3_datagram: Option<u64>, grease: Option<(u64, u64)>, raw: Option<Vec<(u64, u64)>>, @@ -175,6 +177,7 @@ impl Frame { max_field_section_size, qpack_max_table_capacity, qpack_blocked_streams, + connect_protocol_enabled, h3_datagram, grease, .. @@ -196,6 +199,11 @@ impl Frame { len += octets::varint_len(*val); } + if let Some(val) = connect_protocol_enabled { + len += octets::varint_len(SETTINGS_ENABLE_CONNECT_PROTOCOL); + len += octets::varint_len(*val); + } + if let Some(val) = h3_datagram { len += octets::varint_len(SETTINGS_H3_DATAGRAM); len += octets::varint_len(*val); @@ -211,22 +219,27 @@ impl Frame { if let Some(val) = max_field_section_size { b.put_varint(SETTINGS_MAX_FIELD_SECTION_SIZE)?; - b.put_varint(*val as u64)?; + b.put_varint(*val)?; } if let Some(val) = qpack_max_table_capacity { b.put_varint(SETTINGS_QPACK_MAX_TABLE_CAPACITY)?; - b.put_varint(*val as u64)?; + b.put_varint(*val)?; } if let Some(val) = qpack_blocked_streams { b.put_varint(SETTINGS_QPACK_BLOCKED_STREAMS)?; - b.put_varint(*val as u64)?; + b.put_varint(*val)?; + } + + if let Some(val) = connect_protocol_enabled { + b.put_varint(SETTINGS_ENABLE_CONNECT_PROTOCOL)?; + b.put_varint(*val)?; } if let Some(val) = h3_datagram { b.put_varint(SETTINGS_H3_DATAGRAM)?; - b.put_varint(*val as u64)?; + b.put_varint(*val)?; } if let Some(val) = grease { @@ -271,7 +284,7 @@ impl Frame { b.put_varint(PRIORITY_UPDATE_FRAME_REQUEST_TYPE_ID)?; b.put_varint(len as u64)?; - b.put_varint(*prioritized_element_id as u64)?; + b.put_varint(*prioritized_element_id)?; b.put_bytes(priority_field_value)?; }, @@ -285,7 +298,7 @@ impl Frame { b.put_varint(PRIORITY_UPDATE_FRAME_PUSH_TYPE_ID)?; b.put_varint(len as u64)?; - b.put_varint(*prioritized_element_id as u64)?; + b.put_varint(*prioritized_element_id)?; b.put_bytes(priority_field_value)?; }, @@ -297,6 +310,8 @@ impl Frame { #[cfg(feature = "qlog")] pub fn to_qlog(&self) -> Http3Frame { + use qlog::events::RawInfo; + match self { Frame::Data { .. } => Http3Frame::Data { raw: None }, @@ -312,6 +327,7 @@ impl Frame { max_field_section_size, qpack_max_table_capacity, qpack_blocked_streams, + connect_protocol_enabled, h3_datagram, grease, .. @@ -339,6 +355,13 @@ impl Frame { }); } + if let Some(v) = connect_protocol_enabled { + settings.push(qlog::events::h3::Setting { + name: "SETTINGS_ENABLE_CONNECT_PROTOCOL".to_string(), + value: *v, + }); + } + if let Some(v) = h3_datagram { settings.push(qlog::events::h3::Setting { name: "H3_DATAGRAM".to_string(), @@ -399,9 +422,12 @@ impl Frame { raw_type, payload_length, } => Http3Frame::Unknown { - raw_frame_type: *raw_type, - raw_length: Some(*payload_length as u32), - raw: None, + frame_type_value: *raw_type, + raw: Some(RawInfo { + data: None, + payload_length: Some(*payload_length), + length: None, + }), }, } } @@ -419,7 +445,7 @@ impl std::fmt::Debug for Frame { }, Frame::CancelPush { push_id } => { - write!(f, "CANCEL_PUSH push_id={}", push_id)?; + write!(f, "CANCEL_PUSH push_id={push_id}")?; }, Frame::Settings { @@ -429,7 +455,7 @@ impl std::fmt::Debug for Frame { raw, .. } => { - write!(f, "SETTINGS max_field_section={:?}, qpack_max_table={:?}, qpack_blocked={:?} raw={:?}", max_field_section_size, qpack_max_table_capacity, qpack_blocked_streams, raw)?; + write!(f, "SETTINGS max_field_section={max_field_section_size:?}, qpack_max_table={qpack_max_table_capacity:?}, qpack_blocked={qpack_blocked_streams:?} raw={raw:?}")?; }, Frame::PushPromise { @@ -445,11 +471,11 @@ impl std::fmt::Debug for Frame { }, Frame::GoAway { id } => { - write!(f, "GOAWAY id={}", id)?; + write!(f, "GOAWAY id={id}")?; }, Frame::MaxPushId { push_id } => { - write!(f, "MAX_PUSH_ID push_id={}", push_id)?; + write!(f, "MAX_PUSH_ID push_id={push_id}")?; }, Frame::PriorityUpdateRequest { @@ -477,7 +503,7 @@ impl std::fmt::Debug for Frame { }, Frame::Unknown { raw_type, .. } => { - write!(f, "UNKNOWN raw_type={}", raw_type,)?; + write!(f, "UNKNOWN raw_type={raw_type}",)?; }, } @@ -491,6 +517,7 @@ fn parse_settings_frame( let mut max_field_section_size = None; let mut qpack_max_table_capacity = None; let mut qpack_blocked_streams = None; + let mut connect_protocol_enabled = None; let mut h3_datagram = None; let mut raw = Vec::new(); @@ -520,6 +547,14 @@ fn parse_settings_frame( qpack_blocked_streams = Some(value); }, + SETTINGS_ENABLE_CONNECT_PROTOCOL => { + if value > 1 { + return Err(super::Error::SettingsError); + } + + connect_protocol_enabled = Some(value); + }, + SETTINGS_H3_DATAGRAM => { if value > 1 { return Err(super::Error::SettingsError); @@ -541,6 +576,7 @@ fn parse_settings_frame( max_field_section_size, qpack_max_table_capacity, qpack_blocked_streams, + connect_protocol_enabled, h3_datagram, grease: None, raw: Some(raw), @@ -680,6 +716,7 @@ mod tests { (SETTINGS_MAX_FIELD_SECTION_SIZE, 0), (SETTINGS_QPACK_MAX_TABLE_CAPACITY, 0), (SETTINGS_QPACK_BLOCKED_STREAMS, 0), + (SETTINGS_ENABLE_CONNECT_PROTOCOL, 0), (SETTINGS_H3_DATAGRAM, 0), ]; @@ -687,12 +724,13 @@ mod tests { max_field_section_size: Some(0), qpack_max_table_capacity: Some(0), qpack_blocked_streams: Some(0), + connect_protocol_enabled: Some(0), h3_datagram: Some(0), grease: None, raw: Some(raw_settings), }; - let frame_payload_len = 9; + let frame_payload_len = 11; let frame_header_len = 2; let wire_len = { @@ -721,6 +759,7 @@ mod tests { max_field_section_size: Some(0), qpack_max_table_capacity: Some(0), qpack_blocked_streams: Some(0), + connect_protocol_enabled: Some(0), h3_datagram: Some(0), grease: Some((33, 33)), raw: Default::default(), @@ -730,6 +769,7 @@ mod tests { (SETTINGS_MAX_FIELD_SECTION_SIZE, 0), (SETTINGS_QPACK_MAX_TABLE_CAPACITY, 0), (SETTINGS_QPACK_BLOCKED_STREAMS, 0), + (SETTINGS_ENABLE_CONNECT_PROTOCOL, 0), (SETTINGS_H3_DATAGRAM, 0), (33, 33), ]; @@ -740,12 +780,13 @@ mod tests { max_field_section_size: Some(0), qpack_max_table_capacity: Some(0), qpack_blocked_streams: Some(0), + connect_protocol_enabled: Some(0), h3_datagram: Some(0), grease: None, raw: Some(raw_settings), }; - let frame_payload_len = 11; + let frame_payload_len = 13; let frame_header_len = 2; let wire_len = { @@ -776,6 +817,7 @@ mod tests { max_field_section_size: Some(1024), qpack_max_table_capacity: None, qpack_blocked_streams: None, + connect_protocol_enabled: None, h3_datagram: None, grease: None, raw: Some(raw_settings), @@ -803,6 +845,79 @@ mod tests { } #[test] + fn settings_h3_connect_protocol_enabled() { + let mut d = [42; 128]; + + let raw_settings = vec![(SETTINGS_ENABLE_CONNECT_PROTOCOL, 1)]; + + let frame = Frame::Settings { + max_field_section_size: None, + qpack_max_table_capacity: None, + qpack_blocked_streams: None, + connect_protocol_enabled: Some(1), + h3_datagram: None, + grease: None, + raw: Some(raw_settings), + }; + + let frame_payload_len = 2; + let frame_header_len = 2; + + let wire_len = { + let mut b = octets::OctetsMut::with_slice(&mut d); + frame.to_bytes(&mut b).unwrap() + }; + + assert_eq!(wire_len, frame_header_len + frame_payload_len); + + assert_eq!( + Frame::from_bytes( + SETTINGS_FRAME_TYPE_ID, + frame_payload_len as u64, + &d[frame_header_len..] + ) + .unwrap(), + frame + ); + } + + #[test] + fn settings_h3_connect_protocol_enabled_bad() { + let mut d = [42; 128]; + + let raw_settings = vec![(SETTINGS_ENABLE_CONNECT_PROTOCOL, 9)]; + + let frame = Frame::Settings { + max_field_section_size: None, + qpack_max_table_capacity: None, + qpack_blocked_streams: None, + connect_protocol_enabled: Some(9), + h3_datagram: None, + grease: None, + raw: Some(raw_settings), + }; + + let frame_payload_len = 2; + let frame_header_len = 2; + + let wire_len = { + let mut b = octets::OctetsMut::with_slice(&mut d); + frame.to_bytes(&mut b).unwrap() + }; + + assert_eq!(wire_len, frame_header_len + frame_payload_len); + + assert_eq!( + Frame::from_bytes( + SETTINGS_FRAME_TYPE_ID, + frame_payload_len as u64, + &d[frame_header_len..] + ), + Err(crate::h3::Error::SettingsError) + ); + } + + #[test] fn settings_h3_dgram_only() { let mut d = [42; 128]; @@ -812,6 +927,7 @@ mod tests { max_field_section_size: None, qpack_max_table_capacity: None, qpack_blocked_streams: None, + connect_protocol_enabled: None, h3_datagram: Some(1), grease: None, raw: Some(raw_settings), @@ -846,6 +962,7 @@ mod tests { max_field_section_size: None, qpack_max_table_capacity: None, qpack_blocked_streams: None, + connect_protocol_enabled: None, h3_datagram: Some(5), grease: None, raw: Default::default(), @@ -884,6 +1001,7 @@ mod tests { max_field_section_size: None, qpack_max_table_capacity: Some(0), qpack_blocked_streams: Some(0), + connect_protocol_enabled: None, h3_datagram: None, grease: None, raw: Some(raw_settings), |