aboutsummaryrefslogtreecommitdiff
path: root/src/h3/frame.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/h3/frame.rs')
-rw-r--r--src/h3/frame.rs152
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),