| // 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. |
| |
| #ifndef SRC_SYS_FUZZING_COMMON_COMPONENT_CONTEXT_H_ |
| #define SRC_SYS_FUZZING_COMMON_COMPONENT_CONTEXT_H_ |
| |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/fidl/cpp/interface_request.h> |
| #include <lib/sys/cpp/outgoing_directory.h> |
| #include <lib/sys/cpp/service_directory.h> |
| #include <lib/syslog/cpp/macros.h> |
| #include <zircon/compiler.h> |
| #include <zircon/process.h> |
| #include <zircon/processargs.h> |
| #include <zircon/status.h> |
| |
| #include <memory> |
| |
| #include "src/lib/fxl/macros.h" |
| #include "src/sys/fuzzing/common/async-types.h" |
| |
| namespace fuzzing { |
| |
| // Aliases to simplify passing around the unique context. |
| class ComponentContext; |
| using ComponentContextPtr = std::unique_ptr<ComponentContext>; |
| |
| // This class is a wrapper around |sys::ComponentContext| that provides some additional common |
| // behaviors, such as making an |async::Loop| and scheduling a primary task on an |async::Executor|. |
| class ComponentContext { |
| public: |
| // Creates a component context. This method consumes startup handles in order to serve FIDL |
| // protocols, and can therefore be called at most once per process. |
| static ComponentContextPtr Create(); |
| |
| // Creates an "auxiliary" context that does not have an outgoing directory. Such a context can |
| // only be used for creating FIDL clients, but does not consume any startup handles and thus does |
| // not preclude creating other component contexts. |
| static ComponentContextPtr CreateAuxillary(); |
| |
| ComponentContext() = default; |
| virtual ~ComponentContext(); |
| |
| const ExecutorPtr& executor() const { return executor_; } |
| |
| // These must match the channel IDs used by fuzz_test_runner. |
| static constexpr uint32_t kRegistrarId = 0; |
| static constexpr uint32_t kCoverageId = 1; |
| |
| // Takes the |PA_HND(PA_USER0, arg)| startup handle. |
| virtual zx::channel TakeChannel(uint32_t arg); |
| |
| // Adds an interface request handler for a protocol capability provided by this component. |
| template <typename Interface> |
| __WARN_UNUSED_RESULT zx_status_t |
| AddPublicService(fidl::InterfaceRequestHandler<Interface> handler) const { |
| return outgoing_->AddPublicService(std::move(handler)); |
| } |
| |
| // Connects a |request| to a protocol capability provided by another component. |
| template <typename Interface> |
| __WARN_UNUSED_RESULT zx_status_t Connect(fidl::InterfaceRequest<Interface> request) { |
| return Connect(svc_, std::move(request)); |
| } |
| |
| // Returns a handler to connect |request|s to a protocol capability provided by another component. |
| template <typename Interface> |
| fidl::InterfaceRequestHandler<Interface> MakeRequestHandler() { |
| return [svc = svc_](fidl::InterfaceRequest<Interface> request) { |
| Connect(svc, std::move(request)); |
| }; |
| } |
| |
| // Schedules a task to be executed when |Run| is invoked. |
| template <typename Task> |
| void ScheduleTask(Task task) { |
| executor_->schedule_task(std::move(task)); |
| } |
| |
| // Runs the message loop on the current thread. This method should only be called at most once. |
| __WARN_UNUSED_RESULT virtual zx_status_t Run(); |
| |
| // Runs until there are no tasks that can make progress. |
| __WARN_UNUSED_RESULT virtual zx_status_t RunUntilIdle(); |
| |
| protected: |
| using LoopPtr = std::unique_ptr<async::Loop>; |
| using ServiceDirectoryPtr = std::shared_ptr<sys::ServiceDirectory>; |
| using OutgoingDirectoryPtr = std::shared_ptr<sys::OutgoingDirectory>; |
| |
| void set_executor(ExecutorPtr executor) { executor_ = std::move(executor); } |
| void set_svc(ServiceDirectoryPtr svc) { svc_ = std::move(svc); } |
| |
| private: |
| // Connects a |request| to a protocol capability provided by another component. |
| template <typename Interface> |
| static zx_status_t Connect(ServiceDirectoryPtr svc, fidl::InterfaceRequest<Interface> request) { |
| if (auto status = svc->Connect(std::move(request)); status != ZX_OK) { |
| FX_LOGS(ERROR) << "Failed to connect to " << Interface::Name_ << ": " |
| << zx_status_get_string(status); |
| return status; |
| } |
| return ZX_OK; |
| } |
| |
| LoopPtr loop_; |
| ExecutorPtr executor_; |
| ServiceDirectoryPtr svc_; |
| OutgoingDirectoryPtr outgoing_; |
| |
| FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(ComponentContext); |
| }; |
| |
| } // namespace fuzzing |
| |
| #endif // SRC_SYS_FUZZING_COMMON_COMPONENT_CONTEXT_H_ |