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
165    #[fuchsia::test]
166    fn test_suggest_mac_succeeds() {
167        let mut exec = fasync::TestExecutor::new();
168
169        // Set up the DeprecatedConfigurator.
170        let phy_manager = Arc::new(Mutex::new(StubPhyManager::new()));
171        let configurator = DeprecatedConfigurator::new(phy_manager.clone());
172
173        // Create the request stream and proxy.
174        let (configurator_proxy, remote) =
175            create_proxy::<fidl_deprecated::DeprecatedConfiguratorMarker>();
176        let stream = remote.into_stream();
177
178        // Kick off the serve loop and wait for it to stall out waiting for requests.
179        let fut = configurator.serve_deprecated_configuration(stream);
180        let mut fut = pin!(fut);
181        assert!(exec.run_until_stalled(&mut fut).is_pending());
182
183        // Issue a request to set the MAC address.
184        let octets = [0xde, 0xad, 0xbe, 0xef, 0x00, 0x01];
185        let mac = fidl_fuchsia_net::MacAddress { octets };
186        let mut suggest_fut = configurator_proxy.suggest_access_point_mac_address(&mac);
187        assert!(exec.run_until_stalled(&mut fut).is_pending());
188
189        // Verify that the MAC has been set on the PhyManager
190        let lock_fut = phy_manager.lock();
191        let mut lock_fut = pin!(lock_fut);
192        let phy_manager = assert_matches!(
193            exec.run_until_stalled(&mut lock_fut),
194            Poll::Ready(phy_manager) => {
195                phy_manager
196            }
197        );
198        let expected_mac = MacAddr::from(octets);
199        assert_eq!(Some(expected_mac), phy_manager.0);
200
201        assert_matches!(exec.run_until_stalled(&mut suggest_fut), Poll::Ready(Ok(Ok(()))));
202    }
203
204    #[test_case([0xff, 0xff, 0xff, 0xff, 0xff, 0xff] ; "broadcast")]
205    #[test_case([0x01, 0x00, 0x5e, 0x00, 0x00, 0x01] ; "multicast")]
206    #[fuchsia::test]
207    fn test_suggest_mac_fails(octets: [u8; 6]) {
208        let mut exec = fasync::TestExecutor::new();
209
210        // Set up the DeprecatedConfigurator.
211        let phy_manager = Arc::new(Mutex::new(StubPhyManager::new()));
212        let configurator = DeprecatedConfigurator::new(phy_manager.clone());
213
214        // Create the request stream and proxy.
215        let (configurator_proxy, remote) =
216            create_proxy::<fidl_deprecated::DeprecatedConfiguratorMarker>();
217        let stream = remote.into_stream();
218
219        // Kick off the serve loop and wait for it to stall out waiting for requests.
220        let fut = configurator.serve_deprecated_configuration(stream);
221        let mut fut = pin!(fut);
222        assert!(exec.run_until_stalled(&mut fut).is_pending());
223
224        // Issue a request to set the MAC address.
225        let mac = fidl_fuchsia_net::MacAddress { octets };
226        let mut suggest_fut = configurator_proxy.suggest_access_point_mac_address(&mac);
227        assert!(exec.run_until_stalled(&mut fut).is_pending());
228
229        // Verify that the MAC has been set on the PhyManager
230        let lock_fut = phy_manager.lock();
231        let mut lock_fut = pin!(lock_fut);
232        let phy_manager = assert_matches!(
233            exec.run_until_stalled(&mut lock_fut),
234            Poll::Ready(phy_manager) => {
235                phy_manager
236            }
237        );
238        assert_eq!(None, phy_manager.0);
239
240        assert_matches!(
241            exec.run_until_stalled(&mut suggest_fut),
242            Poll::Ready(Ok(Err(fidl_deprecated::SuggestMacAddressError::InvalidArguments)))
243        );
244    }
245}