connect: catch panics during init

This commit is contained in:
Jon Häggblad
2022-07-04 14:59:01 +02:00
parent 1c0ce9a420
commit 06b823f4c1
6 changed files with 46 additions and 17 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ serde_json = "1.0"
tauri = { version = "=1.0.0-rc.8", features = ["ayatana-tray", "shell-open", "system-tray"] }
tendermint-rpc = "0.23.0"
thiserror = "1.0"
tokio = { version = "1.19.1", features = ["sync"] }
tokio = { version = "1.19.1", features = ["sync", "time"] }
url = "2.2"
log = "0.4"
pretty_env_logger = "0.4.0"
+18 -6
View File
@@ -76,10 +76,22 @@ impl Config {
self.socks5.get_base_mut()
}
pub async fn init(service_provider: &str, chosen_gateway_id: &str) {
pub async fn init(service_provider: &str, chosen_gateway_id: &str) -> Result<(), BackendError> {
info!("Initialising...");
init_socks5(service_provider, chosen_gateway_id).await;
let service_provider = service_provider.to_owned();
let chosen_gateway_id = chosen_gateway_id.to_owned();
// The client initialization was originally not written for this use case, so there are
// lots of ways it can panic. Until we have proper error handling in the init code for the
// clients we'll catch any panics here.
std::panic::catch_unwind(move || {
futures::executor::block_on(init_socks5(service_provider, chosen_gateway_id));
})
.map_err(|_| BackendError::InitializationPanic)?;
info!("Configuration saved 🚀");
Ok(())
}
pub fn config_file_location(id: &str) -> PathBuf {
@@ -87,11 +99,11 @@ impl Config {
}
}
pub async fn init_socks5(provider_address: &str, chosen_gateway_id: &str) {
pub async fn init_socks5(provider_address: String, chosen_gateway_id: String) {
log::info!("Initialising client...");
// Append the gateway id to the name id that we store the config under
let id = append_config_id(chosen_gateway_id);
let id = append_config_id(&chosen_gateway_id);
log::debug!(
"Attempting to use config file location: {}",
@@ -112,7 +124,7 @@ pub async fn init_socks5(provider_address: &str, chosen_gateway_id: &str) {
let register_gateway = !already_init || user_wants_force_register;
log::trace!("Creating config for id: {}", id);
let mut config = Config::new(id.as_str(), provider_address);
let mut config = Config::new(id.as_str(), &provider_address);
// As far as I'm aware, these two are not used, they are only set because the socks5 init code
// requires them for initialising the bandwidth controller.
@@ -126,7 +138,7 @@ pub async fn init_socks5(provider_address: &str, chosen_gateway_id: &str) {
let gateway = setup_gateway(
&id,
register_gateway,
Some(chosen_gateway_id),
Some(&chosen_gateway_id),
config.get_socks5(),
)
.await;
+2
View File
@@ -19,6 +19,8 @@ pub enum BackendError {
#[from]
source: reqwest::Error,
},
#[error("Initialization failed with a panic")]
InitializationPanic,
}
impl Serialize for BackendError {
+1
View File
@@ -68,5 +68,6 @@ fn setup_logging() {
.filter_module("sled", log::LevelFilter::Warn)
.filter_module("tokio_tungstenite", log::LevelFilter::Warn)
.filter_module("tungstenite", log::LevelFilter::Warn)
.filter_module("want", log::LevelFilter::Warn)
.init();
}
@@ -13,7 +13,7 @@ pub async fn start_connecting(
log::trace!("Start connecting with:");
log::trace!(" service_provider: {:?}", guard.get_service_provider());
log::trace!(" gateway: {:?}", guard.get_gateway());
guard.start_connecting(&window).await
guard.start_connecting(&window).await?
};
// Setup task for checking status
+23 -9
View File
@@ -1,11 +1,13 @@
use std::time::Duration;
use futures::SinkExt;
use log::info;
use tauri::Manager;
use nym_socks5::client::{Socks5ControlMessage, Socks5ControlMessageSender};
use crate::{
config::append_config_id,
error::BackendError,
models::{
AppEventConnectionStatusChangedPayload, ConnectionStatusKind,
APP_EVENT_CONNECTION_STATUS_CHANGED,
@@ -61,7 +63,7 @@ impl State {
self.gateway = Some(gateway);
}
pub async fn init_config(&self) {
pub async fn init_config(&self) -> Result<(), BackendError> {
let service_provider = self
.service_provider
.as_ref()
@@ -70,16 +72,28 @@ impl State {
.gateway
.as_ref()
.expect("Attempting to init without gateway");
crate::config::Config::init(service_provider, gateway).await;
crate::config::Config::init(service_provider, gateway).await
}
pub async fn start_connecting(&mut self, window: &tauri::Window<tauri::Wry>) -> StatusReceiver {
info!("Connecting");
pub async fn start_connecting(
&mut self,
window: &tauri::Window<tauri::Wry>,
) -> Result<StatusReceiver, BackendError> {
log::info!("Connecting");
self.set_state(ConnectionStatusKind::Connecting, window);
self.status = ConnectionStatusKind::Connecting;
// Setup configuration by writing to file
self.init_config().await;
if let Err(err) = self.init_config().await {
log::warn!("Failed to initialize: {}", err);
// Wait a little to give the user some rudimentary feedback that the click actually
// registered.
tokio::time::sleep(Duration::from_secs(1)).await;
self.set_state(ConnectionStatusKind::Disconnected, window);
self.status = ConnectionStatusKind::Disconnected;
return Err(err);
}
// Kick off the main task and get the channel for controlling it
let id = append_config_id(
@@ -94,11 +108,11 @@ impl State {
self.status = ConnectionStatusKind::Connected;
self.set_state(ConnectionStatusKind::Connected, window);
status_receiver
Ok(status_receiver)
}
pub async fn start_disconnecting(&mut self, window: &tauri::Window<tauri::Wry>) {
info!("Disconnecting");
log::info!("Disconnecting");
self.set_state(ConnectionStatusKind::Disconnecting, window);
self.status = ConnectionStatusKind::Disconnecting;
@@ -109,7 +123,7 @@ impl State {
}
pub async fn mark_disconnected(&mut self, window: &tauri::Window<tauri::Wry>) {
info!("Disconnected");
log::info!("Disconnected");
self.status = ConnectionStatusKind::Disconnected;
self.set_state(ConnectionStatusKind::Disconnected, window);
}