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