blob: 6dfb955bc98b88f08aca23ed217f24ecd685f6e3 [file] [log] [blame]
// Copyright 2018 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 crate::server::Facade;
use anyhow::{format_err, Error};
use async_trait::async_trait;
use fidl_fuchsia_wlan_common as fidl_common;
use fidl_fuchsia_wlan_internal as fidl_internal;
use fuchsia_syslog::macros::*;
use serde::{Deserialize, Serialize};
use serde_json::{to_value, Value};
use std::collections::HashMap;
// Testing helper methods
use crate::wlan::facade::WlanFacade;
use crate::common_utils::common::parse_u64_identifier;
// We're using serde's "remote derive" feature to allow us to derive (De)Serialize for a third-
// party type (i.e. fidl_internal::BssDescription). See here for more info:
// https://serde.rs/remote-derive.html
#[derive(Serialize, Deserialize)]
#[serde(remote = "fidl_common::Cbw")]
#[repr(u32)]
pub enum CbwDef {
Cbw20 = 0,
Cbw40 = 1,
Cbw40Below = 2,
Cbw80 = 3,
Cbw160 = 4,
Cbw80P80 = 5,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "fidl_common::WlanChan")]
pub struct WlanChanDef {
pub primary: u8,
#[serde(with = "CbwDef")]
pub cbw: fidl_common::Cbw,
pub secondary80: u8,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "fidl_internal::BssTypes")]
pub enum BssTypesDef {
Infrastructure = 1,
Personal = 2,
Independent = 3,
Mesh = 4,
AnyBss = 5,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "fidl_internal::BssDescription")]
struct BssDescriptionDef {
pub bssid: [u8; 6],
#[serde(with = "BssTypesDef")]
pub bss_type: fidl_internal::BssTypes,
pub beacon_period: u16,
pub timestamp: u64,
pub local_time: u64,
pub cap: u16,
pub ies: Vec<u8>,
#[serde(with = "WlanChanDef")]
pub chan: fidl_common::WlanChan,
pub rssi_dbm: i8,
pub snr_db: i8,
}
#[derive(serde::Serialize)]
struct BssDescriptionWrapper<'a>(
#[serde(with = "BssDescriptionDef")] &'a fidl_internal::BssDescription,
);
#[async_trait(?Send)]
impl Facade for WlanFacade {
async fn handle_request(&self, method: String, args: Value) -> Result<Value, Error> {
match method.as_ref() {
"scan" => {
fx_log_info!(tag: "WlanFacade", "performing wlan scan");
let results = self.scan().await?;
fx_log_info!(tag: "WlanFacade", "received {:?} scan results", results.len());
// return the scan results
to_value(results).map_err(|e| format_err!("error handling scan results: {}", e))
}
"scan_for_bss_info" => {
fx_log_info!(tag: "WlanFacade", "performing wlan scan");
let results = self.scan_for_bss_info().await?;
fx_log_info!(tag: "WlanFacade", "received {:?} scan results", results.len());
// convert all BssDescription, which can't be serialized, to BssDescriptionWrapper
let results: HashMap<String, Vec<BssDescriptionWrapper<'_>>> = results
.iter()
.map(|(ssid, bss_desc)| {
(
String::from_utf8(ssid.clone()).unwrap(),
bss_desc
.iter()
.map(|bss_desc| BssDescriptionWrapper(&**bss_desc))
.collect(),
)
})
.collect();
// return the scan results
to_value(results).map_err(|e| format_err!("error handling scan results: {}", e))
}
"connect" => {
let target_ssid = match args.get("target_ssid") {
Some(ssid) => {
let ssid = match ssid.as_str() {
Some(ssid) => ssid.as_bytes().to_vec(),
None => {
return Err(format_err!("Please provide a target ssid"));
}
};
ssid
}
None => return Err(format_err!("Please provide a target ssid")),
};
let target_pwd = match args.get("target_pwd") {
Some(pwd) => match pwd.clone().as_str() {
Some(pwd) => pwd.as_bytes().to_vec(),
None => {
fx_log_info!(tag: "WlanFacade", "Please check provided password");
vec![0; 0]
}
},
_ => vec![0; 0],
};
let target_bss_desc = match args.get("target_bss_desc") {
Some(bss_desc_json) => {
let bss_desc = BssDescriptionDef::deserialize(bss_desc_json)?;
Some(Box::new(bss_desc))
}
None => None,
};
fx_log_info!(tag: "WlanFacade", "performing wlan connect to SSID: {:?}", target_ssid);
let results = self.connect(target_ssid, target_pwd, target_bss_desc).await?;
to_value(results)
.map_err(|e| format_err!("error handling connection result: {}", e))
}
"get_iface_id_list" => {
fx_log_info!(tag: "WlanFacade", "Getting the interface id list.");
let result = self.get_iface_id_list().await?;
to_value(result).map_err(|e| format_err!("error handling get_iface_id_list: {}", e))
}
"get_phy_id_list" => {
fx_log_info!(tag: "WlanFacade", "Getting the phy id list.");
let result = self.get_phy_id_list().await?;
to_value(result).map_err(|e| format_err!("error handling get_phy_id_list: {}", e))
}
"destroy_iface" => {
fx_log_info!(tag: "WlanFacade", "Performing wlan destroy_iface");
let iface_id = parse_u64_identifier(args.clone())?;
self.destroy_iface(iface_id as u16).await?;
to_value(true).map_err(|e| format_err!("error handling destroy_iface: {}", e))
}
"disconnect" => {
fx_log_info!(tag: "WlanFacade", "performing wlan disconnect");
self.disconnect().await?;
to_value(true).map_err(|e| format_err!("error handling disconnect: {}", e))
}
"query_iface" => {
let iface_id = match args.get("iface_id") {
Some(iface_id) => match iface_id.as_u64() {
Some(iface_id) => iface_id as u16,
None => return Err(format_err!("Could not parse iface id")),
},
None => return Err(format_err!("Please provide target iface id")),
};
fx_log_info!(tag: "WlanFacade", "performing wlan query iface");
let result = self.query_iface(iface_id).await?;
to_value(result).map_err(|e| format_err!("error handling query iface: {}", e))
}
"status" => {
fx_log_info!(tag: "WlanFacade", "fetching connection status");
let result = self.status().await?;
to_value(result).map_err(|e| format_err!("error handling connection status: {}", e))
}
_ => return Err(format_err!("unsupported command!")),
}
}
}