wlancfg_lib/legacy/
deprecated_client.rs1use crate::legacy::IfaceRef;
5use fidl_fuchsia_wlan_product_deprecatedclient as deprecated;
6use fidl_fuchsia_wlan_sme as fidl_sme;
7use futures::prelude::*;
8use log::{debug, error};
9
10const MAX_CONCURRENT_WLAN_REQUESTS: usize = 1000;
11
12pub async fn serve_deprecated_client(
14 requests: deprecated::DeprecatedClientRequestStream,
15 iface: IfaceRef,
16) -> Result<(), fidl::Error> {
17 requests
18 .try_for_each_concurrent(MAX_CONCURRENT_WLAN_REQUESTS, |req| {
19 handle_request(iface.clone(), req)
20 })
21 .await
22}
23
24async fn handle_request(
26 iface: IfaceRef,
27 req: deprecated::DeprecatedClientRequest,
28) -> Result<(), fidl::Error> {
29 match req {
30 deprecated::DeprecatedClientRequest::Status { responder } => {
31 debug!("Deprecated WLAN client API used for status request");
32 let r = status(&iface).await;
33 responder.send(&r)
34 }
35 }
36}
37
38fn no_client_status() -> deprecated::WlanStatus {
40 deprecated::WlanStatus { state: deprecated::State::NoClient, current_ap: None }
41}
42
43async fn status(iface: &IfaceRef) -> deprecated::WlanStatus {
46 let iface = match iface.get() {
47 Ok(iface) => iface,
48 Err(_) => return no_client_status(),
49 };
50
51 let status = match iface.sme.status().await {
52 Ok(status) => status,
53 Err(e) => {
54 error!("Failed to query status: {}", e);
56 return no_client_status();
57 }
58 };
59
60 deprecated::WlanStatus {
61 state: convert_state(&status),
62 current_ap: extract_current_ap(&status),
63 }
64}
65
66fn convert_state(status: &fidl_sme::ClientStatusResponse) -> deprecated::State {
68 match status {
69 fidl_sme::ClientStatusResponse::Connected(_) => deprecated::State::Associated,
70 fidl_sme::ClientStatusResponse::Connecting(_) => deprecated::State::Associating,
71 fidl_sme::ClientStatusResponse::Roaming(_) => deprecated::State::Associating,
72 fidl_sme::ClientStatusResponse::Idle(_) => deprecated::State::Disassociated,
73 }
74}
75
76fn extract_current_ap(status: &fidl_sme::ClientStatusResponse) -> Option<Box<deprecated::Ap>> {
78 match status {
79 fidl_sme::ClientStatusResponse::Connected(serving_ap_info) => {
80 let ssid = String::from_utf8_lossy(&serving_ap_info.ssid).to_string();
81 let rssi_dbm = serving_ap_info.rssi_dbm;
82 Some(Box::new(deprecated::Ap { ssid, rssi_dbm }))
83 }
84 fidl_sme::ClientStatusResponse::Connecting(_)
85 | fidl_sme::ClientStatusResponse::Roaming(_)
86 | fidl_sme::ClientStatusResponse::Idle(_) => None,
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use crate::legacy::Iface;
94 use assert_matches::assert_matches;
95 use fidl::endpoints::create_proxy;
96 use fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211;
97 use fuchsia_async as fasync;
98 use futures::task::Poll;
99 use std::pin::pin;
100
101 struct TestValues {
102 iface: IfaceRef,
103 sme_stream: fidl_sme::ClientSmeRequestStream,
104 }
105
106 fn test_setup() -> TestValues {
107 let (sme, server) = create_proxy::<fidl_sme::ClientSmeMarker>();
108
109 let iface = Iface { sme, iface_id: 0 };
110 let iface_ref = IfaceRef::new();
111 iface_ref.set_if_empty(iface);
112
113 TestValues { iface: iface_ref, sme_stream: server.into_stream() }
114 }
115
116 #[fuchsia::test]
117 fn test_no_client() {
118 let mut exec = fasync::TestExecutor::new();
119 let iface = IfaceRef::new();
120 let status_fut = status(&iface);
121 let mut status_fut = pin!(status_fut);
122
123 assert_matches!(
125 exec.run_until_stalled(&mut status_fut),
126 Poll::Ready(deprecated::WlanStatus {
127 state: deprecated::State::NoClient,
128 current_ap: None,
129 })
130 );
131 }
132
133 #[fuchsia::test]
134 fn test_broken_sme() {
135 let mut exec = fasync::TestExecutor::new();
136 let test_values = test_setup();
137
138 drop(test_values.sme_stream);
140
141 let status_fut = status(&test_values.iface);
142 let mut status_fut = pin!(status_fut);
143
144 assert_matches!(
146 exec.run_until_stalled(&mut status_fut),
147 Poll::Ready(deprecated::WlanStatus {
148 state: deprecated::State::NoClient,
149 current_ap: None,
150 })
151 );
152 }
153
154 #[fuchsia::test]
155 fn test_disconnected_client() {
156 let mut exec = fasync::TestExecutor::new();
157 let mut test_values = test_setup();
158 let status_fut = status(&test_values.iface);
159 let mut status_fut = pin!(status_fut);
160
161 assert_matches!(exec.run_until_stalled(&mut status_fut), Poll::Pending);
164 assert_matches!(
165 exec.run_until_stalled(&mut test_values.sme_stream.next()),
166 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Status { responder }))) => {
167 responder.send(&fidl_sme::ClientStatusResponse::Idle(fidl_sme::Empty{})).expect("could not send sme response")
168 }
169 );
170
171 assert_matches!(
173 exec.run_until_stalled(&mut status_fut),
174 Poll::Ready(deprecated::WlanStatus {
175 state: deprecated::State::Disassociated,
176 current_ap: None,
177 })
178 );
179 }
180
181 #[fuchsia::test]
182 fn test_connecting_client() {
183 let mut exec = fasync::TestExecutor::new();
184 let mut test_values = test_setup();
185 let status_fut = status(&test_values.iface);
186 let mut status_fut = pin!(status_fut);
187
188 assert_matches!(exec.run_until_stalled(&mut status_fut), Poll::Pending);
191 assert_matches!(
192 exec.run_until_stalled(&mut test_values.sme_stream.next()),
193 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Status { responder }))) => {
194 responder.send(&fidl_sme::ClientStatusResponse::Connecting("test_ssid".as_bytes().to_vec()))
195 .expect("could not send sme response")
196 }
197 );
198
199 assert_matches!(
201 exec.run_until_stalled(&mut status_fut),
202 Poll::Ready(deprecated::WlanStatus {
203 state: deprecated::State::Associating,
204 current_ap: None,
205 })
206 );
207 }
208
209 #[fuchsia::test]
210 fn test_connected_client() {
211 let mut exec = fasync::TestExecutor::new();
212 let mut test_values = test_setup();
213 let ssid = "test_ssid";
214 let rssi_dbm = -70;
215 let status_fut = status(&test_values.iface);
216 let mut status_fut = pin!(status_fut);
217
218 assert_matches!(exec.run_until_stalled(&mut status_fut), Poll::Pending);
221 assert_matches!(
222 exec.run_until_stalled(&mut test_values.sme_stream.next()),
223 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Status { responder }))) => {
224 responder.send(&fidl_sme::ClientStatusResponse::Connected(
225 fidl_sme::ServingApInfo{
226 bssid: [0, 0, 0, 0, 0, 0],
227 ssid: ssid.as_bytes().to_vec(),
228 rssi_dbm,
229 snr_db: 0,
230 primary: fidl_ieee80211::ChannelNumber {
231 band: fidl_ieee80211::WlanBand::TwoGhz,
232 number: 1,
233 },
234 protection: fidl_sme::Protection::Unknown,
235 bandwidth: fidl_ieee80211::ChannelBandwidth::Cbw20,
236 vht_secondary_80_channel: fidl_ieee80211::ChannelNumber {
237 band: fidl_ieee80211::WlanBand::TwoGhz,
238 number: 0,
239 },
240 })).expect("could not send sme response")
241 }
242 );
243
244 let expected_current_ap =
246 Some(Box::new(deprecated::Ap { ssid: ssid.to_string(), rssi_dbm }));
247 assert_matches!(
248 exec.run_until_stalled(&mut status_fut),
249 Poll::Ready(deprecated::WlanStatus {
250 state: deprecated::State::Associated,
251 current_ap,
252 }) => {
253 assert_eq!(current_ap, expected_current_ap);
254 }
255 );
256 }
257}