I am making unix domain sockets to perform local communication and have used uds
create for this. Currently I’m stuck with shutting down an uds listener and I’m not able to peoperly design or come up with a work around to get this problem solved.
uds_listener_interface.rs
use std::{io::Error, io::ErrorKind, net::Shutdown};
use uds::{UnixSeqpacketConn, UnixSeqpacketListener};
pub struct UdsListenerInterface {
listener: UnixSeqpacketListener,
socket: Option<UnixSeqpacketConn>,
}
impl UdsListenerInterface {
pub fn new(sock_name: &str) -> Self {
Self {
listener: match UnixSeqpacketListener::bind(sock_name) {
Ok(listener) => listener,
Err(e) => panic!("uds listener bind failed: {e:?}"),
},
socket: None,
}
}
pub fn accept_connection(&mut self) {
self.socket = match self.listener.accept_unix_addr() {
Ok((socket, _)) => Some(socket),
Err(e) => panic!("uds listener accept failed: {e:?}"),
}
}
pub fn recv_data(&self, buff: &mut [u8]) -> Result<usize, std::io::Error> {
if let Some(socket) = &self.socket {
return socket.recv(buff);
}
Err(Error::new(ErrorKind::NotConnected, "uds listener recv: Invalid socket"))
}
pub fn send_data(&self, buff: &[u8]) -> Result<usize, std::io::Error> {
if let Some(socket) = &self.socket {
return socket.send(buff);
}
Err(Error::new(ErrorKind::NotConnected, "uds listener send: Invalid socket"))
}
pub fn shutdown(&self, how: Shutdown) -> Result<(), std::io::Error>{
if let Some(socket) = &self.socket {
return socket.shutdown(how);
}
Err(Error::new(ErrorKind::NotConnected, "uds listener shutdwon: Invalid socket"))
}
}
uds_listener.rs
use std::thread;
use crossbeam::channel::Sender;
use crate::uds_listener_interface::UdsListenerInterface;
pub struct UdsListener {
uds_listener_interface: UdsListenerInterface,
tx: Option<Sender<Vec<u8>>>,
}
impl UdsListener {
pub fn new(sock_name: &str) -> Self {
Self {
uds_listener_interface: UdsListenerInterface::new(sock_name),
tx : None,
}
}
pub fn set_tx(&mut self, tx: Sender<Vec<u8>>) {
self.tx = Some(tx);
}
pub fn spawn_thread(mut self) -> thread::JoinHandle<()> {
thread::spawn(move || {
self.run();
})
}
fn run(&mut self) {
self.uds_listener_interface.accept_connection();
let mut buff = [0u8; 8192];
loop {
match self.uds_listener_interface.recv_data(&mut buff) {
Ok(length) => {
if length == 0 {
break;
}
if let Some(tx) = &self.tx {
let _ = tx.send(buff[..length].to_vec());
}
},
Err(e) => panic!("uds listener read failed: {e:?}"),
}
}
}
pub fn shutdown_listener(&self) {
self.uds_listener_interface.shutdown(std::net::Shutdown::Both);
}
}
main.rs
mod uds_listener;
mod uds_listener_interface;
use std::{thread, time::Duration};
use uds_listener::UdsListener;
fn main() {
let mut uds_listnener = UdsListener::new("/tmp/aa.sock");
let (tx, rx) = crossbeam::channel::unbounded();
uds_listnener.set_tx(tx);
let uds_listener_jh = uds_listnener.spawn_thread();
thread::sleep(Duration::from_secs(10));
// below code doesn't work as uds_listnener been moved when spawn_thread method was called
// uds_listnener.shutdown_listener();
let _ = uds_listener_jh.join();
}
cargo.toml
[package]
name = "udss"
version = "0.1.0"
edition = "2021"
[dependencies]
crossbeam = "0.8.4"
uds = "0.4.2"