Skip to content

Commit

Permalink
h3i: Improve ConnectionSummary stream_map serialization
Browse files Browse the repository at this point in the history
The ConnectionSummary can be serialized to help other tooling consume
the output of h3i. Previously we didn't support the seralization of
DATA frame payloads. Furthermore, we were a bit inconsistent with how
we serialize frames with binary payloads.

This change adds support for logging DATA frame payloads and ensures
that all frames consistently have a `_len` field to indicate the true
length of the frame. Documentation has been added with a pointer to
the hexstring qlog definition that we use here.

Closes #1917
  • Loading branch information
LPardue authored and ghedo committed Jan 27, 2025
1 parent 2c9a192 commit 3a70151
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
6 changes: 6 additions & 0 deletions h3i/src/client/connection_summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ pub const MAX_SERIALIZED_BUFFER_LEN: usize = 16384;
/// A summary of all frames received on a connection. There are some extra
/// fields included to provide additional context into the connection's
/// behavior.
///
/// ConnectionSummary implements [Serialize]. HTTP/3 frames that contain binary
/// payload are serialized using the qlog
/// [hexstring](https://www.ietf.org/archive/id/draft-ietf-quic-qlog-main-schema-10.html#section-1.2)
/// format - "an even-length lowercase string of hexadecimally encoded bytes
/// examples: 82dc, 027339, 4cdbfd9bf0"
#[derive(Default, Debug)]
pub struct ConnectionSummary {
pub stream_map: StreamMap,
Expand Down
23 changes: 18 additions & 5 deletions h3i/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,13 @@ impl Serialize for SerializableQFrame<'_> {
let name = frame_name(self.0);
match self.0 {
QFrame::Data { payload } => {
let mut state = s.serialize_struct(name, 1)?;
let mut state = s.serialize_struct(name, 2)?;
let max = cmp::min(payload.len(), MAX_SERIALIZED_BUFFER_LEN);
state.serialize_field("payload_len", &payload.len())?;
state.serialize_field(
"payload",
&qlog::HexSlice::maybe_string(Some(&payload[..max])),
)?;
state.end()
},

Expand Down Expand Up @@ -382,7 +387,7 @@ impl Serialize for SerializableQFrame<'_> {
prioritized_element_id,
priority_field_value,
} => {
let mut state = s.serialize_struct(name, 2)?;
let mut state = s.serialize_struct(name, 3)?;
state.serialize_field(
"prioritized_element_id",
&prioritized_element_id,
Expand All @@ -392,6 +397,10 @@ impl Serialize for SerializableQFrame<'_> {
priority_field_value.len(),
MAX_SERIALIZED_BUFFER_LEN,
);
state.serialize_field(
"priority_field_value_len",
&priority_field_value.len(),
)?;
state.serialize_field(
"priority_field_value",
&String::from_utf8_lossy(&priority_field_value[..max]),
Expand All @@ -403,7 +412,7 @@ impl Serialize for SerializableQFrame<'_> {
prioritized_element_id,
priority_field_value,
} => {
let mut state = s.serialize_struct(name, 1)?;
let mut state = s.serialize_struct(name, 3)?;
state.serialize_field(
"prioritized_element_id",
&prioritized_element_id,
Expand All @@ -412,6 +421,10 @@ impl Serialize for SerializableQFrame<'_> {
priority_field_value.len(),
MAX_SERIALIZED_BUFFER_LEN,
);
state.serialize_field(
"priority_field_value_len",
&priority_field_value.len(),
)?;
state.serialize_field(
"priority_field_value",
&String::from_utf8_lossy(&priority_field_value[..max]),
Expand All @@ -420,10 +433,10 @@ impl Serialize for SerializableQFrame<'_> {
},

QFrame::Unknown { raw_type, payload } => {
let mut state = s.serialize_struct(name, 1)?;
let mut state = s.serialize_struct(name, 3)?;
state.serialize_field("raw_type", &raw_type)?;
let max = cmp::min(payload.len(), MAX_SERIALIZED_BUFFER_LEN);

state.serialize_field("payload_len", &payload.len())?;
state.serialize_field(
"payload",
&qlog::HexSlice::maybe_string(Some(&payload[..max])),
Expand Down

0 comments on commit 3a70151

Please sign in to comment.