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