// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <err.h>
#include <inttypes.h>
#include <trace.h>

#include <lib/ktrace.h>

#include <object/channel_dispatcher.h>
#include <object/handle_owner.h>
#include <object/handles.h>
#include <object/message_packet.h>
#include <object/process_dispatcher.h>
#include <zircon/syscalls/policy.h>
#include <zircon/types.h>

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

#include "syscalls_priv.h"

using fbl::AutoLock;

#define LOCAL_TRACE 0

zx_status_t sys_channel_create(
    uint32_t options, user_out_ptr<zx_handle_t> out0, user_out_ptr<zx_handle_t> out1) {
    LTRACEF("out_handles %p,%p\n", out0.get(), out1.get());

    if (options != 0u)
        return ZX_ERR_INVALID_ARGS;

    auto up = ProcessDispatcher::GetCurrent();
    zx_status_t res = up->QueryPolicy(ZX_POL_NEW_CHANNEL);
    if (res != ZX_OK)
        return res;

    fbl::RefPtr<Dispatcher> mpd0, mpd1;
    zx_rights_t rights;
    zx_status_t result = ChannelDispatcher::Create(&mpd0, &mpd1, &rights);
    if (result != ZX_OK)
        return result;

    uint64_t id0 = mpd0->get_koid();
    uint64_t id1 = mpd1->get_koid();

    HandleOwner h0(MakeHandle(fbl::move(mpd0), rights));
    if (!h0)
        return ZX_ERR_NO_MEMORY;

    HandleOwner h1(MakeHandle(fbl::move(mpd1), rights));
    if (!h1)
        return ZX_ERR_NO_MEMORY;

    if (out0.copy_to_user(up->MapHandleToValue(h0)) != ZX_OK)
        return ZX_ERR_INVALID_ARGS;
    if (out1.copy_to_user(up->MapHandleToValue(h1)) != ZX_OK)
        return ZX_ERR_INVALID_ARGS;

    up->AddHandle(fbl::move(h0));
    up->AddHandle(fbl::move(h1));

    ktrace(TAG_CHANNEL_CREATE, (uint32_t)id0, (uint32_t)id1, options, 0);
    return ZX_OK;
}

static void msg_get_handles(ProcessDispatcher* up, MessagePacket* msg,
                            user_out_ptr<zx_handle_t> handles, uint32_t num_handles) {
    Handle* const* handle_list = msg->handles();
    msg->set_owns_handles(false);

    zx_handle_t hvs[kMaxMessageHandles];
    for (size_t i = 0; i < num_handles; ++i) {
        hvs[i] = up->MapHandleToValue(handle_list[i]);
    }
    handles.copy_array_to_user(hvs, num_handles);

    for (size_t i = 0; i < num_handles; ++i) {
        if (handle_list[i]->dispatcher()->has_state_tracker())
            handle_list[i]->dispatcher()->Cancel(handle_list[i]);
        HandleOwner handle(handle_list[i]);
        // TODO(ZX-969): This takes a lock per call. Consider doing these in a batch.
        up->AddHandle(fbl::move(handle));
    }
}

zx_status_t sys_channel_read(zx_handle_t handle_value, uint32_t options,
                             user_out_ptr<void> bytes, user_out_ptr<zx_handle_t> handles,
                             uint32_t num_bytes, uint32_t num_handles,
                             user_out_ptr<uint32_t> actual_bytes,
                             user_out_ptr<uint32_t> actual_handles) {
    LTRACEF("handle %x bytes %p num_bytes %p handles %p num_handles %p",
            handle_value, bytes.get(), actual_bytes.get(), handles.get(), actual_handles.get());

    auto up = ProcessDispatcher::GetCurrent();

    fbl::RefPtr<ChannelDispatcher> channel;
    zx_status_t result = up->GetDispatcherWithRights(handle_value, ZX_RIGHT_READ, &channel);
    if (result != ZX_OK)
        return result;

    // Currently MAY_DISCARD is the only allowable option.
    if (options & ~ZX_CHANNEL_READ_MAY_DISCARD)
        return ZX_ERR_NOT_SUPPORTED;

    fbl::unique_ptr<MessagePacket> msg;
    result = channel->Read(&num_bytes, &num_handles, &msg,
                           options & ZX_CHANNEL_READ_MAY_DISCARD);
    if (result != ZX_OK && result != ZX_ERR_BUFFER_TOO_SMALL)
        return result;

    // On ZX_ERR_BUFFER_TOO_SMALL, Read() gives us the size of the next message (which remains
    // unconsumed, unless |options| has ZX_CHANNEL_READ_MAY_DISCARD set).
    if (actual_bytes) {
        if (actual_bytes.copy_to_user(num_bytes) != ZX_OK)
            return ZX_ERR_INVALID_ARGS;
    }
    if (actual_handles) {
        if (actual_handles.copy_to_user(num_handles) != ZX_OK)
            return ZX_ERR_INVALID_ARGS;
    }
    if (result == ZX_ERR_BUFFER_TOO_SMALL)
        return result;

    if (num_bytes > 0u) {
        if (msg->CopyDataTo(bytes) != ZX_OK)
            return ZX_ERR_INVALID_ARGS;
    }

    // The documented public API states that that writing to the handles buffer
    // must happen after writing to the data buffer.
    if (num_handles > 0u) {
        msg_get_handles(up, msg.get(), handles, num_handles);
    }

    ktrace(TAG_CHANNEL_READ, (uint32_t)channel->get_koid(), num_bytes, num_handles, 0);
    return result;
}

static zx_status_t channel_read_out(ProcessDispatcher* up,
                                    fbl::unique_ptr<MessagePacket> reply,
                                    zx_channel_call_args_t* args,
                                    user_out_ptr<uint32_t> actual_bytes,
                                    user_out_ptr<uint32_t> actual_handles) {
    uint32_t num_bytes = reply->data_size();
    uint32_t num_handles = reply->num_handles();

    if ((args->rd_num_bytes < num_bytes) || (args->rd_num_handles < num_handles)) {
        return ZX_ERR_BUFFER_TOO_SMALL;
    }

    if (actual_bytes.copy_to_user(num_bytes) != ZX_OK) {
        return ZX_ERR_INVALID_ARGS;
    }
    if (actual_handles.copy_to_user(num_handles) != ZX_OK) {
        return ZX_ERR_INVALID_ARGS;
    }

    if (num_bytes > 0u) {
        if (reply->CopyDataTo(make_user_out_ptr(args->rd_bytes)) != ZX_OK) {
            return ZX_ERR_INVALID_ARGS;
        }
    }

    if (num_handles > 0u) {
        msg_get_handles(up, reply.get(), make_user_out_ptr(args->rd_handles), num_handles);
    }
    return ZX_OK;
}

// Handles generating the final results for call successes and read-half failures.
static zx_status_t channel_call_epilogue(ProcessDispatcher* up,
                                         fbl::unique_ptr<MessagePacket> reply,
                                         zx_channel_call_args_t* args,
                                         zx_status_t call_status,
                                         user_out_ptr<uint32_t> actual_bytes,
                                         user_out_ptr<uint32_t> actual_handles,
                                         user_out_ptr<zx_status_t> read_status) {
    // Timeout is always returned directly.
    if (call_status == ZX_ERR_TIMED_OUT) {
        return call_status;
    }

    if (call_status == ZX_OK) {
        call_status = channel_read_out(up, fbl::move(reply), args, actual_bytes, actual_handles);
    }

    if (call_status != ZX_OK) {
        if (read_status) {
            read_status.copy_to_user(call_status);
        }
        return ZX_ERR_CALL_FAILED;
    }

    return ZX_OK;
}

static zx_status_t msg_put_handles(ProcessDispatcher* up, MessagePacket* msg, zx_handle_t* handles,
                                   user_in_ptr<const zx_handle_t> user_handles, uint32_t num_user_handles,
                                   Dispatcher* channel) {

    if (user_handles.copy_array_from_user(handles, num_user_handles) != ZX_OK)
        return ZX_ERR_INVALID_ARGS;

    {
        // Loop twice, first we collect and validate handles, the second pass
        // we remove them from this process.
        AutoLock lock(up->handle_table_lock());

        for (size_t ix = 0; ix != num_user_handles; ++ix) {
            auto handle = up->GetHandleLocked(handles[ix]);
            if (!handle)
                return ZX_ERR_BAD_HANDLE;

            if (handle->dispatcher().get() == channel) {
                // You may not write a channel endpoint handle
                // into that channel endpoint
                return ZX_ERR_NOT_SUPPORTED;
            }

            if (!handle->HasRights(ZX_RIGHT_TRANSFER))
                return ZX_ERR_ACCESS_DENIED;

            msg->mutable_handles()[ix] = handle;
        }

        for (size_t ix = 0; ix != num_user_handles; ++ix) {
            auto handle = up->RemoveHandleLocked(handles[ix]).release();
            // Passing duplicate handles is not allowed.
            // If we've already seen this handle flag an error.
            if (!handle) {
                // Put back the handles we've already removed.
                for (size_t idx = 0; idx < ix; ++idx) {
                    up->UndoRemoveHandleLocked(handles[idx]);
                }
                // TODO(ZX-968): more specific error?
                return ZX_ERR_INVALID_ARGS;
            }
        }
    }

    // On success, the MessagePacket owns the handles.
    msg->set_owns_handles(true);
    return ZX_OK;
}

zx_status_t sys_channel_write(zx_handle_t handle_value, uint32_t options,
                              user_in_ptr<const void> user_bytes, uint32_t num_bytes,
                              user_in_ptr<const zx_handle_t> user_handles, uint32_t num_handles) {
    LTRACEF("handle %x bytes %p num_bytes %u handles %p num_handles %u options 0x%x\n",
            handle_value, user_bytes.get(), num_bytes, user_handles.get(), num_handles, options);

    if (options)
        return ZX_ERR_INVALID_ARGS;

    auto up = ProcessDispatcher::GetCurrent();

    fbl::RefPtr<ChannelDispatcher> channel;
    zx_status_t result = up->GetDispatcherWithRights(handle_value, ZX_RIGHT_WRITE, &channel);
    if (result != ZX_OK)
        return result;


    fbl::unique_ptr<MessagePacket> msg;
    result = MessagePacket::Create(user_bytes, num_bytes, num_handles, &msg);
    if (result != ZX_OK)
        return result;

    zx_handle_t handles[kMaxMessageHandles];
    if (num_handles > 0u) {
        result = msg_put_handles(up, msg.get(), handles, user_handles, num_handles,
                                 static_cast<Dispatcher*>(channel.get()));
        if (result)
            return result;
    }

    result = channel->Write(fbl::move(msg));
    if (result != ZX_OK) {
        // Write failed, put back the handles into this process.
        AutoLock lock(up->handle_table_lock());
        for (size_t ix = 0; ix != num_handles; ++ix) {
            up->UndoRemoveHandleLocked(handles[ix]);
        }
        return result;
    }

    ktrace(TAG_CHANNEL_WRITE, (uint32_t)channel->get_koid(), num_bytes, num_handles, 0);
    return ZX_OK;
}

zx_status_t sys_channel_call_noretry(zx_handle_t handle_value, uint32_t options,
                                     zx_time_t deadline,
                                     user_in_ptr<const zx_channel_call_args_t> user_args,
                                     user_out_ptr<uint32_t> actual_bytes,
                                     user_out_ptr<uint32_t> actual_handles,
                                     user_out_ptr<zx_status_t> read_status) {
    zx_channel_call_args_t args;

    if (user_args.copy_from_user(&args) != ZX_OK)
        return ZX_ERR_INVALID_ARGS;

    if (options)
        return ZX_ERR_INVALID_ARGS;

    uint32_t num_bytes = args.wr_num_bytes;
    uint32_t num_handles = args.wr_num_handles;

    auto up = ProcessDispatcher::GetCurrent();

    fbl::RefPtr<ChannelDispatcher> channel;
    zx_status_t result =
        up->GetDispatcherWithRights(handle_value, ZX_RIGHT_WRITE | ZX_RIGHT_READ, &channel);
    if (result != ZX_OK)
        return result;

    // Prepare a MessagePacket for writing
    fbl::unique_ptr<MessagePacket> msg;
    result = MessagePacket::Create(make_user_in_ptr(args.wr_bytes),
                                   num_bytes, num_handles, &msg);
    if (result != ZX_OK)
        return result;

    zx_handle_t handles[kMaxMessageHandles];
    if (num_handles > 0u) {
        result = msg_put_handles(up, msg.get(), handles,
                                 make_user_in_ptr(args.wr_handles), num_handles,
                                 static_cast<Dispatcher*>(channel.get()));
        if (result)
            return result;
    }

    // TODO(ZX-970): ktrace channel calls; maybe two traces, maybe with txid.

    // Write message and wait for reply, deadline, or cancelation
    bool return_handles = false;
    fbl::unique_ptr<MessagePacket> reply;
    if ((result = channel->Call(fbl::move(msg), deadline, &return_handles, &reply)) != ZX_OK) {
        if (return_handles) {
            // Write phase failed:
            // 1. Put back the handles into this process.
            AutoLock lock(up->handle_table_lock());
            for (size_t ix = 0; ix != num_handles; ++ix) {
                up->UndoRemoveHandleLocked(handles[ix]);
            }
            // 2. Return error directly.  Note that the write phase cannot fail
            // with ZX_ERR_INTERNAL_INTR_RETRY.
            DEBUG_ASSERT(result != ZX_ERR_INTERNAL_INTR_RETRY);
            return result;
        }
    }
    return channel_call_epilogue(up, fbl::move(reply), &args, result,
                                 actual_bytes, actual_handles, read_status);
}

zx_status_t sys_channel_call_finish(zx_time_t deadline,
                                    user_in_ptr<const zx_channel_call_args_t> user_args,
                                    user_out_ptr<uint32_t> actual_bytes,
                                    user_out_ptr<uint32_t> actual_handles,
                                    user_out_ptr<zx_status_t> read_status) {

    zx_channel_call_args_t args;
    if (user_args.copy_from_user(&args) != ZX_OK)
        return ZX_ERR_INVALID_ARGS;

    auto up = ProcessDispatcher::GetCurrent();

    auto waiter = ThreadDispatcher::GetCurrent()->GetMessageWaiter();
    fbl::RefPtr<ChannelDispatcher> channel = waiter->get_channel();
    if (!channel)
        return ZX_ERR_BAD_STATE;

    fbl::unique_ptr<MessagePacket> reply;
    zx_status_t result = channel->ResumeInterruptedCall(
        waiter, deadline, &reply);
    return channel_call_epilogue(up, fbl::move(reply), &args, result,
                                 actual_bytes, actual_handles, read_status);

}
