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