// 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 <zircon/syscalls/policy.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 <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_ptr<zx_handle_t> out0, user_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_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()->get_state_tracker())
            handle_list[i]->dispatcher()->get_state_tracker()->Cancel(handle_list[i]);
        HandleOwner handle(handle_list[i]);
        // TODO(MG-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_ptr<void> bytes, user_ptr<zx_handle_t> handles,
                             uint32_t num_bytes, uint32_t num_handles,
                             user_ptr<uint32_t> actual_bytes, user_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_ptr<uint32_t> actual_bytes,
                                    user_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_ptr(args->rd_bytes)) != ZX_OK) {
            return ZX_ERR_INVALID_ARGS;
        }
    }

    if (num_handles > 0u) {
        msg_get_handles(up, reply.get(), make_user_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_ptr<uint32_t> actual_bytes,
                                         user_ptr<uint32_t> actual_handles,
                                         user_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_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(MG-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_ptr<const void> user_bytes, uint32_t num_bytes,
                              user_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_ptr<const zx_channel_call_args_t> user_args,
                                     user_ptr<uint32_t> actual_bytes,
                                     user_ptr<uint32_t> actual_handles,
                                     user_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_ptr<const void>(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_ptr<const zx_handle_t>(args.wr_handles), num_handles,
                                 static_cast<Dispatcher*>(channel.get()));
        if (result)
            return result;
    }

    // TODO(MG-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_ptr<const zx_channel_call_args_t> user_args,
                                    user_ptr<uint32_t> actual_bytes,
                                    user_ptr<uint32_t> actual_handles,
                                    user_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);

}
