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                            let mut phy_manager = self.phy_manager.lock().await;
35                            phy_manager.suggest_ap_mac(mac);
36
37                            match responder.send(Ok(())) {
38                                Ok(()) => {}
39                                Err(e) => {
40                                    error!("could not send SuggestAccessPointMacAddress response: {:?}", e);
41                                }
42                            }
43                        }
44                    }
45                    Err(e) => error!("encountered an error while serving deprecated configuration requests: {}", e)
46                },
47                complete => break,
48            }
49        }
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56    use crate::client::types as client_types;
57    use crate::mode_management::Defect;
58    use crate::mode_management::phy_manager::{CreateClientIfacesReason, PhyManagerError};
59    use crate::mode_management::recovery::RecoverySummary;
60    use assert_matches::assert_matches;
61    use async_trait::async_trait;
62    use fidl::endpoints::create_proxy;
63    use fuchsia_async as fasync;
64    use futures::task::Poll;
65    use std::collections::HashMap;
66    use std::pin::pin;
67    use std::unimplemented;
68
69    #[derive(Debug)]
70    struct StubPhyManager(Option<MacAddr>);
71
72    impl StubPhyManager {
73        fn new() -> Self {
74            StubPhyManager(None)
75        }
76    }
77
78    #[async_trait(?Send)]
79    impl PhyManagerApi for StubPhyManager {
80        async fn add_phy(&mut self, _phy_id: u16) -> Result<(), PhyManagerError> {
81            unimplemented!();
82        }
83
84        fn remove_phy(&mut self, _phy_id: u16) {
85            unimplemented!();
86        }
87
88        async fn on_iface_added(&mut self, _iface_id: u16) -> Result<(), PhyManagerError> {
89            unimplemented!();
90        }
91
92        fn on_iface_removed(&mut self, _iface_id: u16) {
93            unimplemented!();
94        }
95
96        async fn create_all_client_ifaces(
97            &mut self,
98            _reason: CreateClientIfacesReason,
99        ) -> HashMap<u16, Result<Vec<u16>, PhyManagerError>> {
100            unimplemented!();
101        }
102
103        fn client_connections_enabled(&self) -> bool {
104            unimplemented!();
105        }
106
107        async fn destroy_all_client_ifaces(&mut self) -> Result<(), PhyManagerError> {
108            unimplemented!();
109        }
110
111        fn get_client(&mut self) -> Option<u16> {
112            unimplemented!();
113        }
114
115        async fn create_or_get_ap_iface(&mut self) -> Result<Option<u16>, PhyManagerError> {
116            unimplemented!();
117        }
118
119        async fn destroy_ap_iface(&mut self, _iface_id: u16) -> Result<(), PhyManagerError> {
120            unimplemented!();
121        }
122
123        async fn destroy_all_ap_ifaces(&mut self) -> Result<(), PhyManagerError> {
124            unimplemented!();
125        }
126
127        fn suggest_ap_mac(&mut self, mac: MacAddr) {
128            self.0 = Some(mac);
129        }
130
131        fn get_phy_ids(&self) -> Vec<u16> {
132            unimplemented!();
133        }
134
135        fn log_phy_add_failure(&mut self) {
136            unimplemented!();
137        }
138
139        async fn set_country_code(
140            &mut self,
141            _country_code: Option<client_types::CountryCode>,
142        ) -> Result<(), PhyManagerError> {
143            unimplemented!();
144        }
145
146        fn record_defect(&mut self, _defect: Defect) {
147            unimplemented!();
148        }
149
150        async fn perform_recovery(&mut self, _summary: RecoverySummary) {
151            unimplemented!();
152        }
153    }
154
155    #[fuchsia::test]
156    fn test_suggest_mac_succeeds() {
157        let mut exec = fasync::TestExecutor::new();
158
159        // Set up the DeprecatedConfigurator.
160        let phy_manager = Arc::new(Mutex::new(StubPhyManager::new()));
161        let configurator = DeprecatedConfigurator::new(phy_manager.clone());
162
163        // Create the request stream and proxy.
164        let (configurator_proxy, remote) =
165            create_proxy::<fidl_deprecated::DeprecatedConfiguratorMarker>();
166        let stream = remote.into_stream();
167
168        // Kick off the serve loop and wait for it to stall out waiting for requests.
169        let fut = configurator.serve_deprecated_configuration(stream);
170        let mut fut = pin!(fut);
171        assert!(exec.run_until_stalled(&mut fut).is_pending());
172
173        // Issue a request to set the MAC address.
174        let octets = [1, 2, 3, 4, 5, 6];
175        let mac = fidl_fuchsia_net::MacAddress { octets };
176        let mut suggest_fut = configurator_proxy.suggest_access_point_mac_address(&mac);
177        assert!(exec.run_until_stalled(&mut fut).is_pending());
178
179        // Verify that the MAC has been set on the PhyManager
180        let lock_fut = phy_manager.lock();
181        let mut lock_fut = pin!(lock_fut);
182        let phy_manager = assert_matches!(
183            exec.run_until_stalled(&mut lock_fut),
184            Poll::Ready(phy_manager) => {
185                phy_manager
186            }
187        );
188        let expected_mac = MacAddr::from(octets);
189        assert_eq!(Some(expected_mac), phy_manager.0);
190
191        assert_matches!(exec.run_until_stalled(&mut suggest_fut), Poll::Ready(Ok(Ok(()))));
192    }
193}