// 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::MakeRefCounted<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::MakeRefCounted<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::MakeRefCounted<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
