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