// 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 <fuchsia/device/c/fidl.h>
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/zx/vmo.h>
#include <zircon/status.h>

#include <fbl/auto_lock.h>
#include <fbl/string_printf.h>

#include "connection_destroyer.h"
#include "driver_host.h"
#include "env.h"
#include "fidl_txn.h"
#include "fuchsia/device/llcpp/fidl.h"
#include "log.h"
#include "proxy_iostate.h"
#include "zx_device.h"
#include "zx_driver.h"

namespace {

namespace fuchsia = ::llcpp::fuchsia;

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

  bool complete_bind = true;
  for (auto& child : dev->children()) {
    if ((child.flags() & DEV_FLAG_INVISIBLE) || child.ops()->init) {
      // Driver has initialization to do.
      complete_bind = false;
    }
  }
  if (!complete_bind) {
    dev->set_complete_bind_rebind_after_init(true);
    return;
  }
  if (auto bind_conn = dev->take_bind_conn(); bind_conn) {
    bind_conn(status);
  }

  if (auto rebind_conn = dev->take_rebind_conn(); rebind_conn) {
    rebind_conn(status);
  }
}

}  // namespace

void DeviceControllerConnection::CompleteCompatibilityTests(
    llcpp::fuchsia::device::manager::CompatibilityTestStatus status,
    CompleteCompatibilityTestsCompleter::Sync& _completer) {
  if (auto compat_conn = dev()->PopTestCompatibilityConn(); compat_conn) {
    compat_conn(static_cast<zx_status_t>(status));
  }
}

void DeviceControllerConnection::Init(InitCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->init_cb == nullptr);

  auto trace = this->dev()->BeginAsyncTrace("driver_host:lifecycle", "init");
  this->dev()->init_cb = [completer = completer.ToAsync(), trace = std::move(trace)](
                             zx_status_t status) mutable { completer.Reply(status); };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceInit(this->dev());
}

void DeviceControllerConnection::Suspend(uint32_t flags, SuspendCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->suspend_cb == nullptr);

  auto trace = this->dev()->BeginAsyncTrace("driver_host:lifecycle", "suspend");
  this->dev()->suspend_cb = [completer = completer.ToAsync(), trace = std::move(trace)](
                                zx_status_t status, uint8_t out_state) mutable {
    if (status == ZX_ERR_NOT_SUPPORTED) {
      status = ZX_OK;
    }
    completer.Reply(status);
  };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceSystemSuspend(this->dev(), flags);
}

void DeviceControllerConnection::Resume(uint32_t target_system_state,
                                        ResumeCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->resume_cb == nullptr);

  auto trace = this->dev()->BeginAsyncTrace("driver_host:lifecycle", "resume");
  this->dev()->resume_cb = [completer = completer.ToAsync(), trace = std::move(trace)](
                               zx_status_t status, uint8_t out_power_state,
                               uint32_t out_perf_state) mutable {
    if (status == ZX_ERR_NOT_SUPPORTED) {
      status = ZX_OK;
    }
    if (status != ZX_OK &&
        (out_power_state ==
         static_cast<uint8_t>(llcpp::fuchsia::device::DevicePowerState::DEVICE_POWER_STATE_D0))) {
      // Do not fail system resume, when the device is unable to go into a particular performance
      // state, but resumed to a working state.
      status = ZX_OK;
    }
    completer.Reply(status);
  };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceSystemResume(this->dev(), target_system_state);
}

void DeviceControllerConnection::ConnectProxy(::zx::channel shadow,
                                              ConnectProxyCompleter::Sync& _completer) {
  VLOGD(1, *dev(), "Connected to proxy for device %p", dev().get());
  dev()->ops()->rxrpc(dev()->ctx, ZX_HANDLE_INVALID);
  // Ignore any errors in the creation for now?
  // TODO(teisenbe): Investigate if this is the right thing
  ProxyIostate::Create(dev(), std::move(shadow), driver_host_context_->loop().dispatcher());
}

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

  // TODO: api lock integration
  LOGD(INFO, *dev, "Binding driver '%.*s'", static_cast<int>(driver_path.size()),
       driver_path.data());
  fbl::RefPtr<zx_driver_t> drv;
  if (dev->flags() & DEV_FLAG_DEAD) {
    LOGD(ERROR, *dev, "Cannot bind to removed device");
    BindReply(dev, completer, ZX_ERR_IO_NOT_PRESENT);
    return;
  }

  zx_status_t r = driver_host_context_->FindDriver(driver_path, std::move(driver), &drv);
  if (r != ZX_OK) {
    LOGD(ERROR, *dev, "Failed to load driver '%.*s': %s", static_cast<int>(driver_path.size()),
         driver_path.data(), zx_status_get_string(r));
    BindReply(dev, completer, r);
    return;
  }

  // Check for driver test flags.
  bool tests_default = getenv_bool("driver.tests.enable", false);
  auto option = fbl::StringPrintf("driver.%s.tests.enable", drv->name());
  zx::channel test_output;
  if (getenv_bool(option.data(), 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) {
      FX_LOGF(ERROR, "unit-tests", "[  FAILED  ] %s", drv->name());
      drv->set_status(ZX_ERR_BAD_STATE);
      BindReply(dev, completer, ZX_ERR_BAD_STATE, std::move(test_output));
      return;
    }
    FX_LOGF(INFO, "unit-tests", "[  PASSED  ] %s", drv->name());
  }

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

    if (r != ZX_OK) {
      LOGD(ERROR, *dev, "Failed to bind driver '%.*s': %s", static_cast<int>(driver_path.size()),
           driver_path.data(), zx_status_get_string(r));
    } else if (bind_ctx.child == nullptr) {
      LOGD(WARNING, *dev, "Driver '%.*s' did not add a child device in bind()",
           static_cast<int>(driver_path.size()), driver_path.data());
    }
    BindReply(dev, completer, r, std::move(test_output));
    return;
  }

  if (!drv->has_create_op()) {
    LOGD(ERROR, *dev, "Neither create() nor bind() are implemented for driver '%.*s'",
         static_cast<int>(driver_path.size()), driver_path.data());
  }
  BindReply(dev, completer, ZX_ERR_NOT_SUPPORTED, std::move(test_output));
}

void DeviceControllerConnection::Unbind(UnbindCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->unbind_cb == nullptr);

  auto trace = this->dev()->BeginAsyncTrace("driver_host:lifecycle", "unbind");

  this->dev()->unbind_cb = [dev = this->dev(), completer = completer.ToAsync(),
                            trace = std::move(trace)](zx_status_t status) mutable {
    llcpp::fuchsia::device::manager::DeviceController_Unbind_Result result;
    fidl::aligned<llcpp::fuchsia::device::manager::DeviceController_Unbind_Response> response;
    if (status != ZX_OK && dev->parent()) {
      // If unbind returns an error, and if client is waiting for unbind to complete,
      // inform the client.
      if (auto unbind_children_conn = dev->parent()->take_unbind_children_conn();
          unbind_children_conn) {
        unbind_children_conn(status);
      }
    }
    result.set_response(fidl::unowned_ptr(&response));
    completer.Reply(std::move(result));
  };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceUnbind(this->dev());
}

void DeviceControllerConnection::CompleteRemoval(CompleteRemovalCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->removal_cb == nullptr);
  this->dev()->removal_cb = [completer = completer.ToAsync()](zx_status_t status) mutable {
    llcpp::fuchsia::device::manager::DeviceController_CompleteRemoval_Result result;
    fidl::aligned<llcpp::fuchsia::device::manager::DeviceController_CompleteRemoval_Response>
        response;
    result.set_response(fidl::unowned_ptr(&response));
    completer.Reply(std::move(result));
  };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceCompleteRemoval(this->dev());
}

DeviceControllerConnection::DeviceControllerConnection(DriverHostContext* ctx,
                                                       fbl::RefPtr<zx_device> dev, zx::channel rpc,
                                                       zx::channel coordinator_rpc)
    : driver_host_context_(ctx), dev_(std::move(dev)) {
  dev_->rpc = zx::unowned_channel(rpc);
  dev_->coordinator_rpc = zx::unowned_channel(coordinator_rpc);
  dev_->conn.store(this);
  set_channel(std::move(rpc));
  set_coordinator_channel(std::move(coordinator_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(DriverHostContext* ctx, fbl::RefPtr<zx_device> dev,
                                               zx::channel controller_rpc,
                                               zx::channel coordinator_rpc,
                                               std::unique_ptr<DeviceControllerConnection>* conn) {
  *conn = std::make_unique<DeviceControllerConnection>(
      ctx, std::move(dev), std::move(controller_rpc), std::move(coordinator_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] != '.') {
    LOGD(ERROR, *dev(), "Attempt to open path '%.*s'", static_cast<int>(path.size()), path.data());
  }
  driver_host_context_->DeviceConnect(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) {
  const auto& dev = conn->dev_;
  if (status != ZX_OK) {
    LOGD(ERROR, *dev, "Failed to wait for device controller connection: %s",
         zx_status_get_string(status));
    return;
  }
  if (signal->observed & ZX_CHANNEL_READABLE) {
    zx_status_t r = conn->HandleRead();
    if (r != ZX_OK) {
      if (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 fxbug.dev/33897.
        __UNUSED auto r = conn.release();
        return;
      }
      LOGD(FATAL, *dev, "Failed to handle RPC for device %p: %s", dev.get(),
           zx_status_get_string(r));
    }
    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 (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;
    }

    // This is expected in test environments where driver_manager has terminated.
    // TODO(fxbug.dev/52627): Support graceful termination.
    LOGD(WARNING, *dev, "driver_manager disconnected from device %p", dev.get());
    exit(1);
  }
  LOGD(WARNING, *dev, "Unexpected signal state %#08x for device %p", signal->observed, dev.get());
  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 = std::size(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;
  }

  auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
  uint64_t ordinal = hdr->ordinal;
  if (ordinal == fuchsia_io_DirectoryOpenOrdinal) {
    VLOGD(1, *dev(), "Opening device %p", dev().get());
    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();
}
