ui/vnc: refactor arrays of addresses to SocketAddressList

Let's use SocketAddressList instead of dynamic arrays.
Benefits:
 - Automatic cleanup: don't need specific freeing function and drop
   some gotos.
 - Less indirection: no triple asterix anymore!
 - Prepare for the following commit, which will reuse new interface of
   vnc_display_listen().

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@openvz.org>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20220401143936.356460-2-vsementsov@openvz.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Vladimir Sementsov-Ogievskiy 2022-04-01 17:39:34 +03:00 committed by Gerd Hoffmann
parent 9a0a119a38
commit d708f99d85
1 changed files with 51 additions and 78 deletions

129
ui/vnc.c
View File

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