From ceeef0fa5eddb2ae6ca378ce7377e35e9646267a Mon Sep 17 00:00:00 2001 From: Iwan BK Date: Tue, 7 May 2024 10:00:23 +0700 Subject: [PATCH] feat(mobile): start & stop mycelium. Start & stop implemented by adding a global channel. Upon startup `Node` listens to ctrl-c and channel receiver. On stop, we send message to that channel and Node can exit.. --- Cargo.lock | 1 + mobile/Cargo.toml | 3 ++- mobile/src/lib.rs | 46 ++++++++++++++++++++++++++++++++++++---------- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b56149d..550add3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1047,6 +1047,7 @@ dependencies = [ "android_logger", "log", "mycelium", + "once_cell", "tokio", ] diff --git a/mobile/Cargo.toml b/mobile/Cargo.toml index 56a8d43..542f8db 100644 --- a/mobile/Cargo.toml +++ b/mobile/Cargo.toml @@ -6,12 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -mycelium = { path = "../mycelium"} +mycelium = { path = "../mycelium", features = ["vendored-openssl"]} tokio = { version = "1.37.0", features = [ "signal", "rt-multi-thread", ] } log = "0.4.21" +once_cell = "1.19.0" [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.13.3" diff --git a/mobile/src/lib.rs b/mobile/src/lib.rs index ad75d2a..16d4296 100644 --- a/mobile/src/lib.rs +++ b/mobile/src/lib.rs @@ -1,7 +1,7 @@ use std::convert::TryFrom; use std::io; -use log::info; +use log::{error, info}; use metrics::Metrics; use mycelium::endpoint::Endpoint; @@ -10,19 +10,30 @@ use mycelium::{crypto, metrics, Config, Node}; #[cfg(target_os = "android")] fn setup_the_logger() { use log::LevelFilter; - android_logger::init_once(android_logger::Config::default().with_max_level(LevelFilter::Trace)); + android_logger::init_once(android_logger::Config::default().with_max_level(LevelFilter::Info)); } + +use once_cell::sync::Lazy; +use std::sync::Mutex; +use tokio::sync::mpsc; +// Declare the channel globally so we can use it on the start & stop mycelium functions +static CHANNEL: Lazy<(Mutex>, Mutex>)> = Lazy::new(|| { + let (tx, rx) = mpsc::channel::<()>(1); + (Mutex::new(tx), Mutex::new(rx)) +}); + #[tokio::main] #[allow(unused_variables)] // because tun_fd is only used in android and ios pub async fn start_mycelium(peers: Vec, tun_fd: i32, priv_key: Vec) { + #[cfg(target_os = "android")] + setup_the_logger(); + + info!("starting mycelium"); let endpoints: Vec = peers .into_iter() .filter_map(|peer| peer.parse().ok()) .collect(); - #[cfg(target_os = "android")] - setup_the_logger(); - let secret_key = build_secret_key(priv_key).await.unwrap(); let config = Config { @@ -45,14 +56,29 @@ pub async fn start_mycelium(peers: Vec, tun_fd: i32, priv_key: Vec) match _node { Ok(_) => info!("node successfully created"), - // use info! here because error! is not printed - Err(err) => info!("failed to create stack: {err}"), + Err(err) => error!("failed to create mycelium node: {err}"), }; - // TODO: check what is the better way in Android and iOS - if let Err(e) = tokio::signal::ctrl_c().await { - log::error!("Failed to wait for SIGINT: {e}"); + let mut rx = CHANNEL.1.lock().unwrap(); + tokio::select! { + _ = tokio::signal::ctrl_c() => { + info!("Received SIGINT, stopping mycelium node"); + } + _ = rx.recv() => { + info!("Received stop channel, stopping mycelium node"); + } } + info!("mycelium stopped"); +} + +#[tokio::main] +pub async fn stop_mycelium() { + info!("stopping mycelium by sending stop channel"); + // TODO: check what happens if we send multiple times? + // it is currently OK to have this implementation because + // we prevent multiple calls to stop_mycelium from the UI side. + let tx = CHANNEL.0.lock().unwrap(); + tx.send(()).await.unwrap(); } #[derive(Clone)]