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