mod args; use std::os::unix::net::{UnixListener as StdUnixListener, UnixStream as StdUnixStream}; use args::{Cli, Commands}; use clap::Parser; use once_cell::sync::Lazy; use smol::channel::unbounded; use smol::io::{AsyncReadExt, AsyncWriteExt}; use smol::net::unix::{UnixListener, UnixStream}; use smol::Executor; use uds::{UnixListenerExt, UnixSocketAddr, UnixStreamExt}; static EXEC: Lazy = Lazy::new(Executor::new); fn main() -> anyhow::Result<()> { let cli = Cli::parse(); let (_signal, shutdown) = unbounded::<()>(); for _ in 0..std::thread::available_parallelism().unwrap().into() { std::thread::spawn({ let shutdown = shutdown.clone(); move || smol::future::block_on(EXEC.run(shutdown.recv())) }); } smol::block_on(async { match cli.command { Commands::Server => server().await?, Commands::Client { address } => { let address = UnixSocketAddr::new(&address)?; client(address).await?; } } Ok(()) }) } async fn server() -> anyhow::Result<()> { let (listener, addr) = create_rings_socket()?; println!("{}", addr); loop { match listener.accept().await { Ok((mut conn, _)) => { EXEC.spawn(async move { let mut buf = String::new(); match conn.read_to_string(&mut buf).await { Ok(_) => println!("Got: {buf}"), Err(e) => eprintln!("{e}"), } }) .detach(); } Err(e) => { eprintln!("{e}"); } } } // Ok(()) } async fn client(addr: uds::UnixSocketAddr) -> anyhow::Result<()> { let mut stream: UnixStream = smol::unblock(move || StdUnixStream::connect_to_unix_addr(&addr)) .await? .try_into()?; let msg = "Saturn has cool rings uwu"; stream.write_all(msg.as_bytes()).await?; Ok(()) } fn create_rings_socket() -> anyhow::Result<(UnixListener, UnixSocketAddr)> { let addr = uds::UnixSocketAddr::new_unspecified(); let listener = StdUnixListener::bind_unix_addr(&addr)?; let addr = listener.local_unix_addr()?; Ok((listener.try_into()?, addr)) }