/*
 * Serving QEMU block devices via NBD
 *
 * Copyright (c) 2012 Red Hat, Inc.
 *
 * Author: Paolo Bonzini <pbonzini@redhat.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or
 * later.  See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "system/blockdev.h"
#include "system/block-backend.h"
#include "hw/block/block.h"
#include "qapi/error.h"
#include "qapi/clone-visitor.h"
#include "qapi/qapi-visit-block-export.h"
#include "qapi/qapi-commands-block-export.h"
#include "block/nbd.h"
#include "io/channel-socket.h"
#include "io/net-listener.h"

typedef struct NBDConn {
    QIOChannelSocket *cioc;
    QLIST_ENTRY(NBDConn) next;
} NBDConn;

typedef struct NBDServerData {
    QIONetListener *listener;
    uint32_t handshake_max_secs;
    QCryptoTLSCreds *tlscreds;
    char *tlsauthz;
    uint32_t max_connections;
    uint32_t connections;
    QLIST_HEAD(, NBDConn) conns;
} NBDServerData;

static NBDServerData *nbd_server;
static int qemu_nbd_connections = -1; /* Non-negative if this is qemu-nbd */

static void nbd_update_server_watch(NBDServerData *s);

void nbd_server_is_qemu_nbd(int max_connections)
{
    qemu_nbd_connections = max_connections;
}

bool nbd_server_is_running(void)
{
    return nbd_server || qemu_nbd_connections >= 0;
}

int nbd_server_max_connections(void)
{
    return nbd_server ? nbd_server->max_connections : qemu_nbd_connections;
}

static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
{
    NBDConn *conn = nbd_client_owner(client);

    assert(qemu_in_main_thread() && nbd_server);

    object_unref(OBJECT(conn->cioc));
    QLIST_REMOVE(conn, next);
    g_free(conn);

    nbd_client_put(client);
    assert(nbd_server->connections > 0);
    nbd_server->connections--;
    nbd_update_server_watch(nbd_server);
}

static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
                       gpointer opaque)
{
    NBDConn *conn = g_new0(NBDConn, 1);

    assert(qemu_in_main_thread() && nbd_server);
    nbd_server->connections++;
    object_ref(OBJECT(cioc));
    conn->cioc = cioc;
    QLIST_INSERT_HEAD(&nbd_server->conns, conn, next);
    nbd_update_server_watch(nbd_server);

    qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
    nbd_client_new(cioc, nbd_server->handshake_max_secs,
                   nbd_server->tlscreds, nbd_server->tlsauthz,
                   nbd_blockdev_client_closed, conn);
}

static void nbd_update_server_watch(NBDServerData *s)
{
    if (s->listener) {
        if (!s->max_connections || s->connections < s->max_connections) {
            qio_net_listener_set_client_func(s->listener, nbd_accept, NULL,
                                             NULL);
        } else {
            qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
        }
    }
}

static void nbd_server_free(NBDServerData *server)
{
    NBDConn *conn, *tmp;

    if (!server) {
        return;
    }

    /*
     * Forcefully close the listener socket, and any clients that have
     * not yet disconnected on their own.
     */
    qio_net_listener_disconnect(server->listener);
    object_unref(OBJECT(server->listener));
    server->listener = NULL;
    QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) {
        qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH,
                             NULL);
    }

    AIO_WAIT_WHILE_UNLOCKED(NULL, server->connections > 0);

    if (server->tlscreds) {
        object_unref(OBJECT(server->tlscreds));
    }
    g_free(server->tlsauthz);

    g_free(server);
}

static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
{
    Object *obj;
    QCryptoTLSCreds *creds;

    obj = object_resolve_path_component(
        object_get_objects_root(), id);
    if (!obj) {
        error_setg(errp, "No TLS credentials with id '%s'",
                   id);
        return NULL;
    }
    creds = (QCryptoTLSCreds *)
        object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS);
    if (!creds) {
        error_setg(errp, "Object with id '%s' is not TLS credentials",
                   id);
        return NULL;
    }

    if (!qcrypto_tls_creds_check_endpoint(creds,
                                          QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
                                          errp)) {
        return NULL;
    }
    object_ref(obj);
    return creds;
}


void nbd_server_start(SocketAddress *addr, uint32_t handshake_max_secs,
                      const char *tls_creds, const char *tls_authz,
                      uint32_t max_connections, Error **errp)
{
    if (nbd_server) {
        error_setg(errp, "NBD server already running");
        return;
    }

    nbd_server = g_new0(NBDServerData, 1);
    nbd_server->max_connections = max_connections;
    nbd_server->handshake_max_secs = handshake_max_secs;
    nbd_server->listener = qio_net_listener_new();

    qio_net_listener_set_name(nbd_server->listener,
                              "nbd-listener");

    /*
     * Because this server is persistent, a backlog of SOMAXCONN is
     * better than trying to size it to max_connections.
     */
    if (qio_net_listener_open_sync(nbd_server->listener, addr, SOMAXCONN,
                                   errp) < 0) {
        goto error;
    }

    if (tls_creds) {
        nbd_server->tlscreds = nbd_get_tls_creds(tls_creds, errp);
        if (!nbd_server->tlscreds) {
            goto error;
        }
    }

    nbd_server->tlsauthz = g_strdup(tls_authz);

    nbd_update_server_watch(nbd_server);

    return;

 error:
    nbd_server_free(nbd_server);
    nbd_server = NULL;
}

void nbd_server_start_options(NbdServerOptions *arg, Error **errp)
{
    if (!arg->has_max_connections) {
        arg->max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
    }
    if (!arg->has_handshake_max_seconds) {
        arg->handshake_max_seconds = NBD_DEFAULT_HANDSHAKE_MAX_SECS;
    }

    nbd_server_start(arg->addr, arg->handshake_max_seconds, arg->tls_creds,
                     arg->tls_authz, arg->max_connections, errp);
}

void qmp_nbd_server_start(bool has_handshake_max_secs,
                          uint32_t handshake_max_secs,
                          const char *tls_creds,
                          const char *tls_authz,
                          bool has_max_connections, uint32_t max_connections,
                          SocketAddressLegacy *addr,
                          Error **errp)
{
    SocketAddress *addr_flat = socket_address_flatten(addr);

    if (!has_max_connections) {
        max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
    }
    if (!has_handshake_max_secs) {
        handshake_max_secs = NBD_DEFAULT_HANDSHAKE_MAX_SECS;
    }

    nbd_server_start(addr_flat, handshake_max_secs, tls_creds, tls_authz,
                     max_connections, errp);
    qapi_free_SocketAddress(addr_flat);
}

void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp)
{
    BlockExport *export;
    BlockDriverState *bs;
    BlockBackend *on_eject_blk;
    BlockExportOptions *export_opts;

    bs = bdrv_lookup_bs(arg->device, arg->device, errp);
    if (!bs) {
        return;
    }

    /*
     * block-export-add would default to the node-name, but we may have to use
     * the device name as a default here for compatibility.
     */
    if (!arg->name) {
        arg->name = g_strdup(arg->device);
    }

    export_opts = g_new(BlockExportOptions, 1);
    *export_opts = (BlockExportOptions) {
        .type                   = BLOCK_EXPORT_TYPE_NBD,
        .id                     = g_strdup(arg->name),
        .node_name              = g_strdup(bdrv_get_node_name(bs)),
        .has_writable           = arg->has_writable,
        .writable               = arg->writable,
    };
    QAPI_CLONE_MEMBERS(BlockExportOptionsNbdBase, &export_opts->u.nbd,
                       qapi_NbdServerAddOptions_base(arg));
    if (arg->bitmap) {
        BlockDirtyBitmapOrStr *el = g_new(BlockDirtyBitmapOrStr, 1);

        *el = (BlockDirtyBitmapOrStr) {
            .type = QTYPE_QSTRING,
            .u.local = g_strdup(arg->bitmap),
        };
        export_opts->u.nbd.has_bitmaps = true;
        QAPI_LIST_PREPEND(export_opts->u.nbd.bitmaps, el);
    }

    /*
     * nbd-server-add doesn't complain when a read-only device should be
     * exported as writable, but simply downgrades it. This is an error with
     * block-export-add.
     */
    if (bdrv_is_read_only(bs)) {
        export_opts->has_writable = true;
        export_opts->writable = false;
    }

    export = blk_exp_add(export_opts, errp);
    if (!export) {
        goto fail;
    }

    /*
     * nbd-server-add removes the export when the named BlockBackend used for
     * @device goes away.
     */
    on_eject_blk = blk_by_name(arg->device);
    if (on_eject_blk) {
        nbd_export_set_on_eject_blk(export, on_eject_blk);
    }

fail:
    qapi_free_BlockExportOptions(export_opts);
}

void qmp_nbd_server_remove(const char *name,
                           bool has_mode, BlockExportRemoveMode mode,
                           Error **errp)
{
    BlockExport *exp;

    exp = blk_exp_find(name);
    if (exp && exp->drv->type != BLOCK_EXPORT_TYPE_NBD) {
        error_setg(errp, "Block export '%s' is not an NBD export", name);
        return;
    }

    qmp_block_export_del(name, has_mode, mode, errp);
}

void qmp_nbd_server_stop(Error **errp)
{
    if (!nbd_server) {
        error_setg(errp, "NBD server not running");
        return;
    }

    blk_exp_close_all_type(BLOCK_EXPORT_TYPE_NBD);

    nbd_server_free(nbd_server);
    nbd_server = NULL;
}
