webrtc-util 0.17.1

Utilities for WebRTC.rs stack
Documentation
use std::net::IpAddr;
use std::str::FromStr;

use async_trait::async_trait;

use super::*;
use crate::vnet::chunk::*;
use crate::vnet::conn::*;

#[derive(Default)]
struct DummyObserver;

#[async_trait]
impl ConnObserver for DummyObserver {
    async fn write(&self, _c: Box<dyn Chunk + Send + Sync>) -> Result<()> {
        Ok(())
    }

    async fn on_closed(&self, _addr: SocketAddr) {}

    fn determine_source_ip(&self, loc_ip: IpAddr, _dst_ip: IpAddr) -> Option<IpAddr> {
        Some(loc_ip)
    }
}

#[tokio::test]
async fn test_udp_conn_map_insert_remove() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in = Arc::new(UdpConn::new(
        SocketAddr::from_str("127.0.0.1:1234")?,
        None,
        obs,
    ));

    conn_map.insert(Arc::clone(&conn_in)).await?;

    let conn_out = conn_map.find(&conn_in.local_addr()?).await;
    assert!(conn_out.is_some(), "should succeed");
    if let Some(conn_out) = conn_out {
        assert_eq!(
            conn_in.local_addr()?,
            conn_out.local_addr()?,
            "should match"
        );
        let port_map = conn_map.port_map.lock().await;
        assert_eq!(port_map.len(), 1, "should match");
    }

    conn_map.delete(&conn_in.local_addr()?).await?;
    {
        let port_map = conn_map.port_map.lock().await;
        assert_eq!(port_map.len(), 0, "should match");
    }

    let result = conn_map.delete(&conn_in.local_addr()?).await;
    assert!(result.is_err(), "should fail");

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_insert_0_remove() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in = Arc::new(UdpConn::new(
        SocketAddr::from_str("0.0.0.0:1234")?,
        None,
        obs,
    ));

    conn_map.insert(Arc::clone(&conn_in)).await?;

    let conn_out = conn_map.find(&conn_in.local_addr()?).await;
    assert!(conn_out.is_some(), "should succeed");
    if let Some(conn_out) = conn_out {
        assert_eq!(
            conn_in.local_addr()?,
            conn_out.local_addr()?,
            "should match"
        );
        let port_map = conn_map.port_map.lock().await;
        assert_eq!(port_map.len(), 1, "should match");
    }

    conn_map.delete(&conn_in.local_addr()?).await?;
    {
        let port_map = conn_map.port_map.lock().await;
        assert_eq!(port_map.len(), 0, "should match");
    }

    let result = conn_map.delete(&conn_in.local_addr()?).await;
    assert!(result.is_err(), "should fail");

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_find_0() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in = Arc::new(UdpConn::new(
        SocketAddr::from_str("0.0.0.0:1234")?,
        None,
        obs,
    ));

    conn_map.insert(Arc::clone(&conn_in)).await?;

    let addr = SocketAddr::from_str("192.168.0.1:1234")?;
    let conn_out = conn_map.find(&addr).await;
    assert!(conn_out.is_some(), "should succeed");
    if let Some(conn_out) = conn_out {
        let addr_in = conn_in.local_addr()?;
        let addr_out = conn_out.local_addr()?;
        assert_eq!(addr_in, addr_out, "should match");
        let port_map = conn_map.port_map.lock().await;
        assert_eq!(port_map.len(), 1, "should match");
    }

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_insert_many_ips_with_same_port() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in1 = Arc::new(UdpConn::new(
        SocketAddr::from_str("10.1.2.1:5678")?,
        None,
        Arc::clone(&obs),
    ));

    let conn_in2 = Arc::new(UdpConn::new(
        SocketAddr::from_str("10.1.2.2:5678")?,
        None,
        Arc::clone(&obs),
    ));

    conn_map.insert(Arc::clone(&conn_in1)).await?;
    conn_map.insert(Arc::clone(&conn_in2)).await?;

    let addr1 = SocketAddr::from_str("10.1.2.1:5678")?;
    let conn_out1 = conn_map.find(&addr1).await;
    assert!(conn_out1.is_some(), "should succeed");
    if let Some(conn_out1) = conn_out1 {
        let addr_in = conn_in1.local_addr()?;
        let addr_out = conn_out1.local_addr()?;
        assert_eq!(addr_in, addr_out, "should match");
        let port_map = conn_map.port_map.lock().await;
        assert_eq!(port_map.len(), 1, "should match");
    }

    let addr2 = SocketAddr::from_str("10.1.2.2:5678")?;
    let conn_out2 = conn_map.find(&addr2).await;
    assert!(conn_out2.is_some(), "should succeed");
    if let Some(conn_out2) = conn_out2 {
        let addr_in = conn_in2.local_addr()?;
        let addr_out = conn_out2.local_addr()?;
        assert_eq!(addr_in, addr_out, "should match");
        let port_map = conn_map.port_map.lock().await;
        assert_eq!(port_map.len(), 1, "should match");
    }

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_already_inuse_when_insert_0() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in1 = Arc::new(UdpConn::new(
        SocketAddr::from_str("10.1.2.1:5678")?,
        None,
        Arc::clone(&obs),
    ));
    let conn_in2 = Arc::new(UdpConn::new(
        SocketAddr::from_str("0.0.0.0:5678")?,
        None,
        Arc::clone(&obs),
    ));

    conn_map.insert(Arc::clone(&conn_in1)).await?;
    let result = conn_map.insert(Arc::clone(&conn_in2)).await;
    assert!(result.is_err(), "should fail");

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_already_inuse_when_insert_a_specified_ip() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in1 = Arc::new(UdpConn::new(
        SocketAddr::from_str("0.0.0.0:5678")?,
        None,
        Arc::clone(&obs),
    ));
    let conn_in2 = Arc::new(UdpConn::new(
        SocketAddr::from_str("192.168.0.1:5678")?,
        None,
        Arc::clone(&obs),
    ));

    conn_map.insert(Arc::clone(&conn_in1)).await?;
    let result = conn_map.insert(Arc::clone(&conn_in2)).await;
    assert!(result.is_err(), "should fail");

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_already_inuse_when_insert_same_specified_ip() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in1 = Arc::new(UdpConn::new(
        SocketAddr::from_str("192.168.0.1:5678")?,
        None,
        Arc::clone(&obs),
    ));
    let conn_in2 = Arc::new(UdpConn::new(
        SocketAddr::from_str("192.168.0.1:5678")?,
        None,
        Arc::clone(&obs),
    ));

    conn_map.insert(Arc::clone(&conn_in1)).await?;
    let result = conn_map.insert(Arc::clone(&conn_in2)).await;
    assert!(result.is_err(), "should fail");

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_find_failure_1() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in = Arc::new(UdpConn::new(
        SocketAddr::from_str("192.168.0.1:5678")?,
        None,
        obs,
    ));

    conn_map.insert(Arc::clone(&conn_in)).await?;

    let addr = SocketAddr::from_str("192.168.0.2:5678")?;
    let result = conn_map.find(&addr).await;
    assert!(result.is_none(), "should be none");

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_find_failure_2() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in = Arc::new(UdpConn::new(
        SocketAddr::from_str("192.168.0.1:5678")?,
        None,
        obs,
    ));

    conn_map.insert(Arc::clone(&conn_in)).await?;

    let addr = SocketAddr::from_str("192.168.0.1:1234")?;
    let result = conn_map.find(&addr).await;
    assert!(result.is_none(), "should be none");

    Ok(())
}

#[tokio::test]
async fn test_udp_conn_map_insert_two_on_same_port_then_remove() -> Result<()> {
    let conn_map = UdpConnMap::new();

    let obs: Arc<Mutex<dyn ConnObserver + Send + Sync>> = Arc::new(Mutex::new(DummyObserver));

    let conn_in1 = Arc::new(UdpConn::new(
        SocketAddr::from_str("192.168.0.1:5678")?,
        None,
        Arc::clone(&obs),
    ));
    let conn_in2 = Arc::new(UdpConn::new(
        SocketAddr::from_str("192.168.0.2:5678")?,
        None,
        Arc::clone(&obs),
    ));

    conn_map.insert(Arc::clone(&conn_in1)).await?;
    conn_map.insert(Arc::clone(&conn_in2)).await?;

    conn_map.delete(&conn_in1.local_addr()?).await?;
    conn_map.delete(&conn_in2.local_addr()?).await?;

    Ok(())
}