|
@@ -3820,30 +3820,19 @@ static int vnc_display_get_address(const char *addrstr,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static void vnc_free_addresses(SocketAddress ***retsaddr,
|
|
|
- size_t *retnsaddr)
|
|
|
-{
|
|
|
- size_t i;
|
|
|
-
|
|
|
- for (i = 0; i < *retnsaddr; i++) {
|
|
|
- qapi_free_SocketAddress((*retsaddr)[i]);
|
|
|
- }
|
|
|
- g_free(*retsaddr);
|
|
|
-
|
|
|
- *retsaddr = NULL;
|
|
|
- *retnsaddr = 0;
|
|
|
-}
|
|
|
-
|
|
|
static int vnc_display_get_addresses(QemuOpts *opts,
|
|
|
bool reverse,
|
|
|
- SocketAddress ***retsaddr,
|
|
|
- size_t *retnsaddr,
|
|
|
- SocketAddress ***retwsaddr,
|
|
|
- size_t *retnwsaddr,
|
|
|
+ SocketAddressList **saddr_list_ret,
|
|
|
+ SocketAddressList **wsaddr_list_ret,
|
|
|
Error **errp)
|
|
|
{
|
|
|
SocketAddress *saddr = NULL;
|
|
|
SocketAddress *wsaddr = NULL;
|
|
|
+ g_autoptr(SocketAddressList) saddr_list = NULL;
|
|
|
+ SocketAddressList **saddr_tail = &saddr_list;
|
|
|
+ SocketAddress *single_saddr = NULL;
|
|
|
+ g_autoptr(SocketAddressList) wsaddr_list = NULL;
|
|
|
+ SocketAddressList **wsaddr_tail = &wsaddr_list;
|
|
|
QemuOptsIter addriter;
|
|
|
const char *addr;
|
|
|
int to = qemu_opt_get_number(opts, "to", 0);
|
|
@@ -3852,23 +3841,16 @@ static int vnc_display_get_addresses(QemuOpts *opts,
|
|
|
bool ipv4 = qemu_opt_get_bool(opts, "ipv4", false);
|
|
|
bool ipv6 = qemu_opt_get_bool(opts, "ipv6", false);
|
|
|
int displaynum = -1;
|
|
|
- int ret = -1;
|
|
|
-
|
|
|
- *retsaddr = NULL;
|
|
|
- *retnsaddr = 0;
|
|
|
- *retwsaddr = NULL;
|
|
|
- *retnwsaddr = 0;
|
|
|
|
|
|
addr = qemu_opt_get(opts, "vnc");
|
|
|
if (addr == NULL || g_str_equal(addr, "none")) {
|
|
|
- ret = 0;
|
|
|
- goto cleanup;
|
|
|
+ return 0;
|
|
|
}
|
|
|
if (qemu_opt_get(opts, "websocket") &&
|
|
|
!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1)) {
|
|
|
error_setg(errp,
|
|
|
"SHA1 hash support is required for websockets");
|
|
|
- goto cleanup;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
qemu_opt_iter_init(&addriter, opts, "vnc");
|
|
@@ -3879,7 +3861,7 @@ static int vnc_display_get_addresses(QemuOpts *opts,
|
|
|
ipv4, ipv6,
|
|
|
&saddr, errp);
|
|
|
if (rv < 0) {
|
|
|
- goto cleanup;
|
|
|
+ return -1;
|
|
|
}
|
|
|
/* Historical compat - first listen address can be used
|
|
|
* to set the default websocket port
|
|
@@ -3887,13 +3869,16 @@ static int vnc_display_get_addresses(QemuOpts *opts,
|
|
|
if (displaynum == -1) {
|
|
|
displaynum = rv;
|
|
|
}
|
|
|
- *retsaddr = g_renew(SocketAddress *, *retsaddr, *retnsaddr + 1);
|
|
|
- (*retsaddr)[(*retnsaddr)++] = saddr;
|
|
|
+ QAPI_LIST_APPEND(saddr_tail, saddr);
|
|
|
}
|
|
|
|
|
|
- /* If we had multiple primary displays, we don't do defaults
|
|
|
- * for websocket, and require explicit config instead. */
|
|
|
- if (*retnsaddr > 1) {
|
|
|
+ if (saddr_list && !saddr_list->next) {
|
|
|
+ single_saddr = saddr_list->value;
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * If we had multiple primary displays, we don't do defaults
|
|
|
+ * for websocket, and require explicit config instead.
|
|
|
+ */
|
|
|
displaynum = -1;
|
|
|
}
|
|
|
|
|
@@ -3903,57 +3888,50 @@ static int vnc_display_get_addresses(QemuOpts *opts,
|
|
|
has_ipv4, has_ipv6,
|
|
|
ipv4, ipv6,
|
|
|
&wsaddr, errp) < 0) {
|
|
|
- goto cleanup;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
/* Historical compat - if only a single listen address was
|
|
|
* provided, then this is used to set the default listen
|
|
|
* address for websocket too
|
|
|
*/
|
|
|
- if (*retnsaddr == 1 &&
|
|
|
- (*retsaddr)[0]->type == SOCKET_ADDRESS_TYPE_INET &&
|
|
|
+ if (single_saddr &&
|
|
|
+ single_saddr->type == SOCKET_ADDRESS_TYPE_INET &&
|
|
|
wsaddr->type == SOCKET_ADDRESS_TYPE_INET &&
|
|
|
g_str_equal(wsaddr->u.inet.host, "") &&
|
|
|
- !g_str_equal((*retsaddr)[0]->u.inet.host, "")) {
|
|
|
+ !g_str_equal(single_saddr->u.inet.host, "")) {
|
|
|
g_free(wsaddr->u.inet.host);
|
|
|
- wsaddr->u.inet.host = g_strdup((*retsaddr)[0]->u.inet.host);
|
|
|
+ wsaddr->u.inet.host = g_strdup(single_saddr->u.inet.host);
|
|
|
}
|
|
|
|
|
|
- *retwsaddr = g_renew(SocketAddress *, *retwsaddr, *retnwsaddr + 1);
|
|
|
- (*retwsaddr)[(*retnwsaddr)++] = wsaddr;
|
|
|
+ QAPI_LIST_APPEND(wsaddr_tail, wsaddr);
|
|
|
}
|
|
|
|
|
|
- ret = 0;
|
|
|
- cleanup:
|
|
|
- if (ret < 0) {
|
|
|
- vnc_free_addresses(retsaddr, retnsaddr);
|
|
|
- vnc_free_addresses(retwsaddr, retnwsaddr);
|
|
|
- }
|
|
|
- return ret;
|
|
|
+ *saddr_list_ret = g_steal_pointer(&saddr_list);
|
|
|
+ *wsaddr_list_ret = g_steal_pointer(&wsaddr_list);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int vnc_display_connect(VncDisplay *vd,
|
|
|
- SocketAddress **saddr,
|
|
|
- size_t nsaddr,
|
|
|
- SocketAddress **wsaddr,
|
|
|
- size_t nwsaddr,
|
|
|
+ SocketAddressList *saddr_list,
|
|
|
+ SocketAddressList *wsaddr_list,
|
|
|
Error **errp)
|
|
|
{
|
|
|
/* connect to viewer */
|
|
|
QIOChannelSocket *sioc = NULL;
|
|
|
- if (nwsaddr != 0) {
|
|
|
+ if (wsaddr_list) {
|
|
|
error_setg(errp, "Cannot use websockets in reverse mode");
|
|
|
return -1;
|
|
|
}
|
|
|
- if (nsaddr != 1) {
|
|
|
+ if (!saddr_list || saddr_list->next) {
|
|
|
error_setg(errp, "Expected a single address in reverse mode");
|
|
|
return -1;
|
|
|
}
|
|
|
/* TODO SOCKET_ADDRESS_TYPE_FD when fd has AF_UNIX */
|
|
|
- vd->is_unix = saddr[0]->type == SOCKET_ADDRESS_TYPE_UNIX;
|
|
|
+ vd->is_unix = saddr_list->value->type == SOCKET_ADDRESS_TYPE_UNIX;
|
|
|
sioc = qio_channel_socket_new();
|
|
|
qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-reverse");
|
|
|
- if (qio_channel_socket_connect_sync(sioc, saddr[0], errp) < 0) {
|
|
|
+ if (qio_channel_socket_connect_sync(sioc, saddr_list->value, errp) < 0) {
|
|
|
object_unref(OBJECT(sioc));
|
|
|
return -1;
|
|
|
}
|
|
@@ -3964,20 +3942,18 @@ static int vnc_display_connect(VncDisplay *vd,
|
|
|
|
|
|
|
|
|
static int vnc_display_listen(VncDisplay *vd,
|
|
|
- SocketAddress **saddr,
|
|
|
- size_t nsaddr,
|
|
|
- SocketAddress **wsaddr,
|
|
|
- size_t nwsaddr,
|
|
|
+ SocketAddressList *saddr_list,
|
|
|
+ SocketAddressList *wsaddr_list,
|
|
|
Error **errp)
|
|
|
{
|
|
|
- size_t i;
|
|
|
+ SocketAddressList *el;
|
|
|
|
|
|
- if (nsaddr) {
|
|
|
+ if (saddr_list) {
|
|
|
vd->listener = qio_net_listener_new();
|
|
|
qio_net_listener_set_name(vd->listener, "vnc-listen");
|
|
|
- for (i = 0; i < nsaddr; i++) {
|
|
|
+ for (el = saddr_list; el; el = el->next) {
|
|
|
if (qio_net_listener_open_sync(vd->listener,
|
|
|
- saddr[i], 1,
|
|
|
+ el->value, 1,
|
|
|
errp) < 0) {
|
|
|
return -1;
|
|
|
}
|
|
@@ -3987,12 +3963,12 @@ static int vnc_display_listen(VncDisplay *vd,
|
|
|
vnc_listen_io, vd, NULL);
|
|
|
}
|
|
|
|
|
|
- if (nwsaddr) {
|
|
|
+ if (wsaddr_list) {
|
|
|
vd->wslistener = qio_net_listener_new();
|
|
|
qio_net_listener_set_name(vd->wslistener, "vnc-ws-listen");
|
|
|
- for (i = 0; i < nwsaddr; i++) {
|
|
|
+ for (el = wsaddr_list; el; el = el->next) {
|
|
|
if (qio_net_listener_open_sync(vd->wslistener,
|
|
|
- wsaddr[i], 1,
|
|
|
+ el->value, 1,
|
|
|
errp) < 0) {
|
|
|
return -1;
|
|
|
}
|
|
@@ -4010,8 +3986,8 @@ void vnc_display_open(const char *id, Error **errp)
|
|
|
{
|
|
|
VncDisplay *vd = vnc_display_find(id);
|
|
|
QemuOpts *opts = qemu_opts_find(&qemu_vnc_opts, id);
|
|
|
- SocketAddress **saddr = NULL, **wsaddr = NULL;
|
|
|
- size_t nsaddr, nwsaddr;
|
|
|
+ g_autoptr(SocketAddressList) saddr_list = NULL;
|
|
|
+ g_autoptr(SocketAddressList) wsaddr_list = NULL;
|
|
|
const char *share, *device_id;
|
|
|
QemuConsole *con;
|
|
|
bool password = false;
|
|
@@ -4036,8 +4012,8 @@ void vnc_display_open(const char *id, Error **errp)
|
|
|
}
|
|
|
|
|
|
reverse = qemu_opt_get_bool(opts, "reverse", false);
|
|
|
- if (vnc_display_get_addresses(opts, reverse, &saddr, &nsaddr,
|
|
|
- &wsaddr, &nwsaddr, errp) < 0) {
|
|
|
+ if (vnc_display_get_addresses(opts, reverse, &saddr_list, &wsaddr_list,
|
|
|
+ errp) < 0) {
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
@@ -4219,16 +4195,16 @@ void vnc_display_open(const char *id, Error **errp)
|
|
|
}
|
|
|
qkbd_state_set_delay(vd->kbd, key_delay_ms);
|
|
|
|
|
|
- if (saddr == NULL) {
|
|
|
- goto cleanup;
|
|
|
+ if (saddr_list == NULL) {
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
if (reverse) {
|
|
|
- if (vnc_display_connect(vd, saddr, nsaddr, wsaddr, nwsaddr, errp) < 0) {
|
|
|
+ if (vnc_display_connect(vd, saddr_list, wsaddr_list, errp) < 0) {
|
|
|
goto fail;
|
|
|
}
|
|
|
} else {
|
|
|
- if (vnc_display_listen(vd, saddr, nsaddr, wsaddr, nwsaddr, errp) < 0) {
|
|
|
+ if (vnc_display_listen(vd, saddr_list, wsaddr_list, errp) < 0) {
|
|
|
goto fail;
|
|
|
}
|
|
|
}
|
|
@@ -4237,14 +4213,11 @@ void vnc_display_open(const char *id, Error **errp)
|
|
|
vnc_display_print_local_addr(vd);
|
|
|
}
|
|
|
|
|
|
- cleanup:
|
|
|
- vnc_free_addresses(&saddr, &nsaddr);
|
|
|
- vnc_free_addresses(&wsaddr, &nwsaddr);
|
|
|
+ /* Success */
|
|
|
return;
|
|
|
|
|
|
fail:
|
|
|
vnc_display_close(vd);
|
|
|
- goto cleanup;
|
|
|
}
|
|
|
|
|
|
void vnc_display_add_client(const char *id, int csock, bool skipauth)
|