medea_client_api_proto/stats.rs
1//! Contains DTOs for [RTCPeerConnection] metrics.
2//!
3//! [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
4
5// TODO: Needs refactoring.
6#![expect(clippy::module_name_repetitions, reason = "needs refactoring")]
7
8use std::{
9 hash::{Hash, Hasher},
10 time::{Duration, SystemTime, SystemTimeError},
11};
12
13use derive_more::with_trait::{Display, From};
14use serde::{Deserialize, Serialize};
15
16/// Enum with which you can try to deserialize some known enum and if it
17/// isn't known, then unknown data will be stored as [`String`] in the
18/// [`NonExhaustive::Unknown`] variant.
19#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
20#[serde(untagged)]
21pub enum NonExhaustive<T> {
22 /// Will store known enum variant if it successfully deserialized.
23 Known(T),
24
25 /// Will store unknown enum variant with it's data as [`String`].
26 Unknown(String),
27}
28
29/// Unique ID that is associated with the object that was inspected to produce
30/// [`RtcStat`] object.
31///
32/// Two [`RtcStat`]s objects, extracted from two different [RTCStatsReport]
33/// objects, MUST have the same ID if they were produced by inspecting the same
34/// underlying object.
35///
36/// [RTCStatsReport]: https://w3.org/TR/webrtc#dom-rtcstatsreport
37#[derive(
38 Clone, Debug, Deserialize, Display, Eq, From, Hash, PartialEq, Serialize,
39)]
40#[from(forward)]
41pub struct StatId(pub String);
42
43/// Represents the [stats object] constructed by inspecting a specific
44/// [monitored object].
45///
46/// [Full doc on W3C][1].
47///
48/// [stats object]: https://w3.org/TR/webrtc-stats/#dfn-stats-object
49/// [monitored object]: https://w3.org/TR/webrtc-stats/#dfn-monitored-object
50/// [1]: https://w3.org/TR/webrtc#rtcstats-dictionary
51#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
52pub struct RtcStat {
53 /// Unique ID that is associated with the object that was inspected to
54 /// produce this [RTCStats] object.
55 ///
56 /// [RTCStats]: https://w3.org/TR/webrtc#dom-rtcstats
57 pub id: StatId,
58
59 /// Timestamp associated with this object.
60 ///
61 /// The time is relative to the UNIX epoch (Jan 1, 1970, UTC).
62 ///
63 /// For statistics that came from a remote source (e.g., from received RTCP
64 /// packets), timestamp represents the time at which the information
65 /// arrived at the local endpoint. The remote timestamp can be found in an
66 /// additional field in an [`RtcStat`]-derived dictionary, if applicable.
67 pub timestamp: HighResTimeStamp,
68
69 /// Actual stats of this [`RtcStat`].
70 ///
71 /// All possible stats are described in the [`RtcStatsType`] enum.
72 #[serde(flatten)]
73 pub stats: RtcStatsType,
74}
75
76/// All known types of [`RtcStat`]s.
77///
78/// [List of all RTCStats types on W3C][1].
79///
80/// [1]: https://w3.org/TR/webrtc-stats/#rtctatstype-%2A
81/// [`RtcStat`]: super::RtcStat
82#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
83#[serde(tag = "type", rename_all = "kebab-case")]
84pub enum RtcStatsType {
85 /// Statistics for a codec that is currently used by [RTP] streams
86 /// being sent or received by [RTCPeerConnection] object.
87 ///
88 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
89 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
90 #[cfg(feature = "extended-stats")]
91 Codec(Box<RtcCodecStats>),
92
93 /// Statistics for an inbound [RTP] stream that is currently received
94 /// with [RTCPeerConnection] object.
95 ///
96 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
97 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
98 InboundRtp(Box<RtcInboundRtpStreamStats>),
99
100 /// Statistics for an outbound [RTP] stream that is currently sent with
101 /// [RTCPeerConnection] object.
102 ///
103 /// When there are multiple [RTP] streams connected to the same sender,
104 /// such as when using simulcast or RTX, there will be one
105 /// [`RtcOutboundRtpStreamStats`] per RTP stream, with distinct values
106 /// of the `ssrc` attribute, and all these senders will have a
107 /// reference to the same "sender" object (of type
108 /// [RTCAudioSenderStats][1] or [RTCVideoSenderStats][2]) and
109 /// "track" object (of type
110 /// [RTCSenderAudioTrackAttachmentStats][3] or
111 /// [RTCSenderVideoTrackAttachmentStats][4]).
112 ///
113 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
114 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
115 /// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcaudiosenderstats
116 /// [2]: https://w3.org/TR/webrtc-stats/#dom-rtcvideosenderstats
117 /// [3]: https://tinyurl.com/sefa5z4
118 /// [4]: https://tinyurl.com/rkuvpl4
119 OutboundRtp(Box<RtcOutboundRtpStreamStats>),
120
121 /// Statistics for the remote endpoint's inbound [RTP] stream
122 /// corresponding to an outbound stream that is currently sent with
123 /// [RTCPeerConnection] object.
124 ///
125 /// It is measured at the remote endpoint and reported in a RTCP
126 /// Receiver Report (RR) or RTCP Extended Report (XR).
127 ///
128 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
129 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
130 RemoteInboundRtp(Box<RtcRemoteInboundRtpStreamStats>),
131
132 /// Statistics for the remote endpoint's outbound [RTP] stream
133 /// corresponding to an inbound stream that is currently received with
134 /// [RTCPeerConnection] object.
135 ///
136 /// It is measured at the remote endpoint and reported in an RTCP
137 /// Sender Report (SR).
138 ///
139 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
140 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
141 RemoteOutboundRtp(Box<RtcRemoteOutboundRtpStreamStats>),
142
143 /// Statistics for the media produced by a [MediaStreamTrack][1] that
144 /// is currently attached to an [RTCRtpSender]. This reflects
145 /// the media that is fed to the encoder after [getUserMedia]
146 /// constraints have been applied (i.e. not the raw media
147 /// produced by the camera).
148 ///
149 /// [RTCRtpSender]: https://w3.org/TR/webrtc#rtcrtpsender-interface
150 /// [getUserMedia]: https://tinyurl.com/sngpyr6
151 /// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
152 MediaSource(Box<MediaSourceStats>),
153
154 /// Statistics for a contributing source (CSRC) that contributed to an
155 /// inbound [RTP] stream.
156 ///
157 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
158 #[cfg(feature = "extended-stats")]
159 Csrc(Box<RtpContributingSourceStats>),
160
161 /// Statistics related to the [RTCPeerConnection] object.
162 ///
163 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
164 #[cfg(feature = "extended-stats")]
165 PeerConnection(Box<RtcPeerConnectionStats>),
166
167 /// Statistics related to each [RTCDataChannel] ID.
168 ///
169 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
170 #[cfg(feature = "extended-stats")]
171 DataChannel(Box<DataChannelStats>),
172
173 /// Contains statistics related to a specific [MediaStream].
174 ///
175 /// This is now obsolete.
176 ///
177 /// [MediaStream]: https://w3.org/TR/mediacapture-streams#mediastream
178 #[cfg(feature = "extended-stats")]
179 Stream(Box<MediaStreamStats>),
180
181 /// Statistics related to a specific [MediaStreamTrack][1]'s attachment
182 /// to an [RTCRtpSender] and the corresponding media-level
183 /// metrics.
184 ///
185 /// [RTCRtpSender]: https://w3.org/TR/webrtc#rtcrtpsender-interface
186 /// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
187 Track(Box<TrackStats>),
188
189 /// Statistics related to a specific [RTCRtpTransceiver].
190 ///
191 /// [RTCRtpTransceiver]: https://w3.org/TR/webrtc#dom-rtcrtptransceiver
192 #[cfg(feature = "extended-stats")]
193 Transceiver(Box<RtcRtpTransceiverStats>),
194
195 /// Statistics related to a specific [RTCRtpSender] and the
196 /// corresponding media-level metrics.
197 ///
198 /// [RTCRtpSender]: https://w3.org/TR/webrtc#rtcrtpsender-interface
199 #[cfg(feature = "extended-stats")]
200 Sender(Box<SenderStatsKind>),
201
202 /// Statistics related to a specific [RTCRtpReceiver] and the
203 /// corresponding media-level metrics.
204 ///
205 /// [RTCRtpReceiver]: https://w3.org/TR/webrtc#dom-rtcrtpreceiver
206 #[cfg(feature = "extended-stats")]
207 Receiver(Box<ReceiverStatsKind>),
208
209 /// Transport statistics related to the [RTCPeerConnection] object.
210 ///
211 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
212 Transport(Box<RtcTransportStats>),
213
214 /// SCTP transport statistics related to an [RTCSctpTransport] object.
215 ///
216 /// [RTCSctpTransport]: https://w3.org/TR/webrtc#dom-rtcsctptransport
217 SctpTransport(Box<RtcSctpTransportStats>),
218
219 /// ICE candidate pair statistics related to the [RTCIceTransport]
220 /// objects.
221 ///
222 /// A candidate pair that is not the current pair for a transport is
223 /// [deleted][1] when the [RTCIceTransport] does an ICE restart, at the
224 /// time the state changes to `new`.
225 ///
226 /// The candidate pair that is the current pair for a transport is
227 /// deleted after an ICE restart when the [RTCIceTransport]
228 /// switches to using a candidate pair generated from the new
229 /// candidates; this time doesn't correspond to any other
230 /// externally observable event.
231 ///
232 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
233 /// [1]: https://w3.org/TR/webrtc-stats/#dfn-deleted
234 CandidatePair(Box<RtcIceCandidatePairStats>),
235
236 /// ICE local candidate statistics related to the [RTCIceTransport]
237 /// objects.
238 ///
239 /// A local candidate is [deleted][1] when the [RTCIceTransport] does
240 /// an ICE restart, and the candidate is no longer a member of
241 /// any non-deleted candidate pair.
242 ///
243 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
244 /// [1]: https://w3.org/TR/webrtc-stats/#dfn-deleted
245 LocalCandidate(Box<RtcIceCandidateStats>),
246
247 /// ICE remote candidate statistics related to the [RTCIceTransport]
248 /// objects.
249 ///
250 /// A remote candidate is [deleted][1] when the [RTCIceTransport] does
251 /// an ICE restart, and the candidate is no longer a member of
252 /// any non-deleted candidate pair.
253 ///
254 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
255 /// [1]: https://w3.org/TR/webrtc-stats/#dfn-deleted
256 RemoteCandidate(Box<RtcIceCandidateStats>),
257
258 /// Information about a certificate used by [RTCIceTransport].
259 ///
260 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
261 #[cfg(feature = "extended-stats")]
262 Certificate(Box<RtcCertificateStats>),
263
264 /// Information about the connection to an ICE server (e.g. STUN or
265 /// TURN).
266 #[cfg(feature = "extended-stats")]
267 IceServer(Box<RtcIceServerStats>),
268
269 /// Disabled or unknown variants of stats will be deserialized as
270 /// [`RtcStatsType::Other`].
271 #[serde(other)]
272 Other,
273}
274
275#[cfg(feature = "extended-stats")]
276/// Contains statistics related to a specific [MediaStream].
277///
278/// This is now obsolete.
279///
280/// [`RtcStatsType::Stream`] variant.
281///
282/// [Full doc on W3C][1].
283///
284/// [MediaStream]: https://w3.org/TR/mediacapture-streams#mediastream
285/// [1]: https://w3.org/TR/webrtc-stats/#idl-def-rtcmediastreamstats
286#[serde_with::skip_serializing_none]
287#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
288#[serde(rename_all = "camelCase")]
289pub struct MediaStreamStats {
290 /// [`stream.id`][1] property.
291 ///
292 /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastream-id
293 pub stream_identifier: String,
294
295 /// ID of the stats object, not the `track.id`.
296 pub track_ids: Vec<StatId>,
297}
298
299#[cfg(feature = "extended-stats")]
300/// Statistics related to each [RTCDataChannel] ID.
301///
302/// [`RtcStatsType::DataChannel`] variant.
303///
304/// [Full doc on W3C][1].
305///
306/// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
307/// [1]: https://w3.org/TR/webrtc-stats/#dcstats-dict%2A
308#[serde_with::skip_serializing_none]
309#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
310#[serde(rename_all = "camelCase")]
311pub struct DataChannelStats {
312 /// [`label`][1] value of the [RTCDataChannel] object.
313 ///
314 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
315 /// [1]: https://w3.org/TR/webrtc#dom-datachannel-label
316 pub label: Option<String>,
317
318 /// [`protocol`][1] value of the [RTCDataChannel] object.
319 ///
320 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
321 /// [1]: https://w3.org/TR/webrtc#dom-datachannel-protocol
322 pub protocol: Option<Protocol>,
323
324 /// [`id`][1] attribute of the [RTCDataChannel] object.
325 ///
326 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
327 /// [1]: https://w3.org/TR/webrtc#dom-rtcdatachannel-id
328 pub data_channel_identifier: Option<u64>,
329
330 /// [Stats object reference][1] for the transport used to carry
331 /// [RTCDataChannel].
332 ///
333 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
334 /// [1]: https://w3.org/TR/webrtc-stats/#dfn-stats-object-reference
335 pub transport_id: Option<String>,
336
337 /// [`readyState`][1] value of the [RTCDataChannel] object.
338 ///
339 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
340 /// [1]: https://w3.org/TR/webrtc#dom-datachannel-readystate
341 pub state: Option<DataChannelState>,
342
343 /// Total number of API `message` events sent.
344 pub messages_sent: Option<u64>,
345
346 /// Total number of payload bytes sent on this [RTCDataChannel], i.e. not
347 /// including headers or padding.
348 ///
349 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
350 pub bytes_sent: Option<u64>,
351
352 /// Total number of API `message` events received.
353 pub messages_received: Option<u64>,
354
355 /// Total number of bytes received on this [RTCDataChannel], i.e. not
356 /// including headers or padding.
357 ///
358 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
359 pub bytes_received: Option<u64>,
360}
361
362/// Non-exhaustive version of [`KnownDataChannelState`].
363pub type DataChannelState = NonExhaustive<KnownDataChannelState>;
364
365/// State of the [RTCDataChannel]'s underlying data connection.
366///
367/// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
368#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
369#[serde(rename_all = "kebab-case")]
370pub enum KnownDataChannelState {
371 /// User agent is attempting to establish the underlying data transport.
372 /// This is the initial state of [RTCDataChannel] object, whether created
373 /// with [createDataChannel][1], or dispatched as a part of an
374 /// [RTCDataChannelEvent].
375 ///
376 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
377 /// [RTCDataChannelEvent]: https://w3.org/TR/webrtc#dom-rtcdatachannelevent
378 /// [1]: https://w3.org/TR/webrtc#dom-peerconnection-createdatachannel
379 Connecting,
380
381 /// [Underlying data transport][1] is established and communication is
382 /// possible.
383 ///
384 /// [1]: https://w3.org/TR/webrtc#dfn-data-transport
385 Open,
386
387 /// [`procedure`][2] to close down the [underlying data transport][1] has
388 /// started.
389 ///
390 /// [1]: https://w3.org/TR/webrtc#dfn-data-transport
391 /// [2]: https://w3.org/TR/webrtc#data-transport-closing-procedure
392 Closing,
393
394 /// [Underlying data transport][1] has been [`closed`][2] or could not be
395 /// established.
396 ///
397 /// [1]: https://w3.org/TR/webrtc#dfn-data-transport
398 /// [2]: https://w3.org/TR/webrtc#dom-rtcdatachannelstate-closed
399 Closed,
400}
401
402#[cfg(feature = "extended-stats")]
403/// Stats for the [RTCPeerConnection] object.
404///
405/// [`RtcStatsType::PeerConnection`] variant.
406///
407/// [Full doc on W3C][1].
408///
409/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
410/// [1]: https://w3.org/TR/webrtc-stats/#pcstats-dict%2A
411#[serde_with::skip_serializing_none]
412#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
413#[serde(rename_all = "camelCase")]
414pub struct RtcPeerConnectionStats {
415 /// Number of unique `DataChannel`s that have entered the `open` state
416 /// during their lifetime.
417 pub data_channels_opened: Option<u64>,
418
419 /// Number of unique `DataChannel`s that have left the `open` state during
420 /// their lifetime (due to being closed by either end or the underlying
421 /// transport being closed). `DataChannel`s that transition from
422 /// `connecting` to `closing` or `closed` without ever being `open` are not
423 /// counted in this number.
424 pub data_channels_closed: Option<u64>,
425
426 /// Number of unique `DataChannel`s returned from a successful
427 /// [createDataChannel][1] call on the [RTCPeerConnection].
428 /// If the underlying data transport is not established, these may be in
429 /// the `connecting` state.
430 ///
431 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
432 /// [1]: https://w3.org/TR/webrtc#dom-peerconnection-createdatachannel
433 pub data_channels_requested: Option<u64>,
434
435 /// Number of unique `DataChannel`s signaled in a `datachannel` event on
436 /// the [RTCPeerConnection].
437 ///
438 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
439 pub data_channels_accepted: Option<u64>,
440}
441
442#[cfg(feature = "extended-stats")]
443/// Statistics for a contributing source (CSRC) that contributed to an inbound
444/// [RTP] stream.
445///
446/// [`RtcStatsType::Csrc`] variant.
447///
448/// [Full doc on W3C][1].
449///
450/// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
451/// [1]: https://w3.org/TR/webrtc-stats/#contributingsourcestats-dict%2A
452#[serde_with::skip_serializing_none]
453#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
454#[serde(rename_all = "camelCase")]
455pub struct RtpContributingSourceStats {
456 /// SSRC identifier of the contributing source represented by the stats
457 /// object, as defined by [RFC 3550]. It is a 32-bit unsigned integer that
458 /// appears in the CSRC list of any packets the relevant source contributed
459 /// to.
460 ///
461 /// [RFC 3550]: https://tools.ietf.org/html/rfc3550
462 pub contributor_ssrc: Option<u32>,
463
464 /// ID of the [RTCInboundRtpStreamStats][1] object representing the inbound
465 /// [RTP] stream that this contributing source is contributing to.
466 ///
467 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
468 /// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats
469 pub inbound_rtp_stream_id: Option<String>,
470
471 /// Total number of [RTP] packets that this contributing source contributed
472 /// to.
473 ///
474 /// This value is incremented each time a packet is counted by
475 /// [RTCInboundRtpStreamStats.packetsReceived][2], and the packet's CSRC
476 /// list (as defined by [Section 5.1 in RFC 3550][3]) contains the SSRC
477 /// identifier of this contributing source, [`contributorSsrc`].
478 ///
479 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
480 /// [`contributorSsrc`]: https://tinyurl.com/tf8c7j4
481 /// [2]: https://tinyurl.com/rreuf49
482 /// [3]: https://tools.ietf.org/html/rfc3550#section-5.1
483 pub packets_contributed_to: Option<u64>,
484
485 /// Present if the last received RTP packet that this source contributed to
486 /// contained an [RFC 6465] mixer-to-client audio level header extension.
487 ///
488 /// The value of [`audioLevel`] is between `0..1` (linear), where `1.0`
489 /// represents `0 dBov`, `0` represents silence, and `0.5` represents
490 /// approximately `6 dBSPL` change in the sound pressure level from 0
491 /// dBov. The [RFC 6465] header extension contains values in the range
492 /// `0..127`, in units of `-dBov`, where `127` represents silence. To
493 /// convert these values to the linear `0..1` range of `audioLevel`, a
494 /// value of `127` is converted to `0`, and all other values are
495 /// converted using the equation:
496 ///
497 /// `f(rfc6465_level) = 10^(-rfc6465_level/20)`
498 ///
499 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
500 /// [RFC 6465]: https://tools.ietf.org/html/rfc6465
501 /// [`audioLevel`]: https://tinyurl.com/sfy699q
502 pub audio_level: Option<Float>,
503}
504
505/// Statistics for the remote endpoint's outbound [RTP] stream corresponding
506/// to an inbound stream that is currently received with [RTCPeerConnection]
507/// object.
508///
509/// It is measured at the remote endpoint and reported in an RTCP Sender Report
510/// (SR).
511///
512/// [`RtcStatsType::RemoteOutboundRtp`] variant.
513///
514/// [Full doc on W3C][1].
515///
516/// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
517/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
518/// [1]: https://w3.org/TR/webrtc-stats/#remoteoutboundrtpstats-dict%2A
519#[serde_with::skip_serializing_none]
520#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
521#[serde(rename_all = "camelCase")]
522pub struct RtcRemoteOutboundRtpStreamStats {
523 /// [`localId`] is used for looking up the local
524 /// [RTCInboundRtpStreamStats][1] object for the same SSRC.
525 ///
526 /// [`localId`]: https://tinyurl.com/vu9tb2e
527 /// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats
528 pub local_id: Option<String>,
529
530 /// [`remoteTimestamp`] (as [HIGHRES-TIME]) is the remote timestamp at
531 /// which these statistics were sent by the remote endpoint. This
532 /// differs from timestamp, which represents the time at which the
533 /// statistics were generated or received by the local endpoint. The
534 /// [`remoteTimestamp`], if present, is derived from the NTP timestamp
535 /// in an RTCP Sender Report (SR) block, which reflects the remote
536 /// endpoint's clock. That clock may not be synchronized with the local
537 /// clock.
538 ///
539 /// [`remoteTimestamp`]: https://tinyurl.com/rzlhs87
540 /// [HIGRES-TIME]: https://w3.org/TR/webrtc-stats/#bib-highres-time
541 pub remote_timestamp: Option<HighResTimeStamp>,
542
543 /// Total number of RTCP SR blocks sent for this SSRC.
544 pub reports_sent: Option<u64>,
545}
546
547/// Statistics for the remote endpoint's inbound [RTP] stream corresponding
548/// to an outbound stream that is currently sent with [RTCPeerConnection]
549/// object.
550///
551/// It is measured at the remote endpoint and reported in a RTCP Receiver
552/// Report (RR) or RTCP Extended Report (XR).
553///
554/// [`RtcStatsType::RemoteInboundRtp`] variant.
555///
556/// [Full doc on W3C][1].
557///
558/// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
559/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
560/// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats
561#[serde_with::skip_serializing_none]
562#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
563#[serde(rename_all = "camelCase")]
564pub struct RtcRemoteInboundRtpStreamStats {
565 /// [`localId`] is used for looking up the local
566 /// [RTCOutboundRtpStreamStats] object for the same SSRC.
567 ///
568 /// [`localId`]: https://tinyurl.com/r8uhbo9
569 /// [RTCOutBoundRtpStreamStats]: https://tinyurl.com/r6f5vqg
570 pub local_id: Option<String>,
571
572 /// Packet [jitter] measured in seconds for this SSRC.
573 ///
574 /// [jitter]: https://en.wikipedia.org/wiki/Jitter
575 pub jitter: Option<Float>,
576
577 /// Estimated round trip time for this SSRC based on the RTCP timestamps in
578 /// the RTCP Receiver Report (RR) and measured in seconds. Calculated as
579 /// defined in [Section 6.4.1 of RFC 3550][1]. If no RTCP Receiver Report
580 /// is received with a DLSR value other than 0, the round trip time is
581 /// left undefined.
582 ///
583 /// [1]: https://tools.ietf.org/html/rfc3550#section-6.4.1
584 pub round_trip_time: Option<Float>,
585
586 /// Fraction packet loss reported for this SSRC. Calculated as defined in
587 /// [Section 6.4.1 of RFC 3550][1] and [Appendix A.3][2].
588 ///
589 /// [1]: https://tools.ietf.org/html/rfc3550#section-6.4.1
590 /// [2]: https://tools.ietf.org/html/rfc3550#appendix-A.3
591 pub fraction_lost: Option<Float>,
592
593 /// Total number of RTCP RR blocks received for this SSRC.
594 pub reports_received: Option<u64>,
595
596 /// Total number of RTCP RR blocks received for this SSRC that contain a
597 /// valid round trip time. This counter will increment if the
598 /// [`roundTripTime`] is undefined.
599 ///
600 /// [`roundTripTime`]: https://tinyurl.com/ssg83hq
601 pub round_trip_time_measurements: Option<Float>,
602}
603
604#[cfg(feature = "extended-stats")]
605/// [RTCRtpTransceiverStats][1] object representing an [RTCRtpTransceiver] of an
606/// [RTCPeerConnection].
607///
608/// It appears as soon as the monitored [RTCRtpTransceiver] object is created,
609/// such as by invoking [addTransceiver][2], [addTrack][3] or
610/// [setRemoteDescription][4]. [RTCRtpTransceiverStats][1] objects can only be
611/// deleted if the corresponding [RTCRtpTransceiver] is removed (this can only
612/// happen if a remote description is rolled back).
613///
614/// [`RtcStatsType::Transceiver`] variant.
615///
616/// [Full doc on W3C][1].
617///
618/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
619/// [RTCRtpTransceiver]: https://w3.org/TR/webrtc#dom-rtcrtptransceiver
620/// [1]: https://w3.org/TR/webrtc-stats/#transceiver-dict%2A
621/// [2]: https://w3.org/TR/webrtc#dom-rtcpeerconnection-addtransceiver
622/// [3]: https://w3.org/TR/webrtc#dom-rtcpeerconnection-addtrack
623/// [4]: https://tinyurl.com/vejym8v
624#[serde_with::skip_serializing_none]
625#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
626#[serde(rename_all = "camelCase")]
627pub struct RtcRtpTransceiverStats {
628 /// ID of the stats object representing the
629 /// [RTCRtpSender associated with the RTCRtpTransceiver][1] represented by
630 /// this stats object.
631 ///
632 /// [1]: https://w3.org/TR/webrtc#dom-rtcrtptransceiver-sender
633 pub sender_id: Option<String>,
634
635 /// ID of the stats object representing the
636 /// [RTCRtpReceiver associated with the RTCRtpTransceiver][1] represented
637 /// by this stats object.
638 ///
639 /// [1]: https://w3.org/TR/webrtc#dom-rtcrtptransceiver-receiver
640 pub receiver_id: Option<String>,
641
642 /// If the [RTCRtpTransceiver] that this stats object represents has a
643 /// [`mid` value][1] that is not null, this is that value, otherwise this
644 /// value is undefined.
645 ///
646 /// [RTCRtpTransceiver]: https://w3.org/TR/webrtc#dom-rtcrtptransceiver
647 /// [1]: https://w3.org/TR/webrtc#dom-rtptransceiver-mid
648 pub mid: Option<String>,
649}
650
651/// Representation of the stats corresponding to an [RTCSctpTransport].
652///
653/// [`RtcStatsType::SctpTransport`] variant.
654///
655/// [Full doc on W3C][1].
656///
657/// [RTCSctpTransport]: https://w3.org/TR/webrtc#dom-rtcsctptransport
658/// [1]: https://w3.org/TR/webrtc-stats/#sctptransportstats-dict%2A
659#[serde_with::skip_serializing_none]
660#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Serialize)]
661#[serde(rename_all = "camelCase")]
662pub struct RtcSctpTransportStats {
663 /// Latest smoothed round-trip time value, corresponding to
664 /// [`spinfo_srtt` defined in RFC 6458][1] but converted to seconds.
665 ///
666 /// If there has been no round-trip time measurements yet, this value is
667 /// undefined.
668 ///
669 /// [1]: https://tools.ietf.org/html/rfc6458#page-83
670 pub smoothed_round_trip_time: Option<HighResTimeStamp>,
671}
672
673/// Representation of the stats corresponding to an [RTCDtlsTransport] and its
674/// underlying [RTCIceTransport].
675///
676/// When RTCP multiplexing is used, one transport is used for both RTP and RTCP.
677/// Otherwise, RTP and RTCP will be sent on separate transports, and
678/// `rtcpTransportStatsId` can be used to pair the resulting
679/// [`RtcTransportStats`] objects. Additionally, when bundling is used, a single
680/// transport will be used for all [MediaStreamTrack][2]s in the bundle group.
681/// If bundling is not used, different [MediaStreamTrack][2]s will use different
682/// transports. RTCP multiplexing and bundling are described in [WebRTC].
683///
684/// [`RtcStatsType::Transport`] variant.
685///
686/// [Full doc on W3C][1].
687///
688/// [RTCDtlsTransport]: https://w3.org/TR/webrtc#dom-rtcdtlstransport
689/// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
690/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
691/// [WebRTC]: https://w3.org/TR/webrtc
692/// [1]: https://w3.org/TR/webrtc-stats/#transportstats-dict%2A
693/// [2]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
694#[serde_with::skip_serializing_none]
695#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
696#[serde(rename_all = "camelCase")]
697pub struct RtcTransportStats {
698 /// Total number of packets sent over this transport.
699 pub packets_sent: Option<u64>,
700
701 /// Total number of packets received on this transport.
702 pub packets_received: Option<u64>,
703
704 /// Total number of payload bytes sent on this [RTCPeerConnection], i.e.
705 /// not including headers or padding.
706 ///
707 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
708 pub bytes_sent: Option<u64>,
709
710 /// Total number of bytes received on this [RTCPeerConnection], i.e. not
711 /// including headers or padding.
712 ///
713 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
714 pub bytes_received: Option<u64>,
715
716 /// Set to the current value of the [`role` attribute][1] of the
717 /// [underlying RTCDtlsTransport's `transport`][2].
718 ///
719 /// [1]: https://w3.org/TR/webrtc#dom-icetransport-role
720 /// [2]: https://w3.org/TR/webrtc#dom-rtcdtlstransport-icetransport
721 pub ice_role: Option<IceRole>,
722}
723
724/// Variants of [ICE roles][1].
725///
726/// More info in the [RFC 5245].
727///
728/// [RFC 5245]: https://tools.ietf.org/html/rfc5245
729/// [1]: https://w3.org/TR/webrtc#dom-icetransport-role
730#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
731#[serde(rename_all = "camelCase")]
732pub enum IceRole {
733 /// Agent whose role as defined by [Section 3 in RFC 5245][1], has not yet
734 /// been determined.
735 ///
736 /// [1]: https://tools.ietf.org/html/rfc5245#section-3
737 Unknown,
738
739 /// Controlling agent as defined by [Section 3 in RFC 5245][1].
740 ///
741 /// [1]: https://tools.ietf.org/html/rfc5245#section-3
742 Controlling,
743
744 /// Controlled agent as defined by [Section 3 in RFC 5245][1].
745 ///
746 /// [1]: https://tools.ietf.org/html/rfc5245#section-3
747 Controlled,
748}
749
750#[cfg(feature = "extended-stats")]
751/// Statistics related to a specific [RTCRtpSender] and the corresponding
752/// media-level metrics.
753///
754/// [`RtcStatsType::Sender`] variant.
755///
756/// [Full doc on W3C][1].
757///
758/// [RTCRtpSender]: https://w3.org/TR/webrtc#rtcrtpsender-interface
759/// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcstatstype-sender
760#[serde_with::skip_serializing_none]
761#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
762#[serde(tag = "kind", rename_all = "camelCase")]
763pub enum SenderStatsKind {
764 /// [RTCAudioSenderStats][1] object.
765 ///
766 /// [1]: https://tinyurl.com/w5ow5xs
767 Audio {
768 /// ID of the related media source.
769 media_source_id: Option<String>,
770 },
771
772 /// [RTCVideoSenderStats][1] object.
773 ///
774 /// [1]: https://tinyurl.com/ry39vnw
775 Video {
776 /// ID of the related media source.
777 media_source_id: Option<String>,
778 },
779}
780
781#[cfg(feature = "extended-stats")]
782/// Statistics related to a specific [RTCRtpReceiver] and the corresponding
783/// media-level metrics.
784///
785/// [`RtcStatsType::Receiver`] variant.
786///
787/// [Full doc on W3C][1].
788///
789/// [RTCRtpReceiver]: https://w3.org/TR/webrtc#dom-rtcrtpreceiver
790/// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcstatstype-receiver
791#[expect( // required by `serde`
792 clippy::empty_enum_variants_with_brackets,
793 reason = "required by `serde`"
794)]
795#[serde_with::skip_serializing_none]
796#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
797#[serde(tag = "kind", rename_all = "camelCase")]
798pub enum ReceiverStatsKind {
799 /// [RTCAudioReceiverStats] object.
800 ///
801 /// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcaudioreceiverstats
802 Audio {},
803
804 /// [RTCVideoReceiverStats] object.
805 ///
806 /// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcvideoreceiverstats
807 Video {},
808}
809
810/// ICE candidate pair statistics related to the [RTCIceTransport] objects.
811///
812/// A candidate pair that is not the current pair for a transport is
813/// [deleted][1] when the [RTCIceTransport] does an ICE restart, at the time
814/// the state changes to `new`.
815///
816/// The candidate pair that is the current pair for a transport is deleted after
817/// an ICE restart when the [RTCIceTransport] switches to using a candidate pair
818/// generated from the new candidates; this time doesn't correspond to any other
819/// externally observable event.
820///
821/// [`RtcStatsType::CandidatePair`] variant.
822///
823/// [Full doc on W3C][2].
824///
825/// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
826/// [1]: https://w3.org/TR/webrtc-stats/#dfn-deleted
827/// [2]: https://w3.org/TR/webrtc-stats/#candidatepair-dict%2A
828#[serde_with::skip_serializing_none]
829#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
830#[serde(rename_all = "camelCase")]
831pub struct RtcIceCandidatePairStats {
832 /// Unique identifier associated to the object that was inspected to
833 /// produce the [`RtcTransportStats`] associated with this candidates
834 /// pair.
835 pub transport_id: Option<String>,
836
837 /// Unique identifier associated to the object that was inspected to
838 /// produce the [`RtcIceCandidateStats`] for the local candidate
839 /// associated with this candidates pair.
840 pub local_candidate_id: Option<String>,
841
842 /// Unique identifier associated to the object that was inspected to
843 /// produce the [`RtcIceCandidateStats`] for the remote candidate
844 /// associated with this candidates pair.
845 pub remote_candidate_id: Option<String>,
846
847 /// State of the checklist for the local and remote candidates in a pair.
848 pub state: IceCandidatePairState,
849
850 /// Related to updating the nominated flag described in
851 /// [Section 7.1.3.2.4 of RFC 5245][1].
852 ///
853 /// [1]: https://tools.ietf.org/html/rfc5245#section-7.1.3.2.4
854 pub nominated: bool,
855
856 /// Total number of payload bytes sent on this candidate pair, i.e. not
857 /// including headers or padding.
858 pub bytes_sent: u64,
859
860 /// Total number of payload bytes received on this candidate pair, i.e. not
861 /// including headers or padding.
862 pub bytes_received: u64,
863
864 /// Sum of all round trip time measurements in seconds since the beginning
865 /// of the session, based on STUN connectivity check [STUN-PATH-CHAR]
866 /// responses (responsesReceived), including those that reply to requests
867 /// that are sent in order to verify consent [RFC 7675].
868 ///
869 /// The average round trip time can be computed from
870 /// [`totalRoundTripTime`][1] by dividing it by [`responsesReceived`][2].
871 ///
872 /// [STUN-PATH-CHAR]: https://w3.org/TR/webrtc-stats/#bib-stun-path-char
873 /// [RFC 7675]: https://tools.ietf.org/html/rfc7675
874 /// [1]: https://tinyurl.com/tgr543a
875 /// [2]: https://tinyurl.com/r3zo2um
876 pub total_round_trip_time: Option<HighResTimeStamp>,
877
878 /// Latest round trip time measured in seconds, computed from both STUN
879 /// connectivity checks [STUN-PATH-CHAR], including those that are sent for
880 /// consent verification [RFC 7675].
881 ///
882 /// [STUN-PATH-CHAR]: https://w3.org/TR/webrtc-stats/#bib-stun-path-char
883 /// [RFC 7675]: https://tools.ietf.org/html/rfc7675
884 pub current_round_trip_time: Option<HighResTimeStamp>,
885
886 /// Calculated by the underlying congestion control by combining the
887 /// available bitrate for all the outgoing RTP streams using this candidate
888 /// pair. The bitrate measurement does not count the size of the IP or
889 /// other transport layers like TCP or UDP. It is similar to the TIAS
890 /// defined in [RFC 3890], i.e. it is measured in bits per second and the
891 /// bitrate is calculated over a 1 second window.
892 ///
893 /// Implementations that do not calculate a sender-side estimate MUST leave
894 /// this undefined. Additionally, the value MUST be undefined for candidate
895 /// pairs that were never used. For pairs in use, the estimate is normally
896 /// no lower than the bitrate for the packets sent at
897 /// [`lastPacketSentTimestamp`][1], but might be higher. For candidate
898 /// pairs that are not currently in use but were used before,
899 /// implementations MUST return undefined.
900 ///
901 /// [RFC 3890]: https://tools.ietf.org/html/rfc3890
902 /// [1]: https://tinyurl.com/rfc72eh
903 pub available_outgoing_bitrate: Option<u64>,
904}
905
906/// Possible states of a candidate pair.
907///
908/// > Each candidate pair in the check list has a foundation and a state.
909/// > The foundation is the combination of the foundations of the local and
910/// > remote candidates in the pair. The state is assigned once the check
911/// > list for each media stream has been computed. There are five
912/// > potential values that the state can have.
913#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
914#[serde(rename_all = "kebab-case")]
915pub enum KnownIceCandidatePairState {
916 /// Check has not been performed for this pair, and can be performed as
917 /// soon as it is the highest-priority Waiting pair on the check list.
918 Waiting,
919
920 /// Check has been sent for this pair, but the transaction is in progress.
921 InProgress,
922
923 /// Check for this pair was already done and produced a successful result.
924 Succeeded,
925
926 /// Check for this pair was already done and failed, either never producing
927 /// any response or producing an unrecoverable failure response.
928 Failed,
929
930 /// Check for this pair hasn't been performed, and it can't yet be
931 /// performed until some other check succeeds, allowing this pair to
932 /// unfreeze and move into the [`KnownIceCandidatePairState::Waiting`]
933 /// state.
934 Frozen,
935
936 /// Other Candidate pair was nominated.
937 ///
938 /// This state is **obsolete and not spec compliant**, however, it still
939 /// may be emitted by some implementations.
940 Cancelled,
941}
942
943/// Non-exhaustive version of [`KnownIceCandidatePairState`].
944pub type IceCandidatePairState = NonExhaustive<KnownIceCandidatePairState>;
945
946/// Known protocols used in the WebRTC.
947#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
948#[serde(rename_all = "lowercase")]
949pub enum KnownProtocol {
950 /// [User Datagram Protocol][1].
951 ///
952 /// [1]: https://en.wikipedia.org/wiki/User_Datagram_Protocol
953 Udp,
954
955 /// [Transmission Control Protocol][1].
956 ///
957 /// [1]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol
958 Tcp,
959}
960
961/// Non-exhaustive version of [`KnownProtocol`].
962pub type Protocol = NonExhaustive<KnownProtocol>;
963
964/// [RTCIceCandidateType] represents the type of the ICE candidate, as
965/// defined in [Section 15.1 of RFC 5245][1].
966///
967/// [RTCIceCandidateType]: https://w3.org/TR/webrtc#rtcicecandidatetype-enum
968/// [1]: https://tools.ietf.org/html/rfc5245#section-15.1
969#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
970#[serde(rename_all = "lowercase")]
971pub enum KnownCandidateType {
972 /// Host candidate, as defined in [Section 4.1.1.1 of RFC 5245][1].
973 ///
974 /// [1]: https://tools.ietf.org/html/rfc5245#section-4.1.1.1
975 Host,
976
977 /// Server reflexive candidate, as defined in
978 /// [Section 4.1.1.2 of RFC 5245][1].
979 ///
980 /// [1]: https://tools.ietf.org/html/rfc5245#section-4.1.1.2
981 Srlfx,
982
983 /// Peer reflexive candidate, as defined in
984 /// [Section 4.1.1.2 of RFC 5245][1].
985 ///
986 /// [1]: https://tools.ietf.org/html/rfc5245#section-4.1.1.2
987 Prflx,
988
989 /// Relay candidate, as defined in [Section 7.1.3.2.1 of RFC 5245][1].
990 ///
991 /// [1]: https://tools.ietf.org/html/rfc5245#section-7.1.3.2.1
992 Relay,
993}
994
995/// Non-exhaustive version of [`KnownCandidateType`].
996pub type CandidateType = NonExhaustive<KnownCandidateType>;
997
998/// Fields of [`RtcStatsType::InboundRtp`] variant.
999#[serde_with::skip_serializing_none]
1000#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Serialize)]
1001#[serde(tag = "kind", rename_all = "camelCase")]
1002pub enum RtcInboundRtpStreamMediaType {
1003 /// Fields when the `kind` is `audio`.
1004 #[serde(rename_all = "camelCase")]
1005 Audio {
1006 /// Indicator whether the last RTP packet whose frame was delivered to
1007 /// the [RTCRtpReceiver]'s [MediaStreamTrack][1] for playout contained
1008 /// voice activity or not based on the presence of the V bit in the
1009 /// extension header, as defined in [RFC 6464].
1010 ///
1011 /// [RTCRtpReceiver]: https://w3.org/TR/webrtc#rtcrtpreceiver-interface
1012 /// [RFC 6464]: https://tools.ietf.org/html/rfc6464#page-3
1013 /// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1014 voice_activity_flag: Option<bool>,
1015
1016 /// Total number of samples that have been received on this RTP stream.
1017 /// This includes [`concealedSamples`].
1018 ///
1019 /// [`concealedSamples`]: https://tinyurl.com/s6c4qe4
1020 total_samples_received: Option<u64>,
1021
1022 /// Total number of samples that are concealed samples.
1023 ///
1024 /// A concealed sample is a sample that was replaced with synthesized
1025 /// samples generated locally before being played out.
1026 /// Examples of samples that have to be concealed are samples from lost
1027 /// packets (reported in [`packetsLost`]) or samples from packets that
1028 /// arrive too late to be played out (reported in
1029 /// [`packetsDiscarded`]).
1030 ///
1031 /// [`packetsLost`]: https://tinyurl.com/u2gq965
1032 /// [`packetsDiscarded`]: https://tinyurl.com/yx7qyox3
1033 concealed_samples: Option<u64>,
1034
1035 /// Total number of concealed samples inserted that are "silent".
1036 ///
1037 /// Playing out silent samples results in silence or comfort noise.
1038 /// This is a subset of [`concealedSamples`].
1039 ///
1040 /// [`concealedSamples`]: https://tinyurl.com/s6c4qe4
1041 silent_concealed_samples: Option<u64>,
1042
1043 /// Audio level of the receiving track.
1044 audio_level: Option<Float>,
1045
1046 /// Audio energy of the receiving track.
1047 total_audio_energy: Option<Float>,
1048
1049 /// Audio duration of the receiving track.
1050 ///
1051 /// For audio durations of tracks attached locally, see
1052 /// [RTCAudioSourceStats][1] instead.
1053 ///
1054 /// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcaudiosourcestats
1055 total_samples_duration: Option<HighResTimeStamp>,
1056 },
1057
1058 /// Fields when the `kind` is `video`.
1059 #[serde(rename_all = "camelCase")]
1060 Video {
1061 /// Total number of frames correctly decoded for this RTP stream, i.e.
1062 /// frames that would be displayed if no frames are dropped.
1063 frames_decoded: Option<u64>,
1064
1065 /// Total number of key frames, such as key frames in VP8 [RFC 6386] or
1066 /// IDR-frames in H.264 [RFC 6184], successfully decoded for this RTP
1067 /// media stream.
1068 ///
1069 /// This is a subset of [`framesDecoded`].
1070 /// [`framesDecoded`] - [`keyFramesDecoded`] gives you the number of
1071 /// delta frames decoded.
1072 ///
1073 /// [RFC 6386]: https://w3.org/TR/webrtc-stats/#bib-rfc6386
1074 /// [RFC 6184]: https://w3.org/TR/webrtc-stats/#bib-rfc6184
1075 /// [`framesDecoded`]: https://tinyurl.com/srfwrwt
1076 /// [`keyFramesDecoded`]: https://tinyurl.com/qtdmhtm
1077 key_frames_decoded: Option<u64>,
1078
1079 /// Width of the last decoded frame.
1080 ///
1081 /// Before the first frame is decoded this attribute is missing.
1082 frame_width: Option<u64>,
1083
1084 /// Height of the last decoded frame.
1085 ///
1086 /// Before the first frame is decoded this attribute is missing.
1087 frame_height: Option<u64>,
1088
1089 /// Sum of the interframe delays in seconds between consecutively
1090 /// decoded frames, recorded just after a frame has been decoded.
1091 total_inter_frame_delay: Option<Float>,
1092
1093 /// Number of decoded frames in the last second.
1094 frames_per_second: Option<Float>,
1095
1096 /// Bit depth per pixel of the last decoded frame.
1097 ///
1098 /// Typical values are 24, 30, or 36 bits. Before the first frame is
1099 /// decoded this attribute is missing.
1100 frame_bit_depth: Option<u64>,
1101
1102 /// Total number of Full Intra Request (FIR) packets sent by this
1103 /// receiver.
1104 fir_count: Option<u64>,
1105
1106 /// Total number of Picture Loss Indication (PLI) packets sent by this
1107 /// receiver.
1108 pli_count: Option<u64>,
1109
1110 /// Total number of Slice Loss Indication (SLI) packets sent by this
1111 /// receiver.
1112 sli_count: Option<u64>,
1113
1114 /// Number of concealment events.
1115 ///
1116 /// This counter increases every time a concealed sample is synthesized
1117 /// after a non-concealed sample. That is, multiple consecutive
1118 /// concealed samples will increase the [`concealedSamples`] count
1119 /// multiple times but is a single concealment event.
1120 ///
1121 /// [`concealedSamples`]: https://tinyurl.com/s6c4qe4
1122 concealment_events: Option<u64>,
1123
1124 /// Total number of complete frames received on this RTP stream.
1125 ///
1126 /// This metric is incremented when the complete frame is received.
1127 frames_received: Option<u64>,
1128 },
1129}
1130
1131/// Representation of the measurement metrics for the incoming [RTP] media
1132/// stream. The timestamp reported in the statistics object is the time at which
1133/// the data was sampled.
1134///
1135/// [`RtcStatsType::InboundRtp`] variant.
1136///
1137/// [Full doc on W3C][1].
1138///
1139/// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
1140/// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats
1141#[serde_with::skip_serializing_none]
1142#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
1143#[serde(rename_all = "camelCase")]
1144pub struct RtcInboundRtpStreamStats {
1145 /// ID of the stats object representing the receiving track.
1146 pub track_id: Option<String>,
1147
1148 /// Fields which should be in the [`RtcStat`] based on its `kind`.
1149 #[serde(flatten)]
1150 pub media_specific_stats: RtcInboundRtpStreamMediaType,
1151
1152 /// Total number of bytes received for this SSRC.
1153 pub bytes_received: u64,
1154
1155 /// Total number of RTP data packets received for this SSRC.
1156 pub packets_received: u64,
1157
1158 /// Total number of RTP data packets for this SSRC that have been lost
1159 /// since the beginning of reception.
1160 ///
1161 /// This number is defined to be the number of packets expected less the
1162 /// number of packets actually received, where the number of packets
1163 /// received includes any which are late or duplicates. Thus, packets that
1164 /// arrive late are not counted as lost, and the loss __may be negative__
1165 /// if there are duplicates.
1166 pub packets_lost: Option<i64>,
1167
1168 /// Packet jitter measured in seconds for this SSRC.
1169 pub jitter: Option<Float>,
1170
1171 /// Total number of seconds that have been spent decoding the
1172 /// [`framesDecoded`] frames of this stream.
1173 ///
1174 /// The average decode time can be calculated by dividing this value with
1175 /// [`framesDecoded`]. The time it takes to decode one frame is the time
1176 /// passed between feeding the decoder a frame and the decoder returning
1177 /// decoded data for that frame.
1178 ///
1179 /// [`framesDecoded`]: https://tinyurl.com/srfwrwt
1180 pub total_decode_time: Option<HighResTimeStamp>,
1181
1182 /// Total number of audio samples or video frames that have come out of the
1183 /// jitter buffer (increasing [`jitterBufferDelay`]).
1184 ///
1185 /// [`jitterBufferDelay`]: https://tinyurl.com/qvoojt5
1186 pub jitter_buffer_emitted_count: Option<u64>,
1187}
1188
1189/// Statistics related to a specific [MediaStreamTrack][1]'s attachment to an
1190/// [RTCRtpSender] and the corresponding media-level metrics.
1191///
1192/// [`RtcStatsType::Track`] variant.
1193///
1194/// [Full doc on W3C][1].
1195///
1196/// [RTCRtpSender]: https://w3.org/TR/webrtc#rtcrtpsender-interface
1197/// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1198/// [2]: https://w3.org/TR/webrtc-stats/#dom-rtcstatstype-track
1199#[serde_with::skip_serializing_none]
1200#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1201#[serde(rename_all = "camelCase")]
1202pub struct TrackStats {
1203 /// [`id` property][1] of the track.
1204 ///
1205 /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-id
1206 pub track_identifier: String,
1207
1208 /// `true` if the source is remote, for instance if it is sourced from
1209 /// another host via an [RTCPeerConnection]. `false` otherwise.
1210 ///
1211 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
1212 pub remote_source: Option<bool>,
1213
1214 /// Reflection of the "ended" state of the track.
1215 pub ended: Option<bool>,
1216
1217 /// Either `audio` or `video`.
1218 ///
1219 /// This reflects the [`kind` attribute][2] of the [MediaStreamTrack][1].
1220 ///
1221 /// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1222 /// [2]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-kind
1223 pub kind: Option<TrackStatsKind>,
1224}
1225
1226/// [`kind` attribute] values of the [MediaStreamTrack][1].
1227///
1228/// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1229/// [2]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-kind
1230#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1231#[serde(rename_all = "camelCase")]
1232pub enum TrackStatsKind {
1233 /// Track is used for the audio content.
1234 Audio,
1235
1236 /// Track is used for the video content.
1237 Video,
1238}
1239
1240/// [`RtcStat`] fields of [`RtcStatsType::OutboundRtp`] type based on its
1241/// `kind`.
1242#[serde_with::skip_serializing_none]
1243#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Serialize)]
1244#[serde(tag = "kind", rename_all = "camelCase")]
1245pub enum RtcOutboundRtpStreamMediaType {
1246 /// Fields when the `kind` is `audio`.
1247 #[serde(rename_all = "camelCase")]
1248 Audio {
1249 /// Total number of samples that have been sent over this RTP stream.
1250 total_samples_sent: Option<u64>,
1251
1252 /// Whether the last RTP packet sent contained voice activity or not
1253 /// based on the presence of the V bit in the extension header.
1254 voice_activity_flag: Option<bool>,
1255 },
1256
1257 /// Fields when the `kind` is `video`.
1258 #[serde(rename_all = "camelCase")]
1259 Video {
1260 /// Width of the last encoded frame.
1261 ///
1262 /// The resolution of the encoded frame may be lower than the media
1263 /// source (see [RTCVideoSourceStats.width][1]).
1264 ///
1265 /// Before the first frame is encoded this attribute is missing.
1266 ///
1267 /// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcvideosourcestats-width
1268 frame_width: Option<u64>,
1269
1270 /// Height of the last encoded frame.
1271 ///
1272 /// The resolution of the encoded frame may be lower than the media
1273 /// source (see [RTCVideoSourceStats.height][1]).
1274 ///
1275 /// Before the first frame is encoded this attribute is missing.
1276 ///
1277 /// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcvideosourcestats-height
1278 frame_height: Option<u64>,
1279
1280 /// Number of encoded frames during the last second.
1281 ///
1282 /// This may be lower than the media source frame rate (see
1283 /// [RTCVideoSourceStats.framesPerSecond][1]).
1284 ///
1285 /// [1]: https://tinyurl.com/rrmkrfk
1286 frames_per_second: Option<Float>,
1287 },
1288}
1289
1290/// Statistics for an outbound [RTP] stream that is currently sent with this
1291/// [RTCPeerConnection] object.
1292///
1293/// When there are multiple [RTP] streams connected to the same sender, such
1294/// as when using simulcast or RTX, there will be one
1295/// [`RtcOutboundRtpStreamStats`] per RTP stream, with distinct values of
1296/// the `ssrc` attribute, and all these senders will have a reference to
1297/// the same "sender" object (of type [RTCAudioSenderStats][1] or
1298/// [RTCVideoSenderStats][2]) and "track" object (of type
1299/// [RTCSenderAudioTrackAttachmentStats][3] or
1300/// [RTCSenderVideoTrackAttachmentStats][4]).
1301///
1302/// [`RtcStatsType::OutboundRtp`] variant.
1303///
1304/// [Full doc on W3C][5].
1305///
1306/// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
1307/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
1308/// [1]: https://w3.org/TR/webrtc-stats/#dom-rtcaudiosenderstats
1309/// [2]: https://w3.org/TR/webrtc-stats/#dom-rtcvideosenderstats
1310/// [3]: https://tinyurl.com/sefa5z4
1311/// [4]: https://tinyurl.com/rkuvpl4
1312/// [5]: https://w3.org/TR/webrtc-stats/#outboundrtpstats-dict%2A
1313#[serde_with::skip_serializing_none]
1314#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
1315#[serde(rename_all = "camelCase")]
1316pub struct RtcOutboundRtpStreamStats {
1317 /// ID of the stats object representing the current track attachment to the
1318 /// sender of this stream.
1319 pub track_id: Option<String>,
1320
1321 /// Fields which should be in the [`RtcStat`] based on its `kind`.
1322 #[serde(flatten)]
1323 pub media_type: RtcOutboundRtpStreamMediaType,
1324
1325 /// Total number of bytes sent for this SSRC.
1326 pub bytes_sent: Option<u64>,
1327
1328 /// Total number of RTP packets sent for this SSRC.
1329 pub packets_sent: Option<u64>,
1330
1331 /// ID of the stats object representing the track currently
1332 /// attached to the sender of this stream.
1333 pub media_source_id: Option<String>,
1334}
1335
1336/// Properties of a `candidate` in [Section 15.1 of RFC 5245][1].
1337/// It corresponds to a [RTCIceTransport] object.
1338///
1339/// [`RtcStatsType::LocalCandidate`] or [`RtcStatsType::RemoteCandidate`]
1340/// variant.
1341///
1342/// [Full doc on W3C][2].
1343///
1344/// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1345/// [1]: https://tools.ietf.org/html/rfc5245#section-15.1
1346/// [2]: https://w3.org/TR/webrtc-stats/#icecandidate-dict%2A
1347#[serde_with::skip_serializing_none]
1348#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1349#[serde(rename_all = "camelCase")]
1350pub struct RtcIceCandidateStats {
1351 /// Unique ID that is associated to the object that was inspected to
1352 /// produce the [RTCTransportStats][1] associated with this candidate.
1353 ///
1354 /// [1]: https://w3.org/TR/webrtc-stats/#transportstats-dict%2A
1355 pub transport_id: Option<String>,
1356
1357 /// Address of the candidate, allowing for IPv4 addresses, IPv6 addresses,
1358 /// and fully qualified domain names (FQDNs).
1359 pub address: Option<String>,
1360
1361 /// Port number of the candidate.
1362 pub port: u16,
1363
1364 /// Valid values for transport is one of `udp` and `tcp`.
1365 pub protocol: Protocol,
1366
1367 /// Type of the ICE candidate.
1368 pub candidate_type: CandidateType,
1369
1370 /// Calculated as defined in [Section 15.1 of RFC 5245][1].
1371 ///
1372 /// [1]: https://tools.ietf.org/html/rfc5245#section-15.1
1373 pub priority: u32,
1374
1375 /// For local candidates this is the URL of the ICE server from which the
1376 /// candidate was obtained. It is the same as the
1377 /// [url surfaced in the RTCPeerConnectionIceEvent][1].
1378 ///
1379 /// `None` for remote candidates.
1380 ///
1381 /// [1]: https://w3.org/TR/webrtc#rtcpeerconnectioniceevent
1382 pub url: Option<String>,
1383
1384 /// Protocol used by the endpoint to communicate with the TURN server.
1385 ///
1386 /// Only present for local candidates.
1387 pub relay_protocol: Option<Protocol>,
1388}
1389
1390/// [`RtcStat`] fields of [`RtcStatsType::MediaSource`] type based on its
1391/// `kind`.
1392#[serde_with::skip_serializing_none]
1393#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Serialize)]
1394#[serde(tag = "kind", rename_all = "camelCase")]
1395pub enum MediaKind {
1396 /// Fields when the `kind` is `video`.
1397 #[serde(rename_all = "camelCase")]
1398 Video {
1399 /// Width (in pixels) of the last frame originating from the source.
1400 /// Before a frame has been produced this attribute is missing.
1401 width: Option<u32>,
1402
1403 /// Height (in pixels) of the last frame originating from the source.
1404 /// Before a frame has been produced this attribute is missing.
1405 height: Option<u32>,
1406
1407 /// Number of frames originating from the source, measured during the
1408 /// last second. For the first second of this object's lifetime this
1409 /// attribute is missing.
1410 frames_per_second: Option<Float>,
1411 },
1412
1413 /// Fields when the `kind` is `audio`.
1414 #[serde(rename_all = "camelCase")]
1415 Audio {
1416 /// Audio level of the media source.
1417 audio_level: Option<Float>,
1418
1419 /// Audio energy of the media source.
1420 total_audio_energy: Option<Float>,
1421
1422 /// Audio duration of the media source.
1423 total_samples_duration: Option<Float>,
1424 },
1425}
1426
1427/// Statistics for the media produced by a [MediaStreamTrack][1] that is
1428/// currently attached to an [RTCRtpSender].
1429///
1430/// This reflects the media that is fed to the encoder after [getUserMedia]
1431/// constraints have been applied (i.e. not the raw media produced by the
1432/// camera).
1433///
1434/// [`RtcStatsType::MediaSource`] variant.
1435///
1436/// [Full doc on W3C][2].
1437///
1438/// [RTCRtpSender]: https://w3.org/TR/webrtc#rtcrtpsender-interface
1439/// [getUserMedia]: https://tinyurl.com/sngpyr6
1440/// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1441/// [2]: https://w3.org/TR/webrtc-stats/#dom-rtcstatstype-media-source
1442#[serde_with::skip_serializing_none]
1443#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
1444#[serde(rename_all = "camelCase")]
1445pub struct MediaSourceStats {
1446 /// Value of the [MediaStreamTrack][1]'s ID attribute.
1447 ///
1448 /// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1449 pub track_identifier: Option<String>,
1450
1451 /// Fields which should be in the [`RtcStat`] based on `kind`.
1452 #[serde(flatten)]
1453 pub kind: MediaKind,
1454}
1455
1456#[cfg(feature = "extended-stats")]
1457/// Statistics for a codec that is currently used by [RTP] streams being sent or
1458/// received by [RTCPeerConnection] object.
1459///
1460/// [`RtcStatsType::Codec`] variant.
1461///
1462/// [Full doc on W3C][1].
1463///
1464/// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
1465/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
1466/// [1]: https://w3.org/TR/webrtc-stats/#dom-rtccodecstats
1467#[serde_with::skip_serializing_none]
1468#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1469#[serde(rename_all = "camelCase")]
1470pub struct RtcCodecStats {
1471 /// [Payload type][1] as used in [RTP] encoding or decoding.
1472 ///
1473 /// [RTP]: https://en.wikipedia.org/wiki/Real-time_Transport_Protocol
1474 /// [1]: https://tools.ietf.org/html/rfc3550#page-14
1475 pub payload_type: u32,
1476
1477 /// The codec MIME media `type/subtype` (e.g. `video/vp8` or equivalent).
1478 pub mime_type: String,
1479
1480 /// Media sampling rate.
1481 pub clock_rate: u32,
1482}
1483
1484#[cfg(feature = "extended-stats")]
1485/// Information about a certificate used by [RTCIceTransport].
1486///
1487/// [`RtcStatsType::Certificate`] variant.
1488///
1489/// [Full doc on W3C][1].
1490///
1491/// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1492/// [1]: https://w3.org/TR/webrtc-stats/#certificatestats-dict%2A
1493#[serde_with::skip_serializing_none]
1494#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1495#[serde(rename_all = "camelCase")]
1496pub struct RtcCertificateStats {
1497 /// Fingerprint of the certificate.
1498 ///
1499 /// Only use the fingerprint value as defined in [Section 5 of RFC
1500 /// 4572][1].
1501 ///
1502 /// [1]: https://tools.ietf.org/html/rfc4572#section-5
1503 pub fingerprint: String,
1504
1505 /// Hash function used to compute the certificate fingerprint.
1506 /// For instance, `sha-256`.
1507 pub fingerprint_algorithm: String,
1508
1509 /// The DER-encoded Base64 representation of the certificate.
1510 pub base64_certificate: String,
1511}
1512
1513/// Representation of [DOMHighResTimeStamp][1].
1514///
1515/// Can be converted to the [`SystemTime`] with millisecond-wise accuracy.
1516///
1517/// [`HighResTimeStamp`] type is a [`f64`] and is used to store a time value
1518/// in milliseconds. This type can be used to describe a discrete point in time
1519/// or a time interval (the difference in time between two discrete points in
1520/// time).
1521///
1522/// The time, given in milliseconds, should be accurate to 5 µs (microseconds),
1523/// with the fractional part of the number indicating fractions of a
1524/// millisecond. However, if the browser is unable to provide a time value
1525/// accurate to 5 µs (due, for example, to hardware or software constraints),
1526/// the browser can represent the value as a time in milliseconds accurate to a
1527/// millisecond. Also note the section below on reduced time precision
1528/// controlled by browser preferences to avoid timing attacks and
1529/// fingerprinting.
1530///
1531/// Further, if the device or operating system the user agent is running on
1532/// doesn't have a clock accurate to the microsecond level, they may only be
1533/// accurate to the millisecond.
1534///
1535/// [1]: https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp
1536#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1537pub struct HighResTimeStamp(pub f64);
1538
1539impl From<HighResTimeStamp> for SystemTime {
1540 fn from(timestamp: HighResTimeStamp) -> Self {
1541 Self::UNIX_EPOCH + Duration::from_secs_f64(timestamp.0 / 100.0)
1542 }
1543}
1544
1545impl TryFrom<SystemTime> for HighResTimeStamp {
1546 type Error = SystemTimeError;
1547
1548 fn try_from(time: SystemTime) -> Result<Self, Self::Error> {
1549 Ok(Self(
1550 time.duration_since(SystemTime::UNIX_EPOCH)?.as_secs_f64() * 100.0,
1551 ))
1552 }
1553}
1554
1555/// Hashing string representation.
1556///
1557/// Some people believe that such behavior is incorrect (but in some programming
1558/// languages this is a default behavior) due to `NaN`, `Inf` or `-Inf` (they
1559/// all will have the same hashes).
1560/// But in the case of [`RtcStat`] received from the client, there should be no
1561/// such situations, and the hash will always be correct.
1562impl Hash for HighResTimeStamp {
1563 fn hash<H: Hasher>(&self, state: &mut H) {
1564 self.0.to_string().hash(state);
1565 }
1566}
1567
1568/// Comparison string representations.
1569///
1570/// Such implementation is required, so that the results of comparing values and
1571/// comparing hashes match.
1572impl PartialEq for HighResTimeStamp {
1573 fn eq(&self, other: &Self) -> bool {
1574 self.0.to_string().eq(&other.0.to_string())
1575 }
1576}
1577
1578/// [`f64`] wrapper with [`Hash`] implementation.
1579#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
1580pub struct Float(pub f64);
1581
1582/// Hashing string representation.
1583///
1584/// Some people believe that such behavior is incorrect (but in some programming
1585/// languages this is a default behavior) due to `NaN`, `Inf` or `-Inf` (they
1586/// all will have the same hashes).
1587/// But in the case of [`RtcStat`] received from the client, there should be no
1588/// such situations, and the hash will always be correct.
1589impl Hash for Float {
1590 fn hash<H: Hasher>(&self, state: &mut H) {
1591 self.0.to_string().hash(state);
1592 }
1593}
1594
1595/// Comparison string representations.
1596///
1597/// Such implementation is required, so that the results of comparing values and
1598/// comparing hashes match.
1599impl PartialEq for Float {
1600 fn eq(&self, other: &Self) -> bool {
1601 self.0.to_string().eq(&other.0.to_string())
1602 }
1603}
1604
1605#[cfg(feature = "extended-stats")]
1606/// Information about the connection to an ICE server (e.g. STUN or TURN).
1607///
1608/// [`RtcStatsType::IceServer`] variant.
1609///
1610/// [Full doc on W3C][1].
1611///
1612/// [1]: https://w3.org/TR/webrtc-stats/#ice-server-dict%2A
1613#[serde_with::skip_serializing_none]
1614#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
1615#[serde(rename_all = "camelCase")]
1616pub struct RtcIceServerStats {
1617 /// URL of the ICE server (e.g. TURN or STUN server).
1618 pub url: String,
1619
1620 /// Port number used by the client.
1621 pub port: u16,
1622
1623 /// Protocol used by the client to connect to ICE server.
1624 pub protocol: Protocol,
1625
1626 /// Total amount of requests that have been sent to this server.
1627 pub total_requests_sent: Option<u64>,
1628
1629 /// Total amount of responses received from this server.
1630 pub total_responses_received: Option<u64>,
1631
1632 /// Sum of RTTs for all requests that have been sent where a response has
1633 /// been received.
1634 pub total_round_trip_time: Option<HighResTimeStamp>,
1635}