use crate::{
compound_packet::*, error::Error, goodbye::*, header::*,
payload_feedbacks::full_intra_request::*, payload_feedbacks::picture_loss_indication::*,
payload_feedbacks::receiver_estimated_maximum_bitrate::*,
payload_feedbacks::slice_loss_indication::*, raw_packet::*, receiver_report::*,
sender_report::*, source_description::*,
transport_feedbacks::rapid_resynchronization_request::*,
transport_feedbacks::transport_layer_cc::*, transport_feedbacks::transport_layer_nack::*,
};
use util::marshal::{Marshal, Unmarshal};
use anyhow::Result;
use bytes::Buf;
use std::any::Any;
use std::fmt;
pub trait Packet: Marshal + Unmarshal + fmt::Display + fmt::Debug {
fn header(&self) -> Header;
fn destination_ssrc(&self) -> Vec<u32>;
fn raw_size(&self) -> usize;
fn as_any(&self) -> &dyn Any;
fn equal(&self, other: &dyn Packet) -> bool;
fn cloned(&self) -> Box<dyn Packet>;
}
impl PartialEq for dyn Packet {
fn eq(&self, other: &Self) -> bool {
self.equal(other)
}
}
impl Clone for Box<dyn Packet> {
fn clone(&self) -> Box<dyn Packet> {
self.cloned()
}
}
pub fn unmarshal<B>(raw_data: &mut B) -> Result<Box<dyn Packet>>
where
B: Buf,
{
let mut packets = vec![];
while raw_data.has_remaining() {
let p = unmarshaller(raw_data)?;
packets.push(p);
}
match packets.len() {
0 => Err(Error::InvalidHeader.into()),
1 => packets.pop().ok_or_else(|| Error::BadFirstPacket.into()),
_ => Ok(Box::new(CompoundPacket(packets))),
}
}
pub(crate) fn unmarshaller<B>(raw_data: &mut B) -> Result<Box<dyn Packet>>
where
B: Buf,
{
let h = Header::unmarshal(raw_data)?;
let length = (h.length as usize) * 4;
if length > raw_data.remaining() {
return Err(Error::PacketTooShort.into());
}
let mut in_packet = h.marshal()?.chain(raw_data.take(length));
let p: Box<dyn Packet> = match h.packet_type {
PacketType::SenderReport => Box::new(SenderReport::unmarshal(&mut in_packet)?),
PacketType::ReceiverReport => Box::new(ReceiverReport::unmarshal(&mut in_packet)?),
PacketType::SourceDescription => Box::new(SourceDescription::unmarshal(&mut in_packet)?),
PacketType::Goodbye => Box::new(Goodbye::unmarshal(&mut in_packet)?),
PacketType::TransportSpecificFeedback => match h.count {
FORMAT_TLN => Box::new(TransportLayerNack::unmarshal(&mut in_packet)?),
FORMAT_RRR => Box::new(RapidResynchronizationRequest::unmarshal(&mut in_packet)?),
FORMAT_TCC => Box::new(TransportLayerCc::unmarshal(&mut in_packet)?),
_ => Box::new(RawPacket::unmarshal(&mut in_packet)?),
},
PacketType::PayloadSpecificFeedback => match h.count {
FORMAT_PLI => Box::new(PictureLossIndication::unmarshal(&mut in_packet)?),
FORMAT_SLI => Box::new(SliceLossIndication::unmarshal(&mut in_packet)?),
FORMAT_REMB => Box::new(ReceiverEstimatedMaximumBitrate::unmarshal(&mut in_packet)?),
FORMAT_FIR => Box::new(FullIntraRequest::unmarshal(&mut in_packet)?),
_ => Box::new(RawPacket::unmarshal(&mut in_packet)?),
},
_ => Box::new(RawPacket::unmarshal(&mut in_packet)?),
};
Ok(p)
}
#[cfg(test)]
mod test {
use super::*;
use crate::reception_report::*;
use bytes::Bytes;
#[test]
fn test_packet_unmarshal() {
let mut data = Bytes::from_static(&[
0x81, 0xc9, 0x0, 0x7, 0x90, 0x2f, 0x9e, 0x2e, 0xbc, 0x5e, 0x9a, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0xe1, 0x0, 0x0, 0x1, 0x11, 0x9, 0xf3, 0x64, 0x32, 0x0, 0x2, 0x4a, 0x79, 0x81, 0xca, 0x0, 0xc, 0x90, 0x2f, 0x9e, 0x2e, 0x1, 0x26, 0x7b, 0x39, 0x63, 0x30, 0x30, 0x65, 0x62, 0x39, 0x32, 0x2d, 0x31, 0x61, 0x66, 0x62,
0x2d, 0x39, 0x64, 0x34, 0x39, 0x2d, 0x61, 0x34, 0x37, 0x64, 0x2d, 0x39, 0x31, 0x66,
0x36, 0x34, 0x65, 0x65, 0x65, 0x36, 0x39, 0x66, 0x35,
0x7d, 0x0, 0x0, 0x0, 0x0, 0x81, 0xcb, 0x0, 0x1, 0x90, 0x2f, 0x9e, 0x2e, 0x81, 0xce, 0x0, 0x2, 0x90, 0x2f, 0x9e, 0x2e, 0x90, 0x2f, 0x9e, 0x2e, 0x85, 0xcd, 0x0, 0x2, 0x90, 0x2f, 0x9e, 0x2e, 0x90, 0x2f, 0x9e, 0x2e, ]);
let packet = unmarshal(&mut data).expect("Error unmarshalling packets");
let a = ReceiverReport {
ssrc: 0x902f9e2e,
reports: vec![ReceptionReport {
ssrc: 0xbc5e9a40,
fraction_lost: 0,
total_lost: 0,
last_sequence_number: 0x46e1,
jitter: 273,
last_sender_report: 0x9f36432,
delay: 150137,
}],
..Default::default()
};
let b = SourceDescription {
chunks: vec![SourceDescriptionChunk {
source: 0x902f9e2e,
items: vec![SourceDescriptionItem {
sdes_type: SdesType::SdesCname,
text: Bytes::from_static(b"{9c00eb92-1afb-9d49-a47d-91f64eee69f5}"),
}],
}],
};
let c = Goodbye {
sources: vec![0x902f9e2e],
..Default::default()
};
let d = PictureLossIndication {
sender_ssrc: 0x902f9e2e,
media_ssrc: 0x902f9e2e,
};
let e = RapidResynchronizationRequest {
sender_ssrc: 0x902f9e2e,
media_ssrc: 0x902f9e2e,
};
let expected: Box<dyn Packet> = Box::new(CompoundPacket(vec![
Box::new(a),
Box::new(b),
Box::new(c),
Box::new(d),
Box::new(e),
]));
assert!(packet == expected, "Invalid packets");
}
#[test]
fn test_packet_unmarshal_empty() -> Result<()> {
let result = unmarshal(&mut Bytes::new());
if let Err(got) = result {
let want = Error::InvalidHeader;
assert!(
want.equal(&got),
"Unmarshal(nil) err = {}, want {}",
got,
want
);
} else {
assert!(false, "want error");
}
Ok(())
}
#[test]
fn test_packet_invalid_header_length() -> Result<()> {
let mut data = Bytes::from_static(&[
0x81, 0xcb, 0x0, 0x64,
]);
let result = unmarshal(&mut data);
if let Err(got) = result {
let want = Error::PacketTooShort;
assert!(
want.equal(&got),
"Unmarshal(invalid_header_length) err = {}, want {}",
got,
want
);
} else {
assert!(false, "want error");
}
Ok(())
}
}