v2.0.1 - Pirate Stache - Unix Sockets
Added basic setup for Unix sockets. Need to add shell REPL so a host can talk to the server. It currently only connects and echoes back commands.
This commit is contained in:
parent
2404b04e76
commit
b093903fbf
108
src/main.rs
108
src/main.rs
@ -70,6 +70,42 @@ async fn debug(
|
||||
HttpResponse::Ok().body(serde_json::to_string_pretty(data.as_ref()).unwrap())
|
||||
}
|
||||
|
||||
async fn socket_loop(socket: &UnixStream) -> Result<(), Box<dyn Error>> {
|
||||
loop {
|
||||
let mut data = vec![0; 1024];
|
||||
|
||||
socket.readable().await?;
|
||||
let mut command = String::new();
|
||||
loop {
|
||||
match socket.try_read(&mut data) {
|
||||
Ok(0) => break,
|
||||
Ok(_n) => {
|
||||
command.push_str(&String::from_utf8(data.clone()).unwrap().trim());
|
||||
println!("command: {}", command);
|
||||
},
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
|
||||
break;
|
||||
},
|
||||
Err(e) => {
|
||||
return Err(e.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
socket.writable().await?;
|
||||
match socket.try_write(&command.into_bytes()) {
|
||||
Ok(_n) => {
|
||||
},
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
|
||||
continue;
|
||||
},
|
||||
Err(e) => {
|
||||
return Err(e.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
/* quick and dirty logging */
|
||||
@ -152,6 +188,78 @@ async fn main() -> std::io::Result<()> {
|
||||
let wb = web_data.clone();
|
||||
println!("{}", style("Loaded/Created application data files!").green());
|
||||
|
||||
println!("Connecting to Unix socket...");
|
||||
let (tx0, rx0) = oneshot::channel::<bool>();
|
||||
|
||||
/* NOTE: More phases will probably exist in the future */
|
||||
enum AppPhase {
|
||||
Normal,
|
||||
Shutdown
|
||||
}
|
||||
|
||||
let (s_tx, mut s_rx) = watch::channel::<AppPhase>(AppPhase::Normal);
|
||||
|
||||
let rt = Runtime::new().unwrap();
|
||||
let _guard = rt.enter();
|
||||
/* spawn the thread that manages the unix socket */
|
||||
tokio::spawn(async move {
|
||||
let p = Path::new("./boarders.sock");
|
||||
if p.exists() {
|
||||
std::fs::remove_file(p).unwrap();
|
||||
}
|
||||
let socket = UnixListener::bind("./boarders.sock").unwrap_or_else(|_| {
|
||||
panic!("{}", style("Could not connect to Unix socket").red());
|
||||
});
|
||||
println!("{}", style("Listening on Unix socket!").green());
|
||||
if tx0.send(true).is_err() {
|
||||
panic!("{}", style("[FATAL] Thread reciever was dropped! (should never happen)").red().bold());
|
||||
}
|
||||
|
||||
/*
|
||||
* HACK: clone the reciever a bunch of times to get around moves
|
||||
* not sure if there's a better way
|
||||
*/
|
||||
let s_rx_0 = s_rx.clone();
|
||||
let spawn_t = tokio::spawn(async move {
|
||||
let s_rx = s_rx_0.clone();
|
||||
loop {
|
||||
let mut s_rx = s_rx.clone();
|
||||
/* accept socket then wait for exit, or shutdown signal */
|
||||
let (conn, _addr) = socket.accept().await.unwrap();
|
||||
tokio::spawn(async move {
|
||||
select! {
|
||||
_socket = socket_loop(&conn) => 0,
|
||||
_state = s_rx.changed() => 1
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* FIXME: use enums when I feel like it (not urgent)
|
||||
*/
|
||||
match select! {
|
||||
_st = spawn_t => 0,
|
||||
state = s_rx.changed() => if state.is_ok() {
|
||||
match *s_rx.borrow() {
|
||||
AppPhase::Shutdown => 1,
|
||||
_ => 0
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} {
|
||||
0 => println!("Client disconnected"),
|
||||
1 => println!("Shut down client thread(s)"),
|
||||
_ => println!("Unexpected value from client thread")
|
||||
}
|
||||
});
|
||||
|
||||
/* why do I want a special message for that? Honestly I don't know... */
|
||||
rx0.await.unwrap_or_else(
|
||||
|_| panic!("{}", style("[FATAL] Thread transmitter was dropped! (should never happen)").red().bold())
|
||||
);
|
||||
|
||||
println!("{}", style("Finished initialization").green().bold());
|
||||
println!("Starting server...");
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user