Commit f24ee107 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kraxel/tags/ui-20180202-pull-request' into staging



ui: use QIONetListener in vnc, bugfixes for sdl1 and vnc.

# gpg: Signature made Fri 02 Feb 2018 07:17:36 GMT
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/ui-20180202-pull-request:
  ui: correctly advance output buffer when writing SASL data
  ui: convert VNC server to QIONetListener
  ui: fix mixup between qnum and qcode in SDL1 key handling

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents fb2516ef 627ebec2
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -242,6 +242,7 @@ static const guint16 *sdl_get_keymap(size_t *maplen)

static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
{
    int qcode;
    if (!keycode_map) {
        return 0;
    }
@@ -249,7 +250,13 @@ static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
        return 0;
    }

    return keycode_map[ev->keysym.scancode];
    qcode = keycode_map[ev->keysym.scancode];

    if (qcode > qemu_input_map_qcode_to_qnum_len) {
        return 0;
    }

    return qemu_input_map_qcode_to_qnum[qcode];
}

static void reset_keys(void)
+1 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ size_t vnc_client_write_sasl(VncState *vs)
        } else {
            vs->force_update_offset -= vs->sasl.encodedRawLength;
        }
        vs->output.offset -= vs->sasl.encodedRawLength;
        buffer_advance(&vs->output, vs->sasl.encodedRawLength);
        vs->sasl.encoded = NULL;
        vs->sasl.encodedOffset = vs->sasl.encodedLength = 0;
    }
+55 −140
Original line number Diff line number Diff line
@@ -228,12 +228,12 @@ static VncServerInfo *vnc_server_info_get(VncDisplay *vd)
    VncServerInfo *info;
    Error *err = NULL;

    if (!vd->nlsock) {
    if (!vd->listener || !vd->listener->nsioc) {
        return NULL;
    }

    info = g_malloc0(sizeof(*info));
    vnc_init_basic_info_from_server_addr(vd->lsock[0],
    vnc_init_basic_info_from_server_addr(vd->listener->sioc[0],
                                         qapi_VncServerInfo_base(info), &err);
    info->has_auth = true;
    info->auth = g_strdup(vnc_auth_name(vd));
@@ -379,7 +379,7 @@ VncInfo *qmp_query_vnc(Error **errp)
    VncDisplay *vd = vnc_display_find(NULL);
    SocketAddress *addr = NULL;

    if (vd == NULL || !vd->nlsock) {
    if (vd == NULL || !vd->listener || !vd->listener->nsioc) {
        info->enabled = false;
    } else {
        info->enabled = true;
@@ -388,11 +388,8 @@ VncInfo *qmp_query_vnc(Error **errp)
        info->has_clients = true;
        info->clients = qmp_query_client_list(vd);

        if (vd->lsock == NULL) {
            return info;
        }

        addr = qio_channel_socket_get_local_address(vd->lsock[0], errp);
        addr = qio_channel_socket_get_local_address(vd->listener->sioc[0],
                                                    errp);
        if (!addr) {
            goto out_error;
        }
@@ -572,13 +569,14 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
            info->has_display = true;
            info->display = g_strdup(dev->id);
        }
        for (i = 0; i < vd->nlsock; i++) {
        for (i = 0; vd->listener != NULL && i < vd->listener->nsioc; i++) {
            info->server = qmp_query_server_entry(
                vd->lsock[i], false, vd->auth, vd->subauth, info->server);
                vd->listener->sioc[i], false, vd->auth, vd->subauth,
                info->server);
        }
        for (i = 0; i < vd->nlwebsock; i++) {
        for (i = 0; vd->wslistener != NULL && i < vd->wslistener->nsioc; i++) {
            info->server = qmp_query_server_entry(
                vd->lwebsock[i], true, vd->ws_auth,
                vd->wslistener->sioc[i], true, vd->ws_auth,
                vd->ws_subauth, info->server);
        }

@@ -3143,36 +3141,18 @@ void vnc_start_protocol(VncState *vs)
    qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
}

static gboolean vnc_listen_io(QIOChannel *ioc,
                              GIOCondition condition,
static void vnc_listen_io(QIONetListener *listener,
                          QIOChannelSocket *cioc,
                          void *opaque)
{
    VncDisplay *vd = opaque;
    QIOChannelSocket *sioc = NULL;
    Error *err = NULL;
    bool isWebsock = false;
    size_t i;
    bool isWebsock = listener == vd->wslistener;

    for (i = 0; i < vd->nlwebsock; i++) {
        if (ioc == QIO_CHANNEL(vd->lwebsock[i])) {
            isWebsock = true;
            break;
        }
    }

    sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc), &err);
    if (sioc != NULL) {
        qio_channel_set_name(QIO_CHANNEL(sioc),
    qio_channel_set_name(QIO_CHANNEL(cioc),
                         isWebsock ? "vnc-ws-server" : "vnc-server");
        qio_channel_set_delay(QIO_CHANNEL(sioc), false);
        vnc_connect(vd, sioc, false, isWebsock);
        object_unref(OBJECT(sioc));
    } else {
        /* client probably closed connection before we got there */
        error_free(err);
    }

    return TRUE;
    qio_channel_set_delay(QIO_CHANNEL(cioc), false);
    vnc_connect(vd, cioc, false, isWebsock);
    object_unref(OBJECT(cioc));
}

static const DisplayChangeListenerOps dcl_ops = {
@@ -3224,34 +3204,22 @@ void vnc_display_init(const char *id)

static void vnc_display_close(VncDisplay *vd)
{
    size_t i;
    if (!vd) {
        return;
    }
    vd->is_unix = false;
    for (i = 0; i < vd->nlsock; i++) {
        if (vd->lsock_tag[i]) {
            g_source_remove(vd->lsock_tag[i]);
        }
        object_unref(OBJECT(vd->lsock[i]));
    }
    g_free(vd->lsock);
    g_free(vd->lsock_tag);
    vd->lsock = NULL;
    vd->lsock_tag = NULL;
    vd->nlsock = 0;

    for (i = 0; i < vd->nlwebsock; i++) {
        if (vd->lwebsock_tag[i]) {
            g_source_remove(vd->lwebsock_tag[i]);
    if (vd->listener) {
        qio_net_listener_disconnect(vd->listener);
        object_unref(OBJECT(vd->listener));
    }
        object_unref(OBJECT(vd->lwebsock[i]));
    vd->listener = NULL;

    if (vd->wslistener) {
        qio_net_listener_disconnect(vd->wslistener);
        object_unref(OBJECT(vd->wslistener));
    }
    g_free(vd->lwebsock);
    g_free(vd->lwebsock_tag);
    vd->lwebsock = NULL;
    vd->lwebsock_tag = NULL;
    vd->nlwebsock = 0;
    vd->wslistener = NULL;

    vd->auth = VNC_AUTH_INVALID;
    vd->subauth = VNC_AUTH_INVALID;
@@ -3303,11 +3271,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
    SocketAddress *addr;
    Error *err = NULL;

    if (!vd->nlsock) {
    if (!vd->listener || !vd->listener->nsioc) {
        return;
    }

    addr = qio_channel_socket_get_local_address(vd->lsock[0], &err);
    addr = qio_channel_socket_get_local_address(vd->listener->sioc[0], &err);
    if (!addr) {
        return;
    }
@@ -3815,68 +3783,6 @@ static int vnc_display_connect(VncDisplay *vd,
}


static int vnc_display_listen_addr(VncDisplay *vd,
                                   SocketAddress *addr,
                                   const char *name,
                                   QIOChannelSocket ***lsock,
                                   guint **lsock_tag,
                                   size_t *nlsock,
                                   Error **errp)
{
    QIODNSResolver *resolver = qio_dns_resolver_get_instance();
    SocketAddress **rawaddrs = NULL;
    size_t nrawaddrs = 0;
    Error *listenerr = NULL;
    bool listening = false;
    size_t i;

    if (qio_dns_resolver_lookup_sync(resolver, addr, &nrawaddrs,
                                     &rawaddrs, errp) < 0) {
        return -1;
    }

    for (i = 0; i < nrawaddrs; i++) {
        QIOChannelSocket *sioc = qio_channel_socket_new();

        qio_channel_set_name(QIO_CHANNEL(sioc), name);
        if (qio_channel_socket_listen_sync(
                sioc, rawaddrs[i], listenerr == NULL ? &listenerr : NULL) < 0) {
            object_unref(OBJECT(sioc));
            continue;
        }
        listening = true;
        (*nlsock)++;
        *lsock = g_renew(QIOChannelSocket *, *lsock, *nlsock);
        *lsock_tag = g_renew(guint, *lsock_tag, *nlsock);

        (*lsock)[*nlsock - 1] = sioc;
        (*lsock_tag)[*nlsock - 1] = 0;
    }

    for (i = 0; i < nrawaddrs; i++) {
        qapi_free_SocketAddress(rawaddrs[i]);
    }
    g_free(rawaddrs);

    if (listenerr) {
        if (!listening) {
            error_propagate(errp, listenerr);
            return -1;
        } else {
            error_free(listenerr);
        }
    }

    for (i = 0; i < *nlsock; i++) {
        (*lsock_tag)[i] = qio_channel_add_watch(
            QIO_CHANNEL((*lsock)[i]),
            G_IO_IN, vnc_listen_io, vd, NULL);
    }

    return 0;
}


static int vnc_display_listen(VncDisplay *vd,
                              SocketAddress **saddr,
                              size_t nsaddr,
@@ -3886,27 +3792,36 @@ static int vnc_display_listen(VncDisplay *vd,
{
    size_t i;

    if (nsaddr) {
        vd->listener = qio_net_listener_new();
        qio_net_listener_set_name(vd->listener, "vnc-listen");
        for (i = 0; i < nsaddr; i++) {
        if (vnc_display_listen_addr(vd, saddr[i],
                                    "vnc-listen",
                                    &vd->lsock,
                                    &vd->lsock_tag,
                                    &vd->nlsock,
            if (qio_net_listener_open_sync(vd->listener,
                                           saddr[i],
                                           errp) < 0)  {
                return -1;
            }
        }

        qio_net_listener_set_client_func(vd->listener,
                                         vnc_listen_io, vd, NULL);
    }

    if (nwsaddr) {
        vd->wslistener = qio_net_listener_new();
        qio_net_listener_set_name(vd->wslistener, "vnc-ws-listen");
        for (i = 0; i < nwsaddr; i++) {
        if (vnc_display_listen_addr(vd, wsaddr[i],
                                    "vnc-ws-listen",
                                    &vd->lwebsock,
                                    &vd->lwebsock_tag,
                                    &vd->nlwebsock,
            if (qio_net_listener_open_sync(vd->wslistener,
                                           wsaddr[i],
                                           errp) < 0)  {
                return -1;
            }
        }

        qio_net_listener_set_client_func(vd->wslistener,
                                         vnc_listen_io, vd, NULL);
    }

    return 0;
}

+3 −6
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "qemu/buffer.h"
#include "io/channel-socket.h"
#include "io/channel-tls.h"
#include "io/net-listener.h"
#include <zlib.h>

#include "keymaps.h"
@@ -146,12 +147,8 @@ struct VncDisplay
    int num_exclusive;
    int connections_limit;
    VncSharePolicy share_policy;
    size_t nlsock;
    QIOChannelSocket **lsock;
    guint *lsock_tag;
    size_t nlwebsock;
    QIOChannelSocket **lwebsock;
    guint *lwebsock_tag;
    QIONetListener *listener;
    QIONetListener *wslistener;
    DisplaySurface *ds;
    DisplayChangeListener dcl;
    kbd_layout_t *kbd_layout;