rtcp/transport_feedbacks/transport_layer_nack/
mod.rs

1#[cfg(test)]
2mod transport_layer_nack_test;
3
4use std::any::Any;
5use std::fmt;
6
7use bytes::{Buf, BufMut};
8use util::marshal::{Marshal, MarshalSize, Unmarshal};
9
10use crate::error::Error;
11use crate::header::*;
12use crate::packet::*;
13use crate::util::*;
14
15/// PacketBitmap shouldn't be used like a normal integral,
16/// so it's type is masked here. Access it with PacketList().
17type PacketBitmap = u16;
18
19/// NackPair is a wire-representation of a collection of
20/// Lost RTP packets
21#[derive(Debug, PartialEq, Eq, Default, Clone, Copy)]
22pub struct NackPair {
23    /// ID of lost packets
24    pub packet_id: u16,
25    /// Bitmask of following lost packets
26    pub lost_packets: PacketBitmap,
27}
28
29pub struct NackIterator {
30    packet_id: u16,
31    bitfield: PacketBitmap,
32    has_yielded_packet_id: bool,
33}
34
35impl Iterator for NackIterator {
36    type Item = u16;
37
38    fn next(&mut self) -> Option<Self::Item> {
39        if !self.has_yielded_packet_id {
40            self.has_yielded_packet_id = true;
41
42            Some(self.packet_id)
43        } else {
44            let mut i = 0;
45
46            while self.bitfield != 0 {
47                if (self.bitfield & (1 << i)) != 0 {
48                    self.bitfield &= !(1 << i);
49
50                    return Some(self.packet_id.wrapping_add(i + 1));
51                }
52
53                i += 1;
54            }
55
56            None
57        }
58    }
59}
60
61impl NackPair {
62    pub fn new(seq: u16) -> Self {
63        Self {
64            packet_id: seq,
65            lost_packets: Default::default(),
66        }
67    }
68
69    /// PacketList returns a list of Nack'd packets that's referenced by a NackPair
70    pub fn packet_list(&self) -> Vec<u16> {
71        self.into_iter().collect()
72    }
73
74    pub fn range<F>(&self, f: F)
75    where
76        F: Fn(u16) -> bool,
77    {
78        for packet_id in self.into_iter() {
79            if !f(packet_id) {
80                return;
81            }
82        }
83    }
84}
85
86/// Create an iterator over all the packet sequence numbers expressed by this NACK pair.
87impl IntoIterator for NackPair {
88    type Item = u16;
89
90    type IntoIter = NackIterator;
91
92    fn into_iter(self) -> Self::IntoIter {
93        NackIterator {
94            packet_id: self.packet_id,
95            bitfield: self.lost_packets,
96            has_yielded_packet_id: false,
97        }
98    }
99}
100
101const TLN_LENGTH: usize = 2;
102const NACK_OFFSET: usize = 8;
103
104// The TransportLayerNack packet informs the encoder about the loss of a transport packet
105/// ## Specifications
106///
107/// * [RFC 4585 §6.2.1]
108///
109/// [RFC 4585 §6.2.1]: https://tools.ietf.org/html/rfc4585#section-6.2.1
110#[derive(Debug, PartialEq, Eq, Default, Clone)]
111pub struct TransportLayerNack {
112    /// SSRC of sender
113    pub sender_ssrc: u32,
114    /// SSRC of the media source
115    pub media_ssrc: u32,
116
117    pub nacks: Vec<NackPair>,
118}
119
120impl fmt::Display for TransportLayerNack {
121    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122        let mut out = format!("TransportLayerNack from {:x}\n", self.sender_ssrc);
123        out += format!("\tMedia Ssrc {:x}\n", self.media_ssrc).as_str();
124        out += "\tID\tLostPackets\n";
125        for nack in &self.nacks {
126            out += format!("\t{}\t{:b}\n", nack.packet_id, nack.lost_packets).as_str();
127        }
128        write!(f, "{out}")
129    }
130}
131
132impl Packet for TransportLayerNack {
133    /// returns the Header associated with this packet.
134    fn header(&self) -> Header {
135        Header {
136            padding: get_padding_size(self.raw_size()) != 0,
137            count: FORMAT_TLN,
138            packet_type: PacketType::TransportSpecificFeedback,
139            length: ((self.marshal_size() / 4) - 1) as u16,
140        }
141    }
142
143    /// destination_ssrc returns an array of SSRC values that this packet refers to.
144    fn destination_ssrc(&self) -> Vec<u32> {
145        vec![self.media_ssrc]
146    }
147
148    fn raw_size(&self) -> usize {
149        HEADER_LENGTH + NACK_OFFSET + self.nacks.len() * 4
150    }
151
152    fn as_any(&self) -> &(dyn Any + Send + Sync) {
153        self
154    }
155
156    fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
157        other.as_any().downcast_ref::<TransportLayerNack>() == Some(self)
158    }
159
160    fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
161        Box::new(self.clone())
162    }
163}
164
165impl MarshalSize for TransportLayerNack {
166    fn marshal_size(&self) -> usize {
167        let l = self.raw_size();
168        // align to 32-bit boundary
169        l + get_padding_size(l)
170    }
171}
172
173impl Marshal for TransportLayerNack {
174    /// Marshal encodes the packet in binary.
175    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error> {
176        if self.nacks.len() + TLN_LENGTH > u8::MAX as usize {
177            return Err(Error::TooManyReports.into());
178        }
179        if buf.remaining_mut() < self.marshal_size() {
180            return Err(Error::BufferTooShort.into());
181        }
182
183        let h = self.header();
184        let n = h.marshal_to(buf)?;
185        buf = &mut buf[n..];
186
187        buf.put_u32(self.sender_ssrc);
188        buf.put_u32(self.media_ssrc);
189
190        for i in 0..self.nacks.len() {
191            buf.put_u16(self.nacks[i].packet_id);
192            buf.put_u16(self.nacks[i].lost_packets);
193        }
194
195        if h.padding {
196            put_padding(buf, self.raw_size());
197        }
198
199        Ok(self.marshal_size())
200    }
201}
202
203impl Unmarshal for TransportLayerNack {
204    /// Unmarshal decodes the ReceptionReport from binary
205    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error>
206    where
207        Self: Sized,
208        B: Buf,
209    {
210        let raw_packet_len = raw_packet.remaining();
211        if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
212            return Err(Error::PacketTooShort.into());
213        }
214
215        let h = Header::unmarshal(raw_packet)?;
216
217        if raw_packet_len < (HEADER_LENGTH + (4 * h.length) as usize) {
218            return Err(Error::PacketTooShort.into());
219        }
220
221        if h.packet_type != PacketType::TransportSpecificFeedback || h.count != FORMAT_TLN {
222            return Err(Error::WrongType.into());
223        }
224
225        let sender_ssrc = raw_packet.get_u32();
226        let media_ssrc = raw_packet.get_u32();
227
228        let mut nacks = vec![];
229        for _i in 0..(h.length as i32 - NACK_OFFSET as i32 / 4) {
230            nacks.push(NackPair {
231                packet_id: raw_packet.get_u16(),
232                lost_packets: raw_packet.get_u16(),
233            });
234        }
235
236        if
237        /*h.padding &&*/
238        raw_packet.has_remaining() {
239            raw_packet.advance(raw_packet.remaining());
240        }
241
242        Ok(TransportLayerNack {
243            sender_ssrc,
244            media_ssrc,
245            nacks,
246        })
247    }
248}
249
250pub fn nack_pairs_from_sequence_numbers(seq_nos: &[u16]) -> Vec<NackPair> {
251    if seq_nos.is_empty() {
252        return vec![];
253    }
254
255    let mut nack_pair = NackPair::new(seq_nos[0]);
256    let mut pairs = vec![];
257
258    for &seq in seq_nos.iter().skip(1) {
259        if seq == nack_pair.packet_id {
260            continue;
261        }
262        if seq <= nack_pair.packet_id || seq > nack_pair.packet_id.saturating_add(16) {
263            pairs.push(nack_pair);
264            nack_pair = NackPair::new(seq);
265            continue;
266        }
267
268        // Subtraction here is safe because the above checks that seqnum > nack_pair.packet_id.
269        nack_pair.lost_packets |= 1 << (seq - nack_pair.packet_id - 1);
270    }
271
272    pairs.push(nack_pair);
273
274    pairs
275}