blob: 2a8dde3c32aae8d38e0750a5350160cab2f300a5 [file] [log] [blame]
// Copyright 2022 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/fuchsia.driver.framework/cpp/wire.h>
#include <fidl/test.structuredconfig.receiver.shim/cpp/wire.h>
#include <fidl/test.structuredconfig.receiver/cpp/markers.h>
#include <fidl/test.structuredconfig.receiver/cpp/wire.h>
#include <fidl/test.structuredconfig.receiver/cpp/wire_types.h>
#include <lib/async/cpp/executor.h>
#include <lib/driver2/inspect.h>
#include <lib/driver2/logger.h>
#include <lib/driver2/namespace.h>
#include <lib/driver2/record_cpp.h>
#include <lib/fpromise/bridge.h>
#include <lib/fpromise/scope.h>
#include <lib/sys/component/llcpp/handlers.h>
#include <lib/sys/component/llcpp/outgoing_directory.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/sys/inspect/cpp/component.h>
#include <zircon/assert.h>
#include <memory>
#include <optional>
#include <vector>
#include <bind/fuchsia/test/cpp/fidl.h>
#include "fidl/test.structuredconfig.receiver.shim/cpp/wire_messaging.h"
#include "lib/fidl/llcpp/arena.h"
#include "lib/fidl/llcpp/string_view.h"
#include "lib/fidl/llcpp/vector_view.h"
#include "src/sys/component_manager/tests/structured_config/client_integration/cpp_driver/receiver_config.h"
namespace fdf {
using namespace fuchsia_driver_framework;
} // namespace fdf
namespace scr = test_structuredconfig_receiver;
namespace scrs = test_structuredconfig_receiver_shim;
using fpromise::promise;
namespace {
template <typename T>
class DecodedObject {
public:
DecodedObject() = default;
void Set(std::unique_ptr<uint8_t[]> raw_data, uint32_t size) {
raw_data_ = std::move(raw_data);
decoded_ = std::make_unique<fidl::unstable::DecodedMessage<T>>(
fidl::internal::WireFormatVersion::kV2, raw_data_.get(), size);
object = *decoded_->PrimaryObject();
}
T& Object() { return object; }
bool ok() { return decoded_->ok(); }
private:
std::unique_ptr<uint8_t[]> raw_data_;
T object;
std::unique_ptr<fidl::unstable::DecodedMessage<T>> decoded_;
};
class ReceiverDriver : public fidl::WireServer<scr::ConfigReceiverPuppet> {
public:
ReceiverDriver(async_dispatcher_t* dispatcher, fidl::WireSharedClient<fdf::Node> node,
driver::Namespace ns, driver::Logger logger, receiver_config::Config config)
: dispatcher_(dispatcher),
outgoing_(component::OutgoingDirectory::Create(dispatcher)),
node_(std::move(node)),
ns_(std::move(ns)),
logger_(std::move(logger)),
config_(std::move(config)) {}
static constexpr const char* Name() { return "receiver"; }
static zx::status<std::unique_ptr<ReceiverDriver>> Start(fdf::wire::DriverStartArgs& start_args,
fdf::UnownedDispatcher dispatcher,
fidl::WireSharedClient<fdf::Node> node,
driver::Namespace ns,
driver::Logger logger) {
auto config = receiver_config::Config::TakeFromStartArgs(start_args);
auto driver =
std::make_unique<ReceiverDriver>(dispatcher->async_dispatcher(), std::move(node),
std::move(ns), std::move(logger), std::move(config));
auto result = driver->Run(std::move(start_args.outgoing_dir()));
if (result.is_error()) {
return result.take_error();
}
return zx::ok(std::move(driver));
}
private:
zx::status<> Run(fidl::ServerEnd<::fuchsia_io::Directory> outgoing_dir) {
component::ServiceHandler handler;
scrs::ConfigService::Handler device(&handler);
auto puppet = [this](fidl::ServerEnd<scr::ConfigReceiverPuppet> server_end) -> void {
fidl::BindServer<fidl::WireServer<scr::ConfigReceiverPuppet>>(dispatcher_,
std::move(server_end), this);
};
auto result = device.add_puppet(puppet);
ZX_ASSERT(result.is_ok());
result = outgoing_.AddService<scrs::ConfigService>(std::move(handler));
ZX_ASSERT(result.is_ok());
// Serve the inspect data
auto config_node = inspector_.GetRoot().CreateChild("config");
config_.RecordInspect(&config_node);
inspector_.emplace(std::move(config_node));
auto exposed_inspector = driver::ExposedInspector::Create(dispatcher_, inspector_, outgoing_);
ZX_ASSERT(exposed_inspector.is_ok());
exposed_inspector_ = std::move(exposed_inspector.value());
return outgoing_.Serve(std::move(outgoing_dir));
}
void GetConfig(GetConfigRequestView request, GetConfigCompleter::Sync& _completer) override {
scr::wire::ReceiverConfig receiver_config;
fidl::Arena<65536> arena;
auto bool_vector_view = fidl::VectorView<bool>(arena, config_.my_vector_of_flag().size());
auto string_vector_view =
fidl::VectorView<fidl::StringView>(arena, config_.my_vector_of_string().size());
for (size_t i = 0; i < config_.my_vector_of_flag().size(); i++) {
bool_vector_view[i] = config_.my_vector_of_flag()[i];
}
for (size_t i = 0; i < config_.my_vector_of_string().size(); i++) {
string_vector_view[i] = fidl::StringView::FromExternal(config_.my_vector_of_string()[i]);
}
receiver_config.my_flag = config_.my_flag();
receiver_config.my_int8 = config_.my_int8();
receiver_config.my_int16 = config_.my_int16();
receiver_config.my_int32 = config_.my_int32();
receiver_config.my_int64 = config_.my_int64();
receiver_config.my_uint8 = config_.my_uint8();
receiver_config.my_uint16 = config_.my_uint16();
receiver_config.my_uint32 = config_.my_uint32();
receiver_config.my_uint64 = config_.my_uint64();
receiver_config.my_string = fidl::StringView::FromExternal(config_.my_string());
receiver_config.my_vector_of_flag = bool_vector_view;
receiver_config.my_vector_of_uint8 =
fidl::VectorView<uint8_t>::FromExternal(config_.my_vector_of_uint8());
receiver_config.my_vector_of_uint16 =
fidl::VectorView<uint16_t>::FromExternal(config_.my_vector_of_uint16());
receiver_config.my_vector_of_uint32 =
fidl::VectorView<uint32_t>::FromExternal(config_.my_vector_of_uint32());
receiver_config.my_vector_of_uint64 =
fidl::VectorView<uint64_t>::FromExternal(config_.my_vector_of_uint64());
receiver_config.my_vector_of_int8 =
fidl::VectorView<int8_t>::FromExternal(config_.my_vector_of_int8());
receiver_config.my_vector_of_int16 =
fidl::VectorView<int16_t>::FromExternal(config_.my_vector_of_int16());
receiver_config.my_vector_of_int32 =
fidl::VectorView<int32_t>::FromExternal(config_.my_vector_of_int32());
receiver_config.my_vector_of_int64 =
fidl::VectorView<int64_t>::FromExternal(config_.my_vector_of_int64());
receiver_config.my_vector_of_string = string_vector_view;
_completer.Reply(receiver_config);
}
async_dispatcher_t* const dispatcher_;
component::OutgoingDirectory outgoing_;
fidl::WireSharedClient<fdf::Node> node_;
fidl::WireSharedClient<fdf::NodeController> controller_;
driver::Namespace ns_;
driver::Logger logger_;
receiver_config::Config config_;
inspect::Inspector inspector_;
std::optional<driver::ExposedInspector> exposed_inspector_ = std::nullopt;
// NOTE: Must be the last member.
fpromise::scope scope_;
};
} // namespace
FUCHSIA_DRIVER_RECORD_CPP_V1(ReceiverDriver);