Skip to main content

wlancfg_lib/legacy/
deprecated_configuration.rs

1// Copyright 2020 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::mode_management::phy_manager::PhyManagerApi;
6use fidl_fuchsia_wlan_product_deprecatedconfiguration as fidl_deprecated;
7use futures::lock::Mutex;
8use futures::{StreamExt, select};
9use ieee80211::MacAddr;
10use log::{error, info};
11use std::sync::Arc;
12
13#[derive(Clone)]
14pub struct DeprecatedConfigurator {
15    phy_manager: Arc<Mutex<dyn PhyManagerApi>>,
16}
17
18impl DeprecatedConfigurator {
19    pub fn new(phy_manager: Arc<Mutex<dyn PhyManagerApi>>) -> Self {
20        DeprecatedConfigurator { phy_manager }
21    }
22
23    pub async fn serve_deprecated_configuration(
24        self,
25        mut requests: fidl_deprecated::DeprecatedConfiguratorRequestStream,
26    ) {
27        loop {
28            select! {
29                req = requests.select_next_some() => match req {
30                    Ok(req) => match req {
31                        fidl_deprecated::DeprecatedConfiguratorRequest::SuggestAccessPointMacAddress{mac, responder} => {
32                            info!("setting suggested AP MAC");
33                            let mac = MacAddr::from(mac.octets);
34
35                            if !mac.is_unicast() || mac == ieee80211::NULL_ADDR {
36                                error!("rejecting invalid suggested AP MAC");
37                                if let Err(e) = responder.send(Err(fidl_deprecated::SuggestMacAddressError::InvalidArguments)) {
38                                    error!("could not send SuggestAccessPointMacAddress response: {:?}", e);
39                                }
40                                continue;
41                            }
42
43                            let mut phy_manager = self.phy_manager.lock().await;
44                            phy_manager.suggest_ap_mac(mac);
45
46                            match responder.send(Ok(())) {
47                                Ok(()) => {}
48                                Err(e) => {
49                                    error!("could not send SuggestAccessPointMacAddress response: {:?}", e);
50                                }
51                            }
52                        }
53                    }
54                    Err(e) => error!("encountered an error while serving deprecated configuration requests: {}", e)
55                },
56                complete => break,
57            }
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use crate::client::types as client_types;
66    use crate::mode_management::Defect;
67    use crate::mode_management::phy_manager::{CreateClientIfacesReason, PhyManagerError};
68    use crate::mode_management::recovery::RecoverySummary;
69    use assert_matches::assert_matches;
70    use async_trait::async_trait;
71    use fidl::endpoints::create_proxy;
72    use fuchsia_async as fasync;
73    use futures::task::Poll;
74    use std::collections::HashMap;
75    use std::pin::pin;
76    use std::unimplemented;
77    use test_case::test_case;
78
79    #[derive(Debug)]
80    struct StubPhyManager(Option<MacAddr>);
81
82    impl StubPhyManager {
83        fn new() -> Self {
84            StubPhyManager(None)
85        }
86    }
87
88    #[async_trait(?Send)]
89    impl PhyManagerApi for StubPhyManager {
90        async fn add_phy(&mut self, _phy_id: u16) -> Result<(), PhyManagerError> {
91            unimplemented!();
92        }
93
94        fn remove_phy(&mut self, _phy_id: u16) {
95            unimplemented!();
96        }
97
98        async fn on_iface_added(&mut self, _iface_id: u16) -> Result<(), PhyManagerError> {
99            unimplemented!();
100        }
101
102        fn on_iface_removed(&mut self, _iface_id: u16) {
103            unimplemented!();
104        }
105
106        async fn create_all_client_ifaces(
107            &mut self,
108            _reason: CreateClientIfacesReason,
109        ) -> HashMap<u16, Result<Vec<u16>, PhyManagerError>> {
110            unimplemented!();
111        }
112
113        fn client_connections_enabled(&self) -> bool {
114            unimplemented!();
115        }
116
117        async fn destroy_all_client_ifaces(&mut self) -> Result<(), PhyManagerError> {
118            unimplemented!();
119        }
120
121        fn get_client(&mut self) -> Option<u16> {
122            unimplemented!();
123        }
124
125        async fn create_or_get_ap_iface(&mut self) -> Result<Option<u16>, PhyManagerError> {
126            unimplemented!();
127        }
128
129        async fn destroy_ap_iface(&mut self, _iface_id: u16) -> Result<(), PhyManagerError> {
130            unimplemented!();
131        }
132
133        async fn destroy_all_ap_ifaces(&mut self) -> Result<(), PhyManagerError> {
134            unimplemented!();
135        }
136
137        fn suggest_ap_mac(&mut self, mac: MacAddr) {
138            self.0 = Some(mac);
139        }
140
141        fn get_phy_ids(&self) -> Vec<u16> {
142            unimplemented!();
143        }
144
145        fn log_phy_add_failure(&mut self) {
146            unimplemented!();
147        }
148
149        async fn set_country_code(
150            &mut self,
151            _country_code: Option<client_types::CountryCode>,
152        ) -> Result<(), PhyManagerError> {
153            unimplemented!();
154        }
155
156        fn record_defect(&mut self, _defect: Defect) {
157            unimplemented!();
158        }
159
160        async fn perform_recovery(&mut self, _summary: RecoverySummary) {
161            unimplemented!();
162        }
163
164        async fn on_before_suspend(&mut self) {}
165        async fn on_after_resume(&mut self) {}
166    }
167
168    #[fuchsia::test]
169    fn test_suggest_mac_succeeds() {
170        let mut exec = fasync::TestExecutor::new();
171
172        // Set up the DeprecatedConfigurator.
173        let phy_manager = Arc::new(Mutex::new(StubPhyManager::new()));
174        let configurator = DeprecatedConfigurator::new(phy_manager.clone());
175
176        // Create the request stream and proxy.
177        let (configurator_proxy, remote) =
178            create_proxy::<fidl_deprecated::DeprecatedConfiguratorMarker>();
179        let stream = remote.into_stream();
180
181        // Kick off the serve loop and wait for it to stall out waiting for requests.
182        let fut = configurator.serve_deprecated_configuration(stream);
183        let mut fut = pin!(fut);
184        assert!(exec.run_until_stalled(&mut fut).is_pending());
185
186        // Issue a request to set the MAC address.
187        let octets = [0xde, 0xad, 0xbe, 0xef, 0x00, 0x01];
188        let mac = fidl_fuchsia_net::MacAddress { octets };
189        let mut suggest_fut = configurator_proxy.suggest_access_point_mac_address(&mac);
190        assert!(exec.run_until_stalled(&mut fut).is_pending());
191
192        // Verify that the MAC has been set on the PhyManager
193        let lock_fut = phy_manager.lock();
194        let mut lock_fut = pin!(lock_fut);
195        let phy_manager = assert_matches!(
196            exec.run_until_stalled(&mut lock_fut),
197            Poll::Ready(phy_manager) => {
198                phy_manager
199            }
200        );
201        let expected_mac = MacAddr::from(octets);
202        assert_eq!(Some(expected_mac), phy_manager.0);
203
204        assert_matches!(exec.run_until_stalled(&mut suggest_fut), Poll::Ready(Ok(Ok(()))));
205    }
206
207    #[test_case([0xff, 0xff, 0xff, 0xff, 0xff, 0xff] ; "broadcast")]
208    #[test_case([0x01, 0x00, 0x5e, 0x00, 0x00, 0x01] ; "multicast")]
209    #[fuchsia::test]
210    fn test_suggest_mac_fails(octets: [u8; 6]) {
211        let mut exec = fasync::TestExecutor::new();
212
213        // Set up the DeprecatedConfigurator.
214        let phy_manager = Arc::new(Mutex::new(StubPhyManager::new()));
215        let configurator = DeprecatedConfigurator::new(phy_manager.clone());
216
217        // Create the request stream and proxy.
218        let (configurator_proxy, remote) =
219            create_proxy::<fidl_deprecated::DeprecatedConfiguratorMarker>();
220        let stream = remote.into_stream();
221
222        // Kick off the serve loop and wait for it to stall out waiting for requests.
223        let fut = configurator.serve_deprecated_configuration(stream);
224        let mut fut = pin!(fut);
225        assert!(exec.run_until_stalled(&mut fut).is_pending());
226
227        // Issue a request to set the MAC address.
228        let mac = fidl_fuchsia_net::MacAddress { octets };
229        let mut suggest_fut = configurator_proxy.suggest_access_point_mac_address(&mac);
230        assert!(exec.run_until_stalled(&mut fut).is_pending());
231
232        // Verify that the MAC has been set on the PhyManager
233        let lock_fut = phy_manager.lock();
234        let mut lock_fut = pin!(lock_fut);
235        let phy_manager = assert_matches!(
236            exec.run_until_stalled(&mut lock_fut),
237            Poll::Ready(phy_manager) => {
238                phy_manager
239            }
240        );
241        assert_eq!(None, phy_manager.0);
242
243        assert_matches!(
244            exec.run_until_stalled(&mut suggest_fut),
245            Poll::Ready(Ok(Err(fidl_deprecated::SuggestMacAddressError::InvalidArguments)))
246        );
247    }
248}