From ff98b2a3032f3338cef49ee194865308595792e7 Mon Sep 17 00:00:00 2001 From: hinto-janaiyo Date: Sat, 19 Nov 2022 09:39:26 -0500 Subject: [PATCH] update: recreate tor client on failure in metadata loop --- Cargo.toml | 5 ++++- README.md | 9 +++++---- src/disk.rs | 12 ++++++------ src/gupax.rs | 3 +-- src/main.rs | 3 +-- src/update.rs | 35 +++++++++++++++++++++-------------- 6 files changed, 38 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 888f0a3..3c4ec49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ log = "0.4.17" monero = "0.18.0" num_cpus = "1.13.1" num-format = "0.4.0" -openssl = { version = "*", features = ["vendored"] } rand = "0.8.5" regex = "1.6.0" reqwest = { version = "0.11.12", features = ["blocking", "json"] } @@ -57,6 +56,10 @@ walkdir = "2.3.2" [target.'cfg(unix)'.dependencies] tar = "0.4.38" +# Bundle OpenSSL for Linux +[target.'cfg(linux)'.dependencies] +openssl = { version = "*", features = ["vendored"] } + # Windows dependencies [target.'cfg(windows)'.dependencies] zip = "0.6.3" diff --git a/README.md b/README.md index 477fe06..3baa6aa 100644 --- a/README.md +++ b/README.md @@ -67,11 +67,12 @@ With Monero GUI managing the Monero node on one side and Gupax managing P2Pool/X | Monerujo | nodex.monerujo.io | 18081 | | Rino | node.community.rino.io | 18081 | | Seth | node.sethforprivacy.com | 18089 | -| Singapore | node.supportxmr.com | 18081 | -| SupportXmr | node.supportxmr.ir | 18081 | -| SupportXmrIr | singapore.node.xmr.pm | 18089 | +| Singapore | singapore.node.xmr | 18081 | +| SupportXmr | node.supportxmr.com | 18081 | +| SupportXmrIr | node.supportxmr.ir | 18089 | | XmrVsBeast | p2pmd.xmrvsbeast.com | 18081 | -**Note: All have ZMQ port on 18083** + +*Note: All have ZMQ port on 18083* ## Demo https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e-ac65-3a339b96a9d2.mp4 diff --git a/src/disk.rs b/src/disk.rs index c4a6a89..b7b9666 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -171,9 +171,9 @@ impl State { address: String::with_capacity(95), }, version: Arc::new(Mutex::new(Version { - gupax: Arc::new(Mutex::new(GUPAX_VERSION.to_string())), - p2pool: Arc::new(Mutex::new(P2POOL_VERSION.to_string())), - xmrig: Arc::new(Mutex::new(XMRIG_VERSION.to_string())), + gupax: GUPAX_VERSION.to_string(), + p2pool: P2POOL_VERSION.to_string(), + xmrig: XMRIG_VERSION.to_string(), })), } } @@ -552,7 +552,7 @@ pub struct Xmrig { #[derive(Clone,Debug,Deserialize,Serialize)] pub struct Version { - pub gupax: Arc>, - pub p2pool: Arc>, - pub xmrig: Arc>, + pub gupax: String, + pub p2pool: String, + pub xmrig: String, } diff --git a/src/gupax.rs b/src/gupax.rs index afdd2ad..66734f5 100644 --- a/src/gupax.rs +++ b/src/gupax.rs @@ -72,13 +72,12 @@ impl Gupax { update.lock().unwrap().path_xmrig = og.lock().unwrap().gupax.absolute_xmrig_path.display().to_string(); update.lock().unwrap().tor = og.lock().unwrap().gupax.update_via_tor; let og = Arc::clone(&og); - let og_ver = Arc::clone(&og.lock().unwrap().version); let state_ver = Arc::clone(&state_ver); let update = Arc::clone(&update); let update_thread = Arc::clone(&update); thread::spawn(move|| { info!("Spawning update thread..."); - match Update::start(update_thread, og_ver.clone(), state_ver.clone()) { + match Update::start(update_thread, og.clone(), state_ver.clone()) { Err(e) => { info!("Update ... FAIL ... {}", e); *update.lock().unwrap().msg.lock().unwrap() = format!("{} | {}", MSG_FAILED, e); diff --git a/src/main.rs b/src/main.rs index 107c2d0..24ebce1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -384,13 +384,12 @@ fn init_auto(app: &App) { app.update.lock().unwrap().path_xmrig = path_xmrig; app.update.lock().unwrap().tor = tor; let og = Arc::clone(&app.og); - let og_ver = Arc::clone(&app.og.lock().unwrap().version); let state_ver = Arc::clone(&app.state.version); let update = Arc::clone(&app.update); let update_thread = Arc::clone(&app.update); thread::spawn(move|| { info!("Spawning update thread..."); - match Update::start(update_thread, og_ver.clone(), state_ver.clone()) { + match Update::start(update_thread, og.clone(), state_ver.clone()) { Err(e) => { info!("Update ... FAIL ... {}", e); *update.lock().unwrap().msg.lock().unwrap() = format!("{} | {}", MSG_FAILED, e); diff --git a/src/update.rs b/src/update.rs index 05da782..b005fc5 100644 --- a/src/update.rs +++ b/src/update.rs @@ -270,11 +270,12 @@ impl Update { // ClientEnum::Tor(T) => get_reponse(... T ...) // ClientEnum::Https(H) => get_reponse(... H ...) // - pub async fn get_client(tor: bool) -> Result { + pub fn get_client(tor: bool) -> Result { if tor { - // This one below is non-async, but it doesn't bootstrap immediately. -// let tor = TorClient::builder().bootstrap_behavior(arti_client::BootstrapBehavior::OnDemand).create_unbootstrapped()?; - let tor = TorClient::create_bootstrapped(TorClientConfig::default()).await?; + // This one below is non-async, and doesn't bootstrap immediately. + let tor = TorClient::builder().bootstrap_behavior(arti_client::BootstrapBehavior::OnDemand).create_unbootstrapped()?; + // Below is async, bootstraps immediately but has issues when recreating the circuit +// let tor = TorClient::create_bootstrapped(TorClientConfig::default()).await?; let tls = tls_api_native_tls::TlsConnector::builder()?.build()?; let connector = ArtiHttpConnector::new(tor, tls); let client = ClientEnum::Tor(Client::builder().build(connector)); @@ -296,7 +297,7 @@ impl Update { // 5. extract, upgrade #[tokio::main] - pub async fn start(update: Arc>, og_ver: Arc>, state_ver: Arc>) -> Result<(), anyhow::Error> { + pub async fn start(update: Arc>, og: Arc>, state_ver: Arc>) -> Result<(), anyhow::Error> { //---------------------------------------------------------------------------------------------------- Init *update.lock().unwrap().updating.lock().unwrap() = true; // Set timer @@ -337,7 +338,7 @@ impl Update { let prog = *update.lock().unwrap().prog.lock().unwrap(); info!("Update | {}", update.lock().unwrap().msg.lock().unwrap()); let tor = update.lock().unwrap().tor; - let client = Self::get_client(tor).await?; + let mut client = Self::get_client(tor)?; *update.lock().unwrap().prog.lock().unwrap() += 5.0; info!("Update | Init ... OK ... {}%", prog); @@ -351,7 +352,7 @@ impl Update { // 3. Iterate over all [pkg.new_ver], check if empty // 4. If not empty, move [pkg] to different vec // 5. At end, if original vec isn't empty, that means something failed - // 6. Redo loop [3] times, with the original vec (that now only has the failed pkgs) + // 6. Redo loop [3] times (rebuild circuit if using Tor), with the original vec (that now only has the failed pkgs) // // This logic was originally in the [Pkg::get_metadata()] // function itself but for some reason, it was getting skipped over, @@ -403,6 +404,12 @@ impl Update { vec.remove(index); } if vec.is_empty() { break } + // Some Tor exit nodes seem to be blocked by GitHub's API, + // so recreate the circuit every loop. + if tor { + info!("Update | Recreating Tor client..."); + client = Self::get_client(tor)?; + } } if vec.is_empty() { info!("Update | Metadata ... OK ... {}%", update.lock().unwrap().prog.lock().unwrap()); @@ -423,21 +430,21 @@ impl Update { let name; match pkg.name { Gupax => { - old_ver = og_ver.lock().unwrap().gupax.lock().unwrap().to_string(); // Compare against the built-in compiled version as well as a in-memory version // that gets updated during an update. This prevents the updater always thinking // there's a new Gupax update since the user didnt restart and is still technically // using the old version (even though the underlying binary was updated). + old_ver = og.lock().unwrap().version.lock().unwrap().gupax.clone(); diff = old_ver != new_ver && GUPAX_VERSION != new_ver; name = "Gupax"; } P2pool => { - old_ver = og_ver.lock().unwrap().p2pool.lock().unwrap().to_string(); + old_ver = og.lock().unwrap().version.lock().unwrap().p2pool.clone(); diff = old_ver != new_ver; name = "P2Pool"; } Xmrig => { - old_ver = og_ver.lock().unwrap().xmrig.lock().unwrap().to_string(); + old_ver = og.lock().unwrap().version.lock().unwrap().xmrig.clone(); diff = old_ver != new_ver; name = "XMRig"; } @@ -577,7 +584,7 @@ impl Update { std::fs::rename(&path, tmp_windows)?; info!("Update | Moving [{}] -> [{}]", entry.path().display(), path); std::fs::rename(entry.path(), path)?; - *og_ver.lock().unwrap().gupax.lock().unwrap() = Pkg::get_new_pkg_version(Gupax, &vec4)?; + og.lock().unwrap().version.lock().unwrap().gupax = Pkg::get_new_pkg_version(Gupax, &vec4)?; *update.lock().unwrap().prog.lock().unwrap() += (5.0 / pkg_amount).round(); }, P2POOL_BINARY => { @@ -586,7 +593,7 @@ impl Update { info!("Update | Moving [{}] -> [{}]", entry.path().display(), path.display()); std::fs::create_dir_all(path.parent().ok_or(anyhow::Error::msg("P2Pool path failed"))?)?; std::fs::rename(entry.path(), path)?; - *og_ver.lock().unwrap().p2pool.lock().unwrap() = Pkg::get_new_pkg_version(P2pool, &vec4)?; + og.lock().unwrap().version.lock().unwrap().p2pool = Pkg::get_new_pkg_version(P2pool, &vec4)?; *update.lock().unwrap().prog.lock().unwrap() += (5.0 / pkg_amount).round(); }, XMRIG_BINARY => { @@ -595,7 +602,7 @@ impl Update { info!("Update | Moving [{}] -> [{}]", entry.path().display(), path.display()); std::fs::create_dir_all(path.parent().ok_or(anyhow::Error::msg("XMRig path failed"))?)?; std::fs::rename(entry.path(), path)?; - *og_ver.lock().unwrap().xmrig.lock().unwrap() = Pkg::get_new_pkg_version(Xmrig, &vec4)?; + og.lock().unwrap().version.lock().unwrap().xmrig = Pkg::get_new_pkg_version(Xmrig, &vec4)?; *update.lock().unwrap().prog.lock().unwrap() += (5.0 / pkg_amount).round(); }, _ => (), @@ -611,7 +618,7 @@ impl Update { let seconds = now.elapsed().as_secs(); info!("Update | Seconds elapsed ... [{}s]", seconds); match seconds { - 0 => *update.lock().unwrap().msg.lock().unwrap() = format!("{}! Took 0 seconds... Do you have 10Gbit internet or something...?!{}", MSG_SUCCESS, new_pkgs), + 0 => *update.lock().unwrap().msg.lock().unwrap() = format!("{}! Took 0 seconds... What...?!{}", MSG_SUCCESS, new_pkgs), 1 => *update.lock().unwrap().msg.lock().unwrap() = format!("{}! Took 1 second... Wow!{}", MSG_SUCCESS, new_pkgs), _ => *update.lock().unwrap().msg.lock().unwrap() = format!("{}! Took {} seconds.{}", MSG_SUCCESS, seconds, new_pkgs), }