| // 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; |
| } |