Source code

Revision control

Copy as Markdown

Other Tools

// Copyright (C) 2021, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use serde::Deserialize;
use serde::Serialize;
use crate::events::RawInfo;
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Initiator {
Local,
Remote,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
#[serde(rename_all = "snake_case")]
pub enum StreamType {
Request,
Control,
Push,
Reserved,
#[default]
Unknown,
QpackEncode,
QpackDecode,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum PushDecision {
Claimed,
Abandoned,
}
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Http3EventType {
ParametersSet,
ParametersRestored,
StreamTypeSet,
PriorityUpdated,
FrameCreated,
FrameParsed,
DatagramCreated,
DatagramParsed,
PushResolved,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct HttpHeader {
pub name: Option<String>,
pub name_bytes: Option<String>,
pub value: Option<String>,
pub value_bytes: Option<String>,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct Setting {
pub name: Option<String>,
pub name_bytes: Option<u64>,
pub value: u64,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Http3FrameTypeName {
Data,
Headers,
CancelPush,
Settings,
PushPromise,
Goaway,
MaxPushId,
DuplicatePush,
Reserved,
Unknown,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(tag = "frame_type")]
#[serde(rename_all = "snake_case")]
// Strictly, the qlog spec says that all these frame types have a frame_type
// field. But instead of making that a rust object property, just use serde to
// ensure it goes out on the wire. This means that deserialization of frames
// also works automatically.
pub enum Http3Frame {
Data {
raw: Option<RawInfo>,
},
Headers {
headers: Vec<HttpHeader>,
raw: Option<RawInfo>,
},
CancelPush {
push_id: u64,
raw: Option<RawInfo>,
},
Settings {
settings: Vec<Setting>,
raw: Option<RawInfo>,
},
PushPromise {
push_id: u64,
headers: Vec<HttpHeader>,
raw: Option<RawInfo>,
},
Goaway {
id: u64,
raw: Option<RawInfo>,
},
MaxPushId {
push_id: u64,
raw: Option<RawInfo>,
},
PriorityUpdate {
stream_id: Option<u64>,
push_id: Option<u64>,
priority_field_value: String,
raw: Option<RawInfo>,
},
Reserved {
frame_type_bytes: u64,
raw: Option<RawInfo>,
},
Unknown {
frame_type_bytes: u64,
raw: Option<RawInfo>,
},
}
impl Default for Http3Frame {
fn default() -> Self {
Self::Unknown {
frame_type_bytes: 0,
raw: None,
}
}
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct ParametersSet {
pub initiator: Option<Initiator>,
#[serde(alias = "max_header_list_size")]
pub max_field_section_size: Option<u64>,
pub max_table_capacity: Option<u64>,
pub blocked_streams_count: Option<u64>,
pub extended_connect: Option<u16>,
pub h3_datagram: Option<u16>,
// qlog-defined
pub waits_for_settings: Option<bool>,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct ParametersRestored {
#[serde(alias = "max_header_list_size")]
pub max_field_section_size: Option<u64>,
pub max_table_capacity: Option<u64>,
pub blocked_streams_count: Option<u64>,
pub extended_connect: Option<u16>,
pub h3_datagram: Option<u16>,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
pub struct StreamTypeSet {
pub initiator: Option<Initiator>,
pub stream_id: u64,
pub stream_type: StreamType,
pub stream_type_bytes: Option<u64>,
pub associated_push_id: Option<u64>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum PriorityUpdatedTrigger {
ClientSignalReceived,
Local,
Other,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum PriorityUpdatedReason {
ClientSignalOnly,
ClientServerMerged,
LocalPolicy,
Other,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
pub struct PriorityUpdated {
pub stream_id: Option<u64>,
pub push_id: Option<u64>,
pub old: Option<String>,
pub new: String,
pub trigger: Option<PriorityUpdatedTrigger>,
pub reason: Option<PriorityUpdatedReason>,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
pub struct FrameCreated {
pub stream_id: u64,
pub length: Option<u64>,
pub frame: Http3Frame,
pub raw: Option<RawInfo>,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
pub struct FrameParsed {
pub stream_id: u64,
pub length: Option<u64>,
pub frame: Http3Frame,
pub raw: Option<RawInfo>,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
pub struct DatagramCreated {
pub quarter_stream_id: u64,
pub datagram: Option<Vec<String>>,
pub raw: Option<RawInfo>,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
pub struct DatagramParsed {
pub quarter_stream_id: u64,
pub datagram: Option<Vec<String>>,
pub raw: Option<RawInfo>,
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct PushResolved {
pub push_id: Option<u64>,
pub stream_id: Option<u64>,
pub decision: PushDecision,
}