// 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 <inttypes.h>

#include <fs/tracked-remote-dir.h>
#include <fuchsia/fshost/c/fidl.h>
#include <lib/fidl-utils/bind.h>
#include <lib/memfs/cpp/vnode.h>

#include "vnode.h"

namespace devmgr {
namespace fshost {
namespace {

// A connection bespoke to the fshost Vnode, capable of serving fshost FIDL
// requests.
class Connection final : public fs::Connection {
public:
    Connection(fs::Vfs* vfs, fbl::RefPtr<fs::Vnode> vnode, zx::channel channel,
                     uint32_t flags);
private:
    static const fuchsia_fshost_Registry_ops* Ops() {
        using Binder = fidl::Binder<Connection>;
        static const fuchsia_fshost_Registry_ops kFshostOps = {
            .RegisterFilesystem = Binder::BindMember<&Connection::RegisterFilesystem>,
        };
        return &kFshostOps;
    }

    Vnode& GetVnode() const;
    zx_status_t RegisterFilesystem(zx_handle_t channel, fidl_txn_t* txn);

    zx_status_t HandleFsSpecificMessage(fidl_msg_t* msg, fidl_txn_t* txn) final;
};

} // namespace

Vnode::Vnode(async_dispatcher_t* dispatcher, fbl::RefPtr<fs::PseudoDir> filesystems)
    : filesystems_(std::move(filesystems)),
      filesystem_counter_(0),
      dispatcher_(dispatcher) {
}

zx_status_t Vnode::AddFilesystem(zx::channel directory) {
    char buf[32];
    snprintf(buf, sizeof(buf), "%" PRIu64 "", filesystem_counter_++);

    auto directory_vnode = fbl::AdoptRef<fs::TrackedRemoteDir>(
            new fs::TrackedRemoteDir(std::move(directory)));

    return directory_vnode->AddAsTrackedEntry(dispatcher_, filesystems_.get(), fbl::String(buf));
}

zx_status_t Vnode::ValidateFlags(uint32_t flags) {
    if (flags & ZX_FS_FLAG_DIRECTORY) {
        return ZX_ERR_NOT_DIR;
    }
    return ZX_OK;
}

zx_status_t Vnode::Getattr(vnattr_t* attr) {
    memset(attr, 0, sizeof(vnattr_t));
    attr->mode = V_TYPE_FILE;
    attr->nlink = 1;
    return ZX_OK;
}

zx_status_t Vnode::Serve(fs::Vfs* vfs, zx::channel channel, uint32_t flags) {
    return vfs->ServeConnection(std::make_unique<Connection>(
        vfs, fbl::WrapRefPtr(this), std::move(channel), flags));
}

zx_status_t Vnode::GetNodeInfo(uint32_t flags, fuchsia_io_NodeInfo* info) {
    info->tag = fuchsia_io_NodeInfoTag_service;
    return ZX_OK;
}

Connection::Connection(fs::Vfs* vfs, fbl::RefPtr<fs::Vnode> vnode,
                       zx::channel channel, uint32_t flags)
    : fs::Connection(vfs, std::move(vnode), std::move(channel), flags) {}

Vnode& Connection::GetVnode() const {
    return reinterpret_cast<Vnode&>(fs::Connection::GetVnode());
}

zx_status_t Connection::RegisterFilesystem(zx_handle_t channel, fidl_txn_t* txn) {
    zx::channel public_export(channel);
    zx_status_t status = GetVnode().AddFilesystem(std::move(public_export));
    return fuchsia_fshost_RegistryRegisterFilesystem_reply(txn, status);
}

zx_status_t Connection::HandleFsSpecificMessage(fidl_msg_t* msg, fidl_txn_t* txn) {
    fidl_message_header_t* hdr = reinterpret_cast<fidl_message_header_t*>(msg->bytes);
    // Depending on the state of the migration, GenOrdinal and Ordinal may be the
    // same value.  See FIDL-524.
    uint32_t ordinal = hdr->ordinal;
    if (ordinal == fuchsia_fshost_RegistryRegisterFilesystemOrdinal ||
        ordinal == fuchsia_fshost_RegistryRegisterFilesystemGenOrdinal) {
        return fuchsia_fshost_Registry_dispatch(this, txn, msg, Ops());
    }
    zx_handle_close_many(msg->handles, msg->num_handles);
    return ZX_ERR_NOT_SUPPORTED;
}

} // namespace fshost
} // namespace devmgr
