File
Blob: firmware/vendor/str0m/src/rtp/id.rs
| 1 | use std::fmt; |
| 2 | use std::ops::Deref; |
| 3 | use std::str::from_utf8; |
| 4 | |
| 5 | use serde::{Deserialize, Serialize}; |
| 6 | |
| 7 | use str0m_proto::Id; |
| 8 | use str0m_proto::NonCryptographicRng; |
| 9 | |
| 10 | macro_rules! str_id { |
| 11 | ($id:ident, $name:literal, $num:tt, $new_len:tt) => { |
| 12 | impl $id { |
| 13 | /// Creates a new random id. |
| 14 | pub fn new() -> $id { |
| 15 | let mut arr = Id::<$num>::random().into_array(); |
| 16 | for i in $new_len..$num { |
| 17 | arr[i] = b' '; |
| 18 | } |
| 19 | $id(arr) |
| 20 | } |
| 21 | |
| 22 | /// Converts an array of bytes to an id. |
| 23 | pub const fn from_array(a: [u8; $num]) -> $id { |
| 24 | $id(a) |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | impl fmt::Display for $id { |
| 29 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 30 | let s: &str = self; |
| 31 | write!(f, "{}", s) |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | impl fmt::Debug for $id { |
| 36 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 37 | let s: &str = self; |
| 38 | write!(f, "{}({})", $name, s) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | impl Deref for $id { |
| 43 | type Target = str; |
| 44 | |
| 45 | fn deref(&self) -> &Self::Target { |
| 46 | from_utf8(&self.0).expect("ascii id").trim() |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | impl<'a> From<&'a str> for $id { |
| 51 | fn from(v: &'a str) -> Self { |
| 52 | let v = v |
| 53 | .chars() |
| 54 | .map(|c| if c.is_ascii_alphanumeric() { c } else { '_' }) |
| 55 | .collect::<String>(); |
| 56 | |
| 57 | let bytes = v.as_bytes(); |
| 58 | let bytes = &bytes[0..$num.min(bytes.len())]; |
| 59 | |
| 60 | // pad with space. |
| 61 | let mut array = [b' '; $num]; |
| 62 | |
| 63 | let max = bytes.len().min(array.len()); |
| 64 | (&mut array[0..max]).copy_from_slice(bytes); |
| 65 | |
| 66 | $id(array) |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | impl Default for $id { |
| 71 | fn default() -> Self { |
| 72 | $id::new() |
| 73 | } |
| 74 | } |
| 75 | }; |
| 76 | } |
| 77 | |
| 78 | macro_rules! num_id { |
| 79 | ($id:ident, $t:tt) => { |
| 80 | impl $id { |
| 81 | /// Creates a new random id. |
| 82 | pub fn new() -> Self { |
| 83 | loop { |
| 84 | let v = NonCryptographicRng::$t(); |
| 85 | // At least Ssrc assigns special meaning to 0, |
| 86 | // but it's fine to avoid for the other numeric |
| 87 | // ids as well. |
| 88 | if v != 0 { |
| 89 | return $id(v); |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | impl Deref for $id { |
| 96 | type Target = $t; |
| 97 | |
| 98 | fn deref(&self) -> &Self::Target { |
| 99 | &self.0 |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | impl From<$t> for $id { |
| 104 | fn from(v: $t) -> Self { |
| 105 | $id(v) |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | impl fmt::Display for $id { |
| 110 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 111 | write!(f, "{}", self.0) |
| 112 | } |
| 113 | } |
| 114 | }; |
| 115 | } |
| 116 | |
| 117 | /// Media identifier. |
| 118 | /// |
| 119 | /// In SDP this is found per m-line with the attribute `a=mid:<mid>`. |
| 120 | /// |
| 121 | /// When using Direct API we still need `Mid`, since they group individual |
| 122 | /// encoded streams. For example a simulcast of 3 layers would have |
| 123 | /// 3 incoming StreamRx, but since they belong to the same media, |
| 124 | /// the have the same `Mid`. |
| 125 | #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] |
| 126 | pub struct Mid([u8; 16]); |
| 127 | str_id!(Mid, "Mid", 16, 3); |
| 128 | |
| 129 | /// Identifier of a simulcast layer for an encoded stream. |
| 130 | /// |
| 131 | /// The abbreviation means "RTP Stream Id", which is a very confusing name, because |
| 132 | /// everything in RTP is a stream. People tend to just call it "rid". |
| 133 | /// |
| 134 | /// In SDP this is an optional value that will be seen in [`MediaData`][crate::media::MediaData] |
| 135 | /// if the remote peer is configured for simulcast. |
| 136 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] |
| 137 | pub struct Rid([u8; 8]); |
| 138 | str_id!(Rid, "Rid", 8, 3); |
| 139 | |
| 140 | /// Synchronization source. |
| 141 | /// |
| 142 | /// Uniquely identifies a sending source of data. Each video/audio stream would be associated |
| 143 | /// with at least one synchronization source. Multiple sources for the same stream happens |
| 144 | /// for RTX (resend) and simulcast. |
| 145 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] |
| 146 | pub struct Ssrc(u32); |
| 147 | num_id!(Ssrc, u32); |
| 148 | |
| 149 | impl Ssrc { |
| 150 | /// Returns true if this is the probe SSRC (0). |
| 151 | /// |
| 152 | /// libwebrtc uses SSRC 0 for bandwidth estimation probes sent before |
| 153 | /// video media starts. These probes require special handling. |
| 154 | pub fn is_probe(&self) -> bool { |
| 155 | self.0 == 0 |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | /// Payload type. |
| 160 | /// |
| 161 | /// The payload type identifies which codec and format parameters a stream is sent with. |
| 162 | /// The mappings of Pt-Codec + parameters is negotiated in SDP OFFER/ANSWER. |
| 163 | /// |
| 164 | /// PTs in RTP headers are 7 bits. Values >=128 are not valid. |
| 165 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] |
| 166 | pub struct Pt(u8); |
| 167 | num_id!(Pt, u8); |
| 168 | |
| 169 | /// Identifier of an SDP session. |
| 170 | /// |
| 171 | /// This value is rarely interesting, but is part of the SDP OFFER and ANSWER. |
| 172 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] |
| 173 | pub struct SessionId(u64); |
| 174 | num_id!(SessionId, u64); |
| 175 | |
| 176 | /// Sequence number of an RTP packet. |
| 177 | /// |
| 178 | /// An RTP packet is identified by: SSRC + SeqNo. However in the RTP header the sequence number |
| 179 | /// is a `u16`, meaning the value quite quickly "rolls over". To uniquely identify a packet, |
| 180 | /// str0m keeps track of the roll overs and converts the `u16` to `u64` in this `SeqNo`. |
| 181 | /// |
| 182 | /// To get the RTP u16 value from a `SeqNo`, use `as_u16()` or cast it to u16. |
| 183 | /// |
| 184 | /// ``` |
| 185 | /// # use str0m::rtp::SeqNo; |
| 186 | /// let seq_no: SeqNo = 65_537.into(); |
| 187 | /// |
| 188 | /// // Use `as_u16()`. |
| 189 | /// let a = seq_no.as_u16(); |
| 190 | /// // Discard upper 48 bits to get RTP u16. |
| 191 | /// let b = *seq_no as u16; |
| 192 | /// |
| 193 | /// assert_eq!(a, 1); |
| 194 | /// assert_eq!(b, 1); |
| 195 | /// ``` |
| 196 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] |
| 197 | pub struct SeqNo(u64); |
| 198 | num_id!(SeqNo, u64); |
| 199 | |
| 200 | #[cfg(feature = "drv")] |
| 201 | crate::drv_identity_copy!(Mid, Rid, Ssrc, Pt, SessionId, SeqNo); |
| 202 | |
| 203 | /// TWCC-specific sequence number. |
| 204 | /// |
| 205 | /// Transport-Wide Congestion Control uses its own sequence number space, |
| 206 | /// separate from RTP sequence numbers. This type ensures TWCC sequences |
| 207 | /// cannot be confused with RTP SeqNo values. |
| 208 | /// |
| 209 | /// TWCC sequences are also u64 internally (tracking rollovers), though the |
| 210 | /// wire format uses u16. |
| 211 | #[derive( |
| 212 | Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default, |
| 213 | )] |
| 214 | pub struct TwccSeq(u64); |
| 215 | num_id!(TwccSeq, u64); |
| 216 | |
| 217 | impl SeqNo { |
| 218 | pub(crate) const MAX: SeqNo = SeqNo(u64::MAX); |
| 219 | |
| 220 | /// Check if the `other` sequence number is directly following this. |
| 221 | #[inline(always)] |
| 222 | pub fn is_next(&self, other: SeqNo) -> bool { |
| 223 | if **self >= *other { |
| 224 | return false; |
| 225 | } |
| 226 | *other - **self == 1 |
| 227 | } |
| 228 | |
| 229 | /// Increase (mutate) this sequence number and return the previous value. |
| 230 | #[inline(always)] |
| 231 | pub fn inc(&mut self) -> SeqNo { |
| 232 | let n = SeqNo(self.0); |
| 233 | self.0 += 1; |
| 234 | n |
| 235 | } |
| 236 | |
| 237 | #[inline(always)] |
| 238 | pub(crate) fn is_max(&self) -> bool { |
| 239 | self.0 == Self::MAX.0 |
| 240 | } |
| 241 | |
| 242 | /// The RTP header value (discarding the ROC). |
| 243 | /// |
| 244 | /// This is the same as discarding the top 48 bits by casting to a u16. |
| 245 | /// |
| 246 | /// ``` |
| 247 | /// # use str0m::rtp::SeqNo; |
| 248 | /// let seq_no: SeqNo = 65_537.into(); |
| 249 | /// |
| 250 | /// // Use `as_u16()`. |
| 251 | /// let a = seq_no.as_u16(); |
| 252 | /// |
| 253 | /// assert_eq!(a, 1); |
| 254 | /// ``` |
| 255 | #[inline(always)] |
| 256 | pub fn as_u16(&self) -> u16 { |
| 257 | self.0 as u16 |
| 258 | } |
| 259 | |
| 260 | /// Get the rollover counter (ROC) value. |
| 261 | /// |
| 262 | /// ``` |
| 263 | /// # use str0m::rtp::SeqNo; |
| 264 | /// // More than 2^16, thus rolled over. |
| 265 | /// let seq_no: SeqNo = 95_000.into(); |
| 266 | /// |
| 267 | /// assert_eq!(seq_no.roc(), 1); |
| 268 | /// |
| 269 | /// // Is the same as shifting 16 bits. |
| 270 | /// assert_eq!(seq_no.roc(), 95_000 >> 16); |
| 271 | /// ``` |
| 272 | #[inline(always)] |
| 273 | pub fn roc(&self) -> u64 { |
| 274 | self.0 >> 16 |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | impl TwccSeq { |
| 279 | /// Check if the `other` sequence number is directly following this. |
| 280 | #[inline(always)] |
| 281 | pub fn is_next(&self, other: TwccSeq) -> bool { |
| 282 | if **self >= *other { |
| 283 | return false; |
| 284 | } |
| 285 | *other - **self == 1 |
| 286 | } |
| 287 | |
| 288 | /// Increase (mutate) this sequence number and return the previous value. |
| 289 | #[inline(always)] |
| 290 | pub fn inc(&mut self) -> TwccSeq { |
| 291 | let n = TwccSeq(self.0); |
| 292 | self.0 += 1; |
| 293 | n |
| 294 | } |
| 295 | |
| 296 | /// The TWCC wire format value (discarding the ROC). |
| 297 | /// |
| 298 | /// This is the same as discarding the top 48 bits by casting to a u16. |
| 299 | #[inline(always)] |
| 300 | pub fn as_u16(&self) -> u16 { |
| 301 | self.0 as u16 |
| 302 | } |
| 303 | |
| 304 | /// Get the rollover counter (ROC) value. |
| 305 | #[inline(always)] |
| 306 | pub fn roc(&self) -> u64 { |
| 307 | self.0 >> 16 |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | impl Default for SeqNo { |
| 312 | fn default() -> Self { |
| 313 | // https://www.rfc-editor.org/rfc/rfc3550#page-13 |
| 314 | // The initial value of the sequence number SHOULD be random (unpredictable) |
| 315 | // to make known-plaintext attacks on encryption more difficult |
| 316 | // Upper half of range is avoided in order to prevent SRTP wraparound issues |
| 317 | // during startup. |
| 318 | // Sequence number 0 is avoided for historical reasons, presumably to avoid |
| 319 | // debugability or test usage conflicts. |
| 320 | // i.e the range is (1, 2^15-1) |
| 321 | Self((NonCryptographicRng::u16() % 32767 + 1) as u64) |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | /// Probe cluster identifier for bandwidth estimation. |
| 326 | /// |
| 327 | /// Used to tag TWCC packets as belonging to a specific probe cluster, |
| 328 | /// enabling analysis of probe results when feedback arrives. |
| 329 | /// |
| 330 | /// Uses u64 to avoid wrap-around in long-running connections. |
| 331 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)] |
| 332 | pub struct TwccClusterId(u64); |
| 333 | num_id!(TwccClusterId, u64); |
| 334 | |
| 335 | impl TwccClusterId { |
| 336 | /// Increase (mutate) this cluster ID and return the previous value. |
| 337 | #[inline(always)] |
| 338 | pub fn inc(&mut self) -> TwccClusterId { |
| 339 | let n = TwccClusterId(self.0); |
| 340 | self.0 = self.0.wrapping_add(1); |
| 341 | n |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | impl Pt { |
| 346 | /// Create a PT with a specific value. |
| 347 | /// |
| 348 | /// PTs are 7 bit. Values with 8 bits are not valid in RTP headers. |
| 349 | pub const fn new_with_value(v: u8) -> Pt { |
| 350 | Pt(v) |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | /// A combination of Mid/Rid |
| 355 | /// |
| 356 | /// In many cases they go hand-in-hand. |
| 357 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 358 | pub(crate) struct MidRid(pub Mid, pub Option<Rid>); |
| 359 | |
| 360 | impl MidRid { |
| 361 | #[inline(always)] |
| 362 | pub fn mid(&self) -> Mid { |
| 363 | self.0 |
| 364 | } |
| 365 | |
| 366 | #[inline(always)] |
| 367 | pub fn rid(&self) -> Option<Rid> { |
| 368 | self.1 |
| 369 | } |
| 370 | |
| 371 | pub fn special_equals(&self, other: &MidRid) -> bool { |
| 372 | self.0 == other.0 && (self.1.is_none() || self.1 == other.1) |
| 373 | } |
| 374 | } |