blob: 7764eccc6095a06195e00d25eb80061cf7fb6301 [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)]
use {
failure::{format_err, Error, ResultExt},
fidl_fidl_test_compatibility::{
EchoEvent,
EchoMarker,
EchoProxy,
EchoRequest,
EchoRequestStream,
},
fidl_fuchsia_sys::LauncherProxy,
fuchsia_async as fasync,
fuchsia_component::{
client::{App, launcher, launch},
server::ServiceFs,
},
futures::{StreamExt, TryStreamExt},
};
fn launch_and_connect_to_echo(launcher: &LauncherProxy, url: String) -> Result<(EchoProxy, App), Error> {
let app = launch(&launcher, url, None)?;
let echo = app.connect_to_service::<EchoMarker>()?;
Ok((echo, app))
}
async fn echo_server(stream: EchoRequestStream, launcher: &LauncherProxy) -> Result<(), Error> {
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 = stream
.err_into() // change error type from fidl::Error to failure::Error
.try_for_each_concurrent(None /* max concurrent requests per connection */, handler);
await!(handle_requests_fut)
}
fn main() -> Result<(), Error> {
let mut executor = fasync::Executor::new().context("Error creating executor")?;
let launcher = launcher().context("Error connecting to application launcher")?;
let mut fs = ServiceFs::new_local();
fs.dir("public")
.add_fidl_service(|stream| stream);
fs.take_and_serve_directory_handle().context("Error serving directory handle")?;
let serve_fut = fs.for_each_concurrent(None /* max concurrent connections */, |stream| async {
if let Err(e) = await!(echo_server(stream, &launcher)) {
eprintln!("Closing echo server {:?}", e);
}
});
executor.run_singlethreaded(serve_fut);
Ok(())
}