diff options
| author | namilsk <namilsk@namilsk.tech> | 2026-01-20 18:31:42 +0300 |
|---|---|---|
| committer | namilsk <namilsk@namilsk.tech> | 2026-01-20 18:33:30 +0300 |
| commit | 2be31dc8ca78ecd91ef726c0fa4ca5129629076e (patch) | |
| tree | 93320390eb21013df36c89171046abda5386afe1 /src | |
| parent | 6f2c288f81abcaffb5381fd868b5ef82f00c4816 (diff) | |
Shitcode, again
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 134 | ||||
| -rw-r--r-- | src/pkgtoolkit/install.rs | 80 | ||||
| -rw-r--r-- | src/router/manager.rs | 200 | ||||
| -rw-r--r-- | src/router/router.rs | 11 |
4 files changed, 192 insertions, 233 deletions
diff --git a/src/main.rs b/src/main.rs index dc238b1..0f6b6c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,54 +12,11 @@ use crate::pkgtoolkit::build::BuildOperations; use crate::pkgtoolkit::git_source::GitSource; use crate::pkgtoolkit::index::IndexOperations; use crate::pkgtoolkit::install::InstallOperations; -use crate::router::router::{Emissary, EmissaryConfig, RouterUtils}; -use emissary_core::router::Router; -use emissary_util::runtime::tokio::Runtime as TokioRuntime; -use std::sync::Arc; -use tokio::sync::Mutex; - +use crate::router::manager::RouterManager; use clap::{Args, Parser, Subcommand}; use std::io::Write; use std::path::Path; -lazy_static::lazy_static! { - static ref ROUTER: Arc<Mutex<Option<Router<TokioRuntime>>>> = Arc::new(Mutex::new(None)); -} - -async fn init_router( - config: &crate::cfg::config::Config, -) -> Result<(), Box<dyn std::error::Error>> { - if !config.router.integrated_router { - return Ok(()); - } - - let router_config = EmissaryConfig { - storage: Some(std::path::PathBuf::from(&config.router.storage_path)), - auto_update: Some(config.router.auto_update), - http_proxy_port: Some(config.router.http_proxy_port), - socks_proxy_port: Some(config.router.socks_proxy_port), - }; - - let mut router = Emissary::new(router_config); - - // Check if router storage exists and is not empty - let storage_path = std::path::Path::new(&config.router.storage_path); - if !storage_path.exists() || storage_path.read_dir()?.next().is_none() { - log::info!("Router storage is empty, performing initial reseed..."); - router.config().await?; - router.reseed().await?; - } else { - router.config().await?; - } - - // Start the router and store the Router instance - let router = router.start().await?; - *ROUTER.lock().await = Some(router); - - log::info!("Integrated router initialized successfully"); - Ok(()) -} - #[derive(Parser)] struct Cli { #[command(subcommand)] @@ -76,7 +33,7 @@ enum Commands { Upgrade { pkgname: Option<String> }, #[command(about = "Build package from .mesk ")] Build { pkgname: String }, - #[command(about = "Install package from remote or local sources")] + #[command(about = "Install package")] Install { #[arg(help = "Package name or path to local .mesk file")] pkgname: String, @@ -124,6 +81,27 @@ struct RemoteInstallArgs { async fn main() -> Result<(), Box<dyn std::error::Error>> { let cli: Cli = Cli::parse(); + // Parse config once at the beginning + let config = Config::parse()?; + + // Setup integrated router if enabled + let router_manager = if config.router.integrated_router { + println!("Starting integrated router..."); + match RouterManager::new(&config).await { + Ok(manager) => { + println!("Router manager initialized"); + Some(manager) + } + Err(e) => { + eprintln!("Failed to initialize router manager: {}", e); + return Err(e); + } + } + } else { + println!("Integrated router disabled"); + None + }; + let result = { match &cli.command { Commands::Validate { path } => { @@ -138,7 +116,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { } } Err(e) => { - log::error!("Failed to validate package '{}': {}", path, e); + eprintln!("Failed to validate package '{}': {}", path, e); return Err(e.into()); } } @@ -165,7 +143,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { println!("Extracting archive..."); Package::extract_archive(pkgname)?; - let config = Config::parse()?; let cache_dir = &config.paths.cache_dir; // Find the package directory (should be name-version format) @@ -221,7 +198,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { println!("Extracting archive..."); Package::extract_archive(pkgname)?; - let config = Config::parse()?; let cache_dir = &config.paths.cache_dir; let mut pkg_dir_name = None; @@ -259,25 +235,34 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { pkg.install()?; println!("Package '{}' installed successfully.", pkg.name); } else { - let config = Config::parse()?; // Initialize router if it's needed for I2P connections and is enabled if !args.http && config.router.integrated_router { - init_router(&config).await?; + // Wait for router to be fully started + if let Some(ref manager) = router_manager { + println!("Waiting for router to be ready..."); + tokio::time::sleep(std::time::Duration::from_secs(3)).await; // Give router time to start + if !manager.is_running() { + eprintln!( + "Router is not running, cannot proceed with I2P installation" + ); + return Err(std::io::Error::other("Router not running").into()); + } + } } if args.http { - println!("Installing {} via HTTP", pkgname); + println!("Installing {} via non-i2p mirror", pkgname); let mut http_client = HTTPPackage::new(config); http_client.fetch_index_http().await?; - log::info!("Index fetched successfully."); + println!("Index fetched successfully."); http_client.fetch_package_http(pkgname).await?; - log::info!("Package '{}' installed successfully.", pkgname); + println!("Package '{}' installed successfully.", pkgname); } else { println!("Installing {} via I2P", pkgname); let mut i2p_client = I2PPackage::new(config); i2p_client.fetch_index().await?; - log::info!("Index fetched successfully."); + println!("Index fetched successfully."); i2p_client.fetch_package(pkgname).await?; - log::info!("Package '{}' installed successfully.", pkgname); + println!("Package '{}' installed successfully.", pkgname); } } return Ok(()); @@ -286,7 +271,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { println!("Uninstalling package: {}", pkgname); let installed_packages = Package::list_installed_packages().map_err(|e| { - log::error!("Failed to list installed packages: {}", e); + eprintln!("Failed to list installed packages: {}", e); e })?; @@ -309,23 +294,29 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { Ok(()) } Ok(false) => { - log::warn!( + eprintln!( "Some files could not be removed during uninstallation of {}", pkgname ); Err(std::io::Error::other("Partial uninstallation occurred").into()) } Err(e) => { - log::error!("Failed to uninstall package {}: {}", pkgname, e); + eprintln!("Failed to uninstall package {}: {}", pkgname, e); Err(e.into()) } } } Commands::GetSource { pkgname } => { - let config = Config::parse()?; // Initialize router for I2P connections if enabled if config.router.integrated_router { - init_router(&config).await?; + if let Some(ref manager) = router_manager { + println!("Waiting for router to be ready..."); + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + if !manager.is_running() { + eprintln!("Router is not running, cannot proceed with I2P operation"); + return Err(std::io::Error::other("Router not running").into()); + } + } } println!("Getting source of {}", pkgname); @@ -347,7 +338,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { println!("{}", config); println!("---- End of generated config ----"); - log::warn!("Writing the default config to /etc/mesk/mesk.toml"); + eprintln!("Writing the default config to /etc/mesk/mesk.toml"); let path = Path::new("/etc/mesk/mesk.toml"); std::fs::create_dir_all(path.parent().unwrap())?; @@ -361,7 +352,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { println!("{:?}", config); println!("---- End of generated config ----"); - log::warn!("Writing the default config to /etc/mesk/mesk.toml"); + eprintln!("Writing the default config to /etc/mesk/mesk.toml"); let path = Path::new("/etc/mesk/mesk.toml"); std::fs::create_dir_all(path.parent().unwrap())?; @@ -372,11 +363,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { return Ok(()); } Commands::Update => { - let config = Config::parse()?; // Initialize router for I2P connections if enabled if config.router.integrated_router { - init_router(&config).await?; + if let Some(ref manager) = router_manager { + println!("Waiting for router to be ready..."); + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + if !manager.is_running() { + eprintln!("Router is not running, cannot proceed with I2P operation"); + return Err(std::io::Error::other("Router not running").into()); + } + } } + println!("Updating index from {}", config.repo.repo_url); let mut i2p_client = I2PPackage::new(config); @@ -407,9 +405,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { }; // Shutdown router if it was initialized - if let Some(router) = ROUTER.lock().await.take() { - // TODO: Add proper router shutdown when implemented - log::info!("Shutting down integrated router..."); + if let Some(ref manager) = router_manager { + println!("Shutting down integrated router..."); + if let Err(e) = manager.stop().await { + eprintln!("Error stopping router: {}", e); + } } result diff --git a/src/pkgtoolkit/install.rs b/src/pkgtoolkit/install.rs index 7ba0598..13929e6 100644 --- a/src/pkgtoolkit/install.rs +++ b/src/pkgtoolkit/install.rs @@ -1,5 +1,4 @@ use crate::cfg::config::Config; -use crate::router::manager::RouterManager; use std::{ fs::{self, Permissions, create_dir_all, set_permissions}, os::unix::fs::PermissionsExt, @@ -33,37 +32,9 @@ pub trait InstallOperations { fn load_manifest(&self) -> Result<PackageManifest, std::io::Error>; fn list_installed_packages() -> Result<Vec<PackageManifest>, std::io::Error>; fn is_installed(&self) -> Result<bool, std::io::Error>; - - /// Installs a package using the specified parameters - /// - /// # Arguments - /// * `pkgname` - Name of the package to install - /// * `source` - Optional source URL or path - /// * `is_path` - Whether the source is a local path - /// * `args` - Additional installation arguments - /// * `router_manager` - Optional router manager for I2P connections - async fn install_package( - pkgname: &str, - source: Option<&str>, - is_path: bool, - args: &RemoteInstallArgs, - router_manager: &RouterManager, - ) -> Result<(), Box<dyn std::error::Error>>; } impl InstallOperations for Package { - async fn install_package( - pkgname: &str, - source: Option<&str>, - is_path: bool, - args: &RemoteInstallArgs, - router_manager: &RouterManager, - ) -> Result<(), Box<dyn std::error::Error>> { - // Implementation of install_package - // TODO: Add actual implementation based on your requirements - Ok(()) - } - /// Recursively collects all files from a directory and its subdirectories /// and returns them as a vector of strings. /// @@ -118,7 +89,7 @@ impl InstallOperations for Package { let is_build_present_and_not_empty = build_meta.is_some(); if is_build_present_and_not_empty { - log::info!( + println!( "Found BUILD file, preparing to build and install package: {}", self.name ); @@ -203,7 +174,7 @@ impl InstallOperations for Package { } } } else { - log::info!( + println!( "No BUILD file or it's empty. Treating as binary package. Installing via INSTALL config or custom script." ); if let Some(ref script) = install_meta.install.custom_script { @@ -211,7 +182,7 @@ impl InstallOperations for Package { } if let Some(ref script) = install_meta.install.custom_script { - log::info!( + println!( "Executing custom install script for {}", install_meta.package.name ); @@ -232,16 +203,16 @@ impl InstallOperations for Package { "Custom script used; file list may be incomplete. Add manual tracking if needed." ); } else { - log::info!( + println!( "No custom script. Running default install hook for {}", install_meta.package.name ); - log::info!("Starting default install process"); + println!("Starting default install process"); let build_dir = Path::new(&config.paths.cache_dir) .join(format!("{}-{}", self.name, self.version)); let dest_path = Path::new(&install_meta.install.path); - log::info!( + println!( "Install path: {:?}, is_dir: {}, ends_with_slash: {}", dest_path, dest_path.is_dir(), @@ -249,7 +220,7 @@ impl InstallOperations for Package { ); if dest_path.is_dir() || dest_path.to_string_lossy().ends_with('/') { - log::info!("Taking multi-binary package path"); + println!("Taking multi-binary package path"); let target_release = build_dir.join("target/release"); if !target_release.exists() { return Err(std::io::Error::other(format!( @@ -271,12 +242,12 @@ impl InstallOperations for Package { && let Ok(metadata) = fs::metadata(&path) { let mode = metadata.permissions().mode(); - log::debug!("Checking file: {:?}, mode: {:o}", path.file_name(), mode); + println!("Checking file: {:?}, mode: {:o}", path.file_name(), mode); if mode & 0o111 != 0 { let file_name = path.file_name().unwrap().to_string_lossy(); let dest_file = dest_path.join(&*file_name); - log::info!( + println!( "Copying executable: {} to {}", file_name, dest_file.display() @@ -290,7 +261,7 @@ impl InstallOperations for Package { copied_files.push(dest_file); } else { - log::debug!( + println!( "File {:?} is not executable (mode: {:o})", path.file_name(), mode @@ -337,7 +308,7 @@ impl InstallOperations for Package { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - log::warn!( + println!( "Warning: 'chown' command failed for {} (requires root?):\n{}", file_path.display(), stderr @@ -345,7 +316,7 @@ impl InstallOperations for Package { } } } else { - log::info!("Taking single binary package path"); + println!("Taking single binary package path"); // Single binary package - copy specific file let source_file_name = &self.name; let src_path = build_dir.join(source_file_name); @@ -393,10 +364,7 @@ impl InstallOperations for Package { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - log::warn!( - "Warning: 'chown' command failed (requires root?):\n{}", - stderr - ); + println!("Warning: 'chown' command failed:\n{}", stderr); } all_files = install_meta.files; @@ -414,7 +382,7 @@ impl InstallOperations for Package { toml::to_string_pretty(&manifest).map_err(|e| std::io::Error::other(e.to_string()))?; fs::write(&manifest_path, manifest_toml)?; - log::info!( + println!( "Package {} installed successfully. Manifest generated at {:?} with {} files tracked", self.name, manifest_path, @@ -448,10 +416,9 @@ impl InstallOperations for Package { fn uninstall(&self) -> Result<bool, std::io::Error> { let manifest = self.load_manifest()?; - log::info!( + println!( "Uninstalling package {}-{}", - manifest.name, - manifest.version + manifest.name, manifest.version ); let mut removed_files = 0; @@ -464,15 +431,15 @@ impl InstallOperations for Package { match fs::remove_file(path) { Ok(()) => { removed_files += 1; - log::debug!("Removed file: {:?}", path); + println!("Removed file: {:?}", path); } Err(e) => { failed_removals += 1; - log::warn!("Failed to remove file {:?}: {}", path, e); + println!("Failed to remove file {:?}: {}", path, e); } } } else { - log::debug!("File not found, skipping: {:?}", path); + println!("File not found, skipping: {:?}", path); } } @@ -483,15 +450,12 @@ impl InstallOperations for Package { if manifest_path.exists() { fs::remove_file(&manifest_path)?; - log::info!("Removed manifest file: {:?}", manifest_path); + println!("Removed manifest file: {:?}", manifest_path); } - log::info!( + println!( "Package {}-{} uninstalled successfully. Removed {} files, {} failures", - manifest.name, - manifest.version, - removed_files, - failed_removals + manifest.name, manifest.version, removed_files, failed_removals ); Ok(failed_removals == 0) diff --git a/src/router/manager.rs b/src/router/manager.rs index 23b7c69..5fb8868 100644 --- a/src/router/manager.rs +++ b/src/router/manager.rs @@ -1,21 +1,8 @@ -use crate::router::router::RouterUtils; -use crate::router::router::{Emissary, EmissaryConfig}; -use log::{debug, error, info}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; -use tokio::sync::mpsc; -use tokio::task::JoinHandle; - -#[derive(Debug)] -pub enum RouterMessage { - Start, - Stop, - Status, -} +// Simple RouterManager that just tracks status without complex state management pub struct RouterManager { - handle: Option<JoinHandle<()>>, - tx: mpsc::Sender<RouterMessage>, is_running: Arc<AtomicBool>, } @@ -25,104 +12,114 @@ impl RouterManager { ) -> Result<Self, Box<dyn std::error::Error>> { if !config.router.integrated_router { return Ok(Self { - handle: None, - tx: { - let (tx, _) = mpsc::channel(1); - tx - }, is_running: Arc::new(AtomicBool::new(false)), }); } - let (tx, mut rx) = mpsc::channel::<RouterMessage>(1); - let is_running = Arc::new(AtomicBool::new(false)); - let is_running_clone = is_running.clone(); + // Initialize router synchronously to avoid Send issues + Self::init_router(config).await?; - let router_config = config.router.clone(); - let handle = tokio::spawn(async move { - info!("Router manager task started"); + let manager = Self { + is_running: Arc::new(AtomicBool::new(true)), + }; - let mut router = Emissary::new(EmissaryConfig { - storage: Some(std::path::PathBuf::from(&router_config.storage_path)), - auto_update: Some(router_config.auto_update), - http_proxy_port: Some(router_config.http_proxy_port), - socks_proxy_port: Some(router_config.socks_proxy_port), - }); + // Give the router some time to initialize + tokio::time::sleep(std::time::Duration::from_secs(2)).await; - if let Err(e) = router.config().await { - error!("Failed to configure router: {}", e); - return; - } - - let storage_path = std::path::Path::new(&router_config.storage_path); - if !storage_path.exists() - || storage_path - .read_dir() - .ok() - .is_none_or(|mut d| d.next().is_none()) - { - info!("Router storage is empty, performing initial reseed..."); - if let Err(e) = router.reseed().await { - error!("Failed to reseed router: {}", e); - return; - } - } - - let router_task = tokio::spawn(async move { - info!("Starting router service..."); - match router.start().await { - Ok(_) => info!("Router service stopped"), - Err(e) => error!("Router service error: {}", e), - } - }); + Ok(manager) + } - is_running_clone.store(true, Ordering::SeqCst); - info!("Router manager is now running"); - - while let Some(msg) = rx.recv().await { - match msg { - RouterMessage::Stop => { - info!("Stopping router..."); - // TODO: Implement proper router shutdown - is_running_clone.store(false, Ordering::SeqCst); - break; - } - RouterMessage::Status => { - debug!( - "Router status: {}", - if is_running_clone.load(Ordering::SeqCst) { - "running" - } else { - "stopped" - } - ); - } - _ => {} - } - } - - if let Err(e) = router_task.await { - error!("Router task panicked: {}", e); - } - - info!("Router manager task finished"); + async fn init_router( + config: &crate::cfg::config::Config, + ) -> Result<(), Box<dyn std::error::Error>> { + use crate::router::router::{Emissary, EmissaryConfig, RouterUtils}; + use std::path::Path; + + let router_config = &config.router; + let mut router = Emissary::new(EmissaryConfig { + storage: Some(std::path::PathBuf::from(&router_config.storage_path)), + auto_update: Some(router_config.auto_update), + http_proxy_port: Some(router_config.http_proxy_port), + socks_proxy_port: Some(router_config.socks_proxy_port), }); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; + router.config().await?; + + let storage_path = Path::new(&router_config.storage_path); + if !storage_path.exists() { + std::fs::create_dir_all(storage_path)?; + } + + // Check if storage directory is empty + let should_reseed = match std::fs::read_dir(storage_path) { + Ok(mut entries) => entries.next().is_none(), + Err(_) => true, // if we can't read, reseed anyway + }; + + if should_reseed { + println!("Router storage is empty, performing initial reseed..."); + router.reseed().await?; + } + + let router_instance = router.start().await?; + + // Store the router instance in the global static variable + *super::router::ROUTER.lock().await = Some(router_instance); + println!("Router service successfully initialized and stored globally"); - Ok(Self { - handle: Some(handle), - tx, - is_running, - }) + Ok(()) } - pub async fn stop(&self) { + /// Starts the integrated router if it is not currently running. + /// Note: The router is typically started automatically when the RouterManager is created, + /// so calling this method usually just prints a message indicating that the router + /// starts automatically. + /// + /// # Returns + /// + /// * `Ok(())` always returns OK as this is a compatibility method + pub async fn start(&self) -> Result<(), Box<dyn std::error::Error>> { + if !self.is_running.load(Ordering::SeqCst) { + println!("Router start functionality not implemented for this mode"); + // We can't really control the router lifecycle since it's managed globally + } + Ok(()) + } + + /// Restarts the integrated router if it is currently running. + /// This stops the current router instance and starts a new one. + /// + /// # Returns + /// + /// * `Ok(())` when the restart is initiated + /// * `Err(Box<dyn std::error::Error>)` if the restart failed + pub async fn restart(&self) -> Result<(), Box<dyn std::error::Error>> { + println!("Restarting router..."); + + // Clear the global router instance + *super::router::ROUTER.lock().await = None; + + // Get config again (this is not ideal but needed for restart) + let config = crate::cfg::config::Config::parse() + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + + Self::init_router(&config).await?; + + println!("Router restarted successfully"); + Ok(()) + } + + /// Stops the integrated router if it is currently running. + /// This clears the global router instance. + pub async fn stop(&self) -> Result<(), Box<dyn std::error::Error>> { if self.is_running.load(Ordering::SeqCst) { - if let Err(e) = self.tx.send(RouterMessage::Stop).await { - error!("Failed to send stop message to router: {}", e); - } + println!("Stopping router..."); + // Clear the global router instance + *super::router::ROUTER.lock().await = None; + self.is_running.store(false, Ordering::SeqCst); + println!("Router stopped"); } + Ok(()) } pub fn is_running(&self) -> bool { @@ -132,13 +129,6 @@ impl RouterManager { impl Drop for RouterManager { fn drop(&mut self) { - if self.is_running() { - let tx = self.tx.clone(); - tokio::spawn(async move { - if let Err(e) = tx.send(RouterMessage::Stop).await { - error!("Failed to send stop message during drop: {}", e); - } - }); - } + //todooo } } diff --git a/src/router/router.rs b/src/router/router.rs index 65de900..3f1e629 100644 --- a/src/router/router.rs +++ b/src/router/router.rs @@ -4,9 +4,15 @@ use emissary_util::reseeder::Reseeder; use emissary_util::runtime::tokio::Runtime as TokioRuntime; use emissary_util::storage::{Storage, StorageBundle}; use serde::{Deserialize, Serialize}; + use std::future::Future; use std::path::PathBuf; use std::sync::Arc; +use tokio::sync::Mutex; + +lazy_static::lazy_static! { + pub static ref ROUTER: Arc<Mutex<Option<Router<TokioRuntime>>>> = Arc::new(Mutex::new(None)); +} pub trait RouterUtils { fn config(&mut self) -> impl Future<Output = Result<(), Box<dyn std::error::Error>>> + Send; @@ -86,7 +92,7 @@ impl RouterUtils for Emissary { .store_router_info(info.name.to_string(), info.router_info.clone()) .await { - log::warn!("Failed to store reseeded router info: {}", e); + println!("Failed to store reseeded router info: {}", e); } bundle.routers.push(info.router_info); } @@ -96,7 +102,7 @@ impl RouterUtils for Emissary { self.storage_bundle = Some(bundle); return Err(format!("Reseed failed and no routers available: {}", e).into()); } else { - log::warn!("Reseed failed, but using existing routers: {}", e); + println!("Reseed failed, but using existing routers: {}", e); } } } @@ -142,7 +148,6 @@ impl RouterUtils for Emissary { .await .map_err(|e| format!("Router creation failed: {}", e))?; - // Сохраняем router_info, если он новый storage.store_local_router_info(router_info).await?; Ok(router) |
