wlan_fullmac_mlme/
wlan_fullmac_impl_ifc_request_handler.rs

1// Copyright 2024 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
5use crate::convert::fullmac_to_mlme;
6use crate::{FullmacDriverEvent, FullmacDriverEventSink};
7use anyhow::Context;
8use fidl_fuchsia_wlan_fullmac as fidl_fullmac;
9use futures::StreamExt;
10use log::error;
11
12pub async fn serve_wlan_fullmac_impl_ifc_request_handler(
13    mut fullmac_ifc_request_stream: fidl_fullmac::WlanFullmacImplIfcRequestStream,
14    driver_event_sink: FullmacDriverEventSink,
15) {
16    while let Some(Ok(req)) = fullmac_ifc_request_stream.next().await {
17        if let Err(e) = handle_one_request(req, &driver_event_sink) {
18            error!("Failed to handle driver event: {}", e);
19        }
20    }
21}
22
23fn handle_one_request(
24    req: fidl_fullmac::WlanFullmacImplIfcRequest,
25    driver_event_sink: &FullmacDriverEventSink,
26) -> anyhow::Result<()> {
27    match req {
28        fidl_fullmac::WlanFullmacImplIfcRequest::OnScanResult { payload, responder } => {
29            responder.send().context("Failed to respond to OnScanResult")?;
30            driver_event_sink.0.send(FullmacDriverEvent::OnScanResult {
31                result: fullmac_to_mlme::convert_scan_result(payload)?,
32            });
33        }
34        fidl_fullmac::WlanFullmacImplIfcRequest::OnScanEnd { payload, responder } => {
35            responder.send().context("Failed to respond to OnScanEnd")?;
36            driver_event_sink.0.send(FullmacDriverEvent::OnScanEnd {
37                end: fullmac_to_mlme::convert_scan_end(payload)?,
38            });
39        }
40        fidl_fullmac::WlanFullmacImplIfcRequest::ConnectConf { payload, responder } => {
41            responder.send().context("Failed to respond to ConnectConf")?;
42            driver_event_sink.0.send(FullmacDriverEvent::ConnectConf {
43                resp: fullmac_to_mlme::convert_connect_confirm(payload)?,
44            });
45        }
46        fidl_fullmac::WlanFullmacImplIfcRequest::RoamConf { payload, responder } => {
47            responder.send().context("Failed to respond to RoamConf")?;
48            driver_event_sink.0.send(FullmacDriverEvent::RoamConf {
49                conf: fullmac_to_mlme::convert_roam_confirm(payload)?,
50            });
51        }
52        fidl_fullmac::WlanFullmacImplIfcRequest::RoamStartInd { payload, responder } => {
53            responder.send().context("Failed to respond to RoamStartInd")?;
54            driver_event_sink.0.send(FullmacDriverEvent::RoamStartInd {
55                ind: fullmac_to_mlme::convert_roam_start_indication(payload)?,
56            });
57        }
58        fidl_fullmac::WlanFullmacImplIfcRequest::RoamResultInd { payload, responder } => {
59            responder.send().context("Failed to respond to RoamResultInd")?;
60            driver_event_sink.0.send(FullmacDriverEvent::RoamResultInd {
61                ind: fullmac_to_mlme::convert_roam_result_indication(payload)?,
62            });
63        }
64        fidl_fullmac::WlanFullmacImplIfcRequest::AuthInd { payload, responder } => {
65            responder.send().context("Failed to respond to AuthInd")?;
66            driver_event_sink.0.send(FullmacDriverEvent::AuthInd {
67                ind: fullmac_to_mlme::convert_authenticate_indication(payload)?,
68            });
69        }
70        fidl_fullmac::WlanFullmacImplIfcRequest::DeauthConf { payload, responder } => {
71            responder.send().context("Failed to respond to DeauthConf")?;
72            driver_event_sink.0.send(FullmacDriverEvent::DeauthConf {
73                resp: fullmac_to_mlme::convert_deauthenticate_confirm(payload),
74            });
75        }
76        fidl_fullmac::WlanFullmacImplIfcRequest::DeauthInd { payload, responder } => {
77            responder.send().context("Failed to respond to DeauthInd")?;
78            driver_event_sink.0.send(FullmacDriverEvent::DeauthInd {
79                ind: fullmac_to_mlme::convert_deauthenticate_indication(payload)?,
80            });
81        }
82        fidl_fullmac::WlanFullmacImplIfcRequest::AssocInd { payload, responder } => {
83            responder.send().context("Failed to respond to AssocInd")?;
84            driver_event_sink.0.send(FullmacDriverEvent::AssocInd {
85                ind: fullmac_to_mlme::convert_associate_indication(payload)?,
86            });
87        }
88        fidl_fullmac::WlanFullmacImplIfcRequest::DisassocConf { payload, responder } => {
89            responder.send().context("Failed to respond to DisassocConf")?;
90            driver_event_sink.0.send(FullmacDriverEvent::DisassocConf {
91                resp: fullmac_to_mlme::convert_disassociate_confirm(payload),
92            });
93        }
94        fidl_fullmac::WlanFullmacImplIfcRequest::DisassocInd { payload, responder } => {
95            responder.send().context("Failed to respond to DisassocInd")?;
96            driver_event_sink.0.send(FullmacDriverEvent::DisassocInd {
97                ind: fullmac_to_mlme::convert_disassociate_indication(payload)?,
98            });
99        }
100        fidl_fullmac::WlanFullmacImplIfcRequest::StartConf { payload, responder } => {
101            responder.send().context("Failed to respond to StartConf")?;
102            driver_event_sink.0.send(FullmacDriverEvent::StartConf {
103                resp: fullmac_to_mlme::convert_start_confirm(payload)?,
104            });
105        }
106        fidl_fullmac::WlanFullmacImplIfcRequest::StopConf { payload, responder } => {
107            responder.send().context("Failed to respond to StopConf")?;
108            driver_event_sink.0.send(FullmacDriverEvent::StopConf {
109                resp: fullmac_to_mlme::convert_stop_confirm(payload)?,
110            });
111        }
112        fidl_fullmac::WlanFullmacImplIfcRequest::EapolConf { payload, responder } => {
113            responder.send().context("Failed to respond to EapolConf")?;
114            driver_event_sink.0.send(FullmacDriverEvent::EapolConf {
115                resp: fullmac_to_mlme::convert_eapol_confirm(payload)?,
116            });
117        }
118        fidl_fullmac::WlanFullmacImplIfcRequest::OnChannelSwitch { ind, responder } => {
119            responder.send().context("Failed to respond to OnChannelSwitch")?;
120            driver_event_sink.0.send(FullmacDriverEvent::OnChannelSwitch {
121                resp: fullmac_to_mlme::convert_channel_switch_info(ind),
122            });
123        }
124        fidl_fullmac::WlanFullmacImplIfcRequest::SignalReport { ind, responder } => {
125            responder.send().context("Failed to respond to SignalReport")?;
126            driver_event_sink.0.send(FullmacDriverEvent::SignalReport {
127                ind: fullmac_to_mlme::convert_signal_report_indication(ind),
128            });
129        }
130        fidl_fullmac::WlanFullmacImplIfcRequest::EapolInd { payload, responder } => {
131            responder.send().context("Failed to respond to EapolInd")?;
132            driver_event_sink.0.send(FullmacDriverEvent::EapolInd {
133                ind: fullmac_to_mlme::convert_eapol_indication(payload)?,
134            });
135        }
136        fidl_fullmac::WlanFullmacImplIfcRequest::OnPmkAvailable { payload, responder } => {
137            responder.send().context("Failed to respond to OnPmkAvailable")?;
138            driver_event_sink.0.send(FullmacDriverEvent::OnPmkAvailable {
139                info: fullmac_to_mlme::convert_pmk_info(payload)?,
140            });
141        }
142        fidl_fullmac::WlanFullmacImplIfcRequest::SaeHandshakeInd { payload, responder } => {
143            responder.send().context("Failed to respond to SaeHandshakeInd")?;
144            driver_event_sink.0.send(FullmacDriverEvent::SaeHandshakeInd {
145                ind: fullmac_to_mlme::convert_sae_handshake_indication(payload)?,
146            });
147        }
148        fidl_fullmac::WlanFullmacImplIfcRequest::SaeFrameRx { frame, responder } => {
149            responder.send().context("Failed to respond to SaeFrameRx")?;
150            driver_event_sink.0.send(FullmacDriverEvent::SaeFrameRx {
151                frame: fullmac_to_mlme::convert_sae_frame(frame)?,
152            });
153        }
154        fidl_fullmac::WlanFullmacImplIfcRequest::OnWmmStatusResp {
155            status,
156            wmm_params,
157            responder,
158        } => {
159            responder.send().context("Failed to respond to OnWmmStatusResp")?;
160            driver_event_sink.0.send(FullmacDriverEvent::OnWmmStatusResp {
161                status,
162                resp: fullmac_to_mlme::convert_wmm_params(wmm_params),
163            });
164        }
165    }
166    Ok(())
167}
168
169#[cfg(test)]
170mod tests {
171    use super::*;
172    use fuchsia_async as fasync;
173    use futures::channel::mpsc;
174    use futures::task::Poll;
175    use std::pin::pin;
176    use wlan_common::assert_variant;
177    use wlan_common::sink::UnboundedSink;
178
179    // MLME owns the driver event receiver, but its lifetime is not exactly synchronized with the
180    // lifetime of the WlanFullmacImplIfc server task.
181    //
182    // In case the WlanFullmacImplIfc server task is dropped after MLME is dropped, ensure that
183    // nothing bad happens if we receive a request in the time between MLME and the
184    // WlanFullmacImplIfc server dropping.
185    //
186    // This essentially checks that if the receiver is dropped, the server can still receive a
187    // request and be dropped without issue.
188    #[fuchsia::test]
189    fn receive_request_after_driver_event_receiver_dropped() {
190        let mut exec = fasync::TestExecutor::new();
191        let (driver_event_sender, driver_event_receiver) = mpsc::unbounded();
192        let (ifc_proxy, ifc_req_stream) =
193            fidl::endpoints::create_proxy_and_stream::<fidl_fullmac::WlanFullmacImplIfcMarker>();
194
195        let driver_event_sink = FullmacDriverEventSink(UnboundedSink::new(driver_event_sender));
196        let mut server_fut =
197            pin!(serve_wlan_fullmac_impl_ifc_request_handler(ifc_req_stream, driver_event_sink));
198
199        assert_variant!(exec.run_until_stalled(&mut server_fut), Poll::Pending);
200
201        std::mem::drop(driver_event_receiver);
202
203        let scan_end = fidl_fullmac::WlanFullmacImplIfcOnScanEndRequest {
204            txn_id: Some(42u64),
205            code: Some(fidl_fullmac::WlanScanResult::Success),
206            ..Default::default()
207        };
208
209        let mut req_fut = pin!(ifc_proxy.on_scan_end(&scan_end));
210        assert_variant!(exec.run_until_stalled(&mut req_fut), Poll::Pending,);
211        assert_variant!(exec.run_until_stalled(&mut server_fut), Poll::Pending);
212
213        // check that server_fut completes the FIDL request without error
214        assert_variant!(exec.run_until_stalled(&mut req_fut), Poll::Ready(Ok(())),);
215    }
216}