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