blob: 67b32158cb51d225bbbece9219bb4548400dd302 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use failure::{format_err, Error, ResultExt};
use fidl::endpoints;
use fidl_fuchsia_wlan_device_service::DeviceServiceProxy;
use fidl_fuchsia_wlan_sme as fidl_sme;
use fuchsia_zircon as zx;
type WlanService = DeviceServiceProxy;
pub async fn get_iface_ap_sme_proxy(
wlan_svc: &WlanService, iface_id: u16,
) -> Result<fidl_sme::ApSmeProxy, Error> {
let (sme_proxy, sme_remote) = endpoints::create_proxy()?;
let status = await!(wlan_svc.get_ap_sme(iface_id, sme_remote))
.context("error sending GetApSme request")?;
if status == zx::sys::ZX_OK {
Ok(sme_proxy)
} else {
Err(format_err!("Invalid interface id {}", iface_id))
}
}
pub async fn stop_ap(iface_sme_proxy: &fidl_sme::ApSmeProxy) -> Result<(), Error> {
let stop_ap_result_code = await!(iface_sme_proxy.stop());
match stop_ap_result_code {
Ok(result_code) => Ok(result_code),
_ => Err(format_err!("AP stop failure: {:?}", stop_ap_result_code)),
}
}
pub async fn start_ap(
iface_sme_proxy: &fidl_sme::ApSmeProxy, target_ssid: Vec<u8>, target_pwd: Vec<u8>, channel: u8,
) -> Result<fidl_sme::StartApResultCode, Error> {
// create ConnectRequest holding network info
let mut config = fidl_sme::ApConfig {
ssid: target_ssid,
password: target_pwd,
channel,
};
let start_ap_result_code = await!(iface_sme_proxy.start(&mut config));
match start_ap_result_code {
Ok(result_code) => Ok(result_code),
_ => Err(format_err!("AP start failure: {:?}", start_ap_result_code)),
}
}
#[cfg(test)]
mod tests {
use super::*;
use fidl_fuchsia_wlan_sme::ApSmeMarker;
use fidl_fuchsia_wlan_sme::StartApResultCode;
use fidl_fuchsia_wlan_sme::{ApSmeRequest, ApSmeRequestStream};
use fuchsia_async as fasync;
use futures::stream::{StreamExt, StreamFuture};
use futures::task::Poll;
use pin_utils::pin_mut;
#[test]
fn start_ap_success_returns_true() {
let start_ap_result = test_ap_start("TestAp", "", 6, StartApResultCode::Success);
assert!(start_ap_result == StartApResultCode::Success);
}
#[test]
fn start_ap_already_started_returns_false() {
let start_ap_result = test_ap_start("TestAp", "", 6, StartApResultCode::AlreadyStarted);
assert!(start_ap_result == StartApResultCode::AlreadyStarted);
}
#[test]
fn start_ap_internal_error_returns_false() {
let start_ap_result = test_ap_start("TestAp", "", 6, StartApResultCode::InternalError);
assert!(start_ap_result == StartApResultCode::InternalError);
}
#[test]
fn start_ap_canceled_returns_false() {
let start_ap_result = test_ap_start("TestAp", "", 6, StartApResultCode::Canceled);
assert!(start_ap_result == StartApResultCode::Canceled);
}
#[test]
fn start_ap_timedout_returns_false() {
let start_ap_result = test_ap_start("TestAp", "", 6, StartApResultCode::TimedOut);
assert!(start_ap_result == StartApResultCode::TimedOut);
}
#[test]
fn start_ap_in_progress_returns_false() {
let start_ap_result =
test_ap_start("TestAp", "", 6, StartApResultCode::PreviousStartInProgress);
assert!(start_ap_result == StartApResultCode::PreviousStartInProgress);
}
fn test_ap_start(
ssid: &str, password: &str, channel: u8, result_code: StartApResultCode,
) -> StartApResultCode {
let mut exec = fasync::Executor::new().expect("failed to create an executor");
let (ap_sme, server) = create_ap_sme_proxy();
let mut ap_sme_req = server.into_future();
let target_ssid = ssid.as_bytes().to_vec();
let target_password = password.as_bytes().to_vec();
let config = fidl_sme::ApConfig {
ssid: target_ssid.to_vec(),
password: target_password.to_vec(),
channel,
};
let fut = start_ap(&ap_sme, target_ssid, target_password, channel);
pin_mut!(fut);
assert!(exec.run_until_stalled(&mut fut).is_pending());
send_start_ap_response(&mut exec, &mut ap_sme_req, config, result_code);
let complete = exec.run_until_stalled(&mut fut);
let ap_start_result = match complete {
Poll::Ready(result) => result,
_ => panic!("Expected a start response"),
};
let returned_start_ap_code = match ap_start_result {
Ok(response) => response,
_ => panic!("Expected a valid start result"),
};
returned_start_ap_code
}
fn create_ap_sme_proxy() -> (fidl_sme::ApSmeProxy, ApSmeRequestStream) {
let (proxy, server) =
endpoints::create_proxy::<ApSmeMarker>().expect("failed to create sme ap channel");
let server = server
.into_stream()
.expect("failed to create ap sme response stream");
(proxy, server)
}
fn send_start_ap_response(
exec: &mut fasync::Executor, server: &mut StreamFuture<ApSmeRequestStream>,
expected_config: fidl_sme::ApConfig, result_code: StartApResultCode,
) {
let rsp = match poll_ap_sme_request(exec, server) {
Poll::Ready(ApSmeRequest::Start { config, responder }) => {
assert_eq!(expected_config, config);
responder
}
Poll::Pending => panic!("Expected AP Start Request"),
_ => panic!("Expected AP Start Request"),
};
rsp.send(result_code)
.expect("Failed to send AP start response.");
}
fn poll_ap_sme_request(
exec: &mut fasync::Executor, next_ap_sme_req: &mut StreamFuture<ApSmeRequestStream>,
) -> Poll<ApSmeRequest> {
exec.run_until_stalled(next_ap_sme_req)
.map(|(req, stream)| {
*next_ap_sme_req = stream.into_future();
req.expect("did not expect the ApSmeRequestStream to end")
.expect("error polling ap sme request stream")
})
}
}