blob: 4bfc908cd2f8db7b7dd9ba7c6fd60b7ad23ddfa6 [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.
#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_