From 059e400660a83c4cc3ead34ff1e7878fa0ba6c15 Mon Sep 17 00:00:00 2001 From: dav Date: Fri, 16 Aug 2024 17:32:18 -0700 Subject: [PATCH] Test against mock rpc server --- burrow-gtk/src/components/app.rs | 45 +++- burrow-gtk/src/components/main/mod.rs | 2 +- .../src/components/main/network_card.rs | 17 +- burrow-gtk/src/components/main/networks.rs | 11 +- burrow-gtk/src/components/main/switch.rs | 58 +---- burrow-gtk/src/components/main_screen.rs | 39 ++-- burrow-gtk/src/components/switch_screen.rs | 199 ------------------ 7 files changed, 82 insertions(+), 289 deletions(-) delete mode 100644 burrow-gtk/src/components/switch_screen.rs diff --git a/burrow-gtk/src/components/app.rs b/burrow-gtk/src/components/app.rs index 0fa587c0..97a3f79b 100644 --- a/burrow-gtk/src/components/app.rs +++ b/burrow-gtk/src/components/app.rs @@ -2,7 +2,7 @@ use super::*; use anyhow::Context; use std::time::Duration; -const RECONNECT_POLL_TIME: Duration = Duration::from_secs(5); +const RECONNECT_POLL_TIME: Duration = Duration::from_secs(3); pub struct App { daemon_client: Arc>>, @@ -58,7 +58,16 @@ impl AsyncComponent for App { root: Self::Root, sender: AsyncComponentSender, ) -> AsyncComponentParts { - let daemon_client = Arc::new(Mutex::new(daemon::daemon_connect().await.ok())); + // TODO: RPC REFACTOR (Handle Error) + let mut daemon_client_connected = false; + let daemon_client = Arc::new(Mutex::new( + daemon::daemon_connect() + .await + .inspect(|_| { + daemon_client_connected = true; + }) + .ok(), + )); let main_screen = main_screen::MainScreen::builder() .launch(main_screen::MainScreenInit { @@ -72,6 +81,17 @@ impl AsyncComponent for App { }) .forward(sender.input_sender(), |_| AppMsg::None); + if !daemon_client_connected { + main_screen + .sender() + .send(main_screen::MainScreenMsg::DaemonDisconnect) + .unwrap(); + settings_screen + .sender() + .send(settings_screen::SettingsScreenMsg::DaemonStateChange) + .unwrap(); + } + let widgets = view_output!(); let view_stack = adw::ViewStack::new(); @@ -126,15 +146,20 @@ impl AsyncComponent for App { let mut daemon_client = self.daemon_client.lock().await; let mut disconnected_daemon_client = false; - if let Some(daemon_client) = daemon_client.as_mut() { - let mut client = tunnel_client::TunnelClient::new(daemon_client); - if let Err(_e) = client.tunnel_status(burrow_rpc::Empty {}).await { - disconnected_daemon_client = true; - self.main_screen - .emit(main_screen::MainScreenMsg::DaemonDisconnect); - self.settings_screen - .emit(settings_screen::SettingsScreenMsg::DaemonStateChange) + if let Some(client) = daemon_client.as_mut() { + let mut client = tunnel_client::TunnelClient::new(client); + + if let Ok(mut res) = client.tunnel_status(burrow_rpc::Empty {}).await { + let stream = res.get_mut(); + while let Ok(Some(_)) = stream.message().await {} } + + *daemon_client = None; + disconnected_daemon_client = true; + self.main_screen + .emit(main_screen::MainScreenMsg::DaemonDisconnect); + self.settings_screen + .emit(settings_screen::SettingsScreenMsg::DaemonStateChange) } if disconnected_daemon_client || daemon_client.is_none() { diff --git a/burrow-gtk/src/components/main/mod.rs b/burrow-gtk/src/components/main/mod.rs index 8e03b41e..903bfba0 100644 --- a/burrow-gtk/src/components/main/mod.rs +++ b/burrow-gtk/src/components/main/mod.rs @@ -6,4 +6,4 @@ mod switch; pub use network_card::{NetworkCard, NetworkCardInit}; pub use networks::{Networks, NetworksInit}; -pub use switch::{Switch, SwitchInit, SwitchMsg}; +pub use switch::{Switch, SwitchInit}; diff --git a/burrow-gtk/src/components/main/network_card.rs b/burrow-gtk/src/components/main/network_card.rs index 41a1aa2c..b002cd1b 100644 --- a/burrow-gtk/src/components/main/network_card.rs +++ b/burrow-gtk/src/components/main/network_card.rs @@ -86,30 +86,28 @@ impl AsyncComponent for NetworkCard { async fn update( &mut self, msg: Self::Input, - sender: AsyncComponentSender, + _: AsyncComponentSender, _root: &Self::Root, ) { match msg { NetworkCardMsg::NetworkDelete => { if let Some(daemon_client) = self.daemon_client.lock().await.as_mut() { let mut client = networks_client::NetworksClient::new(daemon_client); - client + let _ = client .network_delete(burrow_rpc::NetworkDeleteRequest { id: self.id }) - .await - .unwrap(); + .await; } } NetworkCardMsg::MoveUp => { if self.index.checked_sub(1).is_some() { if let Some(daemon_client) = self.daemon_client.lock().await.as_mut() { let mut client = networks_client::NetworksClient::new(daemon_client); - client + let _ = client .network_reorder(burrow_rpc::NetworkReorderRequest { id: self.id, index: self.index as i32 - 1, }) - .await - .unwrap(); + .await; } } } @@ -117,13 +115,12 @@ impl AsyncComponent for NetworkCard { if self.index + 1 < self.index_max { if let Some(daemon_client) = self.daemon_client.lock().await.as_mut() { let mut client = networks_client::NetworksClient::new(daemon_client); - client + let _ = client .network_reorder(burrow_rpc::NetworkReorderRequest { id: self.id, index: self.index as i32 + 1, }) - .await - .unwrap(); + .await; } } } diff --git a/burrow-gtk/src/components/main/networks.rs b/burrow-gtk/src/components/main/networks.rs index 5c63b944..aabd480f 100644 --- a/burrow-gtk/src/components/main/networks.rs +++ b/burrow-gtk/src/components/main/networks.rs @@ -7,6 +7,8 @@ pub struct Networks { daemon_client: Arc>>, network_cards: Vec>, networks_list_box: gtk::ListBox, + + _network_state_worker: WorkerController, } pub struct NetworksInit { @@ -94,6 +96,10 @@ impl AsyncComponent for Networks { daemon_client: init.daemon_client, network_cards, networks_list_box: widgets.networks.clone(), + + _network_state_worker: AsyncNetworkStateHandler::builder() + .detach_worker(()) + .forward(sender.input_sender(), |msg| msg), }; AsyncComponentParts { model, widgets } @@ -132,7 +138,7 @@ impl AsyncComponent for Networks { NetworksMsg::NetworkAdd => { if let Some(daemon_client) = self.daemon_client.lock().await.as_mut() { let mut client = networks_client::NetworksClient::new(daemon_client); - client.network_add(burrow_rpc::Empty {}).await.unwrap(); + let _ = client.network_add(burrow_rpc::Empty {}).await; } } _ => {} @@ -147,7 +153,8 @@ impl Worker for AsyncNetworkStateHandler { type Input = (); type Output = NetworksMsg; - fn init(_: Self::Init, _sender: ComponentSender) -> Self { + fn init(_: Self::Init, sender: ComponentSender) -> Self { + sender.input(()); Self } diff --git a/burrow-gtk/src/components/main/switch.rs b/burrow-gtk/src/components/main/switch.rs index 5958e834..0b812ca4 100644 --- a/burrow-gtk/src/components/main/switch.rs +++ b/burrow-gtk/src/components/main/switch.rs @@ -6,8 +6,6 @@ const RECONNECT_POLL_TIME: Duration = Duration::from_secs(3); pub struct Switch { daemon_client: Arc>>, switch: gtk::Switch, - switch_screen: gtk::Box, - disconnected_banner: adw::Banner, _tunnel_state_worker: WorkerController, } @@ -19,8 +17,6 @@ pub struct SwitchInit { #[derive(Debug, PartialEq, Eq)] pub enum SwitchMsg { None, - DaemonReconnect, - DaemonDisconnect, Start, Stop, SwitchSetStart, @@ -51,7 +47,6 @@ impl AsyncComponent for Switch { }, }, - #[name(switch_screen)] gtk::Box { set_orientation: gtk::Orientation::Vertical, set_spacing: 10, @@ -80,37 +75,12 @@ impl AsyncComponent for Switch { root: Self::Root, sender: AsyncComponentSender, ) -> AsyncComponentParts { - let mut initial_daemon_server_down = false; - - if let Some(daemon_client) = init.daemon_client.lock().await.as_mut() { - let mut client = tunnel_client::TunnelClient::new(daemon_client); - if client - .tunnel_status(burrow_rpc::Empty {}) - .await - .as_mut() - .is_err() - { - initial_daemon_server_down = true; - } - } else { - initial_daemon_server_down = true; - } - let switch_sender = sender.clone(); let widgets = view_output!(); - if initial_daemon_server_down { - *init.daemon_client.lock().await = None; - widgets.switch.set_active(false); - widgets.switch_screen.set_sensitive(false); - widgets.setup_banner.set_revealed(true); - } - let model = Switch { daemon_client: init.daemon_client, switch: widgets.switch.clone(), - switch_screen: widgets.switch_screen.clone(), - disconnected_banner: widgets.setup_banner.clone(), _tunnel_state_worker: AsyncTunnelStateHandler::builder() .detach_worker(()) .forward(sender.input_sender(), |_| SwitchMsg::None), @@ -127,20 +97,16 @@ impl AsyncComponent for Switch { _: AsyncComponentSender, _root: &Self::Root, ) { - let mut disconnected_daemon_client = false; - if let Some(daemon_client) = self.daemon_client.lock().await.as_mut() { let mut client = tunnel_client::TunnelClient::new(daemon_client); match msg { Self::Input::Start => { - if let Err(_e) = client.tunnel_start(burrow_rpc::Empty {}).await { - disconnected_daemon_client = true; - } + // TODO: Figure out best way for error handling. + let _ = client.tunnel_start(burrow_rpc::Empty {}).await; } Self::Input::Stop => { - if let Err(_e) = client.tunnel_stop(burrow_rpc::Empty {}).await { - disconnected_daemon_client = true; - } + // TODO: Figure out best way for error handling. + let _ = client.tunnel_stop(burrow_rpc::Empty {}).await; } Self::Input::SwitchSetStart => { self.switch.set_active(true); @@ -150,19 +116,6 @@ impl AsyncComponent for Switch { } _ => {} } - } else { - disconnected_daemon_client = true; - } - - if msg == Self::Input::DaemonReconnect { - self.disconnected_banner.set_revealed(false); - self.switch_screen.set_sensitive(true); - } - - if disconnected_daemon_client || msg == Self::Input::DaemonDisconnect { - *self.daemon_client.lock().await = None; - self.switch_screen.set_sensitive(false); - self.disconnected_banner.set_revealed(true); } } } @@ -174,7 +127,8 @@ impl Worker for AsyncTunnelStateHandler { type Input = (); type Output = SwitchMsg; - fn init(_: Self::Init, _sender: ComponentSender) -> Self { + fn init(_: Self::Init, sender: ComponentSender) -> Self { + sender.input(()); Self } diff --git a/burrow-gtk/src/components/main_screen.rs b/burrow-gtk/src/components/main_screen.rs index 973fe78c..fc55a127 100644 --- a/burrow-gtk/src/components/main_screen.rs +++ b/burrow-gtk/src/components/main_screen.rs @@ -1,8 +1,10 @@ use super::*; pub struct MainScreen { - switch: AsyncController, - networks: AsyncController, + _switch: AsyncController, + _networks: AsyncController, + content_box: gtk::Box, + daemon_status_banner: adw::Banner, } pub struct MainScreenInit { @@ -29,17 +31,17 @@ impl AsyncComponent for MainScreen { set_valign: Align::Fill, set_valign: Align::Center, - // gtk::Box { - // set_orientation: gtk::Orientation::Vertical, - // set_spacing: 5, - // set_margin_all: 5, - // set_valign: Align::Start, + gtk::Box { + set_orientation: gtk::Orientation::Vertical, + set_spacing: 5, + set_margin_all: 5, + set_valign: Align::Start, - // #[name(setup_banner)] - // adw::Banner { - // set_title: "Burrow is not running!", - // }, - // }, + #[name(daemon_status_banner)] + adw::Banner { + set_title: "Burrow is not running!", + }, + }, gtk::Box { set_orientation: gtk::Orientation::Vertical, @@ -86,7 +88,12 @@ impl AsyncComponent for MainScreen { widgets.content.append(networks.widget()); widgets.content.append(switch.widget()); - let model = MainScreen { switch, networks }; + let model = MainScreen { + _switch: switch, + _networks: networks, + content_box: widgets.content.clone(), + daemon_status_banner: widgets.daemon_status_banner.clone(), + }; AsyncComponentParts { model, widgets } } @@ -99,10 +106,12 @@ impl AsyncComponent for MainScreen { ) { match msg { MainScreenMsg::DaemonDisconnect => { - self.switch.emit(main::SwitchMsg::DaemonDisconnect); + self.daemon_status_banner.set_revealed(true); + self.content_box.set_sensitive(false); } MainScreenMsg::DaemonReconnect => { - self.switch.emit(main::SwitchMsg::DaemonReconnect); + self.daemon_status_banner.set_revealed(false); + self.content_box.set_sensitive(true); } _ => {} } diff --git a/burrow-gtk/src/components/switch_screen.rs b/burrow-gtk/src/components/switch_screen.rs deleted file mode 100644 index 9af3ba60..00000000 --- a/burrow-gtk/src/components/switch_screen.rs +++ /dev/null @@ -1,199 +0,0 @@ -use super::*; -use std::{ - thread::{self, JoinHandle}, - time::Duration, -}; - -const RECONNECT_POLL_TIME: Duration = Duration::from_secs(3); - -pub struct SwitchScreen { - daemon_client: Arc>>, - switch: gtk::Switch, - switch_screen: gtk::Box, - disconnected_banner: adw::Banner, - tunnel_state_worker: JoinHandle<()>, -} - -pub struct SwitchScreenInit { - pub daemon_client: Arc>>, -} - -#[derive(Debug, PartialEq, Eq)] -pub enum SwitchScreenMsg { - DaemonReconnect, - DaemonDisconnect, - Start, - Stop, - TunnelStateStopped, - TunnelStateRunning, -} - -#[relm4::component(pub, async)] -impl AsyncComponent for SwitchScreen { - type Init = SwitchScreenInit; - type Input = SwitchScreenMsg; - type Output = (); - type CommandOutput = SwitchScreenMsg; - - view! { - gtk::Box { - set_orientation: gtk::Orientation::Vertical, - set_valign: Align::Fill, - - gtk::Box { - set_orientation: gtk::Orientation::Vertical, - set_spacing: 5, - set_margin_all: 5, - set_valign: Align::Start, - - #[name(setup_banner)] - adw::Banner { - set_title: "Burrow is not running!", - }, - }, - - #[name(switch_screen)] - gtk::Box { - set_orientation: gtk::Orientation::Vertical, - set_spacing: 10, - set_margin_all: 5, - set_valign: Align::Center, - set_vexpand: true, - - gtk::Label { - set_label: "Burrow Switch", - }, - - #[name(switch)] - gtk::Switch { - set_halign: Align::Center, - set_hexpand: false, - set_vexpand: false, - connect_active_notify => move |switch| - switch_sender.input(if switch.is_active() { SwitchScreenMsg::Start } else { SwitchScreenMsg::Stop }) - }, - } - } - } - - async fn init( - init: Self::Init, - root: Self::Root, - sender: AsyncComponentSender, - ) -> AsyncComponentParts { - let mut initial_daemon_server_down = false; - - if let Some(daemon_client) = init.daemon_client.lock().await.as_mut() { - let mut client = tunnel_client::TunnelClient::new(daemon_client); - if client - .tunnel_status(burrow_rpc::Empty {}) - .await - .as_mut() - .is_err() - { - initial_daemon_server_down = true; - } - } else { - initial_daemon_server_down = true; - } - - let switch_sender = sender.clone(); - let tunnel_state_sender = sender.clone(); - let widgets = view_output!(); - - if initial_daemon_server_down { - *init.daemon_client.lock().await = None; - widgets.switch.set_active(false); - widgets.switch_screen.set_sensitive(false); - widgets.setup_banner.set_revealed(true); - } - - let model = SwitchScreen { - daemon_client: init.daemon_client, - switch: widgets.switch.clone(), - switch_screen: widgets.switch_screen.clone(), - disconnected_banner: widgets.setup_banner.clone(), - tunnel_state_worker: thread::spawn(move || { - tunnel_state_worker(tunnel_state_sender); - }), - }; - - widgets.switch.set_active(false); - - AsyncComponentParts { model, widgets } - } - - async fn update( - &mut self, - msg: Self::Input, - _: AsyncComponentSender, - _root: &Self::Root, - ) { - let mut disconnected_daemon_client = false; - - if let Some(daemon_client) = self.daemon_client.lock().await.as_mut() { - let mut client = tunnel_client::TunnelClient::new(daemon_client); - match msg { - Self::Input::Start => { - if let Err(e) = client.tunnel_start(burrow_rpc::Empty {}).await { - disconnected_daemon_client = true; - } - } - Self::Input::Stop => { - if let Err(e) = client.tunnel_stop(burrow_rpc::Empty {}).await { - disconnected_daemon_client = true; - } - } - Self::Input::TunnelStateStopped => { - self.switch.set_active(false); - } - Self::Input::TunnelStateRunning => { - self.switch.set_active(true); - } - _ => {} - } - } else { - disconnected_daemon_client = true; - } - - if msg == Self::Input::DaemonReconnect { - self.disconnected_banner.set_revealed(false); - self.switch_screen.set_sensitive(true); - } - - if disconnected_daemon_client || msg == Self::Input::DaemonDisconnect { - *self.daemon_client.lock().await = None; - self.switch_screen.set_sensitive(false); - self.disconnected_banner.set_revealed(true); - } - } -} - -fn tunnel_state_worker(sender: AsyncComponentSender) { - let rt = tokio::runtime::Runtime::new().unwrap(); - let task = rt.spawn(async move { - loop { - let sender = sender.input_sender(); - let conn = daemon::daemon_connect().await; - if let Ok(conn) = conn { - let mut client = tunnel_client::TunnelClient::new(conn); - if let Ok(mut res) = client.tunnel_status(burrow_rpc::Empty {}).await { - let stream = res.get_mut(); - while let Ok(Some(msg)) = stream.message().await { - match msg.state() { - burrow_rpc::State::Stopped => { - sender.send(SwitchScreenMsg::TunnelStateStopped) - } - burrow_rpc::State::Running => { - sender.send(SwitchScreenMsg::TunnelStateRunning) - } - } - .unwrap(); - } - } - } - tokio::time::sleep(RECONNECT_POLL_TIME).await; - } - }); - rt.block_on(task).unwrap(); -}