mod client; mod tui; // Add this new module use client::handlers::handle_client; use log::{error, info, Level, Log, Metadata, Record}; use serde::Deserialize; use std::sync::mpsc; use std::thread; use tokio::net::TcpListener; use tokio::sync::broadcast; use tui::{run_app, LogEntry}; #[derive(Deserialize, Debug)] struct Config { address: String, port: String, } struct CustomLogger { tx: mpsc::Sender, } impl Log for CustomLogger { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level() <= Level::Info } fn log(&self, record: &Record) { if self.enabled(record.metadata()) { let now = chrono::Local::now(); let log_entry = LogEntry { timestamp: now.format("%H:%M:%S").to_string(), level: record.level().to_string(), message: record.args().to_string(), }; let _ = self.tx.send(log_entry); } } fn flush(&self) {} } #[tokio::main] async fn main() { // Create a channel for logging let (tx, rx) = mpsc::channel(); // Create and set the custom logger let logger = Box::new(CustomLogger { tx }); log::set_boxed_logger(logger).unwrap(); log::set_max_level(log::LevelFilter::Info); // Start the TUI in a separate thread let _tui_handle = thread::spawn(move || { if let Err(e) = run_app(rx) { eprintln!("Error running TUI: {:?}", e); } }); // Load the configuration from config file let config = match std::fs::read_to_string("config.toml") { Ok(config) => match toml::from_str::(&config) { Ok(config) => config, Err(e) => { error!("Failed to parse config file: {:?}", e); std::process::exit(1); } }, Err(e) => { error!("Failed to read config file: {:?}", e); std::process::exit(1); } }; info!("Configuration loaded: {:?}", config); // Bind a TCP listener to accept incoming connections let listener = TcpListener::bind(config.address + ":" + config.port.as_str()) .await .unwrap(); info!("Server running on port 8080"); // Create a broadcast channel for sharing messages let (tx, _) = broadcast::channel(100); loop { // Accept a new client let (socket, addr) = listener.accept().await.unwrap(); info!("Client connected: {}", addr); let tx = tx.clone(); let rx = tx.subscribe(); // Handle the client in a new task tokio::spawn(async move { if let Err(e) = handle_client(socket, tx, rx).await { error!("Error handling client: {}", e); } }); } }