blob: de3e9cf6994015f5865adbda7afff027e1ac3698 [file] [log] [blame]
// Copyright 2021 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 "icd_runner.h"
#include <fidl/fuchsia.component.runner/cpp/fidl.h>
#include <fidl/fuchsia.io/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/default.h>
#include <lib/syslog/cpp/macros.h>
#include "src/storage/lib/vfs/cpp/pseudo_dir.h"
#include "src/storage/lib/vfs/cpp/remote_dir.h"
#include "src/storage/lib/vfs/cpp/synchronous_vfs.h"
#include "src/storage/lib/vfs/cpp/vfs_types.h"
ComponentControllerImpl::ComponentControllerImpl(async_dispatcher_t* dispatcher)
: vfs_(dispatcher) {}
zx::result<std::unique_ptr<fidl::Server<fuchsia_component_runner::ComponentController>>>
ComponentControllerImpl::Bind(
async_dispatcher_t* dispatcher,
fidl::ServerEnd<fuchsia_component_runner::ComponentController> controller,
fidl::ServerEnd<fuchsia_io::Directory> outgoing_dir,
fidl::ClientEnd<fuchsia_io::Directory> pkg_directory) {
std::unique_ptr<ComponentControllerImpl> server(new ComponentControllerImpl(dispatcher));
auto root = fbl::MakeRefCounted<fs::PseudoDir>();
auto remote = fbl::MakeRefCounted<fs::RemoteDir>(std::move(pkg_directory));
root->AddEntry("pkg", remote);
zx_status_t status =
server->vfs_.ServeDirectory(root, std::move(outgoing_dir), fs::Rights::ReadExec());
if (status != ZX_OK) {
FX_PLOGS(ERROR, status) << "Failed to serve package directory!";
return zx::error(status);
}
server->binding_ = fidl::BindServer(dispatcher, std::move(controller), server.get());
return zx::ok(std::move(server));
}
zx::result<> IcdRunnerImpl::Add(std::unique_ptr<IcdRunnerImpl> component_runner,
component::OutgoingDirectory& outgoing_dir) {
return outgoing_dir.AddProtocol<fuchsia_component_runner::ComponentRunner>(
std::move(component_runner));
}
void IcdRunnerImpl::Start(StartRequest& request, StartCompleter::Sync& completer) {
fidl::ServerEnd controller = std::move(request.controller());
if (!controller.is_valid()) {
FX_LOGS(ERROR) << "Invalid controller handle in start request!";
controller.Close(ZX_ERR_BAD_HANDLE);
return;
}
if (!request.start_info().outgoing_dir()) {
FX_LOGS(ERROR) << "Missing outgoing directory handle in start request!";
controller.Close(ZX_ERR_INVALID_ARGS);
return;
}
fidl::ServerEnd outgoing_dir = *std::move(request.start_info().outgoing_dir());
if (!outgoing_dir.is_valid()) {
FX_LOGS(ERROR) << "Invalid outgoing directory handle in start request!";
controller.Close(ZX_ERR_BAD_HANDLE);
return;
}
fidl::ClientEnd<fuchsia_io::Directory> pkg_directory;
for (auto& ns_entry : *request.start_info().ns()) {
if (ns_entry.path() == std::nullopt || ns_entry.directory() == std::nullopt) {
break;
}
if (ns_entry.path() != "/pkg") {
continue;
}
pkg_directory = std::move(*ns_entry.directory());
break;
}
if (!pkg_directory.is_valid()) {
FX_LOGS(ERROR) << "No package directory found for " << *request.start_info().resolved_url();
request.controller().Close(ZX_ERR_INVALID_ARGS);
return;
}
zx::result controller_server = ComponentControllerImpl::Bind(
dispatcher_, std::move(controller), std::move(outgoing_dir), std::move(pkg_directory));
if (controller_server.is_ok()) {
controller_server_ = *std::move(controller_server);
} else {
FX_LOGS(ERROR) << "Failed to bind controller: " << controller_server.status_string();
}
}