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