From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>, Eric Blake <eblake@redhat.com>,
"Daniel P. Berrange" <berrange@redhat.com>
Subject: [Qemu-devel] [PATCH v2 3/8] ui: refactor VncDisplay to allow multiple listening sockets
Date: Tue, 24 Jan 2017 09:53:27 +0000 [thread overview]
Message-ID: <20170124095332.23955-4-berrange@redhat.com> (raw)
In-Reply-To: <20170124095332.23955-1-berrange@redhat.com>
Currently there is only a single listener for plain VNC and
a single listener for websockets VNC. This means that if
getaddrinfo() returns multiple IP addresses, for a hostname,
the VNC server can only listen on one of them. This is
just bearable if listening on wildcard interface, or if
the host only has a single network interface to listen on,
but if there are multiple NICs and the VNC server needs
to listen on 2 or more specific IP addresses, it can't be
done.
This refactors the VncDisplay state so that it holds an
array of listening sockets, but still only listens on
one socket.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
ui/vnc.c | 103 +++++++++++++++++++++++++++++++++++++++++----------------------
ui/vnc.h | 10 ++++---
2 files changed, 73 insertions(+), 40 deletions(-)
diff --git a/ui/vnc.c b/ui/vnc.c
index bd81922..9b9682d 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -224,8 +224,12 @@ static VncServerInfo *vnc_server_info_get(VncDisplay *vd)
VncServerInfo *info;
Error *err = NULL;
+ if (!vd->nlsock) {
+ return NULL;
+ }
+
info = g_malloc0(sizeof(*info));
- vnc_init_basic_info_from_server_addr(vd->lsock,
+ vnc_init_basic_info_from_server_addr(vd->lsock[0],
qapi_VncServerInfo_base(info), &err);
info->has_auth = true;
info->auth = g_strdup(vnc_auth_name(vd));
@@ -371,7 +375,7 @@ VncInfo *qmp_query_vnc(Error **errp)
VncDisplay *vd = vnc_display_find(NULL);
SocketAddress *addr = NULL;
- if (vd == NULL || !vd->lsock) {
+ if (vd == NULL || !vd->nlsock) {
info->enabled = false;
} else {
info->enabled = true;
@@ -384,7 +388,7 @@ VncInfo *qmp_query_vnc(Error **errp)
return info;
}
- addr = qio_channel_socket_get_local_address(vd->lsock, errp);
+ addr = qio_channel_socket_get_local_address(vd->lsock[0], errp);
if (!addr) {
goto out_error;
}
@@ -547,6 +551,7 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
VncInfo2 *info;
VncDisplay *vd;
DeviceState *dev;
+ size_t i;
QTAILQ_FOREACH(vd, &vnc_displays, next) {
info = g_new0(VncInfo2, 1);
@@ -560,13 +565,14 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
info->has_display = true;
info->display = g_strdup(dev->id);
}
- if (vd->lsock != NULL) {
+ for (i = 0; i < vd->nlsock; i++) {
info->server = qmp_query_server_entry(
- vd->lsock, false, vd->auth, vd->subauth, info->server);
+ vd->lsock[i], false, vd->auth, vd->subauth, info->server);
}
- if (vd->lwebsock != NULL) {
+ for (i = 0; i < vd->nlwebsock; i++) {
info->server = qmp_query_server_entry(
- vd->lwebsock, true, vd->ws_auth, vd->ws_subauth, info->server);
+ vd->lwebsock[i], true, vd->ws_auth,
+ vd->ws_subauth, info->server);
}
item = g_new0(VncInfo2List, 1);
@@ -3116,15 +3122,22 @@ static gboolean vnc_listen_io(QIOChannel *ioc,
VncDisplay *vd = opaque;
QIOChannelSocket *sioc = NULL;
Error *err = NULL;
+ bool isWebsock = false;
+ size_t i;
+
+ 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),
- ioc != QIO_CHANNEL(vd->lsock) ?
- "vnc-ws-server" : "vnc-server");
+ isWebsock ? "vnc-ws-server" : "vnc-server");
qio_channel_set_delay(QIO_CHANNEL(sioc), false);
- vnc_connect(vd, sioc, false,
- ioc != QIO_CHANNEL(vd->lsock));
+ vnc_connect(vd, sioc, false, isWebsock);
object_unref(OBJECT(sioc));
} else {
/* client probably closed connection before we got there */
@@ -3184,24 +3197,33 @@ void vnc_display_init(const char *id)
static void vnc_display_close(VncDisplay *vd)
{
+ size_t i;
if (!vd) {
return;
}
vd->is_unix = false;
- if (vd->lsock != NULL) {
- if (vd->lsock_tag) {
- g_source_remove(vd->lsock_tag);
+ for (i = 0; i < vd->nlsock; i++) {
+ if (vd->lsock_tag[i]) {
+ g_source_remove(vd->lsock_tag[i]);
}
- object_unref(OBJECT(vd->lsock));
- vd->lsock = NULL;
+ object_unref(OBJECT(vd->lsock[i]));
}
- if (vd->lwebsock != NULL) {
- if (vd->lwebsock_tag) {
- g_source_remove(vd->lwebsock_tag);
+ g_free(vd->lsock);
+ g_free(vd->lsock_tag);
+ vd->lsock = NULL;
+ vd->nlsock = 0;
+
+ for (i = 0; i < vd->nlwebsock; i++) {
+ if (vd->lwebsock_tag[i]) {
+ g_source_remove(vd->lwebsock_tag[i]);
}
- object_unref(OBJECT(vd->lwebsock));
- vd->lwebsock = NULL;
+ object_unref(OBJECT(vd->lwebsock[i]));
}
+ g_free(vd->lwebsock);
+ g_free(vd->lwebsock_tag);
+ vd->lwebsock = NULL;
+ vd->nlwebsock = 0;
+
vd->auth = VNC_AUTH_INVALID;
vd->subauth = VNC_AUTH_INVALID;
if (vd->tlscreds) {
@@ -3248,7 +3270,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
SocketAddress *addr;
Error *err = NULL;
- addr = qio_channel_socket_get_local_address(vd->lsock, &err);
+ if (!vd->nlsock) {
+ return;
+ }
+
+ addr = qio_channel_socket_get_local_address(vd->lsock[0], &err);
if (!addr) {
return;
}
@@ -3808,8 +3834,6 @@ void vnc_display_open(const char *id, Error **errp)
if (reverse) {
/* connect to viewer */
QIOChannelSocket *sioc = NULL;
- vd->lsock = NULL;
- vd->lwebsock = NULL;
if (ws_enabled) {
error_setg(errp, "Cannot use websockets in reverse mode");
goto fail;
@@ -3823,30 +3847,36 @@ void vnc_display_open(const char *id, Error **errp)
vnc_connect(vd, sioc, false, false);
object_unref(OBJECT(sioc));
} else {
- vd->lsock = qio_channel_socket_new();
- qio_channel_set_name(QIO_CHANNEL(vd->lsock), "vnc-listen");
- if (qio_channel_socket_listen_sync(vd->lsock, saddr, errp) < 0) {
+ vd->nlsock = 1;
+ vd->lsock = g_new0(QIOChannelSocket *, 1);
+ vd->lsock_tag = g_new0(guint, 1);
+
+ vd->lsock[0] = qio_channel_socket_new();
+ qio_channel_set_name(QIO_CHANNEL(vd->lsock[0]), "vnc-listen");
+ if (qio_channel_socket_listen_sync(vd->lsock[0], saddr, errp) < 0) {
goto fail;
}
vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
if (ws_enabled) {
- vd->lwebsock = qio_channel_socket_new();
- qio_channel_set_name(QIO_CHANNEL(vd->lwebsock), "vnc-ws-listen");
- if (qio_channel_socket_listen_sync(vd->lwebsock,
+ vd->nlwebsock = 1;
+ vd->lwebsock = g_new0(QIOChannelSocket *, 1);
+ vd->lwebsock_tag = g_new0(guint, 1);
+
+ vd->lwebsock[0] = qio_channel_socket_new();
+ qio_channel_set_name(QIO_CHANNEL(vd->lwebsock[0]), "vnc-ws-listen");
+ if (qio_channel_socket_listen_sync(vd->lwebsock[0],
wsaddr, errp) < 0) {
- object_unref(OBJECT(vd->lsock));
- vd->lsock = NULL;
goto fail;
}
}
- vd->lsock_tag = qio_channel_add_watch(
- QIO_CHANNEL(vd->lsock),
+ vd->lsock_tag[0] = qio_channel_add_watch(
+ QIO_CHANNEL(vd->lsock[0]),
G_IO_IN, vnc_listen_io, vd, NULL);
if (ws_enabled) {
- vd->lwebsock_tag = qio_channel_add_watch(
- QIO_CHANNEL(vd->lwebsock),
+ vd->lwebsock_tag[0] = qio_channel_add_watch(
+ QIO_CHANNEL(vd->lwebsock[0]),
G_IO_IN, vnc_listen_io, vd, NULL);
}
}
@@ -3860,6 +3890,7 @@ void vnc_display_open(const char *id, Error **errp)
return;
fail:
+ vnc_display_close(vd);
qapi_free_SocketAddress(saddr);
qapi_free_SocketAddress(wsaddr);
ws_enabled = false;
diff --git a/ui/vnc.h b/ui/vnc.h
index d20b154..453695a 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -146,10 +146,12 @@ struct VncDisplay
int num_exclusive;
int connections_limit;
VncSharePolicy share_policy;
- QIOChannelSocket *lsock;
- guint lsock_tag;
- QIOChannelSocket *lwebsock;
- guint lwebsock_tag;
+ size_t nlsock;
+ QIOChannelSocket **lsock;
+ guint *lsock_tag;
+ size_t nlwebsock;
+ QIOChannelSocket **lwebsock;
+ guint *lwebsock_tag;
DisplaySurface *ds;
DisplayChangeListener dcl;
kbd_layout_t *kbd_layout;
--
2.9.3
next prev parent reply other threads:[~2017-01-24 9:53 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-24 9:53 [Qemu-devel] [PATCH v2 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
2017-01-24 9:53 ` [Qemu-devel] [PATCH v2 1/8] ui: fix regression handling bare 'websocket' option to -vnc Daniel P. Berrange
2017-01-24 9:53 ` [Qemu-devel] [PATCH v2 2/8] ui: fix reporting of VNC auth in query-vnc-servers Daniel P. Berrange
2017-01-24 9:53 ` Daniel P. Berrange [this message]
2017-01-24 9:53 ` [Qemu-devel] [PATCH v2 4/8] ui: refactor code for populating SocketAddress from vnc_display_open Daniel P. Berrange
2017-01-24 9:53 ` [Qemu-devel] [PATCH v2 5/8] ui: extract code to connect/listen " Daniel P. Berrange
2017-01-24 9:53 ` [Qemu-devel] [PATCH v2 6/8] ui: let VNC server listen on all resolved IP addresses Daniel P. Berrange
2017-01-24 9:53 ` [Qemu-devel] [PATCH v2 7/8] util: add iterators for QemuOpts values Daniel P. Berrange
2017-01-24 18:58 ` Eric Blake
2017-01-24 9:53 ` [Qemu-devel] [PATCH v2 8/8] ui: add ability to specify multiple VNC listen addresses Daniel P. Berrange
2017-01-24 19:15 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170124095332.23955-4-berrange@redhat.com \
--to=berrange@redhat.com \
--cc=eblake@redhat.com \
--cc=kraxel@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.