webrtc_ice/agent/
agent_stats.rs

1use std::sync::atomic::Ordering;
2
3use tokio::time::Instant;
4
5use crate::agent::agent_internal::AgentInternal;
6use crate::candidate::{CandidatePairState, CandidateType};
7use crate::network_type::NetworkType;
8
9/// Contains ICE candidate pair statistics.
10pub struct CandidatePairStats {
11    /// The timestamp associated with this struct.
12    pub timestamp: Instant,
13
14    /// The id of the local candidate.
15    pub local_candidate_id: String,
16
17    /// The id of the remote candidate.
18    pub remote_candidate_id: String,
19
20    /// The state of the checklist for the local and remote candidates in a pair.
21    pub state: CandidatePairState,
22
23    /// It is true when this valid pair that should be used for media,
24    /// if it is the highest-priority one amongst those whose nominated flag is set.
25    pub nominated: bool,
26
27    /// The total number of packets sent on this candidate pair.
28    pub packets_sent: u32,
29
30    /// The total number of packets received on this candidate pair.
31    pub packets_received: u32,
32
33    /// The total number of payload bytes sent on this candidate pair not including headers or
34    /// padding.
35    pub bytes_sent: u64,
36
37    /// The total number of payload bytes received on this candidate pair not including headers or
38    /// padding.
39    pub bytes_received: u64,
40
41    /// The timestamp at which the last packet was sent on this particular candidate pair, excluding
42    /// STUN packets.
43    pub last_packet_sent_timestamp: Instant,
44
45    /// The timestamp at which the last packet was received on this particular candidate pair,
46    /// excluding STUN packets.
47    pub last_packet_received_timestamp: Instant,
48
49    /// The timestamp at which the first STUN request was sent on this particular candidate pair.
50    pub first_request_timestamp: Instant,
51
52    /// The timestamp at which the last STUN request was sent on this particular candidate pair.
53    /// The average interval between two consecutive connectivity checks sent can be calculated with
54    /// (last_request_timestamp - first_request_timestamp) / requests_sent.
55    pub last_request_timestamp: Instant,
56
57    /// Timestamp at which the last STUN response was received on this particular candidate pair.
58    pub last_response_timestamp: Instant,
59
60    /// The sum of all round trip time measurements in seconds since the beginning of the session,
61    /// based on STUN connectivity check responses (responses_received), including those that reply
62    /// to requests that are sent in order to verify consent. The average round trip time can be
63    /// computed from total_round_trip_time by dividing it by responses_received.
64    pub total_round_trip_time: f64,
65
66    /// The latest round trip time measured in seconds, computed from both STUN connectivity checks,
67    /// including those that are sent for consent verification.
68    pub current_round_trip_time: f64,
69
70    /// It is calculated by the underlying congestion control by combining the available bitrate for
71    /// all the outgoing RTP streams using this candidate pair. The bitrate measurement does not
72    /// count the size of the IP or other transport layers like TCP or UDP. It is similar to the
73    /// TIAS defined in RFC 3890, i.e., it is measured in bits per second and the bitrate is
74    /// calculated over a 1 second window.
75    pub available_outgoing_bitrate: f64,
76
77    /// It is calculated by the underlying congestion control by combining the available bitrate for
78    /// all the incoming RTP streams using this candidate pair. The bitrate measurement does not
79    /// count the size of the IP or other transport layers like TCP or UDP. It is similar to the
80    /// TIAS defined in  RFC 3890, i.e., it is measured in bits per second and the bitrate is
81    /// calculated over a 1 second window.
82    pub available_incoming_bitrate: f64,
83
84    /// The number of times the circuit breaker is triggered for this particular 5-tuple,
85    /// ceasing transmission.
86    pub circuit_breaker_trigger_count: u32,
87
88    /// The total number of connectivity check requests received (including retransmissions).
89    /// It is impossible for the receiver to tell whether the request was sent in order to check
90    /// connectivity or check consent, so all connectivity checks requests are counted here.
91    pub requests_received: u64,
92
93    /// The total number of connectivity check requests sent (not including retransmissions).
94    pub requests_sent: u64,
95
96    /// The total number of connectivity check responses received.
97    pub responses_received: u64,
98
99    /// The total number of connectivity check responses sent. Since we cannot distinguish
100    /// connectivity check requests and consent requests, all responses are counted.
101    pub responses_sent: u64,
102
103    /// The total number of connectivity check request retransmissions received.
104    pub retransmissions_received: u64,
105
106    /// The total number of connectivity check request retransmissions sent.
107    pub retransmissions_sent: u64,
108
109    /// The total number of consent requests sent.
110    pub consent_requests_sent: u64,
111
112    /// The timestamp at which the latest valid STUN binding response expired.
113    pub consent_expired_timestamp: Instant,
114}
115
116impl Default for CandidatePairStats {
117    fn default() -> Self {
118        Self {
119            timestamp: Instant::now(),
120            local_candidate_id: String::new(),
121            remote_candidate_id: String::new(),
122            state: CandidatePairState::default(),
123            nominated: false,
124            packets_sent: 0,
125            packets_received: 0,
126            bytes_sent: 0,
127            bytes_received: 0,
128            last_packet_sent_timestamp: Instant::now(),
129            last_packet_received_timestamp: Instant::now(),
130            first_request_timestamp: Instant::now(),
131            last_request_timestamp: Instant::now(),
132            last_response_timestamp: Instant::now(),
133            total_round_trip_time: 0.0,
134            current_round_trip_time: 0.0,
135            available_outgoing_bitrate: 0.0,
136            available_incoming_bitrate: 0.0,
137            circuit_breaker_trigger_count: 0,
138            requests_received: 0,
139            requests_sent: 0,
140            responses_received: 0,
141            responses_sent: 0,
142            retransmissions_received: 0,
143            retransmissions_sent: 0,
144            consent_requests_sent: 0,
145            consent_expired_timestamp: Instant::now(),
146        }
147    }
148}
149
150/// Contains ICE candidate statistics related to the `ICETransport` objects.
151#[derive(Debug, Clone)]
152pub struct CandidateStats {
153    // The timestamp associated with this struct.
154    pub timestamp: Instant,
155
156    /// The candidate id.
157    pub id: String,
158
159    /// The type of network interface used by the base of a local candidate (the address the ICE
160    /// agent sends from). Only present for local candidates; it's not possible to know what type of
161    /// network interface a remote candidate is using.
162    ///
163    /// Note: This stat only tells you about the network interface used by the first "hop"; it's
164    /// possible that a connection will be bottlenecked by another type of network.  For example,
165    /// when using Wi-Fi tethering, the networkType of the relevant candidate would be "wifi", even
166    /// when the next hop is over a cellular connection.
167    pub network_type: NetworkType,
168
169    /// The IP address of the candidate, allowing for IPv4 addresses and IPv6 addresses, but fully
170    /// qualified domain names (FQDNs) are not allowed.
171    pub ip: String,
172
173    /// The port number of the candidate.
174    pub port: u16,
175
176    /// The `Type` field of the ICECandidate.
177    pub candidate_type: CandidateType,
178
179    /// The `priority` field of the ICECandidate.
180    pub priority: u32,
181
182    /// The url of the TURN or STUN server indicated in the that translated this IP address.
183    /// It is the url address surfaced in an PeerConnectionICEEvent.
184    pub url: String,
185
186    /// The protocol used by the endpoint to communicate with the TURN server. This is only present
187    /// for local candidates. Valid values for the TURN url protocol is one of udp, tcp, or tls.
188    pub relay_protocol: String,
189
190    /// It is true if the candidate has been deleted/freed. For host candidates, this means that any
191    /// network resources (typically a socket) associated with the candidate have been released. For
192    /// TURN candidates, this means the TURN allocation is no longer active.
193    ///
194    /// Only defined for local candidates. For remote candidates, this property is not applicable.
195    pub deleted: bool,
196}
197
198impl Default for CandidateStats {
199    fn default() -> Self {
200        Self {
201            timestamp: Instant::now(),
202            id: String::new(),
203            network_type: NetworkType::default(),
204            ip: String::new(),
205            port: 0,
206            candidate_type: CandidateType::default(),
207            priority: 0,
208            url: String::new(),
209            relay_protocol: String::new(),
210            deleted: false,
211        }
212    }
213}
214
215impl AgentInternal {
216    /// Returns a list of candidate pair stats.
217    pub(crate) async fn get_candidate_pairs_stats(&self) -> Vec<CandidatePairStats> {
218        let checklist = self.agent_conn.checklist.lock().await;
219        let mut res = Vec::with_capacity(checklist.len());
220        for cp in &*checklist {
221            let stat = CandidatePairStats {
222                timestamp: Instant::now(),
223                local_candidate_id: cp.local.id(),
224                remote_candidate_id: cp.remote.id(),
225                state: cp.state.load(Ordering::SeqCst).into(),
226                nominated: cp.nominated.load(Ordering::SeqCst),
227                ..CandidatePairStats::default()
228            };
229            res.push(stat);
230        }
231        res
232    }
233
234    /// Returns a list of local candidates stats.
235    pub(crate) async fn get_local_candidates_stats(&self) -> Vec<CandidateStats> {
236        let local_candidates = self.local_candidates.lock().await;
237        let mut res = Vec::with_capacity(local_candidates.len());
238        for (network_type, local_candidates) in &*local_candidates {
239            for c in local_candidates {
240                let stat = CandidateStats {
241                    timestamp: Instant::now(),
242                    id: c.id(),
243                    network_type: *network_type,
244                    ip: c.address(),
245                    port: c.port(),
246                    candidate_type: c.candidate_type(),
247                    priority: c.priority(),
248                    // URL string
249                    relay_protocol: "udp".to_owned(),
250                    // Deleted bool
251                    ..CandidateStats::default()
252                };
253                res.push(stat);
254            }
255        }
256        res
257    }
258
259    /// Returns a list of remote candidates stats.
260    pub(crate) async fn get_remote_candidates_stats(&self) -> Vec<CandidateStats> {
261        let remote_candidates = self.remote_candidates.lock().await;
262        let mut res = Vec::with_capacity(remote_candidates.len());
263        for (network_type, remote_candidates) in &*remote_candidates {
264            for c in remote_candidates {
265                let stat = CandidateStats {
266                    timestamp: Instant::now(),
267                    id: c.id(),
268                    network_type: *network_type,
269                    ip: c.address(),
270                    port: c.port(),
271                    candidate_type: c.candidate_type(),
272                    priority: c.priority(),
273                    // URL string
274                    relay_protocol: "udp".to_owned(),
275                    // Deleted bool
276                    ..CandidateStats::default()
277                };
278                res.push(stat);
279            }
280        }
281        res
282    }
283}