use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::sync::Mutex;
use webrtc_util::vnet::net::{Net, NetConfig};
use webrtc_util::vnet::router::{Router, RouterConfig};
pub struct VNetPair {
pub net_offerer: Arc<Net>,
pub net_answerer: Arc<Net>,
pub wan: Arc<Mutex<Router>>,
network_blocked: Arc<AtomicBool>,
}
impl VNetPair {
pub async fn new() -> anyhow::Result<Self> {
let network_blocked = Arc::new(AtomicBool::new(false));
let wan = Router::new(RouterConfig {
cidr: "192.168.0.0/24".to_string(),
..Default::default()
})?;
let wan = Arc::new(Mutex::new(wan));
let net_offerer = Net::new(Some(NetConfig {
static_ips: vec!["192.168.0.1".to_string()],
..Default::default()
}));
let net_answerer = Net::new(Some(NetConfig {
static_ips: vec!["192.168.0.2".to_string()],
..Default::default()
}));
let offerer_nic = net_offerer.get_nic()?;
let answerer_nic = net_answerer.get_nic()?;
{
let mut w = wan.lock().await;
w.add_net(offerer_nic.clone()).await?;
w.add_net(answerer_nic.clone()).await?;
}
{
let nic = offerer_nic.lock().await;
nic.set_router(wan.clone()).await?;
}
{
let nic = answerer_nic.lock().await;
nic.set_router(wan.clone()).await?;
}
let blocked = network_blocked.clone();
{
let w = wan.lock().await;
w.add_chunk_filter(Box::new(move |_chunk| {
!blocked.load(Ordering::SeqCst)
}))
.await;
}
{
let mut w = wan.lock().await;
w.start().await?;
}
tracing::info!("🌐 VNet pair created: offerer=192.168.0.1, answerer=192.168.0.2");
Ok(Self {
net_offerer: Arc::new(net_offerer),
net_answerer: Arc::new(net_answerer),
wan,
network_blocked,
})
}
pub fn block_network(&self) {
tracing::warn!("🔴 VNet: Blocking ALL network traffic");
self.network_blocked.store(true, Ordering::SeqCst);
}
pub fn unblock_network(&self) {
tracing::info!("🟢 VNet: Unblocking network traffic");
self.network_blocked.store(false, Ordering::SeqCst);
}
pub fn is_blocked(&self) -> bool {
self.network_blocked.load(Ordering::SeqCst)
}
}
impl Drop for VNetPair {
fn drop(&mut self) {
tracing::debug!("🧹 VNet: Dropping VNetPair");
}
}
pub async fn create_vnet_pair() -> anyhow::Result<VNetPair> {
VNetPair::new().await
}