Commit 57a6d6d5 authored by Daniel P. Berrangé's avatar Daniel P. Berrangé Committed by Gerd Hoffmann
Browse files

ui: let VNC server listen on all resolved IP addresses



Remove the limitation that the VNC server can only listen on
a single resolved IP address. This uses the new DNS resolver
API to resolve a SocketAddress struct into an array of
SocketAddress structs containing raw IP addresses. The VNC
server will then attempt to listen on all resolved IP addresses.
The server must successfully listen on at least one of the
resolved IP addresses, otherwise an error will be reported.

Reviewed-by: default avatarEric Blake <eblake@redhat.com>
Signed-off-by: default avatarDaniel P. Berrange <berrange@redhat.com>
Message-id: 20170203120649.15637-7-berrange@redhat.com
Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
parent 8bd22f47
Loading
Loading
Loading
Loading
+43 −9
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#include "crypto/tlscredsx509.h"
#include "qom/object_interfaces.h"
#include "qemu/cutils.h"
#include "io/dns-resolver.h"

#define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT
#define VNC_REFRESH_INTERVAL_INC  50
@@ -3698,19 +3699,52 @@ static int vnc_display_listen_addr(VncDisplay *vd,
                                   size_t *nlsock,
                                   Error **errp)
{
    *nlsock = 1;
    *lsock = g_new0(QIOChannelSocket *, 1);
    *lsock_tag = g_new0(guint, 1);
    QIODNSResolver *resolver = qio_dns_resolver_get_instance();
    SocketAddress **rawaddrs = NULL;
    size_t nrawaddrs = 0;
    Error *listenerr = NULL;
    size_t i;

    (*lsock)[0] = qio_channel_socket_new();
    qio_channel_set_name(QIO_CHANNEL((*lsock)[0]), name);
    if (qio_channel_socket_listen_sync((*lsock)[0], addr, errp) < 0) {
    if (qio_dns_resolver_lookup_sync(resolver, addr, &nrawaddrs,
                                     &rawaddrs, errp) < 0) {
        return -1;
    }

    (*lsock_tag)[0] = qio_channel_add_watch(
        QIO_CHANNEL((*lsock)[0]),
    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) {
            continue;
        }
        (*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 (*nlsock == 0) {
            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;
}