blob: 9deec9eedf1d498e7a07c53caffd43ce0362b1b7 [file] [log] [blame]
// Copyright 2019 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 "src/virtualization/lib/guest_interaction/client/guest_interaction_service.h"
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <stdlib.h>
#include "src/virtualization/lib/grpc/fdio_util.h"
#include "src/virtualization/lib/guest_interaction/common.h"
static int run_grpc_loop(void* service_to_run) {
FuchsiaGuestInteractionService* gis = (FuchsiaGuestInteractionService*)service_to_run;
gis->Run();
return 0;
}
FuchsiaGuestInteractionService::FuchsiaGuestInteractionService(zx::socket socket)
: executor_(async_get_default_dispatcher()) {
int32_t vsock_fd = ConvertSocketToNonBlockingFd(std::move(socket));
if (vsock_fd < 0) {
abort();
}
client_ = std::make_unique<ClientImpl<PosixPlatform>>(vsock_fd);
thrd_create_with_name(&guest_interaction_service_thread_, run_grpc_loop, this, "gRPC run");
}
FuchsiaGuestInteractionService::~FuchsiaGuestInteractionService() { Stop(); }
fit::promise<zx_status_t> FuchsiaGuestInteractionService::InitiatePut(
zx::channel local_file, const std::string& remote_path) {
fit::bridge<zx_status_t> bridge;
client_->Put(std::move(local_file), remote_path,
[completer = std::move(bridge.completer)](zx_status_t status) mutable {
completer.complete_ok(status);
});
return bridge.consumer.promise();
}
void FuchsiaGuestInteractionService::PutFile(fidl::InterfaceHandle<fuchsia::io::File> local_file,
std::string remote_path,
fit::function<void(zx_status_t)> callback) {
executor_.schedule_task(
InitiatePut(local_file.TakeChannel(), remote_path)
.and_then([callback = std::move(callback),
local_file = std::move(local_file)](zx_status_t& status) { callback(status); })
.wrap_with(scope_));
}
fit::promise<zx_status_t> FuchsiaGuestInteractionService::InitiateGet(
const std::string& remote_path, zx::channel local_file) {
fit::bridge<zx_status_t> bridge;
client_->Get(remote_path, std::move(local_file),
[completer = std::move(bridge.completer)](zx_status_t status) mutable {
completer.complete_ok(status);
});
return bridge.consumer.promise();
}
void FuchsiaGuestInteractionService::GetFile(std::string remote_path,
fidl::InterfaceHandle<fuchsia::io::File> local_file,
fit::function<void(zx_status_t)> callback) {
executor_.schedule_task(
InitiateGet(remote_path, local_file.TakeChannel())
.and_then([callback = std::move(callback),
local_file = std::move(local_file)](zx_status_t& status) { callback(status); })
.wrap_with(scope_));
}
void FuchsiaGuestInteractionService::ExecuteCommand(
std::string command, std::vector<fuchsia::netemul::guest::EnvironmentVariable> env,
zx::socket std_in, zx::socket std_out, zx::socket std_err,
fidl::InterfaceRequest<fuchsia::netemul::guest::CommandListener> req) {
std::map<std::string, std::string> env_map;
for (const auto& env_var : env) {
env_map[env_var.key] = env_var.value;
}
client_->Exec(command, std::move(env_map), std::move(std_in), std::move(std_out),
std::move(std_err), std::move(req));
}
void FuchsiaGuestInteractionService::AddBinding(
fidl::InterfaceRequest<fuchsia::netemul::guest::GuestInteraction> request) {
bindings_.AddBinding(this, std::move(request));
}
void FuchsiaGuestInteractionService::Run() {
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
async_set_default_dispatcher(loop.dispatcher());
loop.StartThread();
client_->Run();
loop.Quit();
}
void FuchsiaGuestInteractionService::Stop() {
client_->Stop();
int32_t ret_code;
thrd_join(guest_interaction_service_thread_, &ret_code);
}