// Copyright 2016 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/sys/appmgr/component_controller_impl.h"

#include <fuchsia/inspect/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fit/bridge.h>
#include <lib/fit/function.h>
#include <lib/inspect/service/cpp/service.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <lib/zx/job.h>
#include <lib/zx/status.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <cinttypes>
#include <string>
#include <utility>

#include <fbl/string_printf.h>
#include <fs/pseudo_file.h>
#include <fs/remote_dir.h>
#include <fs/service.h>
#include <task-utils/walker.h>

#include "fbl/ref_ptr.h"
#include "lib/inspect/service/cpp/service.h"
#include "lib/vfs/cpp/service.h"
#include "src/lib/fsl/handles/object_info.h"
#include "src/sys/appmgr/component_container.h"
#include "src/sys/appmgr/namespace.h"
#include "src/sys/appmgr/realm.h"

namespace component {

using fuchsia::sys::TerminationReason;

namespace {
zx::process DuplicateProcess(const zx::process& process) {
  zx::process ret;
  zx_status_t status = process.duplicate(ZX_RIGHT_SAME_RIGHTS, &ret);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to duplicate process handle: " << status;
  }
  return ret;
}

// TODO(fxbug.dev/46803): The out/diagnostics directory propagation for runners includes a retry.
// The reason of this is that flutter fills the out/ directory *after*
// serving it. Therefore we need to watch that directory to notify.
// Sadly the PseudoDir exposed in the SDK (and used by flutter) returns ZX_ERR_NOT_SUPPORTED on
// Watch. A solution using a watcher is implemented in fxr/366977 pending watch support.
const uint32_t MAX_RETRIES_OUT_DIAGNOSTICS = 30;
const uint32_t OUT_DIAGNOSTICS_INITIAL_RETRY_DELAY_MS = 500;
const uint32_t OUT_DIAGNOSTICS_MAXIMUM_DELAY_MS = 15000;

}  // namespace

ComponentRequestWrapper::ComponentRequestWrapper(
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> request, int64_t default_return,
    fuchsia::sys::TerminationReason default_reason)
    : request_(std::move(request)), return_code_(default_return), reason_(default_reason) {}

ComponentRequestWrapper::~ComponentRequestWrapper() {
  if (request_) {
    FailedComponentController failed(return_code_, reason_, std::move(request_));
  }
}

ComponentRequestWrapper::ComponentRequestWrapper(ComponentRequestWrapper&& other) {
  *this = std::move(other);
}

void ComponentRequestWrapper::operator=(ComponentRequestWrapper&& other) {
  request_ = std::move(other.request_);
  return_code_ = std::move(other.return_code_);
  reason_ = std::move(other.reason_);
}

void ComponentRequestWrapper::SetReturnValues(int64_t return_code, TerminationReason reason) {
  return_code_ = return_code;
  reason_ = reason;
}

FailedComponentController::FailedComponentController(
    int64_t return_code, TerminationReason termination_reason,
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller)
    : binding_(this), return_code_(return_code), termination_reason_(termination_reason) {
  if (controller) {
    binding_.Bind(std::move(controller));
  }
}

FailedComponentController::~FailedComponentController() {
  // This can be false if other side of the channel dies before this object dies.
  if (binding_.is_bound()) {
    binding_.events().OnTerminated(return_code_, termination_reason_);
  }
}

void FailedComponentController::Kill() {}

void FailedComponentController::Detach() {}

ComponentControllerBase::ComponentControllerBase(
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> request, std::string url,
    std::string args, std::string label, std::string hub_instance_id, fxl::RefPtr<Namespace> ns,
    zx::channel exported_dir, zx::channel client_request, uint32_t diagnostics_max_retries)
    : executor_(async_get_default_dispatcher()),
      binding_(this),
      label_(std::move(label)),
      hub_instance_id_(std::move(hub_instance_id)),
      url_(std::move(url)),
      hub_(fbl::AdoptRef(new fs::PseudoDir())),
      ns_(std::move(ns)),
      weak_ptr_factory_(this),
      diagnostics_max_retries_(diagnostics_max_retries),
      diagnostics_retry_backoff_ms_(OUT_DIAGNOSTICS_INITIAL_RETRY_DELAY_MS) {
  if (request.is_valid()) {
    binding_.Bind(std::move(request));
    binding_.set_error_handler([this](zx_status_t /*status*/) { Kill(); });
  }
  if (!exported_dir) {
    return;
  }
  exported_dir_.Bind(std::move(exported_dir), async_get_default_dispatcher());

  if (client_request) {
    fdio_service_connect_at(exported_dir_.channel().get(), "svc", client_request.release());
  }

  ns_->set_component_id(hub_instance_id_);
  hub_.SetName(label_);
  hub_.AddEntry("url", url_);
  hub_.AddEntry("args", std::move(args));
  exported_dir_->Clone(fuchsia::io::OPEN_FLAG_DESCRIBE | fuchsia::io::OPEN_RIGHT_READABLE |
                           fuchsia::io::OPEN_RIGHT_WRITABLE,
                       cloned_exported_dir_.NewRequest());

  cloned_exported_dir_.events().OnOpen = [this](zx_status_t status,
                                                std::unique_ptr<fuchsia::io::NodeInfo> /*info*/) {
    if (status != ZX_OK) {
      FX_LOGS(WARNING) << "could not bind out directory for component" << label_ << "): " << status;
      return;
    }
    out_ready_ = true;
    auto output_dir = fbl::AdoptRef(new fs::RemoteDir(cloned_exported_dir_.Unbind().TakeChannel()));
    hub_.PublishOut(std::move(output_dir));
    NotifyDiagnosticsDirReady(diagnostics_max_retries_);
    TRACE_DURATION_BEGIN("appmgr", "ComponentController::OnDirectoryReady");
    SendOnDirectoryReadyEvent();
    TRACE_DURATION_END("appmgr", "ComponentController::OnDirectoryReady");
  };

  cloned_exported_dir_.set_error_handler(
      [this](zx_status_t status) { cloned_exported_dir_.Unbind(); });
}

void ComponentControllerBase::NotifyDiagnosticsDirReady(uint32_t max_retries) {
  auto promise =
      GetDiagnosticsDir()
          .and_then([self = weak_ptr_factory_.GetWeakPtr()](
                        fidl::InterfaceHandle<fuchsia::io::Directory>& dir) {
            if (self) {
              self->ns_->NotifyComponentDiagnosticsDirReady(self->url_, self->label_,
                                                            self->hub_instance_id_, std::move(dir));
            }
          })
          .or_else([self = weak_ptr_factory_.GetWeakPtr(), max_retries](zx_status_t& status) {
            if (self && status == ZX_ERR_NOT_FOUND) {
              zx::duration next_backoff_duration = zx::msec(self->diagnostics_retry_backoff_ms_);
              self->diagnostics_retry_backoff_ms_ = std::min(
                  self->diagnostics_retry_backoff_ms_ + OUT_DIAGNOSTICS_INITIAL_RETRY_DELAY_MS,
                  OUT_DIAGNOSTICS_MAXIMUM_DELAY_MS);
              async::PostDelayedTask(
                  self->executor_.dispatcher(),
                  [self = std::move(self), max_retries]() {
                    if (self && max_retries > 0) {
                      self->NotifyDiagnosticsDirReady(max_retries - 1);
                    }
                  },
                  next_backoff_duration);
            }
            return fit::error(status);
          });
  executor_.schedule_task(std::move(promise));
}

fit::promise<fidl::InterfaceHandle<fuchsia::io::Directory>, zx_status_t>
ComponentControllerBase::GetDir(std::string path) {
  // This error would occur if the method was called when the component out/ directory wasn't ready
  // yet. This can be triggered when a listener is attached to a realm and notifies about existing
  // components. It could happen that the component exists, but its out is not ready yet. Under such
  // scenario, the listener will receive a START event for the existing component, but won't
  // receive a DIAGNOSTICS_DIR_READY event during the existing flow. The DIAGNOSTICS_READY_EVENT
  // will be triggered later once the out/ directory is ready if the component exposes a
  // diagnostics directory.
  if (!out_ready_) {
    return fit::make_result_promise<fidl::InterfaceHandle<fuchsia::io::Directory>>(
        fit::error(ZX_ERR_BAD_STATE));
  }
  fuchsia::io::NodePtr diagnostics_dir_node;
  fit::bridge<void, zx_status_t> bridge;
  diagnostics_dir_node.events().OnOpen =
      [completer = std::move(bridge.completer), label = label_](
          zx_status_t status, std::unique_ptr<fuchsia::io::NodeInfo> node_info) mutable {
        if (status != ZX_OK) {
          completer.complete_error(status);
        } else if (!node_info) {
          completer.complete_error(ZX_ERR_NOT_FOUND);
        } else if (!node_info->is_directory()) {
          completer.complete_error(ZX_ERR_NOT_DIR);
        } else {
          completer.complete_ok();
        }
      };

  const uint32_t flags = fuchsia::io::OPEN_FLAG_DESCRIBE | fuchsia::io::OPEN_RIGHT_READABLE |
                         fuchsia::io::OPEN_RIGHT_WRITABLE;
  exported_dir_->Open(flags, 0u /* mode */, path, diagnostics_dir_node.NewRequest());
  return bridge.consumer.promise().and_then([diagnostics_dir_node =
                                                 std::move(diagnostics_dir_node)]() mutable {
    auto diagnostics_dir =
        fidl::InterfaceHandle<fuchsia::io::Directory>(diagnostics_dir_node.Unbind().TakeChannel());
    return fit::make_result_promise<fidl::InterfaceHandle<fuchsia::io::Directory>, zx_status_t>(
        fit::ok(std::move(diagnostics_dir)));
  });
}

fit::promise<fidl::InterfaceHandle<fuchsia::io::Directory>, zx_status_t>
ComponentControllerBase::GetDiagnosticsDir() {
  return GetDir("diagnostics");
}

fit::promise<fidl::InterfaceHandle<fuchsia::io::Directory>, zx_status_t>
ComponentControllerBase::GetServiceDir() {
  return GetDir("svc");
}

void ComponentControllerBase::SendOnDirectoryReadyEvent() {
  // This can be false if
  // 1. Other side of the channel dies before this call happens.
  // 2. Component Controller request was not passed while creating the component.
  if (binding_.is_bound()) {
    binding_.events().OnDirectoryReady();
  }
}

void ComponentControllerBase::SendOnTerminationEvent(
    int64_t return_code, fuchsia::sys::TerminationReason termination_reason) {
  // `binding_.is_bound()` can be false if
  //  1. Other side of the channel dies before this call happens.
  //  2. Component Controller request was not passed while creating the component.
  if (on_terminated_event_sent_ || !binding_.is_bound()) {
    return;
  }
  FX_VLOGS(1) << "Sending termination callback with return code: " << return_code;
  binding_.events().OnTerminated(return_code, termination_reason);
  on_terminated_event_sent_ = true;
}

ComponentControllerBase::~ComponentControllerBase() { ns_->FlushAndShutdown(ns_); };

HubInfo ComponentControllerBase::HubInfo() {
  return component::HubInfo(label_, hub_instance_id_, hub_.dir());
}

void ComponentControllerBase::Detach() {
  binding_.set_error_handler([](zx_status_t /*status*/) {});
}

ComponentControllerImpl::ComponentControllerImpl(
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> request,
    ComponentContainer<ComponentControllerImpl>* container, zx::job job, zx::process process,
    std::string url, std::string args, std::string label, fxl::RefPtr<Namespace> ns,
    zx::channel exported_dir, zx::channel client_request, zx::channel package_handle)
    : ComponentControllerBase(std::move(request), std::move(url), std::move(args), std::move(label),
                              std::to_string(fsl::GetKoid(process.get())), std::move(ns),
                              std::move(exported_dir), std::move(client_request)),
      container_(container),
      job_(std::move(job)),
      process_(std::move(process)),
      process_koid_(std::to_string(fsl::GetKoid(process_.get()))),
      job_koid_(std::to_string(fsl::GetKoid(job_.get()))),
      wait_(this, process_.get(), ZX_TASK_TERMINATED),
      system_diagnostics_(DuplicateProcess(process_)) {
  zx_status_t status = wait_.Begin(async_get_default_dispatcher());
  FX_DCHECK(status == ZX_OK);

  hub()->SetJobId(job_koid_);
  hub()->SetProcessId(process_koid_);

  // Serve connections to the system_diagnostics interface.
  auto system_diagnostics = fbl::MakeRefCounted<fs::PseudoDir>();
  system_diagnostics->AddEntry(
      fuchsia::inspect::Tree::Name_,
      fbl::AdoptRef(new fs::Service(
          [handler = inspect::MakeTreeHandler(&system_diagnostics_.inspector())](zx::channel chan) {
            handler(fidl::InterfaceRequest<fuchsia::inspect::Tree>(std::move(chan)));
            return ZX_OK;
          })));

  hub()->AddEntry("system_diagnostics", system_diagnostics);

  hub()->AddIncomingServices(this->incoming_services());

  if (package_handle.is_valid()) {
    hub()->AddPackageHandle(fbl::MakeRefCounted<fs::RemoteDir>(std::move(package_handle)));
  }

  zx::job watch_job;
  if (job_.duplicate(ZX_RIGHT_SAME_RIGHTS, &watch_job) != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to duplicate job handle";
  }
  ComputeComponentInstancePath();
  auto realm = this->ns()->realm();
  if (realm && realm->cpu_watcher() && !instance_path_.empty()) {
    realm->cpu_watcher()->AddTask(instance_path_, std::move(watch_job));
  }
}

ComponentControllerImpl::~ComponentControllerImpl() {
  zx_info_handle_basic_t info = {};
  // Two ways we end up here:
  // 1) OnHandleReady() destroys this object; in which case, process is dead.
  // 2) Our owner destroys this object; in which case, the process may still be
  //    alive.
  if (job_) {
    job_.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
    job_.kill();
    // Our owner destroyed this object before we could obtain a termination
    // reason.

    SendOnTerminationEvent(-1, TerminationReason::UNKNOWN);
  }

  auto realm = this->ns()->realm();
  if (realm && realm->cpu_watcher()) {
    if (!instance_path_.empty()) {
      realm->cpu_watcher()->RemoveTask(instance_path_);
    }
  }

  // Clean up system diagnostics before deleting the backing objects.
  hub()->dir()->RemoveEntry("system_diagnostics");
}

void ComponentControllerImpl::Kill() {
  FX_VLOGS(1) << "ComponentControllerImpl::Kill() called";
  TRACE_DURATION("appmgr", "ComponentController::Kill");
  if (job_) {
    job_.kill();
    job_.reset();
  }
}

bool ComponentControllerImpl::SendReturnCodeIfTerminated() {
  // Get process info.
  zx_info_process_t process_info;
  zx_status_t result =
      process_.get_info(ZX_INFO_PROCESS, &process_info, sizeof(process_info), NULL, NULL);
  FX_DCHECK(result == ZX_OK);

  if (process_info.exited) {
    SendOnTerminationEvent(process_info.return_code, TerminationReason::EXITED);
  }

  return process_info.exited;
}

zx_status_t ComponentControllerImpl::AddSubComponentHub(const component::HubInfo& hub_info) {
  hub()->EnsureComponentDir();
  return hub()->AddComponent(hub_info);
}

zx_status_t ComponentControllerImpl::RemoveSubComponentHub(const component::HubInfo& hub_info) {
  return hub()->RemoveComponent(hub_info);
}

// Called when process terminates, regardless of if Kill() was invoked.
void ComponentControllerImpl::Handler(async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                      zx_status_t status, const zx_packet_signal* signal) {
  FX_DCHECK(status == ZX_OK);
  FX_DCHECK(signal->observed == ZX_TASK_TERMINATED);
  FX_VLOGS(1) << "ComponentControllerImpl::Handler() called";

  bool terminated = SendReturnCodeIfTerminated();
  FX_DCHECK(terminated);

  process_.reset();
  container_->ExtractComponent(this);
  // The destructor of the temporary returned by ExtractComponent destroys
  // |this| at the end of the previous statement.
}

void ComponentControllerImpl::ComputeComponentInstancePath() {
  if (!instance_path_.empty()) {
    return;
  }
  std::vector<std::string> path;
  auto realm = this->ns()->realm();
  if (realm) {
    instance_path_.push_back(this->label());
    auto cur = realm;
    while (cur) {
      instance_path_.push_back(cur->label());
      cur = cur->parent();
    }
    std::reverse(instance_path_.begin(), instance_path_.end());
    instance_path_.push_back(job_koid_);
  }
}

ComponentBridge::ComponentBridge(fidl::InterfaceRequest<fuchsia::sys::ComponentController> request,
                                 fuchsia::sys::ComponentControllerPtr remote_controller,
                                 ComponentContainer<ComponentBridge>* container, std::string url,
                                 std::string args, std::string label, std::string hub_instance_id,
                                 fxl::RefPtr<Namespace> ns, zx::channel exported_dir,
                                 zx::channel client_request,
                                 std::optional<zx::channel> package_handle)
    : ComponentControllerBase(std::move(request), std::move(url), std::move(args), std::move(label),
                              hub_instance_id, std::move(ns), std::move(exported_dir),
                              std::move(client_request), MAX_RETRIES_OUT_DIAGNOSTICS),
      remote_controller_(std::move(remote_controller)),
      container_(std::move(container)),
      termination_reason_(TerminationReason::UNKNOWN) {
  // Forward termination callbacks from the remote component over the bridge.
  remote_controller_.events().OnTerminated = [this](int64_t return_code,
                                                    TerminationReason termination_reason) mutable {
    // Propagate the events to the external proxy.
    if (on_terminated_event_) {
      on_terminated_event_(return_code, termination_reason);
    }

    SendOnTerminationEvent(return_code, termination_reason);
    remote_controller_.events().OnTerminated = nullptr;
    container_->ExtractComponent(this);
  };

  remote_controller_.events().OnDirectoryReady = [this] { SendOnDirectoryReadyEvent(); };

  remote_controller_.set_error_handler([this](zx_status_t status) {
    if (remote_controller_.events().OnTerminated != nullptr) {
      remote_controller_.events().OnTerminated(-1, TerminationReason::UNKNOWN);
    }
  });
  // The destructor of the temporary returned by ExtractComponent destroys
  // |this| at the end of the previous statement.

  hub()->AddIncomingServices(this->incoming_services());
  if (package_handle.has_value() && package_handle->is_valid()) {
    hub()->AddPackageHandle(fbl::MakeRefCounted<fs::RemoteDir>(std::move(*package_handle)));
  }
}

void ComponentBridge::NotifyStopped() {
  ns()->NotifyComponentStopped(url(), label(), hub_instance_id());
}

ComponentBridge::~ComponentBridge() {
  if (remote_controller_.events().OnTerminated) {
    SendOnTerminationEvent(-1, termination_reason_);
  }
}

void ComponentBridge::SetParentJobId(const std::string& id) { hub()->SetJobId(id); }

void ComponentBridge::Kill() { remote_controller_->Kill(); }

void ComponentBridge::SetTerminationReason(TerminationReason termination_reason) {
  termination_reason_ = termination_reason;
}

}  // namespace component
