wlan_sme/serve/
ap.rs

1// Copyright 2018 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::{ap as ap_sme, MlmeEventStream, MlmeSink, MlmeStream};
6use fuchsia_sync::Mutex;
7use futures::channel::mpsc;
8use futures::prelude::*;
9use futures::select;
10use ieee80211::Ssid;
11use log::error;
12use std::pin::pin;
13use std::sync::Arc;
14use wlan_common::RadioConfig;
15use {fidl_fuchsia_wlan_mlme as fidl_mlme, fidl_fuchsia_wlan_sme as fidl_sme};
16
17pub type Endpoint = fidl::endpoints::ServerEnd<fidl_sme::ApSmeMarker>;
18type Sme = ap_sme::ApSme;
19
20pub fn serve(
21    device_info: fidl_mlme::DeviceInfo,
22    event_stream: MlmeEventStream,
23    new_fidl_clients: mpsc::UnboundedReceiver<Endpoint>,
24) -> (MlmeSink, MlmeStream, impl Future<Output = Result<(), anyhow::Error>>) {
25    let (sme, mlme_sink, mlme_stream, time_stream) = Sme::new(device_info);
26    let fut = async move {
27        let sme = Arc::new(Mutex::new(sme));
28        let mlme_sme = super::serve_mlme_sme(event_stream, Arc::clone(&sme), time_stream);
29        let sme_fidl = super::serve_fidl(&*sme, new_fidl_clients, handle_fidl_request);
30        let mlme_sme = pin!(mlme_sme);
31        let sme_fidl = pin!(sme_fidl);
32        select! {
33            mlme_sme = mlme_sme.fuse() => mlme_sme?,
34            sme_fidl = sme_fidl.fuse() => match sme_fidl? {},
35        }
36        Ok(())
37    };
38    (mlme_sink, mlme_stream, fut)
39}
40
41async fn handle_fidl_request(
42    sme: &Mutex<Sme>,
43    request: fidl_sme::ApSmeRequest,
44) -> Result<(), ::fidl::Error> {
45    match request {
46        fidl_sme::ApSmeRequest::Start { config, responder } => {
47            let r = start(sme, config).await;
48            responder.send(r)?;
49        }
50        fidl_sme::ApSmeRequest::Stop { responder } => {
51            let r = stop(sme).await;
52            responder.send(r)?;
53        }
54        fidl_sme::ApSmeRequest::Status { responder } => {
55            let r = status(sme);
56            responder.send(&r)?;
57        }
58    }
59    Ok(())
60}
61
62async fn start(sme: &Mutex<Sme>, config: fidl_sme::ApConfig) -> fidl_sme::StartApResultCode {
63    let radio_cfg = match RadioConfig::try_from(config.radio_cfg) {
64        Ok(radio_cfg) => radio_cfg,
65        Err(e) => {
66            error!("Could not convert RadioConfig from ApConfig: {:?}", e);
67            return fidl_sme::StartApResultCode::InternalError;
68        }
69    };
70
71    let sme_config = ap_sme::Config {
72        ssid: Ssid::from_bytes_unchecked(config.ssid),
73        password: config.password,
74        radio_cfg,
75    };
76
77    let receiver = sme.lock().on_start_command(sme_config);
78    let r = receiver.await.unwrap_or_else(|_| {
79        error!("Responder for AP Start command was dropped without sending a response");
80        ap_sme::StartResult::InternalError
81    });
82
83    match r {
84        ap_sme::StartResult::Success => fidl_sme::StartApResultCode::Success,
85        ap_sme::StartResult::AlreadyStarted => fidl_sme::StartApResultCode::AlreadyStarted,
86        ap_sme::StartResult::InternalError => fidl_sme::StartApResultCode::InternalError,
87        ap_sme::StartResult::Canceled => fidl_sme::StartApResultCode::Canceled,
88        ap_sme::StartResult::TimedOut => fidl_sme::StartApResultCode::TimedOut,
89        ap_sme::StartResult::PreviousStartInProgress => {
90            fidl_sme::StartApResultCode::PreviousStartInProgress
91        }
92        ap_sme::StartResult::InvalidArguments(e) => {
93            error!("Invalid arguments for AP start: {}", e);
94            fidl_sme::StartApResultCode::InvalidArguments
95        }
96    }
97}
98
99async fn stop(sme: &Mutex<Sme>) -> fidl_sme::StopApResultCode {
100    let receiver = sme.lock().on_stop_command();
101    receiver.await.unwrap_or_else(|_| {
102        error!("Responder for AP Stop command was dropped without sending a response");
103        fidl_sme::StopApResultCode::InternalError
104    })
105}
106
107fn status(sme: &Mutex<Sme>) -> fidl_sme::ApStatusResponse {
108    fidl_sme::ApStatusResponse { running_ap: sme.lock().get_running_ap().map(Box::new) }
109}