/*
 * QEMU VNC display driver
 *
 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
 * Copyright (C) 2006 Fabrice Bellard
 * Copyright (C) 2009 Red Hat, Inc
 * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */


#include "qemu/osdep.h"
#include "vnc.h"
#include "vnc-jobs.h"
#include "qemu/sockets.h"
#include "qemu/main-loop.h"
#include "block/aio.h"
#include "trace.h"

/*
 * Locking:
 *
 * There are three levels of locking:
 * - jobs queue lock: for each operation on the queue (push, pop, isEmpty?)
 * - VncDisplay global lock: mainly used for framebuffer updates to avoid
 *                      screen corruption if the framebuffer is updated
 *                      while the worker is doing something.
 * - VncState::output lock: used to make sure the output buffer is not corrupted
 *                          if two threads try to write on it at the same time
 *
 * While the VNC worker thread is working, the VncDisplay global lock is held
 * to avoid screen corruption (this does not block vnc_refresh() because it
 * uses trylock()) but the output lock is not held because the thread works on
 * its own output buffer.
 * When the encoding job is done, the worker thread will hold the output lock
 * and copy its output buffer in vs->output.
 */

struct VncJobQueue {
    QemuCond cond;
    QemuMutex mutex;
    QemuThread thread;
    bool exit;
    QTAILQ_HEAD(, VncJob) jobs;
};

typedef struct VncJobQueue VncJobQueue;

/*
 * We use a single global queue, but most of the functions are
 * already reentrant, so we can easily add more than one encoding thread
 */
static VncJobQueue *queue;

static void vnc_lock_queue(VncJobQueue *queue)
{
    qemu_mutex_lock(&queue->mutex);
}

static void vnc_unlock_queue(VncJobQueue *queue)
{
    qemu_mutex_unlock(&queue->mutex);
}

VncJob *vnc_job_new(VncState *vs)
{
    VncJob *job = g_new0(VncJob, 1);

    assert(vs->magic == VNC_MAGIC);
    job->vs = vs;
    vnc_lock_queue(queue);
    QLIST_INIT(&job->rectangles);
    vnc_unlock_queue(queue);
    return job;
}

int vnc_job_add_rect(VncJob *job, int x, int y, int w, int h)
{
    VncRectEntry *entry = g_new0(VncRectEntry, 1);

    trace_vnc_job_add_rect(job->vs, job, x, y, w, h);

    entry->rect.x = x;
    entry->rect.y = y;
    entry->rect.w = w;
    entry->rect.h = h;

    vnc_lock_queue(queue);
    QLIST_INSERT_HEAD(&job->rectangles, entry, next);
    vnc_unlock_queue(queue);
    return 1;
}

void vnc_job_push(VncJob *job)
{
    vnc_lock_queue(queue);
    if (queue->exit || QLIST_EMPTY(&job->rectangles)) {
        g_free(job);
    } else {
        QTAILQ_INSERT_TAIL(&queue->jobs, job, next);
        qemu_cond_broadcast(&queue->cond);
    }
    vnc_unlock_queue(queue);
}

static bool vnc_has_job_locked(VncState *vs)
{
    VncJob *job;

    QTAILQ_FOREACH(job, &queue->jobs, next) {
        if (job->vs == vs || !vs) {
            return true;
        }
    }
    return false;
}

void vnc_jobs_join(VncState *vs)
{
    vnc_lock_queue(queue);
    while (vnc_has_job_locked(vs)) {
        qemu_cond_wait(&queue->cond, &queue->mutex);
    }
    vnc_unlock_queue(queue);
    vnc_jobs_consume_buffer(vs);
}

void vnc_jobs_consume_buffer(VncState *vs)
{
    bool flush;

    vnc_lock_output(vs);
    if (vs->jobs_buffer.offset) {
        if (vs->ioc != NULL && buffer_empty(&vs->output)) {
            if (vs->ioc_tag) {
                g_source_remove(vs->ioc_tag);
            }
            if (vs->disconnecting == FALSE) {
                vs->ioc_tag = qio_channel_add_watch(
                    vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_OUT,
                    vnc_client_io, vs, NULL);
            }
        }
        buffer_move(&vs->output, &vs->jobs_buffer);

        if (vs->job_update == VNC_STATE_UPDATE_FORCE) {
            vs->force_update_offset = vs->output.offset;
        }
        vs->job_update = VNC_STATE_UPDATE_NONE;
    }
    flush = vs->ioc != NULL && vs->abort != true;
    vnc_unlock_output(vs);

    if (flush) {
      vnc_flush(vs);
    }
}

/*
 * Copy data for local use
 */
static void vnc_async_encoding_start(VncState *orig, VncState *local)
{
    buffer_init(&local->output, "vnc-worker-output");
    local->sioc = NULL; /* Don't do any network work on this thread */
    local->ioc = NULL; /* Don't do any network work on this thread */

    local->vnc_encoding = orig->vnc_encoding;
    local->features = orig->features;
    local->vd = orig->vd;
    local->lossy_rect = orig->lossy_rect;
    local->write_pixels = orig->write_pixels;
    local->client_pf = orig->client_pf;
    local->client_be = orig->client_be;
    local->tight = orig->tight;
    local->zlib = orig->zlib;
    local->hextile = orig->hextile;
    local->zrle = orig->zrle;
    local->client_width = orig->client_width;
    local->client_height = orig->client_height;
}

static void vnc_async_encoding_end(VncState *orig, VncState *local)
{
    buffer_free(&local->output);
    orig->tight = local->tight;
    orig->zlib = local->zlib;
    orig->hextile = local->hextile;
    orig->zrle = local->zrle;
    orig->lossy_rect = local->lossy_rect;
}

static bool vnc_worker_clamp_rect(VncState *vs, VncJob *job, VncRect *rect)
{
    trace_vnc_job_clamp_rect(vs, job, rect->x, rect->y, rect->w, rect->h);

    if (rect->x >= vs->client_width) {
        goto discard;
    }
    rect->w = MIN(vs->client_width - rect->x, rect->w);
    if (rect->w == 0) {
        goto discard;
    }

    if (rect->y >= vs->client_height) {
        goto discard;
    }
    rect->h = MIN(vs->client_height - rect->y, rect->h);
    if (rect->h == 0) {
        goto discard;
    }

    trace_vnc_job_clamped_rect(vs, job, rect->x, rect->y, rect->w, rect->h);
    return true;

 discard:
    trace_vnc_job_discard_rect(vs, job, rect->x, rect->y, rect->w, rect->h);
    return false;
}

static int vnc_worker_thread_loop(VncJobQueue *queue)
{
    VncJob *job;
    VncRectEntry *entry, *tmp;
    VncState vs = {};
    int n_rectangles;
    int saved_offset;

    vnc_lock_queue(queue);
    while (QTAILQ_EMPTY(&queue->jobs) && !queue->exit) {
        qemu_cond_wait(&queue->cond, &queue->mutex);
    }
    /* Here job can only be NULL if queue->exit is true */
    job = QTAILQ_FIRST(&queue->jobs);
    vnc_unlock_queue(queue);
    assert(job->vs->magic == VNC_MAGIC);

    if (queue->exit) {
        return -1;
    }

    vnc_lock_output(job->vs);
    if (job->vs->ioc == NULL || job->vs->abort == true) {
        vnc_unlock_output(job->vs);
        goto disconnected;
    }
    if (buffer_empty(&job->vs->output)) {
        /*
         * Looks like a NOP as it obviously moves no data.  But it
         * moves the empty buffer, so we don't have to malloc a new
         * one for vs.output
         */
        buffer_move_empty(&vs.output, &job->vs->output);
    }
    vnc_unlock_output(job->vs);

    /* Make a local copy of vs and switch output buffers */
    vnc_async_encoding_start(job->vs, &vs);
    vs.magic = VNC_MAGIC;

    /* Start sending rectangles */
    n_rectangles = 0;
    vnc_write_u8(&vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
    vnc_write_u8(&vs, 0);
    saved_offset = vs.output.offset;
    vnc_write_u16(&vs, 0);

    vnc_lock_display(job->vs->vd);
    QLIST_FOREACH_SAFE(entry, &job->rectangles, next, tmp) {
        int n;

        if (job->vs->ioc == NULL) {
            vnc_unlock_display(job->vs->vd);
            /* Copy persistent encoding data */
            vnc_async_encoding_end(job->vs, &vs);
            goto disconnected;
        }

        if (vnc_worker_clamp_rect(&vs, job, &entry->rect)) {
            n = vnc_send_framebuffer_update(&vs, entry->rect.x, entry->rect.y,
                                            entry->rect.w, entry->rect.h);

            if (n >= 0) {
                n_rectangles += n;
            }
        }
        g_free(entry);
    }
    trace_vnc_job_nrects(&vs, job, n_rectangles);
    vnc_unlock_display(job->vs->vd);

    /* Put n_rectangles at the beginning of the message */
    vs.output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
    vs.output.buffer[saved_offset + 1] = n_rectangles & 0xFF;

    vnc_lock_output(job->vs);
    if (job->vs->ioc != NULL) {
        buffer_move(&job->vs->jobs_buffer, &vs.output);
        /* Copy persistent encoding data */
        vnc_async_encoding_end(job->vs, &vs);

        qemu_bh_schedule(job->vs->bh);
    }  else {
        buffer_reset(&vs.output);
        /* Copy persistent encoding data */
        vnc_async_encoding_end(job->vs, &vs);
    }
    vnc_unlock_output(job->vs);

disconnected:
    vnc_lock_queue(queue);
    QTAILQ_REMOVE(&queue->jobs, job, next);
    vnc_unlock_queue(queue);
    qemu_cond_broadcast(&queue->cond);
    g_free(job);
    vs.magic = 0;
    return 0;
}

static VncJobQueue *vnc_queue_init(void)
{
    VncJobQueue *queue = g_new0(VncJobQueue, 1);

    qemu_cond_init(&queue->cond);
    qemu_mutex_init(&queue->mutex);
    QTAILQ_INIT(&queue->jobs);
    return queue;
}

static void vnc_queue_clear(VncJobQueue *q)
{
    qemu_cond_destroy(&queue->cond);
    qemu_mutex_destroy(&queue->mutex);
    g_free(q);
    queue = NULL; /* Unset global queue */
}

static void *vnc_worker_thread(void *arg)
{
    VncJobQueue *queue = arg;

    qemu_thread_get_self(&queue->thread);

    while (!vnc_worker_thread_loop(queue)) ;
    vnc_queue_clear(queue);
    return NULL;
}

static bool vnc_worker_thread_running(void)
{
    return queue; /* Check global queue */
}

void vnc_start_worker_thread(void)
{
    VncJobQueue *q;

    if (vnc_worker_thread_running())
        return ;

    q = vnc_queue_init();
    qemu_thread_create(&q->thread, "vnc_worker", vnc_worker_thread, q,
                       QEMU_THREAD_DETACHED);
    queue = q; /* Set global queue */
}
