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