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