//! SIP UDP transport — owns the main SIP socket. //! //! Binds a UDP socket, receives SIP messages, and provides a send method. use std::net::SocketAddr; use std::sync::Arc; use tokio::net::UdpSocket; /// The SIP UDP transport layer. pub struct SipTransport { socket: Arc, } impl SipTransport { /// Bind a UDP socket on the given address (e.g. "0.0.0.0:5070"). pub async fn bind(bind_addr: &str) -> Result { let socket = UdpSocket::bind(bind_addr) .await .map_err(|e| format!("bind {bind_addr}: {e}"))?; Ok(Self { socket: Arc::new(socket), }) } /// Get a clone of the socket Arc for the receiver task. pub fn socket(&self) -> Arc { self.socket.clone() } /// Send a raw SIP message to a destination. pub async fn send_to(&self, data: &[u8], dest: SocketAddr) -> Result { self.socket .send_to(data, dest) .await .map_err(|e| format!("send to {dest}: {e}")) } /// Send a raw SIP message to an address:port pair. pub async fn send_to_addr(&self, data: &[u8], addr: &str, port: u16) -> Result { let dest: SocketAddr = format!("{addr}:{port}") .parse() .map_err(|e| format!("bad address {addr}:{port}: {e}"))?; self.send_to(data, dest).await } /// Spawn the UDP receive loop. Calls the handler for every received packet. pub fn spawn_receiver( &self, handler: F, ) where F: Fn(&[u8], SocketAddr) + Send + 'static, { let socket = self.socket.clone(); tokio::spawn(async move { let mut buf = vec![0u8; 65535]; loop { match socket.recv_from(&mut buf).await { Ok((n, addr)) => handler(&buf[..n], addr), Err(e) => { eprintln!("[sip_transport] recv error: {e}"); tokio::time::sleep(std::time::Duration::from_millis(100)).await; } } } }); } }