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