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