const UINT16_SIZE_HALF: u16 = 1 << 15;
pub(crate) struct SendBuffer {
packets: Vec<Option<rtp::Packet>>,
size: u16,
highest_added: u16,
started: bool,
}
impl SendBuffer {
pub(crate) fn new(size: u16) -> Option<Self> {
let is_valid = (0..=15).any(|i| size == 1 << i);
if !is_valid {
return None;
}
Some(Self {
packets: vec![None; size as usize],
size,
highest_added: 0,
started: false,
})
}
pub(crate) fn add(&mut self, packet: rtp::Packet) {
let seq = packet.header.sequence_number;
if !self.started {
self.packets[(seq % self.size) as usize] = Some(packet);
self.highest_added = seq;
self.started = true;
return;
}
let diff = seq.wrapping_sub(self.highest_added);
if diff == 0 {
return;
} else if diff < UINT16_SIZE_HALF {
let mut i = self.highest_added.wrapping_add(1);
while i != seq {
let idx = (i % self.size) as usize;
self.packets[idx] = None;
i = i.wrapping_add(1);
}
self.highest_added = seq;
}
let idx = (seq % self.size) as usize;
self.packets[idx] = Some(packet);
}
pub(crate) fn get(&self, seq: u16) -> Option<&rtp::Packet> {
if !self.started {
return None;
}
let diff = self.highest_added.wrapping_sub(seq);
if diff >= UINT16_SIZE_HALF {
return None;
}
if diff >= self.size {
return None;
}
let idx = (seq % self.size) as usize;
let packet = self.packets[idx].as_ref()?;
if packet.header.sequence_number != seq {
return None;
}
Some(packet)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_packet(seq: u16) -> rtp::Packet {
rtp::Packet {
header: rtp::header::Header {
sequence_number: seq,
..Default::default()
},
payload: vec![seq as u8].into(),
}
}
#[test]
fn test_send_buffer_invalid_size() {
assert!(SendBuffer::new(0).is_none());
assert!(SendBuffer::new(3).is_none());
assert!(SendBuffer::new(5).is_none());
assert!(SendBuffer::new(100).is_none());
}
#[test]
fn test_send_buffer_valid_sizes() {
assert!(SendBuffer::new(1).is_some());
assert!(SendBuffer::new(2).is_some());
assert!(SendBuffer::new(8).is_some());
assert!(SendBuffer::new(1024).is_some());
assert!(SendBuffer::new(32768).is_some());
}
#[test]
fn test_send_buffer_basic() {
let mut buf = SendBuffer::new(8).unwrap();
buf.add(make_packet(0));
assert!(buf.get(0).is_some());
assert_eq!(buf.get(0).unwrap().header.sequence_number, 0);
assert!(buf.get(1).is_none());
}
#[test]
fn test_send_buffer_overwrite() {
let mut buf = SendBuffer::new(8).unwrap();
for i in 0..8 {
buf.add(make_packet(i));
}
for i in 0..8 {
assert!(buf.get(i).is_some());
}
buf.add(make_packet(8));
assert!(buf.get(8).is_some());
assert!(buf.get(0).is_none()); }
#[test]
fn test_send_buffer_gap_clears_packets() {
let mut buf = SendBuffer::new(8).unwrap();
buf.add(make_packet(0));
buf.add(make_packet(1));
buf.add(make_packet(2));
buf.add(make_packet(5));
assert!(buf.get(0).is_some());
assert!(buf.get(1).is_some());
assert!(buf.get(2).is_some());
assert!(buf.get(3).is_none()); assert!(buf.get(4).is_none()); assert!(buf.get(5).is_some());
}
#[test]
fn test_send_buffer_out_of_range() {
let mut buf = SendBuffer::new(8).unwrap();
for i in 0..8 {
buf.add(make_packet(i));
}
for i in 8..16 {
buf.add(make_packet(i));
}
for i in 0..8 {
assert!(buf.get(i).is_none());
}
for i in 8..16 {
assert!(buf.get(i).is_some());
}
}
#[test]
fn test_send_buffer_wraparound() {
let mut buf = SendBuffer::new(8).unwrap();
buf.add(make_packet(65534));
buf.add(make_packet(65535));
buf.add(make_packet(0));
buf.add(make_packet(1));
assert!(buf.get(65534).is_some());
assert!(buf.get(65535).is_some());
assert!(buf.get(0).is_some());
assert!(buf.get(1).is_some());
}
#[test]
fn test_send_buffer_out_of_order() {
let mut buf = SendBuffer::new(8).unwrap();
buf.add(make_packet(0));
buf.add(make_packet(2)); buf.add(make_packet(1));
assert!(buf.get(0).is_some());
assert!(buf.get(1).is_some());
assert!(buf.get(2).is_some());
}
}