use std::io;
use std::net::SocketAddr;
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::{Path, PathBuf};
use crate::transport::BlockingTransportListener;
pub struct BlockingUdsListener {
listener: std::os::unix::net::UnixListener,
path: PathBuf,
}
impl BlockingUdsListener {
pub fn bind(path: &Path) -> io::Result<Self> {
if path.exists() {
std::fs::remove_file(path)?;
}
let listener = std::os::unix::net::UnixListener::bind(path)?;
Ok(Self {
listener,
path: path.to_owned(),
})
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
Ok("127.0.0.1:0".parse().expect("valid addr"))
}
pub fn path(&self) -> &Path {
&self.path
}
}
impl AsRawFd for BlockingUdsListener {
fn as_raw_fd(&self) -> RawFd {
self.listener.as_raw_fd()
}
}
impl BlockingTransportListener for BlockingUdsListener {
type Read = std::os::unix::net::UnixStream;
type Write = std::os::unix::net::UnixStream;
fn accept(
&mut self,
) -> io::Result<(
std::os::unix::net::UnixStream,
std::os::unix::net::UnixStream,
SocketAddr,
)> {
let (stream, _unix_addr) = self.listener.accept()?;
let addr: SocketAddr = "127.0.0.1:0".parse().expect("valid addr");
let read_half = stream.try_clone()?;
Ok((read_half, stream, addr))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::blocking::{BlockingFrameReader, BlockingFrameWriter};
#[test]
fn accept_and_exchange_frame() {
let dir = tempfile::tempdir().unwrap();
let sock_path = dir.path().join("test.sock");
let listener = BlockingUdsListener::bind(&sock_path).unwrap();
let sock = sock_path.clone();
let handle = std::thread::spawn(move || {
let mut listener = listener;
let (read, write, _addr) = listener.accept().unwrap();
let mut reader = BlockingFrameReader::new(read);
let mut writer = BlockingFrameWriter::new(write);
let frame = reader.read_frame().unwrap().unwrap();
writer.write_frame(frame).unwrap();
writer.flush().unwrap();
});
let stream = std::os::unix::net::UnixStream::connect(&sock).unwrap();
let mut writer = BlockingFrameWriter::new(stream.try_clone().unwrap());
let mut reader = BlockingFrameReader::new(stream);
let data = b"hello melin";
writer.write_frame(data).unwrap();
writer.flush().unwrap();
let received = reader.read_frame().unwrap().unwrap();
assert_eq!(received, data);
handle.join().unwrap();
}
}