blob: 4fd3838751368e519e24fe8c955e3d854de59379 [file] [log] [blame]
// 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 <fidl/test/compatibility/llcpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/sys/cpp/component_context.h>
#include <zircon/status.h>
#include <cstdlib>
#include <iostream>
#include <string>
constexpr const char kEchoInterfaceName[] = "fidl.test.compatibility.Echo";
namespace fidl {
namespace test {
namespace compatibility {
class EchoClientApp {
public:
EchoClientApp(::fidl::StringView server_url)
: context_(sys::ComponentContext::Create()),
client_(Echo::SyncClient(ConnectTo(server_url))) {}
::fidl::DecodeResult<Echo::EchoStructResponse> EchoStruct(
::fidl::BytePart request_buffer, Struct value,
::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
Struct* out_value) {
return client_.EchoStruct(std::move(request_buffer), std::move(value),
forward_to_server, std::move(response_buffer),
out_value);
}
zx_status_t EchoStructNoRetVal(Struct value,
::fidl::StringView forward_to_server,
Echo::EventHandlers event_handlers) {
auto status =
client_.EchoStructNoRetVal(std::move(value), forward_to_server);
if (status != ZX_OK) {
return status;
}
return client_.HandleEvents(std::move(event_handlers));
}
::fidl::DecodeResult<Echo::EchoArraysResponse> EchoArrays(
::fidl::BytePart request_buffer, ArraysStruct value,
::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
ArraysStruct* out_value) {
return client_.EchoArrays(std::move(request_buffer), std::move(value),
forward_to_server, std::move(response_buffer),
out_value);
}
::fidl::DecodeResult<Echo::EchoVectorsResponse> EchoVectors(
::fidl::BytePart request_buffer, VectorsStruct value,
::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
VectorsStruct* out_value) {
return client_.EchoVectors(std::move(request_buffer), std::move(value),
forward_to_server, std::move(response_buffer),
out_value);
}
::fidl::DecodeResult<Echo::EchoTableResponse> EchoTable(
::fidl::BytePart request_buffer, AllTypesTable value,
::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
AllTypesTable* out_value) {
return client_.EchoTable(std::move(request_buffer), std::move(value),
forward_to_server, std::move(response_buffer),
out_value);
}
::fidl::DecodeResult<Echo::EchoXunionsResponse> EchoXunions(
::fidl::BytePart request_buffer, ::fidl::VectorView<AllTypesXunion> value,
::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
::fidl::VectorView<AllTypesXunion>* out_value) {
return client_.EchoXunions(std::move(request_buffer), std::move(value),
forward_to_server, std::move(response_buffer),
out_value);
}
EchoClientApp(const EchoClientApp&) = delete;
EchoClientApp& operator=(const EchoClientApp&) = delete;
private:
// Called once upon construction to launch and connect to the server.
zx::channel ConnectTo(::fidl::StringView server_url) {
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = std::string(server_url.data(), server_url.size());
echo_provider_ = sys::ServiceDirectory::CreateWithRequest(
&launch_info.directory_request);
fuchsia::sys::LauncherPtr launcher;
context_->svc()->Connect(launcher.NewRequest());
launcher->CreateComponent(std::move(launch_info), controller_.NewRequest());
zx::channel server_end, client_end;
ZX_ASSERT(zx::channel::create(0, &client_end, &server_end) == ZX_OK);
ZX_ASSERT(echo_provider_->Connect(kEchoInterfaceName,
std::move(server_end)) == ZX_OK);
return client_end;
}
std::unique_ptr<sys::ComponentContext> context_;
std::shared_ptr<sys::ServiceDirectory> echo_provider_;
fuchsia::sys::ComponentControllerPtr controller_;
Echo::SyncClient client_;
};
class EchoConnection final : public Echo::Interface {
public:
explicit EchoConnection(zx::unowned_channel channel) : channel_(channel) {}
void EchoStruct(Struct value, ::fidl::StringView forward_to_server,
EchoStructCompleter::Sync completer) override {
if (forward_to_server.empty()) {
completer.Reply(std::move(value));
} else {
std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
EchoClientApp app(forward_to_server);
Struct out_value;
auto result = app.EchoStruct(
::fidl::BytePart(&request_buffer[0],
static_cast<uint32_t>(request_buffer.size())),
std::move(value), ::fidl::StringView{0, ""},
::fidl::BytePart(&response_buffer[0],
static_cast<uint32_t>(response_buffer.size())),
&out_value);
ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
result.error);
completer.Reply(std::move(out_value));
}
}
void EchoStructNoRetVal(
Struct value, ::fidl::StringView forward_to_server,
EchoStructNoRetValCompleter::Sync completer) override {
if (forward_to_server.empty()) {
auto status = Echo::SendEchoEventEvent(zx::unowned_channel(channel_),
std::move(value));
ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed: %s",
zx_status_get_string(status));
} else {
EchoClientApp app(forward_to_server);
zx_status_t status = app.EchoStructNoRetVal(
std::move(value), ::fidl::StringView{0, ""},
Echo::EventHandlers{.echo_event =
[&](Struct value) {
return Echo::SendEchoEventEvent(
zx::unowned_channel(channel_),
std::move(value));
},
.unknown =
[] {
ZX_PANIC("Received unexpected event");
return ZX_ERR_INVALID_ARGS;
}});
ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed: %s",
zx_status_get_string(status));
}
}
void EchoArrays(ArraysStruct value, ::fidl::StringView forward_to_server,
EchoArraysCompleter::Sync completer) override {
if (forward_to_server.empty()) {
completer.Reply(std::move(value));
} else {
std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
EchoClientApp app(forward_to_server);
ArraysStruct out_value;
auto result = app.EchoArrays(
::fidl::BytePart(&request_buffer[0],
static_cast<uint32_t>(request_buffer.size())),
std::move(value), ::fidl::StringView{0, ""},
::fidl::BytePart(&response_buffer[0],
static_cast<uint32_t>(response_buffer.size())),
&out_value);
ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
result.error);
completer.Reply(std::move(out_value));
}
}
void EchoVectors(VectorsStruct value, ::fidl::StringView forward_to_server,
EchoVectorsCompleter::Sync completer) override {
if (forward_to_server.empty()) {
completer.Reply(std::move(value));
} else {
std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
EchoClientApp app(forward_to_server);
VectorsStruct out_value;
auto result = app.EchoVectors(
::fidl::BytePart(&request_buffer[0],
static_cast<uint32_t>(request_buffer.size())),
std::move(value), ::fidl::StringView{0, ""},
::fidl::BytePart(&response_buffer[0],
static_cast<uint32_t>(response_buffer.size())),
&out_value);
ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
result.error);
completer.Reply(std::move(out_value));
}
}
void EchoTable(AllTypesTable value, ::fidl::StringView forward_to_server,
EchoTableCompleter::Sync completer) override {
if (forward_to_server.empty()) {
completer.Reply(std::move(value));
} else {
std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
EchoClientApp app(forward_to_server);
AllTypesTable out_value;
auto result = app.EchoTable(
::fidl::BytePart(&request_buffer[0],
static_cast<uint32_t>(request_buffer.size())),
std::move(value), ::fidl::StringView{0, ""},
::fidl::BytePart(&response_buffer[0],
static_cast<uint32_t>(response_buffer.size())),
&out_value);
ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
result.error);
completer.Reply(std::move(out_value));
}
}
void EchoXunions(fidl::VectorView<AllTypesXunion> value,
::fidl::StringView forward_to_server,
EchoXunionsCompleter::Sync completer) override {
if (forward_to_server.empty()) {
completer.Reply(std::move(value));
} else {
std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
EchoClientApp app(forward_to_server);
fidl::VectorView<AllTypesXunion> out_value;
auto result = app.EchoXunions(
::fidl::BytePart(&request_buffer[0],
static_cast<uint32_t>(request_buffer.size())),
std::move(value), ::fidl::StringView{0, ""},
::fidl::BytePart(&response_buffer[0],
static_cast<uint32_t>(response_buffer.size())),
&out_value);
ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
result.error);
completer.Reply(std::move(out_value));
}
}
private:
zx::unowned_channel channel_;
};
} // namespace compatibility
} // namespace test
} // namespace fidl
int main(int argc, const char** argv) {
// The FIDL support lib requires async_get_default_dispatcher() to return
// non-null.
async::Loop loop(&kAsyncLoopConfigAttachToThread);
auto context = sys::ComponentContext::Create();
std::vector<std::unique_ptr<fidl::test::compatibility::EchoConnection>>
connections;
context->outgoing()->AddPublicService(
std::make_unique<vfs::Service>([&](zx::channel request,
async_dispatcher_t* dispatcher) {
auto conn = std::make_unique<fidl::test::compatibility::EchoConnection>(
zx::unowned_channel(request));
ZX_ASSERT(fidl::Bind(dispatcher, std::move(request), conn.get()) ==
ZX_OK);
connections.push_back(std::move(conn));
}),
kEchoInterfaceName);
loop.Run();
return EXIT_SUCCESS;
}