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