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