sl4f_lib/wlan_policy/
ap_facade.rs1use crate::wlan_policy::types::AccessPointState;
6use anyhow::Error;
7use fidl::endpoints::{create_endpoints, create_proxy};
8use fidl_fuchsia_wlan_policy::{
9 AccessPointControllerMarker, AccessPointControllerProxy, AccessPointListenerMarker,
10 AccessPointProviderMarker, AccessPointStateUpdatesMarker, AccessPointStateUpdatesRequestStream,
11 ConnectivityMode, Credential, NetworkConfig, NetworkIdentifier, OperatingBand, OperatingState,
12 RequestStatus, SecurityType,
13};
14use fuchsia_component::client::connect_to_protocol;
15use futures::TryStreamExt;
16use std::cell::Cell;
17use std::fmt::{self, Debug};
18
19pub struct WlanApPolicyFacade {
20 ap_controller: AccessPointControllerProxy,
21 update_listener: Cell<Option<AccessPointStateUpdatesRequestStream>>,
22}
23
24impl Debug for WlanApPolicyFacade {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 let listener = self.update_listener.take();
27 let update_listener =
28 if listener.is_some() { "Some(AccessPointStateUpdatesRequestStream)" } else { "None" }
29 .to_string();
30 self.update_listener.set(listener);
31
32 f.debug_struct("WlanApPolicyFacade")
33 .field("controller", &self.ap_controller)
34 .field("update_listener", &update_listener)
35 .finish()
36 }
37}
38
39impl WlanApPolicyFacade {
40 pub fn new() -> Result<WlanApPolicyFacade, Error> {
41 let policy_provider = connect_to_protocol::<AccessPointProviderMarker>()?;
42 let (ap_controller, server_end) = create_proxy::<AccessPointControllerMarker>();
43
44 let (update_client_end, update_listener) =
45 create_endpoints::<AccessPointStateUpdatesMarker>();
46 let () = policy_provider.get_controller(server_end, update_client_end)?;
47 let update_stream = update_listener.into_stream();
48 Ok(WlanApPolicyFacade { ap_controller, update_listener: Cell::new(Some(update_stream)) })
49 }
50
51 pub async fn start_access_point(
52 &self,
53 target_ssid: Vec<u8>,
54 type_: SecurityType,
55 credential: Credential,
56 mode: ConnectivityMode,
57 band: OperatingBand,
58 ) -> Result<(), Error> {
59 let listener = connect_to_protocol::<AccessPointListenerMarker>()?;
60 let (client_end, server_end) = create_endpoints::<AccessPointStateUpdatesMarker>();
61 listener.get_listener(client_end)?;
62 let mut server_stream = server_end.into_stream();
63
64 match server_stream.try_next().await? {
65 Some(update) => {
66 let update = update.into_on_access_point_state_update();
67 let (_, responder) = match update {
68 Some((update, responder)) => (update, responder),
69 None => return Err(format_err!("AP provider produced invalid update.")),
70 };
71 let _ = responder.send();
72 }
73 None => return Err(format_err!("initial steam already busted")),
74 }
75
76 let network_id = NetworkIdentifier { ssid: target_ssid.clone(), type_: type_ };
77
78 match self
79 .ap_controller
80 .start_access_point(
81 &NetworkConfig {
82 id: Some(network_id),
83 credential: Some(credential),
84 ..Default::default()
85 },
86 mode,
87 band,
88 )
89 .await?
90 {
91 RequestStatus::Acknowledged => {}
92 RequestStatus::RejectedNotSupported => {
93 return Err(format_err!("failed to start AP (not supported)"))
94 }
95 RequestStatus::RejectedIncompatibleMode => {
96 return Err(format_err!("failed to start AP (incompatible mode)"))
97 }
98 RequestStatus::RejectedAlreadyInUse => {
99 return Err(format_err!("failed to start AP (already in use)"))
100 }
101 RequestStatus::RejectedDuplicateRequest => {
102 return Err(format_err!("failed to start AP (duplicate request)"))
103 }
104 }
105
106 while let Some(update_request) = server_stream.try_next().await.unwrap() {
107 let update = update_request.into_on_access_point_state_update();
108 let (updates, responder) = match update {
109 Some((update, responder)) => (update, responder),
110 None => return Err(format_err!("AP provider produced invalid update.")),
111 };
112 let _ = responder.send();
113
114 for update in updates {
115 match update.state {
116 Some(state) => match state {
117 OperatingState::Failed => {
118 return Err(format_err!("Failed to start AP."));
119 }
120 OperatingState::Starting => {
121 continue;
122 }
123 OperatingState::Active => return Ok(()),
124 },
125 None => continue,
126 }
127 }
128 }
129 return Err(format_err!("AP update stream failed unexpectedly"));
130 }
131
132 pub async fn stop_access_point(
133 &self,
134 target_ssid: Vec<u8>,
135 type_: SecurityType,
136 credential: Credential,
137 ) -> Result<(), Error> {
138 let network_id = NetworkIdentifier { ssid: target_ssid.clone(), type_: type_ };
139 match self
140 .ap_controller
141 .stop_access_point(&NetworkConfig {
142 id: Some(network_id),
143 credential: Some(credential),
144 ..Default::default()
145 })
146 .await?
147 {
148 RequestStatus::Acknowledged => Ok(()),
149 RequestStatus::RejectedNotSupported => {
150 Err(format_err!("Failed to stop AP (not supported)"))
151 }
152 RequestStatus::RejectedIncompatibleMode => {
153 Err(format_err!("Failed to stop AP (incompatible mode)"))
154 }
155 RequestStatus::RejectedAlreadyInUse => {
156 Err(format_err!("Failed to stop AP (already in use)"))
157 }
158 RequestStatus::RejectedDuplicateRequest => {
159 Err(format_err!("Failed to stop AP (duplicate request)"))
160 }
161 }
162 }
163
164 pub async fn stop_all_access_points(&self) -> Result<(), Error> {
165 self.ap_controller.stop_all_access_points()?;
166 Ok(())
167 }
168
169 fn init_listener() -> Result<AccessPointStateUpdatesRequestStream, Error> {
171 let listener = connect_to_protocol::<AccessPointListenerMarker>()?;
172 let (client_end, server_end) =
173 fidl::endpoints::create_endpoints::<AccessPointStateUpdatesMarker>();
174 listener.get_listener(client_end)?;
175 Ok(server_end.into_stream())
176 }
177
178 pub fn set_new_listener(&self) -> Result<(), Error> {
181 self.update_listener.set(Some(Self::init_listener()?));
182 Ok(())
183 }
184
185 pub async fn get_update(&self) -> Result<Vec<AccessPointState>, Error> {
195 let listener = self.update_listener.take();
197 let mut update_listener = if listener.is_none() {
198 Self::init_listener()
199 } else {
200 listener.ok_or_else(|| format_err!("failed to set update listener of facade"))
201 }?;
202
203 if let Some(update_request) = update_listener.try_next().await? {
204 let update = update_request.into_on_access_point_state_update();
205 let (update, responder) = match update {
206 Some((update, responder)) => (update, responder),
207 None => return Err(format_err!("Client provider produced invalid update.")).into(),
208 };
209 responder.send().map_err(|e| format_err!("failed to ack update: {}", e))?;
211 self.update_listener.set(Some(update_listener));
213
214 let update = update.into_iter().map(|update| AccessPointState::from(update)).collect();
215 Ok(update)
216 } else {
217 self.update_listener.set(Some(update_listener));
218 Err(format_err!("update listener's next update is None"))
219 }
220 }
221}