wlan_sme/serve/
mod.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5pub 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    mut feature_support_server_sender: mpsc::UnboundedSender<
44        fidl::endpoints::ServerEnd<fidl_sme::FeatureSupportMarker>,
45    >,
46) -> Result<(), anyhow::Error> {
47    loop {
48        match generic_sme_request_stream.next().await {
49            Some(Ok(req)) => {
50                let result = match req {
51                    fidl_sme::GenericSmeRequest::Query { responder } => {
52                        let (info_responder, info_receiver) = crate::responder::Responder::new();
53                        mlme_sink.send(crate::MlmeRequest::QueryDeviceInfo(info_responder));
54                        let info = info_receiver.await?;
55                        responder.send(&fidl_sme::GenericSmeQuery {
56                            role: info.role,
57                            sta_addr: info.sta_addr,
58                        })
59                    }
60                    fidl_sme::GenericSmeRequest::GetClientSme { sme_server, responder } => {
61                        let response =
62                            if let SmeServer::Client(server_sender) = &mut sme_server_sender {
63                                server_sender
64                                    .send(sme_server)
65                                    .await
66                                    .map_err(|_| zx::Status::PEER_CLOSED.into_raw())
67                            } else {
68                                Err(zx::Status::NOT_SUPPORTED.into_raw())
69                            };
70                        responder.send(response)
71                    }
72                    fidl_sme::GenericSmeRequest::GetApSme { sme_server, responder } => {
73                        let response = if let SmeServer::Ap(server_sender) = &mut sme_server_sender
74                        {
75                            server_sender
76                                .send(sme_server)
77                                .await
78                                .map_err(|_| zx::Status::PEER_CLOSED.into_raw())
79                        } else {
80                            Err(zx::Status::NOT_SUPPORTED.into_raw())
81                        };
82                        responder.send(response)
83                    }
84                    fidl_sme::GenericSmeRequest::GetSmeTelemetry {
85                        telemetry_server,
86                        responder,
87                    } => {
88                        let response = if let Some(server) = telemetry_server_sender.as_mut() {
89                            server
90                                .send(telemetry_server)
91                                .await
92                                .map_err(|_| zx::Status::PEER_CLOSED.into_raw())
93                        } else {
94                            warn!("Requested unsupported SME telemetry API");
95                            Err(zx::Status::NOT_SUPPORTED.into_raw())
96                        };
97                        responder.send(response)
98                    }
99                    fidl_sme::GenericSmeRequest::GetFeatureSupport {
100                        feature_support_server,
101                        responder,
102                    } => {
103                        let response = feature_support_server_sender
104                            .send(feature_support_server)
105                            .await
106                            .map_err(|_| zx::Status::PEER_CLOSED.into_raw());
107                        responder.send(response)
108                    }
109                };
110                if let Err(e) = result {
111                    error!("Failed to respond to SME handle request: {}", e);
112                }
113            }
114            Some(Err(e)) => {
115                return Err(format_err!("Generic SME request stream failed: {}", e));
116            }
117            None => {
118                info!("Generic SME request stream terminated. Shutting down.");
119                return Ok(());
120            }
121        }
122    }
123}
124
125#[allow(
126    clippy::too_many_arguments,
127    clippy::type_complexity,
128    reason = "mass allow for https://fxbug.dev/381896734"
129)]
130pub fn create_sme(
131    cfg: crate::Config,
132    mlme_event_stream: MlmeEventStream,
133    device_info: &fidl_mlme::DeviceInfo,
134    mac_sublayer_support: fidl_common::MacSublayerSupport,
135    security_support: fidl_common::SecuritySupport,
136    spectrum_management_support: fidl_common::SpectrumManagementSupport,
137    inspector: fuchsia_inspect::Inspector,
138    persistence_req_sender: auto_persist::PersistenceReqSender,
139    generic_sme_request_stream: <fidl_sme::GenericSmeMarker as fidl::endpoints::ProtocolMarker>::RequestStream,
140) -> Result<(MlmeStream, Pin<Box<impl Future<Output = Result<(), anyhow::Error>>>>), anyhow::Error>
141{
142    let device_info = device_info.clone();
143    let inspect_node = inspector.root().create_child("usme");
144    let (server, mlme_req_sink, mlme_req_stream, telemetry_sender, sme_fut) = match device_info.role
145    {
146        fidl_common::WlanMacRole::Client => {
147            let (telemetry_endpoint_sender, telemetry_endpoint_receiver) = mpsc::unbounded();
148            let (sender, receiver) = mpsc::unbounded();
149            let (mlme_req_sink, mlme_req_stream, fut) = client::serve(
150                cfg,
151                device_info,
152                security_support,
153                spectrum_management_support,
154                mlme_event_stream,
155                receiver,
156                telemetry_endpoint_receiver,
157                inspector,
158                inspect_node,
159                persistence_req_sender,
160            );
161            (
162                SmeServer::Client(sender),
163                mlme_req_sink,
164                mlme_req_stream,
165                Some(telemetry_endpoint_sender),
166                FutureObj::new(Box::new(fut)),
167            )
168        }
169        fidl_common::WlanMacRole::Ap => {
170            let (sender, receiver) = mpsc::unbounded();
171            let (mlme_req_sink, mlme_req_stream, fut) =
172                ap::serve(device_info, mac_sublayer_support, mlme_event_stream, receiver);
173            (
174                SmeServer::Ap(sender),
175                mlme_req_sink,
176                mlme_req_stream,
177                None,
178                FutureObj::new(Box::new(fut)),
179            )
180        }
181        fidl_common::WlanMacRole::Mesh => {
182            return Err(format_err!("Mesh mode is unsupported"));
183        }
184        fidl_common::WlanMacRoleUnknown!() => {
185            return Err(format_err!("Unknown WlanMacRole type: {:?}", device_info.role));
186        }
187    };
188    let (feature_support_sender, feature_support_receiver) = mpsc::unbounded();
189    let feature_support_fut =
190        serve_fidl(mlme_req_sink.clone(), feature_support_receiver, handle_feature_support_query)
191            .map(|result| result.map(|_| ()));
192    let generic_sme_fut = serve_generic_sme(
193        generic_sme_request_stream,
194        mlme_req_sink,
195        server,
196        telemetry_sender,
197        feature_support_sender,
198    );
199    let unified_fut = async move {
200        select! {
201            sme_fut = sme_fut.fuse() => sme_fut,
202            generic_sme_fut = generic_sme_fut.fuse() => generic_sme_fut,
203            feature_support_fut = feature_support_fut.fuse() => feature_support_fut,
204        }
205    };
206    Ok((mlme_req_stream, Box::pin(unified_fut)))
207}
208
209async fn handle_feature_support_query(
210    mlme_sink: crate::MlmeSink,
211    query: fidl_sme::FeatureSupportRequest,
212) -> Result<(), fidl::Error> {
213    match query {
214        fidl_sme::FeatureSupportRequest::QueryDiscoverySupport { responder } => {
215            let (mlme_responder, mlme_receiver) = crate::responder::Responder::new();
216            mlme_sink.send(crate::MlmeRequest::QueryDiscoverySupport(mlme_responder));
217            responder
218                .send(mlme_receiver.await.as_ref().map_err(|_| zx::Status::CANCELED.into_raw()))
219        }
220        fidl_sme::FeatureSupportRequest::QueryMacSublayerSupport { responder } => {
221            let (mlme_responder, mlme_receiver) = crate::responder::Responder::new();
222            mlme_sink.send(crate::MlmeRequest::QueryMacSublayerSupport(mlme_responder));
223            responder
224                .send(mlme_receiver.await.as_ref().map_err(|_| zx::Status::CANCELED.into_raw()))
225        }
226        fidl_sme::FeatureSupportRequest::QuerySecuritySupport { responder } => {
227            let (mlme_responder, mlme_receiver) = crate::responder::Responder::new();
228            mlme_sink.send(crate::MlmeRequest::QuerySecuritySupport(mlme_responder));
229            responder
230                .send(mlme_receiver.await.as_ref().map_err(|_| zx::Status::CANCELED.into_raw()))
231        }
232        fidl_sme::FeatureSupportRequest::QuerySpectrumManagementSupport { responder } => {
233            let (mlme_responder, mlme_receiver) = crate::responder::Responder::new();
234            mlme_sink.send(crate::MlmeRequest::QuerySpectrumManagementSupport(mlme_responder));
235            responder
236                .send(mlme_receiver.await.as_ref().map_err(|_| zx::Status::CANCELED.into_raw()))
237        }
238    }
239}
240
241// The returned future successfully terminates when MLME closes the channel
242async fn serve_mlme_sme<STA, TS>(
243    mut event_stream: MlmeEventStream,
244    station: Arc<Mutex<STA>>,
245    time_stream: TS,
246) -> Result<(), anyhow::Error>
247where
248    STA: Station,
249    TS: Stream<Item = ScheduledEvent<<STA as crate::Station>::Event>> + Unpin,
250{
251    let mut timeout_stream = timer::make_async_timed_event_stream(time_stream).fuse();
252
253    loop {
254        select! {
255            // Fuse rationale: any `none`s in the MLME stream should result in
256            // bailing immediately, so we don't need to track if we've seen a
257            // `None` or not and can `fuse` directly in the `select` call.
258            mlme_event = event_stream.next() => match mlme_event {
259                Some(mlme_event) => station.lock().on_mlme_event(mlme_event),
260                None => return Ok(()),
261            },
262            timeout = timeout_stream.next() => match timeout {
263                Some(timed_event) => station.lock().on_timeout(timed_event),
264                None => return Err(format_err!("SME timer stream has ended unexpectedly")),
265            },
266        }
267    }
268}
269
270#[allow(clippy::extra_unused_lifetimes, reason = "mass allow for https://fxbug.dev/381896734")]
271async fn serve_fidl<
272    'a,
273    C: Clone,
274    T: fidl::endpoints::ProtocolMarker,
275    Fut: futures::Future<Output = Result<(), fidl::Error>>,
276>(
277    context: C,
278    new_fidl_clients: mpsc::UnboundedReceiver<ServerEnd<T>>,
279    event_handler: impl Fn(C, fidl::endpoints::Request<T>) -> Fut + Copy,
280) -> Result<Infallible, anyhow::Error> {
281    let mut new_fidl_clients = new_fidl_clients.fuse();
282    let mut fidl_clients = FuturesUnordered::new();
283    loop {
284        select! {
285            new_fidl_client = new_fidl_clients.next() => match new_fidl_client {
286                Some(end) => fidl_clients.push(serve_fidl_endpoint(context.clone(), end, event_handler)),
287                None => return Err(format_err!("New FIDL client stream unexpectedly ended")),
288            },
289            () = fidl_clients.select_next_some() => {},
290        }
291    }
292}
293
294#[allow(
295    clippy::extra_unused_lifetimes,
296    clippy::needless_return,
297    reason = "mass allow for https://fxbug.dev/381896734"
298)]
299async fn serve_fidl_endpoint<
300    'a,
301    C: Clone,
302    T: fidl::endpoints::ProtocolMarker,
303    Fut: futures::Future<Output = Result<(), fidl::Error>>,
304>(
305    context: C,
306    endpoint: ServerEnd<T>,
307    event_handler: impl Fn(C, fidl::endpoints::Request<T>) -> Fut + Copy,
308) {
309    let stream = endpoint.into_stream();
310    const MAX_CONCURRENT_REQUESTS: usize = 1000;
311    let handler = &event_handler;
312    let r = stream
313        .try_for_each_concurrent(MAX_CONCURRENT_REQUESTS, move |request| {
314            (*handler)(context.clone(), request)
315        })
316        .await;
317    if let Err(e) = r {
318        error!("Error serving FIDL: {}", e);
319        return;
320    }
321}
322
323#[cfg(test)]
324mod tests {
325    use super::*;
326    use crate::test_utils;
327    use fidl::endpoints::{create_proxy, create_proxy_and_stream};
328    use fuchsia_async as fasync;
329    use fuchsia_inspect::Inspector;
330    use futures::task::Poll;
331    use std::pin::pin;
332    use test_case::test_case;
333    use wlan_common::assert_variant;
334    use wlan_common::test_utils::fake_features::{
335        fake_mac_sublayer_support, fake_security_support, fake_spectrum_management_support_empty,
336    };
337
338    #[test]
339    fn create_sme_fails_startup_role_unknown() {
340        let mut _exec = fasync::TestExecutor::new();
341        let inspector = Inspector::default();
342        let (_mlme_event_sender, mlme_event_stream) = mpsc::unbounded();
343        let (persistence_req_sender, _persistence_stream) =
344            test_utils::create_inspect_persistence_channel();
345        let (_generic_sme_proxy, generic_sme_stream) =
346            create_proxy_and_stream::<fidl_sme::GenericSmeMarker>();
347        let device_info = fidl_mlme::DeviceInfo {
348            role: fidl_common::WlanMacRole::unknown(),
349            ..test_utils::fake_device_info([0; 6].into())
350        };
351        let result = create_sme(
352            crate::Config::default(),
353            mlme_event_stream,
354            &device_info,
355            fake_mac_sublayer_support(),
356            fake_security_support(),
357            fake_spectrum_management_support_empty(),
358            inspector,
359            persistence_req_sender,
360            generic_sme_stream,
361        );
362
363        assert!(result.is_err());
364    }
365
366    #[test]
367    fn sme_shutdown_on_generic_sme_closed() {
368        let mut exec = fasync::TestExecutor::new();
369        let (_mlme_event_sender, mlme_event_stream) = mpsc::unbounded();
370        let inspector = Inspector::default();
371        let (persistence_req_sender, _persistence_stream) =
372            test_utils::create_inspect_persistence_channel();
373        let (generic_sme_proxy, generic_sme_stream) =
374            create_proxy_and_stream::<fidl_sme::GenericSmeMarker>();
375        let (_mlme_req_stream, serve_fut) = create_sme(
376            crate::Config::default(),
377            mlme_event_stream,
378            &test_utils::fake_device_info([0; 6].into()),
379            fake_mac_sublayer_support(),
380            fake_security_support(),
381            fake_spectrum_management_support_empty(),
382            inspector,
383            persistence_req_sender,
384            generic_sme_stream,
385        )
386        .unwrap();
387        let mut serve_fut = pin!(serve_fut);
388        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
389
390        // Also close secondary SME endpoint in the Generic SME.
391        drop(generic_sme_proxy);
392
393        // Verify SME future finished cleanly.
394        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Ready(Ok(())));
395    }
396
397    struct GenericSmeTestHelper {
398        proxy: fidl_sme::GenericSmeProxy,
399        mlme_req_stream: MlmeStream,
400
401        // These values must stay in scope or the SME will terminate, but they
402        // are not relevant to Generic SME tests.
403        _inspector: Inspector,
404        _persistence_stream: mpsc::Receiver<String>,
405        _mlme_event_sender: mpsc::UnboundedSender<crate::MlmeEvent>,
406        // Executor goes last to avoid test shutdown failures.
407        exec: fasync::TestExecutor,
408    }
409
410    #[allow(clippy::type_complexity, reason = "mass allow for https://fxbug.dev/381896734")]
411    fn start_generic_sme_test(
412        role: fidl_common::WlanMacRole,
413    ) -> Result<
414        (GenericSmeTestHelper, Pin<Box<impl Future<Output = Result<(), anyhow::Error>>>>),
415        anyhow::Error,
416    > {
417        let mut exec = fasync::TestExecutor::new();
418        let inspector = Inspector::default();
419        let (mlme_event_sender, mlme_event_stream) = mpsc::unbounded();
420        let (persistence_req_sender, persistence_stream) =
421            test_utils::create_inspect_persistence_channel();
422        let (generic_sme_proxy, generic_sme_stream) =
423            create_proxy_and_stream::<fidl_sme::GenericSmeMarker>();
424        let device_info =
425            fidl_mlme::DeviceInfo { role, ..test_utils::fake_device_info([0; 6].into()) };
426        let (mlme_req_stream, serve_fut) = create_sme(
427            crate::Config::default(),
428            mlme_event_stream,
429            &device_info,
430            fake_mac_sublayer_support(),
431            fake_security_support(),
432            fake_spectrum_management_support_empty(),
433            inspector.clone(),
434            persistence_req_sender,
435            generic_sme_stream,
436        )?;
437        let mut serve_fut = Box::pin(serve_fut);
438        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
439
440        Ok((
441            GenericSmeTestHelper {
442                proxy: generic_sme_proxy,
443                mlme_req_stream,
444                _inspector: inspector,
445                _persistence_stream: persistence_stream,
446                _mlme_event_sender: mlme_event_sender,
447                exec,
448            },
449            serve_fut,
450        ))
451    }
452
453    #[test]
454    fn generic_sme_get_client() {
455        let (mut helper, mut serve_fut) =
456            start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
457
458        let (client_proxy, client_server) = create_proxy();
459        let mut client_sme_fut = helper.proxy.get_client_sme(client_server);
460        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
461        assert_variant!(
462            helper.exec.run_until_stalled(&mut client_sme_fut),
463            Poll::Ready(Ok(Ok(())))
464        );
465
466        let mut status_fut = client_proxy.status();
467        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
468        assert_variant!(
469            helper.exec.run_until_stalled(&mut status_fut),
470            Poll::Ready(Ok(fidl_sme::ClientStatusResponse::Idle(_)))
471        );
472    }
473
474    #[test]
475    fn generic_sme_get_ap_from_client_fails() {
476        let (mut helper, mut serve_fut) =
477            start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
478
479        let (_ap_proxy, ap_server) = create_proxy();
480        let mut client_sme_fut = helper.proxy.get_ap_sme(ap_server);
481        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
482        assert_variant!(
483            helper.exec.run_until_stalled(&mut client_sme_fut),
484            Poll::Ready(Ok(Err(_)))
485        );
486    }
487
488    #[test]
489    fn generic_sme_get_ap() {
490        let (mut helper, mut serve_fut) =
491            start_generic_sme_test(fidl_common::WlanMacRole::Ap).unwrap();
492
493        let (ap_proxy, ap_server) = create_proxy();
494        let mut ap_sme_fut = helper.proxy.get_ap_sme(ap_server);
495        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
496        assert_variant!(helper.exec.run_until_stalled(&mut ap_sme_fut), Poll::Ready(Ok(Ok(()))));
497
498        let mut status_fut = ap_proxy.status();
499        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
500        assert_variant!(
501            helper.exec.run_until_stalled(&mut status_fut),
502            Poll::Ready(Ok(fidl_sme::ApStatusResponse { .. }))
503        );
504    }
505
506    #[test]
507    fn generic_sme_get_client_from_ap_fails() {
508        let (mut helper, mut serve_fut) =
509            start_generic_sme_test(fidl_common::WlanMacRole::Ap).unwrap();
510
511        let (_client_proxy, client_server) = create_proxy();
512        let mut client_sme_fut = helper.proxy.get_client_sme(client_server);
513        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
514        assert_variant!(
515            helper.exec.run_until_stalled(&mut client_sme_fut),
516            Poll::Ready(Ok(Err(_)))
517        );
518    }
519
520    fn get_telemetry_proxy(
521        helper: &mut GenericSmeTestHelper,
522        serve_fut: &mut Pin<Box<impl Future<Output = Result<(), anyhow::Error>>>>,
523    ) -> fidl_sme::TelemetryProxy {
524        let (proxy, server) = create_proxy();
525        let mut telemetry_fut = helper.proxy.get_sme_telemetry(server);
526        assert_variant!(helper.exec.run_until_stalled(serve_fut), Poll::Pending);
527        assert_variant!(helper.exec.run_until_stalled(&mut telemetry_fut), Poll::Ready(Ok(Ok(()))));
528        proxy
529    }
530
531    #[test]
532    fn generic_sme_query_telemetry_support_for_client() {
533        let (mut helper, mut serve_fut) =
534            start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
535        let telemetry_proxy = get_telemetry_proxy(&mut helper, &mut serve_fut);
536
537        // Forward request to MLME.
538        let mut support_fut = telemetry_proxy.query_telemetry_support();
539        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
540
541        // Mock response from MLME. Use a fake error code to make the response easily verifiable.
542        let support_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
543        let support_responder = assert_variant!(support_req, crate::MlmeRequest::QueryTelemetrySupport(responder) => responder);
544        support_responder.respond(Err(1337));
545
546        // Verify that the response made it to us without alteration.
547        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
548        let support_result = assert_variant!(helper.exec.run_until_stalled(&mut support_fut), Poll::Ready(Ok(support_result)) => support_result);
549        assert_eq!(support_result, Err(1337));
550    }
551
552    #[test]
553    fn generic_sme_get_histogram_stats_for_client() {
554        let (mut helper, mut serve_fut) =
555            start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
556        let telemetry_proxy = get_telemetry_proxy(&mut helper, &mut serve_fut);
557
558        // Forward request to MLME.
559        let mut histogram_fut = telemetry_proxy.get_histogram_stats();
560        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
561
562        // Mock response from MLME. Use a fake error code to make the response easily verifiable.
563        let histogram_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
564        let histogram_responder = assert_variant!(histogram_req, crate::MlmeRequest::GetIfaceHistogramStats(responder) => responder);
565        histogram_responder.respond(fidl_mlme::GetIfaceHistogramStatsResponse::ErrorStatus(1337));
566
567        // Verify that the response made it to us without alteration.
568        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
569        let histogram_result = assert_variant!(helper.exec.run_until_stalled(&mut histogram_fut), Poll::Ready(Ok(histogram_result)) => histogram_result);
570        assert_eq!(histogram_result, Err(1337));
571    }
572
573    #[test]
574    fn generic_sme_get_iface_stats_for_client() {
575        let (mut helper, mut serve_fut) =
576            start_generic_sme_test(fidl_common::WlanMacRole::Client).unwrap();
577        let telemetry_proxy = get_telemetry_proxy(&mut helper, &mut serve_fut);
578
579        // Forward request to MLME.
580        let mut counter_fut = telemetry_proxy.get_iface_stats();
581        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
582
583        // Mock response from MLME. Use a fake error code to make the response easily verifiable.
584        let counter_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
585        let counter_responder =
586            assert_variant!(counter_req, crate::MlmeRequest::GetIfaceStats(responder) => responder);
587        counter_responder.respond(fidl_mlme::GetIfaceStatsResponse::ErrorStatus(1337));
588
589        // Verify that the response made it to us without alteration.
590        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
591        let counter_result = assert_variant!(helper.exec.run_until_stalled(&mut counter_fut), Poll::Ready(Ok(counter_result)) => counter_result);
592        assert_eq!(counter_result, Err(1337));
593    }
594
595    #[test]
596    fn generic_sme_get_telemetry_for_ap_fails() {
597        let (mut helper, mut serve_fut) =
598            start_generic_sme_test(fidl_common::WlanMacRole::Ap).unwrap();
599
600        let (_telemetry_proxy, telemetry_server) = create_proxy();
601        let mut telemetry_fut = helper.proxy.get_sme_telemetry(telemetry_server);
602        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
603        assert_variant!(helper.exec.run_until_stalled(&mut telemetry_fut), Poll::Ready(Ok(Err(_))));
604    }
605
606    fn get_feature_support_proxy(
607        helper: &mut GenericSmeTestHelper,
608        serve_fut: &mut Pin<Box<impl Future<Output = Result<(), anyhow::Error>>>>,
609    ) -> fidl_sme::FeatureSupportProxy {
610        let (proxy, server) = create_proxy();
611        let mut features_fut = helper.proxy.get_feature_support(server);
612        assert_variant!(helper.exec.run_until_stalled(serve_fut), Poll::Pending);
613        assert_variant!(helper.exec.run_until_stalled(&mut features_fut), Poll::Ready(Ok(Ok(()))));
614        proxy
615    }
616
617    #[test_case(fidl_common::WlanMacRole::Client)]
618    #[test_case(fidl_common::WlanMacRole::Ap)]
619    fn generic_sme_discovery_support_query(mac_role: fidl_common::WlanMacRole) {
620        let (mut helper, mut serve_fut) = start_generic_sme_test(mac_role).unwrap();
621        let feature_support_proxy = get_feature_support_proxy(&mut helper, &mut serve_fut);
622
623        let mut discovery_support_fut = feature_support_proxy.query_discovery_support();
624        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
625
626        // Mock response from MLME.
627        let discovery_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
628        let discovery_responder = assert_variant!(discovery_req, crate::MlmeRequest::QueryDiscoverySupport(responder) => responder);
629        let expected_discovery_support = fidl_common::DiscoverySupport {
630            scan_offload: fidl_common::ScanOffloadExtension {
631                supported: true,
632                scan_cancel_supported: false,
633            },
634            probe_response_offload: fidl_common::ProbeResponseOffloadExtension { supported: false },
635        };
636        discovery_responder.respond(expected_discovery_support);
637        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
638        let discovery_support = assert_variant!(helper.exec.run_until_stalled(&mut discovery_support_fut), Poll::Ready(Ok(support)) => support);
639        assert_eq!(discovery_support, Ok(expected_discovery_support));
640    }
641
642    #[test_case(fidl_common::WlanMacRole::Client)]
643    #[test_case(fidl_common::WlanMacRole::Ap)]
644    fn generic_sme_mac_sublayer_support_query(mac_role: fidl_common::WlanMacRole) {
645        let (mut helper, mut serve_fut) = start_generic_sme_test(mac_role).unwrap();
646        let feature_support_proxy = get_feature_support_proxy(&mut helper, &mut serve_fut);
647
648        let mut mac_sublayer_support_fut = feature_support_proxy.query_mac_sublayer_support();
649        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
650
651        // Mock response from MLME.
652        let mac_sublayer_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
653        let mac_sublayer_responder = assert_variant!(mac_sublayer_req, crate::MlmeRequest::QueryMacSublayerSupport(responder) => responder);
654        let expected_mac_sublayer_support = fidl_common::MacSublayerSupport {
655            rate_selection_offload: fidl_common::RateSelectionOffloadExtension { supported: true },
656            data_plane: fidl_common::DataPlaneExtension {
657                data_plane_type: fidl_common::DataPlaneType::GenericNetworkDevice,
658            },
659            device: fidl_common::DeviceExtension {
660                is_synthetic: true,
661                mac_implementation_type: fidl_common::MacImplementationType::Softmac,
662                tx_status_report_supported: false,
663            },
664        };
665        mac_sublayer_responder.respond(expected_mac_sublayer_support);
666        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
667        let mac_sublayer_support = assert_variant!(helper.exec.run_until_stalled(&mut mac_sublayer_support_fut), Poll::Ready(Ok(support)) => support);
668        assert_eq!(mac_sublayer_support, Ok(expected_mac_sublayer_support));
669    }
670
671    #[test_case(fidl_common::WlanMacRole::Client)]
672    #[test_case(fidl_common::WlanMacRole::Ap)]
673    fn generic_sme_security_support_query(mac_role: fidl_common::WlanMacRole) {
674        let (mut helper, mut serve_fut) = start_generic_sme_test(mac_role).unwrap();
675        let feature_support_proxy = get_feature_support_proxy(&mut helper, &mut serve_fut);
676
677        let mut security_support_fut = feature_support_proxy.query_security_support();
678        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
679
680        // Mock response from MLME.
681        let security_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
682        let security_responder = assert_variant!(security_req, crate::MlmeRequest::QuerySecuritySupport(responder) => responder);
683        let expected_security_support = fidl_common::SecuritySupport {
684            sae: fidl_common::SaeFeature {
685                driver_handler_supported: true,
686                sme_handler_supported: false,
687            },
688            mfp: fidl_common::MfpFeature { supported: true },
689        };
690        security_responder.respond(expected_security_support);
691        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
692        let security_support = assert_variant!(helper.exec.run_until_stalled(&mut security_support_fut), Poll::Ready(Ok(support)) => support);
693        assert_eq!(security_support, Ok(expected_security_support));
694    }
695
696    #[test_case(fidl_common::WlanMacRole::Client)]
697    #[test_case(fidl_common::WlanMacRole::Ap)]
698    fn generic_sme_spectrum_management_query(mac_role: fidl_common::WlanMacRole) {
699        let (mut helper, mut serve_fut) = start_generic_sme_test(mac_role).unwrap();
700        let feature_support_proxy = get_feature_support_proxy(&mut helper, &mut serve_fut);
701
702        let mut spectrum_support_fut = feature_support_proxy.query_spectrum_management_support();
703        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
704
705        // Mock response from MLME.
706        let spectrum_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
707        let spectrum_responder = assert_variant!(spectrum_req, crate::MlmeRequest::QuerySpectrumManagementSupport(responder) => responder);
708        let expected_spectrum_support = fidl_common::SpectrumManagementSupport {
709            dfs: fidl_common::DfsFeature { supported: true },
710        };
711        spectrum_responder.respond(expected_spectrum_support);
712        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
713        let spectrum_support = assert_variant!(helper.exec.run_until_stalled(&mut spectrum_support_fut), Poll::Ready(Ok(support)) => support);
714        assert_eq!(spectrum_support, Ok(expected_spectrum_support));
715    }
716
717    #[test_case(fidl_common::WlanMacRole::Client)]
718    #[test_case(fidl_common::WlanMacRole::Ap)]
719    fn generic_sme_support_query_cancelled(mac_role: fidl_common::WlanMacRole) {
720        let (mut helper, mut serve_fut) = start_generic_sme_test(mac_role).unwrap();
721        let feature_support_proxy = get_feature_support_proxy(&mut helper, &mut serve_fut);
722
723        let mut discovery_support_fut = feature_support_proxy.query_discovery_support();
724        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
725
726        // No response from MLME, drop the responder instead. This might happen during shutdown.
727        let discovery_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
728        let discovery_responder = assert_variant!(discovery_req, crate::MlmeRequest::QueryDiscoverySupport(responder) => responder);
729        drop(discovery_responder);
730        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
731        let discovery_support = assert_variant!(helper.exec.run_until_stalled(&mut discovery_support_fut), Poll::Ready(Ok(support)) => support);
732        assert_eq!(discovery_support, Err(zx::Status::CANCELED.into_raw()));
733    }
734
735    #[test_case(fidl_common::WlanMacRole::Client)]
736    #[test_case(fidl_common::WlanMacRole::Ap)]
737    fn generic_sme_query(mac_role: fidl_common::WlanMacRole) {
738        let (mut helper, mut serve_fut) = start_generic_sme_test(mac_role).unwrap();
739
740        let mut query_fut = helper.proxy.query();
741        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
742
743        let query_req = assert_variant!(helper.exec.run_until_stalled(&mut helper.mlme_req_stream.next()), Poll::Ready(Some(req)) => req);
744        let query_responder =
745            assert_variant!(query_req, crate::MlmeRequest::QueryDeviceInfo(responder) => responder);
746        query_responder.respond(fidl_mlme::DeviceInfo {
747            role: mac_role,
748            sta_addr: [2; 6],
749            bands: vec![],
750            softmac_hardware_capability: 0,
751            qos_capable: false,
752        });
753
754        assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
755        let query_result = assert_variant!(helper.exec.run_until_stalled(&mut query_fut), Poll::Ready(Ok(result)) => result);
756        assert_eq!(query_result.role, mac_role);
757        assert_eq!(query_result.sta_addr, [2; 6]);
758    }
759}