update: recreate tor client on failure in metadata loop

This commit is contained in:
hinto-janaiyo 2022-11-19 09:39:26 -05:00
parent 14c7664177
commit ff98b2a303
No known key found for this signature in database
GPG key ID: B1C5A64B80691E45
6 changed files with 38 additions and 29 deletions

View file

@ -37,7 +37,6 @@ log = "0.4.17"
monero = "0.18.0" monero = "0.18.0"
num_cpus = "1.13.1" num_cpus = "1.13.1"
num-format = "0.4.0" num-format = "0.4.0"
openssl = { version = "*", features = ["vendored"] }
rand = "0.8.5" rand = "0.8.5"
regex = "1.6.0" regex = "1.6.0"
reqwest = { version = "0.11.12", features = ["blocking", "json"] } reqwest = { version = "0.11.12", features = ["blocking", "json"] }
@ -57,6 +56,10 @@ walkdir = "2.3.2"
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
tar = "0.4.38" tar = "0.4.38"
# Bundle OpenSSL for Linux
[target.'cfg(linux)'.dependencies]
openssl = { version = "*", features = ["vendored"] }
# Windows dependencies # Windows dependencies
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
zip = "0.6.3" zip = "0.6.3"

View file

@ -67,11 +67,12 @@ With Monero GUI managing the Monero node on one side and Gupax managing P2Pool/X
| Monerujo | nodex.monerujo.io | 18081 | | Monerujo | nodex.monerujo.io | 18081 |
| Rino | node.community.rino.io | 18081 | | Rino | node.community.rino.io | 18081 |
| Seth | node.sethforprivacy.com | 18089 | | Seth | node.sethforprivacy.com | 18089 |
| Singapore | node.supportxmr.com | 18081 | | Singapore | singapore.node.xmr | 18081 |
| SupportXmr | node.supportxmr.ir | 18081 | | SupportXmr | node.supportxmr.com | 18081 |
| SupportXmrIr | singapore.node.xmr.pm | 18089 | | SupportXmrIr | node.supportxmr.ir | 18089 |
| XmrVsBeast | p2pmd.xmrvsbeast.com | 18081 | | XmrVsBeast | p2pmd.xmrvsbeast.com | 18081 |
**Note: All have ZMQ port on 18083**
*Note: All have ZMQ port on 18083*
## Demo ## Demo
https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e-ac65-3a339b96a9d2.mp4 https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e-ac65-3a339b96a9d2.mp4

View file

@ -171,9 +171,9 @@ impl State {
address: String::with_capacity(95), address: String::with_capacity(95),
}, },
version: Arc::new(Mutex::new(Version { version: Arc::new(Mutex::new(Version {
gupax: Arc::new(Mutex::new(GUPAX_VERSION.to_string())), gupax: GUPAX_VERSION.to_string(),
p2pool: Arc::new(Mutex::new(P2POOL_VERSION.to_string())), p2pool: P2POOL_VERSION.to_string(),
xmrig: Arc::new(Mutex::new(XMRIG_VERSION.to_string())), xmrig: XMRIG_VERSION.to_string(),
})), })),
} }
} }
@ -552,7 +552,7 @@ pub struct Xmrig {
#[derive(Clone,Debug,Deserialize,Serialize)] #[derive(Clone,Debug,Deserialize,Serialize)]
pub struct Version { pub struct Version {
pub gupax: Arc<Mutex<String>>, pub gupax: String,
pub p2pool: Arc<Mutex<String>>, pub p2pool: String,
pub xmrig: Arc<Mutex<String>>, pub xmrig: String,
} }

View file

@ -72,13 +72,12 @@ impl Gupax {
update.lock().unwrap().path_xmrig = og.lock().unwrap().gupax.absolute_xmrig_path.display().to_string(); 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; update.lock().unwrap().tor = og.lock().unwrap().gupax.update_via_tor;
let og = Arc::clone(&og); let og = Arc::clone(&og);
let og_ver = Arc::clone(&og.lock().unwrap().version);
let state_ver = Arc::clone(&state_ver); let state_ver = Arc::clone(&state_ver);
let update = Arc::clone(&update); let update = Arc::clone(&update);
let update_thread = Arc::clone(&update); let update_thread = Arc::clone(&update);
thread::spawn(move|| { thread::spawn(move|| {
info!("Spawning update thread..."); 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) => { Err(e) => {
info!("Update ... FAIL ... {}", e); info!("Update ... FAIL ... {}", e);
*update.lock().unwrap().msg.lock().unwrap() = format!("{} | {}", MSG_FAILED, e); *update.lock().unwrap().msg.lock().unwrap() = format!("{} | {}", MSG_FAILED, e);

View file

@ -384,13 +384,12 @@ fn init_auto(app: &App) {
app.update.lock().unwrap().path_xmrig = path_xmrig; app.update.lock().unwrap().path_xmrig = path_xmrig;
app.update.lock().unwrap().tor = tor; app.update.lock().unwrap().tor = tor;
let og = Arc::clone(&app.og); 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 state_ver = Arc::clone(&app.state.version);
let update = Arc::clone(&app.update); let update = Arc::clone(&app.update);
let update_thread = Arc::clone(&app.update); let update_thread = Arc::clone(&app.update);
thread::spawn(move|| { thread::spawn(move|| {
info!("Spawning update thread..."); 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) => { Err(e) => {
info!("Update ... FAIL ... {}", e); info!("Update ... FAIL ... {}", e);
*update.lock().unwrap().msg.lock().unwrap() = format!("{} | {}", MSG_FAILED, e); *update.lock().unwrap().msg.lock().unwrap() = format!("{} | {}", MSG_FAILED, e);

View file

@ -270,11 +270,12 @@ impl Update {
// ClientEnum::Tor(T) => get_reponse(... T ...) // ClientEnum::Tor(T) => get_reponse(... T ...)
// ClientEnum::Https(H) => get_reponse(... H ...) // ClientEnum::Https(H) => get_reponse(... H ...)
// //
pub async fn get_client(tor: bool) -> Result<ClientEnum, anyhow::Error> { pub fn get_client(tor: bool) -> Result<ClientEnum, anyhow::Error> {
if tor { if tor {
// This one below is non-async, but it doesn't bootstrap immediately. // This one below is non-async, and doesn't bootstrap immediately.
// let tor = TorClient::builder().bootstrap_behavior(arti_client::BootstrapBehavior::OnDemand).create_unbootstrapped()?; let tor = TorClient::builder().bootstrap_behavior(arti_client::BootstrapBehavior::OnDemand).create_unbootstrapped()?;
let tor = TorClient::create_bootstrapped(TorClientConfig::default()).await?; // 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 tls = tls_api_native_tls::TlsConnector::builder()?.build()?;
let connector = ArtiHttpConnector::new(tor, tls); let connector = ArtiHttpConnector::new(tor, tls);
let client = ClientEnum::Tor(Client::builder().build(connector)); let client = ClientEnum::Tor(Client::builder().build(connector));
@ -296,7 +297,7 @@ impl Update {
// 5. extract, upgrade // 5. extract, upgrade
#[tokio::main] #[tokio::main]
pub async fn start(update: Arc<Mutex<Self>>, og_ver: Arc<Mutex<Version>>, state_ver: Arc<Mutex<Version>>) -> Result<(), anyhow::Error> { pub async fn start(update: Arc<Mutex<Self>>, og: Arc<Mutex<State>>, state_ver: Arc<Mutex<Version>>) -> Result<(), anyhow::Error> {
//---------------------------------------------------------------------------------------------------- Init //---------------------------------------------------------------------------------------------------- Init
*update.lock().unwrap().updating.lock().unwrap() = true; *update.lock().unwrap().updating.lock().unwrap() = true;
// Set timer // Set timer
@ -337,7 +338,7 @@ impl Update {
let prog = *update.lock().unwrap().prog.lock().unwrap(); let prog = *update.lock().unwrap().prog.lock().unwrap();
info!("Update | {}", update.lock().unwrap().msg.lock().unwrap()); info!("Update | {}", update.lock().unwrap().msg.lock().unwrap());
let tor = update.lock().unwrap().tor; 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; *update.lock().unwrap().prog.lock().unwrap() += 5.0;
info!("Update | Init ... OK ... {}%", prog); info!("Update | Init ... OK ... {}%", prog);
@ -351,7 +352,7 @@ impl Update {
// 3. Iterate over all [pkg.new_ver], check if empty // 3. Iterate over all [pkg.new_ver], check if empty
// 4. If not empty, move [pkg] to different vec // 4. If not empty, move [pkg] to different vec
// 5. At end, if original vec isn't empty, that means something failed // 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()] // This logic was originally in the [Pkg::get_metadata()]
// function itself but for some reason, it was getting skipped over, // function itself but for some reason, it was getting skipped over,
@ -403,6 +404,12 @@ impl Update {
vec.remove(index); vec.remove(index);
} }
if vec.is_empty() { break } 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() { if vec.is_empty() {
info!("Update | Metadata ... OK ... {}%", update.lock().unwrap().prog.lock().unwrap()); info!("Update | Metadata ... OK ... {}%", update.lock().unwrap().prog.lock().unwrap());
@ -423,21 +430,21 @@ impl Update {
let name; let name;
match pkg.name { match pkg.name {
Gupax => { 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 // 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 // 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 // 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). // 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; diff = old_ver != new_ver && GUPAX_VERSION != new_ver;
name = "Gupax"; name = "Gupax";
} }
P2pool => { 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; diff = old_ver != new_ver;
name = "P2Pool"; name = "P2Pool";
} }
Xmrig => { 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; diff = old_ver != new_ver;
name = "XMRig"; name = "XMRig";
} }
@ -577,7 +584,7 @@ impl Update {
std::fs::rename(&path, tmp_windows)?; std::fs::rename(&path, tmp_windows)?;
info!("Update | Moving [{}] -> [{}]", entry.path().display(), path); info!("Update | Moving [{}] -> [{}]", entry.path().display(), path);
std::fs::rename(entry.path(), 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(); *update.lock().unwrap().prog.lock().unwrap() += (5.0 / pkg_amount).round();
}, },
P2POOL_BINARY => { P2POOL_BINARY => {
@ -586,7 +593,7 @@ impl Update {
info!("Update | Moving [{}] -> [{}]", entry.path().display(), path.display()); 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::create_dir_all(path.parent().ok_or(anyhow::Error::msg("P2Pool path failed"))?)?;
std::fs::rename(entry.path(), path)?; 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(); *update.lock().unwrap().prog.lock().unwrap() += (5.0 / pkg_amount).round();
}, },
XMRIG_BINARY => { XMRIG_BINARY => {
@ -595,7 +602,7 @@ impl Update {
info!("Update | Moving [{}] -> [{}]", entry.path().display(), path.display()); 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::create_dir_all(path.parent().ok_or(anyhow::Error::msg("XMRig path failed"))?)?;
std::fs::rename(entry.path(), path)?; 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(); *update.lock().unwrap().prog.lock().unwrap() += (5.0 / pkg_amount).round();
}, },
_ => (), _ => (),
@ -611,7 +618,7 @@ impl Update {
let seconds = now.elapsed().as_secs(); let seconds = now.elapsed().as_secs();
info!("Update | Seconds elapsed ... [{}s]", seconds); info!("Update | Seconds elapsed ... [{}s]", seconds);
match 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), 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), _ => *update.lock().unwrap().msg.lock().unwrap() = format!("{}! Took {} seconds.{}", MSG_SUCCESS, seconds, new_pkgs),
} }