use std::net::SocketAddr;
use std::sync::Arc;
use rvoip_sip_dialog::transaction::TransactionManager;
use rvoip_sip_proxy::{ProxyConfig, RouteFn, StatefulProxy};
use rvoip_sip_transport::transport::tcp::TcpTransport;
use rvoip_sip_transport::{Transport, TransportEvent, UdpTransport};
use tokio::sync::mpsc;
use tokio::task::JoinHandle;
use tracing::info;
pub use rvoip_sip_proxy::{ForkMode, ProxyError, ProxyEvent, ProxyResult, RouteDecision};
pub struct ProxyCoordinator {
proxy: Arc<StatefulProxy>,
transport: Arc<dyn Transport>,
local_addr: SocketAddr,
proxy_task: Option<JoinHandle<()>>,
}
impl std::fmt::Debug for ProxyCoordinator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ProxyCoordinator")
.field("local_addr", &self.local_addr)
.field("proxy", &self.proxy)
.finish_non_exhaustive()
}
}
impl ProxyCoordinator {
pub async fn bind(bind_addr: SocketAddr, route_fn: RouteFn) -> ProxyResult<Arc<Self>> {
Self::bind_with_config(bind_addr, route_fn, ProxyConfig::default()).await
}
pub async fn bind_with_config(
bind_addr: SocketAddr,
route_fn: RouteFn,
config: ProxyConfig,
) -> ProxyResult<Arc<Self>> {
let (udp, transport_rx) = UdpTransport::bind(bind_addr, None)
.await
.map_err(|e| ProxyError::Transport(format!("UDP bind: {}", e)))?;
let local_addr = udp
.local_addr()
.map_err(|e| ProxyError::Transport(format!("local_addr: {}", e)))?;
let transport: Arc<dyn Transport> = Arc::new(udp);
Self::new(transport, local_addr, transport_rx, route_fn, config).await
}
pub async fn bind_tcp(bind_addr: SocketAddr, route_fn: RouteFn) -> ProxyResult<Arc<Self>> {
Self::bind_tcp_with_config(bind_addr, route_fn, ProxyConfig::default()).await
}
pub async fn bind_tcp_with_config(
bind_addr: SocketAddr,
route_fn: RouteFn,
config: ProxyConfig,
) -> ProxyResult<Arc<Self>> {
let (tcp, transport_rx) = TcpTransport::bind(bind_addr, None, None)
.await
.map_err(|e| ProxyError::Transport(format!("TCP bind: {}", e)))?;
let local_addr = tcp
.local_addr()
.map_err(|e| ProxyError::Transport(format!("local_addr: {}", e)))?;
let transport: Arc<dyn Transport> = Arc::new(tcp);
Self::new(transport, local_addr, transport_rx, route_fn, config).await
}
pub async fn new(
transport: Arc<dyn Transport>,
local_addr: SocketAddr,
transport_rx: mpsc::Receiver<TransportEvent>,
route_fn: RouteFn,
config: ProxyConfig,
) -> ProxyResult<Arc<Self>> {
let (tm, events) = TransactionManager::new(transport.clone(), transport_rx, Some(64))
.await
.map_err(|e| ProxyError::Transaction(e.to_string()))?;
let tm = Arc::new(tm);
let proxy = StatefulProxy::with_config(tm, route_fn, config);
let proxy_task = proxy.clone().run(events);
info!("ProxyCoordinator bound at {}", local_addr);
Ok(Arc::new(Self {
proxy,
transport,
local_addr,
proxy_task: Some(proxy_task),
}))
}
pub fn local_addr(&self) -> SocketAddr {
self.local_addr
}
pub fn transport(&self) -> Arc<dyn Transport> {
self.transport.clone()
}
pub fn proxy(&self) -> Arc<StatefulProxy> {
self.proxy.clone()
}
pub fn subscribe_events(&self) -> tokio::sync::broadcast::Receiver<ProxyEvent> {
self.proxy.subscribe_events()
}
pub async fn shutdown(self: &Arc<Self>) -> ProxyResult<()> {
if let Some(task) = self.proxy_task.as_ref().map(|t| t.abort_handle()) {
task.abort();
}
self.transport.close().await.ok();
Ok(())
}
}