Skip to main content

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