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