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