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