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