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