blob: 68c7bf4133ddf455783b67ff7a4a3e6c9ab48a2d [file] [log] [blame]
// Copyright 2020 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 <fuchsia/sys/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/sys/cpp/service_directory.h>
void LaunchServer(std::string server_url, const sys::ServiceDirectory& svc,
fidl::InterfaceRequest<fuchsia::io::Directory> directory_request,
fidl::InterfaceRequest<fuchsia::sys::ComponentController> ctrl_request) {
fuchsia::sys::LauncherPtr launcher;
svc.Connect(launcher.NewRequest());
fuchsia::sys::LaunchInfo server_info{
.url = std::move(server_url),
.directory_request = directory_request.TakeChannel(),
};
launcher->CreateComponent(std::move(server_info), std::move(ctrl_request));
}
void CreateNestedEnv(std::vector<std::string> protocol_names, const sys::ServiceDirectory& svc,
fidl::InterfaceHandle<fuchsia::io::Directory> directory,
fidl::InterfaceRequest<fuchsia::sys::EnvironmentController> env_ctrl_request,
fidl::InterfaceRequest<fuchsia::sys::Launcher> launcher_request) {
fuchsia::sys::EnvironmentPtr env;
svc.Connect(env.NewRequest());
fuchsia::sys::EnvironmentPtr nested_env;
std::unique_ptr<fuchsia::sys::ServiceList> services(new fuchsia::sys::ServiceList);
services->names = std::move(protocol_names);
services->host_directory = directory.TakeChannel();
fuchsia::sys::EnvironmentOptions options;
options.inherit_parent_services = true;
env->CreateNestedEnvironment(nested_env.NewRequest(), std::move(env_ctrl_request), "echo",
std::move(services), std::move(options));
nested_env->GetLauncher(std::move(launcher_request));
}
void LaunchClient(std::string client_url, fuchsia::sys::LauncherPtr launcher,
fidl::InterfaceRequest<fuchsia::sys::ComponentController> ctrl_request) {
fuchsia::sys::LaunchInfo client_info{.url = std::move(client_url)};
launcher->CreateComponent(std::move(client_info), std::move(ctrl_request));
}
int64_t LaunchComponents(std::string client_url, std::string server_url,
std::vector<std::string> capability_names) {
async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
auto svc = sys::ServiceDirectory::CreateFromNamespace();
fidl::InterfaceHandle<fuchsia::io::Directory> directory;
fuchsia::sys::ComponentControllerPtr server_controller;
LaunchServer(std::move(server_url), *svc, directory.NewRequest(), server_controller.NewRequest());
// create nested environment with the server's capabilities
fuchsia::sys::EnvironmentControllerPtr nested_env_ctrl;
fuchsia::sys::LauncherPtr client_launcher;
CreateNestedEnv(std::move(capability_names), *svc, std::move(directory),
nested_env_ctrl.NewRequest(), client_launcher.NewRequest());
fuchsia::sys::ComponentControllerPtr client_controller;
LaunchClient(std::move(client_url), std::move(client_launcher), client_controller.NewRequest());
// terminate once client terminates
int64_t client_status = -1;
client_controller.events().OnTerminated =
[&loop, &client_status](uint64_t code, fuchsia::sys::TerminationReason reason) {
client_status = code;
printf("client exit code: %lu, reason: %d\n", code, reason);
loop.Quit();
};
loop.Run();
return client_status;
}