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