diff --git a/src/connection/connection.rs b/src/connection/connection.rs index 483f4521..f4cc9f12 100644 --- a/src/connection/connection.rs +++ b/src/connection/connection.rs @@ -358,30 +358,27 @@ impl Connection { description: String, ) { let trace = qlog::TraceSeq::new( - qlog::VantagePoint::new(None, self.is_server), Some(title.to_string()), Some(description.to_string()), - Some(qlog::Configuration::default()), None, + qlog::VantagePoint::new(None, self.is_server), ); let level = events::EventImportance::Extra; let mut writer = qlog::QlogWriter::new( - qlog::QLOG_VERSION.to_string(), Some(title), Some(description), - None, - time::Instant::now(), trace, level, writer, + time::Instant::now(), ); writer.start().ok(); // Write TransportParametersSet event to qlog - Self::qlog_transport_params_set( + Self::qlog_quic_params_set( &mut writer, &self.local_transport_params, - events::TransportOwner::Local, + events::Owner::Local, self.tls_session.cipher(), ); @@ -588,7 +585,6 @@ impl Connection { // Process each QUIC frame in the QUIC packet let mut ack_eliciting_pkt = false; let mut probing_pkt = true; - let mut qframes = vec![]; while !payload.is_empty() { let (frame, len) = Frame::from_bytes(&mut payload, hdr.pkt_type)?; @@ -598,9 +594,6 @@ impl Connection { if !frame.probing() { probing_pkt = false; } - if self.qlog.is_some() { - qframes.push(frame.to_qlog()); - } self.recv_frame(frame, &hdr, pid, space_id, info.time)?; let _ = payload.split_to(len); @@ -608,7 +601,7 @@ impl Connection { // Write TransportPacketReceived event to qlog. if let Some(qlog) = &mut self.qlog { - Self::qlog_transport_packet_received(qlog, &hdr, pkt_num, read, payload_len, qframes); + Self::qlog_quic_packet_received(qlog, &hdr, pkt_num, read, payload_len); } // Process acknowledged frames. @@ -1165,10 +1158,10 @@ impl Connection { // Write TransportParametersSet event to qlog. if let Some(qlog) = &mut self.qlog { - Self::qlog_transport_params_set( + Self::qlog_quic_params_set( qlog, &self.peer_transport_params, - events::TransportOwner::Remote, + events::Owner::Remote, self.tls_session.cipher(), ); } @@ -1275,9 +1268,9 @@ impl Connection { self.streams .on_stream_frame_acked(stream_id, offset, length); - // Write TransportDataMoved event to qlog + // Write QuicStreamDataMoved event to qlog if let Some(qlog) = &mut self.qlog { - Self::qlog_transport_data_acked(qlog, stream_id, offset, length); + Self::qlog_quic_data_acked(qlog, stream_id, offset, length); } } @@ -1587,11 +1580,7 @@ impl Connection { // Write TransportPacketSent event to qlog. if let Some(qlog) = &mut self.qlog { - let mut qframes = Vec::with_capacity(sent_pkt.frames.len()); - for frame in &sent_pkt.frames { - qframes.push(frame.to_qlog()); - } - Self::qlog_transport_packet_sent(qlog, &hdr, pkt_num, written, payload_len, qframes); + Self::qlog_quic_packet_sent(qlog, &hdr, pkt_num, written, payload_len); } // Notify the packet sent event to the multipath scheduler @@ -3408,7 +3397,7 @@ impl Connection { match self.streams.stream_read(stream_id, out) { Ok((read, fin)) => { - // Write TransportDataMoved event to qlog + // Write QuicStreamDataMoved event to qlog if let Some(qlog) = &mut self.qlog { Self::qlog_transport_data_read(qlog, stream_id, read_off.unwrap_or(0), read); } @@ -3426,7 +3415,7 @@ impl Connection { match self.streams.stream_write(stream_id, buf, fin) { Ok(written) => { - // Write TransportDataMoved event to qlog + // Write QuicStreamDataMoved event to qlog if let Some(qlog) = &mut self.qlog { Self::qlog_transport_data_write( qlog, @@ -3631,25 +3620,24 @@ impl Connection { self.context = Some(Box::new(data)) } - /// Write an TransportParametersSet event to the qlog. - fn qlog_transport_params_set( + /// Write a QuicParametersSet event to the qlog. + fn qlog_quic_params_set( qlog: &mut qlog::QlogWriter, params: &TransportParams, - owner: events::TransportOwner, + owner: events::Owner, cipher: Option, ) { let ev_data = params.to_qlog(owner, cipher); qlog.add_event_data(time::Instant::now(), ev_data).ok(); } - /// Write an TransportPacketReceived event to the qlog. - fn qlog_transport_packet_received( + /// Write a QuicPacketReceived event to the qlog. + fn qlog_quic_packet_received( qlog: &mut qlog::QlogWriter, hdr: &PacketHeader, pkt_num: u64, pkt_len: usize, payload_len: usize, - qlog_frames: Vec, ) { let qlog_pkt_hdr = events::PacketHeader::new_with_type( hdr.pkt_type.to_qlog(), @@ -3663,9 +3651,8 @@ impl Connection { payload_length: Some(payload_len as u64), data: None, }; - let ev_data = events::EventData::TransportPacketReceived { + let ev_data = events::EventData::QuicPacketReceived { header: qlog_pkt_hdr, - frames: Some(qlog_frames), is_coalesced: None, retry_token: None, stateless_reset_token: None, @@ -3677,14 +3664,13 @@ impl Connection { qlog.add_event_data(time::Instant::now(), ev_data).ok(); } - /// Write an TransportPacketSent event to the qlog. - fn qlog_transport_packet_sent( + /// Write a QuicPacketSent event to the qlog. + fn qlog_quic_packet_sent( qlog: &mut qlog::QlogWriter, hdr: &PacketHeader, pkt_num: u64, pkt_len: usize, payload_len: usize, - qlog_frames: Vec, ) { let qlog_pkt_hdr = events::PacketHeader::new_with_type( hdr.pkt_type.to_qlog(), @@ -3700,29 +3686,28 @@ impl Connection { }; let now = time::Instant::now(); - let ev_data = events::EventData::TransportPacketSent { + let ev_data = events::EventData::QuicPacketSent { header: qlog_pkt_hdr, - frames: Some(qlog_frames.into()), is_coalesced: None, retry_token: None, stateless_reset_token: None, supported_versions: None, raw: Some(qlog_raw_info), datagram_id: None, - send_at_time: Some(qlog.relative_time(now)), + is_mtu_probe_packet: None, trigger: None, }; qlog.add_event_data(now, ev_data).ok(); } - /// Write an TransportDataMoved event to the qlog. - fn qlog_transport_data_acked( + /// Write a QuicStreamDataMoved event to the qlog. + fn qlog_quic_data_acked( qlog: &mut qlog::QlogWriter, stream_id: u64, offset: u64, length: usize, ) { - let ev_data = events::EventData::TransportDataMoved { + let ev_data = events::EventData::QuicStreamDataMoved { stream_id: Some(stream_id), offset: Some(offset), length: Some(length as u64), @@ -3733,14 +3718,14 @@ impl Connection { qlog.add_event_data(time::Instant::now(), ev_data).ok(); } - /// Write an TransportDataMoved event to the qlog. + /// Write a QuicStreamDataMoved event to the qlog. fn qlog_transport_data_read( qlog: &mut qlog::QlogWriter, stream_id: u64, read_off: u64, read: usize, ) { - let ev_data = qlog::events::EventData::TransportDataMoved { + let ev_data = qlog::events::EventData::QuicStreamDataMoved { stream_id: Some(stream_id), offset: Some(read_off), length: Some(read as u64), @@ -3751,14 +3736,14 @@ impl Connection { qlog.add_event_data(time::Instant::now(), ev_data).ok(); } - /// Write TransportDataMoved event to the qlog. + /// Write a QuicStreamDataMoved event to the qlog. fn qlog_transport_data_write( qlog: &mut qlog::QlogWriter, stream_id: u64, write_off: u64, written: usize, ) { - let ev_data = qlog::events::EventData::TransportDataMoved { + let ev_data = qlog::events::EventData::QuicStreamDataMoved { stream_id: Some(stream_id), offset: Some(write_off), length: Some(written as u64), @@ -6447,17 +6432,17 @@ pub(crate) mod tests { let mut clog_content = String::new(); cfile.read_to_string(&mut clog_content).unwrap(); assert_eq!(clog_content.contains("client"), true); - assert_eq!(clog_content.contains("transport:parameters_set"), true); - assert_eq!(clog_content.contains("transport:data_moved"), true); - assert_eq!(clog_content.contains("transport:packet_sent"), true); + assert_eq!(clog_content.contains("quic:parameters_set"), true); + assert_eq!(clog_content.contains("quic:stream_data_moved"), true); + assert_eq!(clog_content.contains("quic:packet_sent"), true); // Check server qlog let mut slog_content = String::new(); sfile.read_to_string(&mut slog_content).unwrap(); assert_eq!(slog_content.contains("server"), true); - assert_eq!(slog_content.contains("transport:parameters_set"), true); - assert_eq!(slog_content.contains("transport:data_moved"), true); - assert_eq!(slog_content.contains("transport:packet_received"), true); + assert_eq!(slog_content.contains("quic:parameters_set"), true); + assert_eq!(slog_content.contains("quic:stream_data_moved"), true); + assert_eq!(slog_content.contains("quic:packet_received"), true); Ok(()) } diff --git a/src/qlog/events.rs b/src/qlog/events.rs index ae68011d..b2385018 100644 --- a/src/qlog/events.rs +++ b/src/qlog/events.rs @@ -13,6 +13,8 @@ // limitations under the License. //! Concrete qlog event definitions for QUIC, HTTP/3 and QPACK +//! - draft-ietf-quic-qlog-quic-events-06 +//! - draft-ietf-quic-qlog-h3-events-05 use serde::Deserialize; use serde::Serialize; @@ -31,6 +33,10 @@ pub struct Event { #[serde(flatten)] pub data: EventData, + /// The employed format is indicated in the "time_format" field, which + /// allows one of three values: "absolute", "delta" or "relative" + pub time_format: Option, + /// The "protocol_type" array field indicates to which protocols this event /// belongs. This allows a single qlog file to aggregate traces of different /// protocols @@ -43,10 +49,6 @@ pub struct Event { /// identifier" to each event that indicates to which conceptual "group" /// each event belongs. pub group_id: Option, - - /// The employed format is indicated in the "time_format" field, which - /// allows one of three values: "absolute", "delta" or "relative" - pub time_format: Option, } impl Event { @@ -54,9 +56,9 @@ impl Event { Event { time, data, + time_format: Default::default(), protocol_type: Default::default(), group_id: Default::default(), - time_format: Default::default(), } } @@ -117,7 +119,7 @@ pub enum EventData { /// difficult to reflect using the other options. #[serde(rename = "connectivity:connection_closed")] ConnectivityConnectionClosed { - owner: Option, // which side closed the connection + owner: Option, // which side closed the connection connection_code: Option, application_code: Option, internal_code: Option, @@ -132,7 +134,7 @@ pub enum EventData { /// "packet_received" events. #[serde(rename = "connectivity:connection_id_updated")] ConnectivityConnectionIdUpdated { - owner: Option, + owner: Option, old: Option, new: Option, }, @@ -155,6 +157,15 @@ pub enum EventData { new: ConnectionState, }, + /// This event indicates that the estimated Path MTU was updated. This happens + /// as part of the Path MTU discovery process. + #[serde(rename = "connectivity:mtu_updated")] + ConnectivityMtuUpdated { + old: Option, + new: u16, + done: Option, + }, + /// QUIC endpoints each have their own list of of QUIC versions they support. /// The client uses the most likely version in their first initial. If the /// server does support that version, it replies with a version_negotiation @@ -162,8 +173,8 @@ pub enum EventData { /// version. This event aggregates all this information in a single event type. /// It also allows logging of supported versions at an endpoint without actual /// version negotiation needing to happen. - #[serde(rename = "transport:version_information")] - TransportVersionInformation { + #[serde(rename = "quic:version_information")] + QuicVersionInformation { server_versions: Option>, client_versions: Option>, chosen_version: Option, @@ -175,8 +186,8 @@ pub enum EventData { /// Layer Protocol Negotiation (alpn) extension. If there are common option(s), /// the server chooses the most optimal one and communicates this back to the /// client. If not, the connection is closed. - #[serde(rename = "transport:alpn_information")] - TransportAlpnInformation { + #[serde(rename = "quic:alpn_information")] + QuicAlpnInformation { server_alpns: Option>, client_alpns: Option>, chosen_alpn: Option, @@ -186,13 +197,12 @@ pub enum EventData { /// parameters, TLS ciphers, etc.) into a single event. This is done to /// minimize the amount of events and to decouple conceptual setting /// impacts from their underlying mechanism for easier high-level reasoning. - #[serde(rename = "transport:parameters_set")] - TransportParametersSet { - owner: Option, + #[serde(rename = "quic:parameters_set")] + QuicParametersSet { + owner: Option, resumption_allowed: Option, early_data_enabled: Option, tls_cipher: Option, - aead_tag_length: Option, original_destination_connection_id: Option, initial_source_connection_id: Option, retry_source_connection_id: Option, @@ -210,6 +220,8 @@ pub enum EventData { initial_max_streams_bidi: Option, initial_max_streams_uni: Option, preferred_address: Option, + max_datagram_frame_size: Option, + grease_quic_bit: Option, }, /// When using QUIC 0-RTT, clients are expected to remember and restore the @@ -218,8 +230,8 @@ pub enum EventData { /// utilizing 0-RTT. Note that not all transport parameters should be restored /// (many are even prohibited from being re-utilized). The ones listed here are /// the ones expected to be useful for correct 0-RTT usage. - #[serde(rename = "transport:parameters_restored")] - TransportParametersRestored { + #[serde(rename = "quic:parameters_restored")] + QuicParametersRestored { disable_active_migration: Option, max_idle_timeout: Option, max_udp_payload_size: Option, @@ -232,34 +244,9 @@ pub enum EventData { initial_max_streams_uni: Option, }, - /// When one or more UDP-level datagrams are received from the socket. This is - /// useful for determining how datagrams are passed to the user space stack - /// from the OS. - #[serde(rename = "transport:datagrams_received")] - TransportDatagramsReceived { - count: Option, - raw: Option>, - datagram_ids: Option>, - }, - - /// When one or more UDP-level datagrams are passed to the socket. This is - /// useful for determining how QUIC packet buffers are drained to the OS. - #[serde(rename = "transport:datagrams_sent")] - TransportDatagramsSent { - count: Option, // To support passing multiple at once - raw: Option>, // Include only the UDP payload - datagram_ids: Option>, - }, - - /// When a UDP-level datagram is dropped. This is typically done if it does not - /// contain a valid QUIC packet. If it does, but the QUIC packet is dropped for - /// other reasons, packet_dropped (Section 5.7) should be used instead. - #[serde(rename = "transport:datagram_dropped")] - TransportDatagramDropped { raw: Option }, - - /// This event indicates a QUIC-level packet was received. - #[serde(rename = "transport:packet_received")] - TransportPacketReceived { + /// This event indicates a QUIC-level packet was sent. + #[serde(rename = "quic:packet_sent")] + QuicPacketSent { header: PacketHeader, is_coalesced: Option, retry_token: Option, @@ -267,13 +254,13 @@ pub enum EventData { supported_versions: Option>, raw: Option, datagram_id: Option, - trigger: Option, - frames: Option>, + is_mtu_probe_packet: Option, + trigger: Option, }, - /// This event indicates a QUIC-level packet was sent. - #[serde(rename = "transport:packet_sent")] - TransportPacketSent { + /// This event indicates a QUIC-level packet was received. + #[serde(rename = "quic:packet_received")] + QuicPacketReceived { header: PacketHeader, is_coalesced: Option, retry_token: Option, @@ -281,14 +268,12 @@ pub enum EventData { supported_versions: Option>, raw: Option, datagram_id: Option, - trigger: Option, - send_at_time: Option, - frames: Option>, + trigger: Option, }, /// This event indicates a QUIC-level packet was dropped. - #[serde(rename = "transport:packet_dropped")] - TransportPacketDropped { + #[serde(rename = "quic:packet_dropped")] + QuicPacketDropped { header: Option, raw: Option, datagram_id: Option, @@ -300,8 +285,8 @@ pub enum EventData { /// yet. Typically, this is because the packet cannot be parsed yet, and thus only /// the full packet contents can be logged when it was parsed in a packet_received /// event. - #[serde(rename = "transport:packet_buffered")] - TransportPacketBuffered { + #[serde(rename = "quic:packet_buffered")] + QuicPacketBuffered { header: Option, raw: Option, datagram_id: Option, @@ -315,18 +300,44 @@ pub enum EventData { /// first time, as QUIC uses ACK ranges which can include repeated ACKs. /// Additionally, this event can be used by implementations that do not log /// frame contents. - #[serde(rename = "transport:version_information")] - TransportPacketsAcked { + #[serde(rename = "quic:version_information")] + QuicPacketsAcked { packet_number_space: Option, packet_numbers: Option>, }, + /// When one or more UDP-level datagrams are passed to the socket. This is + /// useful for determining how QUIC packet buffers are drained to the OS. + #[serde(rename = "quic:datagrams_sent")] + QuicDatagramsSent { + count: Option, // To support passing multiple at once + raw: Option>, // Include only the UDP payload + datagram_ids: Option>, + }, + + /// When one or more UDP-level datagrams are received from the socket. This is + /// useful for determining how datagrams are passed to the user space stack + /// from the OS. + #[serde(rename = "quic:datagrams_received")] + QuicDatagramsReceived { + count: Option, + raw: Option>, + ecn: Option>, + datagram_ids: Option>, + }, + + /// When a UDP-level datagram is dropped. This is typically done if it does not + /// contain a valid QUIC packet. If it does, but the QUIC packet is dropped for + /// other reasons, packet_dropped (Section 5.7) should be used instead. + #[serde(rename = "quic:datagram_dropped")] + QuicDatagramDropped { raw: Option }, + /// This event is emitted whenever the internal state of a QUIC stream is updated, /// as described in QUIC transport draft-23 section 3. Most of this can be /// inferred from several types of frames going over the wire, but it's much /// easier to have explicit signals for these state changes. - #[serde(rename = "transport:stream_state_updated")] - TransportStreamStateUpdated { + #[serde(rename = "quic:stream_state_updated")] + QuicStreamStateUpdated { stream_id: u64, stream_type: Option, old: Option, @@ -342,8 +353,8 @@ pub enum EventData { /// of applying a frame to the internal state of an implementation can be /// inferred from that frame's contents, these events are aggregated into this /// single "frames_processed" event. - #[serde(rename = "transport:frames_processed")] - TransportFramesProcessed { + #[serde(rename = "quic:frames_processed")] + QuicFramesProcessed { frames: Vec, packet_number: Option, }, @@ -354,8 +365,8 @@ pub enum EventData { /// actual user application on top (for example a browser engine). This helps /// make clear the flow of data, how long data remains in various buffers and /// the overheads introduced by individual layers. - #[serde(rename = "transport:data_moved")] - TransportDataMoved { + #[serde(rename = "quic:stream_data_moved")] + QuicStreamDataMoved { stream_id: Option, offset: Option, length: Option, @@ -364,6 +375,21 @@ pub enum EventData { raw: Option, }, + /// Used to indicate when QUIC Datagram Frame data (see [RFC9221]) moves + /// between the different layers (for example passing from the application + /// protocol (e.g., WebTransport) to QUIC Datagram Frame buffers and vice + /// versa) or between the application protocol and the actual user + /// application on top (for example a gaming engine or media playback + /// software). This helps make clear the flow of data, how long data remains + /// in various buffers and the overheads introduced by individual layers. + #[serde(rename = "quic:datagram_data_moved")] + QuicDatagramDataMoved { + length: Option, + from: Option, + to: Option, + raw: Option, + }, + /// This event indicates the 1RTT key was updated. #[serde(rename = "security:key_updated")] SecurityKeyUpdated { @@ -447,6 +473,7 @@ pub enum EventData { RecoveryPacketLost { header: Option, frames: Option>, + is_mtu_probe_packet: Option, trigger: Option, }, @@ -458,19 +485,25 @@ pub enum EventData { #[serde(rename = "recovery:marked_for_retransmit")] RecoveryMarkedForRetransmit { frames: Vec }, + #[serde(rename = "recovery:ecn_state_updated")] + RecoveryEcnStateUpdated { + old: Option, + new: EcnState, + }, + /// This event contains HTTP/3 and QPACK-level settings, mostly those received /// from the HTTP/3 SETTINGS frame. All these parameters are typically set once /// and never change. However, they are typically set at different times during /// the connection, so there can be several instances of this event with /// different fields set. - #[serde(rename = "http:parameters_set")] - HttpParametersSet { - owner: Option, + #[serde(rename = "h3:parameters_set")] + H3ParametersSet { + owner: Option, #[serde(alias = "max_header_list_size")] max_field_section_size: Option, max_table_capacity: Option, blocked_streams_count: Option, - enable_connect_protocol: Option, + enable_connect: Option, h3_datagram: Option, /// indicates whether this implementation waits for a SETTINGS frame before /// processing requests @@ -481,8 +514,8 @@ pub enum EventData { /// server's SETTINGs from the previous connection. This event is used to /// indicate which HTTP/3 settings were restored and to which values when /// utilizing 0-RTT. - #[serde(rename = "http:parameters_restored")] - HttpParametersRestored { + #[serde(rename = "h3:parameters_restored")] + H3ParametersRestored { #[serde(alias = "max_header_list_size")] max_field_section_size: Option, max_table_capacity: Option, @@ -493,19 +526,29 @@ pub enum EventData { /// Emitted when a stream's type becomes known. This is typically when a stream /// is opened and the stream's type indicator is sent or received. - #[serde(rename = "http:stream_type_set")] - HttpStreamTypeSet { - owner: Option, + #[serde(rename = "h3:stream_type_set")] + H3StreamTypeSet { + owner: Option, stream_id: u64, stream_type: Http3StreamType, + stream_type_value: Option, associated_push_id: Option, }, + /// Emitted when the priority of a request stream or push stream is initialized + /// or updated through mechanisms defined in [RFC9218]. + H3PriorityUpdated { + stream_id: Option, + push_id: Option, + old: Option, + new: String, + }, + /// This event is emitted when the HTTP/3 framing actually happens. This does /// not necessarily coincide with HTTP/3 data getting passed to the QUIC layer. /// For that, see the "data_moved" event in [QLOG-QUIC]. - #[serde(rename = "http:frame_created")] - HttpFrameCreated { + #[serde(rename = "h3:frame_created")] + H3FrameCreated { stream_id: u64, length: Option, frame: Http3Frame, @@ -515,8 +558,8 @@ pub enum EventData { /// This event is emitted when the HTTP/3 frame is parsed. Note: this is not /// necessarily the same as when the HTTP/3 data is actually received on the /// QUIC layer. For that, see the "data_moved" event in [QLOG-QUIC]. - #[serde(rename = "http:frame_parsed")] - HttpFrameParsed { + #[serde(rename = "h3:frame_parsed")] + H3FrameParsed { stream_id: u64, length: Option, frame: Http3Frame, @@ -527,11 +570,11 @@ pub enum EventData { /// or, conversely, abandoned (rejected) by the application on top of HTTP/3 /// (e.g., the web browser). This event is added to help debug problems with /// unexpected PUSH behaviour, which is commonplace with HTTP/2. - #[serde(rename = "http:push_resolved")] - HttpPushResolved { + #[serde(rename = "h3:push_resolved")] + H3PushResolved { push_id: Option, stream_id: Option, - decision: Option, + decision: Http3PushDecision, }, /// This event is emitted when one or more of the internal QPACK variables @@ -542,7 +585,7 @@ pub enum EventData { /// separate event instances. #[serde(rename = "qpack:state_updated")] QpackStateUpdated { - owner: Option, + owner: Option, dynamic_table_capacity: Option, dynamic_table_size: Option, known_received_count: Option, @@ -561,6 +604,7 @@ pub enum EventData { /// QPACK's dynamic table. #[serde(rename = "qpack:dynamic_table_updated")] QpackDynamicTableUpdated { + owner: Owner, update_type: QpackUpdateType, entries: Vec, }, @@ -652,18 +696,19 @@ impl EventData { ConnectivityConnectionIdUpdated { .. } => EventImportance::Base, ConnectivitySpinBitUpdated { .. } => EventImportance::Base, ConnectivityConnectionStateUpdated { .. } => EventImportance::Base, - - TransportParametersSet { .. } => EventImportance::Core, - TransportDatagramsReceived { .. } => EventImportance::Extra, - TransportDatagramsSent { .. } => EventImportance::Extra, - TransportDatagramDropped { .. } => EventImportance::Extra, - TransportPacketReceived { .. } => EventImportance::Core, - TransportPacketSent { .. } => EventImportance::Core, - TransportPacketDropped { .. } => EventImportance::Base, - TransportPacketBuffered { .. } => EventImportance::Base, - TransportStreamStateUpdated { .. } => EventImportance::Base, - TransportFramesProcessed { .. } => EventImportance::Extra, - TransportDataMoved { .. } => EventImportance::Base, + ConnectivityMtuUpdated { .. } => EventImportance::Extra, + + QuicParametersSet { .. } => EventImportance::Core, + QuicDatagramsReceived { .. } => EventImportance::Extra, + QuicDatagramsSent { .. } => EventImportance::Extra, + QuicDatagramDropped { .. } => EventImportance::Extra, + QuicPacketReceived { .. } => EventImportance::Core, + QuicPacketSent { .. } => EventImportance::Core, + QuicPacketDropped { .. } => EventImportance::Base, + QuicPacketBuffered { .. } => EventImportance::Base, + QuicStreamStateUpdated { .. } => EventImportance::Base, + QuicFramesProcessed { .. } => EventImportance::Extra, + QuicStreamDataMoved { .. } => EventImportance::Base, SecurityKeyUpdated { .. } => EventImportance::Base, SecurityKeyDiscarded { .. } => EventImportance::Base, @@ -675,11 +720,11 @@ impl EventData { RecoveryPacketLost { .. } => EventImportance::Core, RecoveryMarkedForRetransmit { .. } => EventImportance::Extra, - HttpParametersSet { .. } => EventImportance::Base, - HttpStreamTypeSet { .. } => EventImportance::Base, - HttpFrameCreated { .. } => EventImportance::Core, - HttpFrameParsed { .. } => EventImportance::Core, - HttpPushResolved { .. } => EventImportance::Extra, + H3ParametersSet { .. } => EventImportance::Base, + H3StreamTypeSet { .. } => EventImportance::Base, + H3FrameCreated { .. } => EventImportance::Core, + H3FrameParsed { .. } => EventImportance::Core, + H3PushResolved { .. } => EventImportance::Extra, QpackStateUpdated { .. } => EventImportance::Base, QpackStreamStateUpdated { .. } => EventImportance::Base, @@ -778,7 +823,7 @@ pub enum CryptoError { #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[serde(rename_all = "snake_case")] -pub enum TransportOwner { +pub enum Owner { Local, Remote, } @@ -831,22 +876,6 @@ pub enum PacketNumberSpace { ApplicationData, } -#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -#[serde(rename_all = "snake_case")] -pub enum TokenType { - Retry, - Resumption, -} - -#[serde_with::skip_serializing_none] -#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)] -pub struct Token { - #[serde(rename(serialize = "type"))] - pub token_type: Option, - pub details: Option, - pub raw: Option, -} - #[serde_with::skip_serializing_none] #[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)] pub struct PacketHeader { @@ -917,6 +946,53 @@ impl PacketHeader { } } +#[serde_with::skip_serializing_none] +#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)] +pub struct Token { + #[serde(rename(serialize = "type"))] + pub token_type: Option, + pub details: Option, + pub raw: Option, +} + +#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] +#[serde(rename_all = "snake_case")] +pub enum TokenType { + Retry, + Resumption, +} + +#[allow(clippy::enum_variant_names)] +#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] +#[serde(rename_all = "snake_case")] +pub enum KeyType { + ServerInitialSecret, + ClientInitialSecret, + ServerHandshakeSecret, + ClientHandshakeSecret, + #[serde(rename = "server_0rtt_secret")] + Server0RttSecret, + #[serde(rename = "client_0rtt_secret")] + Client0RttSecret, + #[serde(rename = "server_1rtt_secret")] + Server1RttSecret, + #[serde(rename = "client_1rtt_secret")] + Client1RttSecret, +} + +#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] +#[serde(rename_all = "snake_case")] +pub enum Ecn { + #[serde(rename = "Not-ECT")] + NotEct, + #[serde(rename = "ECT(1)")] + Ect1, + #[serde(rename = "ECT(0)")] + Ect0, + #[serde(rename = "CE")] + Ce, +} + #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[serde(rename_all = "snake_case")] pub enum StreamType { @@ -1148,7 +1224,7 @@ pub enum QuicFrame { #[serde_with::skip_serializing_none] #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -pub struct TransportAlpnInformation { +pub struct QuicAlpnInformation { pub server_alpns: Option>, pub client_alpns: Option>, pub chosen_alpn: Option, @@ -1166,7 +1242,7 @@ pub struct PreferredAddress { #[serde_with::skip_serializing_none] #[derive(Serialize, Deserialize, Clone, PartialEq, Debug)] -pub struct TransportPacketSent { +pub struct QuicPacketSent { pub header: PacketHeader, pub is_coalesced: Option, pub retry_token: Option, @@ -1238,24 +1314,6 @@ pub enum PacketLostTrigger { PtoExpired, } -#[allow(clippy::enum_variant_names)] -#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -#[serde(rename_all = "snake_case")] -pub enum KeyType { - ServerInitialSecret, - ClientInitialSecret, - ServerHandshakeSecret, - ClientHandshakeSecret, - #[serde(rename = "server_0rtt_secret")] - Server0RttSecret, - #[serde(rename = "client_0rtt_secret")] - Client0RttSecret, - #[serde(rename = "server_1rtt_secret")] - Server1RttSecret, - #[serde(rename = "client_1rtt_secret")] - Client1RttSecret, -} - #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[serde(rename_all = "snake_case")] pub enum KeyUpdateOrRetiredTrigger { @@ -1266,9 +1324,11 @@ pub enum KeyUpdateOrRetiredTrigger { #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[serde(rename_all = "snake_case")] -pub enum Http3Owner { - Local, - Remote, +pub enum EcnState { + Testing, + Unknown, + Failed, + Capable, } #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] @@ -1478,18 +1538,18 @@ pub enum QPackInstruction { table_type: QpackTableType, name_index: u64, huffman_encoded_value: bool, - value_length: u64, - value: String, + value_length: Option, + value: Option, }, InsertWithoutNameReferenceInstruction { instruction_type: QpackInstructionTypeName, huffman_encoded_name: bool, - name_length: u64, - name: String, + name_length: Option, + name: Option, huffman_encoded_value: bool, - value_length: u64, - value: String, + value_length: Option, + value: Option, }, DuplicateInstruction { @@ -1536,33 +1596,23 @@ pub enum QpackHeaderBlockRepresentation { table_type: QpackTableType, name_index: u64, huffman_encoded_value: bool, - value_length: u64, - value: String, + value_length: Option, + value: Option, is_post_base: Option, }, LiteralHeaderFieldWithoutName { header_field_type: QpackHeaderBlockRepresentationTypeName, preserve_literal: bool, - table_type: QpackTableType, - name_index: u64, huffman_encoded_name: bool, - name_length: u64, - name: String, + name_length: Option, + name: Option, huffman_encoded_value: bool, - value_length: u64, - value: String, - is_post_base: Option, + value_length: Option, + value: Option, }, } -#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -#[serde(rename_all = "snake_case")] -pub enum QpackOwner { - Local, - Remote, -} - #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[serde(rename_all = "snake_case")] pub enum QpackStreamState { @@ -1605,11 +1655,10 @@ pub mod tests { } #[test] - fn serialize_transport_packet_sent_event_without_frames() { + fn serialize_quic_packet_sent_event() { let pkt_hdr = new_test_pkt_hdr(PacketType::Initial); - let event_data = EventData::TransportPacketSent { + let event_data = EventData::QuicPacketSent { header: pkt_hdr, - frames: None, is_coalesced: None, retry_token: None, stateless_reset_token: None, @@ -1620,7 +1669,7 @@ pub mod tests { data: None, }), datagram_id: None, - send_at_time: None, + is_mtu_probe_packet: None, trigger: None, }; @@ -1629,7 +1678,7 @@ pub mod tests { serde_json::to_string_pretty(&event).unwrap(), r#"{ "time": 1234567000.0, - "name": "transport:packet_sent", + "name": "quic:packet_sent", "data": { "header": { "packet_type": "initial", @@ -1645,78 +1694,6 @@ pub mod tests { "payload_length": 1173 } } -}"# - ); - } - - #[test] - fn serialize_transport_packet_sent_event_with_frames() { - let event_data = EventData::TransportPacketSent { - header: new_test_pkt_hdr(PacketType::Initial), - frames: Some( - vec![ - QuicFrame::Padding, - QuicFrame::Ping, - QuicFrame::Stream { - stream_id: 0, - offset: 0, - length: 100, - fin: Some(true), - raw: None, - }, - ] - .into(), - ), - is_coalesced: None, - retry_token: None, - stateless_reset_token: None, - supported_versions: None, - raw: Some(RawInfo { - length: Some(1200), - payload_length: Some(1173), - data: None, - }), - datagram_id: None, - send_at_time: None, - trigger: None, - }; - - let event = Event::new(0.0, event_data); - assert_eq!( - serde_json::to_string_pretty(&event).unwrap(), - r#"{ - "time": 0.0, - "name": "transport:packet_sent", - "data": { - "header": { - "packet_type": "initial", - "packet_number": 0, - "version": "1", - "scil": 8, - "dcil": 8, - "scid": "0102030405060708", - "dcid": "0807060504030201" - }, - "raw": { - "length": 1200, - "payload_length": 1173 - }, - "frames": [ - { - "frame_type": "padding" - }, - { - "frame_type": "ping" - }, - { - "frame_type": "stream", - "stream_id": 0, - "offset": 0, - "length": 100, - "fin": true - } - ] - } }"# ); } diff --git a/src/qlog/qlog.rs b/src/qlog/qlog.rs index f6c0d0ba..849d42fd 100644 --- a/src/qlog/qlog.rs +++ b/src/qlog/qlog.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An implementation of the qlog [main logging schema], [QUIC event definitions] -//! and [HTTP/3 and QPACK event definitions]. +//! An implementation of the qlog main logging schema, QUIC event definitions +//! and HTTP/3 and QPACK event definitions. use std::time::Instant; @@ -27,91 +27,60 @@ use self::events::PacketHeader; use crate::Error; use crate::Result; -pub const QLOG_VERSION: &str = "0.3"; +/// The qlog_version is 0.4 for draft-ietf-quic-qlog-main-schema-07 +pub const QLOG_VERSION: &str = "0.4"; -/// A qlog file should be able to contain several individual traces and logs -/// from multiple vantage points that are in some way related. -#[serde_with::skip_serializing_none] -#[derive(Serialize, Deserialize, Clone)] -pub struct Qlog { - /// The required "qlog_version" field MUST have a value of "0.3" for - /// draft-ietf-quic-qlog-main-schema-05 - pub qlog_version: String, +/// The serialization format for QlogFileSeq is JSON-SEQ +/// See RFC 7464: JavaScript Object Notation (JSON) Text Sequences +pub const JSON_TEXT_SEQS: &str = "JSON-SEQ"; - /// As qlog can be serialized in a variety of ways, the "qlog_format" field - /// is used to indicate which serialization option was chosen. +/// A qlog file using the QlogFileSeq schema can be serialized to a streamable +/// JSON format called JSON Text Sequences (JSON-SEQ) ([RFC7464]) +/// See draft-ietf-quic-qlog-main-schema-07 +#[serde_with::skip_serializing_none] +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct QlogFileSeq { + /// The qlog_format field MUST have the value "JSON-SEQ". pub qlog_format: String, - /// Name of this particular qlog file + /// The qlog_version field MUST have the value "0.4". + pub qlog_version: String, + + /// The title field provide additional free-text information about the file. pub title: Option, - /// Description for this group of traces + /// The description field provide additional free-text information about + /// the file. pub description: Option, - /// In a real-life deployment with a large amount of generated logs, it can - /// be useful to sort and filter logs based on some basic summarized or - /// aggregated data (e.g., log length, packet loss rate, log location, - /// presence of error events, ...). - pub summary: Option, - - /// It is often advantageous to group several related qlog traces together - /// in a single file. The "traces" array contains a list of individual qlog - /// traces. - pub traces: Vec, + /// The trace field contains a singular trace metadata. All qlog events in + /// the file are related to this trace. + pub trace: TraceSeq, } -/// In the normal use case however, a trace is a log of a single data flow -/// collected at a single location or vantage point. #[serde_with::skip_serializing_none] #[derive(Serialize, Deserialize, Clone, PartialEq, Debug)] -pub struct Trace { - /// The vantage_point field describes the vantage point from which the - /// trace originates - pub vantage_point: VantagePoint, - - /// Name of this particular trace +pub struct TraceSeq { pub title: Option, - - /// Description for this trace pub description: Option, - - /// The configuration field can be viewed as a generic metadata field that - /// tools can fill with their own fields, based on per-tool logic. - pub configuration: Option, - - /// qlog uses the "common_fields" list to indicate fields that are shared - /// by all events in this component trace. This prevents these fields from - /// being logged for each individual event. pub common_fields: Option, - - /// The exact conceptual definition of a Trace can be fluid. For example, - /// a trace could contain all events for a single connection, for a single - /// endpoint, for a single measurement interval, for a single protocol, etc. - pub events: Vec, + pub vantage_point: VantagePoint, } -impl Trace { +impl TraceSeq { pub fn new( - vantage_point: VantagePoint, title: Option, description: Option, - configuration: Option, common_fields: Option, + vantage_point: VantagePoint, ) -> Self { - Trace { - vantage_point, + TraceSeq { title, description, - configuration, common_fields, - events: Vec::new(), + vantage_point, } } - - /// Append an Event to a Trace - pub fn push_event(&mut self, event: Event) { - self.events.push(event); - } } /// Describes the vantage point from which the trace originates. @@ -130,7 +99,7 @@ pub struct VantagePoint { } impl VantagePoint { - // Return a Server or Client VantagePoint + /// Return a Server or Client VantagePoint pub fn new(name: Option, is_server: bool) -> VantagePoint { let vp_type = if is_server { VantagePointType::Server @@ -191,6 +160,18 @@ impl Default for Configuration { #[serde_with::skip_serializing_none] #[derive(Serialize, Deserialize, Clone, Default, PartialEq, Debug)] pub struct CommonFields { + /// The employed format is indicated in the "time_format" field, which + /// allows one of three values: "absolute", "delta" or "relative" + pub time_format: Option, + + /// The "reference_time" value is typically the first absolute timestamp. + pub reference_time: Option, + + /// The "protocol_type" array field indicates to which protocols (or + /// protocol "stacks") this event belongs. This allows a single qlog file + /// to aggregate traces of different protocols. + pub protocol_type: Option>, + /// A server implementation might choose to log events for all incoming /// connections in a single large (streamed) qlog file. As such, we need /// a method for splitting up events belonging to separate logical entities. @@ -198,129 +179,78 @@ pub struct CommonFields { /// identifier" to each event that indicates to which conceptual "group" /// each event belongs. pub group_id: Option, - - /// The "protocol_type" array field indicates to which protocols (or - /// protocol "stacks") this event belongs. This allows a single qlog file - /// to aggregate traces of different protocols. - pub protocol_type: Option>, - - /// The "reference_time" value is typically the first absolute timestamp. - pub reference_time: Option, - - /// The employed format is indicated in the "time_format" field, which - /// allows one of three values: "absolute", "delta" or "relative" - pub time_format: Option, } -#[serde_with::skip_serializing_none] -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct QlogSeq { - pub qlog_version: String, - pub qlog_format: String, - pub title: Option, - pub description: Option, - pub summary: Option, - pub trace: TraceSeq, -} +/// Qlog writer using the QlogFileSeq schema +pub struct QlogWriter { + /// The top-level element in this schema that defines only a small set of + /// "header" fields and an array of component traces. + qlog: QlogFileSeq, -#[serde_with::skip_serializing_none] -#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)] -pub struct TraceSeq { - pub vantage_point: VantagePoint, - pub title: Option, - pub description: Option, - pub configuration: Option, - pub common_fields: Option, -} + /// Events below this level will not be written out. + level: EventImportance, -impl TraceSeq { - pub fn new( - vantage_point: VantagePoint, - title: Option, - description: Option, - configuration: Option, - common_fields: Option, - ) -> Self { - TraceSeq { - vantage_point, - title, - description, - configuration, - common_fields, - } - } -} + /// The underlying writer for qlog streaming + writer: Box, -#[derive(PartialEq, Eq, Debug)] -pub enum QlogWriterState { - Initial, - Ready, - Finished, -} + /// Whether the top-level element (QlogFileSeq) has been written + ready: bool, -pub struct QlogWriter { + /// The created time for the QlogWriter start_time: std::time::Instant, - writer: Box, - qlog: QlogSeq, - state: QlogWriterState, - level: EventImportance, } impl QlogWriter { #[allow(clippy::too_many_arguments)] pub fn new( - qlog_version: String, title: Option, description: Option, - summary: Option, - start_time: std::time::Instant, trace: TraceSeq, level: EventImportance, writer: Box, + start_time: std::time::Instant, ) -> Self { - let qlog = QlogSeq { - qlog_version, - qlog_format: "JSON-SEQ".to_string(), + let qlog = QlogFileSeq { + qlog_format: crate::qlog::JSON_TEXT_SEQS.to_string(), + qlog_version: crate::qlog::QLOG_VERSION.to_string(), title, description, - summary, trace, }; QlogWriter { - start_time, - writer, qlog, - state: QlogWriterState::Initial, level, + writer, + ready: false, + start_time, } } - /// Start qlog streaming serialization. + /// Start qlog serialization and write the QlogFileSeq. pub fn start(&mut self) -> Result<()> { - if self.state != QlogWriterState::Initial { + if self.ready { return Err(Error::Done); } self.writer.as_mut().write_all(b" ")?; serde_json::to_writer(self.writer.as_mut(), &self.qlog).map_err(|_| Error::Done)?; self.writer.as_mut().write_all(b"\n")?; - self.state = QlogWriterState::Ready; + self.ready = true; Ok(()) } - /// Finish qlog streaming serialization. - pub fn finish(&mut self) -> Result<()> { - if self.state != QlogWriterState::Ready { + /// Flush qlog serialization data. + pub fn flush(&mut self) -> Result<()> { + if !self.ready { return Err(Error::InvalidState("expect ready state".into())); } - self.state = QlogWriterState::Finished; self.writer.as_mut().flush()?; Ok(()) } - /// Write a JSON-SEQ-serialized Event. + /// Write an event in JSON-SEQ format. pub fn add_event(&mut self, event: Event) -> Result<()> { self.check(event.importance())?; @@ -330,7 +260,7 @@ impl QlogWriter { Ok(()) } - /// Write a JSON-SEQ-serialized Event. + /// Write an event in JSON-SEQ format. pub fn add_event_data(&mut self, time: Instant, event_data: EventData) -> Result<()> { let event = Event::new(self.relative_time(time), event_data); self.add_event(event) @@ -338,7 +268,7 @@ impl QlogWriter { /// Return whether the event should be written fn check(&self, ei: EventImportance) -> Result<()> { - if self.state != QlogWriterState::Ready { + if !self.ready { return Err(Error::InvalidState("not ready".into())); } if !ei.is_contained_in(&self.level) { @@ -362,151 +292,32 @@ mod tests { use crate::qlog::events::EventData; use crate::qlog::events::PacketType; use crate::qlog::events::QuicFrame; + use crate::qlog::events::QuicPacketSent; use crate::qlog::events::RawInfo; - use crate::qlog::events::TransportPacketSent; pub fn new_test_trace_seq() -> TraceSeq { TraceSeq::new( - VantagePoint { - name: None, - r#type: VantagePointType::Server, - flow: None, - }, Some("qlog trace".to_string()), Some("qlog trace description".to_string()), - Some(Configuration::default()), None, - ) - } - - fn new_test_trace() -> Trace { - Trace::new( VantagePoint { name: None, r#type: VantagePointType::Server, flow: None, }, - Some("qlog trace".to_string()), - Some("qlog trace description".to_string()), - Some(Configuration::default()), - None, ) } - #[test] - fn serialize_traces() { - let mut cases = Vec::<(Trace, String)>::new(); - - // trace without events - let trace = new_test_trace(); - let trace_str = r#"{ - "vantage_point": { - "type": "server" - }, - "title": "qlog trace", - "description": "qlog trace description", - "configuration": { - "time_offset": 0.0 - }, - "events": [] -}"#; - cases.push((trace, trace_str.to_string())); - - // trace with single transport event - let mut trace = new_test_trace(); - trace.push_event(Event::new( - 0.0, - EventData::TransportPacketSent { - header: new_test_pkt_hdr(PacketType::Initial), - frames: Some( - vec![QuicFrame::Stream { - stream_id: 0, - offset: 0, - length: 100, - fin: Some(true), - raw: None, - }] - .into(), - ), - is_coalesced: None, - retry_token: None, - stateless_reset_token: None, - supported_versions: None, - raw: Some(RawInfo { - length: Some(1200), - payload_length: Some(1173), - data: None, - }), - datagram_id: None, - send_at_time: None, - trigger: None, - }, - )); - - let trace_str = r#"{ - "vantage_point": { - "type": "server" - }, - "title": "qlog trace", - "description": "qlog trace description", - "configuration": { - "time_offset": 0.0 - }, - "events": [ - { - "time": 0.0, - "name": "transport:packet_sent", - "data": { - "header": { - "packet_type": "initial", - "packet_number": 0, - "version": "1", - "scil": 8, - "dcil": 8, - "scid": "0102030405060708", - "dcid": "0807060504030201" - }, - "raw": { - "length": 1200, - "payload_length": 1173 - }, - "frames": [ - { - "frame_type": "stream", - "stream_id": 0, - "offset": 0, - "length": 100, - "fin": true - } - ] - } - } - ] -}"#; - cases.push((trace, trace_str.to_string())); - - // Check serialization string - for (trace, trace_string) in cases { - let serialized = serde_json::to_string_pretty(&trace).unwrap(); - assert_eq!(serialized, trace_string); - - let deserialized: Trace = serde_json::from_str(&serialized).unwrap(); - assert_eq!(deserialized, trace); - } - } - #[test] fn qlog_writer_operations() -> Result<()> { let writer = std::io::Cursor::new(Vec::::new()); let mut qlog_writer = QlogWriter::new( - "version".to_string(), Some("title".to_string()), Some("description".to_string()), - None, - std::time::Instant::now(), new_test_trace_seq(), EventImportance::Base, Box::new(writer), + std::time::Instant::now(), ); // Add an event before the QlogWriter is started @@ -545,9 +356,8 @@ mod tests { ); qlog_writer.add_event(event3)?; - // Stop the QlogWriter - qlog_writer.finish()?; - assert!(qlog_writer.finish().is_err()); + // Flush the QlogWriter + qlog_writer.flush()?; // Check written logs let w: &Box>> = unsafe { std::mem::transmute(&qlog_writer.writer) }; @@ -555,7 +365,7 @@ mod tests { assert_eq!( log, - r#" {"qlog_version":"version","qlog_format":"JSON-SEQ","title":"title","description":"description","trace":{"vantage_point":{"type":"server"},"title":"qlog trace","description":"qlog trace description","configuration":{"time_offset":0.0}}} + r#" {"qlog_format":"JSON-SEQ","qlog_version":"0.4","title":"title","description":"description","trace":{"title":"qlog trace","description":"qlog trace description","vantage_point":{"type":"server"}}} {"time":0.0,"name":"connectivity:connection_state_updated","data":{"new":"handshake_completed"}} {"time":0.0,"name":"connectivity:connection_state_updated","data":{"new":"handshake_confirmed"}} "# diff --git a/src/trans_param.rs b/src/trans_param.rs index 3f4d2226..553287aa 100644 --- a/src/trans_param.rs +++ b/src/trans_param.rs @@ -391,23 +391,18 @@ impl TransportParams { } /// Create TransportParametersSet event data for Qlog. - pub fn to_qlog( - &self, - owner: qlog::events::TransportOwner, - cipher: Option, - ) -> EventData { + pub fn to_qlog(&self, owner: qlog::events::Owner, cipher: Option) -> EventData { let original_destination_connection_id = Some(format!( "{:?}", self.original_destination_connection_id.as_ref() )); let stateless_reset_token = Some(format!("{:?}", self.stateless_reset_token.as_ref())); - qlog::events::EventData::TransportParametersSet { + qlog::events::EventData::QuicParametersSet { owner: Some(owner), resumption_allowed: None, early_data_enabled: None, tls_cipher: Some(format!("{:?}", cipher)), - aead_tag_length: None, original_destination_connection_id, initial_source_connection_id: None, retry_source_connection_id: None, @@ -425,6 +420,8 @@ impl TransportParams { initial_max_streams_bidi: Some(self.initial_max_streams_bidi), initial_max_streams_uni: Some(self.initial_max_streams_uni), preferred_address: None, + max_datagram_frame_size: None, + grease_quic_bit: None, } } }