use std::collections::VecDeque;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::time::{Duration, Instant};
use crate::change::{SdpAnswer, SdpOffer};
use crate::format::Codec;
use crate::net::{Protocol, Receive};
use crate::packet::{CodecDepacketizer, CodecExtra, Depacketizer, DepacketizingBuffer, RtpMeta};
use crate::rtp_::{Frequency, MediaTime, Rtcp, RtcpFb, RtpHeader};
use crate::streams::register::ReceiverRegister;
use crate::streams::rtx_cache_buf::EvictingBuffer;
use crate::{Input, Output, Rtc};
use super::Rng;
#[allow(unused)]
use super::setup::{random_config, random_extmap};
pub fn rtx_buffer(data: &[u8]) {
if data.len() < 4 {
return;
}
let buf_size = u16::from_be_bytes([data[0], data[1]]);
let max_age = data[2] as u64;
let max_size = data[3] as usize;
let mut buf = EvictingBuffer::new(buf_size as usize, Duration::from_secs(max_age), max_size);
let mut now = Instant::now();
let mut pos = 0;
for d in &data[4..] {
now += Duration::from_millis(*d as u64);
if d % 2 == 0 {
buf.maybe_evict(now)
} else {
pos += *d as u64;
buf.push(pos, now, d);
}
}
}
pub fn rtp_header(data: &[u8]) -> Option<()> {
let mut rng = Rng::new(data);
let exts = random_extmap(&mut rng, 10)?;
let len = rng.usize(76)?;
RtpHeader::_parse(rng.slice(len)?, &exts);
Some(())
}
pub fn rtp_packet(data: &[u8]) -> Option<()> {
let mut rng = Rng::new(data);
let exts = random_extmap(&mut rng, 10)?;
let packet_len = rng.usize(1500)?;
let packet = rng.slice(packet_len)?;
let header = RtpHeader::_parse(packet, &exts)?;
let _payload = packet.get(header.header_len..)?;
Some(())
}
pub fn sdp_offer(data: &[u8]) -> Option<()> {
let str = std::str::from_utf8(data).ok()?;
let _ = SdpOffer::from_sdp_string(str);
Some(())
}
pub fn sdp_answer(data: &[u8]) -> Option<()> {
let str = std::str::from_utf8(data).ok()?;
let _ = SdpAnswer::from_sdp_string(str);
Some(())
}
pub fn depack(data: &[u8]) -> Option<()> {
let mut rng = Rng::new(data);
let codec = match rng.u8(10)? {
0 => Codec::Opus,
1 => Codec::Vp8,
2 => Codec::Vp9,
3 => Codec::H264,
4 => Codec::H265,
5 => Codec::H266,
6 => Codec::Av1,
7 => Codec::PCMU,
8 => Codec::PCMA,
9 => Codec::G722,
10 => Codec::CN,
_ => unreachable!(),
};
let mut depack = DepacketizingBuffer::new(codec.into(), rng.usize(300)?);
let exts = random_extmap(&mut rng, 10)?;
let start = Instant::now();
loop {
let do_push = rng.bool()?;
if do_push {
let hlen = rng.usize(76)?;
let header = RtpHeader::_parse(rng.slice(hlen)?, &exts)?;
let meta = RtpMeta {
received: start + Duration::from_millis(rng.u64(10000)?),
time: MediaTime::new(rng.u64(u64::MAX)?, Frequency::MICROS),
seq_no: rng.u64(u64::MAX)?.into(),
header,
last_sender_info: None,
};
let len = rng.usize(1200)?;
let data = rng.slice(len)?.to_vec();
depack.push(meta, data);
} else {
depack.pop();
}
}
}
pub fn receive_register(data: &[u8]) -> Option<()> {
let mut rng = Rng::new(data);
let mut rr = ReceiverRegister::new(None);
let start = Instant::now();
loop {
match rng.u8(2)? {
0 => {
let seq = rng.u64(u64::MAX / 2)?;
let arrival = start + Duration::from_micros(rng.u64(u64::MAX / 100)?);
let rtp_time = rng.u32(u32::MAX / 2)?;
let clock_rate = rng.u32(u32::MAX / 2)?;
rr.update(seq.into(), arrival, rtp_time, clock_rate);
}
1 => {
rr.nack_report();
}
2 => {
rr.reception_report();
}
_ => unreachable!(),
}
}
}
pub fn receive(data: &[u8]) -> Option<()> {
let mut rng = Rng::new(data);
let base = Instant::now();
let mut rtc = Rtc::new(base);
let source = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)), 5000);
let destination = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(2, 2, 2, 2)), 5001);
let mut millis: u64 = 0;
loop {
millis += rng.u64(50)?;
let now = base + Duration::from_millis(millis);
if rng.bool()? {
let len = rng.usize(2000)?;
let buf = rng.slice(len)?;
if let Ok(receive) = Receive::new(Protocol::Udp, source, destination, buf) {
let _ = rtc.handle_input(Input::Receive(now, receive));
}
} else {
let _ = rtc.handle_input(Input::Timeout(now));
}
for _ in 0..1000 {
match rtc.poll_output() {
Ok(Output::Timeout(_)) => break,
Ok(_) => continue,
Err(_) => break,
}
}
if !rtc.is_alive() {
return Some(());
}
}
}
pub fn stun(data: &[u8]) -> Option<()> {
let _ = is::stun::StunMessage::parse(data);
Some(())
}
pub fn rtcp(data: &[u8]) -> Option<()> {
let mut feedback = VecDeque::new();
Rtcp::read_packet(data, &mut feedback);
let _ = RtcpFb::from_rtcp(feedback.drain(..)).count();
Some(())
}
pub fn depack_direct(data: &[u8]) -> Option<()> {
let mut rng = Rng::new(data);
let codec = match rng.u8(10)? {
0 => Codec::Opus,
1 => Codec::Vp8,
2 => Codec::Vp9,
3 => Codec::H264,
4 => Codec::H265,
5 => Codec::H266,
6 => Codec::Av1,
7 => Codec::PCMU,
8 => Codec::PCMA,
9 => Codec::G722,
10 => Codec::CN,
_ => unreachable!(),
};
let mut depack: CodecDepacketizer = codec.into();
let mut out = Vec::new();
let mut extra = CodecExtra::None;
loop {
let marker = rng.bool()?;
let len = rng.usize(1500)?;
let packet = rng.slice(len)?;
let _ = depack.depacketize(packet, &mut out, &mut extra);
let _ = depack.is_partition_head(packet);
let _ = depack.is_partition_tail(marker, packet);
if out.len() > 4_000_000 {
out.clear();
}
}
}