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:
parent
36d6b75c65
commit
665ab9ab82
3 changed files with 93 additions and 77 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) => {
|
Ok(_) => {
|
||||||
match hyper::body::to_bytes(r).await {
|
// Remove service from starting.
|
||||||
Ok(_) => {
|
let mut w_services = TOR_SERVER_STATE.starting_services.write();
|
||||||
// Remove service from starting.
|
w_services.remove(&service_id);
|
||||||
let mut w_services = TOR_SERVER_STATE.starting_services.write();
|
// Check again after 5 seconds.
|
||||||
w_services.remove(&service_id);
|
Duration::from_millis(5000)
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
// Put service to starting.
|
|
||||||
let mut w_services = TOR_SERVER_STATE.starting_services.write();
|
|
||||||
w_services.insert(service_id.clone());
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
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
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
// Check once per 5 second.
|
sleep(duration).await;
|
||||||
sleep(Duration::from_millis(5000)).await;
|
|
||||||
}
|
}
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1047,31 +1047,6 @@ fn start_sync(mut wallet: Wallet) -> Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start Foreign API listener if API server is not running.
|
|
||||||
let mut api_server_running = {
|
|
||||||
wallet.foreign_api_server.read().is_some()
|
|
||||||
};
|
|
||||||
if !api_server_running && wallet.is_open() {
|
|
||||||
match start_api_server(&mut wallet) {
|
|
||||||
Ok(api_server) => {
|
|
||||||
let mut api_server_w = wallet.foreign_api_server.write();
|
|
||||||
*api_server_w = Some(api_server);
|
|
||||||
api_server_running = true;
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start Tor service if API server is running and wallet is open.
|
|
||||||
if wallet.auto_start_tor_listener() && wallet.is_open() && api_server_running &&
|
|
||||||
!Tor::is_service_running(&wallet.identifier()) {
|
|
||||||
let r_foreign_api = wallet.foreign_api_server.read();
|
|
||||||
let api = r_foreign_api.as_ref().unwrap();
|
|
||||||
if let Ok(sec_key) = wallet.secret_key() {
|
|
||||||
Tor::start_service(api.1, sec_key, &wallet.identifier());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan outputs if repair is needed or sync data if there is no error.
|
// Scan outputs if repair is needed or sync data if there is no error.
|
||||||
if !wallet.sync_error() {
|
if !wallet.sync_error() {
|
||||||
if wallet.is_repairing() {
|
if wallet.is_repairing() {
|
||||||
|
@ -1093,8 +1068,38 @@ fn start_sync(mut wallet: Wallet) -> Thread {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat after default or attempt delay if synchronization was not successful.
|
// Setup flag to check if sync was failed.
|
||||||
let failed_sync = wallet.sync_error() || wallet.get_sync_attempts() != 0;
|
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.
|
||||||
|
let mut api_server_running = {
|
||||||
|
wallet.foreign_api_server.read().is_some()
|
||||||
|
};
|
||||||
|
if !api_server_running && wallet.is_open() {
|
||||||
|
match start_api_server(&mut wallet) {
|
||||||
|
Ok(api_server) => {
|
||||||
|
let mut api_server_w = wallet.foreign_api_server.write();
|
||||||
|
*api_server_w = Some(api_server);
|
||||||
|
api_server_running = true;
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start Tor service if API server is running and wallet is open.
|
||||||
|
if wallet.auto_start_tor_listener() && wallet.is_open() && api_server_running &&
|
||||||
|
!Tor::is_service_running(&wallet.identifier()) {
|
||||||
|
let r_foreign_api = wallet.foreign_api_server.read();
|
||||||
|
let api = r_foreign_api.as_ref().unwrap();
|
||||||
|
if let Ok(sec_key) = wallet.secret_key() {
|
||||||
|
Tor::start_service(api.1, sec_key, &wallet.identifier());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repeat after default or attempt delay if synchronization was not successful.
|
||||||
let delay = if failed_sync {
|
let delay = if failed_sync {
|
||||||
ATTEMPT_DELAY
|
ATTEMPT_DELAY
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue