sl4f_lib/wlan_policy/
facade.rs1use crate::common_utils::common::macros::with_line;
6use crate::wlan_policy::types::{ClientStateSummary, NetworkConfig};
7use anyhow::{Error, format_err};
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 ) -> Result<(), Error> {
206 let controller_guard = self.controller.read();
207 let controller = controller_guard
208 .inner
209 .as_ref()
210 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
211 info!(
212 tag = &with_line!("WlanPolicyFacade::remove_network");
213 "Removing network: ({}{:?})",
214 String::from_utf8_lossy(&target_ssid),
215 type_
216 );
217
218 let id = fidl_policy::NetworkIdentifier { ssid: target_ssid, type_ };
219 controller
220 .forget_network(&id)
221 .await
222 .map_err(|err| format_err!("{:?}", err))? .map_err(|err| format_err!("{:?}", err)) }
225
226 pub async fn remove_all_networks(&self) -> Result<(), Error> {
228 let controller_guard = self.controller.read();
229 let controller = controller_guard
230 .inner
231 .as_ref()
232 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
233
234 let saved_networks = self.get_saved_networks().await?;
236 for network_config in saved_networks {
237 let id = network_config.id.as_ref().ok_or_else(|| format_err!("missing network ID"))?;
238 controller
239 .forget_network(id)
240 .await
241 .map_err(|err| format_err!("{:?}", err))? .map_err(|err| format_err!("{:?}", err))?; }
244 Ok(())
245 }
246
247 pub async fn start_client_connections(&self) -> Result<(), Error> {
249 let controller_guard = self.controller.read();
250 let controller = controller_guard
251 .inner
252 .as_ref()
253 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
254
255 let req_status = controller.start_client_connections().await?;
256 if fidl_policy::RequestStatus::Acknowledged == req_status {
257 Ok(())
258 } else {
259 bail!("{:?}", req_status);
260 }
261 }
262
263 pub async fn get_update(&self) -> Result<ClientStateSummary, Error> {
273 let listener = self.update_listener.take();
275 let mut update_listener = if listener.is_none() {
276 Self::init_listener()
277 } else {
278 listener.ok_or_else(|| format_err!("failed to set update listener of facade"))
279 }?;
280
281 if let Some(update_request) = update_listener.try_next().await? {
282 let update = update_request.into_on_client_state_update();
283 let (update, responder) = match update {
284 Some((update, responder)) => (update, responder),
285 None => return Err(format_err!("Client provider produced invalid update.")),
286 };
287 responder.send().map_err(|e| format_err!("failed to ack update: {}", e))?;
289 self.update_listener.set(Some(update_listener));
291 Ok(update.into())
292 } else {
293 self.update_listener.set(Some(update_listener));
294 Err(format_err!("update listener's next update is None"))
295 }
296 }
297
298 pub async fn stop_client_connections(&self) -> Result<(), Error> {
300 let controller_guard = self.controller.read();
301 let controller = controller_guard
302 .inner
303 .as_ref()
304 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
305
306 let req_status = controller.stop_client_connections().await?;
307 if fidl_policy::RequestStatus::Acknowledged == req_status {
308 Ok(())
309 } else {
310 bail!("{:?}", req_status);
311 }
312 }
313
314 pub async fn save_network(
322 &self,
323 target_ssid: Vec<u8>,
324 type_: fidl_policy::SecurityType,
325 credential: fidl_policy::Credential,
326 ) -> Result<(), Error> {
327 let controller_guard = self.controller.read();
328 let controller = controller_guard
329 .inner
330 .as_ref()
331 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
332
333 let network_id = fidl_policy::NetworkIdentifier { ssid: target_ssid.clone(), type_: type_ };
334
335 controller
336 .save_network(&fidl_policy::NetworkConfig {
337 id: Some(network_id),
338 credential: Some(credential),
339 ..Default::default()
340 })
341 .await?
342 .map_err(|e| format_err!("{:?}", e))
343 }
344
345 pub async fn get_saved_networks_json(&self) -> Result<Vec<NetworkConfig>, Error> {
346 let saved_networks = self.get_saved_networks().await?;
347 Ok(saved_networks.into_iter().map(|cfg| cfg.into()).collect::<Vec<_>>())
349 }
350
351 async fn get_saved_networks(&self) -> Result<Vec<fidl_policy::NetworkConfig>, Error> {
354 let controller_guard = self.controller.read();
355 let controller = controller_guard
356 .inner
357 .as_ref()
358 .ok_or_else(|| format_err!("client controller has not been initialized"))?;
359
360 let (iter, server) =
362 fidl::endpoints::create_proxy::<fidl_policy::NetworkConfigIteratorMarker>();
363 controller
364 .get_saved_networks(server)
365 .map_err(|e| format_err!("Get saved networks: fidl error {:?}", e))?;
366
367 let mut networks = vec![];
369 loop {
370 let cfgs = iter.get_next().await?;
371 if cfgs.is_empty() {
372 break;
373 }
374 networks.extend(cfgs);
375 }
376 Ok(networks)
377 }
378
379 fn stringify_scan_results(results: Vec<fidl_policy::ScanResult>) -> Vec<String> {
380 results
381 .into_iter()
382 .filter_map(|result| result.id)
383 .map(|id| String::from_utf8_lossy(&id.ssid).into_owned())
384 .collect()
385 }
386}