use std::net::TcpListener; use std::os::unix::net::UnixListener; use std::thread; use anyhow::Result; use super::conn::Connection; enum ListenerKind { Tcp(TcpListener), Unix(UnixListener), } pub struct IpcServer { listener: ListenerKind, } impl IpcServer { pub fn bind(addr: &str) -> Result { let listener = TcpListener::bind(addr)?; Ok(IpcServer { listener: ListenerKind::Tcp(listener) }) } pub fn bind_unix(path: &str) -> Result { let _ = std::fs::remove_file(path); let listener = UnixListener::bind(path)?; Ok(IpcServer { listener: ListenerKind::Unix(listener) }) } pub fn accept(&self) -> Result { match &self.listener { ListenerKind::Tcp(l) => { let (stream, _addr) = l.accept()?; stream.set_nodelay(true)?; Ok(Connection::Tcp(stream)) } ListenerKind::Unix(l) => { let (stream, _addr) = l.accept()?; Ok(Connection::Unix(stream)) } } } pub fn accept_with_handler(self, handler: F) -> thread::JoinHandle<()> where F: Fn(Connection) -> Result<()> + Send + 'static, { match self.listener { ListenerKind::Tcp(l) => { thread::spawn(move || { for stream in l.incoming() { match stream { Ok(s) => { let _ = s.set_nodelay(true); if let Err(e) = handler(Connection::Tcp(s)) { eprintln!("ipc handler error: {}", e); } } Err(e) => { eprintln!("ipc accept error: {}", e); break; } } } }) } ListenerKind::Unix(l) => { thread::spawn(move || { for stream in l.incoming() { match stream { Ok(s) => { if let Err(e) = handler(Connection::Unix(s)) { eprintln!("ipc handler error: {}", e); } } Err(e) => { eprintln!("ipc accept error: {}", e); break; } } } }) } } } }