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