// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <limits.h>
#include <poll.h>
#include <stdarg.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>

#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <fdio/io.h>
#include <fdio/remoteio.h>
#include <fdio/util.h>
#include <fdio/vfs.h>

#include "pipe.h"
#include "private.h"

ssize_t zx_pipe_read_internal(zx_handle_t h, void* data, size_t len, int nonblock) {
    // TODO: let the generic read() to do this loop
    for (;;) {
        size_t bytes_read;
        ssize_t r = zx_socket_read(h, 0, data, len, &bytes_read);
        if (r == ZX_OK) {
            // zx_socket_read() sets *actual to the number of bytes in the buffer when data is NULL
            // and len is 0. read() should return 0 in that case.
            if (len == 0) {
                return 0;
            } else {
                return (ssize_t)bytes_read;
            }
        } else if (r == ZX_ERR_PEER_CLOSED || r == ZX_ERR_BAD_STATE) {
            return 0;
        }
        if (r == ZX_ERR_SHOULD_WAIT && !nonblock) {
            zx_signals_t pending;
            r = zx_object_wait_one(h,
                                   ZX_SOCKET_READABLE | ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED,
                                   ZX_TIME_INFINITE,
                                   &pending);
            if (r < 0) {
                return r;
            }
            if (pending & ZX_SOCKET_READABLE) {
                continue;
            }
            if (pending & (ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED)) {
                return 0;
            }
            // impossible
            return ZX_ERR_INTERNAL;
        }
        return r;
    }
}

ssize_t zx_pipe_write_internal(zx_handle_t h, const void* data, size_t len, int nonblock) {
    // TODO: let the generic write() to do this loop
    for (;;) {
        ssize_t r;
        if ((r = zx_socket_write(h, 0, data, len, &len)) == ZX_OK) {
            return (ssize_t)len;
        }
        if (r == ZX_ERR_SHOULD_WAIT && !nonblock) {
            zx_signals_t pending;
            r = zx_object_wait_one(h,
                                   ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED | ZX_SOCKET_PEER_CLOSED,
                                   ZX_TIME_INFINITE,
                                   &pending);
            if (r < 0) {
                return r;
            }
            if (pending & ZX_SOCKET_WRITABLE) {
                continue;
            }
            if (pending & (ZX_SOCKET_WRITE_DISABLED | ZX_SOCKET_PEER_CLOSED)) {
                return ZX_ERR_PEER_CLOSED;
            }
            // impossible
            return ZX_ERR_INTERNAL;
        }
        return r;
    }
}


ssize_t zx_pipe_write(fdio_t* io, const void* data, size_t len) {
    zx_pipe_t* p = (zx_pipe_t*)io;
    return zx_pipe_write_internal(p->h, data, len, io->flags & FDIO_FLAG_NONBLOCK);
}

ssize_t zx_pipe_read(fdio_t* io, void* data, size_t len) {
    zx_pipe_t* p = (zx_pipe_t*)io;
    return zx_pipe_read_internal(p->h, data, len, io->flags & FDIO_FLAG_NONBLOCK);
}
zx_status_t zx_pipe_misc(fdio_t* io, uint32_t op, int64_t off, uint32_t maxreply, void* data, size_t len) {
    switch (op) {
    default:
        return ZX_ERR_NOT_SUPPORTED;

    case ZXRIO_STAT: {
        vnattr_t attr = {};
        if (maxreply < sizeof(attr)) {
            return ZX_ERR_INVALID_ARGS;
        }
        attr.mode = V_TYPE_PIPE | V_IRUSR | V_IWUSR;
        vnattr_t* attr_out = data;
        *attr_out = attr;
        return sizeof(attr);
    }
    case ZXRIO_FCNTL: {
        uint32_t* flags = (uint32_t*) data;
        if (flags) {
            *flags = 0;
        }
        return 0;
    }
    }
}

zx_status_t zx_pipe_close(fdio_t* io) {
    zx_pipe_t* p = (zx_pipe_t*)io;
    zx_handle_t h = p->h;
    p->h = 0;
    zx_handle_close(h);
    return 0;
}

static void zx_pipe_release(fdio_t* io) {
    zx_pipe_t* p = (zx_pipe_t*)io;
    zx_handle_close(p->h);
    free(io);
}

void zx_pipe_wait_begin(fdio_t* io, uint32_t events, zx_handle_t* handle, zx_signals_t* _signals) {
    zx_pipe_t* p = (void*)io;
    *handle = p->h;
    zx_signals_t signals = 0;
    if (events & POLLIN) {
        signals |= ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_READ_DISABLED;
    }
    if (events & POLLOUT) {
        signals |= ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED;
    }
    if (events & POLLRDHUP) {
        signals |= ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_READ_DISABLED;
    }
    *_signals = signals;
}

void zx_pipe_wait_end(fdio_t* io, zx_signals_t signals, uint32_t* _events) {
    uint32_t events = 0;
    if (signals & (ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_READ_DISABLED)) {
        events |= POLLIN;
    }
    if (signals & (ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED)) {
        events |= POLLOUT;
    }
    if (signals & (ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_READ_DISABLED)) {
        events |= POLLRDHUP;
    }
    *_events = events;
}

zx_status_t zx_pipe_clone(fdio_t* io, zx_handle_t* handles, uint32_t* types) {
    zx_pipe_t* p = (void*)io;
    zx_status_t status = zx_handle_duplicate(p->h, ZX_RIGHT_SAME_RIGHTS, &handles[0]);
    if (status < 0) {
        return status;
    }
    types[0] = PA_FDIO_PIPE;
    return 1;
}

zx_status_t zx_pipe_unwrap(fdio_t* io, zx_handle_t* handles, uint32_t* types) {
    zx_pipe_t* p = (void*)io;
    handles[0] = p->h;
    types[0] = PA_FDIO_PIPE;
    free(p);
    return 1;
}

ssize_t zx_pipe_posix_ioctl(fdio_t* io, int req, va_list va) {
    zx_pipe_t* p = (void*)io;
    switch (req) {
    case FIONREAD: {
        zx_status_t r;
        size_t avail;
        if ((r = zx_socket_read(p->h, 0, NULL, 0, &avail)) < 0) {
            return r;
        }
        if (avail > INT_MAX) {
            avail = INT_MAX;
        }
        int* actual = va_arg(va, int*);
        *actual = avail;
        return ZX_OK;
    }
    default:
        return ZX_ERR_NOT_SUPPORTED;
    }
}

static fdio_ops_t zx_pipe_ops = {
    .read = zx_pipe_read,
    .read_at = fdio_default_read_at,
    .write = zx_pipe_write,
    .write_at = fdio_default_write_at,
    .recvfrom = fdio_default_recvfrom,
    .sendto = fdio_default_sendto,
    .recvmsg = fdio_default_recvmsg,
    .sendmsg = fdio_default_sendmsg,
    .seek = fdio_default_seek,
    .misc = zx_pipe_misc,
    .close = zx_pipe_close,
    .open = fdio_default_open,
    .clone = zx_pipe_clone,
    .ioctl = fdio_default_ioctl,
    .wait_begin = zx_pipe_wait_begin,
    .wait_end = zx_pipe_wait_end,
    .unwrap = zx_pipe_unwrap,
    .shutdown = fdio_default_shutdown,
    .posix_ioctl = zx_pipe_posix_ioctl,
    .get_vmo = fdio_default_get_vmo,
};

fdio_t* fdio_pipe_create(zx_handle_t h) {
    zx_pipe_t* p = calloc(1, sizeof(*p));
    if (p == NULL) {
        zx_handle_close(h);
        return NULL;
    }
    p->io.ops = &zx_pipe_ops;
    p->io.magic = FDIO_MAGIC;
    atomic_init(&p->io.refcount, 1);
    p->h = h;
    return &p->io;
}

int fdio_pipe_pair(fdio_t** _a, fdio_t** _b) {
    zx_handle_t h0, h1;
    fdio_t *a, *b;
    zx_status_t r;
    if ((r = zx_socket_create(0, &h0, &h1)) < 0) {
        return r;
    }
    if ((a = fdio_pipe_create(h0)) == NULL) {
        zx_handle_close(h1);
        return ZX_ERR_NO_MEMORY;
    }
    if ((b = fdio_pipe_create(h1)) == NULL) {
        zx_pipe_close(a);
        return ZX_ERR_NO_MEMORY;
    }
    *_a = a;
    *_b = b;
    return 0;
}

zx_status_t fdio_pipe_pair_raw(zx_handle_t* handles, uint32_t* types) {
    zx_status_t r;
    if ((r = zx_socket_create(0, handles, handles + 1)) < 0) {
        return r;
    }
    types[0] = PA_FDIO_PIPE;
    types[1] = PA_FDIO_PIPE;
    return 2;
}

zx_status_t fdio_pipe_half(zx_handle_t* handle, uint32_t* type) {
    zx_handle_t h0, h1;
    zx_status_t r;
    fdio_t* io;
    int fd;
    if ((r = zx_socket_create(0, &h0, &h1)) < 0) {
        return r;
    }
    if ((io = fdio_pipe_create(h0)) == NULL) {
        r = ZX_ERR_NO_MEMORY;
        goto fail;
    }
    if ((fd = fdio_bind_to_fd(io, -1, 0)) < 0) {
        fdio_release(io);
        r = ZX_ERR_NO_RESOURCES;
        goto fail;
    }
    *handle = h1;
    *type = PA_FDIO_PIPE;
    return fd;

fail:
    zx_handle_close(h1);
    return r;
}
