1pub mod ap;
6pub mod client;
7
8use crate::{MlmeEventStream, MlmeStream, Station};
9use anyhow::format_err;
10use fidl::endpoints::ServerEnd;
11use fuchsia_sync::Mutex;
12use futures::channel::mpsc;
13use futures::future::FutureObj;
14use futures::prelude::*;
15use futures::select;
16use futures::stream::FuturesUnordered;
17use log::{error, info, warn};
18use std::convert::Infallible;
19use std::pin::Pin;
20use std::sync::Arc;
21use wlan_common::timer::{self, ScheduledEvent};
22use {
23 fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_mlme as fidl_mlme,
24 fidl_fuchsia_wlan_sme as fidl_sme, fuchsia_inspect_auto_persist as auto_persist,
25};
26
27pub type ClientSmeServer = mpsc::UnboundedSender<client::Endpoint>;
28pub type ApSmeServer = mpsc::UnboundedSender<ap::Endpoint>;
29
30#[derive(Clone)]
31pub enum SmeServer {
32 Client(ClientSmeServer),
33 Ap(ApSmeServer),
34}
35
36async fn serve_generic_sme(
37 mut generic_sme_request_stream: <fidl_sme::GenericSmeMarker as fidl::endpoints::ProtocolMarker>::RequestStream,
38 mlme_sink: crate::MlmeSink,
39 mut sme_server_sender: SmeServer,
40 mut telemetry_server_sender: Option<
41 mpsc::UnboundedSender<fidl::endpoints::ServerEnd<fidl_sme::TelemetryMarker>>,
42 >,
43) -> Result<(), anyhow::Error> {
44 loop {
45 match generic_sme_request_stream.next().await {
46 Some(Ok(req)) => {
47 let result = match req {
48 fidl_sme::GenericSmeRequest::Query { responder } => {
49 let (info_responder, info_receiver) = crate::responder::Responder::new();
50 mlme_sink.send(crate::MlmeRequest::QueryDeviceInfo(info_responder));
51 let info = info_receiver.await?;
52 responder.send(&fidl_sme::GenericSmeQuery {
53 role: info.role,
54 sta_addr: info.sta_addr,
55 })
56 }
57 fidl_sme::GenericSmeRequest::GetClientSme { sme_server, responder } => {
58 let response =
59 if let SmeServer::Client(server_sender) = &mut sme_server_sender {
60 server_sender
61 .send(sme_server)
62 .await
63 .map_err(|_| zx::Status::PEER_CLOSED.into_raw())
64 } else {
65 Err(zx::Status::NOT_SUPPORTED.into_raw())
66 };
67 responder.send(response)
68 }
69 fidl_sme::GenericSmeRequest::GetApSme { sme_server, responder } => {
70 let response = if let SmeServer::Ap(server_sender) = &mut sme_server_sender
71 {
72 server_sender
73 .send(sme_server)
74 .await
75 .map_err(|_| zx::Status::PEER_CLOSED.into_raw())
76 } else {
77 Err(zx::Status::NOT_SUPPORTED.into_raw())
78 };
79 responder.send(response)
80 }
81 fidl_sme::GenericSmeRequest::GetSmeTelemetry {
82 telemetry_server,
83 responder,
84 } => {
85 let response = if let Some(server) = telemetry_server_sender.as_mut() {
86 server
87 .send(telemetry_server)
88 .await
89 .map_err(|_| zx::Status::PEER_CLOSED.into_raw())
90 } else {
91 warn!("Requested unsupported SME telemetry API");
92 Err(zx::Status::NOT_SUPPORTED.into_raw())
93 };
94 responder.send(response)
95 }
96 };
97 if let Err(e) = result {
98 error!("Failed to respond to SME handle request: {}", e);
99 }
100 }
101 Some(Err(e)) => {
102 return Err(format_err!("Generic SME request stream failed: {}", e));
103 }
104 None => {
105 info!("Generic SME request stream terminated. Shutting down.");
106 return Ok(());
107 }
108 }
109 }
110}
111
112#[allow(
113 clippy::too_many_arguments,
114 clippy::type_complexity,
115 reason = "mass allow for https://fxbug.dev/381896734"
116)]
117pub fn create_sme(
118 cfg: crate::Config,
119 mlme_event_stream: MlmeEventStream,
120 device_info: &fidl_mlme::DeviceInfo,
121 security_support: fidl_common::SecuritySupport,
122 spectrum_management_support: fidl_common::SpectrumManagementSupport,
123 inspector: fuchsia_inspect::Inspector,
124 persistence_req_sender: auto_persist::PersistenceReqSender,
125 generic_sme_request_stream: <fidl_sme::GenericSmeMarker as fidl::endpoints::ProtocolMarker>::RequestStream,
126) -> Result<(MlmeStream, Pin<Box<impl Future<Output = Result<(), anyhow::Error>>>>), anyhow::Error>
127{
128 let device_info = device_info.clone();
129 let inspect_node = inspector.root().create_child("usme");
130 let (server, mlme_req_sink, mlme_req_stream, telemetry_sender, sme_fut) = match device_info.role
131 {
132 fidl_common::WlanMacRole::Client => {
133 let (telemetry_endpoint_sender, telemetry_endpoint_receiver) = mpsc::unbounded();
134 let (sender, receiver) = mpsc::unbounded();
135 let (mlme_req_sink, mlme_req_stream, fut) = client::serve(
136 cfg,
137 device_info,
138 security_support,
139 spectrum_management_support,
140 mlme_event_stream,
141 receiver,
142 telemetry_endpoint_receiver,
143 inspector,
144 inspect_node,
145 persistence_req_sender,
146 );
147 (
148 SmeServer::Client(sender),
149 mlme_req_sink,
150 mlme_req_stream,
151 Some(telemetry_endpoint_sender),
152 FutureObj::new(Box::new(fut)),
153 )
154 }
155 fidl_common::WlanMacRole::Ap => {
156 let (sender, receiver) = mpsc::unbounded();
157 let (mlme_req_sink, mlme_req_stream, fut) =
158 ap::serve(device_info, mlme_event_stream, receiver);
159 (
160 SmeServer::Ap(sender),
161 mlme_req_sink,
162 mlme_req_stream,
163 None,
164 FutureObj::new(Box::new(fut)),
165 )
166 }
167 fidl_common::WlanMacRole::Mesh => {
168 return Err(format_err!("Mesh mode is unsupported"));
169 }
170 fidl_common::WlanMacRoleUnknown!() => {
171 return Err(format_err!("Unknown WlanMacRole type: {:?}", device_info.role));
172 }
173 };
174 let generic_sme_fut =
175 serve_generic_sme(generic_sme_request_stream, mlme_req_sink, server, telemetry_sender);
176 let unified_fut = async move {
177 select! {
178 sme_fut = sme_fut.fuse() => sme_fut,
179 generic_sme_fut = generic_sme_fut.fuse() => generic_sme_fut,
180 }
181 };
182 Ok((mlme_req_stream, Box::pin(unified_fut)))
183}
184
185async fn serve_mlme_sme<STA, TS>(
187 mut event_stream: MlmeEventStream,
188 station: Arc<Mutex<STA>>,
189 time_stream: TS,
190) -> Result<(), anyhow::Error>
191where
192 STA: Station,
193 TS: Stream<Item = ScheduledEvent<<STA as crate::Station>::Event>> + Unpin,
194{
195 let mut timeout_stream = timer::make_async_timed_event_stream(time_stream).fuse();
196
197 loop {
198 select! {
199 mlme_event = event_stream.next() => match mlme_event {
203 Some(mlme_event) => station.lock().on_mlme_event(mlme_event),
204 None => return Ok(()),
205 },
206 timeout = timeout_stream.next() => match timeout {
207 Some(timed_event) => station.lock().on_timeout(timed_event),
208 None => return Err(format_err!("SME timer stream has ended unexpectedly")),
209 },
210 }
211 }
212}
213
214#[allow(clippy::extra_unused_lifetimes, reason = "mass allow for https://fxbug.dev/381896734")]
215async fn serve_fidl<
216 'a,
217 C: Clone,
218 T: fidl::endpoints::ProtocolMarker,
219 Fut: futures::Future<Output = Result<(), fidl::Error>>,
220>(
221 context: C,
222 new_fidl_clients: mpsc::UnboundedReceiver<ServerEnd<T>>,
223 event_handler: impl Fn(C, fidl::endpoints::Request<T>) -> Fut + Copy,
224) -> Result<Infallible, anyhow::Error> {
225 let mut new_fidl_clients = new_fidl_clients.fuse();
226 let mut fidl_clients = FuturesUnordered::new();
227 loop {
228 select! {
229 new_fidl_client = new_fidl_clients.next() => match new_fidl_client {
230 Some(end) => fidl_clients.push(serve_fidl_endpoint(context.clone(), end, event_handler)),
231 None => return Err(format_err!("New FIDL client stream unexpectedly ended")),
232 },
233 () = fidl_clients.select_next_some() => {},
234 }
235 }
236}
237
238#[allow(
239 clippy::extra_unused_lifetimes,
240 clippy::needless_return,
241 reason = "mass allow for https://fxbug.dev/381896734"
242)]
243async fn serve_fidl_endpoint<
244 'a,
245 C: Clone,
246 T: fidl::endpoints::ProtocolMarker,
247 Fut: futures::Future<Output = Result<(), fidl::Error>>,
248>(
249 context: C,
250 endpoint: ServerEnd<T>,
251 event_handler: impl Fn(C, fidl::endpoints::Request<T>) -> Fut + Copy,
252) {
253 let stream = endpoint.into_stream();
254 const MAX_CONCURRENT_REQUESTS: usize = 1000;
255 let handler = &event_handler;
256 let r = stream
257 .try_for_each_concurrent(MAX_CONCURRENT_REQUESTS, move |request| {
258 (*handler)(context.clone(), request)
259 })
260 .await;
261 if let Err(e) = r {
262 error!("Error serving FIDL: {}", e);
263 return;
264 }
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270 use crate::test_utils;
271 use fidl::endpoints::{create_proxy, create_proxy_and_stream};
272 use fuchsia_async as fasync;
273 use fuchsia_inspect::Inspector;
274 use futures::task::Poll;
275 use std::pin::pin;
276 use test_case::test_case;
277 use wlan_common::assert_variant;
278 use wlan_common::test_utils::fake_features::{
279 fake_security_support, fake_spectrum_management_support_empty,
280 };
281
282 #[test]
283 fn create_sme_fails_startup_role_unknown() {
284 let mut _exec = fasync::TestExecutor::new();
285 let inspector = Inspector::default();
286 let (_mlme_event_sender, mlme_event_stream) = mpsc::unbounded();
287 let (persistence_req_sender, _persistence_stream) =
288 test_utils::create_inspect_persistence_channel();
289 let (_generic_sme_proxy, generic_sme_stream) =
290 create_proxy_and_stream::<fidl_sme::GenericSmeMarker>();
291 let device_info = fidl_mlme::DeviceInfo {
292 role: fidl_common::WlanMacRole::unknown(),
293 ..test_utils::fake_device_info([0; 6].into())
294 };
295 let result = create_sme(
296 crate::Config::default(),
297 mlme_event_stream,
298 &device_info,
299 fake_security_support(),
300 fake_spectrum_management_support_empty(),
301 inspector,
302 persistence_req_sender,
303 generic_sme_stream,
304 );
305
306 assert!(result.is_err());
307 }
308
309 #[test]
310 fn sme_shutdown_on_generic_sme_closed() {
311 let mut exec = fasync::TestExecutor::new();
312 let (_mlme_event_sender, mlme_event_stream) = mpsc::unbounded();
313 let inspector = Inspector::default();
314 let (persistence_req_sender, _persistence_stream) =
315 test_utils::create_inspect_persistence_channel();
316 let (generic_sme_proxy, generic_sme_stream) =
317 create_proxy_and_stream::<fidl_sme::GenericSmeMarker>();
318 let (_mlme_req_stream, serve_fut) = create_sme(
319 crate::Config::default(),
320 mlme_event_stream,
321 &test_utils::fake_device_info([0; 6].into()),
322 fake_security_support(),
323 fake_spectrum_management_support_empty(),
324 inspector,
325 persistence_req_sender,
326 generic_sme_stream,
327 )
328 .unwrap();
329 let mut serve_fut = pin!(serve_fut);
330 assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
331
332 drop(generic_sme_proxy);
334
335 assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Ready(Ok(())));
337 }
338
339 struct GenericSmeTestHelper {
340 proxy: fidl_sme::GenericSmeProxy,
341 mlme_req_stream: MlmeStream,
342
343 _inspector: Inspector,
346 _persistence_stream: mpsc::Receiver<String>,
347 _mlme_event_sender: mpsc::UnboundedSender<crate::MlmeEvent>,
348 exec: fasync::TestExecutor,
350 }
351
352 #[allow(clippy::type_complexity, reason = "mass allow for https://fxbug.dev/381896734")]
353 fn start_generic_sme_test(
354 role: fidl_common::WlanMacRole,
355 ) -> Result<
356 (GenericSmeTestHelper, Pin<Box<impl Future<Output = Result<(), anyhow::Error>>>>),
357 anyhow::Error,
358 > {
359 let mut exec = fasync::TestExecutor::new();
360 let inspector = Inspector::default();
361 let (mlme_event_sender, mlme_event_stream) = mpsc::unbounded();
362 let (persistence_req_sender, persistence_stream) =
363 test_utils::create_inspect_persistence_channel();
364 let (generic_sme_proxy, generic_sme_stream) =
365 create_proxy_and_stream::<fidl_sme::GenericSmeMarker>();
366 let device_info =
367 fidl_mlme::DeviceInfo { role, ..test_utils::fake_device_info([0; 6].into()) };
368 let (mlme_req_stream, serve_fut) = create_sme(
369 crate::Config::default(),
370 mlme_event_stream,
371 &device_info,
372 fake_security_support(),
373 fake_spectrum_management_support_empty(),
374 inspector.clone(),
375 persistence_req_sender,
376 generic_sme_stream,
377 )?;
378 let mut serve_fut = Box::pin(serve_fut);
379 assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
380
381 Ok((
382 GenericSmeTestHelper {
383 proxy: generic_sme_proxy,
384 mlme_req_stream,
385 _inspector: inspector,
386 _persistence_stream: persistence_stream,
387 _mlme_event_sender: mlme_event_sender,
388 exec,
389 },
390 serve_fut,
391 ))
392 }
393
394 #[test]
395 fn generic_sme_get_client() {
396 let (mut helper, mut serve_fut) =
397 start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
398
399 let (client_proxy, client_server) = create_proxy();
400 let mut client_sme_fut = helper.proxy.get_client_sme(client_server);
401 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
402 assert_variant!(
403 helper.exec.run_until_stalled(&mut client_sme_fut),
404 Poll::Ready(Ok(Ok(())))
405 );
406
407 let mut status_fut = client_proxy.status();
408 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
409 assert_variant!(
410 helper.exec.run_until_stalled(&mut status_fut),
411 Poll::Ready(Ok(fidl_sme::ClientStatusResponse::Idle(_)))
412 );
413 }
414
415 #[test]
416 fn generic_sme_get_ap_from_client_fails() {
417 let (mut helper, mut serve_fut) =
418 start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
419
420 let (_ap_proxy, ap_server) = create_proxy();
421 let mut client_sme_fut = helper.proxy.get_ap_sme(ap_server);
422 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
423 assert_variant!(
424 helper.exec.run_until_stalled(&mut client_sme_fut),
425 Poll::Ready(Ok(Err(_)))
426 );
427 }
428
429 #[test]
430 fn generic_sme_get_ap() {
431 let (mut helper, mut serve_fut) =
432 start_generic_sme_test(fidl_common::WlanMacRole::Ap).unwrap();
433
434 let (ap_proxy, ap_server) = create_proxy();
435 let mut ap_sme_fut = helper.proxy.get_ap_sme(ap_server);
436 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
437 assert_variant!(helper.exec.run_until_stalled(&mut ap_sme_fut), Poll::Ready(Ok(Ok(()))));
438
439 let mut status_fut = ap_proxy.status();
440 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
441 assert_variant!(
442 helper.exec.run_until_stalled(&mut status_fut),
443 Poll::Ready(Ok(fidl_sme::ApStatusResponse { .. }))
444 );
445 }
446
447 #[test]
448 fn generic_sme_get_client_from_ap_fails() {
449 let (mut helper, mut serve_fut) =
450 start_generic_sme_test(fidl_common::WlanMacRole::Ap).unwrap();
451
452 let (_client_proxy, client_server) = create_proxy();
453 let mut client_sme_fut = helper.proxy.get_client_sme(client_server);
454 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
455 assert_variant!(
456 helper.exec.run_until_stalled(&mut client_sme_fut),
457 Poll::Ready(Ok(Err(_)))
458 );
459 }
460
461 fn get_telemetry_proxy(
462 helper: &mut GenericSmeTestHelper,
463 serve_fut: &mut Pin<Box<impl Future<Output = Result<(), anyhow::Error>>>>,
464 ) -> fidl_sme::TelemetryProxy {
465 let (proxy, server) = create_proxy();
466 let mut telemetry_fut = helper.proxy.get_sme_telemetry(server);
467 assert_variant!(helper.exec.run_until_stalled(serve_fut), Poll::Pending);
468 assert_variant!(helper.exec.run_until_stalled(&mut telemetry_fut), Poll::Ready(Ok(Ok(()))));
469 proxy
470 }
471
472 #[test]
473 fn generic_sme_query_telemetry_support_for_client() {
474 let (mut helper, mut serve_fut) =
475 start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
476 let telemetry_proxy = get_telemetry_proxy(&mut helper, &mut serve_fut);
477
478 let mut support_fut = telemetry_proxy.query_telemetry_support();
480 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
481
482 let support_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
484 let support_responder = assert_variant!(support_req, crate::MlmeRequest::QueryTelemetrySupport(responder) => responder);
485 support_responder.respond(Err(1337));
486
487 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
489 let support_result = assert_variant!(helper.exec.run_until_stalled(&mut support_fut), Poll::Ready(Ok(support_result)) => support_result);
490 assert_eq!(support_result, Err(1337));
491 }
492
493 #[test]
494 fn generic_sme_get_histogram_stats_for_client() {
495 let (mut helper, mut serve_fut) =
496 start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
497 let telemetry_proxy = get_telemetry_proxy(&mut helper, &mut serve_fut);
498
499 let mut histogram_fut = telemetry_proxy.get_histogram_stats();
501 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
502
503 let histogram_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
505 let histogram_responder = assert_variant!(histogram_req, crate::MlmeRequest::GetIfaceHistogramStats(responder) => responder);
506 histogram_responder.respond(fidl_mlme::GetIfaceHistogramStatsResponse::ErrorStatus(1337));
507
508 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
510 let histogram_result = assert_variant!(helper.exec.run_until_stalled(&mut histogram_fut), Poll::Ready(Ok(histogram_result)) => histogram_result);
511 assert_eq!(histogram_result, Err(1337));
512 }
513
514 #[test]
515 fn generic_sme_get_iface_stats_for_client() {
516 let (mut helper, mut serve_fut) =
517 start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
518 let telemetry_proxy = get_telemetry_proxy(&mut helper, &mut serve_fut);
519
520 let mut counter_fut = telemetry_proxy.get_iface_stats();
522 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
523
524 let counter_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
526 let counter_responder =
527 assert_variant!(counter_req, crate::MlmeRequest::GetIfaceStats(responder) => responder);
528 counter_responder.respond(fidl_mlme::GetIfaceStatsResponse::ErrorStatus(1337));
529
530 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
532 let counter_result = assert_variant!(helper.exec.run_until_stalled(&mut counter_fut), Poll::Ready(Ok(counter_result)) => counter_result);
533 assert_eq!(counter_result, Err(1337));
534 }
535
536 #[test]
537 fn generic_sme_get_telemetry_for_ap_fails() {
538 let (mut helper, mut serve_fut) =
539 start_generic_sme_test(fidl_common::WlanMacRole::Ap).unwrap();
540
541 let (_telemetry_proxy, telemetry_server) = create_proxy();
542 let mut telemetry_fut = helper.proxy.get_sme_telemetry(telemetry_server);
543 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
544 assert_variant!(helper.exec.run_until_stalled(&mut telemetry_fut), Poll::Ready(Ok(Err(_))));
545 }
546
547 #[test_case(fidl_common::WlanMacRole::Client)]
548 #[test_case(fidl_common::WlanMacRole::Ap)]
549 fn generic_sme_query(mac_role: fidl_common::WlanMacRole) {
550 let (mut helper, mut serve_fut) = start_generic_sme_test(mac_role).unwrap();
551
552 let mut query_fut = helper.proxy.query();
553 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
554
555 let query_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
556 let query_responder =
557 assert_variant!(query_req, crate::MlmeRequest::QueryDeviceInfo(responder) => responder);
558 query_responder.respond(fidl_mlme::DeviceInfo {
559 role: mac_role,
560 sta_addr: [2; 6],
561 bands: vec![],
562 softmac_hardware_capability: 0,
563 qos_capable: false,
564 });
565
566 assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
567 let query_result = assert_variant!(helper.exec.run_until_stalled(&mut query_fut), Poll::Ready(Ok(result)) => result);
568 assert_eq!(query_result.role, mac_role);
569 assert_eq!(query_result.sta_addr, [2; 6]);
570 }
571}