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