// 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 "device-controller-connection.h"

#include <fbl/auto_lock.h>
#include <fuchsia/device/c/fidl.h>
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/zx/vmo.h>
#include <zircon/status.h>

#include "../shared/env.h"
#include "../shared/fidl_txn.h"
#include "../shared/log.h"
#include "connection-destroyer.h"
#include "devhost.h"
#include "proxy-iostate.h"
#include "zx-device.h"

namespace devmgr {

namespace {

namespace fuchsia = ::llcpp::fuchsia;

// Handles outstanding calls to fuchsia.device.manager.DeviceController/BindDriver
// and fuchsia.device.Controller/Bind.
zx_status_t BindReply(const fbl::RefPtr<zx_device_t>& dev,
                      DeviceControllerConnection::BindDriverCompleter::Sync completer,
                      zx_status_t status, zx::channel test_output = zx::channel()) {
  zx_status_t bind_status = ZX_OK;
  completer.Reply(status, std::move(test_output));

  fs::FidlConnection conn(fidl_txn_t{}, ZX_HANDLE_INVALID, 0);
  if (dev->PopBindConn(&conn)) {
    bind_status = fuchsia_device_ControllerBind_reply(conn.Txn(), status);
  }

  return bind_status;
}

}  // namespace

void DeviceControllerConnection::CompleteCompatibilityTests(
    llcpp::fuchsia::device::manager::CompatibilityTestStatus status,
    CompleteCompatibilityTestsCompleter::Sync completer) {
  const auto& dev = this->dev();
  fs::FidlConnection conn(fidl_txn_t{}, ZX_HANDLE_INVALID, 0);
  if (dev->PopTestCompatibilityConn(&conn)) {
    fuchsia_device_ControllerRunCompatibilityTests_reply(conn.Txn(), static_cast<uint32_t>(status));
  }
}

void DeviceControllerConnection::Suspend(uint32_t flags, SuspendCompleter::Sync completer) {
  zx_status_t r;
  {
    ApiAutoLock lock;
    r = devhost_device_suspend(this->dev(), flags);
  }
  completer.Reply(r);
}

void DeviceControllerConnection::Resume(uint32_t target_system_state, ResumeCompleter::Sync completer) {
  zx_status_t r;
  {
    ApiAutoLock lock;
    r = devhost_device_resume(this->dev(), target_system_state);
  }
  completer.Reply(r);
}

void DeviceControllerConnection::ConnectProxy(::zx::channel shadow,
                                              ConnectProxyCompleter::Sync _completer) {
  log(RPC_SDW, "devhost connect proxy rpc\n");
  this->dev()->ops->rxrpc(this->dev()->ctx, ZX_HANDLE_INVALID);
  // Ignore any errors in the creation for now?
  // TODO(teisenbe): Investigate if this is the right thing
  ProxyIostate::Create(this->dev(), std::move(shadow), DevhostAsyncLoop()->dispatcher());
}

void DeviceControllerConnection::RemoveDevice(RemoveDeviceCompleter::Sync completer) {
  device_remove(this->dev().get());
}

void DeviceControllerConnection::BindDriver(::fidl::StringView driver_path_view, zx::vmo driver,
                                            BindDriverCompleter::Sync completer) {
  const auto& dev = this->dev();
  fbl::StringPiece driver_path(driver_path_view.data(), driver_path_view.size());

  // get path
  char buffer[512];
  const char* path = mkdevpath(dev, buffer, sizeof(buffer));

  // TODO: api lock integration
  log(ERROR, "devhost[%s] bind driver '%.*s'\n", path, static_cast<int>(driver_path.size()),
      driver_path.data());
  fbl::RefPtr<zx_driver_t> drv;
  if (dev->flags & DEV_FLAG_DEAD) {
    log(ERROR, "devhost[%s] bind to removed device disallowed\n", path);
    BindReply(dev, std::move(completer), ZX_ERR_IO_NOT_PRESENT);
    return;
  }

  zx_status_t r;
  if ((r = dh_find_driver(driver_path, std::move(driver), &drv)) < 0) {
    log(ERROR, "devhost[%s] driver load failed: %d\n", path, r);
    BindReply(dev, std::move(completer), r);
    return;
  }

  // Check for driver test flags.
  bool tests_default = getenv_bool("driver.tests.enable", false);
  char tmp[128];
  snprintf(tmp, sizeof(tmp), "driver.%s.tests.enable", drv->name());
  zx::channel test_output;
  if (getenv_bool(tmp, tests_default) && drv->has_run_unit_tests_op()) {
    zx::channel test_input;
    zx::channel::create(0, &test_input, &test_output);
    bool tests_passed = drv->RunUnitTestsOp(dev, std::move(test_input));
    if (!tests_passed) {
      log(ERROR, "devhost: driver '%s' unit tests failed\n", drv->name());
      drv->set_status(ZX_ERR_BAD_STATE);
      BindReply(dev, std::move(completer), ZX_ERR_BAD_STATE, std::move(test_output));
      return;
    }
    log(INFO, "devhost: driver '%s' unit tests passed\n", drv->name());
  }

  if (drv->has_bind_op()) {
    BindContext bind_ctx = {
        .parent = dev,
        .child = nullptr,
    };
    r = drv->BindOp(&bind_ctx, dev);

    if ((r == ZX_OK) && (bind_ctx.child == nullptr)) {
      printf("devhost: WARNING: driver '%.*s' did not add device in bind()\n",
             static_cast<int>(driver_path.size()), driver_path.data());
    }
    if (r != ZX_OK) {
      log(ERROR, "devhost[%s] bind driver '%.*s' failed: %d\n", path,
          static_cast<int>(driver_path.size()), driver_path.data(), r);
    }
    BindReply(dev, std::move(completer), r, std::move(test_output));
    return;
  }

  if (!drv->has_create_op()) {
    log(ERROR, "devhost[%s] neither create nor bind are implemented: '%.*s'\n", path,
        static_cast<int>(driver_path.size()), driver_path.data());
  }
  BindReply(dev, std::move(completer), ZX_ERR_NOT_SUPPORTED, std::move(test_output));
}

void DeviceControllerConnection::Unbind(UnbindCompleter::Sync completer) {
  ApiAutoLock lock;
  devhost_device_unbind(this->dev());
}

void DeviceControllerConnection::CompleteRemoval(CompleteRemovalCompleter::Sync completer) {
  ApiAutoLock lock;
  devhost_device_complete_removal(this->dev());
}

DeviceControllerConnection::DeviceControllerConnection(fbl::RefPtr<zx_device> dev, zx::channel rpc)
    : dev_(std::move(dev)) {
  dev_->rpc = zx::unowned_channel(rpc);
  dev_->conn.store(this);
  set_channel(std::move(rpc));
}

DeviceControllerConnection::~DeviceControllerConnection() {
  // Ensure that the device has no dangling references to the resources we're
  // destroying.  This is safe because a device only ever has one associated
  // DeviceControllerConnection.
  dev_->conn.store(nullptr);
  dev_->rpc = zx::unowned_channel();
}

zx_status_t DeviceControllerConnection::Create(fbl::RefPtr<zx_device> dev, zx::channel rpc,
                                               std::unique_ptr<DeviceControllerConnection>* conn) {
  *conn = std::make_unique<DeviceControllerConnection>(std::move(dev), std::move(rpc));
  if (*conn == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }
  return ZX_OK;
}

// Handler for when a io.fidl open() is called on a device
void DeviceControllerConnection::Open(uint32_t flags, uint32_t mode, ::fidl::StringView path,
                                      ::zx::channel object, OpenCompleter::Sync completer) {
  if (path.size() != 1 && path.data()[0] != '.') {
    log(ERROR, "devhost: Tried to open path '%.*s'\n", static_cast<int>(path.size()), path.data());
  }
  devhost_device_connect(this->dev(), flags, std::move(object));
}

void DeviceControllerConnection::HandleRpc(std::unique_ptr<DeviceControllerConnection> conn,
                                           async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                           zx_status_t status, const zx_packet_signal_t* signal) {
  if (status != ZX_OK) {
    log(ERROR, "devhost: devcoord conn wait error: %d\n", status);
    return;
  }
  if (signal->observed & ZX_CHANNEL_READABLE) {
    zx_status_t r = conn->HandleRead();
    if (r != ZX_OK) {
      if (conn->dev_->conn.load() == nullptr && (r == ZX_ERR_INTERNAL || r == ZX_ERR_PEER_CLOSED)) {
        // Treat this as a PEER_CLOSED below.  It can happen if the
        // devcoordinator sent us a request while we asked the
        // devcoordinator to remove us.  The coordinator then closes the
        // channel before we can reply, and the FIDL bindings convert
        // the PEER_CLOSED on zx_channel_write() to a ZX_ERR_INTERNAL.  See ZX-4114.
        __UNUSED auto r = conn.release();
        return;
      }
      log(ERROR, "devhost: devmgr rpc unhandleable ios=%p r=%d. fatal.\n", conn.get(), r);
      abort();
    }
    BeginWait(std::move(conn), dispatcher);
    return;
  }
  if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
    // Check if we were expecting this peer close.  If not, this could be a
    // serious bug.
    if (conn->dev_->conn.load() == nullptr) {
      // We're in the middle of shutting down, so just stop processing
      // signals and wait for the queued shutdown packet.  It has a
      // reference to the connection, which it will use to recover
      // ownership of it.
      __UNUSED auto r = conn.release();
      return;
    }

    log(ERROR, "devhost: devmgr disconnected! fatal. (conn=%p)\n", conn.get());
    abort();
  }
  log(ERROR, "devhost: no work? %08x\n", signal->observed);
  BeginWait(std::move(conn), dispatcher);
}

zx_status_t DeviceControllerConnection::HandleRead() {
  zx::unowned_channel conn = channel();
  uint8_t msg[8192];
  zx_handle_t hin[ZX_CHANNEL_MAX_MSG_HANDLES];
  uint32_t msize = sizeof(msg);
  uint32_t hcount = fbl::count_of(hin);
  zx_status_t status = conn->read(0, msg, hin, msize, hcount, &msize, &hcount);
  if (status != ZX_OK) {
    return status;
  }

  fidl_msg_t fidl_msg = {
      .bytes = msg,
      .handles = hin,
      .num_bytes = msize,
      .num_handles = hcount,
  };

  if (fidl_msg.num_bytes < sizeof(fidl_message_header_t)) {
    zx_handle_close_many(fidl_msg.handles, fidl_msg.num_handles);
    return ZX_ERR_IO;
  }

  char buffer[512];
  const char* path = mkdevpath(dev_, buffer, sizeof(buffer));

  auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
  // Depending on the state of the migration, GenOrdinal and Ordinal may be the
  // same value.  See FIDL-524.
  uint64_t ordinal = hdr->ordinal;
  if (ordinal == fuchsia_io_DirectoryOpenOrdinal || ordinal == fuchsia_io_DirectoryOpenGenOrdinal) {
    log(RPC_RIO, "devhost[%s] FIDL OPEN\n", path);
    zx::unowned_channel conn = channel();
    DevmgrFidlTxn txn(std::move(conn), hdr->txid);
    fuchsia::io::Directory::Dispatch(this, &fidl_msg, &txn);
    if (status != ZX_OK) {
      return txn.Status();
    }
    return txn.Status();
  }

  DevmgrFidlTxn txn(std::move(conn), hdr->txid);
  fuchsia::device::manager::DeviceController::Dispatch(this, &fidl_msg, &txn);
  return txn.Status();
}

}  // namespace devmgr
