tor: restart service on 3rd ping error, do not start API and Tor service before first successful sync, restart running service or rebuild client on config change

This commit is contained in:
ardocrat 2024-05-16 21:29:07 +03:00
parent 36d6b75c65
commit 665ab9ab82
3 changed files with 93 additions and 77 deletions

View file

@ -285,6 +285,19 @@ impl WalletTransport {
let os = OperatingSystem::from_target_os(); let os = OperatingSystem::from_target_os();
let show_bridges = os != OperatingSystem::Android; let show_bridges = os != OperatingSystem::Android;
// Restart running service or rebuild client.
let restart_or_rebuild = || {
let service_id = &wallet.identifier();
if Tor::is_service_running(service_id) {
if let Ok(key) = wallet.secret_key() {
let api_port = wallet.foreign_api_port().unwrap();
Tor::restart_service(api_port, key, service_id);
}
} else {
Tor::rebuild_client();
}
};
ui.add_space(6.0); ui.add_space(6.0);
if show_bridges { if show_bridges {
let bridge = TorConfig::get_bridge(); let bridge = TorConfig::get_bridge();
@ -304,14 +317,8 @@ impl WalletTransport {
Some(b) Some(b)
}; };
TorConfig::save_bridge(value); TorConfig::save_bridge(value);
// Restart service. // Restart running service or rebuild client.
if let Ok(key) = wallet.secret_key() { restart_or_rebuild();
let service_id = &wallet.identifier();
Tor::stop_service(service_id);
Tor::rebuild_client();
let api_port = wallet.foreign_api_port().unwrap();
Tor::start_service(api_port, key, service_id);
}
}); });
}); });
@ -341,14 +348,8 @@ impl WalletTransport {
if current_bridge != bridge { if current_bridge != bridge {
TorConfig::save_bridge(Some(bridge.clone())); TorConfig::save_bridge(Some(bridge.clone()));
self.bridge_bin_path_edit = bridge.binary_path(); self.bridge_bin_path_edit = bridge.binary_path();
// Restart service. // Restart running service or rebuild client.
if let Ok(key) = wallet.secret_key() { restart_or_rebuild();
let service_id = &wallet.identifier();
Tor::stop_service(service_id);
Tor::rebuild_client();
let api_port = wallet.foreign_api_port().unwrap();
Tor::start_service(api_port, key, service_id);
}
} }
// Draw binary path text edit. // Draw binary path text edit.
@ -370,13 +371,8 @@ impl WalletTransport {
} }
}; };
TorConfig::save_bridge(Some(b)); TorConfig::save_bridge(Some(b));
// Restart service. // Restart running service or rebuild client.
if let Ok(key) = wallet.secret_key() { restart_or_rebuild();
let service_id = &wallet.identifier();
Tor::stop_service(service_id);
let api_port = wallet.foreign_api_port().unwrap();
Tor::start_service(api_port, key, service_id);
}
} }
ui.add_space(2.0); ui.add_space(2.0);
} }

View file

@ -18,7 +18,6 @@ use std::sync::Arc;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use arti_client::config::pt::TransportConfigBuilder; use arti_client::config::pt::TransportConfigBuilder;
use grin_api::client;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use futures::task::SpawnExt; use futures::task::SpawnExt;
@ -34,7 +33,7 @@ use sha2::Sha512;
use tokio::time::sleep; use tokio::time::sleep;
use tor_config::CfgPath; use tor_config::CfgPath;
use tor_rtcompat::tokio::TokioNativeTlsRuntime; use tor_rtcompat::tokio::TokioNativeTlsRuntime;
use tor_rtcompat::{BlockOn, Runtime}; use tor_rtcompat::Runtime;
use tor_hsrproxy::OnionServiceReverseProxy; use tor_hsrproxy::OnionServiceReverseProxy;
use tor_hsrproxy::config::{Encapsulation, ProxyAction, ProxyPattern, ProxyRule, TargetAddr, ProxyConfigBuilder}; use tor_hsrproxy::config::{Encapsulation, ProxyAction, ProxyPattern, ProxyRule, TargetAddr, ProxyConfigBuilder};
use tor_hsservice::config::OnionServiceConfigBuilder; use tor_hsservice::config::OnionServiceConfigBuilder;
@ -115,7 +114,7 @@ impl Tor {
.unwrap(), config) .unwrap(), config)
} }
/// Recreate Tor client on configuration change. /// Recreate Tor client.
pub fn rebuild_client() { pub fn rebuild_client() {
let client_config = Self::build_client(TokioNativeTlsRuntime::create().unwrap()); let client_config = Self::build_client(TokioNativeTlsRuntime::create().unwrap());
let mut w_client = TOR_SERVER_STATE.client_config.write(); let mut w_client = TOR_SERVER_STATE.client_config.write();
@ -182,6 +181,13 @@ impl Tor {
r_services.contains(id) r_services.contains(id)
} }
// Restart Onion service.
pub fn restart_service(port: u16, key: SecretKey, id: &String) {
Self::stop_service(id);
Self::rebuild_client();
Self::start_service(port, key, id)
}
/// Stop running Onion service. /// Stop running Onion service.
pub fn stop_service(id: &String) { pub fn stop_service(id: &String) {
let mut w_services = TOR_SERVER_STATE.running_services.write(); let mut w_services = TOR_SERVER_STATE.running_services.write();
@ -237,9 +243,9 @@ impl Tor {
} }
let url = format!("http://{}/v2/foreign", service.onion_name().unwrap().to_string()); let url = format!("http://{}/v2/foreign", service.onion_name().unwrap().to_string());
thread::spawn(move || { thread::spawn(move || {
// Wait 5 seconds to start. // Wait 1 second to start.
thread::sleep(Duration::from_millis(5000)); thread::sleep(Duration::from_millis(1000));
let runtime = TokioNativeTlsRuntime::create().unwrap(); let runtime = client_thread.runtime();
let client_runtime = runtime.clone(); let client_runtime = runtime.clone();
// Put service to checking. // Put service to checking.
{ {
@ -248,9 +254,10 @@ impl Tor {
} }
runtime runtime
.spawn(async move { .spawn(async move {
const MAX_ERRORS: i32 = 3;
let mut errors_count = 0;
loop { loop {
if !Self::is_service_running(&service_id) && if !Self::is_service_running(&service_id) {
!Self::is_service_starting(&service_id) {
// Remove service from checking. // Remove service from checking.
let mut w_services = TOR_SERVER_STATE.checking_services.write(); let mut w_services = TOR_SERVER_STATE.checking_services.write();
w_services.remove(&service_id); w_services.remove(&service_id);
@ -276,29 +283,37 @@ impl Tor {
.body(Body::from(data)) .body(Body::from(data))
.unwrap(); .unwrap();
// Send request. // Send request.
match http.request(req).await { let duration = match http.request(req).await {
Ok(r) => {
match hyper::body::to_bytes(r).await {
Ok(_) => { Ok(_) => {
// Remove service from starting. // Remove service from starting.
let mut w_services = TOR_SERVER_STATE.starting_services.write(); let mut w_services = TOR_SERVER_STATE.starting_services.write();
w_services.remove(&service_id); w_services.remove(&service_id);
// Check again after 5 seconds.
Duration::from_millis(5000)
}, },
Err(_) => { Err(_) => {
// Put service to starting. // Restart service on 3rd error.
let mut w_services = TOR_SERVER_STATE.starting_services.write(); let duration = if errors_count == MAX_ERRORS - 1 {
w_services.insert(service_id.clone()); errors_count = 0;
let key = key.clone();
let service_id = service_id.clone();
let client_runtime = client_runtime.clone();
thread::spawn(move || {
Self::stop_service(&service_id);
let client_config = Self::build_client(client_runtime);
let mut w_client = TOR_SERVER_STATE.client_config.write();
*w_client = client_config;
Self::start_service(port, key, &service_id);
});
Duration::from_millis(5000)
} else {
errors_count += 1;
Duration::from_millis(1000)
};
duration
}, },
} };
}, sleep(duration).await;
Err(_) => {
// Put service to starting.
let mut w_services = TOR_SERVER_STATE.starting_services.write();
w_services.insert(service_id.clone());
},
}
// Check once per 5 second.
sleep(Duration::from_millis(5000)).await;
} }
}).unwrap(); }).unwrap();
}); });

View file

@ -1047,6 +1047,32 @@ fn start_sync(mut wallet: Wallet) -> Thread {
} }
} }
// Scan outputs if repair is needed or sync data if there is no error.
if !wallet.sync_error() {
if wallet.is_repairing() {
repair_wallet(&wallet)
} else {
sync_wallet_data(&wallet);
}
}
// Stop sync if wallet was closed.
if !wallet.is_open() {
// Clear thread instance.
let mut thread_w = wallet.sync_thread.write();
*thread_w = None;
// Clear wallet info.
let mut w_data = wallet.data.write();
*w_data = None;
return;
}
// Setup flag to check if sync was failed.
let failed_sync = wallet.sync_error() || wallet.get_sync_attempts() != 0;
// Start Foreign API server and Tor service only if first sync was successful.
if !failed_sync {
// Start Foreign API listener if API server is not running. // Start Foreign API listener if API server is not running.
let mut api_server_running = { let mut api_server_running = {
wallet.foreign_api_server.read().is_some() wallet.foreign_api_server.read().is_some()
@ -1071,30 +1097,9 @@ fn start_sync(mut wallet: Wallet) -> Thread {
Tor::start_service(api.1, sec_key, &wallet.identifier()); Tor::start_service(api.1, sec_key, &wallet.identifier());
} }
} }
// Scan outputs if repair is needed or sync data if there is no error.
if !wallet.sync_error() {
if wallet.is_repairing() {
repair_wallet(&wallet)
} else {
sync_wallet_data(&wallet);
}
}
// Stop sync if wallet was closed.
if !wallet.is_open() {
// Clear thread instance.
let mut thread_w = wallet.sync_thread.write();
*thread_w = None;
// Clear wallet info.
let mut w_data = wallet.data.write();
*w_data = None;
return;
} }
// Repeat after default or attempt delay if synchronization was not successful. // Repeat after default or attempt delay if synchronization was not successful.
let failed_sync = wallet.sync_error() || wallet.get_sync_attempts() != 0;
let delay = if failed_sync { let delay = if failed_sync {
ATTEMPT_DELAY ATTEMPT_DELAY
} else { } else {