#[cfg(test)]
mod compound_packet_test;
use std::any::Any;
use std::fmt;
use bytes::{Buf, Bytes};
use util::marshal::{Marshal, MarshalSize, Unmarshal};
use crate::error::Error;
use crate::header::*;
use crate::packet::*;
use crate::receiver_report::*;
use crate::sender_report::*;
use crate::source_description::*;
use crate::util::*;
type Result<T> = std::result::Result<T, util::Error>;
#[derive(Debug, Default, PartialEq, Clone)]
pub struct CompoundPacket(pub Vec<Box<dyn Packet + Send + Sync>>);
impl fmt::Display for CompoundPacket {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl Packet for CompoundPacket {
fn header(&self) -> Header {
Header::default()
}
fn destination_ssrc(&self) -> Vec<u32> {
if self.0.is_empty() {
vec![]
} else {
self.0[0].destination_ssrc()
}
}
fn raw_size(&self) -> usize {
let mut l = 0;
for packet in &self.0 {
l += packet.marshal_size();
}
l
}
fn as_any(&self) -> &(dyn Any + Send + Sync) {
self
}
fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
other.as_any().downcast_ref::<CompoundPacket>() == Some(self)
}
fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
Box::new(self.clone())
}
}
impl MarshalSize for CompoundPacket {
fn marshal_size(&self) -> usize {
let l = self.raw_size();
l + get_padding_size(l)
}
}
impl Marshal for CompoundPacket {
fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
self.validate()?;
for packet in &self.0 {
let n = packet.marshal_to(buf)?;
buf = &mut buf[n..];
}
Ok(self.marshal_size())
}
}
impl Unmarshal for CompoundPacket {
fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
where
Self: Sized,
B: Buf,
{
let mut packets = vec![];
while raw_packet.has_remaining() {
let p = unmarshaller(raw_packet)?;
packets.push(p);
}
let c = CompoundPacket(packets);
c.validate()?;
Ok(c)
}
}
impl CompoundPacket {
pub fn validate(&self) -> Result<()> {
if self.0.is_empty() {
return Err(Error::EmptyCompound.into());
}
if self.0[0].as_any().downcast_ref::<SenderReport>().is_none()
&& self.0[0]
.as_any()
.downcast_ref::<ReceiverReport>()
.is_none()
{
return Err(Error::BadFirstPacket.into());
}
for pkt in &self.0[1..] {
if pkt.as_any().downcast_ref::<ReceiverReport>().is_some() {
continue;
} else if let Some(e) = pkt.as_any().downcast_ref::<SourceDescription>() {
let mut has_cname = false;
for c in &e.chunks {
for it in &c.items {
if it.sdes_type == SdesType::SdesCname {
has_cname = true
}
}
}
if !has_cname {
return Err(Error::MissingCname.into());
}
return Ok(());
} else {
return Err(Error::PacketBeforeCname.into());
}
}
Err(Error::MissingCname.into())
}
pub fn cname(&self) -> Result<Bytes> {
if self.0.is_empty() {
return Err(Error::EmptyCompound.into());
}
for pkt in &self.0[1..] {
if let Some(sdes) = pkt.as_any().downcast_ref::<SourceDescription>() {
for c in &sdes.chunks {
for it in &c.items {
if it.sdes_type == SdesType::SdesCname {
return Ok(it.text.clone());
}
}
}
} else if pkt.as_any().downcast_ref::<ReceiverReport>().is_none() {
return Err(Error::PacketBeforeCname.into());
}
}
Err(Error::MissingCname.into())
}
}