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