/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <lk/list.h>
#include <stdlib.h>
#include <trusty_ipc.h>
#include <trusty_log.h>
#include <uapi/err.h>

#include "ipc.h"

#define MSG_BUF_MAX_SIZE 4096

#define TLOG_TAG "ss-ipc"

/* Start logging response waits after this many milliseconds. */
#define RESPONSE_TIMEOUT 1000

/*
 * Don't wait more than this many ms between logging statements (currently
 * 1000s)
 */
#define RESPONSE_TIMEOUT_MAX (RESPONSE_TIMEOUT * 1000 * 1000)

static void* msg_buf;
static size_t msg_buf_size;

static void handle_channel(struct ipc_context* ctx, const struct uevent* ev);
static void handle_port(struct ipc_context* ctx, const struct uevent* ev);

static int maybe_grow_msg_buf(size_t new_max_size) {
    if (new_max_size > msg_buf_size) {
        uint8_t* tmp = realloc(msg_buf, new_max_size);
        if (tmp == NULL) {
            return ERR_NO_MEMORY;
        }
        msg_buf = tmp;
        msg_buf_size = new_max_size;
    }
    return NO_ERROR;
}

static inline void handle_port_errors(const uevent_t* ev) {
    if ((ev->event & IPC_HANDLE_POLL_ERROR) ||
        (ev->event & IPC_HANDLE_POLL_HUP) ||
        (ev->event & IPC_HANDLE_POLL_MSG) ||
        (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) {
        /* should never happen with port handles */
        TLOGE("error event (0x%x) for port (%d)\n", ev->event, ev->handle);
        abort();
    }
}

static inline void handle_chan_errors(const uevent_t* ev) {
    if ((ev->event & IPC_HANDLE_POLL_ERROR) ||
        (ev->event & IPC_HANDLE_POLL_READY)) {
        TLOGE("error event (0x%x) for chan (%d)\n", ev->event, ev->handle);
        abort();
    }
}

static int is_valid_port_ops(struct ipc_port_ops* ops) {
    return (ops->on_connect != NULL);
}

static bool is_valid_chan_ops(struct ipc_channel_ops* ops) {
    return (ops->on_disconnect != NULL);
}

static struct ipc_port_context* to_port_context(struct ipc_context* context) {
    assert(context);
    return containerof(context, struct ipc_port_context, common);
}

static struct ipc_channel_context* to_channel_context(
        struct ipc_context* context) {
    assert(context);
    return containerof(context, struct ipc_channel_context, common);
}

static int do_connect(struct ipc_port_context* ctx, const uevent_t* ev) {
    int rc;
    handle_t chan_handle;
    struct ipc_channel_context* chan_ctx;

    if (ev->event & IPC_HANDLE_POLL_READY) {
        /* incoming connection: accept it */
        uuid_t peer_uuid;
        rc = accept(ev->handle, &peer_uuid);
        if (rc < 0) {
            TLOGE("failed (%d) to accept on port %d\n", rc, ev->handle);
            return rc;
        }

        chan_handle = (handle_t)rc;

        chan_ctx = ctx->ops.on_connect(ctx, &peer_uuid, chan_handle);
        if (chan_ctx == NULL) {
            TLOGE("%s: failure initializing channel state (%d)\n", __func__,
                  rc);
            rc = ERR_GENERIC;
            goto err_on_connect;
        }

        assert(is_valid_chan_ops(&chan_ctx->ops));

        chan_ctx->common.evt_handler = handle_channel;
        chan_ctx->common.handle = chan_handle;

        rc = set_cookie(chan_handle, chan_ctx);
        if (rc < 0) {
            TLOGE("failed (%d) to set_cookie on chan %d\n", rc, chan_handle);
            goto err_set_cookie;
        }
        list_add_tail(&ctx->channels, &chan_ctx->node);
    }

    return NO_ERROR;

err_set_cookie:
    chan_ctx->ops.on_disconnect(chan_ctx);
err_on_connect:
    close(chan_handle);
    return rc;
}

static int do_handle_msg(struct ipc_channel_context* ctx, const uevent_t* ev) {
    handle_t chan = ev->handle;

    /* get message info */
    ipc_msg_info_t msg_inf;
    int rc = get_msg(chan, &msg_inf);
    if (rc == ERR_NO_MSG)
        return NO_ERROR; /* no new messages */

    if (rc != NO_ERROR) {
        TLOGE("failed (%d) to get_msg for chan (%d), closing connection\n", rc,
              chan);
        return rc;
    }

    if (msg_inf.len > MSG_BUF_MAX_SIZE) {
        TLOGE("%s: message too large %zu\n", __func__, msg_inf.len);
        put_msg(chan, msg_inf.id);
        return ERR_NOT_ENOUGH_BUFFER;
    }

    /* read msg content */
    struct iovec iov = {
            .iov_base = msg_buf,
            .iov_len = msg_inf.len,
    };
    ipc_msg_t msg = {
            .iov = &iov,
            .num_iov = 1,
    };

    rc = read_msg(chan, msg_inf.id, 0, &msg);
    put_msg(chan, msg_inf.id);
    if (rc < 0) {
        TLOGE("failed to read msg (%d, %d)\n", rc, chan);
        return rc;
    }

    if (((size_t)rc) < msg_inf.len) {
        TLOGE("invalid message of size (%d, %d)\n", rc, chan);
        return ERR_NOT_VALID;
    }

    rc = ctx->ops.on_handle_msg(ctx, msg_buf, msg_inf.len);

err_handle_msg:
err_read_msg:
    return rc;
}

static void do_disconnect(struct ipc_channel_context* context,
                          const uevent_t* ev) {
    list_delete(&context->node);
    context->ops.on_disconnect(context);
    close(ev->handle);
}

static void handle_port(struct ipc_context* ctx, const struct uevent* ev) {
    struct ipc_port_context* port_ctx = to_port_context(ctx);
    assert(is_valid_port_ops(&port_ctx->ops));

    handle_port_errors(ev);

    do_connect(port_ctx, ev);
}

static void handle_channel(struct ipc_context* ctx, const struct uevent* ev) {
    struct ipc_channel_context* channel_ctx = to_channel_context(ctx);
    assert(is_valid_chan_ops(&channel_ctx->ops));

    handle_chan_errors(ev);

    if (ev->event & IPC_HANDLE_POLL_MSG) {
        if (channel_ctx->ops.on_handle_msg != NULL) {
            int rc = do_handle_msg(channel_ctx, ev);
            if (rc < 0) {
                TLOGE("error (%d) in channel, disconnecting "
                      "peer\n",
                      rc);
                do_disconnect(channel_ctx, ev);
                return;
            }
        } else {
            TLOGE("error: unexpected message in channel (%d). closing...\n",
                  ev->handle);
            do_disconnect(channel_ctx, ev);
            return;
        }
    }

    if (ev->event & IPC_HANDLE_POLL_HUP) {
        do_disconnect(channel_ctx, ev);
    }
}

static int read_response(handle_t session,
                         uint32_t msg_id,
                         struct iovec* iovecs,
                         size_t iovec_count) {
    struct ipc_msg rx_msg = {
            .iov = iovecs,
            .num_iov = iovec_count,
    };

    long rc = read_msg(session, msg_id, 0, &rx_msg);
    put_msg(session, msg_id);
    if (rc < 0) {
        TLOGE("%s: failed to read msg (%ld)\n", __func__, rc);
        return rc;
    }

    size_t read_size = (size_t)rc;
    return read_size;
}

static int await_response(handle_t session, struct ipc_msg_info* inf) {
    uevent_t uevt;
    unsigned long wait_timeout = RESPONSE_TIMEOUT;
    long rc;
    while (true) {
        rc = wait(session, &uevt, wait_timeout);
        if (rc != ERR_TIMED_OUT) {
            break;
        }
        TLOGE("%s: storage response wait timed out after %ldx ms\n", __func__,
              wait_timeout);
        wait_timeout *= 2;
        if (wait_timeout > RESPONSE_TIMEOUT_MAX) {
            wait_timeout = RESPONSE_TIMEOUT_MAX;
        }
    }
    if (rc != NO_ERROR) {
        TLOGE("%s: error while waiting for response (%ld)\n", __func__, rc);
        return rc;
    }

    rc = get_msg(session, inf);
    if (rc != NO_ERROR) {
        TLOGE("%s: failed to get_msg (%ld)\n", __func__, rc);
    }

    return rc;
}

static int wait_to_send(handle_t session, struct ipc_msg* msg) {
    int rc;
    struct uevent ev = UEVENT_INITIAL_VALUE(ev);

    rc = wait(session, &ev, INFINITE_TIME);
    if (rc < 0) {
        TLOGE("failed to wait for outgoing queue to free up\n");
        return rc;
    }

    if (ev.event & IPC_HANDLE_POLL_SEND_UNBLOCKED) {
        return send_msg(session, msg);
    }

    if (ev.event & IPC_HANDLE_POLL_MSG) {
        return ERR_BUSY;
    }

    if (ev.event & IPC_HANDLE_POLL_HUP) {
        return ERR_CHANNEL_CLOSED;
    }

    return rc;
}

int sync_ipc_send_msg(handle_t session,
                      struct iovec* tx_iovecs,
                      unsigned int tx_iovec_count,
                      struct iovec* rx_iovecs,
                      unsigned int rx_iovec_count) {
    struct ipc_msg tx_msg = {
            .iov = tx_iovecs,
            .num_iov = tx_iovec_count,
    };

    long rc = send_msg(session, &tx_msg);
    if (rc == ERR_NOT_ENOUGH_BUFFER) {
        rc = wait_to_send(session, &tx_msg);
    }

    if (rc < 0) {
        TLOGE("%s: failed (%ld) to send_msg\n", __func__, rc);
        return rc;
    }

    if (rx_iovecs == NULL || rx_iovec_count == 0) {
        assert(rx_iovec_count == 0);
        assert(rx_iovecs == NULL);
        return NO_ERROR;
    }

    struct ipc_msg_info inf;
    rc = await_response(session, &inf);
    if (rc < 0) {
        TLOGE("%s: failed (%ld) to await response\n", __func__, rc);
        return rc;
    }

    size_t min_len = rx_iovecs[0].iov_len;
    if (inf.len < min_len) {
        TLOGE("%s: invalid response length (%zu)\n", __func__, inf.len);
        put_msg(session, inf.id);
        return ERR_NOT_VALID;
    }

    /* calculate total message size */
    size_t resp_size = 0;
    for (size_t i = 0; i < rx_iovec_count; ++i) {
        resp_size += rx_iovecs[i].iov_len;
    }

    if (resp_size < inf.len) {
        TLOGE("%s: response buffer too short (%zu < %zu) \n", __func__,
              resp_size, inf.len);
        put_msg(session, inf.id);
        return ERR_BAD_LEN;
    }

    rc = read_response(session, inf.id, rx_iovecs, rx_iovec_count);
    put_msg(session, inf.id);
    if (rc < 0) {
        TLOGE("%s: response has error (%ld)\n", __func__, rc);
        return rc;
    }

    size_t read_len = (size_t)rc;
    if (read_len != inf.len) {
        // data read in does not match message length
        TLOGE("%s: invalid response length (%zu)\n", __func__, read_len);
        return ERR_IO;
    }

    return read_len;
}

static void dispatch_event(const uevent_t* ev) {
    assert(ev);

    if (ev->event == IPC_HANDLE_POLL_NONE) {
        return;
    }

    struct ipc_context* context = ev->cookie;
    assert(context);
    assert(context->evt_handler);
    assert(context->handle == ev->handle);

    context->evt_handler(context, ev);
}

int ipc_port_create(struct ipc_port_context* ctxp,
                    const char* port_name,
                    size_t queue_size,
                    size_t max_buffer_size,
                    uint32_t flags) {
    int rc;
    assert(ctxp);
    assert(is_valid_port_ops(&ctxp->ops));

    rc = port_create(port_name, queue_size, max_buffer_size, flags);

    if (rc < 0) {
        TLOGE("Failed to create port %s %d\n", port_name, rc);
        return rc;
    }

    handle_t port_handle = (handle_t)rc;
    rc = set_cookie(port_handle, ctxp);
    if (rc < 0) {
        TLOGE("Failed to set cookie on port %s (%d)\n", port_name, rc);
        goto err_set_cookie;
    }

    rc = maybe_grow_msg_buf(max_buffer_size);
    if (rc < 0) {
        TLOGE("Failed to create msg buffer of size %zu (%d)\n", max_buffer_size,
              rc);
        goto err_grow_msg;
    }

    ctxp->common.handle = port_handle;
    ctxp->common.evt_handler = handle_port;
    list_initialize(&ctxp->channels);
    return NO_ERROR;

err_set_cookie:
err_grow_msg:
    close(port_handle);
    return rc;
}

int ipc_port_destroy(struct ipc_port_context* ctx) {
    close(ctx->common.handle);
    while (!list_is_empty(&ctx->channels)) {
        struct ipc_channel_context* chan_ctx = list_remove_head_type(
                &ctx->channels, struct ipc_channel_context, node);
        assert(chan_ctx);
        handle_t chan_handle = chan_ctx->common.handle;
        TLOGE("client still connected, handle %d\n", chan_handle);
        chan_ctx->ops.on_disconnect(chan_ctx);
        close(chan_handle);
    }
    return NO_ERROR;
}

void ipc_loop(void) {
    int rc;
    uevent_t event;

    while (true) {
        event.handle = INVALID_IPC_HANDLE;
        event.event = 0;
        event.cookie = NULL;
        rc = wait_any(&event, INFINITE_TIME);
        if (rc < 0) {
            TLOGE("wait_any failed (%d)\n", rc);
            break;
        }

        if (rc == NO_ERROR) { /* got an event */
            dispatch_event(&event);
        }
    }
}
