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