|  | // Copyright 2019 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. | 
|  |  | 
|  | #include <fuchsia/examples/llcpp/fidl.h> | 
|  | #include <fuchsia/sys/cpp/fidl.h> | 
|  | #include <lib/async-loop/cpp/loop.h> | 
|  | #include <lib/async-loop/default.h> | 
|  | #include <lib/service/llcpp/service.h> | 
|  | #include <lib/sys/cpp/component_context.h> | 
|  |  | 
|  | #include <iostream> | 
|  |  | 
|  | using fuchsia_examples::Echo; | 
|  | using fuchsia_examples::EchoService; | 
|  |  | 
|  | fidl::InterfaceHandle<fuchsia::io::Directory> StartEchoServer( | 
|  | sys::ComponentContext* context, | 
|  | fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) { | 
|  | fidl::InterfaceHandle<fuchsia::io::Directory> svc; | 
|  | fuchsia::sys::LaunchInfo info{ | 
|  | .url = "fuchsia-pkg://fuchsia.com/echo-hlcpp-service-server#meta/echo-server.cmx", | 
|  | .directory_request = svc.NewRequest().TakeChannel(), | 
|  | }; | 
|  |  | 
|  | auto launcher = context->svc()->Connect<fuchsia::sys::Launcher>(); | 
|  | launcher->CreateComponent(std::move(info), std::move(controller)); | 
|  | return svc; | 
|  | } | 
|  |  | 
|  | zx::status<> llcpp_example(fidl::UnownedClientEnd<fuchsia_io::Directory> svc) { | 
|  | zx::status<EchoService::ServiceClient> open_result = | 
|  | llcpp::sys::OpenServiceAt<EchoService>(std::move(svc)); | 
|  | if (open_result.is_error()) { | 
|  | std::cerr << "failed to open default instance of EchoService: " << open_result.status_string() | 
|  | << std::endl; | 
|  | return open_result.take_error(); | 
|  | } | 
|  |  | 
|  | EchoService::ServiceClient service = std::move(open_result.value()); | 
|  |  | 
|  | zx::status<fidl::ClientEnd<Echo>> connect_result = service.connect_regular_echo(); | 
|  | if (connect_result.is_error()) { | 
|  | std::cerr << "failed to connect to member protocol regular_echo of EchoService: " | 
|  | << connect_result.status_string() << std::endl; | 
|  | return connect_result.take_error(); | 
|  | } | 
|  |  | 
|  | fidl::WireSyncClient<Echo> client = fidl::BindSyncClient(std::move(connect_result.value())); | 
|  | fidl::WireResult<Echo::EchoString> echo_result = client.EchoString(fidl::StringView("hello")); | 
|  | if (!echo_result.ok()) { | 
|  | std::cerr << "failed to make EchoString call to member protocol regular_echo of EchoService: " | 
|  | << echo_result.error() << std::endl; | 
|  | return zx::error(ZX_ERR_IO); | 
|  | } | 
|  |  | 
|  | auto response = echo_result.Unwrap(); | 
|  |  | 
|  | std::string result_string(response->response.data(), response->response.size()); | 
|  | if (result_string != "hello") { | 
|  | std::cerr << "got unexpected response '" << result_string << "'. expected 'hello'." | 
|  | << std::endl; | 
|  | return zx::error(ZX_ERR_INTERNAL); | 
|  | } | 
|  | return zx::ok(); | 
|  | } | 
|  |  | 
|  | int main(int argc, const char** argv) { | 
|  | async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread); | 
|  | auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory(); | 
|  |  | 
|  | // Start the echo service. | 
|  | // | 
|  | // In a real system, the service would be offered to the client instead of | 
|  | // being started by the client. | 
|  | fuchsia::sys::ComponentControllerPtr controller; | 
|  | auto svc = StartEchoServer(context.get(), controller.NewRequest()); | 
|  |  | 
|  | // Convert the typed handle to LLCPP types. | 
|  | auto llsvc = fidl::ClientEnd<fuchsia_io::Directory>(svc.TakeChannel()); | 
|  |  | 
|  | zx::status<> result = llcpp_example(llsvc); | 
|  | if (result.is_error()) { | 
|  | std::cerr << "llcpp_example failed with status: " << result.status_string() << std::endl; | 
|  | return 1; | 
|  | } | 
|  | return 0; | 
|  | } |