// 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/function.h>
#include <lib/fpromise/bridge.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 <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/lib/storage/vfs/cpp/pseudo_file.h"
#include "src/lib/storage/vfs/cpp/remote_dir.h"
#include "src/lib/storage/vfs/cpp/service.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::OpenFlags::DESCRIBE | fuchsia::io::OpenFlags::RIGHT_READABLE |
                           fuchsia::io::OpenFlags::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 fpromise::error(status);
          });
  executor_.schedule_task(std::move(promise));
}

fpromise::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 fpromise::make_result_promise<fidl::InterfaceHandle<fuchsia::io::Directory>>(
        fpromise::error(ZX_ERR_BAD_STATE));
  }
  fuchsia::io::NodePtr diagnostics_dir_node;
  fpromise::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 fuchsia::io::OpenFlags flags = fuchsia::io::OpenFlags::DESCRIBE |
                                       fuchsia::io::OpenFlags::RIGHT_READABLE |
                                       fuchsia::io::OpenFlags::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 fpromise::make_result_promise<fidl::InterfaceHandle<fuchsia::io::Directory>,
                                         zx_status_t>(fpromise::ok(std::move(diagnostics_dir)));
  });
}

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

fpromise::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::make_unique<JobStatsReader>(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.flags & ZX_INFO_PROCESS_FLAG_EXITED) {
    SendOnTerminationEvent(process_info.return_code, TerminationReason::EXITED);
  }

  return (process_info.flags & ZX_INFO_PROCESS_FLAG_EXITED) != 0;
}

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
