// 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.h>
#include <object/process_dispatcher.h>
#include <object/socket_dispatcher.h>

#include <zircon/syscalls/policy.h>
#include <fbl/ref_ptr.h>

#include "priv.h"

#define LOCAL_TRACE 0

// zx_status_t zx_socket_create
zx_status_t sys_socket_create(uint32_t options,
                              user_out_handle* out0,
                              user_out_handle* out1) {
    auto up = ProcessDispatcher::GetCurrent();
    zx_status_t res = up->QueryBasicPolicy(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)
        result = out0->make(ktl::move(socket0), rights);
    if (result == ZX_OK)
        result = out1->make(ktl::move(socket1), rights);
    return result;
}

// zx_status_t zx_socket_write
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;
    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 zx_socket_read
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 zx_socket_share
zx_status_t sys_socket_share(zx_handle_t handle, zx_handle_t socket_to_share) {
    auto up = ProcessDispatcher::GetCurrent();

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

    HandleOwner other_handle = up->RemoveHandle(socket_to_share);
    if (!other_handle) {
        return ZX_ERR_BAD_HANDLE;
    }
    if (!other_handle->HasRights(ZX_RIGHT_TRANSFER)) {
        return ZX_ERR_ACCESS_DENIED;
    }

    fbl::RefPtr<Dispatcher> other_dispatcher = other_handle->dispatcher();
    auto other_socket = DownCastDispatcher<SocketDispatcher>(&other_dispatcher);
    if (other_socket == nullptr) {
        return ZX_ERR_WRONG_TYPE;
    }

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

    return socket->Share(ktl::move(other_handle));
}

// zx_status_t zx_socket_accept
zx_status_t sys_socket_accept(zx_handle_t handle, user_out_handle* 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;

    HandleOwner outhandle;
    status = socket->Accept(&outhandle);
    if (status != ZX_OK)
        return status;

    return out->transfer(ktl::move(outhandle));
}

// zx_status_t zx_socket_shutdown
zx_status_t sys_socket_shutdown(zx_handle_t handle, uint32_t options) {
    if (options & ~ZX_SOCKET_SHUTDOWN_MASK)
        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;

    return socket->Shutdown(options & ZX_SOCKET_SHUTDOWN_MASK);
}
