From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>,
"Daniel P. Berrange" <berrange@redhat.com>
Subject: [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets
Date: Thu, 5 Jan 2017 16:06:56 +0000 [thread overview]
Message-ID: <20170105160701.22118-4-berrange@redhat.com> (raw)
In-Reply-To: <20170105160701.22118-1-berrange@redhat.com>
Currently there is only a single listener for plain VNC and
a single listener for websockets VNC. This means that is
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.
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 28ee3e3..b37aab4 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);
@@ -3112,15 +3118,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 */
@@ -3180,24 +3193,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) {
@@ -3244,7 +3266,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;
}
@@ -3804,8 +3830,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;
@@ -3819,30 +3843,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);
}
}
@@ -3856,6 +3886,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-05 16:07 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
2017-01-05 16:06 ` [Qemu-devel] [PATCH 1/8] ui: fix regression handling bare 'websocket' option to -vnc Daniel P. Berrange
2017-01-06 13:39 ` Eric Blake
2017-01-05 16:06 ` [Qemu-devel] [PATCH 2/8] ui: fix reporting of VNC auth in query-vnc-servers Daniel P. Berrange
2017-01-06 15:06 ` Eric Blake
2017-01-05 16:06 ` Daniel P. Berrange [this message]
2017-01-06 15:23 ` [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets Eric Blake
2017-01-06 15:28 ` Daniel P. Berrange
2017-01-05 16:06 ` [Qemu-devel] [PATCH 4/8] ui: refactor code for populating SocketAddress from vnc_display_open Daniel P. Berrange
2017-01-06 15:47 ` Eric Blake
2017-01-05 16:06 ` [Qemu-devel] [PATCH 5/8] ui: extract code to connect/listen " Daniel P. Berrange
2017-01-06 16:00 ` Eric Blake
2017-01-05 16:06 ` [Qemu-devel] [PATCH 6/8] ui: let VNC server listen on all resolved IP addresses Daniel P. Berrange
2017-01-06 16:14 ` Eric Blake
2017-01-05 16:07 ` [Qemu-devel] [PATCH 7/8] util: add qemu_opt_get_all() to get repeated opts Daniel P. Berrange
2017-01-06 16:22 ` Eric Blake
2017-01-05 16:07 ` [Qemu-devel] [PATCH 8/8] ui: add ability to specify multiple VNC listen addresses Daniel P. Berrange
2017-01-06 16:34 ` Eric Blake
2017-01-05 17:26 ` [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server no-reply
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=20170105160701.22118-4-berrange@redhat.com \
--to=berrange@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.