sl4f_lib/wlan_policy/
facade.rs1use crate::common_utils::common::macros::with_line;
6use crate::wlan_policy::types::{ClientStateSummary, NetworkConfig};
7use anyhow::{format_err, Error};
8use fidl::endpoints::Proxy as _;
9use fidl_fuchsia_wlan_policy as fidl_policy;
10use fuchsia_async::{self as fasync, DurationExt as _};
11use fuchsia_component::client::connect_to_protocol;
12use fuchsia_sync::RwLock;
13use futures::TryStreamExt;
14use log::*;
15use std::cell::Cell;
16use std::collections::HashSet;
17use std::fmt::{self, Debug};
18
19pub struct WlanPolicyFacade {
20 controller: RwLock<InnerController>,
21 update_listener: Cell<Option<fidl_policy::ClientStateUpdatesRequestStream>>,
22}
23
24#[derive(Debug)]
25pub struct InnerController {
26 inner: Option<fidl_policy::ClientControllerProxy>,
27}
28
29impl Debug for WlanPolicyFacade {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 let listener = self.update_listener.take();
32 let update_listener =
33 if listener.is_some() { "Some(ClientStateUpdatesRequestStream)" } else { "None" }
34 .to_string();
35 self.update_listener.set(listener);
36
37 f.debug_struct("InnerWlanPolicyFacade")
38 .field("controller", &self.controller)
39 .field("update_listener", &update_listener)
40 .finish()
41 }
42}
43
44impl WlanPolicyFacade {
45 pub fn new() -> Result<WlanPolicyFacade, Error> {
46 Ok(Self {
47 controller: RwLock::new(InnerController { inner: None }),
48 update_listener: Cell::new(None),
49 })
50 }
51
52 pub async fn create_client_controller(&self) -> Result<(), Error> {
59 let tag = "WlanPolicyFacade::create_client_controller";
60 let mut controller_guard = self.controller.write();
61 controller_guard.inner = None;
63
64 let (controller, update_stream) = Self::init_client_controller().await.map_err(|e| {
65 info!(tag = &with_line!(tag); "Error getting client controller: {}", e);
66 format_err!("Error getting client controller: {}", e)
67 })?;
68 controller_guard.inner = Some(controller);
69 self.update_listener.set(Some(update_stream));
70
71 Ok(())
72 }
73
74 async fn init_client_controller() -> Result<
77 (fidl_policy::ClientControllerProxy, fidl_policy::ClientStateUpdatesRequestStream),
78 Error,
79 > {
80 let provider = connect_to_protocol::<fidl_policy::ClientProviderMarker>()?;
81 let (controller, req) =
82 fidl::endpoints::create_proxy::<fidl_policy::ClientControllerMarker>();
83 let (update_sink, update_stream) =
84 fidl::endpoints::create_request_stream::<fidl_policy::ClientStateUpdatesMarker>();
85 provider.get_controller(req, update_sink)?;
86
87 let sleep_duration = zx::MonotonicDuration::from_millis(10);
91 fasync::Timer::new(sleep_duration.after_now()).await;
92 if controller.is_closed() {
93 return Err(format_err!(
94 "Policy layer closed channel, client controller is likely already in use."
95 ));
96 }
97
98 Ok((controller, update_stream))
99 }
100
101 pub fn drop_client_controller(&self) {
103 let mut controller_guard = self.controller.write();
104 controller_guard.inner = None;
105 }
106
107 fn init_listener() -> Result<fidl_policy::ClientStateUpdatesRequestStream, Error> {
109 let listener = connect_to_protocol::<fidl_policy::ClientListenerMarker>()?;
110 let (client_end, server_end) =
111 fidl::endpoints::create_endpoints::<fidl_policy::ClientStateUpdatesMarker>();
112 listener.get_listener(client_end)?;
113 Ok(server_end.into_stream())
114 }
115
116 pub fn set_new_listener(&self) -> Result<(), Error> {
121 self.update_listener.set(Some(Self::init_listener()?));
122 Ok(())
123 }
124
125 pub async fn scan_for_networks(&self) -> Result<Vec<String>, Error> {
127 let controller_guard = self.controller.read();
128 let controller = controller_guard
129 .inner
130 .as_ref()
131 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
132
133 let (iter, server) =
135 fidl::endpoints::create_proxy::<fidl_policy::ScanResultIteratorMarker>();
136 controller.scan_for_networks(server)?;
138
139 let mut scan_results = HashSet::new();
142 loop {
143 let results = iter.get_next().await?.map_err(|e| format_err!("{:?}", e))?;
144 if results.is_empty() {
145 break;
146 }
147
148 let results = Self::stringify_scan_results(results);
150 scan_results.extend(results);
151 }
152 Ok(scan_results.into_iter().collect())
153 }
154
155 pub async fn connect(
165 &self,
166 target_ssid: Vec<u8>,
167 type_: fidl_policy::SecurityType,
168 ) -> Result<String, Error> {
169 let controller_guard = self.controller.read();
170 let controller = controller_guard
171 .inner
172 .as_ref()
173 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
174
175 let network_id = fidl_policy::NetworkIdentifier { ssid: target_ssid, type_ };
176 let response = controller
177 .connect(&network_id)
178 .await
179 .map_err(|e| format_err!("Connect: failed to connect: {}", e))?;
180 Ok(Self::request_status_as_string(response))
181 }
182
183 fn request_status_as_string(response: fidl_policy::RequestStatus) -> String {
184 match response {
185 fidl_policy::RequestStatus::Acknowledged => "Acknowledged",
186 fidl_policy::RequestStatus::RejectedNotSupported => "RejectedNotSupported",
187 fidl_policy::RequestStatus::RejectedIncompatibleMode => "RejectedIncompatibleMode",
188 fidl_policy::RequestStatus::RejectedAlreadyInUse => "RejectedAlreadyInUse",
189 fidl_policy::RequestStatus::RejectedDuplicateRequest => "RejectedDuplicateRequest",
190 }
191 .to_string()
192 }
193
194 pub async fn remove_network(
202 &self,
203 target_ssid: Vec<u8>,
204 type_: fidl_policy::SecurityType,
205 credential: fidl_policy::Credential,
206 ) -> Result<(), Error> {
207 let controller_guard = self.controller.read();
208 let controller = controller_guard
209 .inner
210 .as_ref()
211 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
212 info!(
213 tag = &with_line!("WlanPolicyFacade::remove_network");
214 "Removing network: ({}{:?})",
215 String::from_utf8_lossy(&target_ssid),
216 type_
217 );
218
219 let config = fidl_policy::NetworkConfig {
220 id: Some(fidl_policy::NetworkIdentifier { ssid: target_ssid, type_ }),
221 credential: Some(credential),
222 ..Default::default()
223 };
224 controller
225 .remove_network(&config)
226 .await
227 .map_err(|err| format_err!("{:?}", err))? .map_err(|err| format_err!("{:?}", err)) }
230
231 pub async fn remove_all_networks(&self) -> Result<(), Error> {
233 let controller_guard = self.controller.read();
234 let controller = controller_guard
235 .inner
236 .as_ref()
237 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
238
239 let saved_networks = self.get_saved_networks().await?;
241 for network_config in saved_networks {
242 controller
243 .remove_network(&network_config)
244 .await
245 .map_err(|err| format_err!("{:?}", err))? .map_err(|err| format_err!("{:?}", err))?; }
248 Ok(())
249 }
250
251 pub async fn start_client_connections(&self) -> Result<(), Error> {
253 let controller_guard = self.controller.read();
254 let controller = controller_guard
255 .inner
256 .as_ref()
257 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
258
259 let req_status = controller.start_client_connections().await?;
260 if fidl_policy::RequestStatus::Acknowledged == req_status {
261 Ok(())
262 } else {
263 bail!("{:?}", req_status);
264 }
265 }
266
267 pub async fn get_update(&self) -> Result<ClientStateSummary, Error> {
277 let listener = self.update_listener.take();
279 let mut update_listener = if listener.is_none() {
280 Self::init_listener()
281 } else {
282 listener.ok_or_else(|| format_err!("failed to set update listener of facade"))
283 }?;
284
285 if let Some(update_request) = update_listener.try_next().await? {
286 let update = update_request.into_on_client_state_update();
287 let (update, responder) = match update {
288 Some((update, responder)) => (update, responder),
289 None => return Err(format_err!("Client provider produced invalid update.")),
290 };
291 responder.send().map_err(|e| format_err!("failed to ack update: {}", e))?;
293 self.update_listener.set(Some(update_listener));
295 Ok(update.into())
296 } else {
297 self.update_listener.set(Some(update_listener));
298 Err(format_err!("update listener's next update is None"))
299 }
300 }
301
302 pub async fn stop_client_connections(&self) -> Result<(), Error> {
304 let controller_guard = self.controller.read();
305 let controller = controller_guard
306 .inner
307 .as_ref()
308 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
309
310 let req_status = controller.stop_client_connections().await?;
311 if fidl_policy::RequestStatus::Acknowledged == req_status {
312 Ok(())
313 } else {
314 bail!("{:?}", req_status);
315 }
316 }
317
318 pub async fn save_network(
326 &self,
327 target_ssid: Vec<u8>,
328 type_: fidl_policy::SecurityType,
329 credential: fidl_policy::Credential,
330 ) -> Result<(), Error> {
331 let controller_guard = self.controller.read();
332 let controller = controller_guard
333 .inner
334 .as_ref()
335 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
336
337 let network_id = fidl_policy::NetworkIdentifier { ssid: target_ssid.clone(), type_: type_ };
338
339 controller
340 .save_network(&fidl_policy::NetworkConfig {
341 id: Some(network_id),
342 credential: Some(credential),
343 ..Default::default()
344 })
345 .await?
346 .map_err(|e| format_err!("{:?}", e))
347 }
348
349 pub async fn get_saved_networks_json(&self) -> Result<Vec<NetworkConfig>, Error> {
350 let saved_networks = self.get_saved_networks().await?;
351 Ok(saved_networks.into_iter().map(|cfg| cfg.into()).collect::<Vec<_>>())
353 }
354
355 async fn get_saved_networks(&self) -> Result<Vec<fidl_policy::NetworkConfig>, Error> {
358 let controller_guard = self.controller.read();
359 let controller = controller_guard
360 .inner
361 .as_ref()
362 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
363
364 let (iter, server) =
366 fidl::endpoints::create_proxy::<fidl_policy::NetworkConfigIteratorMarker>();
367 controller
368 .get_saved_networks(server)
369 .map_err(|e| format_err!("Get saved networks: fidl error {:?}", e))?;
370
371 let mut networks = vec![];
373 loop {
374 let cfgs = iter.get_next().await?;
375 if cfgs.is_empty() {
376 break;
377 }
378 networks.extend(cfgs);
379 }
380 Ok(networks)
381 }
382
383 fn stringify_scan_results(results: Vec<fidl_policy::ScanResult>) -> Vec<String> {
384 results
385 .into_iter()
386 .filter_map(|result| result.id)
387 .map(|id| String::from_utf8_lossy(&id.ssid).into_owned())
388 .collect()
389 }
390}