// 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 "garnet/bin/appmgr/component_controller_impl.h"

#include <fbl/string_printf.h>
#include <fs/pseudo-file.h>
#include <fs/remote-dir.h>
#include <lib/async/default.h>
#include <lib/fdio/util.h>
#include <lib/fit/function.h>
#include <trace/event.h>
#include <cinttypes>
#include <utility>

#include "garnet/bin/appmgr/component_container.h"
#include "garnet/bin/appmgr/namespace.h"
#include "lib/fsl/handles/object_info.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) {
    FXL_LOG(ERROR) << "Failed to duplicate process handle: " << status;
  }
  return ret;
}
}  // namespace

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

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

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

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

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

TerminationCallback MakeForwardingTerminationCallback() {
  return TerminationCallback(
      [](int64_t return_code,
         fuchsia::sys::TerminationReason termination_reason,
         fuchsia::sys::ComponentController_EventSender* event) {
        TRACE_DURATION("appmgr", "ComponentController::OnTerminated");
        if (event == nullptr) {
          FXL_LOG(DFATAL)
              << "Termination callback called with null event sender";
          return;
        }
        event->OnTerminated(return_code, termination_reason);
      });
}

FailedComponentController::FailedComponentController(
    int64_t return_code, TerminationReason termination_reason,
    TerminationCallback termination_callback,
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller)
    : binding_(this, std::move(controller)),
      return_code_(return_code),
      termination_reason_(termination_reason),
      termination_callback_(std::move(termination_callback)) {}

FailedComponentController::~FailedComponentController() {
  termination_callback_(return_code_, termination_reason_, &binding_.events());
}

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,
    ExportedDirType export_dir_type, zx::channel exported_dir,
    zx::channel client_request)
    : binding_(this),
      label_(std::move(label)),
      hub_instance_id_(std::move(hub_instance_id)),
      hub_(fbl::AdoptRef(new fs::PseudoDir())),
      ns_(std::move(ns)) {
  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) {
    if (export_dir_type == ExportedDirType::kPublicDebugCtrlLayout) {
      fdio_service_connect_at(exported_dir_.channel().get(), "public",
                              client_request.release());
    } else if (export_dir_type == ExportedDirType::kLegacyFlatLayout) {
      fdio_service_clone_to(exported_dir_.channel().get(),
                            client_request.release());
    }
  }

  hub_.SetName(label_);
  hub_.AddEntry("url", std::move(url));
  hub_.AddEntry("args", std::move(args));
  if (export_dir_type == ExportedDirType::kPublicDebugCtrlLayout) {
    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) {
            FXL_LOG(WARNING) << "could not bind out directory for component"
                             << label_ << "): " << status;
            return;
          }
          auto output_dir = fbl::AdoptRef(
              new fs::RemoteDir(cloned_exported_dir_.Unbind().TakeChannel()));
          hub_.PublishOut(std::move(output_dir));
          TRACE_DURATION_BEGIN("appmgr",
                               "ComponentController::OnDirectoryReady");
          binding_.events().OnDirectoryReady();
          TRACE_DURATION_END("appmgr", "ComponentController::OnDirectoryReady");
        };

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

ComponentControllerBase::~ComponentControllerBase() {}

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

void ComponentControllerBase::Detach() { binding_.set_error_handler(nullptr); }

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, ExportedDirType export_dir_type,
    zx::channel exported_dir, zx::channel client_request,
    TerminationCallback termination_callback)
    : 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(export_dir_type), std::move(exported_dir),
          std::move(client_request)),
      container_(container),
      job_(std::move(job)),
      process_(std::move(process)),
      koid_(std::to_string(fsl::GetKoid(process_.get()))),
      wait_(this, process_.get(), ZX_TASK_TERMINATED),
      termination_callback_(std::move(termination_callback)),
      system_objects_directory_(DuplicateProcess(process_)) {
  zx_status_t status = wait_.Begin(async_get_default_dispatcher());
  FXL_DCHECK(status == ZX_OK);

  hub()->SetJobId(std::to_string(fsl::GetKoid(job_.get())));
  hub()->SetProcessId(koid_);

  hub()->AddEntry("system_objects", system_objects_directory_.object());

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

ComponentControllerImpl::~ComponentControllerImpl() {
  // 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_.kill();
    // Our owner destroyed this object before we could obtain a termination
    // reason.
    if (termination_callback_) {
      termination_callback_(-1, TerminationReason::UNKNOWN, &binding_.events());
      termination_callback_ = nullptr;
    }
  }
}

void ComponentControllerImpl::Kill() {
  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);
  FXL_DCHECK(result == ZX_OK);

  if (process_info.exited) {
    if (termination_callback_) {
      termination_callback_(process_info.return_code, TerminationReason::EXITED,
                            &binding_.events());
      termination_callback_ = nullptr;
    }
  }

  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) {
  FXL_DCHECK(status == ZX_OK);
  FXL_DCHECK(signal->observed == ZX_TASK_TERMINATED);
  bool terminated = SendReturnCodeIfTerminated();
  FXL_DCHECK(terminated);

  process_.reset();

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

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, ExportedDirType export_dir_type,
    zx::channel exported_dir, zx::channel client_request,
    TerminationCallback termination_callback)
    : ComponentControllerBase(
          std::move(request), std::move(url), std::move(args), std::move(label),
          hub_instance_id, std::move(ns), std::move(export_dir_type),
          std::move(exported_dir), std::move(client_request)),
      remote_controller_(std::move(remote_controller)),
      container_(std::move(container)),
      termination_callback_(std::move(termination_callback)),
      termination_reason_(TerminationReason::UNKNOWN) {
  // Forward termination callbacks from the remote component over the bridge.
  remote_controller_.events().OnTerminated =
      [this](int64_t result_code,
             TerminationReason termination_reason) mutable {
        // Propagate the events to the external proxy.
        if (on_terminated_event_) {
          on_terminated_event_(result_code, termination_reason);
        }
        termination_callback_(result_code, termination_reason,
                              &binding_.events());
        remote_controller_.events().OnTerminated = nullptr;
        container_->ExtractComponent(this);
      };

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

  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());
}

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

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
