blob: dbc5109de79982a8eaccd7b250e418c845f38065 [file] [log] [blame]
// Copyright 2020 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.
/// This macro generates a mod containing the logic to process a FIDL stream.
/// Callers can spawn a handler task by invoking fidl_io::spawn.
/// Macro usages specify the interface's base name (prefix for all generated
/// classes), along with a repeated set of the following:
/// - `Switchboard` setting type.
/// - FIDL setting type.
/// - The responder type for the `HangingGetHandler`.
/// - An optional type of a key for change functions if custom change functions are used.
/// - The handler function for requests.
#[macro_export]
macro_rules! fidl_process_full {
($interface:ident $(,$setting_type:expr, $fidl_settings:ty,
$fidl_responder:ty, $change_func_key:ty, $handle_func:ident)+$(,)*) => {
type HandleResult<'a> = LocalBoxFuture<'a, Result<Option<paste::item!{[<$interface Request>]}>, anyhow::Error>>;
pub mod fidl_io {
paste::item!{use fidl_fuchsia_settings::{[<$interface Marker>], [<$interface RequestStream>]};}
use super::*;
use fuchsia_async as fasync;
use crate::fidl_processor::{FidlProcessor};
use crate::internal::switchboard;
use crate::message::base::MessengerType;
pub fn spawn (switchboard_messenger_factory: switchboard::message::Factory,
stream: paste::item!{[<$interface RequestStream>]}) {
fasync::Task::local(async move {
let messenger = if let Ok((messenger, _)) = switchboard_messenger_factory.create(MessengerType::Unbound).await {
messenger
} else {
return
};
let mut processor = FidlProcessor::<paste::item!{[<$interface Marker>]}>::new(stream, messenger).await;
$(processor
.register::<$fidl_settings, $fidl_responder, $change_func_key>(
$setting_type,
Box::new(
move |context, req| -> HandleResult<'_> {
async move {
$handle_func(context, req).await
}
.boxed_local()
},
),
)
.await;)*
processor.process().await;
}).detach();
}
}
};
}
#[macro_export]
macro_rules! fidl_process {
// Generates a fidl_io mod with a spawn for the given fidl interface,
// setting type, and handler function. Additional handlers can be specified
// by providing the switchboard setting type, fidl setting type,
// watch responder, and handle function.
($interface:ident, $setting_type:expr, $handle_func:ident
$(,$item_setting_type:expr, $fidl_settings:ty, $fidl_responder:ty,
$item_handle_func:ident)*$(,)*) => {
paste::item! {
$crate::fidl_process_full!(
$interface,
$setting_type,
[<$interface Settings>],
[<$interface WatchResponder>],
String,
$handle_func
$(,$item_setting_type, $fidl_settings, $fidl_responder, String, $item_handle_func)*
);
}
};
// Generates a fidl_io mod with a spawn for the given fidl interface,
// setting type, and handler function. Additional handlers can be specified
// by providing the responder type and handle function.
($interface:ident, $setting_type:expr, $handle_func:ident
$(, $fidl_responder:ty, $item_handle_func:ident)*$(,)*) => {
paste::item! {
$crate::fidl_process_full!(
$interface,
$setting_type,
[<$interface Settings>],
[<$interface WatchResponder>],
String,
$handle_func
$(, $setting_type,
[<$interface Settings>],
$fidl_responder,
String,
$item_handle_func)*
);
}
};
// Generates a fidl_io mod with a spawn for the given fidl interface,
// setting type, fidl setting type and handler function. To be used when the
// fidl interface and fidl setting type differ in name.
($interface:ident, $setting_type:expr, $fidl_settings:ident,
$handle_func:ident) => {
paste::item! {
$crate::fidl_process_full!(
$interface,
$setting_type,
$fidl_settings,
[<$interface WatchResponder>],
String,
$handle_func
);
}
};
}
// Only differentiated from fidl_process in that the expected responder
// type is Watch2Responder.
// TODO(fxb/55719): remove when watch2 is migrated back to watch
#[macro_export]
macro_rules! fidl_process_2 {
// Generates a fidl_io mod with a spawn for the given fidl interface,
// setting type, and handler function. Additional handlers can be specified
// by providing the switchboard setting type, fidl setting type,
// watch responder, and handle function.
($interface:ident, $setting_type:expr, $handle_func:ident
$(,$item_setting_type:expr, $fidl_settings:ty, $fidl_responder:ty,
$item_handle_func:ident)*$(,)*) => {
paste::item! {
$crate::fidl_process_full!(
$interface,
$setting_type,
[<$interface Settings>],
[<$interface Watch2Responder>],
String,
$handle_func
$(,$item_setting_type, $fidl_settings, $fidl_responder, String, $item_handle_func)*
);
}
};
}
#[macro_export]
macro_rules! fidl_hanging_get_responder {
($marker_type:ty $(, $setting_type:ty, $responder_type:ty)+$(,)*) => {
use crate::switchboard::base::FidlResponseErrorLogger;
use fidl::endpoints::ServiceMarker;
use fuchsia_syslog::fx_log_err;
use fuchsia_zircon::Status;
$(impl Sender<$setting_type> for $responder_type {
fn send_response(self, data: $setting_type) {
self.send(data).log_fidl_response_error(
<$marker_type as ServiceMarker>::DEBUG_NAME);
}
fn on_error(self) {
fx_log_err!("error occurred watching for service: {:?}",
<$marker_type as ServiceMarker>::DEBUG_NAME);
self.control_handle().shutdown_with_epitaph(Status::INTERNAL);
}
})+
};
}
#[macro_export]
macro_rules! fidl_hanging_get_result_responder {
($setting_type:ty, $responder_type:ty, $marker_debug_name:expr) => {
impl Sender<$setting_type> for $responder_type {
fn send_response(self, data: $setting_type) {
self.send(&mut Ok(data)).log_fidl_response_error($marker_debug_name);
}
fn on_error(self) {
self.send(&mut Err(fidl_fuchsia_settings::Error::Failed))
.log_fidl_response_error($marker_debug_name);
}
}
};
}