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