mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 16:23:55 -06:00
vnc: add display-update monitor command.
screendump: add png support. vmsvga: screen update fix. i386: sev setup for -bios loaded firmware -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmJpfYUACgkQTLbY7tPo cTg6ChAAn5EWtNwmVbfbVzRTu0kqdx7QXyK6FFgTgXrsrmBCWzJhHDraYa9cMOZU wBlU/Rutuv9ETvtRTRic3t0qcdRmvZjpHuA/3agBMJY7xpEQbQ8NwVdSRZTOZo0i hXzWEAnxviEv8F/W1TXwB5d2Q9sWlJ2yO8SvcxTfAEK7hOSFrWypp3XRKr5WBHjO DFTtwqTk9MRNsgsfnpEHNGDb30JPTqKZKRbDal15NDR9fQz+iCq3FIv/FpBaUfys v9GA2zNT324MvhR64xNblaujCn2XFOsFvDY4nGDrfbKGJch8ltAg5t4G1CCZqOn7 NIiwodC0508sAv9xUm+qvh+oHyf11EFdcAMWYimrExY2I51XOEDnJip/SAdogo5u h7LyLkZTEG5tyc+a4PGIcC216ecDDNytMnJM9nh9YK3p5UiBOgcHV2wWDdzJbsdS GRoP0fzF/MBQd985HBCF2vtQVk4AbQA7atZ8FKp1ZsHr3sFfs+vd0xyItsDMinBP k/eKOOKbHRgXcdIocw4PK16yURrMo5IUGCGGiG9waqYz+VDyHhtikBAzQvYYdnqN NaZttCcEieIk4XNd+wCfI0GQLtOY/AP1k8TV0rCaDTnO6nOxJ/uP64IaCzxzCT10 b8VRdCfYDGjd2C14XYKmTzBRPM4hVrf9bo7FtXVtmSksTG+eIao= =yaxh -----END PGP SIGNATURE----- Merge tag 'kraxel-20220427-pull-request' of git://git.kraxel.org/qemu into staging vnc: add display-update monitor command. screendump: add png support. vmsvga: screen update fix. i386: sev setup for -bios loaded firmware # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmJpfYUACgkQTLbY7tPo # cTg6ChAAn5EWtNwmVbfbVzRTu0kqdx7QXyK6FFgTgXrsrmBCWzJhHDraYa9cMOZU # wBlU/Rutuv9ETvtRTRic3t0qcdRmvZjpHuA/3agBMJY7xpEQbQ8NwVdSRZTOZo0i # hXzWEAnxviEv8F/W1TXwB5d2Q9sWlJ2yO8SvcxTfAEK7hOSFrWypp3XRKr5WBHjO # DFTtwqTk9MRNsgsfnpEHNGDb30JPTqKZKRbDal15NDR9fQz+iCq3FIv/FpBaUfys # v9GA2zNT324MvhR64xNblaujCn2XFOsFvDY4nGDrfbKGJch8ltAg5t4G1CCZqOn7 # NIiwodC0508sAv9xUm+qvh+oHyf11EFdcAMWYimrExY2I51XOEDnJip/SAdogo5u # h7LyLkZTEG5tyc+a4PGIcC216ecDDNytMnJM9nh9YK3p5UiBOgcHV2wWDdzJbsdS # GRoP0fzF/MBQd985HBCF2vtQVk4AbQA7atZ8FKp1ZsHr3sFfs+vd0xyItsDMinBP # k/eKOOKbHRgXcdIocw4PK16yURrMo5IUGCGGiG9waqYz+VDyHhtikBAzQvYYdnqN # NaZttCcEieIk4XNd+wCfI0GQLtOY/AP1k8TV0rCaDTnO6nOxJ/uP64IaCzxzCT10 # b8VRdCfYDGjd2C14XYKmTzBRPM4hVrf9bo7FtXVtmSksTG+eIao= # =yaxh # -----END PGP SIGNATURE----- # gpg: Signature made Wed 27 Apr 2022 10:29:41 AM PDT # gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [undefined] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [undefined] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * tag 'kraxel-20220427-pull-request' of git://git.kraxel.org/qemu: i386: firmware parsing and sev setup for -bios loaded firmware i386: factor out x86_firmware_configure() i386: move bios load error message avocado/vnc: add test_change_listen qapi/ui: add 'display-update' command for changing listen address ui/vnc: refactor arrays of addresses to SocketAddressList Added parameter to take screenshot with screendump as PNG Replacing CONFIG_VNC_PNG with CONFIG_PNG hw/display/vmware_vga: do not discard screen updates Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
cf6f26d6f9
21 changed files with 456 additions and 156 deletions
156
ui/vnc.c
156
ui/vnc.c
|
@ -2165,7 +2165,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
|
|||
vs->features |= VNC_FEATURE_TIGHT_MASK;
|
||||
vs->vnc_encoding = enc;
|
||||
break;
|
||||
#ifdef CONFIG_VNC_PNG
|
||||
#ifdef CONFIG_PNG
|
||||
case VNC_ENCODING_TIGHT_PNG:
|
||||
vs->features |= VNC_FEATURE_TIGHT_PNG_MASK;
|
||||
vs->vnc_encoding = enc;
|
||||
|
@ -3256,7 +3256,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
|
|||
#ifdef CONFIG_VNC_JPEG
|
||||
buffer_init(&vs->tight->jpeg, "vnc-tight-jpeg/%p", sioc);
|
||||
#endif
|
||||
#ifdef CONFIG_VNC_PNG
|
||||
#ifdef CONFIG_PNG
|
||||
buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc);
|
||||
#endif
|
||||
buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -4005,13 +3981,36 @@ static int vnc_display_listen(VncDisplay *vd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool vnc_display_update(DisplayUpdateOptionsVNC *arg, Error **errp)
|
||||
{
|
||||
VncDisplay *vd = vnc_display_find(NULL);
|
||||
|
||||
if (!vd) {
|
||||
error_setg(errp, "Can not find vnc display");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (arg->has_addresses) {
|
||||
if (vd->listener) {
|
||||
qio_net_listener_disconnect(vd->listener);
|
||||
object_unref(OBJECT(vd->listener));
|
||||
vd->listener = NULL;
|
||||
}
|
||||
|
||||
if (vnc_display_listen(vd, arg->addresses, NULL, errp) < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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 +4035,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;
|
||||
}
|
||||
|
||||
|
@ -4212,16 +4211,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;
|
||||
}
|
||||
}
|
||||
|
@ -4230,14 +4229,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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue