use log::{error, info, warn}; use tokio::net::{ UnixStream, UnixListener }; use tokio::time::{sleep, Duration}; use std::fs; use std::sync::Arc; use tokio::io::{ AsyncWriteExt, AsyncReadExt}; use noxis_cli::Cli; use super::preboot::PrebootParams; /// # Fn `init_cli_pipeline` /// ## for catching all input requests from CLI /// /// *input* : - /// /// *output* : `anyhow::Result<()>` to wrap errors /// /// *initiator* : fn `main` /// /// *managing* : `TcpListener` object to handle requests /// /// *depends on* : - /// pub async fn init_cli_pipeline(params: Arc) -> anyhow::Result<()> { let socket_path = ¶ms.self_socket; let _ = fs::remove_file(socket_path); match UnixListener::bind(socket_path) { Ok(list) => { // TODO: remove `unwrap`s info!("Listening on {}", socket_path.display()); std::env::set_var("NOXIS_SOCKET_PATH", socket_path); loop { match list.accept().await { Ok((socket, _)) => { // tokio::spawn(); process_connection(socket, params.clone()).await; }, Err(er) => { error!("Cannot poll connection to CLI due to {}", er); sleep(Duration::from_millis(300)).await; }, } } // Ok(()) }, Err(er) => { error!("Failed to open UnixListener for CLI"); Err(er.into()) }, } } /// # Fn `process_connection` /// ## for processing input CLI requests /// /// *input* : mut stream: `TcpStream` /// /// *output* : - /// /// *initiator* : fn `init_cli_pipeline` /// /// *managing* : mutable object of `TcpStream` /// /// *depends on* : `tokio::net::TcpStream` /// async fn process_connection(mut stream: UnixStream, params: Arc) { let mut buf = vec![0; 1024]; match stream.read(&mut buf).await { Ok(0) => { info!("Client disconnected "); }, Ok(n) => { buf.truncate(n); info!("CLI have sent {} bytes", n); match serde_json::from_slice::(&buf) { Ok(cli) => { info!("Received CLI request: {:?}", cli); match process_cli_cmd(cli, params.clone()).await { Ok(response) => { if let Err(e) = stream.write_all(response.as_bytes()).await { error!("Failed to send response: {}", e); } }, Err(er) => { error!("Can't send response from cli_pipeline: {}", er); }, } } Err(e) => { error!("Failed to parse CLI request: {}", e); } } }, Err(e) => error!("Failed to read from socket: {}", e), } let _ = stream.shutdown().await; } async fn process_cli_cmd(cli : Cli, params: Arc) -> anyhow::Result { use noxis_cli::{Commands, ConfigAction}; return match cli.command { Commands::Config(config) => { match config.action { ConfigAction::Show(env ) => { if env.is_env { Ok(serde_json::to_string_pretty(params.as_ref())?) } else { /* */ Ok(String::from("Ok")) } }, /* */ _ => Ok(String::from("Ok")) } }, /* */ Commands::Status => Ok(String::from("Ok")), _ => Ok(String::from("Ok")) } }