blob: 6cb4435724e9c4339377924f84167e3b6127b49d [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/developer/shell/console/executor.h"
#include <lib/fdio/spawn.h>
#include <lib/zx/process.h>
#include <zircon/compiler.h>
#include <zircon/status.h>
#include <iostream>
#include <map>
#include <memory>
#include <vector>
#include "src/developer/shell/common/result.h"
namespace shell::console {
Executor::Executor(llcpp::fuchsia::shell::Shell::SyncClient* client)
: context_id_(0), client_(client) {}
Executor::~Executor() = default;
Err Executor::Execute(std::unique_ptr<Command> command,
fit::function<void(const std::string&)> out_callback,
fit::function<void(const std::string&)> err_callback,
fit::callback<void()> done_callback) {
if (!command->parse_error().ok()) {
std::string msg = "Invalid command: ";
msg.append(command->parse_error().msg);
err_callback(msg);
return Err(ZX_ERR_NEXT, zx_status_get_string(ZX_ERR_NEXT));
}
if (command->nodes().empty()) {
return Err(ZX_ERR_NEXT, zx_status_get_string(ZX_ERR_NEXT));
}
bool done = false;
context_id_ += 1;
llcpp::fuchsia::shell::Shell::ResultOf::CreateExecutionContext create_result =
client_->CreateExecutionContext(context_id_);
if (!create_result.ok()) {
return Err(create_result.status(), create_result.error());
}
// TODO: Make sure that add_result is small enough to fit in a single FIDL message. Otherwise,
// split it.
llcpp::fuchsia::shell::Shell::ResultOf::AddNodes add_result =
client_->AddNodes(context_id_, command->nodes().DefsAsVectorView());
if (!add_result.ok()) {
return Err(add_result.status(), add_result.error());
}
llcpp::fuchsia::shell::Shell::ResultOf::ExecuteExecutionContext execute_result =
client_->ExecuteExecutionContext(context_id_);
if (!execute_result.ok()) {
return Err(execute_result.status(), execute_result.error());
}
llcpp::fuchsia::shell::Shell::EventHandlers handlers;
handlers.on_text_result =
[&out_callback](llcpp::fuchsia::shell::Shell::OnTextResultResponse* message) {
out_callback(message->result.data());
return ZX_OK;
};
handlers.on_execution_done =
[&done](llcpp::fuchsia::shell::Shell::OnExecutionDoneResponse* message) {
done = true;
return ZX_OK;
};
handlers.on_error = [&err_callback](llcpp::fuchsia::shell::Shell::OnErrorResponse* message) {
err_callback(message->error_message.data());
return ZX_OK;
};
handlers.on_result = [&err_callback,
&out_callback](llcpp::fuchsia::shell::Shell::OnResultResponse* message) {
if (message->partial_result) {
err_callback("Result too large: partial results not supported");
return ZX_OK;
}
std::stringstream ss;
shell::common::DeserializeResult deserialize;
deserialize.Deserialize(message->nodes)->Dump(ss);
out_callback(ss.str());
return ZX_OK;
};
while (!done) {
::fidl::Result result = client_->HandleEvents(handlers);
if (!result.ok()) {
return Err(result.status(), result.status_string());
}
}
if (done_callback != nullptr) {
done_callback();
}
return Err(ZX_ERR_NEXT, zx_status_get_string(ZX_ERR_NEXT));
}
void Executor::KillForegroundTask() {
// TODO(fidl-tools-team): What happens when we hit ^C?
}
} // namespace shell::console