use clap::Parser; use tracing_subscriber::EnvFilter; use anyhow::Result; use rustproxy::RustProxy; use rustproxy::management; use rustproxy_config::RustProxyOptions; /// RustProxy - High-performance multi-protocol proxy #[derive(Parser, Debug)] #[command(name = "rustproxy", version, about)] struct Cli { /// Path to JSON configuration file #[arg(short, long, default_value = "config.json")] config: String, /// Log level (trace, debug, info, warn, error) #[arg(short, long, default_value = "info")] log_level: String, /// Validate configuration without starting #[arg(long)] validate: bool, /// Run in management mode (JSON-over-stdin IPC for TypeScript wrapper) #[arg(long)] management: bool, } #[tokio::main] async fn main() -> Result<()> { let cli = Cli::parse(); // Initialize tracing - write to stderr so stdout is reserved for management IPC tracing_subscriber::fmt() .with_writer(std::io::stderr) .with_env_filter( EnvFilter::try_from_default_env() .unwrap_or_else(|_| EnvFilter::new(&cli.log_level)) ) .init(); // Management mode: JSON IPC over stdin/stdout if cli.management { tracing::info!("RustProxy starting in management mode..."); return management::management_loop().await; } tracing::info!("RustProxy starting..."); // Load configuration let options = RustProxyOptions::from_file(&cli.config) .map_err(|e| anyhow::anyhow!("Failed to load config '{}': {}", cli.config, e))?; tracing::info!( "Loaded {} routes from {}", options.routes.len(), cli.config ); // Validate-only mode if cli.validate { match rustproxy_config::validate_routes(&options.routes) { Ok(()) => { tracing::info!("Configuration is valid"); return Ok(()); } Err(errors) => { for err in &errors { tracing::error!("Validation error: {}", err); } anyhow::bail!("{} validation errors found", errors.len()); } } } // Create and start proxy let mut proxy = RustProxy::new(options)?; proxy.start().await?; // Wait for shutdown signal tracing::info!("RustProxy is running. Press Ctrl+C to stop."); tokio::signal::ctrl_c().await?; tracing::info!("Shutdown signal received"); proxy.stop().await?; tracing::info!("RustProxy shutdown complete"); Ok(()) }