#![feature(random)] use std::{ collections::HashSet, random::random, time::{Duration, Instant}, }; use log::debug; use rtcp::{RtcpPacket, RtcpPart}; use rtp::SSRC; pub mod rtcp; pub mod rtp; pub struct Session { tp: Instant, tc: Instant, tn: Instant, pmembers: usize, members: usize, senders: usize, rtcp_bw: f32, we_sent: bool, avg_rtcp_size: f32, initial: bool, member_table: HashSet, sender_table: HashSet, } impl Session { /// RFC 3550, Section 6.3.1 pub fn compute_rtcp_transmission_interval(&self) -> Duration { let n; let c; if self.senders * 4 < self.members { if self.we_sent { // Senders use a quarter of the bandwidth c = self.avg_rtcp_size / (self.rtcp_bw * 0.25); n = self.senders; } else { // Receivers use the remaining three quarters c = self.avg_rtcp_size / (self.rtcp_bw * 0.75); n = self.members - self.senders } } else { // Equally split between members c = self.avg_rtcp_size / self.rtcp_bw; n = self.members; } let tmin = if self.initial { 2.5f32 } else { 5. }; let td = tmin.max(n as f32 * c); let t = td * ((random::() as f32) / (u16::MAX as f32) + 0.5); let t = t / 1.5f32.exp(); debug!("RTCP transmission interval is {t:.02}s"); Duration::from_secs_f32(t) } /// RFC 3550, Section 6.3.2 pub fn new() -> Self { let mut se = Self { tp: Instant::now(), tc: Instant::now(), tn: Instant::now(), senders: 0, pmembers: 1, members: 1, we_sent: false, initial: true, sender_table: HashSet::new(), member_table: HashSet::new(), // TODO add own ssrc to members rtcp_bw: 1000., // TODO set rtcp bandwidth from params avg_rtcp_size: 1000., // TODO set to next likely rtcp packet size }; se.tn += se.compute_rtcp_transmission_interval(); se } pub fn tt_expire(&mut self) { let t = self.compute_rtcp_transmission_interval(); if self.tp + t < self.tc { self.send_rtcp(); self.tp = self.tc; let t = self.compute_rtcp_transmission_interval(); self.tn = self.tc + t; if self.tp + t > self.tc { self.tn = self.tp + t; } self.pmembers = self.members; } } pub fn send_rtcp(&mut self) { } /// RFC 3550, Section 6.3.3 / 6.3.4 pub fn on_receive(&mut self, packet_raw: &[u8]) { let packet = RtcpPacket::parse(packet_raw).unwrap(); // TODO let bye = packet.parts.iter().find_map(|p| match p { RtcpPart::Bye(b) => Some(b), _ => None, }); if let Some(bye) = bye { for s in &bye.ssrcs { if self.member_table.remove(s) { self.members -= 1; } if self.sender_table.remove(s) { self.senders -= 1; } } let f_mem = self.members as f32 / self.pmembers as f32; self.tn = self.tc + (self.tn - self.tc).mul_f32(f_mem); self.tp = self.tc - (self.tc - self.tp).mul_f32(f_mem); self.pmembers = self.members } else { self.avg_rtcp_size = (1. / 16.) * packet_raw.len() as f32 + (15. / 16.) * self.avg_rtcp_size; } } }