| // 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::{launch, launcher, App}, |
| 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")?; |
| } |
| EchoRequest::EchoArrays { 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_arrays(&mut value, "")) |
| .context("Error calling echo_arrays on proxy")?; |
| drop(app); |
| } |
| responder.send(&mut value).context("Error responding")?; |
| } |
| EchoRequest::EchoVectors { 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_vectors(&mut value, "")) |
| .context("Error calling echo_vectors on proxy")?; |
| drop(app); |
| } |
| responder.send(&mut value).context("Error responding")?; |
| } |
| EchoRequest::EchoTable { value: _, forward_to_server: _, responder: _ } => { |
| // Enabling this blows the stack. |
| } |
| /* |
| EchoRequest::EchoTable { 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_table(value, "")) |
| .context("Error calling echo_table on proxy")?; |
| drop(app); |
| } |
| responder.send(value) |
| .context("Error responding")?; |
| } |
| */ |
| EchoRequest::EchoXunions { 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_xunions(&mut value.iter_mut(), "")) |
| .context("Error calling echo_xunions on proxy")?; |
| drop(app); |
| } |
| responder.send(&mut value.iter_mut()).context("Error responding")?; |
| } |
| } |
| 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(()) |
| } |