Skip to main content

wlancfg_lib/client/
mod.rs

1// Copyright 2021 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
5//! Serves Client policy services.
6use crate::client::types as client_types;
7use crate::config_management::{
8    self, Credential, NetworkConfigError, NetworkIdentifier, SaveError, SavedNetworksManagerApi,
9};
10use crate::mode_management::iface_manager_api::{ConnectAttemptRequest, IfaceManagerApi};
11use crate::telemetry::{TelemetryEvent, TelemetrySender};
12use crate::util::listener;
13use fidl::epitaph::ChannelEpitaphExt;
14use fidl_fuchsia_wlan_policy as fidl_policy;
15use futures::lock::{Mutex, MutexGuard};
16use futures::prelude::*;
17use futures::select;
18use futures::stream::FuturesUnordered;
19use log::{error, info, warn};
20use std::sync::Arc;
21
22pub mod connection_selection;
23pub mod roaming;
24pub mod scan;
25pub mod state_machine;
26pub mod types;
27
28/// Max number of network configs that we will send at once through the network config iterator
29/// in get_saved_networks. This depends on the maximum size of a FIDL NetworkConfig, so it may
30/// need to change if a FIDL NetworkConfig or FIDL Credential changes.
31const MAX_CONFIGS_PER_RESPONSE: usize = 100;
32
33// This number was chosen arbitrarily.
34const MAX_CONCURRENT_LISTENERS: usize = 1000;
35
36type ClientRequests = fidl::endpoints::ServerEnd<fidl_policy::ClientControllerMarker>;
37type SavedNetworksPtr = Arc<dyn SavedNetworksManagerApi>;
38
39/// Serves the ClientProvider protocol.
40/// Only one ClientController can be active. Additional requests to register ClientControllers
41/// will result in their channel being immediately closed.
42pub async fn serve_provider_requests(
43    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
44    update_sender: listener::ClientListenerMessageSender,
45    saved_networks: SavedNetworksPtr,
46    scan_requester: Arc<dyn scan::ScanRequestApi>,
47    client_provider_lock: Arc<Mutex<()>>,
48    mut requests: fidl_policy::ClientProviderRequestStream,
49    telemetry_sender: TelemetrySender,
50    power_manager: Arc<dyn wlan_power_manager::PowerManager>,
51) {
52    let mut controller_reqs = FuturesUnordered::new();
53
54    loop {
55        select! {
56            // Progress controller requests.
57            _ = controller_reqs.select_next_some() => (),
58            // Process provider requests.
59            req = requests.select_next_some() => if let Ok(req) = req {
60                // If another component already has a client provider, rejest the request.
61                if let Some(client_provider_guard) = client_provider_lock.try_lock() {
62                    let fut = handle_provider_request(
63                        Arc::clone(&iface_manager),
64                        update_sender.clone(),
65                        saved_networks.clone(),
66                        scan_requester.clone(),
67                        client_provider_guard,
68                        req,
69                        telemetry_sender.clone(),
70                        power_manager.clone(),
71                    );
72                    controller_reqs.push(fut);
73                } else if let Err(e) = reject_provider_request(req) {
74                    error!("error sending rejection epitaph: {:?}", e);
75                }
76            },
77            complete => break,
78        }
79    }
80}
81
82/// Serves the ClientListener protocol.
83pub async fn serve_listener_requests(
84    update_sender: listener::ClientListenerMessageSender,
85    requests: fidl_policy::ClientListenerRequestStream,
86) {
87    let serve_fut = requests
88        .try_for_each_concurrent(MAX_CONCURRENT_LISTENERS, |req| {
89            handle_listener_request(update_sender.clone(), req)
90        })
91        .unwrap_or_else(|e| error!("error serving Client Listener API: {}", e));
92    serve_fut.await;
93}
94
95/// Handle inbound requests to acquire a new ClientController.
96async fn handle_provider_request(
97    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
98    update_sender: listener::ClientListenerMessageSender,
99    saved_networks: SavedNetworksPtr,
100    scan_requester: Arc<dyn scan::ScanRequestApi>,
101    client_provider_guard: MutexGuard<'_, ()>,
102    req: fidl_policy::ClientProviderRequest,
103    telemetry_sender: TelemetrySender,
104    power_manager: Arc<dyn wlan_power_manager::PowerManager>,
105) -> Result<(), fidl::Error> {
106    match req {
107        fidl_policy::ClientProviderRequest::GetController { requests, updates, .. } => {
108            register_listener(update_sender, updates.into_proxy());
109            handle_client_requests(
110                iface_manager,
111                scan_requester,
112                saved_networks,
113                client_provider_guard,
114                requests,
115                telemetry_sender,
116                power_manager,
117            )
118            .await?;
119            Ok(())
120        }
121    }
122}
123
124/// Logs a message for an incoming ClientControllerRequest
125fn log_client_request(request: &fidl_policy::ClientControllerRequest) {
126    info!(
127        "Received policy client request {}",
128        match request {
129            fidl_policy::ClientControllerRequest::Connect { .. } => "Connect",
130            fidl_policy::ClientControllerRequest::StartClientConnections { .. } =>
131                "StartClientConnections",
132            fidl_policy::ClientControllerRequest::StopClientConnections { .. } =>
133                "StopClientConnections",
134            fidl_policy::ClientControllerRequest::ScanForNetworks { .. } => "ScanForNetworks",
135            fidl_policy::ClientControllerRequest::SaveNetwork { .. } => "SaveNetwork",
136            fidl_policy::ClientControllerRequest::RemoveNetwork { .. } => "RemoveNetwork",
137            fidl_policy::ClientControllerRequest::ForgetNetwork { .. } => "ForgetNetwork",
138            fidl_policy::ClientControllerRequest::GetSavedNetworks { .. } => "GetSavedNetworks",
139        }
140    );
141}
142
143/// Handles all incoming requests from a ClientController.
144async fn handle_client_requests(
145    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
146    scan_requester: Arc<dyn scan::ScanRequestApi>,
147    saved_networks: SavedNetworksPtr,
148    client_provider_guard: MutexGuard<'_, ()>,
149    requests: ClientRequests,
150    telemetry_sender: TelemetrySender,
151    power_manager: Arc<dyn wlan_power_manager::PowerManager>,
152) -> Result<(), fidl::Error> {
153    let mut request_stream = requests.into_stream();
154    while let Some(request) = request_stream.try_next().await? {
155        log_client_request(&request);
156        match request {
157            fidl_policy::ClientControllerRequest::Connect { id, responder, .. } => {
158                let _wake_lease = power_manager.take_wake_lease("wlancfg-client-connect").await;
159                let response = handle_client_request_connect(
160                    Arc::clone(&iface_manager),
161                    saved_networks.clone(),
162                    &id,
163                )
164                .await;
165                responder.send(response)?
166            }
167            fidl_policy::ClientControllerRequest::StartClientConnections { responder } => {
168                let _wake_lease =
169                    power_manager.take_wake_lease("wlancfg-client-start-connections").await;
170                telemetry_sender.send(TelemetryEvent::StartClientConnectionsRequest);
171                let response =
172                    handle_client_request_start_client_connections(iface_manager.clone()).await;
173                responder.send(response)?
174            }
175            fidl_policy::ClientControllerRequest::StopClientConnections { responder } => {
176                let _wake_lease =
177                    power_manager.take_wake_lease("wlancfg-client-stop-connections").await;
178                telemetry_sender.send(TelemetryEvent::StopClientConnectionsRequest);
179                let response =
180                    handle_client_request_stop_client_connections(iface_manager.clone()).await;
181                responder.send(response)?
182            }
183            fidl_policy::ClientControllerRequest::ScanForNetworks { iterator, .. } => {
184                let fut = handle_client_request_scan(
185                    scan_requester.clone(),
186                    saved_networks.clone(),
187                    telemetry_sender.clone(),
188                    power_manager.clone(),
189                    iterator,
190                );
191                // The scan handler is infallible and should not block handling of further request.
192                // Detach the future here so we continue responding to other requests.
193                fuchsia_async::Task::local(fut).detach();
194            }
195            fidl_policy::ClientControllerRequest::SaveNetwork { config, responder } => {
196                let _wake_lease =
197                    power_manager.take_wake_lease("wlancfg-client-save-network").await;
198                // If there is an error saving the network, log it and convert to a FIDL value.
199                let response = handle_client_request_save_network(
200                    saved_networks.clone(),
201                    config,
202                    Arc::clone(&iface_manager),
203                )
204                .await
205                .map_err(|e| {
206                    error!("Failed to save network: {:?}", e);
207                    fidl_policy::NetworkConfigChangeError::from(e)
208                });
209                responder.send(response)?;
210            }
211            fidl_policy::ClientControllerRequest::RemoveNetwork { config, responder } => {
212                let _wake_lease =
213                    power_manager.take_wake_lease("wlancfg-client-remove-network").await;
214                let id_opt = config.id;
215                let err = async {
216                    let id = id_opt.ok_or(NetworkConfigError::ConfigMissingId)?;
217                    handle_client_request_remove_network(
218                        saved_networks.clone(),
219                        id,
220                        iface_manager.clone(),
221                    )
222                    .await
223                }
224                .await
225                .map_err(|_| SaveError::GeneralError);
226
227                responder.send(err)?;
228            }
229            fidl_policy::ClientControllerRequest::ForgetNetwork { id, responder } => {
230                let _wake_lease =
231                    power_manager.take_wake_lease("wlancfg-client-remove-network").await;
232                let err = handle_client_request_remove_network(
233                    saved_networks.clone(),
234                    id,
235                    iface_manager.clone(),
236                )
237                .map_err(|_| SaveError::GeneralError)
238                .await;
239                responder.send(err)?;
240            }
241            fidl_policy::ClientControllerRequest::GetSavedNetworks { iterator, .. } => {
242                let _wake_lease =
243                    power_manager.take_wake_lease("wlancfg-client-get-saved-networks").await;
244                handle_client_request_get_networks(saved_networks.clone(), iterator).await?;
245            }
246        }
247    }
248    drop(client_provider_guard);
249    Ok(())
250}
251
252/// Attempts to issue a new connect request to the currently active Client.
253/// The network's configuration must have been stored before issuing a connect request.
254async fn handle_client_request_connect(
255    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
256    saved_networks: SavedNetworksPtr,
257    network: &fidl_policy::NetworkIdentifier,
258) -> fidl_policy::RequestStatus {
259    let network_config = match saved_networks
260        .lookup(&NetworkIdentifier::new(
261            client_types::Ssid::from_bytes_unchecked(network.ssid.clone()),
262            network.type_.into(),
263        ))
264        .await
265    {
266        Some(config) => config,
267        None => {
268            error!("Requested network not found in saved networks");
269            return fidl_policy::RequestStatus::RejectedNotSupported;
270        }
271    };
272
273    let network_id = fidl_policy::NetworkIdentifier {
274        ssid: network_config.ssid.into(),
275        type_: fidl_policy::SecurityType::from(network_config.security_type),
276    };
277    let connect_req = ConnectAttemptRequest::new(
278        network_id.into(),
279        network_config.credential,
280        client_types::ConnectReason::FidlConnectRequest,
281    );
282
283    let mut iface_manager = iface_manager.lock().await;
284    match iface_manager.connect(connect_req).await {
285        Ok(_) => fidl_policy::RequestStatus::Acknowledged,
286        Err(e) => {
287            error!("failed to connect: {:?}", e);
288            fidl_policy::RequestStatus::RejectedIncompatibleMode
289        }
290    }
291}
292
293async fn handle_client_request_scan(
294    scan_requester: Arc<dyn scan::ScanRequestApi>,
295    saved_networks: SavedNetworksPtr,
296    telemetry_sender: TelemetrySender,
297    power_manager: Arc<dyn wlan_power_manager::PowerManager>,
298    output_iterator: fidl::endpoints::ServerEnd<fidl_fuchsia_wlan_policy::ScanResultIteratorMarker>,
299) {
300    let _wake_lease = power_manager.take_wake_lease("wlancfg-client-scan").await;
301    let get_scan_results = async {
302        let passive_scan_results =
303            scan_requester.perform_scan(scan::ScanReason::ClientRequest, vec![], vec![]).await?;
304
305        let requested_active_scan_ssids: Vec<types::Ssid> =
306            config_management::select_high_probability_hidden_networks(
307                saved_networks.get_networks().await,
308            )
309            .drain(..)
310            .map(|id| id.ssid)
311            .collect();
312
313        info!(
314            "Completed passive scan for API request, {} likely-hidden networks to scan for.",
315            requested_active_scan_ssids.len()
316        );
317        telemetry_sender.send(TelemetryEvent::ActiveScanRequestedViaApi {
318            num_ssids_requested: requested_active_scan_ssids.len(),
319        });
320
321        if requested_active_scan_ssids.is_empty() {
322            Ok(passive_scan_results)
323        } else {
324            scan_requester
325                .perform_scan(scan::ScanReason::ClientRequest, requested_active_scan_ssids, vec![])
326                .await
327                .map(|mut scan_results| {
328                    scan_results.extend(passive_scan_results);
329                    scan_results
330                })
331        }
332    };
333
334    match get_scan_results.await {
335        Ok(results) => {
336            // Note: for now, we must always present WPA2/3 networks as WPA2 over our external
337            // interfaces (i.e. to FIDL consumers of scan results). See b/182209070 for more
338            // information.
339            let fidl_results = scan::scan_result_to_policy_scan_result(&results);
340            if let Err(e) = scan::send_scan_results_over_fidl(output_iterator, &fidl_results).await
341            {
342                warn!("Failed to send scan results to requester: {:?}", e);
343            }
344        }
345        Err(e) => {
346            if let Err(e) = scan::send_scan_error_over_fidl(output_iterator, e).await {
347                warn!("Failed to send scan error to requester: {:?}", e);
348            }
349        }
350    }
351}
352
353/// This function handles requests to save a network by saving the network and sending back to the
354/// controller whether or not we successfully saved the network. There could be a FIDL error in
355/// sending the response.
356async fn handle_client_request_save_network(
357    saved_networks: SavedNetworksPtr,
358    network_config: fidl_policy::NetworkConfig,
359    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
360) -> Result<(), NetworkConfigError> {
361    // The FIDL network config fields are defined as Options, and we consider it an error if either
362    // field is missing (ie None) here.
363    let net_id: client_types::NetworkIdentifier =
364        network_config.id.ok_or(NetworkConfigError::ConfigMissingId)?.into();
365    let credential = Credential::try_from(
366        network_config.credential.ok_or(NetworkConfigError::ConfigMissingCredential)?,
367    )?;
368    let evicted_config = saved_networks.store(net_id.clone(), credential.clone()).await?;
369
370    // If a config was removed, disconnect from that network.
371    let mut iface_manager = iface_manager.lock().await;
372    if let Some(config) = evicted_config {
373        let net_id = client_types::NetworkIdentifier {
374            ssid: config.ssid,
375            security_type: config.security_type,
376        };
377        match iface_manager
378            .disconnect(net_id, client_types::DisconnectReason::NetworkConfigUpdated)
379            .await
380        {
381            Ok(()) => {}
382            Err(e) => error!("failed to disconnect from network: {}", e),
383        }
384    }
385
386    // Attempt to connect to the new network if there is an idle client interface.
387    let connect_req = ConnectAttemptRequest::new(
388        net_id,
389        credential,
390        client_types::ConnectReason::NewSavedNetworkAutoconnect,
391    );
392    match iface_manager.has_idle_client().await {
393        Ok(true) => {
394            info!("Idle interface available, will attempt connection to new saved network");
395            let _ = iface_manager.connect(connect_req).await;
396        }
397        Ok(false) => {}
398        Err(e) => {
399            error!("Unable to query idle client state while saving network: {:?}", e);
400        }
401    }
402
403    Ok(())
404}
405
406/// Will remove the specified network and respond to the remove network request with a network
407/// config change error if an error occurs while trying to remove the network.
408async fn handle_client_request_remove_network(
409    saved_networks: SavedNetworksPtr,
410    network_id: fidl_policy::NetworkIdentifier,
411    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
412) -> Result<(), NetworkConfigError> {
413    let net_id = NetworkIdentifier::from(network_id);
414    if saved_networks.remove(net_id.clone()).await? {
415        match iface_manager
416            .lock()
417            .await
418            .disconnect(net_id, client_types::DisconnectReason::NetworkUnsaved)
419            .await
420        {
421            Ok(()) => {}
422            Err(e) => error!("failed to disconnect from network: {}", e),
423        }
424    }
425    Ok(())
426}
427
428async fn handle_client_request_get_networks(
429    saved_networks: SavedNetworksPtr,
430    iterator: fidl::endpoints::ServerEnd<fidl_policy::NetworkConfigIteratorMarker>,
431) -> Result<(), fidl::Error> {
432    // make sufficiently small batches of networks to send and convert configs to FIDL values
433    let network_configs = saved_networks.get_networks().await;
434    let chunks = network_configs.chunks(MAX_CONFIGS_PER_RESPONSE);
435    let fidl_chunks = chunks.into_iter().map(|chunk| {
436        chunk
437            .iter()
438            .map(fidl_policy::NetworkConfig::from)
439            .collect::<Vec<fidl_policy::NetworkConfig>>()
440    });
441    let mut stream = iterator.into_stream();
442    for chunk in fidl_chunks {
443        send_next_chunk(&mut stream, chunk).await?;
444    }
445    send_next_chunk(&mut stream, vec![]).await
446}
447
448/// Send a chunk of saved networks to the specified FIDL iterator
449async fn send_next_chunk(
450    stream: &mut fidl_policy::NetworkConfigIteratorRequestStream,
451    chunk: Vec<fidl_policy::NetworkConfig>,
452) -> Result<(), fidl::Error> {
453    if let Some(req) = stream.try_next().await? {
454        let fidl_policy::NetworkConfigIteratorRequest::GetNext { responder } = req;
455        responder.send(&chunk)
456    } else {
457        // This will happen if the iterator request stream was closed and we expected to send
458        // another response.
459        // TODO(https://fxbug.dev/42121602) Test this error path
460        info!("Info: peer closed channel for network config results unexpectedly");
461        Ok(())
462    }
463}
464
465/// Handle inbound requests to register an additional ClientStateUpdates listener.
466async fn handle_listener_request(
467    update_sender: listener::ClientListenerMessageSender,
468    req: fidl_policy::ClientListenerRequest,
469) -> Result<(), fidl::Error> {
470    match req {
471        fidl_policy::ClientListenerRequest::GetListener { updates, .. } => {
472            register_listener(update_sender, updates.into_proxy());
473            Ok(())
474        }
475    }
476}
477
478/// Registers a new update listener.
479/// The client's current state will be send to the newly added listener immediately.
480fn register_listener(
481    update_sender: listener::ClientListenerMessageSender,
482    listener: fidl_policy::ClientStateUpdatesProxy,
483) {
484    let _ignored = update_sender.unbounded_send(listener::Message::NewListener(listener));
485}
486
487/// Rejects a ClientProvider request by sending a corresponding Epitaph via the |requests| and
488/// |updates| channels.
489fn reject_provider_request(req: fidl_policy::ClientProviderRequest) -> Result<(), fidl::Error> {
490    match req {
491        fidl_policy::ClientProviderRequest::GetController { requests, updates, .. } => {
492            info!("Rejecting new client controller request because a controller is in use");
493            requests.into_channel().close_with_epitaph(zx::Status::ALREADY_BOUND)?;
494            updates.into_channel().close_with_epitaph(zx::Status::ALREADY_BOUND)?;
495            Ok(())
496        }
497    }
498}
499
500/// Allows client operations to be performed.
501async fn handle_client_request_start_client_connections(
502    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
503) -> fidl_policy::RequestStatus {
504    let mut iface_manager = iface_manager.lock().await;
505    if let Err(e) = iface_manager.start_client_connections().await {
506        warn!("encountered an error while starting client connections: {:?}", e);
507    }
508    fidl_policy::RequestStatus::Acknowledged
509}
510
511/// Stops all active client connections and disallows future client operations.
512async fn handle_client_request_stop_client_connections(
513    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
514) -> fidl_policy::RequestStatus {
515    let mut iface_manager = iface_manager.lock().await;
516    if let Err(e) = iface_manager
517        .stop_client_connections(client_types::DisconnectReason::FidlStopClientConnectionsRequest)
518        .await
519    {
520        warn!("encountered an error while stopping client connections: {:?}", e);
521    }
522    fidl_policy::RequestStatus::Acknowledged
523}
524
525#[cfg(test)]
526mod tests {
527    use super::*;
528    use crate::access_point::state_machine as ap_fsm;
529    use crate::config_management::{NetworkConfig, SecurityType, WPA_PSK_BYTE_LEN};
530    use crate::mode_management::iface_manager_api::SmeForScan;
531    use crate::util::testing::fakes::{FakeSavedNetworksManager, FakeScanRequester};
532    use crate::util::testing::{
533        generate_random_fidl_network_config, generate_random_fidl_network_config_with_ssid,
534    };
535    use anyhow::{Error, format_err};
536    use assert_matches::assert_matches;
537    use async_trait::async_trait;
538    use fidl::endpoints::{Proxy, create_proxy, create_request_stream};
539    use fuchsia_async as fasync;
540    use futures::channel::{mpsc, oneshot};
541    use futures::task::Poll;
542    use std::pin::pin;
543    use test_case::test_case;
544
545    /// Only used to tell us what disconnect request was given to the IfaceManager so that we
546    /// don't need to worry about the implementation logic in the FakeIfaceManager.
547    #[derive(Debug)]
548    enum IfaceManagerRequest {
549        Disconnect(client_types::NetworkIdentifier, client_types::DisconnectReason),
550    }
551
552    struct FakeIfaceManager {
553        pub sme_proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
554        pub disconnected_ifaces: Vec<u16>,
555        command_sender: mpsc::Sender<IfaceManagerRequest>,
556        start_client_connections_succeeds: bool,
557        stop_client_connections_succeeds: bool,
558    }
559
560    impl FakeIfaceManager {
561        pub fn new(
562            proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
563            command_sender: mpsc::Sender<IfaceManagerRequest>,
564        ) -> Self {
565            FakeIfaceManager {
566                sme_proxy: proxy,
567                disconnected_ifaces: Vec::new(),
568                command_sender,
569                start_client_connections_succeeds: true,
570                stop_client_connections_succeeds: true,
571            }
572        }
573    }
574
575    #[async_trait(?Send)]
576    impl IfaceManagerApi for FakeIfaceManager {
577        async fn disconnect(
578            &mut self,
579            network_id: client_types::NetworkIdentifier,
580            reason: client_types::DisconnectReason,
581        ) -> Result<(), Error> {
582            self.command_sender
583                .try_send(IfaceManagerRequest::Disconnect(network_id, reason))
584                .map_err(|e| {
585                    error!(
586                        "Failed to send disconnect: commands_sender's receiver may have
587                        been dropped. FakeIfaceManager should be created manually with a sender
588                        assigned: {:?}",
589                        e
590                    );
591                    format_err!("failed to send disconnect: {:?}", e)
592                })
593        }
594
595        async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
596            let _ = self.disconnected_ifaces.pop();
597            Ok(())
598        }
599
600        async fn record_idle_client(&mut self, iface_id: u16) -> Result<(), Error> {
601            self.disconnected_ifaces.push(iface_id);
602            Ok(())
603        }
604
605        async fn has_idle_client(&mut self) -> Result<bool, Error> {
606            Ok(!self.disconnected_ifaces.is_empty())
607        }
608
609        async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
610            unimplemented!()
611        }
612
613        async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
614            unimplemented!()
615        }
616
617        async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
618            let (defect_sender, _) = mpsc::channel(100);
619            Ok(SmeForScan::new(self.sme_proxy.clone(), 0, defect_sender))
620        }
621
622        async fn stop_client_connections(
623            &mut self,
624            _reason: client_types::DisconnectReason,
625        ) -> Result<(), Error> {
626            if self.stop_client_connections_succeeds {
627                Ok(())
628            } else {
629                Err(format_err!("stop client connections failed"))
630            }
631        }
632
633        async fn start_client_connections(&mut self) -> Result<(), Error> {
634            if self.start_client_connections_succeeds {
635                Ok(())
636            } else {
637                Err(format_err!("start client connections failed"))
638            }
639        }
640
641        async fn start_ap(
642            &mut self,
643            _config: ap_fsm::ApConfig,
644        ) -> Result<oneshot::Receiver<()>, Error> {
645            unimplemented!()
646        }
647
648        async fn stop_ap(&mut self, _ssid: types::Ssid, _password: Vec<u8>) -> Result<(), Error> {
649            unimplemented!()
650        }
651
652        async fn stop_all_aps(&mut self) -> Result<(), Error> {
653            unimplemented!()
654        }
655
656        async fn set_country(
657            &mut self,
658            _country_code: Option<types::CountryCode>,
659        ) -> Result<(), Error> {
660            unimplemented!()
661        }
662    }
663
664    /// Requests a new ClientController from the given ClientProvider.
665    fn request_controller(
666        provider: &fidl_policy::ClientProviderProxy,
667    ) -> (fidl_policy::ClientControllerProxy, fidl_policy::ClientStateUpdatesRequestStream) {
668        let (controller, requests) = create_proxy::<fidl_policy::ClientControllerMarker>();
669        let (update_sink, update_stream) =
670            create_request_stream::<fidl_policy::ClientStateUpdatesMarker>();
671        provider.get_controller(requests, update_sink).expect("error getting controller");
672        (controller, update_stream)
673    }
674
675    struct TestValues {
676        saved_networks: SavedNetworksPtr,
677        net_id_open: fidl_policy::NetworkIdentifier,
678        net_id_wpa2_w_password: fidl_policy::NetworkIdentifier,
679        net_id_wpa2_w_psk: fidl_policy::NetworkIdentifier,
680        provider: fidl_policy::ClientProviderProxy,
681        requests: fidl_policy::ClientProviderRequestStream,
682        iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
683        iface_mgr_req_recvr: mpsc::Receiver<IfaceManagerRequest>,
684        scan_requester: Arc<FakeScanRequester>,
685        update_sender: mpsc::UnboundedSender<listener::ClientListenerMessage>,
686        listener_updates: mpsc::UnboundedReceiver<listener::ClientListenerMessage>,
687        client_provider_lock: Arc<Mutex<()>>,
688        telemetry_sender: TelemetrySender,
689        telemetry_receiver: mpsc::Receiver<TelemetryEvent>,
690        power_manager: Arc<wlan_power_manager_testing::TestPowerManager>,
691    }
692
693    // setup channels and proxies needed for the tests to use use the Client Provider and
694    // Client Controller APIs in tests. The stash id should be the test name so that each
695    // test will have a unique persistent store behind it.
696    fn test_setup() -> TestValues {
697        let net_id_open = fidl_policy::NetworkIdentifier {
698            ssid: "foobar".to_string().into_bytes(),
699            type_: fidl_policy::SecurityType::None,
700        };
701        let net_id_wpa2_w_password = fidl_policy::NetworkIdentifier {
702            ssid: b"foobar-wpa2".to_vec(),
703            type_: fidl_policy::SecurityType::Wpa2,
704        };
705        let net_id_wpa2_w_psk = fidl_policy::NetworkIdentifier {
706            ssid: b"foobar-psk".to_vec(),
707            type_: fidl_policy::SecurityType::Wpa2,
708        };
709
710        let presaved_default_configs = vec![
711            fidl_policy::NetworkConfig {
712                id: Some(net_id_open.clone()),
713                credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
714                ..Default::default()
715            },
716            fidl_policy::NetworkConfig {
717                id: Some(net_id_wpa2_w_password.clone()),
718                credential: Some(fidl_policy::Credential::Password(b"foobar-password".to_vec())),
719                ..Default::default()
720            },
721            fidl_policy::NetworkConfig {
722                id: Some(net_id_wpa2_w_psk.clone()),
723                credential: Some(fidl_policy::Credential::Psk([64; WPA_PSK_BYTE_LEN].to_vec())),
724                ..Default::default()
725            },
726        ];
727        let saved_networks =
728            Arc::new(FakeSavedNetworksManager::new_with_saved_networks(presaved_default_configs));
729        let (telemetry_sender, telemetry_receiver) = mpsc::channel::<TelemetryEvent>(100);
730        let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>();
731        let requests = requests.into_stream();
732
733        let (proxy, _server) = create_proxy::<fidl_fuchsia_wlan_sme::ClientSmeMarker>();
734        let (req_sender, iface_mgr_req_recvr) = mpsc::channel(1);
735        let iface_manager = FakeIfaceManager::new(proxy.clone(), req_sender);
736        let iface_manager = Arc::new(Mutex::new(iface_manager));
737        let scan_requester = Arc::new(FakeScanRequester::new());
738
739        let (update_sender, listener_updates) = mpsc::unbounded();
740        let power_manager = Arc::new(wlan_power_manager_testing::TestPowerManager::new());
741
742        TestValues {
743            saved_networks,
744            net_id_open,
745            net_id_wpa2_w_password,
746            net_id_wpa2_w_psk,
747            provider,
748            requests,
749            iface_manager,
750            iface_mgr_req_recvr,
751            scan_requester,
752            update_sender,
753            listener_updates,
754            client_provider_lock: Arc::new(Mutex::new(())),
755            telemetry_sender: TelemetrySender::new(telemetry_sender),
756            telemetry_receiver,
757            power_manager,
758        }
759    }
760
761    #[fuchsia::test]
762    fn connect_request_unknown_network() {
763        let ssid = client_types::Ssid::try_from("foobar-unknown").unwrap();
764        let mut exec = fasync::TestExecutor::new();
765        let test_values = test_setup();
766        let serve_fut = serve_provider_requests(
767            test_values.iface_manager,
768            test_values.update_sender,
769            Arc::clone(&test_values.saved_networks),
770            test_values.scan_requester,
771            test_values.client_provider_lock,
772            test_values.requests,
773            test_values.telemetry_sender,
774            test_values.power_manager.clone(),
775        );
776        let mut serve_fut = pin!(serve_fut);
777
778        // No request has been sent yet. Future should be idle.
779        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
780
781        // Request a new controller.
782        let (controller, _) = request_controller(&test_values.provider);
783        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
784
785        // Issue connect request.
786        let connect_fut = controller.connect(&fidl_policy::NetworkIdentifier {
787            ssid: ssid.to_vec(),
788            type_: fidl_policy::SecurityType::None,
789        });
790        let mut connect_fut = pin!(connect_fut);
791
792        // Process connect request and verify connect response.
793        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
794
795        assert_matches!(
796            exec.run_until_stalled(&mut connect_fut),
797            Poll::Ready(Ok(fidl_policy::RequestStatus::RejectedNotSupported))
798        );
799
800        // Unknown network should not have been saved by saved networks manager
801        // since we did not successfully connect.
802        let id = NetworkIdentifier::new(ssid, SecurityType::None);
803        let lookup_fut = test_values.saved_networks.lookup(&id);
804        assert!(exec.run_singlethreaded(lookup_fut).is_none());
805    }
806
807    #[fuchsia::test]
808    fn connect_request_open_network() {
809        let mut exec = fasync::TestExecutor::new();
810
811        let test_values = test_setup();
812        let serve_fut = serve_provider_requests(
813            test_values.iface_manager,
814            test_values.update_sender,
815            Arc::clone(&test_values.saved_networks),
816            test_values.scan_requester,
817            test_values.client_provider_lock,
818            test_values.requests,
819            test_values.telemetry_sender,
820            test_values.power_manager.clone(),
821        );
822        let mut serve_fut = pin!(serve_fut);
823
824        // No request has been sent yet. Future should be idle.
825        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
826
827        // Request a new controller.
828        let (controller, _update_stream) = request_controller(&test_values.provider);
829        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
830
831        // Issue connect request.
832        let connect_fut = controller.connect(&test_values.net_id_open);
833        let mut connect_fut = pin!(connect_fut);
834
835        // Process connect request and verify connect response.
836        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
837
838        // Verify that the connect call is acknowledged.
839        assert_matches!(
840            exec.run_until_stalled(&mut connect_fut),
841            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
842        );
843    }
844
845    #[fuchsia::test]
846    fn connect_request_protected_network() {
847        let mut exec = fasync::TestExecutor::new();
848
849        let test_values = test_setup();
850        let serve_fut = serve_provider_requests(
851            test_values.iface_manager,
852            test_values.update_sender,
853            Arc::clone(&test_values.saved_networks),
854            test_values.scan_requester,
855            test_values.client_provider_lock,
856            test_values.requests,
857            test_values.telemetry_sender,
858            test_values.power_manager.clone(),
859        );
860        let mut serve_fut = pin!(serve_fut);
861
862        // No request has been sent yet. Future should be idle.
863        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
864
865        // Request a new controller.
866        let (controller, _update_stream) = request_controller(&test_values.provider);
867        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
868
869        // Issue connect request.
870        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_password);
871        let mut connect_fut = pin!(connect_fut);
872
873        // Process connect request and verify connect response.
874        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
875
876        // Verify that the connect call is acknowledged.
877        assert_matches!(
878            exec.run_until_stalled(&mut connect_fut),
879            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
880        );
881    }
882
883    #[fuchsia::test]
884    fn connect_request_protected_psk_network() {
885        let mut exec = fasync::TestExecutor::new();
886
887        let test_values = test_setup();
888        let serve_fut = serve_provider_requests(
889            test_values.iface_manager,
890            test_values.update_sender,
891            Arc::clone(&test_values.saved_networks),
892            test_values.scan_requester,
893            test_values.client_provider_lock,
894            test_values.requests,
895            test_values.telemetry_sender,
896            test_values.power_manager.clone(),
897        );
898        let mut serve_fut = pin!(serve_fut);
899
900        // No request has been sent yet. Future should be idle.
901        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
902
903        // Request a new controller.
904        let (controller, _update_stream) = request_controller(&test_values.provider);
905        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
906
907        // Issue connect request.
908        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_psk);
909        let mut connect_fut = pin!(connect_fut);
910
911        // Process connect request and verify connect response.
912        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
913
914        // Verify that the connect call is acknowledged.
915        assert_matches!(
916            exec.run_until_stalled(&mut connect_fut),
917            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
918        );
919    }
920
921    #[fuchsia::test]
922    fn start_and_stop_client_connections() {
923        let mut exec = fasync::TestExecutor::new();
924        let mut test_values = test_setup();
925        let serve_fut = serve_provider_requests(
926            test_values.iface_manager,
927            test_values.update_sender,
928            test_values.saved_networks,
929            test_values.scan_requester,
930            test_values.client_provider_lock,
931            test_values.requests,
932            test_values.telemetry_sender,
933            test_values.power_manager.clone(),
934        );
935        let mut serve_fut = pin!(serve_fut);
936
937        // No request has been sent yet. Future should now be waiting for request.
938        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
939
940        // Request a new controller.
941        let (controller, _update_stream) = request_controller(&test_values.provider);
942        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
943
944        // Issue request to start client connections.
945        let start_fut = controller.start_client_connections();
946        let mut start_fut = pin!(start_fut);
947
948        // Request should be acknowledged.
949        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
950        assert_matches!(
951            exec.run_until_stalled(&mut start_fut),
952            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
953        );
954
955        // A message should be sent to telemetry.
956        assert_matches!(test_values.telemetry_receiver.try_recv(), Ok(event) => {
957            assert_matches!(event, TelemetryEvent::StartClientConnectionsRequest);
958        });
959
960        // Perform a connect operation.
961        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_password);
962        let mut connect_fut = pin!(connect_fut);
963
964        // Process connect request and verify connect response.
965        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
966
967        // Verify that the connect call is acknowledged.
968        assert_matches!(
969            exec.run_until_stalled(&mut connect_fut),
970            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
971        );
972
973        // The client state machine will immediately query for status.
974        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
975
976        // Issue request to stop client connections.
977        let stop_fut = controller.stop_client_connections();
978        let mut stop_fut = pin!(stop_fut);
979
980        // Run the serve future until it stalls and expect the client to disconnect
981        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
982
983        // A message should be sent to telemetry.
984        assert_matches!(test_values.telemetry_receiver.try_recv(), Ok(event) => {
985            assert_matches!(event, TelemetryEvent::StopClientConnectionsRequest);
986        });
987
988        // Request should be acknowledged.
989        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
990        assert_matches!(
991            exec.run_until_stalled(&mut stop_fut),
992            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
993        );
994    }
995
996    /// End-to-end test of the scan function, verifying that an incoming
997    /// FIDL scan request results in a scan in the SME, and that the results
998    /// make it back to the requester.
999    #[fuchsia::test]
1000    fn scan_end_to_end() {
1001        let mut exec = fasync::TestExecutor::new();
1002        let test_values = test_setup();
1003        let serve_fut = serve_provider_requests(
1004            test_values.iface_manager,
1005            test_values.update_sender,
1006            test_values.saved_networks,
1007            test_values.scan_requester.clone(),
1008            test_values.client_provider_lock,
1009            test_values.requests,
1010            test_values.telemetry_sender,
1011            test_values.power_manager.clone(),
1012        );
1013        let mut serve_fut = pin!(serve_fut);
1014
1015        // No request has been sent yet. Future should be idle.
1016        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1017
1018        // Request a new controller.
1019        let (controller, _update_stream) = request_controller(&test_values.provider);
1020        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1021
1022        // Issue a scan request.
1023        let (_iter, server) = fidl::endpoints::create_proxy();
1024        controller.scan_for_networks(server).expect("Failed to call scan for networks");
1025
1026        // Currently the FakeScanRequester will panic if a scan is requested and no results
1027        // are queued, so add something.
1028        exec.run_singlethreaded(test_values.scan_requester.add_scan_result(Ok(vec![])));
1029        // A second scan request for all the likely-hidden networks
1030        exec.run_singlethreaded(test_values.scan_requester.add_scan_result(Ok(vec![])));
1031
1032        // Process scan request and verify scan response.
1033        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1034
1035        // Check that a scan request was sent to the scan module, including an active scan for the
1036        // potentially-hidden networks.
1037        let expected_active_ssids = [
1038            test_values.net_id_wpa2_w_password,
1039            test_values.net_id_wpa2_w_psk,
1040            test_values.net_id_open,
1041        ]
1042        .iter()
1043        .map(|id| types::Ssid::from_bytes_unchecked(id.ssid.clone()))
1044        .collect();
1045        exec.run_singlethreaded(test_values.scan_requester.verify_scan_request((
1046            scan::ScanReason::ClientRequest,
1047            vec![],
1048            vec![],
1049        )));
1050        exec.run_singlethreaded(test_values.scan_requester.verify_scan_request((
1051            scan::ScanReason::ClientRequest,
1052            expected_active_ssids,
1053            vec![],
1054        )));
1055    }
1056
1057    #[fuchsia::test]
1058    fn save_network() {
1059        let mut exec = fasync::TestExecutor::new();
1060        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1061
1062        let mut test_values = test_setup();
1063        let serve_fut = serve_provider_requests(
1064            test_values.iface_manager,
1065            test_values.update_sender,
1066            saved_networks.clone(),
1067            test_values.scan_requester,
1068            test_values.client_provider_lock,
1069            test_values.requests,
1070            test_values.telemetry_sender,
1071            test_values.power_manager.clone(),
1072        );
1073        let mut serve_fut = pin!(serve_fut);
1074
1075        // No request has been sent yet. Future should be idle.
1076        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1077
1078        // Request a new controller.
1079        let (controller, _update_stream) = request_controller(&test_values.provider);
1080        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1081        assert_matches!(
1082            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1083            Poll::Ready(_)
1084        );
1085
1086        // Save some network
1087        let network_id = fidl_policy::NetworkIdentifier {
1088            ssid: b"foo".to_vec(),
1089            type_: fidl_policy::SecurityType::None,
1090        };
1091        let network_config = fidl_policy::NetworkConfig {
1092            id: Some(network_id.clone()),
1093            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1094            ..Default::default()
1095        };
1096        let mut save_fut = controller.save_network(&network_config);
1097
1098        // Run server_provider forward so that it will process the save network request
1099        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Pending);
1100        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1101
1102        // Check that the the response says we succeeded.
1103        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(Ok(()))));
1104
1105        // Check that the value was actually saved in the saved networks manager.
1106        let target_id = NetworkIdentifier::from(network_id);
1107        let target_config = NetworkConfig::new(target_id.clone(), Credential::None, false, None)
1108            .expect("Failed to create network config");
1109        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), Some(target_config));
1110    }
1111
1112    #[fuchsia::test]
1113    fn save_network_with_disconnected_iface() {
1114        let mut exec = fasync::TestExecutor::new();
1115        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1116
1117        let mut test_values = test_setup();
1118        let serve_fut = serve_provider_requests(
1119            test_values.iface_manager.clone(),
1120            test_values.update_sender,
1121            saved_networks.clone(),
1122            test_values.scan_requester,
1123            test_values.client_provider_lock,
1124            test_values.requests,
1125            test_values.telemetry_sender,
1126            test_values.power_manager.clone(),
1127        );
1128        let mut serve_fut = pin!(serve_fut);
1129
1130        // Setup the IfaceManager so that it has a disconnected iface.
1131        {
1132            let iface_manager = test_values.iface_manager.clone();
1133            let iface_manager_fut = iface_manager.lock();
1134            let mut iface_manager_fut = pin!(iface_manager_fut);
1135            let mut iface_manager = match exec.run_until_stalled(&mut iface_manager_fut) {
1136                Poll::Ready(iface_manager) => iface_manager,
1137                Poll::Pending => panic!("expected to acquire iface_manager lock"),
1138            };
1139            let record_idle_fut = iface_manager.record_idle_client(0);
1140            let mut record_idle_fut = pin!(record_idle_fut);
1141            assert_matches!(exec.run_until_stalled(&mut record_idle_fut), Poll::Ready(Ok(())));
1142        }
1143
1144        // No request has been sent yet. Future should be idle.
1145        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1146
1147        // Request a new controller.
1148        let (controller, _update_stream) = request_controller(&test_values.provider);
1149        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1150        assert_matches!(
1151            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1152            Poll::Ready(_)
1153        );
1154
1155        // Save some network
1156        let network_id = fidl_policy::NetworkIdentifier {
1157            ssid: b"foo".to_vec(),
1158            type_: fidl_policy::SecurityType::None,
1159        };
1160        let network_config = fidl_policy::NetworkConfig {
1161            id: Some(network_id.clone()),
1162            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1163            ..Default::default()
1164        };
1165        let mut save_fut = controller.save_network(&network_config);
1166
1167        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Pending);
1168        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1169
1170        // Check that the the response says we succeeded.
1171        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(result) => {
1172            let save_result = result.expect("Failed to get save network response");
1173            assert_eq!(save_result, Ok(()));
1174        });
1175
1176        // Check that the value was actually saved in the saved networks manager.
1177        let target_id = NetworkIdentifier::from(network_id);
1178        let target_config = NetworkConfig::new(target_id.clone(), Credential::None, false, None)
1179            .expect("Failed to create network config");
1180        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), Some(target_config));
1181    }
1182
1183    #[fuchsia::test]
1184    fn save_network_overwrite_disconnects() {
1185        let mut exec = fasync::TestExecutor::new();
1186        let mut test_values = test_setup();
1187        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1188
1189        let serve_fut = serve_provider_requests(
1190            test_values.iface_manager,
1191            test_values.update_sender,
1192            saved_networks.clone(),
1193            test_values.scan_requester,
1194            test_values.client_provider_lock,
1195            test_values.requests,
1196            test_values.telemetry_sender,
1197            test_values.power_manager.clone(),
1198        );
1199        let mut serve_fut = pin!(serve_fut);
1200
1201        // No request has been sent yet. Future should be idle.
1202        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1203
1204        // Request a new controller.
1205        let (controller, _update_stream) = request_controller(&test_values.provider);
1206        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1207        assert_matches!(
1208            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1209            Poll::Ready(_)
1210        );
1211
1212        // Save the network directly.
1213        let network_id = NetworkIdentifier::try_from("foo", SecurityType::Wpa2).unwrap();
1214        let credential = Credential::Password(b"password".to_vec());
1215        let save_fut = saved_networks.store(network_id.clone(), credential.clone());
1216        let mut save_fut = pin!(save_fut);
1217        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(None)));
1218
1219        // Save a network with the same identifier but a different password
1220        let network_config = fidl_policy::NetworkConfig {
1221            id: Some(fidl_policy::NetworkIdentifier::from(network_id.clone())),
1222            credential: Some(fidl_policy::Credential::Password(b"other-password".to_vec())),
1223            ..Default::default()
1224        };
1225        let mut save_fut = controller.save_network(&network_config);
1226
1227        // Process the remove request on the server side and handle requests to stash on the way.
1228        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1229        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1230
1231        // Check that the iface manager was asked to disconnect from some network
1232        assert_matches!(exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()), Poll::Ready(Some(IfaceManagerRequest::Disconnect(net_id, reason))) => {
1233            assert_eq!(net_id, network_id.clone());
1234            assert_eq!(reason, client_types::DisconnectReason::NetworkConfigUpdated);
1235        });
1236        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1237        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(Ok(()))));
1238    }
1239
1240    #[fuchsia::test]
1241    fn save_bad_network_should_fail() {
1242        let mut exec = fasync::TestExecutor::new();
1243        let mut saved_networks = FakeSavedNetworksManager::new();
1244        saved_networks.fail_all_stores = true;
1245        let saved_networks = Arc::new(saved_networks);
1246
1247        let mut test_values = test_setup();
1248        let serve_fut = serve_provider_requests(
1249            test_values.iface_manager,
1250            test_values.update_sender,
1251            saved_networks.clone(),
1252            test_values.scan_requester,
1253            test_values.client_provider_lock,
1254            test_values.requests,
1255            test_values.telemetry_sender,
1256            test_values.power_manager.clone(),
1257        );
1258        let mut serve_fut = pin!(serve_fut);
1259
1260        // No request has been sent yet. Future should be idle.
1261        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1262
1263        // Request a new controller.
1264        let (controller, _update_stream) = request_controller(&test_values.provider);
1265        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1266        assert_matches!(
1267            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1268            Poll::Ready(_)
1269        );
1270
1271        // Create a network config whose password is too short. FIDL network config does not
1272        // require valid fields unlike our crate define config. We should not be able to
1273        // successfully save this network through the API.
1274        let bad_network_id = fidl_policy::NetworkIdentifier {
1275            ssid: b"foo".to_vec(),
1276            type_: fidl_policy::SecurityType::Wpa2,
1277        };
1278        let network_config = fidl_policy::NetworkConfig {
1279            id: Some(bad_network_id.clone()),
1280            credential: Some(fidl_policy::Credential::Password(b"bar".to_vec())),
1281            ..Default::default()
1282        };
1283        // Attempt to save the config
1284        let mut save_fut = controller.save_network(&network_config);
1285
1286        // Run server_provider forward so that it will process the save network request
1287        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1288
1289        // Check that the the response says we failed to save the network.
1290        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(result) => {
1291            let error = result.expect("Failed to get save network response");
1292            assert_eq!(error, Err(fidl_policy::NetworkConfigChangeError::NetworkConfigWriteError));
1293        });
1294
1295        // Check that the value was was not saved in saved networks manager.
1296        let target_id = NetworkIdentifier::from(bad_network_id);
1297        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), None);
1298    }
1299
1300    #[fuchsia::test]
1301    fn test_remove_a_network() {
1302        let mut exec = fasync::TestExecutor::new();
1303        let mut test_values = test_setup();
1304
1305        let serve_fut = serve_provider_requests(
1306            test_values.iface_manager,
1307            test_values.update_sender,
1308            test_values.saved_networks.clone(),
1309            test_values.scan_requester,
1310            test_values.client_provider_lock,
1311            test_values.requests,
1312            test_values.telemetry_sender,
1313            test_values.power_manager.clone(),
1314        );
1315        let mut serve_fut = pin!(serve_fut);
1316
1317        // No request has been sent yet. Future should be idle.
1318        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1319
1320        // Request a new controller.
1321        let (controller, _update_stream) = request_controller(&test_values.provider);
1322        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1323        assert_matches!(
1324            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1325            Poll::Ready(_)
1326        );
1327
1328        // Request to a network that is saved
1329        let mut remove_fut = controller.forget_network(&test_values.net_id_open);
1330
1331        // Process the remove request on the server side and handle requests to stash on the way.
1332        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1333        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1334
1335        // Successfully removing a network should always request a disconnect from IfaceManager,
1336        // which will know whether we are connected to the network to disconnect from. This checks
1337        // that the IfaceManager is told to disconnect (if connected).
1338        assert_matches!(exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()), Poll::Ready(Some(IfaceManagerRequest::Disconnect(net_id, reason))) => {
1339            assert_eq!(net_id, test_values.net_id_open.clone().into());
1340            assert_eq!(reason, client_types::DisconnectReason::NetworkUnsaved);
1341        });
1342        assert_matches!(exec.run_until_stalled(&mut remove_fut), Poll::Ready(Ok(Ok(()))));
1343        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1344        assert!(
1345            exec.run_singlethreaded(
1346                test_values.saved_networks.lookup(&test_values.net_id_open.clone().into())
1347            )
1348            .is_none()
1349        );
1350
1351        // Removing a network that is not saved should not trigger a disconnect.
1352        let mut remove_fut = controller.forget_network(&test_values.net_id_open);
1353        // Process the remove request on the server side and handle requests to stash on the way.
1354        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1355        assert_matches!(
1356            exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()),
1357            Poll::Pending
1358        );
1359        assert_matches!(exec.run_until_stalled(&mut remove_fut), Poll::Ready(Ok(Ok(()))));
1360    }
1361
1362    #[fuchsia::test]
1363    fn test_get_saved_network() {
1364        let expected_configs = vec![generate_random_fidl_network_config()];
1365        let expected_num_sends = 1;
1366        run_get_saved_networks_test(expected_configs, expected_num_sends);
1367    }
1368
1369    #[fuchsia::test]
1370    fn test_get_saved_networks_multiple_chunks() {
1371        // Save MAX_CONFIGS_PER_RESPONSE + 1 configs so that get_saved_networks should respond with
1372        // 2 chunks of responses plus one response with an empty vector.
1373        let mut configs = vec![];
1374        for index in 0..MAX_CONFIGS_PER_RESPONSE + 1 {
1375            // Create unique network config to be saved.
1376            let ssid = format!("some_config{index}");
1377            let network_config = generate_random_fidl_network_config_with_ssid(&ssid);
1378            configs.push(network_config);
1379        }
1380
1381        let expected_num_sends = 2;
1382        run_get_saved_networks_test(configs, expected_num_sends);
1383    }
1384
1385    /// Test that get saved networks with the given saved networks
1386    /// test_id: the name of the test to create a unique persistent store for each test
1387    /// configs: list of FIDL NetworkConfigs that we expect to get from get_saved_networks and
1388    ///          and which are returned by SavedNetworksManager
1389    /// expected_num_sends: number of chunks of results we expect to get from get_saved_networks.
1390    ///     This is not counting the empty vector that signifies no more results.
1391    fn run_get_saved_networks_test(
1392        configs: Vec<fidl_policy::NetworkConfig>,
1393        expected_num_sends: usize,
1394    ) {
1395        let mut exec = fasync::TestExecutor::new();
1396        let saved_networks =
1397            Arc::new(FakeSavedNetworksManager::new_with_saved_networks(configs.clone()));
1398
1399        let test_values = test_setup();
1400        let serve_fut = serve_provider_requests(
1401            test_values.iface_manager,
1402            test_values.update_sender,
1403            saved_networks.clone(),
1404            test_values.scan_requester,
1405            test_values.client_provider_lock,
1406            test_values.requests,
1407            test_values.telemetry_sender,
1408            test_values.power_manager.clone(),
1409        );
1410        let mut serve_fut = pin!(serve_fut);
1411
1412        // No request has been sent yet. Future should be idle.
1413        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1414
1415        // Request a new controller.
1416        let (controller, _update_stream) = request_controller(&test_values.provider);
1417        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1418
1419        // Issue request to get the list of saved networks.
1420        let (iter, server) =
1421            fidl::endpoints::create_proxy::<fidl_policy::NetworkConfigIteratorMarker>();
1422        controller.get_saved_networks(server).expect("Failed to call get saved networks");
1423
1424        // Get responses from iterator. Expect to see the specified number of responses with
1425        // results plus one response of an empty vector indicating the end of results.
1426        let mut saved_networks_results = vec![];
1427        for i in 0..expected_num_sends {
1428            let get_saved_fut = iter.get_next();
1429            assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1430            let results = exec
1431                .run_singlethreaded(get_saved_fut)
1432                .expect("Failed to get next chunk of saved networks results");
1433            // the size of received chunk should either be max chunk size or whatever is left
1434            // to receive in the last chunk
1435            if i < expected_num_sends - 1 {
1436                assert_eq!(results.len(), MAX_CONFIGS_PER_RESPONSE);
1437            } else {
1438                assert_eq!(results.len(), configs.len() % MAX_CONFIGS_PER_RESPONSE);
1439            }
1440            saved_networks_results.extend(results);
1441        }
1442        let get_saved_end_fut = iter.get_next();
1443        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1444        let results = exec
1445            .run_singlethreaded(get_saved_end_fut)
1446            .expect("Failed to get next chunk of saved networks results");
1447        assert!(results.is_empty());
1448
1449        // check whether each network we saved is in the results and that nothing else is there.
1450        for network_config in &configs {
1451            assert!(saved_networks_results.contains(network_config));
1452        }
1453        assert_eq!(configs.len(), saved_networks_results.len());
1454    }
1455
1456    #[fuchsia::test]
1457    fn register_update_listener() {
1458        let mut exec = fasync::TestExecutor::new();
1459        let mut test_values = test_setup();
1460        let serve_fut = serve_provider_requests(
1461            test_values.iface_manager,
1462            test_values.update_sender,
1463            test_values.saved_networks,
1464            test_values.scan_requester,
1465            test_values.client_provider_lock,
1466            test_values.requests,
1467            test_values.telemetry_sender,
1468            test_values.power_manager.clone(),
1469        );
1470        let mut serve_fut = pin!(serve_fut);
1471
1472        // No request has been sent yet. Future should be idle.
1473        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1474
1475        // Request a new controller.
1476        let (_controller, _update_stream) = request_controller(&test_values.provider);
1477        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1478        assert_matches!(
1479            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1480            Poll::Ready(Some(listener::Message::NewListener(_)))
1481        );
1482    }
1483
1484    #[fuchsia::test]
1485    fn get_listener() {
1486        let mut exec = fasync::TestExecutor::new();
1487        let (listener, requests) = create_proxy::<fidl_policy::ClientListenerMarker>();
1488        let requests = requests.into_stream();
1489
1490        let (update_sender, mut listener_updates) = mpsc::unbounded();
1491        let serve_fut = serve_listener_requests(update_sender, requests);
1492        let mut serve_fut = pin!(serve_fut);
1493
1494        // No request has been sent yet. Future should be idle.
1495        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1496
1497        // Register listener.
1498        let (update_sink, _update_stream) =
1499            create_request_stream::<fidl_policy::ClientStateUpdatesMarker>();
1500        listener.get_listener(update_sink).expect("error getting listener");
1501
1502        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1503        assert_matches!(
1504            exec.run_until_stalled(&mut listener_updates.next()),
1505            Poll::Ready(Some(listener::Message::NewListener(_)))
1506        );
1507    }
1508
1509    #[fuchsia::test]
1510    fn multiple_controllers_write_attempt() {
1511        let mut exec = fasync::TestExecutor::new();
1512        let test_values = test_setup();
1513        let serve_fut = serve_provider_requests(
1514            test_values.iface_manager,
1515            test_values.update_sender,
1516            test_values.saved_networks,
1517            test_values.scan_requester,
1518            test_values.client_provider_lock,
1519            test_values.requests,
1520            test_values.telemetry_sender,
1521            test_values.power_manager.clone(),
1522        );
1523        let mut serve_fut = pin!(serve_fut);
1524
1525        // No request has been sent yet. Future should be idle.
1526        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1527
1528        // Request a controller.
1529        let (controller1, _) = request_controller(&test_values.provider);
1530        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1531
1532        // Request another controller.
1533        let (controller2, _) = request_controller(&test_values.provider);
1534        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1535
1536        // Ensure first controller is operable. Issue connect request.
1537        let connect_fut = controller1.connect(&test_values.net_id_open);
1538        let mut connect_fut = pin!(connect_fut);
1539
1540        // Process connect request from first controller. Verify success.
1541        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1542
1543        assert_matches!(
1544            exec.run_until_stalled(&mut connect_fut),
1545            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
1546        );
1547
1548        // Ensure second controller is not operable. Issue connect request.
1549        let connect_fut = controller2.connect(&test_values.net_id_open);
1550        let mut connect_fut = pin!(connect_fut);
1551
1552        // Process connect request from second controller. Verify failure.
1553        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1554        assert_matches!(
1555            exec.run_until_stalled(&mut connect_fut),
1556            Poll::Ready(Err(fidl::Error::ClientChannelClosed { epitaph, .. }))
1557                if epitaph == zx::Status::ALREADY_BOUND
1558        );
1559
1560        // Drop first controller. A new controller can now take control.
1561        drop(controller1);
1562        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1563
1564        // Request another controller.
1565        let (controller3, _) = request_controller(&test_values.provider);
1566        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1567
1568        // Ensure third controller is operable. Issue connect request.
1569        let connect_fut = controller3.connect(&test_values.net_id_open);
1570        let mut connect_fut = pin!(connect_fut);
1571
1572        // Process connect request from third controller. Verify success.
1573        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1574
1575        assert_matches!(
1576            exec.run_until_stalled(&mut connect_fut),
1577            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
1578        );
1579    }
1580
1581    #[fuchsia::test]
1582    fn multiple_controllers_epitaph() {
1583        let mut exec = fasync::TestExecutor::new();
1584        let test_values = test_setup();
1585        let serve_fut = serve_provider_requests(
1586            test_values.iface_manager,
1587            test_values.update_sender,
1588            test_values.saved_networks.clone(),
1589            test_values.scan_requester,
1590            test_values.client_provider_lock,
1591            test_values.requests,
1592            test_values.telemetry_sender,
1593            test_values.power_manager.clone(),
1594        );
1595        let mut serve_fut = pin!(serve_fut);
1596
1597        // No request has been sent yet. Future should be idle.
1598        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1599
1600        // Request a controller.
1601        let (_controller1, _) = request_controller(&test_values.provider);
1602        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1603
1604        // Request another controller.
1605        let (controller2, _) = request_controller(&test_values.provider);
1606        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1607
1608        // Verify Epitaph was received.
1609        let mut controller2_event_stream = controller2.take_event_stream();
1610        let controller2_event_fut = controller2_event_stream.next();
1611        let mut controller2_event_fut = pin!(controller2_event_fut);
1612        assert_matches!(
1613            exec.run_until_stalled(&mut controller2_event_fut),
1614            Poll::Ready(Some(Err(fidl::Error::ClientChannelClosed { epitaph, .. })))
1615                if epitaph == zx::Status::ALREADY_BOUND
1616        );
1617
1618        assert!(controller2.is_closed());
1619    }
1620
1621    struct FakeIfaceManagerNoIfaces {}
1622
1623    #[async_trait(?Send)]
1624    impl IfaceManagerApi for FakeIfaceManagerNoIfaces {
1625        async fn disconnect(
1626            &mut self,
1627            _network_id: client_types::NetworkIdentifier,
1628            _reason: client_types::DisconnectReason,
1629        ) -> Result<(), Error> {
1630            Err(format_err!("No ifaces"))
1631        }
1632
1633        async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
1634            Err(format_err!("No ifaces"))
1635        }
1636
1637        async fn record_idle_client(&mut self, _iface_id: u16) -> Result<(), Error> {
1638            unimplemented!()
1639        }
1640
1641        async fn has_idle_client(&mut self) -> Result<bool, Error> {
1642            unimplemented!()
1643        }
1644
1645        async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
1646            unimplemented!()
1647        }
1648
1649        async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
1650            unimplemented!()
1651        }
1652
1653        async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
1654            Err(format_err!("No ifaces"))
1655        }
1656
1657        async fn stop_client_connections(
1658            &mut self,
1659            _reason: client_types::DisconnectReason,
1660        ) -> Result<(), Error> {
1661            unimplemented!()
1662        }
1663
1664        async fn start_client_connections(&mut self) -> Result<(), Error> {
1665            unimplemented!()
1666        }
1667
1668        async fn start_ap(
1669            &mut self,
1670            _config: ap_fsm::ApConfig,
1671        ) -> Result<oneshot::Receiver<()>, Error> {
1672            unimplemented!()
1673        }
1674
1675        async fn stop_ap(&mut self, _ssid: types::Ssid, _password: Vec<u8>) -> Result<(), Error> {
1676            unimplemented!()
1677        }
1678
1679        async fn stop_all_aps(&mut self) -> Result<(), Error> {
1680            unimplemented!()
1681        }
1682
1683        async fn set_country(
1684            &mut self,
1685            _country_code: Option<types::CountryCode>,
1686        ) -> Result<(), Error> {
1687            unimplemented!()
1688        }
1689    }
1690
1691    #[fuchsia::test]
1692    fn no_client_interface() {
1693        let mut exec = fasync::TestExecutor::new();
1694        let test_values = test_setup();
1695
1696        let iface_manager = Arc::new(Mutex::new(FakeIfaceManagerNoIfaces {}));
1697
1698        let serve_fut = serve_provider_requests(
1699            iface_manager,
1700            test_values.update_sender,
1701            test_values.saved_networks,
1702            test_values.scan_requester,
1703            test_values.client_provider_lock,
1704            test_values.requests,
1705            test_values.telemetry_sender,
1706            test_values.power_manager.clone(),
1707        );
1708        let mut serve_fut = pin!(serve_fut);
1709
1710        // No request has been sent yet. Future should be idle.
1711        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1712
1713        // Request a controller.
1714        let (controller, _) = request_controller(&test_values.provider);
1715        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1716
1717        // Issue connect request.
1718        let connect_fut = controller.connect(&test_values.net_id_open);
1719        let mut connect_fut = pin!(connect_fut);
1720
1721        // Process connect request from first controller. Verify success.
1722        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1723        assert_matches!(
1724            exec.run_until_stalled(&mut connect_fut),
1725            Poll::Ready(Ok(fidl_policy::RequestStatus::RejectedIncompatibleMode))
1726        );
1727    }
1728
1729    // Gets a saved network config with a particular SSID, security type, and credential.
1730    // If there are more than one configs saved for the same SSID, security type, and credential,
1731    // the function will panic.
1732    async fn get_config(
1733        saved_networks: Arc<dyn SavedNetworksManagerApi>,
1734        id: NetworkIdentifier,
1735        cred: Credential,
1736    ) -> Option<NetworkConfig> {
1737        saved_networks.lookup(&id).await.filter(|cfg| cfg.credential == cred)
1738    }
1739
1740    #[fuchsia::test]
1741    async fn get_correct_config() {
1742        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1743        let network_id = NetworkIdentifier::try_from("foo", SecurityType::Wpa2).unwrap();
1744        let cfg = NetworkConfig::new(
1745            network_id.clone(),
1746            Credential::Password(b"password".to_vec()),
1747            false,
1748            None,
1749        )
1750        .expect("Failed to create network config");
1751
1752        assert!(
1753            saved_networks
1754                .store(network_id.clone(), Credential::Password(b"password".to_vec()))
1755                .await
1756                .expect("Failed to store network config")
1757                .is_none()
1758        );
1759
1760        assert_eq!(
1761            Some(cfg),
1762            get_config(
1763                saved_networks.clone(),
1764                network_id,
1765                Credential::Password(b"password".to_vec())
1766            )
1767            .await
1768        );
1769        assert_eq!(
1770            None,
1771            get_config(
1772                saved_networks.clone(),
1773                NetworkIdentifier::try_from("foo", SecurityType::Wpa2).unwrap(),
1774                Credential::Password(b"not-saved".to_vec())
1775            )
1776            .await
1777        );
1778    }
1779
1780    #[fuchsia::test]
1781    fn multiple_api_clients() {
1782        let mut exec = fasync::TestExecutor::new();
1783        let test_values = test_setup();
1784        let serve_fut = serve_provider_requests(
1785            test_values.iface_manager.clone(),
1786            test_values.update_sender.clone(),
1787            test_values.saved_networks.clone(),
1788            test_values.scan_requester.clone(),
1789            test_values.client_provider_lock.clone(),
1790            test_values.requests,
1791            test_values.telemetry_sender.clone(),
1792            test_values.power_manager.clone(),
1793        );
1794        let mut serve_fut = pin!(serve_fut);
1795
1796        // No request has been sent yet. Future should be idle.
1797        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1798
1799        // Request a controller.
1800        let (controller1, _) = request_controller(&test_values.provider);
1801        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1802
1803        // Create another client provider request stream and start serving it.  This is equivalent
1804        // to the behavior that occurs when a second client connects to the ClientProvider service.
1805        let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>();
1806        let requests = requests.into_stream();
1807
1808        let second_serve_fut = serve_provider_requests(
1809            test_values.iface_manager.clone(),
1810            test_values.update_sender.clone(),
1811            test_values.saved_networks.clone(),
1812            test_values.scan_requester,
1813            test_values.client_provider_lock.clone(),
1814            requests,
1815            test_values.telemetry_sender,
1816            test_values.power_manager.clone(),
1817        );
1818        let mut second_serve_fut = pin!(second_serve_fut);
1819
1820        // Request a client controller from the second instance of the service.
1821        let (controller2, _) = request_controller(&provider);
1822        assert_matches!(exec.run_until_stalled(&mut second_serve_fut), Poll::Pending);
1823
1824        // Verify Epitaph was received.
1825        let mut controller2_event_stream = controller2.take_event_stream();
1826        let controller2_event_fut = controller2_event_stream.next();
1827        let mut controller2_event_fut = pin!(controller2_event_fut);
1828        assert_matches!(
1829            exec.run_until_stalled(&mut controller2_event_fut),
1830            Poll::Ready(Some(Err(fidl::Error::ClientChannelClosed { epitaph, .. })))
1831                if epitaph == zx::Status::ALREADY_BOUND
1832        );
1833
1834        assert!(controller2.is_closed());
1835
1836        // Drop the first controller and verify that the second provider client can get a
1837        // functional client controller.
1838        drop(controller1);
1839        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1840
1841        let (controller2, _) = request_controller(&provider);
1842        assert_matches!(exec.run_until_stalled(&mut second_serve_fut), Poll::Pending);
1843
1844        // Ensure the new controller works by issuing a connect request.
1845        let connect_fut = controller2.connect(&test_values.net_id_open);
1846        let mut connect_fut = pin!(connect_fut);
1847
1848        // Process connect request from first controller. Verify success.
1849        assert_matches!(exec.run_until_stalled(&mut second_serve_fut), Poll::Pending);
1850
1851        assert_matches!(
1852            exec.run_until_stalled(&mut connect_fut),
1853            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
1854        );
1855    }
1856
1857    #[test_case(true)]
1858    #[test_case(false)]
1859    #[fuchsia::test(add_test_attr = false)]
1860    fn test_start_client_connections(start_client_connections_succeeds: bool) {
1861        let mut exec = fasync::TestExecutor::new();
1862        let (proxy, _server) = create_proxy::<fidl_fuchsia_wlan_sme::ClientSmeMarker>();
1863        let (req_sender, _req_recvr) = mpsc::channel(1);
1864        let mut iface_manager = FakeIfaceManager::new(proxy.clone(), req_sender);
1865
1866        // Setup the IfaceManager to succeed or fail depending on the test configuration.
1867        iface_manager.start_client_connections_succeeds = start_client_connections_succeeds;
1868
1869        let iface_manager: Arc<Mutex<dyn IfaceManagerApi>> = Arc::new(Mutex::new(iface_manager));
1870
1871        // Regardless of what the IfaceManager is actually able to do, we expect the response to
1872        // simply ack the caller.
1873        let fut = handle_client_request_start_client_connections(iface_manager);
1874        let mut fut = pin!(fut);
1875        assert_matches!(
1876            exec.run_until_stalled(&mut fut),
1877            Poll::Ready(fidl_policy::RequestStatus::Acknowledged)
1878        );
1879    }
1880
1881    #[test_case(true)]
1882    #[test_case(false)]
1883    #[fuchsia::test(add_test_attr = false)]
1884    fn test_stop_client_connections(stop_client_connections_succeeds: bool) {
1885        let mut exec = fasync::TestExecutor::new();
1886        let (proxy, _server) = create_proxy::<fidl_fuchsia_wlan_sme::ClientSmeMarker>();
1887        let (req_sender, _req_recvr) = mpsc::channel(1);
1888        let mut iface_manager = FakeIfaceManager::new(proxy.clone(), req_sender);
1889
1890        // Setup the IfaceManager to succeed or fail depending on the test configuration.
1891        iface_manager.stop_client_connections_succeeds = stop_client_connections_succeeds;
1892
1893        let iface_manager: Arc<Mutex<dyn IfaceManagerApi>> = Arc::new(Mutex::new(iface_manager));
1894
1895        // Regardless of what the IfaceManager is actually able to do, we expect the response to
1896        // simply ack the caller.
1897        let fut = handle_client_request_stop_client_connections(iface_manager);
1898        let mut fut = pin!(fut);
1899        assert_matches!(
1900            exec.run_until_stalled(&mut fut),
1901            Poll::Ready(fidl_policy::RequestStatus::Acknowledged)
1902        );
1903    }
1904
1905    #[fuchsia::test]
1906    fn test_client_wake_leases() {
1907        let mut exec = fasync::TestExecutor::new();
1908        let test_values = test_setup();
1909        let serve_fut = serve_provider_requests(
1910            test_values.iface_manager,
1911            test_values.update_sender,
1912            Arc::clone(&test_values.saved_networks),
1913            test_values.scan_requester,
1914            test_values.client_provider_lock,
1915            test_values.requests,
1916            test_values.telemetry_sender,
1917            test_values.power_manager.clone(),
1918        );
1919        let mut serve_fut = pin!(serve_fut);
1920        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1921
1922        let (controller, _) = request_controller(&test_values.provider);
1923        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1924
1925        // 1. Connect
1926        let connect_fut = controller.connect(&test_values.net_id_open);
1927        let mut connect_fut = pin!(connect_fut);
1928        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1929        assert_matches!(exec.run_until_stalled(&mut connect_fut), Poll::Ready(Ok(_)));
1930
1931        // 2. StartClientConnections
1932        let start_fut = controller.start_client_connections();
1933        let mut start_fut = pin!(start_fut);
1934        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1935        assert_matches!(exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(_)));
1936
1937        // 3. StopClientConnections
1938        let stop_fut = controller.stop_client_connections();
1939        let mut stop_fut = pin!(stop_fut);
1940        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1941        assert_matches!(exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1942
1943        // 4. SaveNetwork
1944        let save_fut = controller.save_network(&fidl_policy::NetworkConfig {
1945            id: Some(test_values.net_id_open.clone()),
1946            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1947            ..Default::default()
1948        });
1949        let mut save_fut = pin!(save_fut);
1950        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1951        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(_)));
1952
1953        // 5. RemoveNetwork
1954        let remove_fut = controller.remove_network(&fidl_policy::NetworkConfig {
1955            id: Some(test_values.net_id_open.clone()),
1956            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1957            ..Default::default()
1958        });
1959        let mut remove_fut = pin!(remove_fut);
1960        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1961        assert_matches!(exec.run_until_stalled(&mut remove_fut), Poll::Ready(Ok(_)));
1962
1963        // 6. GetSavedNetworks
1964        let (_iterator, server_end) =
1965            fidl::endpoints::create_endpoints::<fidl_policy::NetworkConfigIteratorMarker>();
1966        let _ = controller.get_saved_networks(server_end);
1967        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1968
1969        // Verify that all wake leases were taken.
1970        let calls = test_values.power_manager.calls.lock();
1971        assert!(calls.contains(&"wlancfg-client-connect".to_string()));
1972        assert!(calls.contains(&"wlancfg-client-start-connections".to_string()));
1973        assert!(calls.contains(&"wlancfg-client-stop-connections".to_string()));
1974        assert!(calls.contains(&"wlancfg-client-save-network".to_string()));
1975        assert!(calls.contains(&"wlancfg-client-remove-network".to_string()));
1976        assert!(calls.contains(&"wlancfg-client-get-saved-networks".to_string()));
1977    }
1978}