@@ -8,55 +8,58 @@ use crate::{
88 known_network:: KnownNetwork ,
99 station:: { Station , StationDiagnostics } ,
1010} ;
11- use std:: collections:: HashMap ;
11+ use std:: { collections:: HashMap , future} ;
12+ use futures_lite:: { StreamExt , FutureExt } ;
1213use uuid:: Uuid ;
13- use zbus:: { Connection , Proxy } ;
14+ use zbus:: { Connection , Proxy , fdo :: { InterfacesAddedArgs , InterfacesAddedStream , InterfacesRemovedStream , ObjectManagerProxy } , names :: OwnedInterfaceName } ;
1415use zvariant:: { OwnedObjectPath , OwnedValue } ;
1516
17+ type OwnedPropertiesMap = HashMap < String , OwnedValue > ;
18+ type OwnedInterfaceMap = HashMap < OwnedInterfaceName , OwnedPropertiesMap > ;
19+
1620#[ derive( Debug ) ]
1721pub struct Session {
1822 connection : Connection ,
19- pub ( crate ) objects : HashMap < OwnedObjectPath , HashMap < String , HashMap < String , OwnedValue > > > ,
23+ _object_manager : ObjectManagerProxy < ' static > ,
24+ cache : async_lock:: Mutex < ObjectCache >
2025}
2126
2227impl Session {
2328 pub async fn new ( ) -> zbus:: Result < Self > {
2429 let connection = Connection :: system ( ) . await ?;
2530
26- let proxy = Proxy :: new (
27- & connection,
31+ let proxy = Proxy :: new_owned (
32+ connection. clone ( ) ,
2833 "net.connman.iwd" ,
2934 "/" ,
3035 "org.freedesktop.DBus.ObjectManager" ,
3136 )
3237 . await ?;
38+ let object_manager = ObjectManagerProxy :: from ( proxy) ;
3339
34- let objects: HashMap < OwnedObjectPath , HashMap < String , HashMap < String , OwnedValue > > > =
35- proxy. call ( "GetManagedObjects" , & ( ) ) . await ?;
40+ let objects: HashMap < OwnedObjectPath , OwnedInterfaceMap > =
41+ object_manager. get_managed_objects ( ) . await ?;
42+ let interfaces_added = object_manager. receive_interfaces_added ( ) . await ?;
43+ let interfaces_removed = object_manager. receive_interfaces_removed ( ) . await ?;
3644
3745 Ok ( Self {
3846 connection,
39- objects,
40- } )
41- }
42-
43- fn object_type (
44- & self ,
45- interface_type : & ' static str ,
46- ) -> impl IntoIterator < Item = OwnedObjectPath > {
47- self . objects . iter ( ) . flat_map ( move |( path, interfaces) | {
48- let path = path. clone ( ) ;
49- interfaces
50- . iter ( )
51- . filter ( move |( interface, _) | interface. as_str ( ) == interface_type)
52- . map ( move |_| path. clone ( ) )
47+ _object_manager : object_manager,
48+ cache : async_lock:: Mutex :: new ( ObjectCache {
49+ interfaces_added,
50+ interfaces_removed,
51+ objects,
52+ } ) ,
5353 } )
5454 }
5555
5656 async fn collect_interface < Output : iwd_interface:: IwdInterface > (
5757 & self ,
5858 ) -> zbus:: Result < Vec < Output > > {
59- let paths: Vec < _ > = self . object_type ( Output :: INTERFACE ) . into_iter ( ) . collect ( ) ;
59+ let mut cache = self . cache . lock ( ) . await ;
60+ cache. update_objects_cache ( ) . await ?;
61+
62+ let paths: Vec < _ > = cache. object_type ( Output :: INTERFACE ) . into_iter ( ) . collect ( ) ;
6063 let mut results = Vec :: with_capacity ( paths. len ( ) ) ;
6164 for path in paths {
6265 results. push ( Output :: new ( self . connection . clone ( ) , path) . await ?) ;
@@ -106,3 +109,52 @@ impl Session {
106109 self . collect_interface ( ) . await
107110 }
108111}
112+
113+ #[ derive( Debug ) ]
114+ struct ObjectCache {
115+ interfaces_added : InterfacesAddedStream ,
116+ interfaces_removed : InterfacesRemovedStream ,
117+ objects : HashMap < OwnedObjectPath , OwnedInterfaceMap > ,
118+ }
119+
120+ impl ObjectCache {
121+ fn object_type (
122+ & self ,
123+ interface_type : & ' static str ,
124+ ) -> impl IntoIterator < Item = OwnedObjectPath > {
125+ self . objects . iter ( ) . flat_map ( move |( path, interfaces) | {
126+ let path = path. clone ( ) ;
127+ interfaces
128+ . iter ( )
129+ . filter ( move |( interface, _) | interface. as_str ( ) == interface_type)
130+ . map ( move |_| path. clone ( ) )
131+ } )
132+ }
133+
134+ async fn update_objects_cache ( & mut self ) -> zbus:: Result < ( ) > {
135+ while let Some ( removal) = self . interfaces_removed . next ( ) . or ( future:: ready ( None ) ) . await {
136+ let args = removal. args ( ) ?;
137+ self . objects . remove ( args. object_path ( ) ) ;
138+ }
139+
140+ while let Some ( added) = self . interfaces_added . next ( ) . or ( future:: ready ( None ) ) . await {
141+ let args = added. args ( ) ?;
142+ let InterfacesAddedArgs { object_path, interfaces_and_properties, .. } = args;
143+ let object_path: OwnedObjectPath = object_path. into_owned ( ) . into ( ) ;
144+ let interfaces_and_properties: OwnedInterfaceMap = interfaces_and_properties. into_iter ( ) . map ( |( iface, props) | {
145+ let iface = iface. into_owned ( ) . into ( ) ;
146+ let props: OwnedPropertiesMap = props. into_iter ( ) . filter_map ( |( key, val) | {
147+ let Ok ( val) = val. try_into_owned ( ) else {
148+ return None
149+ } ;
150+ Some ( ( key. to_string ( ) , val) )
151+ } ) . collect ( ) ;
152+ ( iface, props)
153+ } ) . collect ( ) ;
154+ self . objects . insert ( object_path, interfaces_and_properties) ;
155+ }
156+
157+
158+ Ok ( ( ) )
159+ }
160+ }
0 commit comments