diff --git a/src/main.rs b/src/main.rs index 8771062..e6526f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -// #![allow(warnings)] +#![allow(warnings)] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release use log::{error, info, warn, LevelFilter}; @@ -8,7 +8,7 @@ use std::ops::Deref; use std::sync::Arc; mod utils; -use utils::logger::MyLogger; +use utils::logger::*; mod servers; use crate::servers::{*}; @@ -17,10 +17,6 @@ use clap::Parser; extern crate ctrlc; extern crate core; -use tokio::sync::broadcast; -use egui::mutex::Mutex; - - #[cfg(feature = "ui")] mod ui; #[cfg(feature = "ui")] use crate::ui::window::UI; #[cfg(feature = "ui")] use egui::{Style, Visuals}; @@ -29,6 +25,14 @@ use egui::mutex::Mutex; #[derive(Parser, Debug)] #[command(author, version, about = "Quick-Serve", long_about = "Instant file serving made easy")] struct Cli { + + // If the UI gets compiled, give the option to run headless + #[cfg(feature = "ui")] + #[arg( + help = "Headless", + short = 'H', long, required = false, + )] headless: bool, + #[arg( help = "Bind IP", short, long, required = false, @@ -54,7 +58,7 @@ struct Cli { #[arg( default_missing_value = "8080", help = "Start the HTTP server [default port: 8080]", - short = 'H', long, required = false, + long, required = false, num_args = 0..=1, require_equals = true, value_name = "PORT", @@ -63,7 +67,7 @@ struct Cli { #[arg( default_missing_value = "2121", help = "Start the FTP server [default port: 2121]", - short, long, required = false, + long, required = false, num_args = 0..=1, require_equals = true, value_name = "PORT", @@ -72,7 +76,7 @@ struct Cli { #[arg( default_missing_value = "6969", help = "Start the TFTP server [default port: 6969]", - short, long, required = false, + long, required = false, num_args = 0..=1, require_equals = true, value_name = "PORT", @@ -89,8 +93,10 @@ async fn main() { // log_level = "debug"; // } - let logs = Arc::new(Mutex::new(String::from(""))); - let mut logger = Box::new(MyLogger {logs: logs.clone()}); + let logger = Box::new(MyLogger::new()); + // Clone the producer, so that we can pass it to the consumer + // in the UI + let logs = logger.logs.clone(); // ::std::env::set_var("RUST_LOG", log_level); // env_logger::builder() @@ -99,32 +105,6 @@ async fn main() { log::set_boxed_logger(logger).unwrap(); log::set_max_level(LevelFilter::Trace); // Set the maximum log level - - ////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////// - #[cfg(feature = "ui")]{ - let options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default() - .with_inner_size([500.0, 700.0]), - ..Default::default() - }; - - let _ = eframe::run_native( - "Quick-Serve", - options, - Box::new(|cc| { - let style = Style { - visuals: Visuals::light(), - ..Style::default() - }; - cc.egui_ctx.set_style(style); - let mut ui = UI::new(cc); - ui.logs = logs; - Box::new(ui) - }), - ); - } - ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // debug!("\n{:#?}\n", cli_args); @@ -136,26 +116,51 @@ async fn main() { let bind_ip = cli_args.bind_ip; let path = cli_args.serve_dir; + #[cfg(not(feature = "ui"))] + let headless = true; + #[cfg(feature = "ui")] + let headless = cli_args.headless; + /////////////////////////////////////////////////////////////////////////////// // // TFTP from here on // // Spin the runners to wait for any potential server start - if cli_args.tftp.is_some() { - let port = cli_args.tftp.unwrap() as u16; - let tftp_server = Arc::new(::new(path.clone(), bind_ip.clone(), port)); - let tftp_server_c = tftp_server.clone(); + if cli_args.tftp.is_some() || headless == false { - spawned_servers.push(tftp_server.clone()); - spawned_runners.push( - tokio::spawn(async move { - TFTPServerRunner::runner(tftp_server).await - }) - ); + // loop { + // // Enter loop which wait for messages to either start or stop the servers + + // if headless == false { + // // when using the GUI, wait for the turn-on event + // // message here + // } + + // TODO:in case of the gui version, these values should come from the UI + let port = cli_args.tftp.unwrap() as u16; + let tftp_server = Arc::new(::new(path.clone(), bind_ip.clone(), port)); + let tftp_server_c = tftp_server.clone(); + + spawned_servers.push(tftp_server.clone()); + spawned_runners.push( + tokio::spawn(async move { + TFTPServerRunner::runner(tftp_server).await + }) + ); + + let _port = cli_args.tftp.unwrap() as u16; + let _ = tftp_server_c.start(); + + // if headless { + // // exit the loop after running once + // break; + // } + + // tftp_server_c.terminate(); + // del(tftp_server); + // } - let _port = cli_args.tftp.unwrap() as u16; - let _ = tftp_server_c.start(); } @@ -210,7 +215,7 @@ async fn main() { ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// - if spawned_runners.iter().count() == 0 { + if headless && spawned_runners.iter().count() == 0 { error!("No server(s) specified. Run with -h for more info..."); return; } @@ -227,6 +232,34 @@ async fn main() { }).expect("Error setting Ctrl+C handler"); info!("Press Ctrl+C to exit."); + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + // let headless = true; + #[cfg(feature = "ui")]{ + if cli_args.headless == false { + let options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default() + .with_inner_size([500.0, 700.0]), + ..Default::default() + }; + + let _ = eframe::run_native( + "Quick-Serve", + options, + Box::new(|cc| { + let style = Style { + visuals: Visuals::light(), + ..Style::default() + }; + cc.egui_ctx.set_style(style); + let mut ui = UI::new(cc); + ui.logs = logs; + Box::new(ui) + }), + ); + } + } + futures::future::join_all(spawned_runners).await; return; } diff --git a/src/ui/window.rs b/src/ui/window.rs index ac9dd5b..68b5f26 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -1,10 +1,8 @@ -use std::sync::Arc; - +use std::sync::{Arc, Mutex}; use eframe::egui; use egui::DragValue; use crate::ui::toggle_switch::toggle; use crate::servers::server::Protocol; -use egui::mutex::Mutex; pub struct UI { @@ -135,13 +133,9 @@ impl eframe::App for UI { ui.with_layout( egui::Layout::top_down(egui::Align::LEFT).with_cross_justify(true), |ui| { - + // TODO: Change font to monospace, and add syntax highlight // Acquire the lock - let guard = self.logs.lock(); - // Dereference the guard and clone the inner string - let logs_string = (*guard).clone(); - - ui.label(logs_string); + ui.label(self.logs.lock().unwrap().clone()); }, ); }); diff --git a/src/utils/logger.rs b/src/utils/logger.rs index 1d70678..f56d052 100644 --- a/src/utils/logger.rs +++ b/src/utils/logger.rs @@ -1,19 +1,22 @@ use log::{Level, Log, Metadata, Record}; -use egui::mutex::Mutex; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; +pub trait MyLoggerFn { + fn new () -> Self; +} + pub struct MyLogger { pub logs: Arc>, } -// impl Default for MyLogger { -// fn default() -> Self { -// MyLogger { -// logs: Arc::new(Mutex::new(String::new())), -// } -// } -// } +impl MyLoggerFn for MyLogger { + fn new () -> Self { + MyLogger { + logs: Arc::new(Mutex::new(String::new())) + } + } +} impl Log for MyLogger { fn enabled(&self, metadata: &Metadata) -> bool { @@ -31,8 +34,8 @@ impl Log for MyLogger { record.args() ); - println!("-> {}", log_line); - self.logs.lock().push_str(&format!("{}\n", log_line)); + println!("{}", log_line); + self.logs.lock().unwrap().push_str(&format!("{}\n", log_line)); } }