// Copyright 2018 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 <lib/async/wait.h>
#include <lib/fidl-async/bind.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>

typedef struct fidl_binding {
    async_wait_t wait;
    fidl_dispatch_t* dispatch;
    async_dispatcher_t* dispatcher;
    void* ctx;
    const void* ops;
} fidl_binding_t;

typedef struct fidl_connection {
    fidl_txn_t txn;
    zx_handle_t channel;
    zx_txid_t txid;
    fidl_binding_t* binding;
} fidl_connection_t;

static zx_status_t fidl_reply(fidl_txn_t* txn, const fidl_msg_t* msg) {
    fidl_connection_t* conn = (fidl_connection_t*)txn;
    if (conn->txid == 0u)
        return ZX_ERR_BAD_STATE;
    if (msg->num_bytes < sizeof(fidl_message_header_t))
        return ZX_ERR_INVALID_ARGS;
    fidl_message_header_t* hdr = (fidl_message_header_t*)msg->bytes;
    hdr->txid = conn->txid;
    conn->txid = 0u;
    return zx_channel_write(conn->channel, 0, msg->bytes, msg->num_bytes,
                            msg->handles, msg->num_handles);
}

static void fidl_binding_destroy(fidl_binding_t* binding) {
    zx_handle_close(binding->wait.object);
    free(binding);
}

static void fidl_message_handler(async_dispatcher_t* dispatcher,
                                 async_wait_t* wait,
                                 zx_status_t status,
                                 const zx_packet_signal_t* signal) {
    fidl_binding_t* binding = (fidl_binding_t*)wait;
    if (status != ZX_OK) {
        goto shutdown;
    }

    if (signal->observed & ZX_CHANNEL_READABLE) {
        char bytes[ZX_CHANNEL_MAX_MSG_BYTES];
        zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES];
        for (uint64_t i = 0; i < signal->count; i++) {
            fidl_msg_t msg = {
                .bytes = bytes,
                .handles = handles,
                .num_bytes = 0u,
                .num_handles = 0u,
            };
            status = zx_channel_read(wait->object, 0, bytes, handles,
                                     ZX_CHANNEL_MAX_MSG_BYTES,
                                     ZX_CHANNEL_MAX_MSG_HANDLES,
                                     &msg.num_bytes, &msg.num_handles);
            if (status == ZX_ERR_SHOULD_WAIT) {
                // This occurs when someone else has read the message we were expecting.
                goto shutdown;
            }
            if (status != ZX_OK || msg.num_bytes < sizeof(fidl_message_header_t)) {
                goto shutdown;
            }
            fidl_message_header_t* hdr = (fidl_message_header_t*)msg.bytes;
            fidl_connection_t conn = {
                .txn.reply = fidl_reply,
                .channel = wait->object,
                .txid = hdr->txid,
                .binding = binding,
            };
            status = binding->dispatch(binding->ctx, &conn.txn, &msg, binding->ops);
            switch (status) {
            case ZX_OK:
                continue;
            case ZX_ERR_ASYNC:
                return;
            default:
                goto shutdown;
            }
        }

        // Only |status| == ZX_OK will lead here
        if (async_begin_wait(dispatcher, wait) == ZX_OK) {
            return;
        } else {
            goto shutdown;
        }
    } else {
        ZX_DEBUG_ASSERT(signal->observed & ZX_CHANNEL_PEER_CLOSED);
    }

shutdown:
    fidl_binding_destroy(binding);
}

zx_status_t fidl_bind(async_dispatcher_t* dispatcher, zx_handle_t channel,
                      fidl_dispatch_t* dispatch, void* ctx, const void* ops) {
    fidl_binding_t* binding = calloc(1, sizeof(fidl_binding_t));
    binding->wait.handler = fidl_message_handler;
    binding->wait.object = channel;
    binding->wait.trigger = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
    binding->dispatch = dispatch;
    binding->dispatcher = dispatcher;
    binding->ctx = ctx;
    binding->ops = ops;
    zx_status_t status = async_begin_wait(dispatcher, &binding->wait);
    if (status != ZX_OK) {
        fidl_binding_destroy(binding);
    }
    return status;
}

typedef struct fidl_async_txn {
    fidl_connection_t connection;
} fidl_async_txn_t;

fidl_async_txn_t* fidl_async_txn_create(fidl_txn_t* txn) {
    fidl_connection_t* connection = (fidl_connection_t*) txn;

    fidl_async_txn_t* async_txn = calloc(1, sizeof(fidl_async_txn_t));
    memcpy(&async_txn->connection, connection, sizeof(*connection));

    return async_txn;
}

fidl_txn_t* fidl_async_txn_borrow(fidl_async_txn_t* async_txn) {
    return &async_txn->connection.txn;
}

zx_status_t fidl_async_txn_complete(fidl_async_txn_t* async_txn, bool rebind) {
    zx_status_t status = ZX_OK;
    if (rebind) {
        status = async_begin_wait(async_txn->connection.binding->dispatcher,
                                  &async_txn->connection.binding->wait);
        if (status == ZX_OK) {
            return ZX_OK;
        }
    }

    fidl_binding_destroy(async_txn->connection.binding);
    free(async_txn);
    return status;
}
