// 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 <fidl/fuchsia.io/cpp/wire.h>
#include <lib/fdio/limits.h>
#include <lib/fdio/namespace.h>
#include <lib/zx/channel.h>
#include <lib/zxio/cpp/inception.h>
#include <poll.h>

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

#include "sdk/lib/fdio/internal.h"
#include "sdk/lib/fdio/socket.h"
#include "sdk/lib/fdio/zxio.h"

namespace fio = fuchsia_io;

static_assert(FDIO_CHUNK_SIZE >= PATH_MAX, "FDIO_CHUNK_SIZE must be large enough to contain paths");

static_assert(static_cast<uint32_t>(fio::wire::VmoFlags::kRead) == ZX_VM_PERM_READ,
              "Vmar / Vmo flags should be aligned");
static_assert(static_cast<uint32_t>(fio::wire::VmoFlags::kWrite) == ZX_VM_PERM_WRITE,
              "Vmar / Vmo flags should be aligned");
static_assert(static_cast<uint32_t>(fio::wire::VmoFlags::kExecute) == ZX_VM_PERM_EXECUTE,
              "Vmar / Vmo flags should be aligned");

zx_status_t fdio_validate_path(const char* path, size_t* out_length) {
  if (path == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }
  const size_t length = strnlen(path, PATH_MAX);
  if (length >= PATH_MAX) {
    return ZX_ERR_INVALID_ARGS;
  }
  if (out_length != nullptr) {
    *out_length = length;
  }
  return ZX_OK;
}

// Allocates an fdio_t instance containing storage for a zxio_t object.
zx_status_t fdio::zxio_allocator(zxio_object_type_t type, zxio_storage_t** out_storage,
                                 void** out_context) {
  fdio_ptr io;
  // The type of storage (fdio subclass) depends on the type of the object until
  // https://fxbug.dev/42119552 is resolved, so this has to switch on the type.
  switch (type) {
    case ZXIO_OBJECT_TYPE_DATAGRAM_SOCKET:
    case ZXIO_OBJECT_TYPE_PACKET_SOCKET:
    case ZXIO_OBJECT_TYPE_RAW_SOCKET:
    case ZXIO_OBJECT_TYPE_STREAM_SOCKET:
    case ZXIO_OBJECT_TYPE_SYNCHRONOUS_DATAGRAM_SOCKET:
      io = fdio_socket_allocate();
      break;
    case ZXIO_OBJECT_TYPE_DEBUGLOG:
      io = fbl::MakeRefCounted<fdio_internal::zxio>();
      break;
    case ZXIO_OBJECT_TYPE_DIR:
    case ZXIO_OBJECT_TYPE_FILE:
    case ZXIO_OBJECT_TYPE_SERVICE:
    case ZXIO_OBJECT_TYPE_TTY:
    case ZXIO_OBJECT_TYPE_VMO:
      io = fbl::MakeRefCounted<fdio_internal::remote>();
      break;
    case ZXIO_OBJECT_TYPE_PIPE:
      io = fbl::MakeRefCounted<fdio_internal::pipe>();
      break;
    default:
      // Unknown type - allocate a generic fdio object so that zxio_create can
      // initialize a zxio object holding the object for us.
      io = fbl::MakeRefCounted<fdio_internal::zxio>();
      break;
  }
  if (io == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }
  *out_storage = &io->zxio_storage();
  *out_context = fbl::ExportToRawPtr(&io);
  return ZX_OK;
}

zx::result<fdio_ptr> fdio::create(void*& context, zx_status_t status) {
  // If the status is ZX_ERR_NO_MEMORY, then zxio_create_with_allocator has not allocated
  // anything and we can return immediately with no cleanup.
  if (status == ZX_ERR_NO_MEMORY) {
    ZX_ASSERT(context == nullptr);
    return zx::error(status);
  }

  // Otherwise, fdio_zxio_allocator has allocated an fdio instance that we now own.
  fdio_ptr io = fbl::ImportFromRawPtr(static_cast<fdio*>(context));
  return zx::make_result(status, std::move(io));
}

zx::result<fdio_ptr> fdio::create(zx::handle handle) {
  return fdio::create([&](zxio_storage_alloc allocator, void** out_context) {
    return zxio_create_with_allocator(std::move(handle), allocator, out_context);
  });
}

zx::result<fdio_ptr> fdio::create(fidl::ClientEnd<fio::Node> node,
                                  fio::wire::NodeInfoDeprecated info) {
  return fdio::create([&](zxio_storage_alloc allocator, void** out_context) {
    return zxio_create_with_allocator(std::move(node), info, allocator, out_context);
  });
}

zx::result<fdio_ptr> fdio::create_with_on_open(fidl::ClientEnd<fio::Node> node) {
  class EventHandler : public fidl::WireSyncEventHandler<fio::Node> {
   public:
    explicit EventHandler(fidl::ClientEnd<fio::Node> client_end)
        : client_end_(std::move(client_end)) {}

    zx::result<fdio_ptr>& result() { return result_; }

    const fidl::ClientEnd<fio::Node>& client_end() const { return client_end_; }

    void OnOpen(fidl::WireEvent<fio::Node::OnOpen>* event) override {
      result_ = [&event = *event, this]() -> zx::result<fdio_ptr> {
        if (event.s != ZX_OK) {
          return zx::error(event.s);
        }
        if (!event.info.has_value()) {
          // Status was OK but the server did not give us an info union.
          return zx::error(ZX_ERR_INVALID_ARGS);
        }
        return fdio::create(std::move(client_end_), std::move(event.info.value()));
      }();
    }

    void OnRepresentation(fidl::WireEvent<fio::Node::OnRepresentation>* event) override {
      result_ = zx::error(ZX_ERR_NOT_SUPPORTED);
    }

   private:
    fidl::ClientEnd<fio::Node> client_end_;
    zx::result<fdio_ptr> result_ = zx::error(ZX_ERR_INTERNAL);
  };

  EventHandler event_handler(std::move(node));
  const fidl::Status status = event_handler.HandleOneEvent(event_handler.client_end());
  if (!status.ok()) {
    // TODO(https://fxbug.dev/42105838): This should probably be ZX_ERR_IO (EIO in
    // POSIX) or the transformation to errno should happen differently. This
    // behavior is kept to avoid breaking tests that check for EPIPE when
    // talking to a closed server endpoint.
    if (status.is_peer_closed()) {
      return zx::error(ZX_ERR_PEER_CLOSED);
    }
    return zx::error(ZX_ERR_IO);
  }
  return event_handler.result();
}
