// Copyright 2017 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 <platform.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <trace.h>

#include <lib/user_copy/user_ptr.h>
#include <object/handle_owner.h>
#include <object/handles.h>
#include <object/process_dispatcher.h>
#include <object/socket_dispatcher.h>

#include <zircon/syscalls/policy.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_socket_create(uint32_t options, user_out_ptr<zx_handle_t> out0, user_out_ptr<zx_handle_t> out1) {
    LTRACEF("entry out_handles %p, %p\n", out0.get(), out1.get());

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

    fbl::RefPtr<Dispatcher> socket0, socket1;
    zx_rights_t rights;
    zx_status_t result = SocketDispatcher::Create(options, &socket0, &socket1, &rights);
    if (result != ZX_OK)
        return result;

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

    HandleOwner h1(MakeHandle(fbl::move(socket1), 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));

    return ZX_OK;
}

zx_status_t sys_socket_write(zx_handle_t handle, uint32_t options,
                             user_in_ptr<const void> buffer, size_t size,
                             user_out_ptr<size_t> actual) {
    LTRACEF("handle %x\n", handle);

    if ((size > 0u) && !buffer)
        return ZX_ERR_INVALID_ARGS;

    auto up = ProcessDispatcher::GetCurrent();

    fbl::RefPtr<SocketDispatcher> socket;
    zx_status_t status = up->GetDispatcherWithRights(handle, ZX_RIGHT_WRITE, &socket);
    if (status != ZX_OK)
        return status;

    size_t nwritten;
    switch (options) {
    case 0:
        status = socket->Write(buffer, size, &nwritten);
        break;
    case ZX_SOCKET_CONTROL:
        status = socket->WriteControl(buffer, size);
        if (status == ZX_OK)
            nwritten = size;
        break;
    case ZX_SOCKET_SHUTDOWN_WRITE:
    case ZX_SOCKET_SHUTDOWN_READ:
    case ZX_SOCKET_SHUTDOWN_READ | ZX_SOCKET_SHUTDOWN_WRITE:
        if (size == 0)
            return socket->Shutdown(options & ZX_SOCKET_SHUTDOWN_MASK);
        // fallthrough
    default:
        return ZX_ERR_INVALID_ARGS;
    }

    // Caller may ignore results if desired.
    if (status == ZX_OK && actual)
        status = actual.copy_to_user(nwritten);

    return status;
}

zx_status_t sys_socket_read(zx_handle_t handle, uint32_t options,
                            user_out_ptr<void> buffer, size_t size,
                            user_out_ptr<size_t> actual) {
    LTRACEF("handle %x\n", handle);

    if (!buffer && size > 0)
        return ZX_ERR_INVALID_ARGS;

    auto up = ProcessDispatcher::GetCurrent();

    fbl::RefPtr<SocketDispatcher> socket;
    zx_status_t status = up->GetDispatcherWithRights(handle, ZX_RIGHT_READ, &socket);
    if (status != ZX_OK)
        return status;

    size_t nread;

    switch (options) {
    case 0:
        status = socket->Read(buffer, size, &nread);
        break;
    case ZX_SOCKET_CONTROL:
        status = socket->ReadControl(buffer, size, &nread);
        break;
    default:
        return ZX_ERR_INVALID_ARGS;
    }

    // Caller may ignore results if desired.
    if (status == ZX_OK && actual)
        status = actual.copy_to_user(nread);

    return status;
}

zx_status_t sys_socket_share(zx_handle_t handle, zx_handle_t other) {
    auto up = ProcessDispatcher::GetCurrent();

    fbl::RefPtr<SocketDispatcher> socket;
    zx_status_t status = up->GetDispatcherWithRights(handle, ZX_RIGHT_WRITE, &socket);
    if (status != ZX_OK)
        return status;

    fbl::RefPtr<SocketDispatcher> other_socket;
    status = up->GetDispatcherWithRights(other, ZX_RIGHT_TRANSFER, &other_socket);
    if (status != ZX_OK)
        return status;

    status = socket->CheckShareable(other_socket.get());
    if (status != ZX_OK)
        return status;

    Handle* h = up->RemoveHandle(other).release();

    status = socket->Share(h);

    if (status != ZX_OK) {
        AutoLock lock(up->handle_table_lock());
        up->UndoRemoveHandleLocked(other);
        return status;
    }

    return ZX_OK;
}

zx_status_t sys_socket_accept(zx_handle_t handle, user_out_ptr<zx_handle_t> out) {
    auto up = ProcessDispatcher::GetCurrent();

    fbl::RefPtr<SocketDispatcher> socket;
    zx_status_t status = up->GetDispatcherWithRights(handle, ZX_RIGHT_READ, &socket);
    if (status != ZX_OK)
        return status;

    Handle* h = NULL;
    status = socket->Accept(&h);
    if (status != ZX_OK)
        return status;

    zx_handle_t hv = up->MapHandleToValue(h);

    HandleOwner outhandle(h);
    up->AddHandle(fbl::move(outhandle));

    if (out.copy_to_user(hv) != ZX_OK)
        return ZX_ERR_INVALID_ARGS;

    return ZX_OK;
}