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())
|
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]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
/* quick and dirty logging */
|
/* quick and dirty logging */
|
||||||
@ -152,6 +188,78 @@ async fn main() -> std::io::Result<()> {
|
|||||||
let wb = web_data.clone();
|
let wb = web_data.clone();
|
||||||
println!("{}", style("Loaded/Created application data files!").green());
|
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!("{}", style("Finished initialization").green().bold());
|
||||||
println!("Starting server...");
|
println!("Starting server...");
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user