use anyhow::Result;
use rustrtc::{DataChannelEvent, PeerConnection, RtcConfiguration};
use std::time::{Duration, Instant};
#[tokio::test]
async fn test_sctp_reliability_under_loss() -> Result<()> {
let _ = env_logger::builder().is_test(true).try_init();
let config = RtcConfiguration::default();
let pc1 = PeerConnection::new(config.clone());
let pc2 = PeerConnection::new(config);
let dc1 = pc1.create_data_channel("reliable", None)?;
let offer = pc1.create_offer().await?;
pc1.set_local_description(offer.clone())?;
pc1.wait_for_gathering_complete().await;
let offer = pc1.local_description().unwrap();
pc2.set_remote_description(offer).await?;
let answer = pc2.create_answer().await?;
pc2.set_local_description(answer.clone())?;
pc2.wait_for_gathering_complete().await;
let answer = pc2.local_description().unwrap();
pc1.set_remote_description(answer).await?;
tokio::try_join!(pc1.wait_for_connected(), pc2.wait_for_connected())?;
println!("Connected!");
unsafe {
std::env::set_var("RUSTRTC_PACKET_LOSS", "30.0");
}
let mut dc1_open = false;
while let Some(event) = dc1.recv().await {
if let DataChannelEvent::Open = event {
dc1_open = true;
break;
}
}
assert!(dc1_open);
let mut dc2 = None;
while let Ok(Some(event)) = tokio::time::timeout(Duration::from_secs(5), pc2.recv()).await {
if let PeerConnectionEvent::DataChannel(dc) = event {
dc2 = Some(dc);
break;
}
}
let dc2 = dc2.expect("DC2 not received");
let data = b"Hello, reliability!";
pc1.send_data(dc1.id, data).await?;
let mut received = false;
let start = Instant::now();
while start.elapsed() < Duration::from_secs(10) {
if let Ok(Some(event)) = tokio::time::timeout(Duration::from_millis(100), dc2.recv()).await
{
match event {
DataChannelEvent::Message(msg) => {
assert_eq!(msg.as_ref(), data);
received = true;
break;
}
DataChannelEvent::Open => {
println!("DC2 Open");
}
_ => {}
}
}
}
assert!(received, "Message not received within timeout");
Ok(())
}
use rustrtc::PeerConnectionEvent;