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