// 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 "zircon_platform_connection.h"

#include "platform_connection.h"
#include "zircon_platform_event.h"
#include <fuchsia/gpu/magma/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/task.h>
#include <lib/async/time.h>
#include <lib/async/wait.h>
#include <lib/zx/channel.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

namespace magma {

template <typename T>
T* OpCast(uint8_t* bytes, uint32_t num_bytes, zx_handle_t* handles, uint32_t kNumHandles)
{
    if (num_bytes != sizeof(T))
        return DRETP(nullptr, "wrong number of bytes in message, expected %zu, got %u", sizeof(T),
                     num_bytes);
    if (kNumHandles != T::kNumHandles)
        return DRETP(nullptr, "wrong number of handles in message");
    return reinterpret_cast<T*>(bytes);
}

template <>
ExecuteImmediateCommandsOp* OpCast<ExecuteImmediateCommandsOp>(uint8_t* bytes, uint32_t num_bytes,
                                                               zx_handle_t* handles,
                                                               uint32_t kNumHandles)
{
    if (num_bytes < sizeof(ExecuteImmediateCommandsOp))
        return DRETP(nullptr, "too few bytes for executing immediate commands %u", num_bytes);

    auto execute_immediate_commands_op = reinterpret_cast<ExecuteImmediateCommandsOp*>(bytes);
    uint32_t expected_size =
        ExecuteImmediateCommandsOp::size(execute_immediate_commands_op->semaphore_count,
                                         execute_immediate_commands_op->commands_size);
    if (num_bytes != expected_size)
        return DRETP(nullptr, "wrong number of bytes in message, expected %u, got %u",
                     expected_size, num_bytes);
    if (kNumHandles != ExecuteImmediateCommandsOp::kNumHandles)
        return DRETP(nullptr, "wrong number of handles in message");
    return reinterpret_cast<ExecuteImmediateCommandsOp*>(bytes);
}

class ZirconPlatformConnection : public PlatformConnection, public fuchsia::gpu::magma::Primary {
public:
    struct AsyncWait : public async_wait {
        AsyncWait(ZirconPlatformConnection* connection, zx_handle_t object, zx_signals_t trigger)
        {
            this->state = ASYNC_STATE_INIT;
            this->handler = AsyncWaitHandlerStatic;
            this->object = object;
            this->trigger = trigger;
            this->connection = connection;
        }
        ZirconPlatformConnection* connection;
    };

    struct AsyncTask : public async_task {
        AsyncTask(ZirconPlatformConnection* connection, msd_notification_t* notification)
        {
            this->state = ASYNC_STATE_INIT;
            this->handler = AsyncTaskHandlerStatic;
            this->deadline = async_now(connection->async_loop()->dispatcher());
            this->connection = connection;
            // Copy the notification struct
            this->notification = *notification;
        }

        ZirconPlatformConnection* connection;
        msd_notification_t notification;
    };

    ZirconPlatformConnection(std::unique_ptr<Delegate> delegate, zx::channel server_endpoint,
                             zx::channel client_endpoint, zx::channel server_notification_endpoint,
                             zx::channel client_notification_endpoint,
                             std::shared_ptr<magma::PlatformEvent> shutdown_event)
        : magma::PlatformConnection(shutdown_event), delegate_(std::move(delegate)),
#if !MAGMA_FIDL
          server_endpoint_(std::move(server_endpoint)),
#endif
          client_endpoint_(std::move(client_endpoint)),
          server_notification_endpoint_(std::move(server_notification_endpoint)),
          client_notification_endpoint_(std::move(client_notification_endpoint)),
          async_loop_(&kAsyncLoopConfigNoAttachToThread),
#if !MAGMA_FIDL
          async_wait_channel_(this, server_endpoint_.get(),
                              ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED),
#endif
          async_wait_shutdown_(
              this, static_cast<magma::ZirconPlatformEvent*>(shutdown_event.get())->zx_handle(),
              ZX_EVENT_SIGNALED)
#if MAGMA_FIDL
          ,
          binding_(this, std::move(server_endpoint), async_loop_.dispatcher())
#endif
    {
#if MAGMA_FIDL
        binding_.set_error_handler([this](zx_status_t status) { async_loop()->Quit(); });
#endif
        delegate_->SetNotificationCallback(NotificationCallbackStatic, this);
    }

    ~ZirconPlatformConnection() { delegate_->SetNotificationCallback(nullptr, 0); }

    bool HandleRequest() override
    {
        zx_status_t status = async_loop_.Run(zx::time::infinite(), true /* once */);
        if (status != ZX_OK)
            return false;
        return true;
    }

#if !MAGMA_FIDL
    bool BeginChannelWait()
    {
        zx_status_t status = async_begin_wait(async_loop()->dispatcher(), &async_wait_channel_);
        if (status != ZX_OK)
            return DRETF(false, "Couldn't begin wait on channel: %s", zx_status_get_string(status));
        return true;
    }
#endif

    bool BeginShutdownWait()
    {
        zx_status_t status = async_begin_wait(async_loop()->dispatcher(), &async_wait_shutdown_);
        if (status != ZX_OK)
            return DRETF(false, "Couldn't begin wait on shutdown: %s",
                         zx_status_get_string(status));
        return true;
    }

#if !MAGMA_FIDL
    bool ReadChannel()
    {
        constexpr uint32_t kNumBytes = fuchsia::gpu::magma::kReceiveBufferSize;
        constexpr uint32_t kNumHandles = 1;

        uint32_t actual_bytes;
        uint32_t actual_handles;

        uint8_t bytes[kNumBytes];
        zx_handle_t handles[kNumHandles];

        zx_status_t status = server_endpoint_.read(0, bytes, kNumBytes, &actual_bytes, handles,
                                                   kNumHandles, &actual_handles);
        if (status != ZX_OK)
            return DRETF(false, "failed to read from channel");

        if (actual_bytes < sizeof(OpCode))
            return DRETF(false, "malformed message");

        OpCode* opcode = reinterpret_cast<OpCode*>(bytes);
        bool success = false;
        switch (*opcode) {
            case OpCode::ImportBuffer:
                success = ImportBuffer(
                    OpCast<ImportBufferOp>(bytes, actual_bytes, handles, actual_handles), handles);
                break;
            case OpCode::ReleaseBuffer:
                success = ReleaseBuffer(
                    OpCast<ReleaseBufferOp>(bytes, actual_bytes, handles, actual_handles));
                break;
            case OpCode::ImportObject:
                success = ImportObject(
                    OpCast<ImportObjectOp>(bytes, actual_bytes, handles, actual_handles), handles);
                break;
            case OpCode::ReleaseObject:
                success = ReleaseObject(
                    OpCast<ReleaseObjectOp>(bytes, actual_bytes, handles, actual_handles));
                break;
            case OpCode::CreateContext:
                success = CreateContext(
                    OpCast<CreateContextOp>(bytes, actual_bytes, handles, actual_handles));
                break;
            case OpCode::DestroyContext:
                success = DestroyContext(
                    OpCast<DestroyContextOp>(bytes, actual_bytes, handles, actual_handles));
                break;
            case OpCode::ExecuteCommandBuffer:
                success = ExecuteCommandBuffer(
                    OpCast<ExecuteCommandBufferOp>(bytes, actual_bytes, handles, actual_handles),
                    handles);
                break;
            case OpCode::ExecuteImmediateCommands:
                success = ExecuteImmediateCommands(OpCast<ExecuteImmediateCommandsOp>(
                    bytes, actual_bytes, handles, actual_handles));
                break;
            case OpCode::GetError:
                success =
                    GetError(OpCast<GetErrorOp>(bytes, actual_bytes, handles, actual_handles));
                break;
            case OpCode::MapBufferGpu:
                success = MapBufferGpu(
                    OpCast<MapBufferGpuOp>(bytes, actual_bytes, handles, actual_handles));
                break;
            case OpCode::UnmapBufferGpu:
                success = UnmapBufferGpu(
                    OpCast<UnmapBufferGpuOp>(bytes, actual_bytes, handles, actual_handles));
                break;
            case OpCode::CommitBuffer:
                success = CommitBuffer(
                    OpCast<CommitBufferOp>(bytes, actual_bytes, handles, actual_handles));
                break;
        }

        if (!success)
            return DRETF(false, "failed to interpret message");

        if (error_)
            return DRETF(false, "PlatformConnection encountered fatal error");

        return true;
    }
#endif

    uint32_t GetClientEndpoint() override
    {
        DASSERT(client_endpoint_);
        return client_endpoint_.release();
    }

    uint32_t GetClientNotificationEndpoint() override
    {
        DASSERT(client_notification_endpoint_);
        return client_notification_endpoint_.release();
    }

    async::Loop* async_loop() { return &async_loop_; }

private:
    static void AsyncWaitHandlerStatic(async_dispatcher_t* dispatcher, async_wait_t* async_wait,
                                       zx_status_t status, const zx_packet_signal_t* signal)
    {
        auto wait = static_cast<AsyncWait*>(async_wait);
        wait->connection->AsyncWaitHandler(dispatcher, wait, status, signal);
    }

    void AsyncWaitHandler(async_dispatcher_t* dispatcher, AsyncWait* wait, zx_status_t status,
                          const zx_packet_signal_t* signal)
    {
        if (status != ZX_OK)
            return;

        bool quit = false;
        if (wait == &async_wait_shutdown_) {
            DASSERT(signal->observed == ZX_EVENT_SIGNALED);
            quit = true;
            DLOG("got shutdown event");
        }
#if !MAGMA_FIDL
        else if (wait == &async_wait_channel_ && signal->observed & ZX_CHANNEL_PEER_CLOSED) {
            quit = true;
        } else if (wait == &async_wait_channel_ && signal->observed & ZX_CHANNEL_READABLE) {
            if (!ReadChannel() || !BeginChannelWait()) {
                quit = true;
            }
        }
#endif
        else {
            DASSERT(false);
        }

        if (quit) {
            async_loop()->Quit();
        }
    }

    // Could occur on an arbitrary thread (see |msd_connection_set_notification_callback|).
    // MSD must ensure we aren't in the process of destroying our connection.
    static void NotificationCallbackStatic(void* token, msd_notification_t* notification)
    {
        auto connection = static_cast<ZirconPlatformConnection*>(token);
        zx_status_t status = async_post_task(connection->async_loop()->dispatcher(),
                                             new AsyncTask(connection, notification));
        if (status != ZX_OK)
            DLOG("async_post_task failed, status %s", zx_status_get_string(status));
    }

    static void AsyncTaskHandlerStatic(async_dispatcher_t* dispatcher, async_task_t* async_task,
                                       zx_status_t status)
    {
        auto task = static_cast<AsyncTask*>(async_task);
        task->connection->AsyncTaskHandler(dispatcher, task, status);
        delete task;
    }

    bool AsyncTaskHandler(async_dispatcher_t* dispatcher, AsyncTask* task, zx_status_t status)
    {
        switch (static_cast<MSD_CONNECTION_NOTIFICATION_TYPE>(task->notification.type)) {
            case MSD_CONNECTION_NOTIFICATION_CHANNEL_SEND: {
                zx_status_t status = zx_channel_write(
                    server_notification_endpoint_.get(), 0, task->notification.u.channel_send.data,
                    task->notification.u.channel_send.size, nullptr, 0);
                if (status != ZX_OK)
                    return DRETF(false, "Failed writing to channel: %s", zx_status_get_string(status));
                return true;
            }
            case MSD_CONNECTION_NOTIFICATION_CONTEXT_KILLED:
                // Kill the connection.
                ShutdownEvent()->Signal();
                return true;
        }
        return DRETF(false, "Unhandled notification type: %d", task->notification.type);
    }

    bool ImportBuffer(ImportBufferOp* op, zx_handle_t* handle)
    {
        DLOG("ZirconPlatformConnection: ImportBuffer");
        if (!op)
            return DRETF(false, "malformed message");
        uint64_t buffer_id;
        if (!delegate_->ImportBuffer(*handle, &buffer_id))
            SetError(MAGMA_STATUS_INVALID_ARGS);
        return true;
    }

    void ImportBufferFIDL(zx::vmo vmo) override
    {
        DLOG("ZirconPlatformConnection - ImportBufferFIDL");
        uint64_t buffer_id;
        if (!delegate_->ImportBuffer(vmo.release(), &buffer_id)) {
            SetError(MAGMA_STATUS_INVALID_ARGS);
        }
    }

    bool ReleaseBuffer(ReleaseBufferOp* op)
    {
        DLOG("ZirconPlatformConnection: ReleaseBuffer");
        if (!op)
            return DRETF(false, "malformed message");
        if (!delegate_->ReleaseBuffer(op->buffer_id))
            SetError(MAGMA_STATUS_INVALID_ARGS);
        return true;
    }

    void ReleaseBufferFIDL(uint64_t buffer_id) override
    {
        DLOG("ZirconPlatformConnection: ReleaseBufferFIDL");
        if (!delegate_->ReleaseBuffer(buffer_id))
            SetError(MAGMA_STATUS_INVALID_ARGS);
    }

    bool ImportObject(ImportObjectOp* op, zx_handle_t* handle)
    {
        DLOG("ZirconPlatformConnection: ImportObject");
        if (!op)
            return DRETF(false, "malformed message");
        if (!delegate_->ImportObject(*handle, static_cast<PlatformObject::Type>(op->object_type)))
            SetError(MAGMA_STATUS_INVALID_ARGS);
        return true;
    }

    void ImportObjectFIDL(zx::handle handle, uint32_t object_type) override
    {
        DLOG("ZirconPlatformConnection: ImportObjectFIDL");
        if (!delegate_->ImportObject(handle.release(),
                                     static_cast<PlatformObject::Type>(object_type)))
            SetError(MAGMA_STATUS_INVALID_ARGS);
    }

    bool ReleaseObject(ReleaseObjectOp* op)
    {
        DLOG("ZirconPlatformConnection: ReleaseObject");
        if (!op)
            return DRETF(false, "malformed message");
        if (!delegate_->ReleaseObject(op->object_id,
                                      static_cast<PlatformObject::Type>(op->object_type)))
            SetError(MAGMA_STATUS_INVALID_ARGS);
        return true;
    }

    void ReleaseObjectFIDL(uint64_t object_id, uint32_t object_type) override
    {
        DLOG("ZirconPlatformConnection: ReleaseObjectFIDL");
        if (!delegate_->ReleaseObject(object_id, static_cast<PlatformObject::Type>(object_type)))
            SetError(MAGMA_STATUS_INVALID_ARGS);
    }

    bool CreateContext(CreateContextOp* op)
    {
        DLOG("ZirconPlatformConnection: CreateContext");
        if (!op)
            return DRETF(false, "malformed message");
        if (!delegate_->CreateContext(op->context_id))
            SetError(MAGMA_STATUS_INTERNAL_ERROR);
        return true;
    }

    void CreateContextFIDL(uint32_t context_id) override
    {
        DLOG("ZirconPlatformConnection: CreateContextFIDL");
        if (!delegate_->CreateContext(context_id))
            SetError(MAGMA_STATUS_INTERNAL_ERROR);
    }

    bool DestroyContext(DestroyContextOp* op)
    {
        DLOG("ZirconPlatformConnection: DestroyContext");
        if (!op)
            return DRETF(false, "malformed message");
        if (!delegate_->DestroyContext(op->context_id))
            SetError(MAGMA_STATUS_INTERNAL_ERROR);
        return true;
    }

    void DestroyContextFIDL(uint32_t context_id) override
    {
        DLOG("ZirconPlatformConnection: DestroyContextFIDL");
        if (!delegate_->DestroyContext(context_id))
            SetError(MAGMA_STATUS_INTERNAL_ERROR);
    }

    bool ExecuteCommandBuffer(ExecuteCommandBufferOp* op, zx_handle_t* handle)
    {
        DLOG("ZirconPlatformConnection: ExecuteCommandBuffer");
        if (!op)
            return DRETF(false, "malformed message");
        magma::Status status = delegate_->ExecuteCommandBuffer(*handle, op->context_id);
        if (status.get() == MAGMA_STATUS_CONTEXT_KILLED)
            ShutdownEvent()->Signal();
        if (!status)
            SetError(MAGMA_STATUS_INTERNAL_ERROR);
        return true;
    }

    void ExecuteCommandBufferFIDL(zx::handle command_buffer, uint32_t context_id) override
    {
        DLOG("ZirconPlatformConnection: ExecuteCommandBufferFIDL");
        magma::Status status =
            delegate_->ExecuteCommandBuffer(command_buffer.release(), context_id);
        if (status.get() == MAGMA_STATUS_CONTEXT_KILLED)
            ShutdownEvent()->Signal();
        if (!status)
            SetError(MAGMA_STATUS_INTERNAL_ERROR);
    }

    bool ExecuteImmediateCommands(ExecuteImmediateCommandsOp* op)
    {
        DLOG("ZirconPlatformConnection: ExecuteImmediateCommands");
        if (!op)
            return DRETF(false, "malformed message");

        magma::Status status = delegate_->ExecuteImmediateCommands(
            op->context_id, op->commands_size, op->command_data(), op->semaphore_count,
            op->semaphores);
        if (!status)
            SetError(status.get());
        return true;
    }

    void ExecuteImmediateCommandsFIDL(uint32_t context_id, ::std::vector<uint8_t> command_data_vec,
                                      ::std::vector<uint64_t> semaphore_vec) override
    {
        DLOG("ZirconPlatformConnection: ExecuteImmediateCommandsFIDL");
        magma::Status status = delegate_->ExecuteImmediateCommands(
            context_id, command_data_vec.size(), command_data_vec.data(), semaphore_vec.size(),
            semaphore_vec.data());
        if (!status)
            SetError(status.get());
    }

    bool GetError(GetErrorOp* op)
    {
        DLOG("ZirconPlatformConnection: GetError");
        if (!op)
            return DRETF(false, "malformed message");
        magma_status_t result = error_;
        error_ = 0;
        if (!WriteError(result))
            return false;
        return true;
    }

    void GetErrorFIDL(fuchsia::gpu::magma::Primary::GetErrorFIDLCallback error_callback) override
    {
        magma_status_t result = error_;
        error_ = 0;
        error_callback(result);
    }

    bool MapBufferGpu(MapBufferGpuOp* op)
    {
        DLOG("ZirconPlatformConnection: MapBufferGpu");
        if (!op)
            return DRETF(false, "malformed message");
        if (!delegate_->MapBufferGpu(op->buffer_id, op->gpu_va, op->page_offset, op->page_count,
                                     op->flags))
            SetError(MAGMA_STATUS_INVALID_ARGS);
        return true;
    }

    void MapBufferGpuFIDL(uint64_t buffer_id, uint64_t gpu_va, uint64_t page_offset,
                          uint64_t page_count, uint64_t flags) override
    {
        DLOG("ZirconPlatformConnection: MapBufferGpuFIDL");
        if (!delegate_->MapBufferGpu(buffer_id, gpu_va, page_offset, page_count, flags))
            SetError(MAGMA_STATUS_INVALID_ARGS);
    }

    bool UnmapBufferGpu(UnmapBufferGpuOp* op)
    {
        DLOG("ZirconPlatformConnection: UnmapBufferGpu");
        if (!op)
            return DRETF(false, "malformed message");
        if (!delegate_->UnmapBufferGpu(op->buffer_id, op->gpu_va))
            SetError(MAGMA_STATUS_INVALID_ARGS);
        return true;
    }

    void UnmapBufferGpuFIDL(uint64_t buffer_id, uint64_t gpu_va) override
    {
        DLOG("ZirconPlatformConnection: UnmapBufferGpuFIDL");
        if (!delegate_->UnmapBufferGpu(buffer_id, gpu_va))
            SetError(MAGMA_STATUS_INVALID_ARGS);
    }

    bool CommitBuffer(CommitBufferOp* op)
    {
        DLOG("ZirconPlatformConnection: CommitBuffer");
        if (!op)
            return DRETF(false, "malformed message");
        if (!delegate_->CommitBuffer(op->buffer_id, op->page_offset, op->page_count))
            SetError(MAGMA_STATUS_INVALID_ARGS);
        return true;
    }

    void CommitBufferFIDL(uint64_t buffer_id, uint64_t page_offset, uint64_t page_count) override
    {
        DLOG("ZirconPlatformConnection: CommitBufferFIDL");
        if (!delegate_->CommitBuffer(buffer_id, page_offset, page_count))
            SetError(MAGMA_STATUS_INVALID_ARGS);
    }

    void SetError(magma_status_t error)
    {
        if (!error_)
            error_ = DRET_MSG(error, "ZirconPlatformConnection encountered dispatcher error");
    }

    bool WriteError(magma_status_t error)
    {
        DLOG("Writing error %d to channel", error);
        zx_status_t status = server_endpoint_.write(0, &error, sizeof(error), nullptr, 0);
        return DRETF(status == ZX_OK, "failed to write to channel");
    }

    std::unique_ptr<Delegate> delegate_;
    zx::channel server_endpoint_;
    zx::channel client_endpoint_;
    magma_status_t error_{};
    zx::channel server_notification_endpoint_;
    zx::channel client_notification_endpoint_;
    async::Loop async_loop_;
#if !MAGMA_FIDL
    AsyncWait async_wait_channel_;
#endif
    AsyncWait async_wait_shutdown_;

#if MAGMA_FIDL
    fidl::Binding<fuchsia::gpu::magma::Primary> binding_;
#endif
};

std::shared_ptr<PlatformConnection>
PlatformConnection::Create(std::unique_ptr<PlatformConnection::Delegate> delegate)
{
    if (!delegate)
        return DRETP(nullptr, "attempting to create PlatformConnection with null delegate");

    zx::channel server_endpoint;
    zx::channel client_endpoint;
    zx_status_t status = zx::channel::create(0, &server_endpoint, &client_endpoint);
    if (status != ZX_OK)
        return DRETP(nullptr, "zx::channel::create failed");

    zx::channel server_notification_endpoint;
    zx::channel client_notification_endpoint;
    status = zx::channel::create(0, &server_notification_endpoint, &client_notification_endpoint);
    if (status != ZX_OK)
        return DRETP(nullptr, "zx::channel::create failed");

    auto shutdown_event = magma::PlatformEvent::Create();
    if (!shutdown_event)
        return DRETP(nullptr, "Failed to create shutdown event");

    auto connection = std::make_shared<ZirconPlatformConnection>(
        std::move(delegate), std::move(server_endpoint), std::move(client_endpoint),
        std::move(server_notification_endpoint), std::move(client_notification_endpoint),
        std::shared_ptr<magma::PlatformEvent>(std::move(shutdown_event)));

#if !MAGMA_FIDL
    if (!connection->BeginChannelWait())
        return DRETP(nullptr, "Failed to begin channel wait");
#endif

    if (!connection->BeginShutdownWait())
        return DRETP(nullptr, "Failed to begin shutdown wait");

    return connection;
}

} // namespace magma
