blob: 1be09da1eb899ef902729e0111df12a658aaa093 [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.
#![deny(warnings)]
#![feature(async_await, await_macro, futures_api)]
use {
failure::{format_err, Error, ResultExt},
fidl::endpoints::{RequestStream, ServiceMarker},
fidl_fidl_test_compatibility::{
EchoEvent,
EchoMarker,
EchoProxy,
EchoRequest,
EchoRequestStream,
},
fuchsia_app::{
client::Launcher,
client::App,
server::ServicesServer,
},
fuchsia_async as fasync,
futures::TryStreamExt,
};
fn launch_and_connect_to_echo(launcher: &Launcher, url: String) -> Result<(EchoProxy, App), Error> {
let app = launcher.launch(url, None)?;
let echo = app.connect_to_service(EchoMarker)?;
Ok((echo, app))
}
async fn echo_server(chan: fasync::Channel, launcher: &Launcher) -> Result<(), Error> {
const CONCURRENT_REQ_LIMIT: Option<usize> = None;
let handler = move |request| Box::pin(async move {
match request {
EchoRequest::EchoStruct { mut value, forward_to_server, responder } => {
if !forward_to_server.is_empty() {
let (echo, app) = launch_and_connect_to_echo(launcher, forward_to_server)
.context("Error connecting to proxy")?;
value = await!(echo.echo_struct(&mut value, ""))
.context("Error calling echo_struct on proxy")?;
drop(app);
}
responder.send(&mut value)
.context("Error responding")?;
}
EchoRequest::EchoStructNoRetVal { mut value, forward_to_server, control_handle } => {
if !forward_to_server.is_empty() {
let (echo, app) = launch_and_connect_to_echo(launcher, forward_to_server)
.context("Error connecting to proxy")?;
echo.echo_struct_no_ret_val(&mut value, "")
.context("Error sending echo_struct_no_ret_val to proxy")?;
let mut event_stream = echo.take_event_stream();
let EchoEvent::EchoEvent { value: response_val } =
await!(event_stream.try_next())
.context("Error getting event response from proxy")?
.ok_or_else(|| format_err!("Proxy sent no events"))?;
value = response_val;
drop(app);
}
control_handle.send_echo_event(&mut value)
.context("Error responding with event")?;
}
}
Ok(())
});
let handle_requests_fut = EchoRequestStream::from_channel(chan)
.err_into() // change error type from fidl::Error to failure::Error
.try_for_each_concurrent(CONCURRENT_REQ_LIMIT, handler);
await!(handle_requests_fut)
}
fn main() -> Result<(), Error> {
let mut executor = fasync::Executor::new().context("Error creating executor")?;
let launcher = Launcher::new().context("Error connecting to application launcher")?;
let fut = ServicesServer::new()
.add_service((EchoMarker::NAME, move |chan| {
let launcher = launcher.clone();
fasync::spawn(async move {
if let Err(e) = await!(echo_server(chan, &launcher)) {
eprintln!("Closing echo server {:?}", e);
}
})
}))
.start()
.context("Error starting compatibility echo ServicesServer")?;
executor.run_singlethreaded(fut).context("failed to execute echo future")?;
Ok(())
}