]> git.proxmox.com Git - mirror_qemu.git/blame - ui/vnc.c
ui/gtk.c: add ctrl-alt-= support for zoom in acceleration
[mirror_qemu.git] / ui / vnc.c
CommitLineData
7d510b8c
FB
1/*
2 * QEMU VNC display driver
5fafdf24 3 *
7d510b8c
FB
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
19a490bf 6 * Copyright (C) 2009 Red Hat, Inc
5fafdf24 7 *
7d510b8c
FB
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
e16f4c87 27#include "qemu/osdep.h"
19a490bf 28#include "vnc.h"
bd023f95 29#include "vnc-jobs.h"
40066175 30#include "trace.h"
1d0d59fe 31#include "hw/qdev.h"
9c17d615 32#include "sysemu/sysemu.h"
d49b6836 33#include "qemu/error-report.h"
1de7afc9
PB
34#include "qemu/sockets.h"
35#include "qemu/timer.h"
36#include "qemu/acl.h"
4db14629 37#include "qemu/config-file.h"
cc7a8ea7 38#include "qapi/qmp/qerror.h"
7b1b5d19 39#include "qapi/qmp/types.h"
2b54aa87 40#include "qmp-commands.h"
8d447d10 41#include "ui/input.h"
fb6ba0d5 42#include "qapi-event.h"
8e9b0d24 43#include "crypto/hash.h"
3e305e4a
DB
44#include "crypto/tlscredsanon.h"
45#include "crypto/tlscredsx509.h"
46#include "qom/object_interfaces.h"
f348b6d1 47#include "qemu/cutils.h"
24236869 48
0f7b2864 49#define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT
2430ffe4 50#define VNC_REFRESH_INTERVAL_INC 50
0f7b2864 51#define VNC_REFRESH_INTERVAL_MAX GUI_REFRESH_INTERVAL_IDLE
999342a0
CC
52static const struct timeval VNC_REFRESH_STATS = { 0, 500000 };
53static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
24236869
FB
54
55#include "vnc_keysym.h"
800567a6 56#include "crypto/cipher.h"
70848515 57
d616ccc5
GH
58static QTAILQ_HEAD(, VncDisplay) vnc_displays =
59 QTAILQ_HEAD_INITIALIZER(vnc_displays);
a9ce8590 60
d467b679 61static int vnc_cursor_define(VncState *vs);
7bc9318b 62static void vnc_release_modifiers(VncState *vs);
d467b679 63
8cf36489
GH
64static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
65{
66#ifdef _VNC_DEBUG
67 static const char *mn[] = {
68 [0] = "undefined",
69 [VNC_SHARE_MODE_CONNECTING] = "connecting",
70 [VNC_SHARE_MODE_SHARED] = "shared",
71 [VNC_SHARE_MODE_EXCLUSIVE] = "exclusive",
72 [VNC_SHARE_MODE_DISCONNECTED] = "disconnected",
73 };
04d2529d
DB
74 fprintf(stderr, "%s/%p: %s -> %s\n", __func__,
75 vs->ioc, mn[vs->share_mode], mn[mode]);
8cf36489
GH
76#endif
77
e5f34cdd
GH
78 switch (vs->share_mode) {
79 case VNC_SHARE_MODE_CONNECTING:
80 vs->vd->num_connecting--;
81 break;
82 case VNC_SHARE_MODE_SHARED:
83 vs->vd->num_shared--;
84 break;
85 case VNC_SHARE_MODE_EXCLUSIVE:
8cf36489 86 vs->vd->num_exclusive--;
e5f34cdd
GH
87 break;
88 default:
89 break;
8cf36489 90 }
e5f34cdd 91
8cf36489 92 vs->share_mode = mode;
e5f34cdd
GH
93
94 switch (vs->share_mode) {
95 case VNC_SHARE_MODE_CONNECTING:
96 vs->vd->num_connecting++;
97 break;
98 case VNC_SHARE_MODE_SHARED:
99 vs->vd->num_shared++;
100 break;
101 case VNC_SHARE_MODE_EXCLUSIVE:
8cf36489 102 vs->vd->num_exclusive++;
e5f34cdd
GH
103 break;
104 default:
105 break;
8cf36489
GH
106 }
107}
108
1ff7df1a 109
04d2529d 110static void vnc_init_basic_info(SocketAddress *addr,
98481bfc
EB
111 VncBasicInfo *info,
112 Error **errp)
d96fd29c 113{
04d2529d
DB
114 switch (addr->type) {
115 case SOCKET_ADDRESS_KIND_INET:
32bafa8f
EB
116 info->host = g_strdup(addr->u.inet.data->host);
117 info->service = g_strdup(addr->u.inet.data->port);
118 if (addr->u.inet.data->ipv6) {
04d2529d
DB
119 info->family = NETWORK_ADDRESS_FAMILY_IPV6;
120 } else {
121 info->family = NETWORK_ADDRESS_FAMILY_IPV4;
122 }
123 break;
d96fd29c 124
04d2529d
DB
125 case SOCKET_ADDRESS_KIND_UNIX:
126 info->host = g_strdup("");
32bafa8f 127 info->service = g_strdup(addr->u.q_unix.data->path);
04d2529d
DB
128 info->family = NETWORK_ADDRESS_FAMILY_UNIX;
129 break;
130
131 default:
132 error_setg(errp, "Unsupported socket kind %d",
133 addr->type);
134 break;
d96fd29c
LC
135 }
136
04d2529d 137 return;
d96fd29c
LC
138}
139
04d2529d
DB
140static void vnc_init_basic_info_from_server_addr(QIOChannelSocket *ioc,
141 VncBasicInfo *info,
98481bfc 142 Error **errp)
d96fd29c 143{
04d2529d 144 SocketAddress *addr = NULL;
d96fd29c 145
624cdd46
DB
146 if (!ioc) {
147 error_setg(errp, "No listener socket available");
148 return;
149 }
150
04d2529d
DB
151 addr = qio_channel_socket_get_local_address(ioc, errp);
152 if (!addr) {
98481bfc 153 return;
d96fd29c
LC
154 }
155
04d2529d
DB
156 vnc_init_basic_info(addr, info, errp);
157 qapi_free_SocketAddress(addr);
d96fd29c
LC
158}
159
04d2529d
DB
160static void vnc_init_basic_info_from_remote_addr(QIOChannelSocket *ioc,
161 VncBasicInfo *info,
98481bfc 162 Error **errp)
d96fd29c 163{
04d2529d 164 SocketAddress *addr = NULL;
d96fd29c 165
04d2529d
DB
166 addr = qio_channel_socket_get_remote_address(ioc, errp);
167 if (!addr) {
98481bfc 168 return;
d96fd29c
LC
169 }
170
04d2529d
DB
171 vnc_init_basic_info(addr, info, errp);
172 qapi_free_SocketAddress(addr);
d96fd29c
LC
173}
174
1ff7df1a
AL
175static const char *vnc_auth_name(VncDisplay *vd) {
176 switch (vd->auth) {
177 case VNC_AUTH_INVALID:
178 return "invalid";
179 case VNC_AUTH_NONE:
180 return "none";
181 case VNC_AUTH_VNC:
182 return "vnc";
183 case VNC_AUTH_RA2:
184 return "ra2";
185 case VNC_AUTH_RA2NE:
186 return "ra2ne";
187 case VNC_AUTH_TIGHT:
188 return "tight";
189 case VNC_AUTH_ULTRA:
190 return "ultra";
191 case VNC_AUTH_TLS:
192 return "tls";
193 case VNC_AUTH_VENCRYPT:
1ff7df1a
AL
194 switch (vd->subauth) {
195 case VNC_AUTH_VENCRYPT_PLAIN:
196 return "vencrypt+plain";
197 case VNC_AUTH_VENCRYPT_TLSNONE:
198 return "vencrypt+tls+none";
199 case VNC_AUTH_VENCRYPT_TLSVNC:
200 return "vencrypt+tls+vnc";
201 case VNC_AUTH_VENCRYPT_TLSPLAIN:
202 return "vencrypt+tls+plain";
203 case VNC_AUTH_VENCRYPT_X509NONE:
204 return "vencrypt+x509+none";
205 case VNC_AUTH_VENCRYPT_X509VNC:
206 return "vencrypt+x509+vnc";
207 case VNC_AUTH_VENCRYPT_X509PLAIN:
208 return "vencrypt+x509+plain";
28a76be8
AL
209 case VNC_AUTH_VENCRYPT_TLSSASL:
210 return "vencrypt+tls+sasl";
211 case VNC_AUTH_VENCRYPT_X509SASL:
212 return "vencrypt+x509+sasl";
1ff7df1a
AL
213 default:
214 return "vencrypt";
215 }
2f9606b3 216 case VNC_AUTH_SASL:
28a76be8 217 return "sasl";
1ff7df1a
AL
218 }
219 return "unknown";
220}
221
d616ccc5 222static VncServerInfo *vnc_server_info_get(VncDisplay *vd)
a7789382 223{
fb6ba0d5 224 VncServerInfo *info;
98481bfc 225 Error *err = NULL;
a7789382 226
3e7f136d 227 info = g_malloc0(sizeof(*info));
ddf21908
EB
228 vnc_init_basic_info_from_server_addr(vd->lsock,
229 qapi_VncServerInfo_base(info), &err);
fb6ba0d5 230 info->has_auth = true;
d616ccc5 231 info->auth = g_strdup(vnc_auth_name(vd));
98481bfc
EB
232 if (err) {
233 qapi_free_VncServerInfo(info);
234 info = NULL;
235 error_free(err);
236 }
fb6ba0d5 237 return info;
a7789382
LC
238}
239
4a80dba3 240static void vnc_client_cache_auth(VncState *client)
1ff7df1a 241{
4a80dba3
LC
242 if (!client->info) {
243 return;
d96fd29c 244 }
1263b7d6 245
3e305e4a
DB
246 if (client->tls) {
247 client->info->x509_dname =
248 qcrypto_tls_session_get_peer_name(client->tls);
249 client->info->has_x509_dname =
250 client->info->x509_dname != NULL;
d96fd29c 251 }
1263b7d6
AL
252#ifdef CONFIG_VNC_SASL
253 if (client->sasl.conn &&
d96fd29c 254 client->sasl.username) {
fb6ba0d5
WX
255 client->info->has_sasl_username = true;
256 client->info->sasl_username = g_strdup(client->sasl.username);
d96fd29c 257 }
1263b7d6 258#endif
4a80dba3 259}
d96fd29c 260
4a80dba3
LC
261static void vnc_client_cache_addr(VncState *client)
262{
98481bfc
EB
263 Error *err = NULL;
264
265 client->info = g_malloc0(sizeof(*client->info));
04d2529d 266 vnc_init_basic_info_from_remote_addr(client->sioc,
ddf21908 267 qapi_VncClientInfo_base(client->info),
98481bfc
EB
268 &err);
269 if (err) {
270 qapi_free_VncClientInfo(client->info);
271 client->info = NULL;
272 error_free(err);
4a80dba3 273 }
1ff7df1a
AL
274}
275
fb6ba0d5 276static void vnc_qmp_event(VncState *vs, QAPIEvent event)
586153d9 277{
fb6ba0d5 278 VncServerInfo *si;
586153d9
LC
279
280 if (!vs->info) {
281 return;
282 }
283
d616ccc5 284 si = vnc_server_info_get(vs->vd);
fb6ba0d5 285 if (!si) {
586153d9
LC
286 return;
287 }
288
fb6ba0d5
WX
289 switch (event) {
290 case QAPI_EVENT_VNC_CONNECTED:
ddf21908
EB
291 qapi_event_send_vnc_connected(si, qapi_VncClientInfo_base(vs->info),
292 &error_abort);
fb6ba0d5
WX
293 break;
294 case QAPI_EVENT_VNC_INITIALIZED:
295 qapi_event_send_vnc_initialized(si, vs->info, &error_abort);
296 break;
297 case QAPI_EVENT_VNC_DISCONNECTED:
298 qapi_event_send_vnc_disconnected(si, vs->info, &error_abort);
299 break;
300 default:
301 break;
302 }
586153d9 303
fb6ba0d5 304 qapi_free_VncServerInfo(si);
586153d9
LC
305}
306
2b54aa87 307static VncClientInfo *qmp_query_vnc_client(const VncState *client)
a9ce8590 308{
2b54aa87 309 VncClientInfo *info;
04d2529d 310 Error *err = NULL;
2b54aa87 311
04d2529d 312 info = g_malloc0(sizeof(*info));
2b54aa87 313
04d2529d
DB
314 vnc_init_basic_info_from_remote_addr(client->sioc,
315 qapi_VncClientInfo_base(info),
316 &err);
317 if (err) {
318 error_free(err);
319 qapi_free_VncClientInfo(info);
2b54aa87
LC
320 return NULL;
321 }
d96fd29c 322
ddf21908 323 info->websocket = client->websocket;
d96fd29c 324
3e305e4a
DB
325 if (client->tls) {
326 info->x509_dname = qcrypto_tls_session_get_peer_name(client->tls);
327 info->has_x509_dname = info->x509_dname != NULL;
2b54aa87 328 }
d96fd29c 329#ifdef CONFIG_VNC_SASL
2b54aa87
LC
330 if (client->sasl.conn && client->sasl.username) {
331 info->has_sasl_username = true;
332 info->sasl_username = g_strdup(client->sasl.username);
d96fd29c 333 }
2b54aa87 334#endif
1ff7df1a 335
2b54aa87 336 return info;
d96fd29c 337}
1ff7df1a 338
d616ccc5
GH
339static VncDisplay *vnc_display_find(const char *id)
340{
341 VncDisplay *vd;
342
343 if (id == NULL) {
344 return QTAILQ_FIRST(&vnc_displays);
345 }
346 QTAILQ_FOREACH(vd, &vnc_displays, next) {
347 if (strcmp(id, vd->id) == 0) {
348 return vd;
349 }
350 }
351 return NULL;
352}
353
2d29a436
GH
354static VncClientInfoList *qmp_query_client_list(VncDisplay *vd)
355{
356 VncClientInfoList *cinfo, *prev = NULL;
357 VncState *client;
358
359 QTAILQ_FOREACH(client, &vd->clients, next) {
360 cinfo = g_new0(VncClientInfoList, 1);
361 cinfo->value = qmp_query_vnc_client(client);
362 cinfo->next = prev;
363 prev = cinfo;
364 }
365 return prev;
366}
367
2b54aa87 368VncInfo *qmp_query_vnc(Error **errp)
d96fd29c 369{
2b54aa87 370 VncInfo *info = g_malloc0(sizeof(*info));
d616ccc5 371 VncDisplay *vd = vnc_display_find(NULL);
04d2529d 372 SocketAddress *addr = NULL;
2b54aa87 373
12b28067 374 if (vd == NULL || !vd->lsock) {
2b54aa87 375 info->enabled = false;
d96fd29c 376 } else {
2b54aa87
LC
377 info->enabled = true;
378
379 /* for compatibility with the original command */
380 info->has_clients = true;
2d29a436 381 info->clients = qmp_query_client_list(vd);
d96fd29c 382
04d2529d 383 if (vd->lsock == NULL) {
417b0b88
PB
384 return info;
385 }
386
04d2529d
DB
387 addr = qio_channel_socket_get_local_address(vd->lsock, errp);
388 if (!addr) {
2b54aa87
LC
389 goto out_error;
390 }
d96fd29c 391
04d2529d
DB
392 switch (addr->type) {
393 case SOCKET_ADDRESS_KIND_INET:
32bafa8f
EB
394 info->host = g_strdup(addr->u.inet.data->host);
395 info->service = g_strdup(addr->u.inet.data->port);
396 if (addr->u.inet.data->ipv6) {
04d2529d
DB
397 info->family = NETWORK_ADDRESS_FAMILY_IPV6;
398 } else {
399 info->family = NETWORK_ADDRESS_FAMILY_IPV4;
400 }
401 break;
402
403 case SOCKET_ADDRESS_KIND_UNIX:
404 info->host = g_strdup("");
32bafa8f 405 info->service = g_strdup(addr->u.q_unix.data->path);
04d2529d
DB
406 info->family = NETWORK_ADDRESS_FAMILY_UNIX;
407 break;
408
409 default:
410 error_setg(errp, "Unsupported socket kind %d",
411 addr->type);
2b54aa87 412 goto out_error;
1ff7df1a 413 }
2b54aa87
LC
414
415 info->has_host = true;
2b54aa87 416 info->has_service = true;
2b54aa87 417 info->has_family = true;
2b54aa87
LC
418
419 info->has_auth = true;
d616ccc5 420 info->auth = g_strdup(vnc_auth_name(vd));
a9ce8590 421 }
2b54aa87 422
04d2529d 423 qapi_free_SocketAddress(addr);
2b54aa87
LC
424 return info;
425
426out_error:
04d2529d 427 qapi_free_SocketAddress(addr);
2b54aa87
LC
428 qapi_free_VncInfo(info);
429 return NULL;
a9ce8590
FB
430}
431
04d2529d 432static VncBasicInfoList *qmp_query_server_entry(QIOChannelSocket *ioc,
4478aa76 433 bool websocket,
df887684
GH
434 VncBasicInfoList *prev)
435{
436 VncBasicInfoList *list;
437 VncBasicInfo *info;
04d2529d
DB
438 Error *err = NULL;
439 SocketAddress *addr;
440
441 addr = qio_channel_socket_get_local_address(ioc, &err);
442 if (!addr) {
443 error_free(err);
df887684
GH
444 return prev;
445 }
446
447 info = g_new0(VncBasicInfo, 1);
04d2529d
DB
448 vnc_init_basic_info(addr, info, &err);
449 qapi_free_SocketAddress(addr);
450 if (err) {
451 qapi_free_VncBasicInfo(info);
452 error_free(err);
453 return prev;
454 }
4478aa76 455 info->websocket = websocket;
df887684
GH
456
457 list = g_new0(VncBasicInfoList, 1);
458 list->value = info;
459 list->next = prev;
460 return list;
461}
462
463static void qmp_query_auth(VncDisplay *vd, VncInfo2 *info)
464{
465 switch (vd->auth) {
466 case VNC_AUTH_VNC:
467 info->auth = VNC_PRIMARY_AUTH_VNC;
468 break;
469 case VNC_AUTH_RA2:
470 info->auth = VNC_PRIMARY_AUTH_RA2;
471 break;
472 case VNC_AUTH_RA2NE:
473 info->auth = VNC_PRIMARY_AUTH_RA2NE;
474 break;
475 case VNC_AUTH_TIGHT:
476 info->auth = VNC_PRIMARY_AUTH_TIGHT;
477 break;
478 case VNC_AUTH_ULTRA:
479 info->auth = VNC_PRIMARY_AUTH_ULTRA;
480 break;
481 case VNC_AUTH_TLS:
482 info->auth = VNC_PRIMARY_AUTH_TLS;
483 break;
484 case VNC_AUTH_VENCRYPT:
485 info->auth = VNC_PRIMARY_AUTH_VENCRYPT;
df887684
GH
486 info->has_vencrypt = true;
487 switch (vd->subauth) {
488 case VNC_AUTH_VENCRYPT_PLAIN:
489 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_PLAIN;
490 break;
491 case VNC_AUTH_VENCRYPT_TLSNONE:
492 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_NONE;
493 break;
494 case VNC_AUTH_VENCRYPT_TLSVNC:
495 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_VNC;
496 break;
497 case VNC_AUTH_VENCRYPT_TLSPLAIN:
498 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_PLAIN;
499 break;
500 case VNC_AUTH_VENCRYPT_X509NONE:
501 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_NONE;
502 break;
503 case VNC_AUTH_VENCRYPT_X509VNC:
504 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_VNC;
505 break;
506 case VNC_AUTH_VENCRYPT_X509PLAIN:
507 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_PLAIN;
508 break;
509 case VNC_AUTH_VENCRYPT_TLSSASL:
510 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_SASL;
511 break;
512 case VNC_AUTH_VENCRYPT_X509SASL:
513 info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_SASL;
514 break;
515 default:
516 info->has_vencrypt = false;
517 break;
518 }
df887684
GH
519 break;
520 case VNC_AUTH_SASL:
521 info->auth = VNC_PRIMARY_AUTH_SASL;
522 break;
523 case VNC_AUTH_NONE:
524 default:
525 info->auth = VNC_PRIMARY_AUTH_NONE;
526 break;
527 }
528}
529
530VncInfo2List *qmp_query_vnc_servers(Error **errp)
531{
532 VncInfo2List *item, *prev = NULL;
533 VncInfo2 *info;
534 VncDisplay *vd;
535 DeviceState *dev;
536
537 QTAILQ_FOREACH(vd, &vnc_displays, next) {
538 info = g_new0(VncInfo2, 1);
539 info->id = g_strdup(vd->id);
540 info->clients = qmp_query_client_list(vd);
541 qmp_query_auth(vd, info);
542 if (vd->dcl.con) {
543 dev = DEVICE(object_property_get_link(OBJECT(vd->dcl.con),
544 "device", NULL));
545 info->has_display = true;
546 info->display = g_strdup(dev->id);
547 }
04d2529d
DB
548 if (vd->lsock != NULL) {
549 info->server = qmp_query_server_entry(
550 vd->lsock, false, info->server);
df887684 551 }
04d2529d
DB
552 if (vd->lwebsock != NULL) {
553 info->server = qmp_query_server_entry(
554 vd->lwebsock, true, info->server);
df887684 555 }
df887684
GH
556
557 item = g_new0(VncInfo2List, 1);
558 item->value = info;
559 item->next = prev;
560 prev = item;
561 }
562 return prev;
563}
564
24236869
FB
565/* TODO
566 1) Get the queue working for IO.
567 2) there is some weirdness when using the -S option (the screen is grey
568 and not totally invalidated
569 3) resolutions > 1024
570*/
571
38ee14f4 572static int vnc_update_client(VncState *vs, int has_dirty, bool sync);
198a0039 573static void vnc_disconnect_start(VncState *vs);
24236869 574
753b4053 575static void vnc_colordepth(VncState *vs);
1fc62412
SS
576static void framebuffer_update_request(VncState *vs, int incremental,
577 int x_position, int y_position,
578 int w, int h);
0f7b2864 579static void vnc_refresh(DisplayChangeListener *dcl);
1fc62412 580static int vnc_refresh_server_surface(VncDisplay *vd);
7eac3a87 581
d05959c2
GH
582static int vnc_width(VncDisplay *vd)
583{
584 return MIN(VNC_MAX_WIDTH, ROUND_UP(surface_width(vd->ds),
585 VNC_DIRTY_PIXELS_PER_BIT));
586}
587
588static int vnc_height(VncDisplay *vd)
589{
590 return MIN(VNC_MAX_HEIGHT, surface_height(vd->ds));
591}
592
bea60dd7
PL
593static void vnc_set_area_dirty(DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT],
594 VNC_MAX_WIDTH / VNC_DIRTY_PIXELS_PER_BIT),
f7b3d68c
GH
595 VncDisplay *vd,
596 int x, int y, int w, int h)
597{
598 int width = vnc_width(vd);
599 int height = vnc_height(vd);
600
91937225
PL
601 /* this is needed this to ensure we updated all affected
602 * blocks if x % VNC_DIRTY_PIXELS_PER_BIT != 0 */
b4c85ddc
PL
603 w += (x % VNC_DIRTY_PIXELS_PER_BIT);
604 x -= (x % VNC_DIRTY_PIXELS_PER_BIT);
0486e8a7 605
9f64916d
GH
606 x = MIN(x, width);
607 y = MIN(y, height);
608 w = MIN(x + w, width) - x;
91937225 609 h = MIN(y + h, height);
788abf8e 610
b4c85ddc 611 for (; y < h; y++) {
bea60dd7 612 bitmap_set(dirty[y], x / VNC_DIRTY_PIXELS_PER_BIT,
91937225 613 DIV_ROUND_UP(w, VNC_DIRTY_PIXELS_PER_BIT));
b4c85ddc 614 }
24236869
FB
615}
616
bea60dd7
PL
617static void vnc_dpy_update(DisplayChangeListener *dcl,
618 int x, int y, int w, int h)
619{
620 VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
621 struct VncSurface *s = &vd->guest;
bea60dd7 622
f7b3d68c 623 vnc_set_area_dirty(s->dirty, vd, x, y, w, h);
bea60dd7
PL
624}
625
70a4568f
CC
626void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
627 int32_t encoding)
24236869
FB
628{
629 vnc_write_u16(vs, x);
630 vnc_write_u16(vs, y);
631 vnc_write_u16(vs, w);
632 vnc_write_u16(vs, h);
633
634 vnc_write_s32(vs, encoding);
635}
636
32ed2680 637
621aaeb9
GH
638static void vnc_desktop_resize(VncState *vs)
639{
04d2529d 640 if (vs->ioc == NULL || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
621aaeb9
GH
641 return;
642 }
bea60dd7
PL
643 if (vs->client_width == pixman_image_get_width(vs->vd->server) &&
644 vs->client_height == pixman_image_get_height(vs->vd->server)) {
1d4b638a
GH
645 return;
646 }
bea60dd7
PL
647 vs->client_width = pixman_image_get_width(vs->vd->server);
648 vs->client_height = pixman_image_get_height(vs->vd->server);
bd023f95 649 vnc_lock_output(vs);
621aaeb9
GH
650 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
651 vnc_write_u8(vs, 0);
652 vnc_write_u16(vs, 1); /* number of rects */
5862d195 653 vnc_framebuffer_update(vs, 0, 0, vs->client_width, vs->client_height,
621aaeb9 654 VNC_ENCODING_DESKTOPRESIZE);
bd023f95 655 vnc_unlock_output(vs);
621aaeb9
GH
656 vnc_flush(vs);
657}
658
bd023f95
CC
659static void vnc_abort_display_jobs(VncDisplay *vd)
660{
661 VncState *vs;
662
663 QTAILQ_FOREACH(vs, &vd->clients, next) {
664 vnc_lock_output(vs);
665 vs->abort = true;
666 vnc_unlock_output(vs);
667 }
668 QTAILQ_FOREACH(vs, &vd->clients, next) {
669 vnc_jobs_join(vs);
670 }
671 QTAILQ_FOREACH(vs, &vd->clients, next) {
672 vnc_lock_output(vs);
673 vs->abort = false;
674 vnc_unlock_output(vs);
675 }
676}
bd023f95 677
9f64916d
GH
678int vnc_server_fb_stride(VncDisplay *vd)
679{
680 return pixman_image_get_stride(vd->server);
681}
682
683void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
684{
685 uint8_t *ptr;
686
687 ptr = (uint8_t *)pixman_image_get_data(vd->server);
688 ptr += y * vnc_server_fb_stride(vd);
689 ptr += x * VNC_SERVER_FB_BYTES;
690 return ptr;
691}
692
453f842b
GH
693static void vnc_update_server_surface(VncDisplay *vd)
694{
b69a553b
DB
695 int width, height;
696
453f842b
GH
697 qemu_pixman_image_unref(vd->server);
698 vd->server = NULL;
699
c7628bff
GH
700 if (QTAILQ_EMPTY(&vd->clients)) {
701 return;
702 }
703
b69a553b
DB
704 width = vnc_width(vd);
705 height = vnc_height(vd);
453f842b 706 vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
b69a553b 707 width, height,
453f842b 708 NULL, 0);
b69a553b
DB
709
710 memset(vd->guest.dirty, 0x00, sizeof(vd->guest.dirty));
711 vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0,
712 width, height);
453f842b
GH
713}
714
c12aeb86 715static void vnc_dpy_switch(DisplayChangeListener *dcl,
c12aeb86 716 DisplaySurface *surface)
24236869 717{
21ef45d7 718 VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
41b4bef6 719 VncState *vs;
1fc62412 720
bd023f95 721 vnc_abort_display_jobs(vd);
453f842b 722 vd->ds = surface;
bd023f95 723
1fc62412 724 /* server surface */
453f842b 725 vnc_update_server_surface(vd);
24236869 726
6baebed7 727 /* guest surface */
9f64916d 728 qemu_pixman_image_unref(vd->guest.fb);
d39fa6d8
GH
729 vd->guest.fb = pixman_image_ref(surface->image);
730 vd->guest.format = surface->format;
24236869 731
41b4bef6 732 QTAILQ_FOREACH(vs, &vd->clients, next) {
1fc62412 733 vnc_colordepth(vs);
1d4b638a 734 vnc_desktop_resize(vs);
d467b679
GH
735 if (vs->vd->cursor) {
736 vnc_cursor_define(vs);
737 }
bea60dd7 738 memset(vs->dirty, 0x00, sizeof(vs->dirty));
f7b3d68c 739 vnc_set_area_dirty(vs->dirty, vd, 0, 0,
b69a553b
DB
740 vnc_width(vd),
741 vnc_height(vd));
753b4053
AL
742 }
743}
744
3512779a 745/* fastest code */
9f64916d 746static void vnc_write_pixels_copy(VncState *vs,
d467b679 747 void *pixels, int size)
3512779a
FB
748{
749 vnc_write(vs, pixels, size);
750}
751
752/* slowest but generic code. */
70a4568f 753void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
3512779a 754{
7eac3a87 755 uint8_t r, g, b;
1fc62412 756
9f64916d
GH
757#if VNC_SERVER_FB_FORMAT == PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8)
758 r = (((v & 0x00ff0000) >> 16) << vs->client_pf.rbits) >> 8;
759 g = (((v & 0x0000ff00) >> 8) << vs->client_pf.gbits) >> 8;
760 b = (((v & 0x000000ff) >> 0) << vs->client_pf.bbits) >> 8;
761#else
762# error need some bits here if you change VNC_SERVER_FB_FORMAT
763#endif
764 v = (r << vs->client_pf.rshift) |
765 (g << vs->client_pf.gshift) |
766 (b << vs->client_pf.bshift);
767 switch (vs->client_pf.bytes_per_pixel) {
3512779a
FB
768 case 1:
769 buf[0] = v;
770 break;
771 case 2:
9f64916d 772 if (vs->client_be) {
3512779a
FB
773 buf[0] = v >> 8;
774 buf[1] = v;
775 } else {
776 buf[1] = v >> 8;
777 buf[0] = v;
778 }
779 break;
780 default:
781 case 4:
9f64916d 782 if (vs->client_be) {
3512779a
FB
783 buf[0] = v >> 24;
784 buf[1] = v >> 16;
785 buf[2] = v >> 8;
786 buf[3] = v;
787 } else {
788 buf[3] = v >> 24;
789 buf[2] = v >> 16;
790 buf[1] = v >> 8;
791 buf[0] = v;
792 }
793 break;
794 }
795}
796
9f64916d 797static void vnc_write_pixels_generic(VncState *vs,
d467b679 798 void *pixels1, int size)
3512779a 799{
3512779a 800 uint8_t buf[4];
3512779a 801
9f64916d 802 if (VNC_SERVER_FB_BYTES == 4) {
7eac3a87
AL
803 uint32_t *pixels = pixels1;
804 int n, i;
805 n = size >> 2;
9f64916d 806 for (i = 0; i < n; i++) {
7eac3a87 807 vnc_convert_pixel(vs, buf, pixels[i]);
9f64916d 808 vnc_write(vs, buf, vs->client_pf.bytes_per_pixel);
7eac3a87 809 }
3512779a
FB
810 }
811}
812
a885211e 813int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
24236869
FB
814{
815 int i;
60fe76f3 816 uint8_t *row;
1fc62412 817 VncDisplay *vd = vs->vd;
24236869 818
9f64916d 819 row = vnc_server_fb_ptr(vd, x, y);
24236869 820 for (i = 0; i < h; i++) {
9f64916d
GH
821 vs->write_pixels(vs, row, w * VNC_SERVER_FB_BYTES);
822 row += vnc_server_fb_stride(vd);
24236869 823 }
a885211e 824 return 1;
24236869
FB
825}
826
bd023f95 827int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
24236869 828{
a885211e 829 int n = 0;
de3f7de7
PL
830 bool encode_raw = false;
831 size_t saved_offs = vs->output.offset;
a885211e 832
fb437313 833 switch(vs->vnc_encoding) {
28a76be8 834 case VNC_ENCODING_ZLIB:
a885211e 835 n = vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
28a76be8
AL
836 break;
837 case VNC_ENCODING_HEXTILE:
838 vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
a885211e 839 n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
28a76be8 840 break;
380282b0
CC
841 case VNC_ENCODING_TIGHT:
842 n = vnc_tight_send_framebuffer_update(vs, x, y, w, h);
843 break;
efe556ad
CC
844 case VNC_ENCODING_TIGHT_PNG:
845 n = vnc_tight_png_send_framebuffer_update(vs, x, y, w, h);
846 break;
148954fa
CC
847 case VNC_ENCODING_ZRLE:
848 n = vnc_zrle_send_framebuffer_update(vs, x, y, w, h);
849 break;
850 case VNC_ENCODING_ZYWRLE:
851 n = vnc_zywrle_send_framebuffer_update(vs, x, y, w, h);
852 break;
28a76be8 853 default:
de3f7de7 854 encode_raw = true;
28a76be8 855 break;
fb437313 856 }
de3f7de7
PL
857
858 /* If the client has the same pixel format as our internal buffer and
859 * a RAW encoding would need less space fall back to RAW encoding to
860 * save bandwidth and processing power in the client. */
861 if (!encode_raw && vs->write_pixels == vnc_write_pixels_copy &&
862 12 + h * w * VNC_SERVER_FB_BYTES <= (vs->output.offset - saved_offs)) {
863 vs->output.offset = saved_offs;
864 encode_raw = true;
865 }
866
867 if (encode_raw) {
868 vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
869 n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
870 }
871
a885211e 872 return n;
24236869
FB
873}
874
753b4053 875static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
24236869 876{
3e28c9ad 877 /* send bitblit op to the vnc client */
bd023f95 878 vnc_lock_output(vs);
46a183da 879 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
24236869
FB
880 vnc_write_u8(vs, 0);
881 vnc_write_u16(vs, 1); /* number of rects */
29fa4ed9 882 vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
24236869
FB
883 vnc_write_u16(vs, src_x);
884 vnc_write_u16(vs, src_y);
bd023f95 885 vnc_unlock_output(vs);
24236869
FB
886 vnc_flush(vs);
887}
888
7c20b4a3 889static void vnc_dpy_copy(DisplayChangeListener *dcl,
7c20b4a3
GH
890 int src_x, int src_y,
891 int dst_x, int dst_y, int w, int h)
753b4053 892{
21ef45d7 893 VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
198a0039 894 VncState *vs, *vn;
1fc62412
SS
895 uint8_t *src_row;
896 uint8_t *dst_row;
9f64916d 897 int i, x, y, pitch, inc, w_lim, s;
1fc62412 898 int cmp_bytes;
198a0039 899
7fe4a41c
GH
900 if (!vd->server) {
901 /* no client connected */
902 return;
903 }
904
1fc62412 905 vnc_refresh_server_surface(vd);
41b4bef6 906 QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
198a0039
GH
907 if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
908 vs->force_update = 1;
38ee14f4 909 vnc_update_client(vs, 1, true);
198a0039
GH
910 /* vs might be free()ed here */
911 }
912 }
913
3e10c3ec
GA
914 if (!vd->server) {
915 /* no client connected */
916 return;
917 }
1fc62412 918 /* do bitblit op on the local surface too */
9f64916d
GH
919 pitch = vnc_server_fb_stride(vd);
920 src_row = vnc_server_fb_ptr(vd, src_x, src_y);
921 dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
1fc62412
SS
922 y = dst_y;
923 inc = 1;
924 if (dst_y > src_y) {
925 /* copy backwards */
926 src_row += pitch * (h-1);
927 dst_row += pitch * (h-1);
928 pitch = -pitch;
929 y = dst_y + h - 1;
930 inc = -1;
931 }
b4c85ddc
PL
932 w_lim = w - (VNC_DIRTY_PIXELS_PER_BIT - (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
933 if (w_lim < 0) {
1fc62412 934 w_lim = w;
b4c85ddc
PL
935 } else {
936 w_lim = w - (w_lim % VNC_DIRTY_PIXELS_PER_BIT);
937 }
1fc62412
SS
938 for (i = 0; i < h; i++) {
939 for (x = 0; x <= w_lim;
940 x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
941 if (x == w_lim) {
942 if ((s = w - w_lim) == 0)
943 break;
944 } else if (!x) {
b4c85ddc
PL
945 s = (VNC_DIRTY_PIXELS_PER_BIT -
946 (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
1fc62412
SS
947 s = MIN(s, w_lim);
948 } else {
b4c85ddc 949 s = VNC_DIRTY_PIXELS_PER_BIT;
1fc62412 950 }
9f64916d 951 cmp_bytes = s * VNC_SERVER_FB_BYTES;
1fc62412
SS
952 if (memcmp(src_row, dst_row, cmp_bytes) == 0)
953 continue;
954 memmove(dst_row, src_row, cmp_bytes);
41b4bef6
AS
955 QTAILQ_FOREACH(vs, &vd->clients, next) {
956 if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
b4c85ddc
PL
957 set_bit(((x + dst_x) / VNC_DIRTY_PIXELS_PER_BIT),
958 vs->dirty[y]);
41b4bef6 959 }
1fc62412
SS
960 }
961 }
9f64916d
GH
962 src_row += pitch - w * VNC_SERVER_FB_BYTES;
963 dst_row += pitch - w * VNC_SERVER_FB_BYTES;
1fc62412
SS
964 y += inc;
965 }
966
41b4bef6
AS
967 QTAILQ_FOREACH(vs, &vd->clients, next) {
968 if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
753b4053 969 vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
41b4bef6 970 }
753b4053
AL
971 }
972}
973
7c20b4a3 974static void vnc_mouse_set(DisplayChangeListener *dcl,
7c20b4a3 975 int x, int y, int visible)
d467b679
GH
976{
977 /* can we ask the client(s) to move the pointer ??? */
978}
979
980static int vnc_cursor_define(VncState *vs)
981{
982 QEMUCursor *c = vs->vd->cursor;
d467b679
GH
983 int isize;
984
985 if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) {
d01f9595 986 vnc_lock_output(vs);
d467b679
GH
987 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
988 vnc_write_u8(vs, 0); /* padding */
989 vnc_write_u16(vs, 1); /* # of rects */
990 vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
991 VNC_ENCODING_RICH_CURSOR);
9f64916d
GH
992 isize = c->width * c->height * vs->client_pf.bytes_per_pixel;
993 vnc_write_pixels_generic(vs, c->data, isize);
d467b679 994 vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
d01f9595 995 vnc_unlock_output(vs);
d467b679
GH
996 return 0;
997 }
998 return -1;
999}
1000
7c20b4a3 1001static void vnc_dpy_cursor_define(DisplayChangeListener *dcl,
7c20b4a3 1002 QEMUCursor *c)
d467b679 1003{
d616ccc5 1004 VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
d467b679
GH
1005 VncState *vs;
1006
1007 cursor_put(vd->cursor);
7267c094 1008 g_free(vd->cursor_mask);
d467b679
GH
1009
1010 vd->cursor = c;
1011 cursor_get(vd->cursor);
1012 vd->cursor_msize = cursor_get_mono_bpl(c) * c->height;
7267c094 1013 vd->cursor_mask = g_malloc0(vd->cursor_msize);
d467b679
GH
1014 cursor_get_mono_mask(c, 0, vd->cursor_mask);
1015
1016 QTAILQ_FOREACH(vs, &vd->clients, next) {
1017 vnc_cursor_define(vs);
1018 }
1019}
1020
4769a881 1021static int find_and_clear_dirty_height(VncState *vs,
6c71a539 1022 int y, int last_x, int x, int height)
24236869
FB
1023{
1024 int h;
1025
6c71a539 1026 for (h = 1; h < (height - y); h++) {
bc2429b9 1027 if (!test_bit(last_x, vs->dirty[y + h])) {
28a76be8 1028 break;
bc2429b9 1029 }
863d7c91 1030 bitmap_clear(vs->dirty[y + h], last_x, x - last_x);
24236869
FB
1031 }
1032
1033 return h;
1034}
1035
38ee14f4 1036static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
24236869 1037{
5a8be0f7
GH
1038 if (vs->disconnecting) {
1039 vnc_disconnect_finish(vs);
1040 return 0;
1041 }
1042
63658280 1043 vs->has_dirty += has_dirty;
5a693efd 1044 if (vs->need_update && !vs->disconnecting) {
1fc62412 1045 VncDisplay *vd = vs->vd;
bd023f95 1046 VncJob *job;
28a76be8 1047 int y;
2f487a3d 1048 int height, width;
bd023f95
CC
1049 int n = 0;
1050
703bc68f 1051 if (vs->output.offset && !vs->audio_cap && !vs->force_update)
c522d0e2 1052 /* kernel send buffers are full -> drop frames to throttle */
2430ffe4 1053 return 0;
a0ecfb73 1054
63658280 1055 if (!vs->has_dirty && !vs->audio_cap && !vs->force_update)
2430ffe4 1056 return 0;
28a76be8 1057
6baebed7
AL
1058 /*
1059 * Send screen updates to the vnc client using the server
1060 * surface and server dirty map. guest surface updates
1061 * happening in parallel don't disturb us, the next pass will
1062 * send them to the client.
1063 */
bd023f95 1064 job = vnc_job_new(vs);
28a76be8 1065
bea60dd7
PL
1066 height = pixman_image_get_height(vd->server);
1067 width = pixman_image_get_width(vd->server);
847ce6a1 1068
12b316d4
PL
1069 y = 0;
1070 for (;;) {
1071 int x, h;
1072 unsigned long x2;
1073 unsigned long offset = find_next_bit((unsigned long *) &vs->dirty,
1074 height * VNC_DIRTY_BPL(vs),
1075 y * VNC_DIRTY_BPL(vs));
1076 if (offset == height * VNC_DIRTY_BPL(vs)) {
1077 /* no more dirty bits */
1078 break;
28a76be8 1079 }
12b316d4
PL
1080 y = offset / VNC_DIRTY_BPL(vs);
1081 x = offset % VNC_DIRTY_BPL(vs);
1082 x2 = find_next_zero_bit((unsigned long *) &vs->dirty[y],
1083 VNC_DIRTY_BPL(vs), x);
1084 bitmap_clear(vs->dirty[y], x, x2 - x);
1085 h = find_and_clear_dirty_height(vs, y, x, x2, height);
2f487a3d
PL
1086 x2 = MIN(x2, width / VNC_DIRTY_PIXELS_PER_BIT);
1087 if (x2 > x) {
1088 n += vnc_job_add_rect(job, x * VNC_DIRTY_PIXELS_PER_BIT, y,
1089 (x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h);
1090 }
0e7d6f60
PL
1091 if (!x && x2 == width / VNC_DIRTY_PIXELS_PER_BIT) {
1092 y += h;
1093 if (y == height) {
1094 break;
1095 }
1096 }
28a76be8 1097 }
bd023f95
CC
1098
1099 vnc_job_push(job);
eb214ff8
GH
1100 if (sync) {
1101 vnc_jobs_join(vs);
1102 }
c522d0e2 1103 vs->force_update = 0;
63658280 1104 vs->has_dirty = 0;
bd023f95 1105 return n;
24236869 1106 }
24236869 1107
04d2529d 1108 if (vs->disconnecting) {
198a0039 1109 vnc_disconnect_finish(vs);
38ee14f4
GH
1110 } else if (sync) {
1111 vnc_jobs_join(vs);
1112 }
2430ffe4
SS
1113
1114 return 0;
24236869
FB
1115}
1116
429a8ed3 1117/* audio */
1118static void audio_capture_notify(void *opaque, audcnotification_e cmd)
1119{
1120 VncState *vs = opaque;
1121
1122 switch (cmd) {
1123 case AUD_CNOTIFY_DISABLE:
bd023f95 1124 vnc_lock_output(vs);
46a183da
DB
1125 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
1126 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
1127 vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_END);
bd023f95 1128 vnc_unlock_output(vs);
429a8ed3 1129 vnc_flush(vs);
1130 break;
1131
1132 case AUD_CNOTIFY_ENABLE:
bd023f95 1133 vnc_lock_output(vs);
46a183da
DB
1134 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
1135 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
1136 vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_BEGIN);
bd023f95 1137 vnc_unlock_output(vs);
429a8ed3 1138 vnc_flush(vs);
1139 break;
1140 }
1141}
1142
1143static void audio_capture_destroy(void *opaque)
1144{
1145}
1146
1147static void audio_capture(void *opaque, void *buf, int size)
1148{
1149 VncState *vs = opaque;
1150
bd023f95 1151 vnc_lock_output(vs);
46a183da
DB
1152 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
1153 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
1154 vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA);
429a8ed3 1155 vnc_write_u32(vs, size);
1156 vnc_write(vs, buf, size);
bd023f95 1157 vnc_unlock_output(vs);
429a8ed3 1158 vnc_flush(vs);
1159}
1160
1161static void audio_add(VncState *vs)
1162{
1163 struct audio_capture_ops ops;
1164
1165 if (vs->audio_cap) {
027a79c3 1166 error_report("audio already running");
429a8ed3 1167 return;
1168 }
1169
1170 ops.notify = audio_capture_notify;
1171 ops.destroy = audio_capture_destroy;
1172 ops.capture = audio_capture;
1173
1a7dafce 1174 vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
429a8ed3 1175 if (!vs->audio_cap) {
027a79c3 1176 error_report("Failed to add audio capture");
429a8ed3 1177 }
1178}
1179
1180static void audio_del(VncState *vs)
1181{
1182 if (vs->audio_cap) {
1183 AUD_del_capture(vs->audio_cap, vs);
1184 vs->audio_cap = NULL;
1185 }
1186}
1187
198a0039
GH
1188static void vnc_disconnect_start(VncState *vs)
1189{
04d2529d 1190 if (vs->disconnecting) {
198a0039 1191 return;
04d2529d 1192 }
8cf36489 1193 vnc_set_share_mode(vs, VNC_SHARE_MODE_DISCONNECTED);
04d2529d
DB
1194 if (vs->ioc_tag) {
1195 g_source_remove(vs->ioc_tag);
1196 }
1197 qio_channel_close(vs->ioc, NULL);
1198 vs->disconnecting = TRUE;
198a0039
GH
1199}
1200
7536ee4b 1201void vnc_disconnect_finish(VncState *vs)
198a0039 1202{
7d964c9d
CC
1203 int i;
1204
bd023f95
CC
1205 vnc_jobs_join(vs); /* Wait encoding jobs */
1206
1207 vnc_lock_output(vs);
fb6ba0d5 1208 vnc_qmp_event(vs, QAPI_EVENT_VNC_DISCONNECTED);
0d72f3d3 1209
5d418e3b
CC
1210 buffer_free(&vs->input);
1211 buffer_free(&vs->output);
4a80dba3 1212
fb6ba0d5 1213 qapi_free_VncClientInfo(vs->info);
4a80dba3 1214
161c4f20 1215 vnc_zlib_clear(vs);
380282b0 1216 vnc_tight_clear(vs);
148954fa 1217 vnc_zrle_clear(vs);
161c4f20 1218
198a0039
GH
1219#ifdef CONFIG_VNC_SASL
1220 vnc_sasl_client_cleanup(vs);
1221#endif /* CONFIG_VNC_SASL */
1222 audio_del(vs);
7bc9318b 1223 vnc_release_modifiers(vs);
198a0039 1224
90cd03a3 1225 if (vs->mouse_mode_notifier.notify != NULL) {
6fd8e79a 1226 qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
90cd03a3
DB
1227 }
1228 QTAILQ_REMOVE(&vs->vd->clients, vs, next);
1229 if (QTAILQ_EMPTY(&vs->vd->clients)) {
1230 /* last client gone */
1231 vnc_update_server_surface(vs->vd);
6fd8e79a 1232 }
41b4bef6 1233
bd023f95
CC
1234 vnc_unlock_output(vs);
1235
bd023f95 1236 qemu_mutex_destroy(&vs->output_mutex);
6fd8e79a
TH
1237 if (vs->bh != NULL) {
1238 qemu_bh_delete(vs->bh);
1239 }
175b2a6e 1240 buffer_free(&vs->jobs_buffer);
175b2a6e 1241
7d964c9d 1242 for (i = 0; i < VNC_STAT_ROWS; ++i) {
7267c094 1243 g_free(vs->lossy_rect[i]);
7d964c9d 1244 }
7267c094 1245 g_free(vs->lossy_rect);
04d2529d
DB
1246
1247 object_unref(OBJECT(vs->ioc));
1248 vs->ioc = NULL;
1249 object_unref(OBJECT(vs->sioc));
1250 vs->sioc = NULL;
7267c094 1251 g_free(vs);
198a0039 1252}
2f9606b3 1253
04d2529d 1254ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp)
24236869 1255{
04d2529d
DB
1256 if (ret <= 0) {
1257 if (ret == 0) {
1258 VNC_DEBUG("Closing down client sock: EOF\n");
1259 } else if (ret != QIO_CHANNEL_ERR_BLOCK) {
6b557d7c 1260 VNC_DEBUG("Closing down client sock: ret %zd (%s)\n",
04d2529d 1261 ret, errp ? error_get_pretty(*errp) : "Unknown");
ea01e5fd 1262 }
24236869 1263
198a0039 1264 vnc_disconnect_start(vs);
04d2529d
DB
1265 if (errp) {
1266 error_free(*errp);
1267 *errp = NULL;
1268 }
28a76be8 1269 return 0;
24236869
FB
1270 }
1271 return ret;
1272}
1273
5fb6c7a8
AL
1274
1275void vnc_client_error(VncState *vs)
24236869 1276{
198a0039
GH
1277 VNC_DEBUG("Closing down client sock: protocol error\n");
1278 vnc_disconnect_start(vs);
24236869
FB
1279}
1280
3e305e4a 1281
2f9606b3
AL
1282/*
1283 * Called to write a chunk of data to the client socket. The data may
1284 * be the raw data, or may have already been encoded by SASL.
1285 * The data will be written either straight onto the socket, or
1286 * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1287 *
1288 * NB, it is theoretically possible to have 2 layers of encryption,
1289 * both SASL, and this TLS layer. It is highly unlikely in practice
1290 * though, since SASL encryption will typically be a no-op if TLS
1291 * is active
1292 *
1293 * Returns the number of bytes written, which may be less than
1294 * the requested 'datalen' if the socket would block. Returns
1295 * -1 on error, and disconnects the client socket.
1296 */
fdd1ab6a 1297ssize_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
24236869 1298{
04d2529d 1299 Error *err = NULL;
fdd1ab6a 1300 ssize_t ret;
2cc45228
DB
1301 ret = qio_channel_write(
1302 vs->ioc, (const char *)data, datalen, &err);
23decc87 1303 VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret);
04d2529d 1304 return vnc_client_io_error(vs, ret, &err);
2f9606b3
AL
1305}
1306
1307
1308/*
1309 * Called to write buffered data to the client socket, when not
1310 * using any SASL SSF encryption layers. Will write as much data
1311 * as possible without blocking. If all buffered data is written,
1312 * will switch the FD poll() handler back to read monitoring.
1313 *
1314 * Returns the number of bytes written, which may be less than
1315 * the buffered output data if the socket would block. Returns
1316 * -1 on error, and disconnects the client socket.
1317 */
fdd1ab6a 1318static ssize_t vnc_client_write_plain(VncState *vs)
2f9606b3 1319{
fdd1ab6a 1320 ssize_t ret;
2f9606b3
AL
1321
1322#ifdef CONFIG_VNC_SASL
23decc87 1323 VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n",
2f9606b3
AL
1324 vs->output.buffer, vs->output.capacity, vs->output.offset,
1325 vs->sasl.waitWriteSSF);
1326
1327 if (vs->sasl.conn &&
1328 vs->sasl.runSSF &&
1329 vs->sasl.waitWriteSSF) {
1330 ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF);
1331 if (ret)
1332 vs->sasl.waitWriteSSF -= ret;
1333 } else
1334#endif /* CONFIG_VNC_SASL */
1335 ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset);
24236869 1336 if (!ret)
2f9606b3 1337 return 0;
24236869 1338
32ed2680 1339 buffer_advance(&vs->output, ret);
24236869
FB
1340
1341 if (vs->output.offset == 0) {
04d2529d
DB
1342 if (vs->ioc_tag) {
1343 g_source_remove(vs->ioc_tag);
1344 }
1345 vs->ioc_tag = qio_channel_add_watch(
1346 vs->ioc, G_IO_IN, vnc_client_io, vs, NULL);
24236869 1347 }
2f9606b3
AL
1348
1349 return ret;
1350}
1351
1352
1353/*
1354 * First function called whenever there is data to be written to
1355 * the client socket. Will delegate actual work according to whether
1356 * SASL SSF layers are enabled (thus requiring encryption calls)
1357 */
04d2529d 1358static void vnc_client_write_locked(VncState *vs)
2f9606b3 1359{
2f9606b3
AL
1360#ifdef CONFIG_VNC_SASL
1361 if (vs->sasl.conn &&
1362 vs->sasl.runSSF &&
9678d950
BS
1363 !vs->sasl.waitWriteSSF) {
1364 vnc_client_write_sasl(vs);
1365 } else
2f9606b3 1366#endif /* CONFIG_VNC_SASL */
7536ee4b 1367 {
d5f04223 1368 vnc_client_write_plain(vs);
7536ee4b 1369 }
24236869
FB
1370}
1371
04d2529d 1372static void vnc_client_write(VncState *vs)
bd023f95 1373{
bd023f95
CC
1374
1375 vnc_lock_output(vs);
d5f04223 1376 if (vs->output.offset) {
04d2529d
DB
1377 vnc_client_write_locked(vs);
1378 } else if (vs->ioc != NULL) {
1379 if (vs->ioc_tag) {
1380 g_source_remove(vs->ioc_tag);
1381 }
1382 vs->ioc_tag = qio_channel_add_watch(
1383 vs->ioc, G_IO_IN, vnc_client_io, vs, NULL);
bd023f95
CC
1384 }
1385 vnc_unlock_output(vs);
1386}
1387
5fb6c7a8 1388void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
24236869
FB
1389{
1390 vs->read_handler = func;
1391 vs->read_handler_expect = expecting;
1392}
1393
2f9606b3
AL
1394
1395/*
1396 * Called to read a chunk of data from the client socket. The data may
1397 * be the raw data, or may need to be further decoded by SASL.
1398 * The data will be read either straight from to the socket, or
1399 * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1400 *
1401 * NB, it is theoretically possible to have 2 layers of encryption,
1402 * both SASL, and this TLS layer. It is highly unlikely in practice
1403 * though, since SASL encryption will typically be a no-op if TLS
1404 * is active
1405 *
1406 * Returns the number of bytes read, which may be less than
1407 * the requested 'datalen' if the socket would block. Returns
1408 * -1 on error, and disconnects the client socket.
1409 */
fdd1ab6a 1410ssize_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
24236869 1411{
fdd1ab6a 1412 ssize_t ret;
04d2529d 1413 Error *err = NULL;
2cc45228
DB
1414 ret = qio_channel_read(
1415 vs->ioc, (char *)data, datalen, &err);
23decc87 1416 VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret);
04d2529d 1417 return vnc_client_io_error(vs, ret, &err);
2f9606b3 1418}
24236869 1419
2f9606b3
AL
1420
1421/*
1422 * Called to read data from the client socket to the input buffer,
1423 * when not using any SASL SSF encryption layers. Will read as much
1424 * data as possible without blocking.
1425 *
1426 * Returns the number of bytes read. Returns -1 on error, and
1427 * disconnects the client socket.
1428 */
fdd1ab6a 1429static ssize_t vnc_client_read_plain(VncState *vs)
2f9606b3 1430{
fdd1ab6a 1431 ssize_t ret;
23decc87 1432 VNC_DEBUG("Read plain %p size %zd offset %zd\n",
2f9606b3
AL
1433 vs->input.buffer, vs->input.capacity, vs->input.offset);
1434 buffer_reserve(&vs->input, 4096);
1435 ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096);
1436 if (!ret)
1437 return 0;
24236869 1438 vs->input.offset += ret;
2f9606b3
AL
1439 return ret;
1440}
1441
175b2a6e
CC
1442static void vnc_jobs_bh(void *opaque)
1443{
1444 VncState *vs = opaque;
1445
1446 vnc_jobs_consume_buffer(vs);
1447}
2f9606b3
AL
1448
1449/*
1450 * First function called whenever there is more data to be read from
1451 * the client socket. Will delegate actual work according to whether
1452 * SASL SSF layers are enabled (thus requiring decryption calls)
ea697449 1453 * Returns 0 on success, -1 if client disconnected
2f9606b3 1454 */
ea697449 1455static int vnc_client_read(VncState *vs)
2f9606b3 1456{
fdd1ab6a 1457 ssize_t ret;
2f9606b3
AL
1458
1459#ifdef CONFIG_VNC_SASL
1460 if (vs->sasl.conn && vs->sasl.runSSF)
1461 ret = vnc_client_read_sasl(vs);
1462 else
1463#endif /* CONFIG_VNC_SASL */
d5f04223 1464 ret = vnc_client_read_plain(vs);
198a0039 1465 if (!ret) {
04d2529d 1466 if (vs->disconnecting) {
198a0039 1467 vnc_disconnect_finish(vs);
ea697449 1468 return -1;
04d2529d 1469 }
ea697449 1470 return 0;
198a0039 1471 }
24236869
FB
1472
1473 while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
28a76be8
AL
1474 size_t len = vs->read_handler_expect;
1475 int ret;
1476
1477 ret = vs->read_handler(vs, vs->input.buffer, len);
04d2529d 1478 if (vs->disconnecting) {
198a0039 1479 vnc_disconnect_finish(vs);
ea697449 1480 return -1;
198a0039 1481 }
28a76be8
AL
1482
1483 if (!ret) {
32ed2680 1484 buffer_advance(&vs->input, len);
28a76be8
AL
1485 } else {
1486 vs->read_handler_expect = ret;
1487 }
24236869 1488 }
ea697449 1489 return 0;
24236869
FB
1490}
1491
04d2529d
DB
1492gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED,
1493 GIOCondition condition, void *opaque)
1494{
1495 VncState *vs = opaque;
1496 if (condition & G_IO_IN) {
ea697449
DB
1497 if (vnc_client_read(vs) < 0) {
1498 return TRUE;
1499 }
04d2529d
DB
1500 }
1501 if (condition & G_IO_OUT) {
1502 vnc_client_write(vs);
1503 }
1504 return TRUE;
1505}
1506
1507
5fb6c7a8 1508void vnc_write(VncState *vs, const void *data, size_t len)
24236869
FB
1509{
1510 buffer_reserve(&vs->output, len);
1511
04d2529d
DB
1512 if (vs->ioc != NULL && buffer_empty(&vs->output)) {
1513 if (vs->ioc_tag) {
1514 g_source_remove(vs->ioc_tag);
1515 }
1516 vs->ioc_tag = qio_channel_add_watch(
1517 vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL);
24236869
FB
1518 }
1519
1520 buffer_append(&vs->output, data, len);
1521}
1522
5fb6c7a8 1523void vnc_write_s32(VncState *vs, int32_t value)
24236869
FB
1524{
1525 vnc_write_u32(vs, *(uint32_t *)&value);
1526}
1527
5fb6c7a8 1528void vnc_write_u32(VncState *vs, uint32_t value)
24236869
FB
1529{
1530 uint8_t buf[4];
1531
1532 buf[0] = (value >> 24) & 0xFF;
1533 buf[1] = (value >> 16) & 0xFF;
1534 buf[2] = (value >> 8) & 0xFF;
1535 buf[3] = value & 0xFF;
1536
1537 vnc_write(vs, buf, 4);
1538}
1539
5fb6c7a8 1540void vnc_write_u16(VncState *vs, uint16_t value)
24236869 1541{
64f5a135 1542 uint8_t buf[2];
24236869
FB
1543
1544 buf[0] = (value >> 8) & 0xFF;
1545 buf[1] = value & 0xFF;
1546
1547 vnc_write(vs, buf, 2);
1548}
1549
5fb6c7a8 1550void vnc_write_u8(VncState *vs, uint8_t value)
24236869
FB
1551{
1552 vnc_write(vs, (char *)&value, 1);
1553}
1554
5fb6c7a8 1555void vnc_flush(VncState *vs)
24236869 1556{
bd023f95 1557 vnc_lock_output(vs);
d5f04223 1558 if (vs->ioc != NULL && vs->output.offset) {
bd023f95
CC
1559 vnc_client_write_locked(vs);
1560 }
1561 vnc_unlock_output(vs);
24236869
FB
1562}
1563
71a8cdec 1564static uint8_t read_u8(uint8_t *data, size_t offset)
24236869
FB
1565{
1566 return data[offset];
1567}
1568
71a8cdec 1569static uint16_t read_u16(uint8_t *data, size_t offset)
24236869
FB
1570{
1571 return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
1572}
1573
71a8cdec 1574static int32_t read_s32(uint8_t *data, size_t offset)
24236869
FB
1575{
1576 return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
28a76be8 1577 (data[offset + 2] << 8) | data[offset + 3]);
24236869
FB
1578}
1579
5fb6c7a8 1580uint32_t read_u32(uint8_t *data, size_t offset)
24236869
FB
1581{
1582 return ((data[offset] << 24) | (data[offset + 1] << 16) |
28a76be8 1583 (data[offset + 2] << 8) | data[offset + 3]);
24236869
FB
1584}
1585
60fe76f3 1586static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
24236869
FB
1587{
1588}
1589
9e8dd451 1590static void check_pointer_type_change(Notifier *notifier, void *data)
564c337e 1591{
37c34d9d 1592 VncState *vs = container_of(notifier, VncState, mouse_mode_notifier);
14768eba 1593 int absolute = qemu_input_is_absolute();
37c34d9d 1594
29fa4ed9 1595 if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) {
bd023f95 1596 vnc_lock_output(vs);
46a183da 1597 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
28a76be8
AL
1598 vnc_write_u8(vs, 0);
1599 vnc_write_u16(vs, 1);
1600 vnc_framebuffer_update(vs, absolute, 0,
bea60dd7
PL
1601 pixman_image_get_width(vs->vd->server),
1602 pixman_image_get_height(vs->vd->server),
29fa4ed9 1603 VNC_ENCODING_POINTER_TYPE_CHANGE);
bd023f95 1604 vnc_unlock_output(vs);
28a76be8 1605 vnc_flush(vs);
564c337e
FB
1606 }
1607 vs->absolute = absolute;
1608}
1609
24236869
FB
1610static void pointer_event(VncState *vs, int button_mask, int x, int y)
1611{
7fb1cf16 1612 static uint32_t bmap[INPUT_BUTTON__MAX] = {
14768eba
GH
1613 [INPUT_BUTTON_LEFT] = 0x01,
1614 [INPUT_BUTTON_MIDDLE] = 0x02,
1615 [INPUT_BUTTON_RIGHT] = 0x04,
f22d0af0
GH
1616 [INPUT_BUTTON_WHEEL_UP] = 0x08,
1617 [INPUT_BUTTON_WHEEL_DOWN] = 0x10,
14768eba
GH
1618 };
1619 QemuConsole *con = vs->vd->dcl.con;
bea60dd7
PL
1620 int width = pixman_image_get_width(vs->vd->server);
1621 int height = pixman_image_get_height(vs->vd->server);
24236869 1622
14768eba
GH
1623 if (vs->last_bmask != button_mask) {
1624 qemu_input_update_buttons(con, bmap, vs->last_bmask, button_mask);
1625 vs->last_bmask = button_mask;
1626 }
564c337e
FB
1627
1628 if (vs->absolute) {
14768eba
GH
1629 qemu_input_queue_abs(con, INPUT_AXIS_X, x, width);
1630 qemu_input_queue_abs(con, INPUT_AXIS_Y, y, height);
29fa4ed9 1631 } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
14768eba
GH
1632 qemu_input_queue_rel(con, INPUT_AXIS_X, x - 0x7FFF);
1633 qemu_input_queue_rel(con, INPUT_AXIS_Y, y - 0x7FFF);
564c337e 1634 } else {
14768eba
GH
1635 if (vs->last_x != -1) {
1636 qemu_input_queue_rel(con, INPUT_AXIS_X, x - vs->last_x);
1637 qemu_input_queue_rel(con, INPUT_AXIS_Y, y - vs->last_y);
1638 }
28a76be8
AL
1639 vs->last_x = x;
1640 vs->last_y = y;
24236869 1641 }
14768eba 1642 qemu_input_event_sync();
24236869
FB
1643}
1644
64f5a135
FB
1645static void reset_keys(VncState *vs)
1646{
1647 int i;
1648 for(i = 0; i < 256; i++) {
1649 if (vs->modifiers_state[i]) {
8d447d10 1650 qemu_input_event_send_key_number(vs->vd->dcl.con, i, false);
c5ce8333 1651 qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
64f5a135
FB
1652 vs->modifiers_state[i] = 0;
1653 }
1654 }
1655}
1656
a528b80c
AZ
1657static void press_key(VncState *vs, int keysym)
1658{
44bb61c8 1659 int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
8d447d10 1660 qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true);
c5ce8333 1661 qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
8d447d10 1662 qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
c5ce8333 1663 qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
a528b80c
AZ
1664}
1665
ab99e5c1
LL
1666static void vnc_led_state_change(VncState *vs)
1667{
ab99e5c1
LL
1668 if (!vnc_has_feature(vs, VNC_FEATURE_LED_STATE)) {
1669 return;
1670 }
1671
ab99e5c1
LL
1672 vnc_lock_output(vs);
1673 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1674 vnc_write_u8(vs, 0);
1675 vnc_write_u16(vs, 1);
1676 vnc_framebuffer_update(vs, 0, 0, 1, 1, VNC_ENCODING_LED_STATE);
a54f0d2b 1677 vnc_write_u8(vs, vs->vd->ledstate);
ab99e5c1
LL
1678 vnc_unlock_output(vs);
1679 vnc_flush(vs);
1680}
1681
7ffb82ca
GH
1682static void kbd_leds(void *opaque, int ledstate)
1683{
a54f0d2b
PO
1684 VncDisplay *vd = opaque;
1685 VncState *client;
7ffb82ca 1686
40066175
GH
1687 trace_vnc_key_guest_leds((ledstate & QEMU_CAPS_LOCK_LED),
1688 (ledstate & QEMU_NUM_LOCK_LED),
1689 (ledstate & QEMU_SCROLL_LOCK_LED));
1690
a54f0d2b
PO
1691 if (ledstate == vd->ledstate) {
1692 return;
96f3d174 1693 }
ab99e5c1 1694
a54f0d2b
PO
1695 vd->ledstate = ledstate;
1696
1697 QTAILQ_FOREACH(client, &vd->clients, next) {
1698 vnc_led_state_change(client);
ab99e5c1 1699 }
7ffb82ca
GH
1700}
1701
9ca313aa 1702static void do_key_event(VncState *vs, int down, int keycode, int sym)
24236869 1703{
64f5a135
FB
1704 /* QEMU console switch */
1705 switch(keycode) {
1706 case 0x2a: /* Left Shift */
1707 case 0x36: /* Right Shift */
1708 case 0x1d: /* Left CTRL */
1709 case 0x9d: /* Right CTRL */
1710 case 0x38: /* Left ALT */
1711 case 0xb8: /* Right ALT */
1712 if (down)
1713 vs->modifiers_state[keycode] = 1;
1714 else
1715 vs->modifiers_state[keycode] = 0;
1716 break;
5fafdf24 1717 case 0x02 ... 0x0a: /* '1' to '9' keys */
1d0d59fe
GH
1718 if (vs->vd->dcl.con == NULL &&
1719 down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
64f5a135
FB
1720 /* Reset the modifiers sent to the current console */
1721 reset_keys(vs);
1722 console_select(keycode - 0x02);
1723 return;
1724 }
1725 break;
28a76be8
AL
1726 case 0x3a: /* CapsLock */
1727 case 0x45: /* NumLock */
7ffb82ca 1728 if (down)
a528b80c
AZ
1729 vs->modifiers_state[keycode] ^= 1;
1730 break;
1731 }
1732
e7b2aacc
LL
1733 /* Turn off the lock state sync logic if the client support the led
1734 state extension.
1735 */
9892088b 1736 if (down && vs->vd->lock_key_sync &&
e7b2aacc 1737 !vnc_has_feature(vs, VNC_FEATURE_LED_STATE) &&
3a0558b5 1738 keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
a528b80c
AZ
1739 /* If the numlock state needs to change then simulate an additional
1740 keypress before sending this one. This will happen if the user
1741 toggles numlock away from the VNC window.
1742 */
753b4053 1743 if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
a528b80c 1744 if (!vs->modifiers_state[0x45]) {
40066175 1745 trace_vnc_key_sync_numlock(true);
a528b80c
AZ
1746 vs->modifiers_state[0x45] = 1;
1747 press_key(vs, 0xff7f);
1748 }
1749 } else {
1750 if (vs->modifiers_state[0x45]) {
40066175 1751 trace_vnc_key_sync_numlock(false);
a528b80c
AZ
1752 vs->modifiers_state[0x45] = 0;
1753 press_key(vs, 0xff7f);
1754 }
1755 }
64f5a135 1756 }
24236869 1757
9892088b 1758 if (down && vs->vd->lock_key_sync &&
e7b2aacc 1759 !vnc_has_feature(vs, VNC_FEATURE_LED_STATE) &&
3a0558b5 1760 ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
6b132502
GH
1761 /* If the capslock state needs to change then simulate an additional
1762 keypress before sending this one. This will happen if the user
1763 toggles capslock away from the VNC window.
1764 */
1765 int uppercase = !!(sym >= 'A' && sym <= 'Z');
1766 int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
1767 int capslock = !!(vs->modifiers_state[0x3a]);
1768 if (capslock) {
1769 if (uppercase == shift) {
40066175 1770 trace_vnc_key_sync_capslock(false);
6b132502
GH
1771 vs->modifiers_state[0x3a] = 0;
1772 press_key(vs, 0xffe5);
1773 }
1774 } else {
1775 if (uppercase != shift) {
40066175 1776 trace_vnc_key_sync_capslock(true);
6b132502
GH
1777 vs->modifiers_state[0x3a] = 1;
1778 press_key(vs, 0xffe5);
1779 }
1780 }
1781 }
1782
81c0d5a6 1783 if (qemu_console_is_graphic(NULL)) {
8d447d10 1784 qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, down);
c5ce8333 1785 qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
64f5a135 1786 } else {
e26437c2
GH
1787 bool numlock = vs->modifiers_state[0x45];
1788 bool control = (vs->modifiers_state[0x1d] ||
1789 vs->modifiers_state[0x9d]);
64f5a135
FB
1790 /* QEMU console emulation */
1791 if (down) {
1792 switch (keycode) {
1793 case 0x2a: /* Left Shift */
1794 case 0x36: /* Right Shift */
1795 case 0x1d: /* Left CTRL */
1796 case 0x9d: /* Right CTRL */
1797 case 0x38: /* Left ALT */
1798 case 0xb8: /* Right ALT */
1799 break;
1800 case 0xc8:
1801 kbd_put_keysym(QEMU_KEY_UP);
1802 break;
1803 case 0xd0:
1804 kbd_put_keysym(QEMU_KEY_DOWN);
1805 break;
1806 case 0xcb:
1807 kbd_put_keysym(QEMU_KEY_LEFT);
1808 break;
1809 case 0xcd:
1810 kbd_put_keysym(QEMU_KEY_RIGHT);
1811 break;
1812 case 0xd3:
1813 kbd_put_keysym(QEMU_KEY_DELETE);
1814 break;
1815 case 0xc7:
1816 kbd_put_keysym(QEMU_KEY_HOME);
1817 break;
1818 case 0xcf:
1819 kbd_put_keysym(QEMU_KEY_END);
1820 break;
1821 case 0xc9:
1822 kbd_put_keysym(QEMU_KEY_PAGEUP);
1823 break;
1824 case 0xd1:
1825 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1826 break;
bb0a18e1
GH
1827
1828 case 0x47:
1829 kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
1830 break;
1831 case 0x48:
1832 kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
1833 break;
1834 case 0x49:
1835 kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
1836 break;
1837 case 0x4b:
1838 kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
1839 break;
1840 case 0x4c:
1841 kbd_put_keysym('5');
1842 break;
1843 case 0x4d:
1844 kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
1845 break;
1846 case 0x4f:
1847 kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
1848 break;
1849 case 0x50:
1850 kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
1851 break;
1852 case 0x51:
1853 kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
1854 break;
1855 case 0x52:
1856 kbd_put_keysym('0');
1857 break;
1858 case 0x53:
1859 kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
1860 break;
1861
1862 case 0xb5:
1863 kbd_put_keysym('/');
1864 break;
1865 case 0x37:
1866 kbd_put_keysym('*');
1867 break;
1868 case 0x4a:
1869 kbd_put_keysym('-');
1870 break;
1871 case 0x4e:
1872 kbd_put_keysym('+');
1873 break;
1874 case 0x9c:
1875 kbd_put_keysym('\n');
1876 break;
1877
64f5a135 1878 default:
e26437c2
GH
1879 if (control) {
1880 kbd_put_keysym(sym & 0x1f);
1881 } else {
1882 kbd_put_keysym(sym);
1883 }
64f5a135
FB
1884 break;
1885 }
1886 }
1887 }
24236869
FB
1888}
1889
7bc9318b
GH
1890static void vnc_release_modifiers(VncState *vs)
1891{
1892 static const int keycodes[] = {
1893 /* shift, control, alt keys, both left & right */
1894 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
1895 };
1896 int i, keycode;
1897
81c0d5a6 1898 if (!qemu_console_is_graphic(NULL)) {
7bc9318b
GH
1899 return;
1900 }
1901 for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
1902 keycode = keycodes[i];
1903 if (!vs->modifiers_state[keycode]) {
1904 continue;
1905 }
8d447d10 1906 qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
c5ce8333 1907 qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
7bc9318b
GH
1908 }
1909}
1910
40066175
GH
1911static const char *code2name(int keycode)
1912{
1913 return QKeyCode_lookup[qemu_input_key_number_to_qcode(keycode)];
1914}
1915
bdbd7676
FB
1916static void key_event(VncState *vs, int down, uint32_t sym)
1917{
9ca313aa 1918 int keycode;
4a93fe17 1919 int lsym = sym;
9ca313aa 1920
81c0d5a6 1921 if (lsym >= 'A' && lsym <= 'Z' && qemu_console_is_graphic(NULL)) {
4a93fe17
GH
1922 lsym = lsym - 'A' + 'a';
1923 }
9ca313aa 1924
44bb61c8 1925 keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK;
40066175 1926 trace_vnc_key_event_map(down, sym, keycode, code2name(keycode));
9ca313aa
AL
1927 do_key_event(vs, down, keycode, sym);
1928}
1929
1930static void ext_key_event(VncState *vs, int down,
1931 uint32_t sym, uint16_t keycode)
1932{
1933 /* if the user specifies a keyboard layout, always use it */
40066175 1934 if (keyboard_layout) {
9ca313aa 1935 key_event(vs, down, sym);
40066175
GH
1936 } else {
1937 trace_vnc_key_event_ext(down, sym, keycode, code2name(keycode));
9ca313aa 1938 do_key_event(vs, down, keycode, sym);
40066175 1939 }
bdbd7676
FB
1940}
1941
24236869 1942static void framebuffer_update_request(VncState *vs, int incremental,
bea60dd7 1943 int x, int y, int w, int h)
24236869 1944{
24236869 1945 vs->need_update = 1;
bea60dd7
PL
1946
1947 if (incremental) {
1948 return;
24236869 1949 }
bea60dd7 1950
07535a89 1951 vs->force_update = 1;
f7b3d68c 1952 vnc_set_area_dirty(vs->dirty, vs->vd, x, y, w, h);
24236869
FB
1953}
1954
9ca313aa
AL
1955static void send_ext_key_event_ack(VncState *vs)
1956{
bd023f95 1957 vnc_lock_output(vs);
46a183da 1958 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
9ca313aa
AL
1959 vnc_write_u8(vs, 0);
1960 vnc_write_u16(vs, 1);
d39fa6d8 1961 vnc_framebuffer_update(vs, 0, 0,
bea60dd7
PL
1962 pixman_image_get_width(vs->vd->server),
1963 pixman_image_get_height(vs->vd->server),
29fa4ed9 1964 VNC_ENCODING_EXT_KEY_EVENT);
bd023f95 1965 vnc_unlock_output(vs);
9ca313aa
AL
1966 vnc_flush(vs);
1967}
1968
429a8ed3 1969static void send_ext_audio_ack(VncState *vs)
1970{
bd023f95 1971 vnc_lock_output(vs);
46a183da 1972 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
429a8ed3 1973 vnc_write_u8(vs, 0);
1974 vnc_write_u16(vs, 1);
d39fa6d8 1975 vnc_framebuffer_update(vs, 0, 0,
bea60dd7
PL
1976 pixman_image_get_width(vs->vd->server),
1977 pixman_image_get_height(vs->vd->server),
29fa4ed9 1978 VNC_ENCODING_AUDIO);
bd023f95 1979 vnc_unlock_output(vs);
429a8ed3 1980 vnc_flush(vs);
1981}
1982
24236869
FB
1983static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1984{
1985 int i;
29fa4ed9 1986 unsigned int enc = 0;
24236869 1987
29fa4ed9 1988 vs->features = 0;
a9f20d31 1989 vs->vnc_encoding = 0;
d1af0e05
CC
1990 vs->tight.compression = 9;
1991 vs->tight.quality = -1; /* Lossless by default */
564c337e 1992 vs->absolute = -1;
24236869 1993
8a0f0d0c
CC
1994 /*
1995 * Start from the end because the encodings are sent in order of preference.
e5bed759 1996 * This way the preferred encoding (first encoding defined in the array)
8a0f0d0c
CC
1997 * will be set at the end of the loop.
1998 */
24236869 1999 for (i = n_encodings - 1; i >= 0; i--) {
29fa4ed9
AL
2000 enc = encodings[i];
2001 switch (enc) {
2002 case VNC_ENCODING_RAW:
a9f20d31 2003 vs->vnc_encoding = enc;
29fa4ed9
AL
2004 break;
2005 case VNC_ENCODING_COPYRECT:
753b4053 2006 vs->features |= VNC_FEATURE_COPYRECT_MASK;
29fa4ed9
AL
2007 break;
2008 case VNC_ENCODING_HEXTILE:
2009 vs->features |= VNC_FEATURE_HEXTILE_MASK;
a9f20d31 2010 vs->vnc_encoding = enc;
29fa4ed9 2011 break;
380282b0
CC
2012 case VNC_ENCODING_TIGHT:
2013 vs->features |= VNC_FEATURE_TIGHT_MASK;
2014 vs->vnc_encoding = enc;
2015 break;
fe3e7f2d 2016#ifdef CONFIG_VNC_PNG
efe556ad
CC
2017 case VNC_ENCODING_TIGHT_PNG:
2018 vs->features |= VNC_FEATURE_TIGHT_PNG_MASK;
2019 vs->vnc_encoding = enc;
2020 break;
fe3e7f2d 2021#endif
059cef40
AL
2022 case VNC_ENCODING_ZLIB:
2023 vs->features |= VNC_FEATURE_ZLIB_MASK;
a9f20d31 2024 vs->vnc_encoding = enc;
059cef40 2025 break;
148954fa
CC
2026 case VNC_ENCODING_ZRLE:
2027 vs->features |= VNC_FEATURE_ZRLE_MASK;
2028 vs->vnc_encoding = enc;
2029 break;
2030 case VNC_ENCODING_ZYWRLE:
2031 vs->features |= VNC_FEATURE_ZYWRLE_MASK;
2032 vs->vnc_encoding = enc;
2033 break;
29fa4ed9
AL
2034 case VNC_ENCODING_DESKTOPRESIZE:
2035 vs->features |= VNC_FEATURE_RESIZE_MASK;
2036 break;
2037 case VNC_ENCODING_POINTER_TYPE_CHANGE:
2038 vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
2039 break;
d467b679
GH
2040 case VNC_ENCODING_RICH_CURSOR:
2041 vs->features |= VNC_FEATURE_RICH_CURSOR_MASK;
91ec41dc
FZ
2042 if (vs->vd->cursor) {
2043 vnc_cursor_define(vs);
2044 }
d467b679 2045 break;
29fa4ed9 2046 case VNC_ENCODING_EXT_KEY_EVENT:
9ca313aa
AL
2047 send_ext_key_event_ack(vs);
2048 break;
29fa4ed9 2049 case VNC_ENCODING_AUDIO:
429a8ed3 2050 send_ext_audio_ack(vs);
2051 break;
29fa4ed9
AL
2052 case VNC_ENCODING_WMVi:
2053 vs->features |= VNC_FEATURE_WMVI_MASK;
ca4cca4d 2054 break;
ab99e5c1
LL
2055 case VNC_ENCODING_LED_STATE:
2056 vs->features |= VNC_FEATURE_LED_STATE_MASK;
2057 break;
fb437313 2058 case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
d1af0e05 2059 vs->tight.compression = (enc & 0x0F);
fb437313
AL
2060 break;
2061 case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
b31f519e
CC
2062 if (vs->vd->lossy) {
2063 vs->tight.quality = (enc & 0x0F);
2064 }
fb437313 2065 break;
29fa4ed9
AL
2066 default:
2067 VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
2068 break;
2069 }
24236869 2070 }
6356e472 2071 vnc_desktop_resize(vs);
9e8dd451 2072 check_pointer_type_change(&vs->mouse_mode_notifier, NULL);
ab99e5c1 2073 vnc_led_state_change(vs);
24236869
FB
2074}
2075
6cec5487
AL
2076static void set_pixel_conversion(VncState *vs)
2077{
9f64916d
GH
2078 pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf);
2079
2080 if (fmt == VNC_SERVER_FB_FORMAT) {
6cec5487 2081 vs->write_pixels = vnc_write_pixels_copy;
70a4568f 2082 vnc_hextile_set_pixel_conversion(vs, 0);
6cec5487
AL
2083 } else {
2084 vs->write_pixels = vnc_write_pixels_generic;
70a4568f 2085 vnc_hextile_set_pixel_conversion(vs, 1);
6cec5487
AL
2086 }
2087}
2088
0c426e45
AG
2089static void send_color_map(VncState *vs)
2090{
2091 int i;
2092
2093 vnc_write_u8(vs, VNC_MSG_SERVER_SET_COLOUR_MAP_ENTRIES);
2094 vnc_write_u8(vs, 0); /* padding */
2095 vnc_write_u16(vs, 0); /* first color */
2096 vnc_write_u16(vs, 256); /* # of colors */
2097
2098 for (i = 0; i < 256; i++) {
2099 PixelFormat *pf = &vs->client_pf;
2100
2101 vnc_write_u16(vs, (((i >> pf->rshift) & pf->rmax) << (16 - pf->rbits)));
2102 vnc_write_u16(vs, (((i >> pf->gshift) & pf->gmax) << (16 - pf->gbits)));
2103 vnc_write_u16(vs, (((i >> pf->bshift) & pf->bmax) << (16 - pf->bbits)));
2104 }
2105}
2106
ec9fb41a 2107static void set_pixel_format(VncState *vs, int bits_per_pixel,
28a76be8
AL
2108 int big_endian_flag, int true_color_flag,
2109 int red_max, int green_max, int blue_max,
2110 int red_shift, int green_shift, int blue_shift)
24236869 2111{
3512779a 2112 if (!true_color_flag) {
0c426e45
AG
2113 /* Expose a reasonable default 256 color map */
2114 bits_per_pixel = 8;
0c426e45
AG
2115 red_max = 7;
2116 green_max = 7;
2117 blue_max = 3;
2118 red_shift = 0;
2119 green_shift = 3;
2120 blue_shift = 6;
3512779a 2121 }
24236869 2122
e6908bfe
PM
2123 switch (bits_per_pixel) {
2124 case 8:
2125 case 16:
2126 case 32:
2127 break;
2128 default:
2129 vnc_client_error(vs);
2130 return;
2131 }
2132
4c65fed8 2133 vs->client_pf.rmax = red_max ? red_max : 0xFF;
9f64916d
GH
2134 vs->client_pf.rbits = hweight_long(red_max);
2135 vs->client_pf.rshift = red_shift;
2136 vs->client_pf.rmask = red_max << red_shift;
4c65fed8 2137 vs->client_pf.gmax = green_max ? green_max : 0xFF;
9f64916d
GH
2138 vs->client_pf.gbits = hweight_long(green_max);
2139 vs->client_pf.gshift = green_shift;
2140 vs->client_pf.gmask = green_max << green_shift;
4c65fed8 2141 vs->client_pf.bmax = blue_max ? blue_max : 0xFF;
9f64916d
GH
2142 vs->client_pf.bbits = hweight_long(blue_max);
2143 vs->client_pf.bshift = blue_shift;
2144 vs->client_pf.bmask = blue_max << blue_shift;
2145 vs->client_pf.bits_per_pixel = bits_per_pixel;
2146 vs->client_pf.bytes_per_pixel = bits_per_pixel / 8;
2147 vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
2148 vs->client_be = big_endian_flag;
6cec5487 2149
0c426e45
AG
2150 if (!true_color_flag) {
2151 send_color_map(vs);
2152 }
2153
6cec5487 2154 set_pixel_conversion(vs);
24236869 2155
1d0d59fe
GH
2156 graphic_hw_invalidate(vs->vd->dcl.con);
2157 graphic_hw_update(vs->vd->dcl.con);
24236869
FB
2158}
2159
ca4cca4d
AL
2160static void pixel_format_message (VncState *vs) {
2161 char pad[3] = { 0, 0, 0 };
2162
9f64916d
GH
2163 vs->client_pf = qemu_default_pixelformat(32);
2164
2165 vnc_write_u8(vs, vs->client_pf.bits_per_pixel); /* bits-per-pixel */
2166 vnc_write_u8(vs, vs->client_pf.depth); /* depth */
ca4cca4d 2167
e2542fe2 2168#ifdef HOST_WORDS_BIGENDIAN
ca4cca4d
AL
2169 vnc_write_u8(vs, 1); /* big-endian-flag */
2170#else
2171 vnc_write_u8(vs, 0); /* big-endian-flag */
2172#endif
2173 vnc_write_u8(vs, 1); /* true-color-flag */
9f64916d
GH
2174 vnc_write_u16(vs, vs->client_pf.rmax); /* red-max */
2175 vnc_write_u16(vs, vs->client_pf.gmax); /* green-max */
2176 vnc_write_u16(vs, vs->client_pf.bmax); /* blue-max */
2177 vnc_write_u8(vs, vs->client_pf.rshift); /* red-shift */
2178 vnc_write_u8(vs, vs->client_pf.gshift); /* green-shift */
2179 vnc_write_u8(vs, vs->client_pf.bshift); /* blue-shift */
2180 vnc_write(vs, pad, 3); /* padding */
70a4568f
CC
2181
2182 vnc_hextile_set_pixel_conversion(vs, 0);
ca4cca4d 2183 vs->write_pixels = vnc_write_pixels_copy;
ca4cca4d
AL
2184}
2185
753b4053 2186static void vnc_colordepth(VncState *vs)
7eac3a87 2187{
753b4053 2188 if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
ca4cca4d 2189 /* Sending a WMVi message to notify the client*/
bd023f95 2190 vnc_lock_output(vs);
46a183da 2191 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
ca4cca4d
AL
2192 vnc_write_u8(vs, 0);
2193 vnc_write_u16(vs, 1); /* number of rects */
d39fa6d8 2194 vnc_framebuffer_update(vs, 0, 0,
bea60dd7
PL
2195 pixman_image_get_width(vs->vd->server),
2196 pixman_image_get_height(vs->vd->server),
d39fa6d8 2197 VNC_ENCODING_WMVi);
ca4cca4d 2198 pixel_format_message(vs);
bd023f95 2199 vnc_unlock_output(vs);
ca4cca4d 2200 vnc_flush(vs);
7eac3a87 2201 } else {
6cec5487 2202 set_pixel_conversion(vs);
7eac3a87
AL
2203 }
2204}
2205
60fe76f3 2206static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
24236869
FB
2207{
2208 int i;
2209 uint16_t limit;
2430ffe4
SS
2210 VncDisplay *vd = vs->vd;
2211
2212 if (data[0] > 3) {
0f7b2864 2213 update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
2430ffe4 2214 }
24236869
FB
2215
2216 switch (data[0]) {
46a183da 2217 case VNC_MSG_CLIENT_SET_PIXEL_FORMAT:
28a76be8
AL
2218 if (len == 1)
2219 return 20;
2220
ec9fb41a 2221 set_pixel_format(vs, read_u8(data, 4),
28a76be8
AL
2222 read_u8(data, 6), read_u8(data, 7),
2223 read_u16(data, 8), read_u16(data, 10),
2224 read_u16(data, 12), read_u8(data, 14),
2225 read_u8(data, 15), read_u8(data, 16));
2226 break;
46a183da 2227 case VNC_MSG_CLIENT_SET_ENCODINGS:
28a76be8
AL
2228 if (len == 1)
2229 return 4;
24236869 2230
28a76be8 2231 if (len == 4) {
69dd5c9f
AL
2232 limit = read_u16(data, 2);
2233 if (limit > 0)
2234 return 4 + (limit * 4);
2235 } else
2236 limit = read_u16(data, 2);
24236869 2237
28a76be8
AL
2238 for (i = 0; i < limit; i++) {
2239 int32_t val = read_s32(data, 4 + (i * 4));
2240 memcpy(data + 4 + (i * 4), &val, sizeof(val));
2241 }
24236869 2242
28a76be8
AL
2243 set_encodings(vs, (int32_t *)(data + 4), limit);
2244 break;
46a183da 2245 case VNC_MSG_CLIENT_FRAMEBUFFER_UPDATE_REQUEST:
28a76be8
AL
2246 if (len == 1)
2247 return 10;
24236869 2248
28a76be8
AL
2249 framebuffer_update_request(vs,
2250 read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
2251 read_u16(data, 6), read_u16(data, 8));
2252 break;
46a183da 2253 case VNC_MSG_CLIENT_KEY_EVENT:
28a76be8
AL
2254 if (len == 1)
2255 return 8;
24236869 2256
28a76be8
AL
2257 key_event(vs, read_u8(data, 1), read_u32(data, 4));
2258 break;
46a183da 2259 case VNC_MSG_CLIENT_POINTER_EVENT:
28a76be8
AL
2260 if (len == 1)
2261 return 6;
24236869 2262
28a76be8
AL
2263 pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
2264 break;
46a183da 2265 case VNC_MSG_CLIENT_CUT_TEXT:
f9a70e79 2266 if (len == 1) {
28a76be8 2267 return 8;
f9a70e79 2268 }
28a76be8 2269 if (len == 8) {
baa7666c 2270 uint32_t dlen = read_u32(data, 4);
f9a70e79
PL
2271 if (dlen > (1 << 20)) {
2272 error_report("vnc: client_cut_text msg payload has %u bytes"
2273 " which exceeds our limit of 1MB.", dlen);
2274 vnc_client_error(vs);
2275 break;
2276 }
2277 if (dlen > 0) {
baa7666c 2278 return 8 + dlen;
f9a70e79 2279 }
baa7666c 2280 }
24236869 2281
28a76be8
AL
2282 client_cut_text(vs, read_u32(data, 4), data + 8);
2283 break;
46a183da 2284 case VNC_MSG_CLIENT_QEMU:
9ca313aa
AL
2285 if (len == 1)
2286 return 2;
2287
2288 switch (read_u8(data, 1)) {
46a183da 2289 case VNC_MSG_CLIENT_QEMU_EXT_KEY_EVENT:
9ca313aa
AL
2290 if (len == 2)
2291 return 12;
2292
2293 ext_key_event(vs, read_u16(data, 2),
2294 read_u32(data, 4), read_u32(data, 8));
2295 break;
46a183da 2296 case VNC_MSG_CLIENT_QEMU_AUDIO:
429a8ed3 2297 if (len == 2)
2298 return 4;
2299
2300 switch (read_u16 (data, 2)) {
46a183da 2301 case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE:
429a8ed3 2302 audio_add(vs);
2303 break;
46a183da 2304 case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE:
429a8ed3 2305 audio_del(vs);
2306 break;
46a183da 2307 case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT:
429a8ed3 2308 if (len == 4)
2309 return 10;
2310 switch (read_u8(data, 4)) {
2311 case 0: vs->as.fmt = AUD_FMT_U8; break;
2312 case 1: vs->as.fmt = AUD_FMT_S8; break;
2313 case 2: vs->as.fmt = AUD_FMT_U16; break;
2314 case 3: vs->as.fmt = AUD_FMT_S16; break;
2315 case 4: vs->as.fmt = AUD_FMT_U32; break;
2316 case 5: vs->as.fmt = AUD_FMT_S32; break;
2317 default:
153130cd 2318 VNC_DEBUG("Invalid audio format %d\n", read_u8(data, 4));
429a8ed3 2319 vnc_client_error(vs);
2320 break;
2321 }
2322 vs->as.nchannels = read_u8(data, 5);
2323 if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
153130cd
DB
2324 VNC_DEBUG("Invalid audio channel coount %d\n",
2325 read_u8(data, 5));
429a8ed3 2326 vnc_client_error(vs);
2327 break;
2328 }
2329 vs->as.freq = read_u32(data, 6);
2330 break;
2331 default:
153130cd 2332 VNC_DEBUG("Invalid audio message %d\n", read_u8(data, 4));
429a8ed3 2333 vnc_client_error(vs);
2334 break;
2335 }
2336 break;
2337
9ca313aa 2338 default:
153130cd 2339 VNC_DEBUG("Msg: %d\n", read_u16(data, 0));
9ca313aa
AL
2340 vnc_client_error(vs);
2341 break;
2342 }
2343 break;
24236869 2344 default:
153130cd 2345 VNC_DEBUG("Msg: %d\n", data[0]);
28a76be8
AL
2346 vnc_client_error(vs);
2347 break;
24236869 2348 }
5fafdf24 2349
24236869
FB
2350 vnc_read_when(vs, protocol_client_msg, 1);
2351 return 0;
2352}
2353
60fe76f3 2354static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
24236869 2355{
c35734b2 2356 char buf[1024];
8cf36489 2357 VncShareMode mode;
c35734b2 2358 int size;
24236869 2359
8cf36489
GH
2360 mode = data[0] ? VNC_SHARE_MODE_SHARED : VNC_SHARE_MODE_EXCLUSIVE;
2361 switch (vs->vd->share_policy) {
2362 case VNC_SHARE_POLICY_IGNORE:
2363 /*
2364 * Ignore the shared flag. Nothing to do here.
2365 *
2366 * Doesn't conform to the rfb spec but is traditional qemu
2367 * behavior, thus left here as option for compatibility
2368 * reasons.
2369 */
2370 break;
2371 case VNC_SHARE_POLICY_ALLOW_EXCLUSIVE:
2372 /*
2373 * Policy: Allow clients ask for exclusive access.
2374 *
2375 * Implementation: When a client asks for exclusive access,
2376 * disconnect all others. Shared connects are allowed as long
2377 * as no exclusive connection exists.
2378 *
2379 * This is how the rfb spec suggests to handle the shared flag.
2380 */
2381 if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
2382 VncState *client;
2383 QTAILQ_FOREACH(client, &vs->vd->clients, next) {
2384 if (vs == client) {
2385 continue;
2386 }
2387 if (client->share_mode != VNC_SHARE_MODE_EXCLUSIVE &&
2388 client->share_mode != VNC_SHARE_MODE_SHARED) {
2389 continue;
2390 }
2391 vnc_disconnect_start(client);
2392 }
2393 }
2394 if (mode == VNC_SHARE_MODE_SHARED) {
2395 if (vs->vd->num_exclusive > 0) {
2396 vnc_disconnect_start(vs);
2397 return 0;
2398 }
2399 }
2400 break;
2401 case VNC_SHARE_POLICY_FORCE_SHARED:
2402 /*
2403 * Policy: Shared connects only.
2404 * Implementation: Disallow clients asking for exclusive access.
2405 *
2406 * Useful for shared desktop sessions where you don't want
2407 * someone forgetting to say -shared when running the vnc
2408 * client disconnect everybody else.
2409 */
2410 if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
2411 vnc_disconnect_start(vs);
2412 return 0;
2413 }
2414 break;
2415 }
2416 vnc_set_share_mode(vs, mode);
2417
e5f34cdd
GH
2418 if (vs->vd->num_shared > vs->vd->connections_limit) {
2419 vnc_disconnect_start(vs);
2420 return 0;
2421 }
2422
bea60dd7
PL
2423 vs->client_width = pixman_image_get_width(vs->vd->server);
2424 vs->client_height = pixman_image_get_height(vs->vd->server);
5862d195
GH
2425 vnc_write_u16(vs, vs->client_width);
2426 vnc_write_u16(vs, vs->client_height);
24236869 2427
ca4cca4d 2428 pixel_format_message(vs);
24236869 2429
97efe4f9 2430 if (qemu_name) {
c35734b2 2431 size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
97efe4f9
TH
2432 if (size > sizeof(buf)) {
2433 size = sizeof(buf);
2434 }
2435 } else {
c35734b2 2436 size = snprintf(buf, sizeof(buf), "QEMU");
97efe4f9 2437 }
c35734b2
TS
2438
2439 vnc_write_u32(vs, size);
2440 vnc_write(vs, buf, size);
24236869
FB
2441 vnc_flush(vs);
2442
4a80dba3 2443 vnc_client_cache_auth(vs);
fb6ba0d5 2444 vnc_qmp_event(vs, QAPI_EVENT_VNC_INITIALIZED);
4a80dba3 2445
24236869
FB
2446 vnc_read_when(vs, protocol_client_msg, 1);
2447
2448 return 0;
2449}
2450
5fb6c7a8
AL
2451void start_client_init(VncState *vs)
2452{
2453 vnc_read_when(vs, protocol_client_init, 1);
2454}
2455
70848515
TS
2456static void make_challenge(VncState *vs)
2457{
2458 int i;
2459
2460 srand(time(NULL)+getpid()+getpid()*987654+rand());
2461
2462 for (i = 0 ; i < sizeof(vs->challenge) ; i++)
2463 vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
2464}
2465
60fe76f3 2466static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
70848515 2467{
60fe76f3 2468 unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
800567a6 2469 size_t i, pwlen;
60fe76f3 2470 unsigned char key[8];
3c9405a0 2471 time_t now = time(NULL);
60928458 2472 QCryptoCipher *cipher = NULL;
800567a6 2473 Error *err = NULL;
70848515 2474
1cd20f8b 2475 if (!vs->vd->password) {
28a76be8 2476 VNC_DEBUG("No password configured on server");
6bffdf0f 2477 goto reject;
70848515 2478 }
3c9405a0
GH
2479 if (vs->vd->expires < now) {
2480 VNC_DEBUG("Password is expired");
2481 goto reject;
2482 }
70848515
TS
2483
2484 memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
2485
2486 /* Calculate the expected challenge response */
753b4053 2487 pwlen = strlen(vs->vd->password);
70848515 2488 for (i=0; i<sizeof(key); i++)
753b4053 2489 key[i] = i<pwlen ? vs->vd->password[i] : 0;
800567a6
DB
2490
2491 cipher = qcrypto_cipher_new(
2492 QCRYPTO_CIPHER_ALG_DES_RFB,
2493 QCRYPTO_CIPHER_MODE_ECB,
2494 key, G_N_ELEMENTS(key),
2495 &err);
2496 if (!cipher) {
2497 VNC_DEBUG("Cannot initialize cipher %s",
2498 error_get_pretty(err));
2499 error_free(err);
2500 goto reject;
2501 }
2502
a1695137 2503 if (qcrypto_cipher_encrypt(cipher,
800567a6
DB
2504 vs->challenge,
2505 response,
2506 VNC_AUTH_CHALLENGE_SIZE,
2507 &err) < 0) {
2508 VNC_DEBUG("Cannot encrypt challenge %s",
2509 error_get_pretty(err));
2510 error_free(err);
2511 goto reject;
2512 }
70848515
TS
2513
2514 /* Compare expected vs actual challenge response */
2515 if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
e5bed759 2516 VNC_DEBUG("Client challenge response did not match\n");
6bffdf0f 2517 goto reject;
70848515 2518 } else {
28a76be8
AL
2519 VNC_DEBUG("Accepting VNC challenge response\n");
2520 vnc_write_u32(vs, 0); /* Accept auth */
2521 vnc_flush(vs);
70848515 2522
5fb6c7a8 2523 start_client_init(vs);
70848515 2524 }
60928458
GA
2525
2526 qcrypto_cipher_free(cipher);
70848515 2527 return 0;
6bffdf0f
GH
2528
2529reject:
2530 vnc_write_u32(vs, 1); /* Reject auth */
2531 if (vs->minor >= 8) {
2532 static const char err[] = "Authentication failed";
2533 vnc_write_u32(vs, sizeof(err));
2534 vnc_write(vs, err, sizeof(err));
2535 }
2536 vnc_flush(vs);
2537 vnc_client_error(vs);
60928458 2538 qcrypto_cipher_free(cipher);
6bffdf0f 2539 return 0;
70848515
TS
2540}
2541
5fb6c7a8 2542void start_auth_vnc(VncState *vs)
70848515
TS
2543{
2544 make_challenge(vs);
2545 /* Send client a 'random' challenge */
2546 vnc_write(vs, vs->challenge, sizeof(vs->challenge));
2547 vnc_flush(vs);
2548
2549 vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
469b15c6
TS
2550}
2551
2552
60fe76f3 2553static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
70848515
TS
2554{
2555 /* We only advertise 1 auth scheme at a time, so client
2556 * must pick the one we sent. Verify this */
7e7e2ebc 2557 if (data[0] != vs->auth) { /* Reject auth */
1263b7d6 2558 VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
70848515
TS
2559 vnc_write_u32(vs, 1);
2560 if (vs->minor >= 8) {
2561 static const char err[] = "Authentication failed";
2562 vnc_write_u32(vs, sizeof(err));
2563 vnc_write(vs, err, sizeof(err));
2564 }
2565 vnc_client_error(vs);
2566 } else { /* Accept requested auth */
2567 VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
7e7e2ebc 2568 switch (vs->auth) {
70848515
TS
2569 case VNC_AUTH_NONE:
2570 VNC_DEBUG("Accept auth none\n");
a26c97ad
AZ
2571 if (vs->minor >= 8) {
2572 vnc_write_u32(vs, 0); /* Accept auth completion */
2573 vnc_flush(vs);
2574 }
5fb6c7a8 2575 start_client_init(vs);
70848515
TS
2576 break;
2577
2578 case VNC_AUTH_VNC:
2579 VNC_DEBUG("Start VNC auth\n");
5fb6c7a8
AL
2580 start_auth_vnc(vs);
2581 break;
70848515 2582
8d5d2d4c 2583 case VNC_AUTH_VENCRYPT:
3a93113a 2584 VNC_DEBUG("Accept VeNCrypt auth\n");
5fb6c7a8
AL
2585 start_auth_vencrypt(vs);
2586 break;
8d5d2d4c 2587
2f9606b3
AL
2588#ifdef CONFIG_VNC_SASL
2589 case VNC_AUTH_SASL:
2590 VNC_DEBUG("Accept SASL auth\n");
2591 start_auth_sasl(vs);
2592 break;
2593#endif /* CONFIG_VNC_SASL */
2594
70848515 2595 default: /* Should not be possible, but just in case */
7e7e2ebc 2596 VNC_DEBUG("Reject auth %d server code bug\n", vs->auth);
70848515
TS
2597 vnc_write_u8(vs, 1);
2598 if (vs->minor >= 8) {
2599 static const char err[] = "Authentication failed";
2600 vnc_write_u32(vs, sizeof(err));
2601 vnc_write(vs, err, sizeof(err));
2602 }
2603 vnc_client_error(vs);
2604 }
2605 }
2606 return 0;
2607}
2608
60fe76f3 2609static int protocol_version(VncState *vs, uint8_t *version, size_t len)
24236869
FB
2610{
2611 char local[13];
24236869
FB
2612
2613 memcpy(local, version, 12);
2614 local[12] = 0;
2615
70848515 2616 if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
28a76be8
AL
2617 VNC_DEBUG("Malformed protocol version %s\n", local);
2618 vnc_client_error(vs);
2619 return 0;
24236869 2620 }
70848515
TS
2621 VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2622 if (vs->major != 3 ||
28a76be8
AL
2623 (vs->minor != 3 &&
2624 vs->minor != 4 &&
2625 vs->minor != 5 &&
2626 vs->minor != 7 &&
2627 vs->minor != 8)) {
2628 VNC_DEBUG("Unsupported client version\n");
2629 vnc_write_u32(vs, VNC_AUTH_INVALID);
2630 vnc_flush(vs);
2631 vnc_client_error(vs);
2632 return 0;
70848515 2633 }
b0566f4f 2634 /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
70848515
TS
2635 * as equivalent to v3.3 by servers
2636 */
b0566f4f 2637 if (vs->minor == 4 || vs->minor == 5)
28a76be8 2638 vs->minor = 3;
70848515
TS
2639
2640 if (vs->minor == 3) {
7e7e2ebc 2641 if (vs->auth == VNC_AUTH_NONE) {
70848515 2642 VNC_DEBUG("Tell client auth none\n");
7e7e2ebc 2643 vnc_write_u32(vs, vs->auth);
70848515 2644 vnc_flush(vs);
28a76be8 2645 start_client_init(vs);
7e7e2ebc 2646 } else if (vs->auth == VNC_AUTH_VNC) {
70848515 2647 VNC_DEBUG("Tell client VNC auth\n");
7e7e2ebc 2648 vnc_write_u32(vs, vs->auth);
70848515
TS
2649 vnc_flush(vs);
2650 start_auth_vnc(vs);
2651 } else {
7e7e2ebc 2652 VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
70848515
TS
2653 vnc_write_u32(vs, VNC_AUTH_INVALID);
2654 vnc_flush(vs);
2655 vnc_client_error(vs);
2656 }
2657 } else {
7e7e2ebc 2658 VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
28a76be8 2659 vnc_write_u8(vs, 1); /* num auth */
7e7e2ebc 2660 vnc_write_u8(vs, vs->auth);
28a76be8
AL
2661 vnc_read_when(vs, protocol_client_auth, 1);
2662 vnc_flush(vs);
70848515 2663 }
24236869
FB
2664
2665 return 0;
2666}
2667
999342a0
CC
2668static VncRectStat *vnc_stat_rect(VncDisplay *vd, int x, int y)
2669{
2670 struct VncSurface *vs = &vd->guest;
2671
2672 return &vs->stats[y / VNC_STAT_RECT][x / VNC_STAT_RECT];
2673}
2674
7d964c9d
CC
2675void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h)
2676{
2677 int i, j;
2678
2679 w = (x + w) / VNC_STAT_RECT;
2680 h = (y + h) / VNC_STAT_RECT;
2681 x /= VNC_STAT_RECT;
2682 y /= VNC_STAT_RECT;
2683
207f328a
CC
2684 for (j = y; j <= h; j++) {
2685 for (i = x; i <= w; i++) {
7d964c9d
CC
2686 vs->lossy_rect[j][i] = 1;
2687 }
2688 }
2689}
2690
2691static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
2692{
2693 VncState *vs;
2694 int sty = y / VNC_STAT_RECT;
2695 int stx = x / VNC_STAT_RECT;
2696 int has_dirty = 0;
2697
2698 y = y / VNC_STAT_RECT * VNC_STAT_RECT;
2699 x = x / VNC_STAT_RECT * VNC_STAT_RECT;
2700
2701 QTAILQ_FOREACH(vs, &vd->clients, next) {
bc2429b9 2702 int j;
7d964c9d
CC
2703
2704 /* kernel send buffers are full -> refresh later */
2705 if (vs->output.offset) {
2706 continue;
2707 }
2708
2709 if (!vs->lossy_rect[sty][stx]) {
2710 continue;
2711 }
207f328a 2712
7d964c9d
CC
2713 vs->lossy_rect[sty][stx] = 0;
2714 for (j = 0; j < VNC_STAT_RECT; ++j) {
b4c85ddc
PL
2715 bitmap_set(vs->dirty[y + j],
2716 x / VNC_DIRTY_PIXELS_PER_BIT,
2717 VNC_STAT_RECT / VNC_DIRTY_PIXELS_PER_BIT);
7d964c9d
CC
2718 }
2719 has_dirty++;
2720 }
207f328a 2721
7d964c9d
CC
2722 return has_dirty;
2723}
2724
2725static int vnc_update_stats(VncDisplay *vd, struct timeval * tv)
999342a0 2726{
9f64916d
GH
2727 int width = pixman_image_get_width(vd->guest.fb);
2728 int height = pixman_image_get_height(vd->guest.fb);
999342a0
CC
2729 int x, y;
2730 struct timeval res;
7d964c9d 2731 int has_dirty = 0;
999342a0 2732
9f64916d
GH
2733 for (y = 0; y < height; y += VNC_STAT_RECT) {
2734 for (x = 0; x < width; x += VNC_STAT_RECT) {
999342a0
CC
2735 VncRectStat *rect = vnc_stat_rect(vd, x, y);
2736
2737 rect->updated = false;
2738 }
2739 }
2740
ad620c29 2741 qemu_timersub(tv, &VNC_REFRESH_STATS, &res);
999342a0
CC
2742
2743 if (timercmp(&vd->guest.last_freq_check, &res, >)) {
7d964c9d 2744 return has_dirty;
999342a0
CC
2745 }
2746 vd->guest.last_freq_check = *tv;
2747
9f64916d
GH
2748 for (y = 0; y < height; y += VNC_STAT_RECT) {
2749 for (x = 0; x < width; x += VNC_STAT_RECT) {
999342a0
CC
2750 VncRectStat *rect= vnc_stat_rect(vd, x, y);
2751 int count = ARRAY_SIZE(rect->times);
2752 struct timeval min, max;
2753
2754 if (!timerisset(&rect->times[count - 1])) {
2755 continue ;
2756 }
2757
2758 max = rect->times[(rect->idx + count - 1) % count];
ad620c29 2759 qemu_timersub(tv, &max, &res);
999342a0
CC
2760
2761 if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) {
2762 rect->freq = 0;
7d964c9d 2763 has_dirty += vnc_refresh_lossy_rect(vd, x, y);
999342a0
CC
2764 memset(rect->times, 0, sizeof (rect->times));
2765 continue ;
2766 }
2767
2768 min = rect->times[rect->idx];
2769 max = rect->times[(rect->idx + count - 1) % count];
ad620c29 2770 qemu_timersub(&max, &min, &res);
999342a0
CC
2771
2772 rect->freq = res.tv_sec + res.tv_usec / 1000000.;
2773 rect->freq /= count;
2774 rect->freq = 1. / rect->freq;
2775 }
2776 }
7d964c9d 2777 return has_dirty;
999342a0
CC
2778}
2779
2780double vnc_update_freq(VncState *vs, int x, int y, int w, int h)
2781{
2782 int i, j;
2783 double total = 0;
2784 int num = 0;
2785
2786 x = (x / VNC_STAT_RECT) * VNC_STAT_RECT;
2787 y = (y / VNC_STAT_RECT) * VNC_STAT_RECT;
2788
2789 for (j = y; j <= y + h; j += VNC_STAT_RECT) {
2790 for (i = x; i <= x + w; i += VNC_STAT_RECT) {
2791 total += vnc_stat_rect(vs->vd, i, j)->freq;
2792 num++;
2793 }
2794 }
2795
2796 if (num) {
2797 return total / num;
2798 } else {
2799 return 0;
2800 }
2801}
2802
2803static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv)
2804{
2805 VncRectStat *rect;
2806
2807 rect = vnc_stat_rect(vd, x, y);
2808 if (rect->updated) {
2809 return ;
2810 }
2811 rect->times[rect->idx] = *tv;
2812 rect->idx = (rect->idx + 1) % ARRAY_SIZE(rect->times);
2813 rect->updated = true;
2814}
2815
1fc62412
SS
2816static int vnc_refresh_server_surface(VncDisplay *vd)
2817{
bea60dd7
PL
2818 int width = MIN(pixman_image_get_width(vd->guest.fb),
2819 pixman_image_get_width(vd->server));
2820 int height = MIN(pixman_image_get_height(vd->guest.fb),
2821 pixman_image_get_height(vd->server));
eb8934b0 2822 int cmp_bytes, server_stride, line_bytes, guest_ll, guest_stride, y = 0;
12b316d4 2823 uint8_t *guest_row0 = NULL, *server_row0;
41b4bef6 2824 VncState *vs;
1fc62412 2825 int has_dirty = 0;
9f64916d 2826 pixman_image_t *tmpbuf = NULL;
1fc62412 2827
80e0c8c3 2828 struct timeval tv = { 0, 0 };
999342a0 2829
80e0c8c3
CC
2830 if (!vd->non_adaptive) {
2831 gettimeofday(&tv, NULL);
2832 has_dirty = vnc_update_stats(vd, &tv);
2833 }
999342a0 2834
1fc62412
SS
2835 /*
2836 * Walk through the guest dirty map.
2837 * Check and copy modified bits from guest to server surface.
2838 * Update server dirty map.
2839 */
bea60dd7 2840 server_row0 = (uint8_t *)pixman_image_get_data(vd->server);
eb8934b0
GH
2841 server_stride = guest_stride = guest_ll =
2842 pixman_image_get_stride(vd->server);
bea60dd7
PL
2843 cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES,
2844 server_stride);
9f64916d
GH
2845 if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
2846 int width = pixman_image_get_width(vd->server);
2847 tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width);
12b316d4 2848 } else {
eb8934b0
GH
2849 int guest_bpp =
2850 PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb));
12b316d4
PL
2851 guest_row0 = (uint8_t *)pixman_image_get_data(vd->guest.fb);
2852 guest_stride = pixman_image_get_stride(vd->guest.fb);
eb8934b0 2853 guest_ll = pixman_image_get_width(vd->guest.fb) * ((guest_bpp + 7) / 8);
12b316d4 2854 }
eb8934b0 2855 line_bytes = MIN(server_stride, guest_ll);
12b316d4 2856
12b316d4
PL
2857 for (;;) {
2858 int x;
2859 uint8_t *guest_ptr, *server_ptr;
2860 unsigned long offset = find_next_bit((unsigned long *) &vd->guest.dirty,
2861 height * VNC_DIRTY_BPL(&vd->guest),
2862 y * VNC_DIRTY_BPL(&vd->guest));
2863 if (offset == height * VNC_DIRTY_BPL(&vd->guest)) {
2864 /* no more dirty bits */
2865 break;
2866 }
2867 y = offset / VNC_DIRTY_BPL(&vd->guest);
2868 x = offset % VNC_DIRTY_BPL(&vd->guest);
1fc62412 2869
12b316d4
PL
2870 server_ptr = server_row0 + y * server_stride + x * cmp_bytes;
2871
2872 if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
2873 qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, 0, y);
2874 guest_ptr = (uint8_t *)pixman_image_get_data(tmpbuf);
2875 } else {
2876 guest_ptr = guest_row0 + y * guest_stride;
2877 }
2878 guest_ptr += x * cmp_bytes;
2879
2880 for (; x < DIV_ROUND_UP(width, VNC_DIRTY_PIXELS_PER_BIT);
2881 x++, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
bea60dd7 2882 int _cmp_bytes = cmp_bytes;
12b316d4
PL
2883 if (!test_and_clear_bit(x, vd->guest.dirty[y])) {
2884 continue;
2885 }
eb8934b0
GH
2886 if ((x + 1) * cmp_bytes > line_bytes) {
2887 _cmp_bytes = line_bytes - x * cmp_bytes;
bea60dd7 2888 }
eb8934b0 2889 assert(_cmp_bytes >= 0);
bea60dd7 2890 if (memcmp(server_ptr, guest_ptr, _cmp_bytes) == 0) {
12b316d4
PL
2891 continue;
2892 }
bea60dd7 2893 memcpy(server_ptr, guest_ptr, _cmp_bytes);
12b316d4
PL
2894 if (!vd->non_adaptive) {
2895 vnc_rect_updated(vd, x * VNC_DIRTY_PIXELS_PER_BIT,
2896 y, &tv);
1fc62412 2897 }
12b316d4
PL
2898 QTAILQ_FOREACH(vs, &vd->clients, next) {
2899 set_bit(x, vs->dirty[y]);
2900 }
2901 has_dirty++;
1fc62412 2902 }
12b316d4
PL
2903
2904 y++;
1fc62412 2905 }
9f64916d 2906 qemu_pixman_image_unref(tmpbuf);
1fc62412
SS
2907 return has_dirty;
2908}
2909
0f7b2864 2910static void vnc_refresh(DisplayChangeListener *dcl)
703bc68f 2911{
0f7b2864 2912 VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
41b4bef6
AS
2913 VncState *vs, *vn;
2914 int has_dirty, rects = 0;
703bc68f 2915
9d6b2070
C
2916 if (QTAILQ_EMPTY(&vd->clients)) {
2917 update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_MAX);
2918 return;
2919 }
2920
1d0d59fe 2921 graphic_hw_update(vd->dcl.con);
703bc68f 2922
bd023f95 2923 if (vnc_trylock_display(vd)) {
0f7b2864 2924 update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
bd023f95
CC
2925 return;
2926 }
2927
1fc62412 2928 has_dirty = vnc_refresh_server_surface(vd);
bd023f95 2929 vnc_unlock_display(vd);
1fc62412 2930
41b4bef6 2931 QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
38ee14f4 2932 rects += vnc_update_client(vs, has_dirty, false);
6185c578 2933 /* vs might be free()ed here */
703bc68f 2934 }
bd023f95 2935
2430ffe4 2936 if (has_dirty && rects) {
0f7b2864
GH
2937 vd->dcl.update_interval /= 2;
2938 if (vd->dcl.update_interval < VNC_REFRESH_INTERVAL_BASE) {
2939 vd->dcl.update_interval = VNC_REFRESH_INTERVAL_BASE;
2940 }
2430ffe4 2941 } else {
0f7b2864
GH
2942 vd->dcl.update_interval += VNC_REFRESH_INTERVAL_INC;
2943 if (vd->dcl.update_interval > VNC_REFRESH_INTERVAL_MAX) {
2944 vd->dcl.update_interval = VNC_REFRESH_INTERVAL_MAX;
2945 }
703bc68f
SS
2946 }
2947}
2948
04d2529d 2949static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
2c8cf549 2950 bool skipauth, bool websocket)
3aa3eea3 2951{
fedf0d35 2952 VncState *vs = g_new0(VncState, 1);
90cd03a3 2953 bool first_client = QTAILQ_EMPTY(&vd->clients);
7d964c9d
CC
2954 int i;
2955
04d2529d
DB
2956 vs->sioc = sioc;
2957 object_ref(OBJECT(vs->sioc));
2958 vs->ioc = QIO_CHANNEL(sioc);
2959 object_ref(OBJECT(vs->ioc));
d616ccc5 2960 vs->vd = vd;
7e7e2ebc 2961
04d2529d
DB
2962 buffer_init(&vs->input, "vnc-input/%p", sioc);
2963 buffer_init(&vs->output, "vnc-output/%p", sioc);
04d2529d 2964 buffer_init(&vs->jobs_buffer, "vnc-jobs_buffer/%p", sioc);
543b9580 2965
04d2529d
DB
2966 buffer_init(&vs->tight.tight, "vnc-tight/%p", sioc);
2967 buffer_init(&vs->tight.zlib, "vnc-tight-zlib/%p", sioc);
2968 buffer_init(&vs->tight.gradient, "vnc-tight-gradient/%p", sioc);
543b9580 2969#ifdef CONFIG_VNC_JPEG
04d2529d 2970 buffer_init(&vs->tight.jpeg, "vnc-tight-jpeg/%p", sioc);
543b9580
GH
2971#endif
2972#ifdef CONFIG_VNC_PNG
04d2529d 2973 buffer_init(&vs->tight.png, "vnc-tight-png/%p", sioc);
543b9580 2974#endif
04d2529d
DB
2975 buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc);
2976 buffer_init(&vs->zrle.zrle, "vnc-zrle/%p", sioc);
2977 buffer_init(&vs->zrle.fb, "vnc-zrle-fb/%p", sioc);
2978 buffer_init(&vs->zrle.zlib, "vnc-zrle-zlib/%p", sioc);
543b9580 2979
7e7e2ebc
DB
2980 if (skipauth) {
2981 vs->auth = VNC_AUTH_NONE;
7e7e2ebc 2982 vs->subauth = VNC_AUTH_INVALID;
7e7e2ebc 2983 } else {
f9148c8a
DB
2984 if (websocket) {
2985 vs->auth = vd->ws_auth;
2986 vs->subauth = VNC_AUTH_INVALID;
2987 } else {
2988 vs->auth = vd->auth;
2989 vs->subauth = vd->subauth;
2990 }
7e7e2ebc 2991 }
04d2529d
DB
2992 VNC_DEBUG("Client sioc=%p ws=%d auth=%d subauth=%d\n",
2993 sioc, websocket, vs->auth, vs->subauth);
7e7e2ebc 2994
7267c094 2995 vs->lossy_rect = g_malloc0(VNC_STAT_ROWS * sizeof (*vs->lossy_rect));
7d964c9d 2996 for (i = 0; i < VNC_STAT_ROWS; ++i) {
fedf0d35 2997 vs->lossy_rect[i] = g_new0(uint8_t, VNC_STAT_COLS);
7d964c9d 2998 }
753b4053 2999
04d2529d 3000 VNC_DEBUG("New client on socket %p\n", vs->sioc);
0f7b2864 3001 update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
04d2529d 3002 qio_channel_set_blocking(vs->ioc, false, NULL);
7536ee4b
TH
3003 if (websocket) {
3004 vs->websocket = 1;
38e5756a 3005 if (vd->tlscreds) {
04d2529d
DB
3006 vs->ioc_tag = qio_channel_add_watch(
3007 vs->ioc, G_IO_IN, vncws_tls_handshake_io, vs, NULL);
3e305e4a 3008 } else {
04d2529d
DB
3009 vs->ioc_tag = qio_channel_add_watch(
3010 vs->ioc, G_IO_IN, vncws_handshake_io, vs, NULL);
0057a0d5 3011 }
04d2529d
DB
3012 } else {
3013 vs->ioc_tag = qio_channel_add_watch(
3014 vs->ioc, G_IO_IN, vnc_client_io, vs, NULL);
7536ee4b 3015 }
753b4053 3016
4a80dba3 3017 vnc_client_cache_addr(vs);
fb6ba0d5 3018 vnc_qmp_event(vs, QAPI_EVENT_VNC_CONNECTED);
8cf36489 3019 vnc_set_share_mode(vs, VNC_SHARE_MODE_CONNECTING);
4a80dba3 3020
753b4053
AL
3021 vs->last_x = -1;
3022 vs->last_y = -1;
3023
3024 vs->as.freq = 44100;
3025 vs->as.nchannels = 2;
3026 vs->as.fmt = AUD_FMT_S16;
3027 vs->as.endianness = 0;
3028
bd023f95 3029 qemu_mutex_init(&vs->output_mutex);
175b2a6e 3030 vs->bh = qemu_bh_new(vnc_jobs_bh, vs);
bd023f95 3031
e5f34cdd 3032 QTAILQ_INSERT_TAIL(&vd->clients, vs, next);
c7628bff
GH
3033 if (first_client) {
3034 vnc_update_server_surface(vd);
3035 }
1fc62412 3036
1d0d59fe 3037 graphic_hw_update(vd->dcl.con);
1fc62412 3038
90cd03a3 3039 if (!vs->websocket) {
dbee9897 3040 vnc_start_protocol(vs);
90cd03a3
DB
3041 }
3042
3043 if (vd->num_connecting > vd->connections_limit) {
3044 QTAILQ_FOREACH(vs, &vd->clients, next) {
3045 if (vs->share_mode == VNC_SHARE_MODE_CONNECTING) {
3046 vnc_disconnect_start(vs);
3047 return;
3048 }
3049 }
3050 }
3051}
3052
dbee9897 3053void vnc_start_protocol(VncState *vs)
90cd03a3 3054{
3aa3eea3
AZ
3055 vnc_write(vs, "RFB 003.008\n", 12);
3056 vnc_flush(vs);
3057 vnc_read_when(vs, protocol_version, 12);
753b4053 3058
37c34d9d
AL
3059 vs->mouse_mode_notifier.notify = check_pointer_type_change;
3060 qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
3aa3eea3
AZ
3061}
3062
04d2529d
DB
3063static gboolean vnc_listen_io(QIOChannel *ioc,
3064 GIOCondition condition,
3065 void *opaque)
24236869 3066{
bf01c179 3067 VncDisplay *vd = opaque;
04d2529d
DB
3068 QIOChannelSocket *sioc = NULL;
3069 Error *err = NULL;
24236869 3070
04d2529d
DB
3071 sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc), &err);
3072 if (sioc != NULL) {
10bcfe58
DB
3073 qio_channel_set_name(QIO_CHANNEL(sioc),
3074 ioc != QIO_CHANNEL(vd->lsock) ?
3075 "vnc-ws-server" : "vnc-server");
04d2529d 3076 qio_channel_set_delay(QIO_CHANNEL(sioc), false);
bf01c179
DB
3077 vnc_connect(vd, sioc, false,
3078 ioc != QIO_CHANNEL(vd->lsock));
04d2529d 3079 object_unref(OBJECT(sioc));
8e9b0d24 3080 } else {
04d2529d
DB
3081 /* client probably closed connection before we got there */
3082 error_free(err);
24236869 3083 }
7536ee4b 3084
04d2529d 3085 return TRUE;
7536ee4b 3086}
7536ee4b 3087
7c20b4a3 3088static const DisplayChangeListenerOps dcl_ops = {
34da30af
BH
3089 .dpy_name = "vnc",
3090 .dpy_refresh = vnc_refresh,
3091 .dpy_gfx_copy = vnc_dpy_copy,
3092 .dpy_gfx_update = vnc_dpy_update,
3093 .dpy_gfx_switch = vnc_dpy_switch,
3094 .dpy_gfx_check_format = qemu_pixman_check_format,
3095 .dpy_mouse_set = vnc_mouse_set,
3096 .dpy_cursor_define = vnc_dpy_cursor_define,
7c20b4a3
GH
3097};
3098
14f7143e 3099void vnc_display_init(const char *id)
24236869 3100{
bf01c179 3101 VncDisplay *vd;
4db14629
GH
3102
3103 if (vnc_display_find(id) != NULL) {
3104 return;
3105 }
bf01c179 3106 vd = g_malloc0(sizeof(*vd));
24236869 3107
bf01c179
DB
3108 vd->id = strdup(id);
3109 QTAILQ_INSERT_TAIL(&vnc_displays, vd, next);
24236869 3110
bf01c179
DB
3111 QTAILQ_INIT(&vd->clients);
3112 vd->expires = TIME_MAX;
24236869 3113
40066175
GH
3114 if (keyboard_layout) {
3115 trace_vnc_key_map_init(keyboard_layout);
bf01c179 3116 vd->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
40066175 3117 } else {
bf01c179 3118 vd->kbd_layout = init_keyboard_layout(name2keysym, "en-us");
40066175 3119 }
24236869 3120
bf01c179 3121 if (!vd->kbd_layout) {
28a76be8 3122 exit(1);
bf01c179 3123 }
24236869 3124
bf01c179
DB
3125 vd->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
3126 vd->connections_limit = 32;
12e29b16 3127
bf01c179 3128 qemu_mutex_init(&vd->mutex);
bd023f95 3129 vnc_start_worker_thread();
bd023f95 3130
bf01c179
DB
3131 vd->dcl.ops = &dcl_ops;
3132 register_displaychangelistener(&vd->dcl);
71cab5ca
TS
3133}
3134
6f43024c 3135
bf01c179 3136static void vnc_display_close(VncDisplay *vd)
71cab5ca 3137{
bf01c179 3138 if (!vd) {
452b4d88 3139 return;
bf01c179
DB
3140 }
3141 vd->is_unix = false;
3142 if (vd->lsock != NULL) {
3143 if (vd->lsock_tag) {
3144 g_source_remove(vd->lsock_tag);
04d2529d 3145 }
bf01c179
DB
3146 object_unref(OBJECT(vd->lsock));
3147 vd->lsock = NULL;
71cab5ca 3148 }
bf01c179
DB
3149 if (vd->lwebsock != NULL) {
3150 if (vd->lwebsock_tag) {
3151 g_source_remove(vd->lwebsock_tag);
04d2529d 3152 }
bf01c179
DB
3153 object_unref(OBJECT(vd->lwebsock));
3154 vd->lwebsock = NULL;
7536ee4b 3155 }
bf01c179
DB
3156 vd->auth = VNC_AUTH_INVALID;
3157 vd->subauth = VNC_AUTH_INVALID;
3158 if (vd->tlscreds) {
3159 object_unparent(OBJECT(vd->tlscreds));
3160 vd->tlscreds = NULL;
3e305e4a 3161 }
bf01c179
DB
3162 g_free(vd->tlsaclname);
3163 vd->tlsaclname = NULL;
a54f0d2b
PO
3164 if (vd->lock_key_sync) {
3165 qemu_remove_led_event_handler(vd->led);
3166 }
70848515
TS
3167}
3168
14f7143e 3169int vnc_display_password(const char *id, const char *password)
70848515 3170{
bf01c179 3171 VncDisplay *vd = vnc_display_find(id);
70848515 3172
bf01c179 3173 if (!vd) {
a6aa9d3e 3174 return -EINVAL;
7ef92331 3175 }
bf01c179 3176 if (vd->auth == VNC_AUTH_NONE) {
cf864569 3177 error_printf_unless_qmp("If you want use passwords please enable "
7ea7d36e 3178 "password auth using '-vnc ${dpy},password'.\n");
cf864569 3179 return -EINVAL;
1cd20f8b
AL
3180 }
3181
bf01c179
DB
3182 g_free(vd->password);
3183 vd->password = g_strdup(password);
a6aa9d3e
LC
3184
3185 return 0;
71cab5ca
TS
3186}
3187
14f7143e 3188int vnc_display_pw_expire(const char *id, time_t expires)
3c9405a0 3189{
bf01c179 3190 VncDisplay *vd = vnc_display_find(id);
3c9405a0 3191
bf01c179 3192 if (!vd) {
1643f2b2
GH
3193 return -EINVAL;
3194 }
3195
bf01c179 3196 vd->expires = expires;
3c9405a0
GH
3197 return 0;
3198}
3199
bf01c179 3200static void vnc_display_print_local_addr(VncDisplay *vd)
f92f8afe 3201{
04d2529d 3202 SocketAddress *addr;
04d2529d 3203 Error *err = NULL;
d616ccc5 3204
bf01c179 3205 addr = qio_channel_socket_get_local_address(vd->lsock, &err);
04d2529d 3206 if (!addr) {
33df7bf3 3207 return;
04d2529d
DB
3208 }
3209
3210 if (addr->type != SOCKET_ADDRESS_KIND_INET) {
3211 qapi_free_SocketAddress(addr);
33df7bf3 3212 return;
04d2529d 3213 }
33df7bf3
PB
3214 error_printf_unless_qmp("VNC server running on %s:%s\n",
3215 addr->u.inet.data->host,
3216 addr->u.inet.data->port);
04d2529d 3217 qapi_free_SocketAddress(addr);
f92f8afe
AL
3218}
3219
4db14629
GH
3220static QemuOptsList qemu_vnc_opts = {
3221 .name = "vnc",
3222 .head = QTAILQ_HEAD_INITIALIZER(qemu_vnc_opts.head),
3223 .implied_opt_name = "vnc",
3224 .desc = {
3225 {
3226 .name = "vnc",
3227 .type = QEMU_OPT_STRING,
3228 },{
3229 .name = "websocket",
3230 .type = QEMU_OPT_STRING,
3231 },{
3e305e4a
DB
3232 .name = "tls-creds",
3233 .type = QEMU_OPT_STRING,
3234 },{
3235 /* Deprecated in favour of tls-creds */
4db14629
GH
3236 .name = "x509",
3237 .type = QEMU_OPT_STRING,
3238 },{
3239 .name = "share",
3240 .type = QEMU_OPT_STRING,
1d0d59fe
GH
3241 },{
3242 .name = "display",
3243 .type = QEMU_OPT_STRING,
3244 },{
3245 .name = "head",
3246 .type = QEMU_OPT_NUMBER,
e5f34cdd
GH
3247 },{
3248 .name = "connections",
3249 .type = QEMU_OPT_NUMBER,
88428b7a
GA
3250 },{
3251 .name = "to",
3252 .type = QEMU_OPT_NUMBER,
3253 },{
3254 .name = "ipv4",
3255 .type = QEMU_OPT_BOOL,
3256 },{
3257 .name = "ipv6",
3258 .type = QEMU_OPT_BOOL,
4db14629
GH
3259 },{
3260 .name = "password",
3261 .type = QEMU_OPT_BOOL,
3262 },{
3263 .name = "reverse",
3264 .type = QEMU_OPT_BOOL,
3265 },{
3266 .name = "lock-key-sync",
3267 .type = QEMU_OPT_BOOL,
c5ce8333
GH
3268 },{
3269 .name = "key-delay-ms",
3270 .type = QEMU_OPT_NUMBER,
4db14629
GH
3271 },{
3272 .name = "sasl",
3273 .type = QEMU_OPT_BOOL,
3274 },{
3e305e4a 3275 /* Deprecated in favour of tls-creds */
4db14629
GH
3276 .name = "tls",
3277 .type = QEMU_OPT_BOOL,
3278 },{
3e305e4a 3279 /* Deprecated in favour of tls-creds */
4db14629 3280 .name = "x509verify",
8c7d0645 3281 .type = QEMU_OPT_STRING,
4db14629
GH
3282 },{
3283 .name = "acl",
3284 .type = QEMU_OPT_BOOL,
3285 },{
3286 .name = "lossy",
3287 .type = QEMU_OPT_BOOL,
3288 },{
3289 .name = "non-adaptive",
3290 .type = QEMU_OPT_BOOL,
3291 },
3292 { /* end of list */ }
3293 },
3294};
3295
0dd72e15 3296
3e305e4a 3297static int
eda24e18
DB
3298vnc_display_setup_auth(int *auth,
3299 int *subauth,
3300 QCryptoTLSCreds *tlscreds,
0dd72e15
DB
3301 bool password,
3302 bool sasl,
3e305e4a
DB
3303 bool websocket,
3304 Error **errp)
0dd72e15
DB
3305{
3306 /*
3307 * We have a choice of 3 authentication options
3308 *
3309 * 1. none
3310 * 2. vnc
3311 * 3. sasl
3312 *
3313 * The channel can be run in 2 modes
3314 *
3315 * 1. clear
3316 * 2. tls
3317 *
3318 * And TLS can use 2 types of credentials
3319 *
3320 * 1. anon
3321 * 2. x509
3322 *
3323 * We thus have 9 possible logical combinations
3324 *
3325 * 1. clear + none
3326 * 2. clear + vnc
3327 * 3. clear + sasl
3328 * 4. tls + anon + none
3329 * 5. tls + anon + vnc
3330 * 6. tls + anon + sasl
3331 * 7. tls + x509 + none
3332 * 8. tls + x509 + vnc
3333 * 9. tls + x509 + sasl
3334 *
3335 * These need to be mapped into the VNC auth schemes
3336 * in an appropriate manner. In regular VNC, all the
3337 * TLS options get mapped into VNC_AUTH_VENCRYPT
3338 * sub-auth types.
f9148c8a
DB
3339 *
3340 * In websockets, the https:// protocol already provides
3341 * TLS support, so there is no need to make use of the
3342 * VeNCrypt extension. Furthermore, websockets browser
3343 * clients could not use VeNCrypt even if they wanted to,
3344 * as they cannot control when the TLS handshake takes
3345 * place. Thus there is no option but to rely on https://,
3346 * meaning combinations 4->6 and 7->9 will be mapped to
3347 * VNC auth schemes in the same way as combos 1->3.
3348 *
3349 * Regardless of fact that we have a different mapping to
3350 * VNC auth mechs for plain VNC vs websockets VNC, the end
3351 * result has the same security characteristics.
0dd72e15 3352 */
eda24e18
DB
3353 if (websocket || !tlscreds) {
3354 if (password) {
0dd72e15 3355 VNC_DEBUG("Initializing VNC server with password auth\n");
eda24e18
DB
3356 *auth = VNC_AUTH_VNC;
3357 } else if (sasl) {
3358 VNC_DEBUG("Initializing VNC server with SASL auth\n");
3359 *auth = VNC_AUTH_SASL;
f9148c8a 3360 } else {
eda24e18
DB
3361 VNC_DEBUG("Initializing VNC server with no auth\n");
3362 *auth = VNC_AUTH_NONE;
f9148c8a 3363 }
eda24e18
DB
3364 *subauth = VNC_AUTH_INVALID;
3365 } else {
3366 bool is_x509 = object_dynamic_cast(OBJECT(tlscreds),
3367 TYPE_QCRYPTO_TLS_CREDS_X509) != NULL;
3368 bool is_anon = object_dynamic_cast(OBJECT(tlscreds),
3369 TYPE_QCRYPTO_TLS_CREDS_ANON) != NULL;
3370
3371 if (!is_x509 && !is_anon) {
3372 error_setg(errp,
3373 "Unsupported TLS cred type %s",
3374 object_get_typename(OBJECT(tlscreds)));
3375 return -1;
3376 }
3377 *auth = VNC_AUTH_VENCRYPT;
3378 if (password) {
3379 if (is_x509) {
3380 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
3381 *subauth = VNC_AUTH_VENCRYPT_X509VNC;
3382 } else {
3383 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
3384 *subauth = VNC_AUTH_VENCRYPT_TLSVNC;
3385 }
3386
3387 } else if (sasl) {
3388 if (is_x509) {
0dd72e15 3389 VNC_DEBUG("Initializing VNC server with x509 SASL auth\n");
eda24e18 3390 *subauth = VNC_AUTH_VENCRYPT_X509SASL;
3e305e4a 3391 } else {
eda24e18
DB
3392 VNC_DEBUG("Initializing VNC server with TLS SASL auth\n");
3393 *subauth = VNC_AUTH_VENCRYPT_TLSSASL;
0dd72e15
DB
3394 }
3395 } else {
eda24e18 3396 if (is_x509) {
0dd72e15 3397 VNC_DEBUG("Initializing VNC server with x509 no auth\n");
eda24e18 3398 *subauth = VNC_AUTH_VENCRYPT_X509NONE;
3e305e4a 3399 } else {
eda24e18
DB
3400 VNC_DEBUG("Initializing VNC server with TLS no auth\n");
3401 *subauth = VNC_AUTH_VENCRYPT_TLSNONE;
0dd72e15 3402 }
f9148c8a 3403 }
0dd72e15 3404 }
3e305e4a
DB
3405 return 0;
3406}
3407
3408
3409/*
3410 * Handle back compat with old CLI syntax by creating some
3411 * suitable QCryptoTLSCreds objects
3412 */
3413static QCryptoTLSCreds *
3414vnc_display_create_creds(bool x509,
3415 bool x509verify,
3416 const char *dir,
3417 const char *id,
3418 Error **errp)
3419{
3420 gchar *credsid = g_strdup_printf("tlsvnc%s", id);
3421 Object *parent = object_get_objects_root();
3422 Object *creds;
3423 Error *err = NULL;
3424
3425 if (x509) {
3426 creds = object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_X509,
3427 parent,
3428 credsid,
3429 &err,
3430 "endpoint", "server",
3431 "dir", dir,
3432 "verify-peer", x509verify ? "yes" : "no",
3433 NULL);
3434 } else {
3435 creds = object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_ANON,
3436 parent,
3437 credsid,
3438 &err,
3439 "endpoint", "server",
3440 NULL);
3441 }
3442
3443 g_free(credsid);
3444
3445 if (err) {
3446 error_propagate(errp, err);
3447 return NULL;
3448 }
3449
3450 return QCRYPTO_TLS_CREDS(creds);
0dd72e15
DB
3451}
3452
3e305e4a 3453
4db14629 3454void vnc_display_open(const char *id, Error **errp)
71cab5ca 3455{
bf01c179 3456 VncDisplay *vd = vnc_display_find(id);
4db14629 3457 QemuOpts *opts = qemu_opts_find(&qemu_vnc_opts, id);
e0d03b8c 3458 SocketAddress *saddr = NULL, *wsaddr = NULL;
e2a11d9d 3459 const char *share, *device_id;
1d0d59fe 3460 QemuConsole *con;
a2c72de0
GA
3461 bool password = false;
3462 bool reverse = false;
e2a11d9d 3463 const char *vnc;
e5560329 3464 char *h;
3e305e4a 3465 const char *credid;
33df7bf3 3466 int show_vnc_port = 0;
a2c72de0 3467 bool sasl = false;
d169f04b 3468#ifdef CONFIG_VNC_SASL
2f9606b3
AL
3469 int saslErr;
3470#endif
76655d6d 3471 int acl = 0;
3a0558b5 3472 int lock_key_sync = 1;
c5ce8333 3473 int key_delay_ms;
12b28067 3474 bool ws_enabled = false;
71cab5ca 3475
bf01c179 3476 if (!vd) {
2d55f0e8
PB
3477 error_setg(errp, "VNC display not active");
3478 return;
3479 }
bf01c179 3480 vnc_display_close(vd);
24236869 3481
4db14629
GH
3482 if (!opts) {
3483 return;
3484 }
e2a11d9d
GA
3485 vnc = qemu_opt_get(opts, "vnc");
3486 if (!vnc || strcmp(vnc, "none") == 0) {
4db14629
GH
3487 return;
3488 }
e2a11d9d 3489
e5560329
GH
3490 h = strrchr(vnc, ':');
3491 if (h) {
274c3b52
JT
3492 size_t hlen = h - vnc;
3493
e0d03b8c
DB
3494 const char *websocket = qemu_opt_get(opts, "websocket");
3495 int to = qemu_opt_get_number(opts, "to", 0);
3f0230e9
DB
3496 bool has_ipv4 = qemu_opt_get(opts, "ipv4");
3497 bool has_ipv6 = qemu_opt_get(opts, "ipv6");
3498 bool ipv4 = qemu_opt_get_bool(opts, "ipv4", false);
3499 bool ipv6 = qemu_opt_get_bool(opts, "ipv6", false);
e0d03b8c
DB
3500
3501 saddr = g_new0(SocketAddress, 1);
3502 if (websocket) {
3503 if (!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1)) {
3504 error_setg(errp,
3505 "SHA1 hash support is required for websockets");
3506 goto fail;
3507 }
3508
3509 wsaddr = g_new0(SocketAddress, 1);
12b28067 3510 ws_enabled = true;
e0d03b8c
DB
3511 }
3512
3513 if (strncmp(vnc, "unix:", 5) == 0) {
2d32adda 3514 saddr->type = SOCKET_ADDRESS_KIND_UNIX;
32bafa8f
EB
3515 saddr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
3516 saddr->u.q_unix.data->path = g_strdup(vnc + 5);
e0d03b8c 3517
12b28067 3518 if (ws_enabled) {
e0d03b8c
DB
3519 error_setg(errp, "UNIX sockets not supported with websock");
3520 goto fail;
3521 }
274c3b52 3522 } else {
e0d03b8c 3523 unsigned long long baseport;
0399293e 3524 InetSocketAddress *inet;
2d32adda 3525 saddr->type = SOCKET_ADDRESS_KIND_INET;
32bafa8f 3526 inet = saddr->u.inet.data = g_new0(InetSocketAddress, 1);
e0d03b8c 3527 if (vnc[0] == '[' && vnc[hlen - 1] == ']') {
0399293e 3528 inet->host = g_strndup(vnc + 1, hlen - 2);
e0d03b8c 3529 } else {
0399293e 3530 inet->host = g_strndup(vnc, hlen);
e0d03b8c
DB
3531 }
3532 if (parse_uint_full(h + 1, &baseport, 10) < 0) {
3533 error_setg(errp, "can't convert to a number: %s", h + 1);
3534 goto fail;
3535 }
3536 if (baseport > 65535 ||
3537 baseport + 5900 > 65535) {
3538 error_setg(errp, "port %s out of range", h + 1);
3539 goto fail;
3540 }
0399293e 3541 inet->port = g_strdup_printf(
e0d03b8c
DB
3542 "%d", (int)baseport + 5900);
3543
3544 if (to) {
0399293e
EB
3545 inet->has_to = true;
3546 inet->to = to + 5900;
33df7bf3 3547 show_vnc_port = 1;
e0d03b8c 3548 }
0399293e
EB
3549 inet->ipv4 = ipv4;
3550 inet->has_ipv4 = has_ipv4;
3551 inet->ipv6 = ipv6;
3552 inet->has_ipv6 = has_ipv6;
e0d03b8c 3553
12b28067 3554 if (ws_enabled) {
2d32adda 3555 wsaddr->type = SOCKET_ADDRESS_KIND_INET;
32bafa8f
EB
3556 inet = wsaddr->u.inet.data = g_new0(InetSocketAddress, 1);
3557 inet->host = g_strdup(saddr->u.inet.data->host);
0399293e 3558 inet->port = g_strdup(websocket);
e0d03b8c
DB
3559
3560 if (to) {
0399293e
EB
3561 inet->has_to = true;
3562 inet->to = to;
e0d03b8c 3563 }
0399293e
EB
3564 inet->ipv4 = ipv4;
3565 inet->has_ipv4 = has_ipv4;
3566 inet->ipv6 = ipv6;
3567 inet->has_ipv6 = has_ipv6;
e0d03b8c 3568 }
274c3b52 3569 }
e5560329
GH
3570 } else {
3571 error_setg(errp, "no vnc port specified");
3572 goto fail;
e2a11d9d 3573 }
e5560329 3574
4db14629 3575 password = qemu_opt_get_bool(opts, "password", false);
800567a6
DB
3576 if (password) {
3577 if (fips_get_state()) {
3578 error_setg(errp,
3579 "VNC password auth disabled due to FIPS mode, "
3580 "consider using the VeNCrypt or SASL authentication "
3581 "methods as an alternative");
3582 goto fail;
3583 }
3584 if (!qcrypto_cipher_supports(
f844836d 3585 QCRYPTO_CIPHER_ALG_DES_RFB, QCRYPTO_CIPHER_MODE_ECB)) {
800567a6
DB
3586 error_setg(errp,
3587 "Cipher backend does not support DES RFB algorithm");
3588 goto fail;
3589 }
4db14629
GH
3590 }
3591
3592 reverse = qemu_opt_get_bool(opts, "reverse", false);
3593 lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true);
c5ce8333 3594 key_delay_ms = qemu_opt_get_number(opts, "key-delay-ms", 1);
4db14629 3595 sasl = qemu_opt_get_bool(opts, "sasl", false);
d169f04b
DB
3596#ifndef CONFIG_VNC_SASL
3597 if (sasl) {
3598 error_setg(errp, "VNC SASL auth requires cyrus-sasl support");
3599 goto fail;
3600 }
3601#endif /* CONFIG_VNC_SASL */
3e305e4a
DB
3602 credid = qemu_opt_get(opts, "tls-creds");
3603 if (credid) {
3604 Object *creds;
3605 if (qemu_opt_get(opts, "tls") ||
3606 qemu_opt_get(opts, "x509") ||
3607 qemu_opt_get(opts, "x509verify")) {
3608 error_setg(errp,
c62e90af 3609 "'tls-creds' parameter is mutually exclusive with "
3e305e4a 3610 "'tls', 'x509' and 'x509verify' parameters");
4db14629
GH
3611 goto fail;
3612 }
3e305e4a
DB
3613
3614 creds = object_resolve_path_component(
3615 object_get_objects_root(), credid);
3616 if (!creds) {
3617 error_setg(errp, "No TLS credentials with id '%s'",
3618 credid);
3619 goto fail;
3620 }
bf01c179 3621 vd->tlscreds = (QCryptoTLSCreds *)
3e305e4a
DB
3622 object_dynamic_cast(creds,
3623 TYPE_QCRYPTO_TLS_CREDS);
bf01c179 3624 if (!vd->tlscreds) {
3e305e4a
DB
3625 error_setg(errp, "Object with id '%s' is not TLS credentials",
3626 credid);
3627 goto fail;
3628 }
bf01c179 3629 object_ref(OBJECT(vd->tlscreds));
3e305e4a 3630
bf01c179 3631 if (vd->tlscreds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
3e305e4a
DB
3632 error_setg(errp,
3633 "Expecting TLS credentials with a server endpoint");
3634 goto fail;
3635 }
3636 } else {
3637 const char *path;
3638 bool tls = false, x509 = false, x509verify = false;
3639 tls = qemu_opt_get_bool(opts, "tls", false);
3640 if (tls) {
3641 path = qemu_opt_get(opts, "x509");
3642
3643 if (path) {
3644 x509 = true;
3645 } else {
3646 path = qemu_opt_get(opts, "x509verify");
3647 if (path) {
3648 x509 = true;
3649 x509verify = true;
3650 }
3651 }
bf01c179 3652 vd->tlscreds = vnc_display_create_creds(x509,
3e305e4a
DB
3653 x509verify,
3654 path,
bf01c179 3655 vd->id,
3e305e4a 3656 errp);
bf01c179 3657 if (!vd->tlscreds) {
3e305e4a
DB
3658 goto fail;
3659 }
3660 }
4db14629 3661 }
4db14629 3662 acl = qemu_opt_get_bool(opts, "acl", false);
4db14629
GH
3663
3664 share = qemu_opt_get(opts, "share");
3665 if (share) {
3666 if (strcmp(share, "ignore") == 0) {
bf01c179 3667 vd->share_policy = VNC_SHARE_POLICY_IGNORE;
4db14629 3668 } else if (strcmp(share, "allow-exclusive") == 0) {
bf01c179 3669 vd->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
4db14629 3670 } else if (strcmp(share, "force-shared") == 0) {
bf01c179 3671 vd->share_policy = VNC_SHARE_POLICY_FORCE_SHARED;
4db14629
GH
3672 } else {
3673 error_setg(errp, "unknown vnc share= option");
3674 goto fail;
3675 }
3676 } else {
bf01c179 3677 vd->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
4db14629 3678 }
bf01c179 3679 vd->connections_limit = qemu_opt_get_number(opts, "connections", 32);
4db14629 3680
4db14629 3681#ifdef CONFIG_VNC_JPEG
bf01c179 3682 vd->lossy = qemu_opt_get_bool(opts, "lossy", false);
4db14629 3683#endif
bf01c179 3684 vd->non_adaptive = qemu_opt_get_bool(opts, "non-adaptive", false);
e22492d3
PL
3685 /* adaptive updates are only used with tight encoding and
3686 * if lossy updates are enabled so we can disable all the
3687 * calculations otherwise */
bf01c179
DB
3688 if (!vd->lossy) {
3689 vd->non_adaptive = true;
e22492d3
PL
3690 }
3691
3e305e4a 3692 if (acl) {
bf01c179
DB
3693 if (strcmp(vd->id, "default") == 0) {
3694 vd->tlsaclname = g_strdup("vnc.x509dname");
c8496408 3695 } else {
bf01c179 3696 vd->tlsaclname = g_strdup_printf("vnc.%s.x509dname", vd->id);
c8496408 3697 }
bf01c179 3698 qemu_acl_init(vd->tlsaclname);
2cc45228 3699 }
76655d6d
AL
3700#ifdef CONFIG_VNC_SASL
3701 if (acl && sasl) {
c8496408
GH
3702 char *aclname;
3703
bf01c179 3704 if (strcmp(vd->id, "default") == 0) {
c8496408
GH
3705 aclname = g_strdup("vnc.username");
3706 } else {
bf01c179 3707 aclname = g_strdup_printf("vnc.%s.username", vd->id);
c8496408 3708 }
bf01c179 3709 vd->sasl.acl = qemu_acl_init(aclname);
c8496408 3710 g_free(aclname);
76655d6d
AL
3711 }
3712#endif
3713
eda24e18
DB
3714 if (vnc_display_setup_auth(&vd->auth, &vd->subauth,
3715 vd->tlscreds, password,
3716 sasl, false, errp) < 0) {
3717 goto fail;
3718 }
3719
3720 if (vnc_display_setup_auth(&vd->ws_auth, &vd->ws_subauth,
3721 vd->tlscreds, password,
3722 sasl, true, errp) < 0) {
3e305e4a
DB
3723 goto fail;
3724 }
24236869 3725
2f9606b3
AL
3726#ifdef CONFIG_VNC_SASL
3727 if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) {
2d55f0e8
PB
3728 error_setg(errp, "Failed to initialize SASL auth: %s",
3729 sasl_errstring(saslErr, NULL, NULL));
1ce52c78 3730 goto fail;
2f9606b3
AL
3731 }
3732#endif
bf01c179 3733 vd->lock_key_sync = lock_key_sync;
a54f0d2b
PO
3734 if (lock_key_sync) {
3735 vd->led = qemu_add_led_event_handler(kbd_leds, vd);
3736 }
3737 vd->ledstate = 0;
bf01c179 3738 vd->key_delay_ms = key_delay_ms;
2f9606b3 3739
1d0d59fe
GH
3740 device_id = qemu_opt_get(opts, "display");
3741 if (device_id) {
1d0d59fe 3742 int head = qemu_opt_get_number(opts, "head", 0);
f2c1d54c 3743 Error *err = NULL;
1d0d59fe 3744
f2c1d54c
GH
3745 con = qemu_console_lookup_by_device_name(device_id, head, &err);
3746 if (err) {
3747 error_propagate(errp, err);
1d0d59fe
GH
3748 goto fail;
3749 }
3750 } else {
3751 con = NULL;
3752 }
3753
bf01c179
DB
3754 if (con != vd->dcl.con) {
3755 unregister_displaychangelistener(&vd->dcl);
3756 vd->dcl.con = con;
3757 register_displaychangelistener(&vd->dcl);
1d0d59fe
GH
3758 }
3759
3aa3eea3 3760 if (reverse) {
9712ecaf 3761 /* connect to viewer */
04d2529d 3762 QIOChannelSocket *sioc = NULL;
bf01c179
DB
3763 vd->lsock = NULL;
3764 vd->lwebsock = NULL;
12b28067 3765 if (ws_enabled) {
e0d03b8c
DB
3766 error_setg(errp, "Cannot use websockets in reverse mode");
3767 goto fail;
3aa3eea3 3768 }
bf01c179 3769 vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
04d2529d 3770 sioc = qio_channel_socket_new();
10bcfe58 3771 qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-reverse");
04d2529d 3772 if (qio_channel_socket_connect_sync(sioc, saddr, errp) < 0) {
007fcd3e
PB
3773 goto fail;
3774 }
bf01c179 3775 vnc_connect(vd, sioc, false, false);
04d2529d 3776 object_unref(OBJECT(sioc));
9712ecaf 3777 } else {
bf01c179 3778 vd->lsock = qio_channel_socket_new();
10bcfe58 3779 qio_channel_set_name(QIO_CHANNEL(vd->lsock), "vnc-listen");
bf01c179 3780 if (qio_channel_socket_listen_sync(vd->lsock, saddr, errp) < 0) {
e0d03b8c
DB
3781 goto fail;
3782 }
bf01c179 3783 vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
04d2529d 3784
12b28067 3785 if (ws_enabled) {
bf01c179 3786 vd->lwebsock = qio_channel_socket_new();
10bcfe58 3787 qio_channel_set_name(QIO_CHANNEL(vd->lwebsock), "vnc-ws-listen");
bf01c179 3788 if (qio_channel_socket_listen_sync(vd->lwebsock,
04d2529d 3789 wsaddr, errp) < 0) {
bf01c179
DB
3790 object_unref(OBJECT(vd->lsock));
3791 vd->lsock = NULL;
e0d03b8c 3792 goto fail;
7536ee4b 3793 }
9712ecaf 3794 }
04d2529d 3795
bf01c179
DB
3796 vd->lsock_tag = qio_channel_add_watch(
3797 QIO_CHANNEL(vd->lsock),
3798 G_IO_IN, vnc_listen_io, vd, NULL);
12b28067 3799 if (ws_enabled) {
bf01c179
DB
3800 vd->lwebsock_tag = qio_channel_add_watch(
3801 QIO_CHANNEL(vd->lwebsock),
3802 G_IO_IN, vnc_listen_io, vd, NULL);
7536ee4b 3803 }
24236869 3804 }
e0d03b8c 3805
33df7bf3 3806 if (show_vnc_port) {
bf01c179 3807 vnc_display_print_local_addr(vd);
33df7bf3
PB
3808 }
3809
e0d03b8c
DB
3810 qapi_free_SocketAddress(saddr);
3811 qapi_free_SocketAddress(wsaddr);
2d55f0e8 3812 return;
1ce52c78
PB
3813
3814fail:
e0d03b8c
DB
3815 qapi_free_SocketAddress(saddr);
3816 qapi_free_SocketAddress(wsaddr);
12b28067 3817 ws_enabled = false;
24236869 3818}
13661089 3819
14f7143e 3820void vnc_display_add_client(const char *id, int csock, bool skipauth)
13661089 3821{
bf01c179 3822 VncDisplay *vd = vnc_display_find(id);
04d2529d 3823 QIOChannelSocket *sioc;
13661089 3824
bf01c179 3825 if (!vd) {
d616ccc5
GH
3826 return;
3827 }
04d2529d
DB
3828
3829 sioc = qio_channel_socket_new_fd(csock, NULL);
3830 if (sioc) {
10bcfe58 3831 qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-server");
bf01c179 3832 vnc_connect(vd, sioc, skipauth, false);
04d2529d
DB
3833 object_unref(OBJECT(sioc));
3834 }
13661089 3835}
4db14629 3836
9634f4e3 3837static void vnc_auto_assign_id(QemuOptsList *olist, QemuOpts *opts)
2779672f
GA
3838{
3839 int i = 2;
3840 char *id;
3841
3842 id = g_strdup("default");
3843 while (qemu_opts_find(olist, id)) {
3844 g_free(id);
3845 id = g_strdup_printf("vnc%d", i++);
3846 }
3847 qemu_opts_set_id(opts, id);
3848}
3849
70b94331 3850QemuOpts *vnc_parse(const char *str, Error **errp)
4db14629 3851{
4db14629 3852 QemuOptsList *olist = qemu_find_opts("vnc");
70b94331 3853 QemuOpts *opts = qemu_opts_parse(olist, str, true, errp);
81607cbf 3854 const char *id;
4db14629 3855
81607cbf
GA
3856 if (!opts) {
3857 return NULL;
3858 }
3859
3860 id = qemu_opts_id(opts);
4db14629
GH
3861 if (!id) {
3862 /* auto-assign id if not present */
2779672f 3863 vnc_auto_assign_id(olist, opts);
4db14629 3864 }
9634f4e3
GH
3865 return opts;
3866}
3867
28d0de7a 3868int vnc_init_func(void *opaque, QemuOpts *opts, Error **errp)
9634f4e3
GH
3869{
3870 Error *local_err = NULL;
3871 char *id = (char *)qemu_opts_id(opts);
4db14629 3872
9634f4e3 3873 assert(id);
4db14629
GH
3874 vnc_display_init(id);
3875 vnc_display_open(id, &local_err);
3876 if (local_err != NULL) {
c29b77f9 3877 error_reportf_err(local_err, "Failed to start VNC server: ");
4db14629
GH
3878 exit(1);
3879 }
3880 return 0;
3881}
3882
3883static void vnc_register_config(void)
3884{
3885 qemu_add_opts(&qemu_vnc_opts);
3886}
34294e2f 3887opts_init(vnc_register_config);