blob: 854cbe8880450ee5ede2c75868ee84b16ee10df4 [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 failure::Error;
use fuchsia_bluetooth::error::Error as BTError;
use fuchsia_syslog::macros::*;
use futures::channel::mpsc;
use futures::StreamExt;
use parking_lot::RwLock;
use serde_json::Value;
use std::sync::Arc;
// Sl4f related inclusions
use crate::server::sl4f::Sl4f;
use crate::server::sl4f_types::{AsyncRequest, AsyncResponse, FacadeType};
// Translation layers go here (i.e netstack_method_to_fidl)
use crate::bluetooth::commands::ble_advertise_method_to_fidl;
use crate::bluetooth::commands::ble_method_to_fidl;
use crate::bluetooth::commands::gatt_client_method_to_fidl;
use crate::bluetooth::commands::gatt_server_method_to_fidl;
use crate::netstack::commands::netstack_method_to_fidl;
use crate::wlan::commands::wlan_method_to_fidl;
pub async fn run_fidl_loop(
sl4f_session: Arc<RwLock<Sl4f>>, receiver: mpsc::UnboundedReceiver<AsyncRequest>,
) {
const CONCURRENT_REQ_LIMIT: usize = 10; // TODO(CONN-6) figure out a good parallel value for this
let session = &sl4f_session;
let handler = async move |request| {
await!(handle_request(Arc::clone(session), request)).unwrap();
};
let receiver_fut = receiver.for_each_concurrent(CONCURRENT_REQ_LIMIT, handler);
await!(receiver_fut);
}
async fn handle_request(sl4f_session: Arc<RwLock<Sl4f>>, request: AsyncRequest) -> Result<(), Error> {
match request {
AsyncRequest { tx, id, method_type, name, params } => {
let curr_sl4f_session = sl4f_session.clone();
fx_log_info!(tag: "run_fidl_loop",
"Received synchronous request: {:?}, {:?}, {:?}, {:?}, {:?}",
tx, id, method_type, name, params);
match await!(method_to_fidl(method_type, name, params, curr_sl4f_session)) {
Ok(response) => {
let async_response = AsyncResponse::new(Ok(response));
// Ignore any tx sending errors since there is not a recovery path. The
// connection to the test server may be broken.
let _ = tx.send(async_response);
},
Err(e) => {
println!("Error returned from calling method_to_fidl {}", e);
let async_response = AsyncResponse::new(Err(e));
// Ignore any tx sending errors since there is not a recovery path. The
// connection to the test server may be broken.
let _ = tx.send(async_response);
}
};
}
}
Ok(())
}
async fn method_to_fidl(
method_type: String, method_name: String, args: Value, sl4f_session: Arc<RwLock<Sl4f>>,
) -> Result<Value, Error> {
match FacadeType::from_str(&method_type) {
FacadeType::BleAdvertiseFacade => await!(ble_advertise_method_to_fidl(
method_name,
args,
sl4f_session.read().get_ble_advertise_facade(),
)),
FacadeType::Bluetooth => await!(ble_method_to_fidl(
method_name,
args,
sl4f_session.read().get_bt_facade(),
)),
FacadeType::GattClientFacade => await!(gatt_client_method_to_fidl(
method_name,
args,
sl4f_session.read().get_gatt_client_facade(),
)),
FacadeType::GattServerFacade => await!(gatt_server_method_to_fidl(
method_name,
args,
sl4f_session.read().get_gatt_server_facade(),
)),
FacadeType::NetstackFacade => await!(netstack_method_to_fidl(
method_name,
args,
sl4f_session.read().get_netstack_facade(),
)),
FacadeType::Wlan => await!(wlan_method_to_fidl(
method_name,
args,
sl4f_session.read().get_wlan_facade()
)),
_ => Err(BTError::new("Invalid FIDL method type").into()),
}
}