qlog/events/
h3.rs

1// Copyright (C) 2021, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//
11//     * Redistributions in binary form must reproduce the above copyright
12//       notice, this list of conditions and the following disclaimer in the
13//       documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27use serde::Deserialize;
28use serde::Serialize;
29
30use super::RawInfo;
31
32#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
33#[serde(rename_all = "snake_case")]
34pub enum H3Owner {
35    Local,
36    Remote,
37}
38
39#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
40#[serde(rename_all = "snake_case")]
41pub enum H3StreamType {
42    Request,
43    Control,
44    Push,
45    Reserved,
46    #[default]
47    Unknown,
48    QpackEncode,
49    QpackDecode,
50}
51
52#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
53#[serde(rename_all = "snake_case")]
54pub enum H3PushDecision {
55    Claimed,
56    Abandoned,
57}
58
59#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
60#[serde(rename_all = "snake_case")]
61pub enum H3PriorityTargetStreamType {
62    Request,
63    Push,
64}
65
66#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug)]
67#[serde(rename_all = "snake_case")]
68pub enum Http3EventType {
69    ParametersSet,
70    ParametersRestored,
71    StreamTypeSet,
72    FrameCreated,
73    FrameParsed,
74    PushResolved,
75}
76
77#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
78#[serde(rename_all = "snake_case")]
79pub enum ApplicationError {
80    HttpNoError,
81    HttpGeneralProtocolError,
82    HttpInternalError,
83    HttpRequestCancelled,
84    HttpIncompleteRequest,
85    HttpConnectError,
86    HttpFrameError,
87    HttpExcessiveLoad,
88    HttpVersionFallback,
89    HttpIdError,
90    HttpStreamCreationError,
91    HttpClosedCriticalStream,
92    HttpEarlyResponse,
93    HttpMissingSettings,
94    HttpUnexpectedFrame,
95    HttpRequestRejection,
96    HttpSettingsError,
97    Unknown,
98}
99
100#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
101pub struct HttpHeader {
102    pub name: String,
103    pub value: String,
104}
105
106#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
107pub struct Setting {
108    pub name: String,
109    pub value: u64,
110}
111
112#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
113#[serde(rename_all = "snake_case")]
114pub enum Http3FrameTypeName {
115    Data,
116    Headers,
117    CancelPush,
118    Settings,
119    PushPromise,
120    Goaway,
121    MaxPushId,
122    DuplicatePush,
123    Reserved,
124    Unknown,
125}
126
127#[serde_with::skip_serializing_none]
128#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
129#[serde(tag = "frame_type")]
130#[serde(rename_all = "snake_case")]
131// Strictly, the qlog spec says that all these frame types have a frame_type
132// field. But instead of making that a rust object property, just use serde to
133// ensure it goes out on the wire. This means that deserialization of frames
134// also works automatically.
135pub enum Http3Frame {
136    Data {
137        raw: Option<RawInfo>,
138    },
139
140    Headers {
141        headers: Vec<HttpHeader>,
142    },
143
144    CancelPush {
145        push_id: u64,
146    },
147
148    Settings {
149        settings: Vec<Setting>,
150    },
151
152    PushPromise {
153        push_id: u64,
154        headers: Vec<HttpHeader>,
155    },
156
157    Goaway {
158        id: u64,
159    },
160
161    MaxPushId {
162        push_id: u64,
163    },
164
165    PriorityUpdate {
166        target_stream_type: H3PriorityTargetStreamType,
167        prioritized_element_id: u64,
168        priority_field_value: String,
169    },
170
171    Reserved {
172        length: Option<u64>,
173    },
174
175    Unknown {
176        frame_type_value: u64,
177        raw: Option<RawInfo>,
178    },
179}
180
181impl Default for Http3Frame {
182    fn default() -> Self {
183        Self::Unknown {
184            frame_type_value: 0,
185            raw: None,
186        }
187    }
188}
189
190#[serde_with::skip_serializing_none]
191#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
192pub struct H3ParametersSet {
193    pub owner: Option<H3Owner>,
194
195    #[serde(alias = "max_header_list_size")]
196    pub max_field_section_size: Option<u64>,
197    pub max_table_capacity: Option<u64>,
198    pub blocked_streams_count: Option<u64>,
199    pub enable_connect_protocol: Option<u64>,
200    pub h3_datagram: Option<u64>,
201
202    // qlog-defined
203    pub waits_for_settings: Option<bool>,
204}
205
206#[serde_with::skip_serializing_none]
207#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
208pub struct H3ParametersRestored {
209    #[serde(alias = "max_header_list_size")]
210    pub max_field_section_size: Option<u64>,
211    pub max_table_capacity: Option<u64>,
212    pub blocked_streams_count: Option<u64>,
213    pub enable_connect_protocol: Option<u64>,
214    pub h3_datagram: Option<u64>,
215}
216
217#[serde_with::skip_serializing_none]
218#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
219pub struct H3StreamTypeSet {
220    pub owner: Option<H3Owner>,
221    pub stream_id: u64,
222    pub stream_type: H3StreamType,
223    pub stream_type_value: Option<u64>,
224    pub associated_push_id: Option<u64>,
225}
226
227#[serde_with::skip_serializing_none]
228#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
229pub struct H3FrameCreated {
230    pub stream_id: u64,
231    pub length: Option<u64>,
232    pub frame: Http3Frame,
233
234    pub raw: Option<RawInfo>,
235}
236
237#[serde_with::skip_serializing_none]
238#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug, Default)]
239pub struct H3FrameParsed {
240    pub stream_id: u64,
241    pub length: Option<u64>,
242    pub frame: Http3Frame,
243
244    pub raw: Option<RawInfo>,
245}
246
247#[serde_with::skip_serializing_none]
248#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
249pub struct H3PushResolved {
250    push_id: Option<u64>,
251    stream_id: Option<u64>,
252
253    decision: Option<H3PushDecision>,
254}