diff --git a/src/clients/networkmanager/mod.rs b/src/clients/networkmanager/mod.rs index 27fef2e..da545e5 100644 --- a/src/clients/networkmanager/mod.rs +++ b/src/clients/networkmanager/mod.rs @@ -35,109 +35,6 @@ struct ClientInner<'l> { dbus_connection: Connection, } -macro_rules! initialise_path_map { - ( - $client:expr, - $path_map:ident, - $proxy_type:ident - $(, |$new_path:ident| $property_watcher:expr)* - ) => { - let new_paths = $client.root_object.$path_map()?; - let mut path_map = HashMap::new(); - for new_path in new_paths { - let new_proxy = $proxy_type::builder(&$client.dbus_connection) - .path(new_path.clone())? - .build()?; - path_map.insert(new_path.clone(), new_proxy); - $({ - let $new_path = &new_path; - $property_watcher; - })* - } - *write_lock!($client.$path_map) = path_map; - }; -} - -macro_rules! spawn_path_list_watcher { - ( - $client:expr, - $property:ident, - $property_changes:ident, - $proxy_type:ident - $(, |$inner_client:ident, $new_path:ident| $property_watcher:expr)* - ) => { - let client = $client.clone(); - spawn_blocking_result!({ - let changes = client.root_object.$property_changes(); - for _ in changes { - let mut new_path_map = HashMap::new(); - { - let new_paths = client.root_object.$property()?; - let path_map = read_lock!(client.$property); - for new_path in new_paths { - if path_map.contains_key(&new_path) { - let proxy = path_map - .get(&new_path) - .expect("Should contain the key, guarded by runtime check"); - new_path_map.insert(new_path, proxy.to_owned()); - } else { - let new_proxy = $proxy_type::builder(&client.dbus_connection) - .path(new_path.clone())? - .build()?; - new_path_map.insert(new_path.clone(), new_proxy); - $({ - let $inner_client = &client; - let $new_path = &new_path; - $property_watcher; - })* - } - } - } - *write_lock!(client.$property) = new_path_map; - client.state.set(State { - // TODO: Investigate if there's a sane way to do only the relevant updates - wired: determine_wired_state(&read_lock!(client.devices))?, - wifi: determine_wifi_state(&read_lock!(client.devices))?, - cellular: determine_cellular_state(&read_lock!(client.devices))?, - vpn: determine_vpn_state(&read_lock!(client.active_connections))?, - }); - } - Ok(()) - }); - } -} - -macro_rules! spawn_property_watcher { - ( - $client:expr, - $path:expr, - $property_changes:ident, - $containing_list:ident - ) => { - let client = $client.clone(); - let path = $path.clone(); - spawn_blocking_result!({ - let changes = read_lock!(client.$containing_list) - .get(&path) - .expect("Should contain the key upon watcher start") - .$property_changes(); - for _ in changes { - if !read_lock!(client.$containing_list).contains_key(&path) { - break; - } - client.state.set(State { - // TODO: Investigate if there's a sane way to do only the relevant updates - wired: determine_wired_state(&read_lock!(client.devices))?, - wifi: determine_wifi_state(&read_lock!(client.devices))?, - cellular: determine_cellular_state(&read_lock!(client.devices))?, - vpn: determine_vpn_state(&read_lock!(client.active_connections))?, - }); - } - Ok(()) - }); - }; -} - impl Client { fn new() -> Result { let state = Mutable::new(State { @@ -163,13 +60,121 @@ impl Client { } fn run(&self) -> Result<()> { + macro_rules! initialise_path_map { + ( + $client:expr, + $path_map:ident, + $proxy_type:ident + $(, |$new_path:ident| $property_watcher:expr)* + ) => { + let new_paths = $client.root_object.$path_map()?; + let mut path_map = HashMap::new(); + for new_path in new_paths { + let new_proxy = $proxy_type::builder(&$client.dbus_connection) + .path(new_path.clone())? + .build()?; + path_map.insert(new_path.clone(), new_proxy); + $({ + let $new_path = &new_path; + $property_watcher; + })* + } + *write_lock!($client.$path_map) = path_map; + }; + } + + macro_rules! spawn_path_list_watcher { + ( + $client:expr, + $property:ident, + $property_changes:ident, + $proxy_type:ident + $(, |$inner_client:ident, $new_path:ident| $property_watcher:expr)* + ) => { + let client = $client.clone(); + spawn_blocking_result!({ + let changes = client.root_object.$property_changes(); + for _ in changes { + let mut new_path_map = HashMap::new(); + { + let new_paths = client.root_object.$property()?; + let path_map = read_lock!(client.$property); + for new_path in new_paths { + if path_map.contains_key(&new_path) { + let proxy = path_map + .get(&new_path) + .expect("Should contain the key, guarded by runtime check"); + new_path_map.insert(new_path, proxy.to_owned()); + } else { + let new_proxy = $proxy_type::builder(&client.dbus_connection) + .path(new_path.clone())? + .build()?; + new_path_map.insert(new_path.clone(), new_proxy); + $({ + let $inner_client = &client; + let $new_path = &new_path; + $property_watcher; + })* + } + } + } + *write_lock!(client.$property) = new_path_map; + client.state.set(State { + // TODO: Investigate if there's a sane way to do only the relevant updates + wired: determine_wired_state(&read_lock!(client.devices))?, + wifi: determine_wifi_state(&read_lock!(client.devices))?, + cellular: determine_cellular_state(&read_lock!(client.devices))?, + vpn: determine_vpn_state(&read_lock!(client.active_connections))?, + }); + } + Ok(()) + }); + } + } + + macro_rules! spawn_property_watcher { + ( + $client:expr, + $path:expr, + $property_changes:ident, + $containing_list:ident, + |$inner_client:ident| $state_update:expr + ) => { + let client = $client.clone(); + let path = $path.clone(); + spawn_blocking_result!({ + let changes = read_lock!(client.$containing_list) + .get(&path) + .expect("Should contain the key upon watcher start") + .$property_changes(); + for _ in changes { + if !read_lock!(client.$containing_list).contains_key(&path) { + break; + } + { + let $inner_client = &client; + $state_update; + } + } + Ok(()) + }); + }; + } + initialise_path_map!( self.0, active_connections, ActiveConnectionDbusProxyBlocking ); initialise_path_map!(self.0, devices, DeviceDbusProxyBlocking, |path| { - spawn_property_watcher!(self.0, path, receive_state_changed, devices); + spawn_property_watcher!(self.0, path, receive_state_changed, devices, |client| { + client.state.set(State { + wired: determine_wired_state(&read_lock!(client.devices))?, + wifi: determine_wifi_state(&read_lock!(client.devices))?, + cellular: determine_cellular_state(&read_lock!(client.devices))?, + vpn: client.state.get_cloned().vpn, + }); + }); }); self.0.state.set(State { wired: determine_wired_state(&read_lock!(self.0.devices))?, @@ -190,7 +195,14 @@ impl Client { receive_devices_changed, DeviceDbusProxyBlocking, |client, path| { - spawn_property_watcher!(client, path, receive_state_changed, devices); + spawn_property_watcher!(client, path, receive_state_changed, devices, |client| { + client.state.set(State { + wired: determine_wired_state(&read_lock!(client.devices))?, + wifi: determine_wifi_state(&read_lock!(client.devices))?, + cellular: determine_cellular_state(&read_lock!(client.devices))?, + vpn: client.state.get_cloned().vpn, + }); + }); } );