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