rings/src/main.rs

75 lines
2.3 KiB
Rust

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<Executor> = 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))
}