Skip to content

Commit

Permalink
packet: support creating a builder from an existing packet
Browse files Browse the repository at this point in the history
  • Loading branch information
ystreet committed Jan 19, 2024
1 parent 19a9039 commit 2c305f8
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
11 changes: 10 additions & 1 deletion fuzz/fuzz_targets/rtp_from_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,14 @@
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
let _packet = rtp_types::RtpPacket::parse(data);
if let Ok(packet) = rtp_types::RtpPacket::parse(data) {
let mut built = vec![];
packet.as_builder().write(&mut built).unwrap();
if let Some(padding) = packet.padding() {
// ignore any padding as its contents in the original data are undefined
assert_eq!(&built[..built.len() - padding as usize], &data[..data.len() - padding as usize]);
} else {
assert_eq!(&built, &data);
}
}
});
24 changes: 24 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,24 @@ impl<'a> RtpPacketBuilder<'a> {
self
}

/// Set 1. whether padding is used and 2. the number of padding bytes to use for this packet
pub fn maybe_padding(mut self, padding: Option<u8>) -> Self {
self.padding = padding;
self
}

/// Add a Contribution Source for this packet
pub fn add_csrc(mut self, csrc: u32) -> Self {
self.csrcs.push(csrc);
self
}

/// Clear any CSRCs configured for this packet
pub fn clear_csrcs(mut self) -> Self {
self.csrcs.clear();
self
}

/// Set the marker bit for this packet
pub fn marker(mut self, marker: bool) -> Self {
self.marker = marker;
Expand Down Expand Up @@ -113,6 +125,12 @@ impl<'a> RtpPacketBuilder<'a> {
self
}

/// Clear any extension data configured for this packet
pub fn clear_extension(mut self) -> Self {
self.extension = None;
self
}

/// Add a chunk of payload data for this packet.
///
/// Can be called multiple times, in which case the payload data chunks will be
Expand All @@ -122,6 +140,12 @@ impl<'a> RtpPacketBuilder<'a> {
self
}

/// Clear any payloads currently configured
pub fn clear_payloads(mut self) -> Self {
self.payloads.clear();
self
}

/// Calculate the size required for writing the packet.
pub fn calculate_size(&self) -> Result<usize, RtpWriteError> {
let payload_len = self.payloads.iter().map(|p| p.len()).sum::<usize>();
Expand Down
38 changes: 37 additions & 1 deletion src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ impl<'a> RtpPacket<'a> {
pub fn extension(&self) -> Option<(u16, &[u8])> {
if self.extension_bit() {
let offset = self.extension_offset();
println!("{offset} {}", self.data.len());
let id = (self.data[offset] as u16) << 8 | self.data[offset + 1] as u16;
let offset = offset + 4;
Some((id, &self.data[offset..offset + self.extension_len()]))
Expand Down Expand Up @@ -254,6 +253,28 @@ impl<'a> RtpPacket<'a> {
};
&self.data[offset..self.data.len() - pad]
}

/// Creates a builder that will be able to reconstruct this packet byte for byte (excluding
/// any padding bytes). Any aspect of the returned builder can be modified.
pub fn as_builder(&'a self) -> crate::RtpPacketBuilder<'a> {
let mut builder = crate::RtpPacketBuilder::new()
.marker(self.marker())
.payload_type(self.payload_type())
.sequence_number(self.sequence_number())
.timestamp(self.timestamp())
.ssrc(self.ssrc())
.payload(self.payload());
for csrc in self.csrc() {
builder = builder.add_csrc(csrc);
}
if let Some((ext_id, ext_data)) = self.extension() {
builder = builder.extension(ext_id, ext_data);
}
if let Some(padding) = self.padding() {
builder = builder.padding(padding);
}
builder
}
}

#[cfg(test)]
Expand All @@ -277,6 +298,9 @@ mod tests {
assert_eq!(rtp.csrc().count(), 0);
assert_eq!(rtp.extension(), None);
assert_eq!(rtp.payload(), &[]);
let mut built = vec![];
rtp.as_builder().write(&mut built).unwrap();
assert_eq!(built, data.as_ref());
}

#[test]
Expand Down Expand Up @@ -313,6 +337,9 @@ mod tests {
assert_eq!(csrc.next(), None);
assert_eq!(rtp.extension(), None);
assert_eq!(rtp.payload(), &[]);
let mut built = vec![];
rtp.as_builder().write(&mut built).unwrap();
assert_eq!(built, data.as_ref());
}

#[test]
Expand Down Expand Up @@ -351,6 +378,9 @@ mod tests {
Some((0x0b0c, [0x0d, 0x0e, 0x0f, 0x10].as_ref()))
);
assert_eq!(rtp.payload(), &[]);
let mut built = vec![];
rtp.as_builder().write(&mut built).unwrap();
assert_eq!(built, data.as_ref());
}

#[test]
Expand Down Expand Up @@ -401,6 +431,9 @@ mod tests {
assert_eq!(rtp.csrc().count(), 0);
assert_eq!(rtp.extension(), None);
assert_eq!(rtp.payload(), &[0x0b, 0x0c, 0x0d, 0x0e]);
let mut built = vec![];
rtp.as_builder().write(&mut built).unwrap();
assert_eq!(built, data.as_ref());
}

#[test]
Expand All @@ -421,6 +454,9 @@ mod tests {
assert_eq!(rtp.csrc().count(), 0);
assert_eq!(rtp.extension(), None);
assert_eq!(rtp.payload(), &[0x0b, 0x0c]);
let mut built = vec![];
rtp.as_builder().write(&mut built).unwrap();
assert_eq!(built, data.as_ref());
}

#[test]
Expand Down

0 comments on commit 2c305f8

Please sign in to comment.