1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use crate::{frame::Frame, Dir};
use std::time::Duration;
#[derive(Default, Debug, Copy, Clone)]
#[non_exhaustive]
pub struct UdpStats {
pub datagrams: u64,
pub bytes: u64,
pub transmits: u64,
}
#[derive(Default, Copy, Clone)]
#[non_exhaustive]
pub struct FrameStats {
pub acks: u64,
pub crypto: u64,
pub connection_close: u64,
pub data_blocked: u64,
pub datagram: u64,
pub handshake_done: u8,
pub max_data: u64,
pub max_stream_data: u64,
pub max_streams_bidi: u64,
pub max_streams_uni: u64,
pub new_connection_id: u64,
pub new_token: u64,
pub path_challenge: u64,
pub path_response: u64,
pub ping: u64,
pub reset_stream: u64,
pub retire_connection_id: u64,
pub stream_data_blocked: u64,
pub streams_blocked_bidi: u64,
pub streams_blocked_uni: u64,
pub stop_sending: u64,
pub stream: u64,
}
impl FrameStats {
pub(crate) fn record(&mut self, frame: &Frame) {
match frame {
Frame::Padding => {}
Frame::Ping => self.ping += 1,
Frame::Ack(_) => self.acks += 1,
Frame::ResetStream(_) => self.reset_stream += 1,
Frame::StopSending(_) => self.stop_sending += 1,
Frame::Crypto(_) => self.crypto += 1,
Frame::Datagram(_) => self.datagram += 1,
Frame::NewToken { .. } => self.new_token += 1,
Frame::MaxData(_) => self.max_data += 1,
Frame::MaxStreamData { .. } => self.max_stream_data += 1,
Frame::MaxStreams { dir, .. } => {
if *dir == Dir::Bi {
self.max_streams_bidi += 1;
} else {
self.max_streams_uni += 1;
}
}
Frame::DataBlocked { .. } => self.data_blocked += 1,
Frame::Stream(_) => self.stream += 1,
Frame::StreamDataBlocked { .. } => self.stream_data_blocked += 1,
Frame::StreamsBlocked { dir, .. } => {
if *dir == Dir::Bi {
self.streams_blocked_bidi += 1;
} else {
self.streams_blocked_uni += 1;
}
}
Frame::NewConnectionId(_) => self.new_connection_id += 1,
Frame::RetireConnectionId { .. } => self.retire_connection_id += 1,
Frame::PathChallenge(_) => self.path_challenge += 1,
Frame::PathResponse(_) => self.path_response += 1,
Frame::Close(_) => self.connection_close += 1,
Frame::HandshakeDone => self.handshake_done += 1,
Frame::Invalid { .. } => {}
}
}
}
impl std::fmt::Debug for FrameStats {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FrameStats")
.field("ACK", &self.acks)
.field("CONNECTION_CLOSE", &self.connection_close)
.field("CRYPTO", &self.crypto)
.field("DATA_BLOCKED", &self.data_blocked)
.field("DATAGRAM", &self.datagram)
.field("HANDSHAKE_DONE", &self.handshake_done)
.field("MAX_DATA", &self.max_data)
.field("MAX_STREAM_DATA", &self.max_stream_data)
.field("MAX_STREAMS_BIDI", &self.max_streams_bidi)
.field("MAX_STREAMS_UNI", &self.max_streams_uni)
.field("NEW_CONNECTION_ID", &self.new_connection_id)
.field("NEW_TOKEN", &self.new_token)
.field("PATH_CHALLENGE", &self.path_challenge)
.field("PATH_RESPONSE", &self.path_response)
.field("PING", &self.ping)
.field("RESET_STREAM", &self.reset_stream)
.field("RETIRE_CONNECTION_ID", &self.retire_connection_id)
.field("STREAM_DATA_BLOCKED", &self.stream_data_blocked)
.field("STREAMS_BLOCKED_BIDI", &self.streams_blocked_bidi)
.field("STREAMS_BLOCKED_UNI", &self.streams_blocked_uni)
.field("STOP_SENDING", &self.stop_sending)
.field("STREAM", &self.stream)
.finish()
}
}
#[derive(Debug, Default, Copy, Clone)]
#[non_exhaustive]
pub struct PathStats {
pub rtt: Duration,
pub cwnd: u64,
pub congestion_events: u64,
}
#[derive(Debug, Default, Copy, Clone)]
#[non_exhaustive]
pub struct ConnectionStats {
pub udp_tx: UdpStats,
pub udp_rx: UdpStats,
pub frame_tx: FrameStats,
pub frame_rx: FrameStats,
pub path: PathStats,
}