ia64/xen-unstable

view tools/ioemu/vnc.c @ 17042:a905c582a406

Add stubdomain support. See stubdom/README for usage details.

- Move PAGE_SIZE and STACK_SIZE into __PAGE_SIZE and __STACK_SIZE in
arch_limits.h so as to permit getting them from there without
pulling all the internal Mini-OS defines.
- Setup a xen-elf cross-compilation environment in stubdom/cross-root
- Add a POSIX layer on top of Mini-OS by linking against the newlib C
library and lwIP, and implementing the Unixish part in mini-os/lib/sys.c
- Cross-compile zlib and libpci too.
- Add an xs.h-compatible layer on top of Mini-OS' xenbus.
- Cross-compile libxc with an additional xc_minios.c and a few things
disabled.
- Cross-compile ioemu with an additional block-vbd, but without sound,
tpm and other details. A few hacks are needed:
- Align ide and scsi buffers at least on sector size to permit
direct transmission to the block backend. While we are at it, just
page-align it to possibly save a segment. Also, limit the scsi
buffer size because of limitations of the block paravirtualization
protocol.
- Allocate big tables dynamically rather that letting them go to
bss: when Mini-OS gets installed in memory, bss is not lazily
allocated, and doing so during Mini-OS is unnecessarily trick while
we can simply use malloc.
- Had to change the Mini-OS compilation somehow, so as to export
Mini-OS compilation flags to the Makefiles of libxc and ioemu.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Feb 12 14:35:39 2008 +0000 (2008-02-12)
parents 7b0c0ab0566b
children c9d9bbf1204c
line source
1 /*
2 * QEMU VNC display driver
3 *
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
6 * Copyright (C) 2006 Christian Limpach <Christian.Limpach@xensource.com>
7 *
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 */
27 #include <sys/stat.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include "vl.h"
31 #include "qemu_socket.h"
32 #include <assert.h>
33 #ifdef CONFIG_STUBDOM
34 #include <netfront.h>
35 #endif
37 /* The refresh interval starts at BASE. If we scan the buffer and
38 find no change, we increase by INC, up to MAX. If the mouse moves
39 or we get a keypress, the interval is set back to BASE. If we find
40 an update, halve the interval.
42 All times in milliseconds. */
43 #define VNC_REFRESH_INTERVAL_BASE 30
44 #define VNC_REFRESH_INTERVAL_INC 50
45 #define VNC_REFRESH_INTERVAL_MAX 2000
47 /* Wait at most one second between updates, so that we can detect a
48 minimised vncviewer reasonably quickly. */
49 #define VNC_MAX_UPDATE_INTERVAL 5000
51 #include "vnc_keysym.h"
52 #include "keymaps.c"
53 #include "d3des.h"
55 #if CONFIG_VNC_TLS
56 #include <gnutls/gnutls.h>
57 #include <gnutls/x509.h>
58 #endif /* CONFIG_VNC_TLS */
60 // #define _VNC_DEBUG 1
62 #if _VNC_DEBUG
63 #define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
65 #if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
66 /* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
67 static void vnc_debug_gnutls_log(int level, const char* str) {
68 VNC_DEBUG("%d %s", level, str);
69 }
70 #endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
71 #else
72 #define VNC_DEBUG(fmt, ...) do { } while (0)
73 #endif
76 typedef struct Buffer
77 {
78 size_t capacity;
79 size_t offset;
80 uint8_t *buffer;
81 } Buffer;
83 typedef struct VncState VncState;
85 typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
87 typedef void VncWritePixels(VncState *vs, void *data, int size);
89 typedef void VncSendHextileTile(VncState *vs,
90 int x, int y, int w, int h,
91 void *last_bg,
92 void *last_fg,
93 int *has_bg, int *has_fg);
95 #if 0
96 #define VNC_MAX_WIDTH 2048
97 #define VNC_MAX_HEIGHT 2048
98 #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
99 #endif
101 #define VNC_AUTH_CHALLENGE_SIZE 16
103 enum {
104 VNC_AUTH_INVALID = 0,
105 VNC_AUTH_NONE = 1,
106 VNC_AUTH_VNC = 2,
107 VNC_AUTH_RA2 = 5,
108 VNC_AUTH_RA2NE = 6,
109 VNC_AUTH_TIGHT = 16,
110 VNC_AUTH_ULTRA = 17,
111 VNC_AUTH_TLS = 18,
112 VNC_AUTH_VENCRYPT = 19
113 };
115 #if CONFIG_VNC_TLS
116 enum {
117 VNC_WIREMODE_CLEAR,
118 VNC_WIREMODE_TLS,
119 };
121 enum {
122 VNC_AUTH_VENCRYPT_PLAIN = 256,
123 VNC_AUTH_VENCRYPT_TLSNONE = 257,
124 VNC_AUTH_VENCRYPT_TLSVNC = 258,
125 VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
126 VNC_AUTH_VENCRYPT_X509NONE = 260,
127 VNC_AUTH_VENCRYPT_X509VNC = 261,
128 VNC_AUTH_VENCRYPT_X509PLAIN = 262,
129 };
131 #if CONFIG_VNC_TLS
132 #define X509_CA_CERT_FILE "ca-cert.pem"
133 #define X509_CA_CRL_FILE "ca-crl.pem"
134 #define X509_SERVER_KEY_FILE "server-key.pem"
135 #define X509_SERVER_CERT_FILE "server-cert.pem"
136 #endif
138 #endif /* CONFIG_VNC_TLS */
140 struct VncState
141 {
142 QEMUTimer *timer;
143 int timer_interval;
144 int64_t last_update_time;
145 int lsock;
146 int csock;
147 DisplayState *ds;
148 int width;
149 int height;
150 uint64_t *dirty_row; /* screen regions which are possibly dirty */
151 int dirty_pixel_shift;
152 uint64_t *update_row; /* outstanding updates */
153 int has_update; /* there's outstanding updates in the
154 * visible area */
155 uint8_t *old_data;
156 int depth; /* internal VNC frame buffer byte per pixel */
157 int has_resize;
158 int has_hextile;
159 int has_pointer_type_change;
160 int absolute;
161 int last_x;
162 int last_y;
164 int major;
165 int minor;
167 char *display;
168 char *password;
169 int auth;
170 #if CONFIG_VNC_TLS
171 int subauth;
172 int x509verify;
174 char *x509cacert;
175 char *x509cacrl;
176 char *x509cert;
177 char *x509key;
178 #endif
179 char challenge[VNC_AUTH_CHALLENGE_SIZE];
181 #if CONFIG_VNC_TLS
182 int wiremode;
183 gnutls_session_t tls_session;
184 #endif
186 Buffer output;
187 Buffer input;
188 kbd_layout_t *kbd_layout;
189 /* current output mode information */
190 VncWritePixels *write_pixels;
191 VncSendHextileTile *send_hextile_tile;
192 int pix_bpp, pix_big_endian;
193 int red_shift, red_max, red_shift1, red_max1;
194 int green_shift, green_max, green_shift1, green_max1;
195 int blue_shift, blue_max, blue_shift1, blue_max1;
197 VncReadEvent *read_handler;
198 size_t read_handler_expect;
200 int visible_x;
201 int visible_y;
202 int visible_w;
203 int visible_h;
205 /* input */
206 uint8_t modifiers_state[256];
207 };
209 static VncState *vnc_state; /* needed for info vnc */
211 #define DIRTY_PIXEL_BITS 64
212 #define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift)
213 #define X2DP_UP(vs, x) \
214 (((x) + (1ULL << (vs)->dirty_pixel_shift) - 1) >> (vs)->dirty_pixel_shift)
215 #define DP2X(vs, x) ((x) << (vs)->dirty_pixel_shift)
217 void do_info_vnc(void)
218 {
219 if (vnc_state == NULL)
220 term_printf("VNC server disabled\n");
221 else {
222 term_printf("VNC server active on: ");
223 term_print_filename(vnc_state->display);
224 term_printf("\n");
226 if (vnc_state->csock == -1)
227 term_printf("No client connected\n");
228 else
229 term_printf("Client connected\n");
230 }
231 }
233 /* TODO
234 1) Get the queue working for IO.
235 2) there is some weirdness when using the -S option (the screen is grey
236 and not totally invalidated
237 3) resolutions > 1024
238 */
240 static void vnc_write(VncState *vs, const void *data, size_t len);
241 static void vnc_write_u32(VncState *vs, uint32_t value);
242 static void vnc_write_s32(VncState *vs, int32_t value);
243 static void vnc_write_u16(VncState *vs, uint16_t value);
244 static void vnc_write_u8(VncState *vs, uint8_t value);
245 static void vnc_flush(VncState *vs);
246 static void _vnc_update_client(void *opaque);
247 static void vnc_update_client(void *opaque);
248 static void vnc_client_read(void *opaque);
249 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
251 #if 0
252 static inline void vnc_set_bit(uint32_t *d, int k)
253 {
254 d[k >> 5] |= 1 << (k & 0x1f);
255 }
257 static inline void vnc_clear_bit(uint32_t *d, int k)
258 {
259 d[k >> 5] &= ~(1 << (k & 0x1f));
260 }
262 static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
263 {
264 int j;
266 j = 0;
267 while (n >= 32) {
268 d[j++] = -1;
269 n -= 32;
270 }
271 if (n > 0)
272 d[j++] = (1 << n) - 1;
273 while (j < nb_words)
274 d[j++] = 0;
275 }
277 static inline int vnc_get_bit(const uint32_t *d, int k)
278 {
279 return (d[k >> 5] >> (k & 0x1f)) & 1;
280 }
282 static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
283 int nb_words)
284 {
285 int i;
286 for(i = 0; i < nb_words; i++) {
287 if ((d1[i] & d2[i]) != 0)
288 return 1;
289 }
290 return 0;
291 }
292 #endif
294 static void set_bits_in_row(VncState *vs, uint64_t *row,
295 int x, int y, int w, int h)
296 {
297 int x1, x2;
298 uint64_t mask;
300 if (w == 0)
301 return;
303 x1 = X2DP_DOWN(vs, x);
304 x2 = X2DP_UP(vs, x + w);
306 if (X2DP_UP(vs, w) != DIRTY_PIXEL_BITS)
307 mask = ((1ULL << (x2 - x1)) - 1) << x1;
308 else
309 mask = ~(0ULL);
311 h += y;
312 if (h > vs->ds->height)
313 h = vs->ds->height;
314 for (; y < h; y++)
315 row[y] |= mask;
316 }
318 static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
319 {
320 VncState *vs = ds->opaque;
322 set_bits_in_row(vs, vs->dirty_row, x, y, w, h);
323 }
325 static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
326 int32_t encoding)
327 {
328 vnc_write_u16(vs, x);
329 vnc_write_u16(vs, y);
330 vnc_write_u16(vs, w);
331 vnc_write_u16(vs, h);
333 vnc_write_s32(vs, encoding);
334 }
336 static void vnc_dpy_resize(DisplayState *ds, int w, int h)
337 {
338 int size_changed;
339 VncState *vs = ds->opaque;
340 int o;
342 ds->data = realloc(ds->data, w * h * vs->depth);
343 vs->old_data = realloc(vs->old_data, w * h * vs->depth);
344 vs->dirty_row = realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0]));
345 vs->update_row = realloc(vs->update_row, h * sizeof(vs->dirty_row[0]));
347 if (ds->data == NULL || vs->old_data == NULL ||
348 vs->dirty_row == NULL || vs->update_row == NULL) {
349 fprintf(stderr, "vnc: memory allocation failed\n");
350 exit(1);
351 }
353 if (ds->depth != vs->depth * 8) {
354 ds->depth = vs->depth * 8;
355 set_color_table(ds);
356 }
357 size_changed = ds->width != w || ds->height != h;
358 ds->width = w;
359 ds->height = h;
360 ds->linesize = w * vs->depth;
361 if (vs->csock != -1 && vs->has_resize && size_changed) {
362 vnc_write_u8(vs, 0); /* msg id */
363 vnc_write_u8(vs, 0);
364 vnc_write_u16(vs, 1); /* number of rects */
365 vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
366 vnc_flush(vs);
367 vs->width = ds->width;
368 vs->height = ds->height;
369 }
370 vs->dirty_pixel_shift = 0;
371 for (o = DIRTY_PIXEL_BITS; o < ds->width; o *= 2)
372 vs->dirty_pixel_shift++;
373 framebuffer_set_updated(vs, 0, 0, ds->width, ds->height);
374 }
376 /* fastest code */
377 static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
378 {
379 vnc_write(vs, pixels, size);
380 }
382 /* slowest but generic code. */
383 static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
384 {
385 uint8_t r, g, b;
387 r = ((v >> vs->red_shift1) & vs->red_max1) * (vs->red_max + 1) / (vs->red_max1 + 1);
388 g = ((v >> vs->green_shift1) & vs->green_max1) * (vs->green_max + 1) / (vs->green_max1 + 1);
389 b = ((v >> vs->blue_shift1) & vs->blue_max1) * (vs->blue_max + 1) / (vs->blue_max1 + 1);
390 switch(vs->pix_bpp) {
391 case 1:
392 buf[0] = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
393 break;
394 case 2:
395 {
396 uint16_t *p = (uint16_t *) buf;
397 *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
398 if (vs->pix_big_endian) {
399 *p = htons(*p);
400 }
401 }
402 break;
403 default:
404 case 4:
405 {
406 uint32_t *p = (uint32_t *) buf;
407 *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
408 if (vs->pix_big_endian) {
409 *p = htonl(*p);
410 }
411 break;
412 }
413 }
414 }
416 static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
417 {
418 uint8_t buf[4];
420 if (vs->depth == 4) {
421 uint32_t *pixels = pixels1;
422 int n, i;
423 n = size >> 2;
424 for(i = 0; i < n; i++) {
425 vnc_convert_pixel(vs, buf, pixels[i]);
426 vnc_write(vs, buf, vs->pix_bpp);
427 }
428 } else if (vs->depth == 2) {
429 uint16_t *pixels = pixels1;
430 int n, i;
431 n = size >> 1;
432 for(i = 0; i < n; i++) {
433 vnc_convert_pixel(vs, buf, pixels[i]);
434 vnc_write(vs, buf, vs->pix_bpp);
435 }
436 } else if (vs->depth == 1) {
437 uint8_t *pixels = pixels1;
438 int n, i;
439 n = size;
440 for(i = 0; i < n; i++) {
441 vnc_convert_pixel(vs, buf, pixels[i]);
442 vnc_write(vs, buf, vs->pix_bpp);
443 }
444 } else {
445 fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
446 }
447 }
449 static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
450 {
451 int i;
452 uint8_t *row;
454 vnc_framebuffer_update(vs, x, y, w, h, 0);
456 row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
457 for (i = 0; i < h; i++) {
458 vs->write_pixels(vs, row, w * vs->depth);
459 row += vs->ds->linesize;
460 }
461 }
463 static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
464 {
465 ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
466 ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
467 }
469 #define BPP 8
470 #include "vnchextile.h"
471 #undef BPP
473 #define BPP 16
474 #include "vnchextile.h"
475 #undef BPP
477 #define BPP 32
478 #include "vnchextile.h"
479 #undef BPP
481 #define GENERIC
482 #define BPP 8
483 #include "vnchextile.h"
484 #undef BPP
485 #undef GENERIC
487 #define GENERIC
488 #define BPP 16
489 #include "vnchextile.h"
490 #undef BPP
491 #undef GENERIC
493 #define GENERIC
494 #define BPP 32
495 #include "vnchextile.h"
496 #undef BPP
497 #undef GENERIC
499 static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
500 {
501 int i, j;
502 int has_fg, has_bg;
503 void *last_fg, *last_bg;
505 vnc_framebuffer_update(vs, x, y, w, h, 5);
507 last_fg = (void *) malloc(vs->depth);
508 last_bg = (void *) malloc(vs->depth);
509 has_fg = has_bg = 0;
510 for (j = y; j < (y + h); j += 16) {
511 for (i = x; i < (x + w); i += 16) {
512 vs->send_hextile_tile(vs, i, j,
513 MIN(16, x + w - i), MIN(16, y + h - j),
514 last_bg, last_fg, &has_bg, &has_fg);
515 }
516 }
517 free(last_fg);
518 free(last_bg);
519 }
521 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
522 {
523 if (vs->has_hextile)
524 send_framebuffer_update_hextile(vs, x, y, w, h);
525 else
526 send_framebuffer_update_raw(vs, x, y, w, h);
527 }
529 static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
530 {
531 int src, dst;
532 uint8_t *src_row;
533 uint8_t *dst_row;
534 uint8_t *old_row;
535 int y = 0;
536 int pitch = ds->linesize;
537 VncState *vs = ds->opaque;
538 int updating_client = 1;
540 if (src_x < vs->visible_x || src_y < vs->visible_y ||
541 dst_x < vs->visible_x || dst_y < vs->visible_y ||
542 (src_x + w) > (vs->visible_x + vs->visible_w) ||
543 (src_y + h) > (vs->visible_y + vs->visible_h) ||
544 (dst_x + w) > (vs->visible_x + vs->visible_w) ||
545 (dst_y + h) > (vs->visible_y + vs->visible_h))
546 updating_client = 0;
548 if (updating_client)
549 _vnc_update_client(vs);
551 if (dst_y > src_y) {
552 y = h - 1;
553 pitch = -pitch;
554 }
556 src = (ds->linesize * (src_y + y) + vs->depth * src_x);
557 dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
559 src_row = ds->data + src;
560 dst_row = ds->data + dst;
561 old_row = vs->old_data + dst;
563 for (y = 0; y < h; y++) {
564 memmove(old_row, src_row, w * vs->depth);
565 memmove(dst_row, src_row, w * vs->depth);
566 src_row += pitch;
567 dst_row += pitch;
568 old_row += pitch;
569 }
571 if (updating_client && vs->csock != -1 && !vs->has_update) {
572 vnc_write_u8(vs, 0); /* msg id */
573 vnc_write_u8(vs, 0);
574 vnc_write_u16(vs, 1); /* number of rects */
575 vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
576 vnc_write_u16(vs, src_x);
577 vnc_write_u16(vs, src_y);
578 vnc_flush(vs);
579 } else
580 framebuffer_set_updated(vs, dst_x, dst_y, w, h);
581 }
583 static int find_update_height(VncState *vs, int y, int maxy, int last_x, int x)
584 {
585 int h;
587 for (h = 1; y + h < maxy; h++) {
588 int tmp_x;
589 if (!(vs->update_row[y + h] & (1ULL << last_x)))
590 break;
591 for (tmp_x = last_x; tmp_x < x; tmp_x++)
592 vs->update_row[y + h] &= ~(1ULL << tmp_x);
593 }
595 return h;
596 }
598 static void _vnc_update_client(void *opaque)
599 {
600 VncState *vs = opaque;
601 int64_t now;
602 int y;
603 uint8_t *row;
604 uint8_t *old_row;
605 uint64_t width_mask;
606 int n_rectangles;
607 int saved_offset;
608 int maxx, maxy;
609 int tile_bytes = vs->depth * DP2X(vs, 1);
611 if (vs->csock == -1)
612 return;
614 now = qemu_get_clock(rt_clock);
616 if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))
617 width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;
618 else
619 width_mask = ~(0ULL);
621 /* Walk through the dirty map and eliminate tiles that really
622 aren't dirty */
623 row = vs->ds->data;
624 old_row = vs->old_data;
626 for (y = 0; y < vs->ds->height; y++) {
627 if (vs->dirty_row[y] & width_mask) {
628 int x;
629 uint8_t *ptr, *old_ptr;
631 ptr = row;
632 old_ptr = old_row;
634 for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {
635 if (vs->dirty_row[y] & (1ULL << x)) {
636 if (memcmp(old_ptr, ptr, tile_bytes)) {
637 vs->has_update = 1;
638 vs->update_row[y] |= (1ULL << x);
639 memcpy(old_ptr, ptr, tile_bytes);
640 }
641 vs->dirty_row[y] &= ~(1ULL << x);
642 }
644 ptr += tile_bytes;
645 old_ptr += tile_bytes;
646 }
647 }
649 row += vs->ds->linesize;
650 old_row += vs->ds->linesize;
651 }
653 if (!vs->has_update || vs->visible_y >= vs->ds->height ||
654 vs->visible_x >= vs->ds->width)
655 goto backoff;
657 /* Count rectangles */
658 n_rectangles = 0;
659 vnc_write_u8(vs, 0); /* msg id */
660 vnc_write_u8(vs, 0);
661 saved_offset = vs->output.offset;
662 vnc_write_u16(vs, 0);
664 maxy = vs->visible_y + vs->visible_h;
665 if (maxy > vs->ds->height)
666 maxy = vs->ds->height;
667 maxx = vs->visible_x + vs->visible_w;
668 if (maxx > vs->ds->width)
669 maxx = vs->ds->width;
671 for (y = vs->visible_y; y < maxy; y++) {
672 int x;
673 int last_x = -1;
674 for (x = X2DP_DOWN(vs, vs->visible_x);
675 x < X2DP_UP(vs, maxx); x++) {
676 if (vs->update_row[y] & (1ULL << x)) {
677 if (last_x == -1)
678 last_x = x;
679 vs->update_row[y] &= ~(1ULL << x);
680 } else {
681 if (last_x != -1) {
682 int h = find_update_height(vs, y, maxy, last_x, x);
683 if (h != 0) {
684 send_framebuffer_update(vs, DP2X(vs, last_x), y,
685 DP2X(vs, (x - last_x)), h);
686 n_rectangles++;
687 }
688 }
689 last_x = -1;
690 }
691 }
692 if (last_x != -1) {
693 int h = find_update_height(vs, y, maxy, last_x, x);
694 if (h != 0) {
695 send_framebuffer_update(vs, DP2X(vs, last_x), y,
696 DP2X(vs, (x - last_x)), h);
697 n_rectangles++;
698 }
699 }
700 }
701 vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
702 vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
704 if (n_rectangles == 0)
705 goto backoff;
707 vs->has_update = 0;
708 vnc_flush(vs);
709 vs->last_update_time = now;
711 vs->timer_interval /= 2;
712 if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE)
713 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
715 return;
717 backoff:
718 /* No update -> back off a bit */
719 vs->timer_interval += VNC_REFRESH_INTERVAL_INC;
720 if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) {
721 vs->timer_interval = VNC_REFRESH_INTERVAL_MAX;
722 if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) {
723 /* Send a null update. If the client is no longer
724 interested (e.g. minimised) it'll ignore this, and we
725 can stop scanning the buffer until it sends another
726 update request. */
727 /* It turns out that there's a bug in realvncviewer 4.1.2
728 which means that if you send a proper null update (with
729 no update rectangles), it gets a bit out of sync and
730 never sends any further requests, regardless of whether
731 it needs one or not. Fix this by sending a single 1x1
732 update rectangle instead. */
733 vnc_write_u8(vs, 0);
734 vnc_write_u8(vs, 0);
735 vnc_write_u16(vs, 1);
736 send_framebuffer_update(vs, 0, 0, 1, 1);
737 vnc_flush(vs);
738 vs->last_update_time = now;
739 return;
740 }
741 }
742 qemu_mod_timer(vs->timer, now + vs->timer_interval);
743 return;
744 }
746 static void vnc_update_client(void *opaque)
747 {
748 VncState *vs = opaque;
750 vs->ds->dpy_refresh(vs->ds);
751 _vnc_update_client(vs);
752 }
754 static void vnc_timer_init(VncState *vs)
755 {
756 if (vs->timer == NULL) {
757 vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
758 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
759 }
760 }
762 static void vnc_dpy_refresh(DisplayState *ds)
763 {
764 vga_hw_update();
765 }
767 static int vnc_listen_poll(void *opaque)
768 {
769 VncState *vs = opaque;
770 if (vs->csock == -1)
771 return 1;
772 return 0;
773 }
775 static void buffer_reserve(Buffer *buffer, size_t len)
776 {
777 if ((buffer->capacity - buffer->offset) < len) {
778 buffer->capacity += (len + 1024);
779 buffer->buffer = realloc(buffer->buffer, buffer->capacity);
780 if (buffer->buffer == NULL) {
781 fprintf(stderr, "vnc: out of memory\n");
782 exit(1);
783 }
784 }
785 }
787 static int buffer_empty(Buffer *buffer)
788 {
789 return buffer->offset == 0;
790 }
792 static uint8_t *buffer_end(Buffer *buffer)
793 {
794 return buffer->buffer + buffer->offset;
795 }
797 static void buffer_reset(Buffer *buffer)
798 {
799 buffer->offset = 0;
800 }
802 static void buffer_append(Buffer *buffer, const void *data, size_t len)
803 {
804 memcpy(buffer->buffer + buffer->offset, data, len);
805 buffer->offset += len;
806 }
808 static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
809 {
810 if (ret == 0 || ret == -1) {
811 if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
812 return 0;
814 VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
815 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
816 closesocket(vs->csock);
817 vs->csock = -1;
818 buffer_reset(&vs->input);
819 buffer_reset(&vs->output);
820 #if CONFIG_VNC_TLS
821 if (vs->tls_session) {
822 gnutls_deinit(vs->tls_session);
823 vs->tls_session = NULL;
824 }
825 vs->wiremode = VNC_WIREMODE_CLEAR;
826 #endif /* CONFIG_VNC_TLS */
827 return 0;
828 }
829 return ret;
830 }
832 static void vnc_client_error(VncState *vs)
833 {
834 vnc_client_io_error(vs, -1, EINVAL);
835 }
837 static void vnc_client_write(void *opaque)
838 {
839 long ret;
840 VncState *vs = opaque;
842 #if CONFIG_VNC_TLS
843 if (vs->tls_session) {
844 ret = gnutls_write(vs->tls_session, vs->output.buffer, vs->output.offset);
845 if (ret < 0) {
846 if (ret == GNUTLS_E_AGAIN)
847 errno = EAGAIN;
848 else
849 errno = EIO;
850 ret = -1;
851 }
852 } else
853 #endif /* CONFIG_VNC_TLS */
854 ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
855 ret = vnc_client_io_error(vs, ret, socket_error());
856 if (!ret)
857 return;
859 memmove(vs->output.buffer, vs->output.buffer + ret,
860 vs->output.offset - ret);
861 vs->output.offset -= ret;
863 if (vs->output.offset == 0)
864 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
865 }
867 static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
868 {
869 vs->read_handler = func;
870 vs->read_handler_expect = expecting;
871 }
873 static void vnc_client_read(void *opaque)
874 {
875 VncState *vs = opaque;
876 long ret;
878 buffer_reserve(&vs->input, 4096);
880 #if CONFIG_VNC_TLS
881 if (vs->tls_session) {
882 ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
883 if (ret < 0) {
884 if (ret == GNUTLS_E_AGAIN)
885 errno = EAGAIN;
886 else
887 errno = EIO;
888 ret = -1;
889 }
890 } else
891 #endif /* CONFIG_VNC_TLS */
892 ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
893 ret = vnc_client_io_error(vs, ret, socket_error());
894 if (!ret)
895 return;
897 vs->input.offset += ret;
899 while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
900 size_t len = vs->read_handler_expect;
901 int ret;
903 ret = vs->read_handler(vs, vs->input.buffer, len);
904 if (vs->csock == -1)
905 return;
907 if (!ret) {
908 memmove(vs->input.buffer, vs->input.buffer + len,
909 vs->input.offset - len);
910 vs->input.offset -= len;
911 } else {
912 assert(ret > vs->read_handler_expect);
913 vs->read_handler_expect = ret;
914 }
915 }
916 }
918 static void vnc_write(VncState *vs, const void *data, size_t len)
919 {
920 buffer_reserve(&vs->output, len);
922 if (buffer_empty(&vs->output))
923 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read,
924 vnc_client_write, vs);
926 buffer_append(&vs->output, data, len);
927 }
929 static void vnc_write_s32(VncState *vs, int32_t value)
930 {
931 vnc_write_u32(vs, *(uint32_t *)&value);
932 }
934 static void vnc_write_u32(VncState *vs, uint32_t value)
935 {
936 uint8_t buf[4];
938 buf[0] = (value >> 24) & 0xFF;
939 buf[1] = (value >> 16) & 0xFF;
940 buf[2] = (value >> 8) & 0xFF;
941 buf[3] = value & 0xFF;
943 vnc_write(vs, buf, 4);
944 }
946 static void vnc_write_u16(VncState *vs, uint16_t value)
947 {
948 uint8_t buf[2];
950 buf[0] = (value >> 8) & 0xFF;
951 buf[1] = value & 0xFF;
953 vnc_write(vs, buf, 2);
954 }
956 static void vnc_write_u8(VncState *vs, uint8_t value)
957 {
958 vnc_write(vs, &value, 1);
959 }
961 static void vnc_flush(VncState *vs)
962 {
963 if (vs->output.offset)
964 vnc_client_write(vs);
965 }
967 static uint8_t read_u8(uint8_t *data, size_t offset)
968 {
969 return data[offset];
970 }
972 static uint16_t read_u16(uint8_t *data, size_t offset)
973 {
974 return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
975 }
977 static int32_t read_s32(uint8_t *data, size_t offset)
978 {
979 return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
980 (data[offset + 2] << 8) | data[offset + 3]);
981 }
983 static uint32_t read_u32(uint8_t *data, size_t offset)
984 {
985 return ((data[offset] << 24) | (data[offset + 1] << 16) |
986 (data[offset + 2] << 8) | data[offset + 3]);
987 }
989 #if CONFIG_VNC_TLS
990 ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
991 const void *data,
992 size_t len) {
993 struct VncState *vs = (struct VncState *)transport;
994 int ret;
996 retry:
997 ret = send(vs->csock, data, len, 0);
998 if (ret < 0) {
999 if (errno == EINTR)
1000 goto retry;
1001 return -1;
1003 return ret;
1007 ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
1008 void *data,
1009 size_t len) {
1010 struct VncState *vs = (struct VncState *)transport;
1011 int ret;
1013 retry:
1014 ret = recv(vs->csock, data, len, 0);
1015 if (ret < 0) {
1016 if (errno == EINTR)
1017 goto retry;
1018 return -1;
1020 return ret;
1022 #endif /* CONFIG_VNC_TLS */
1024 static void client_cut_text(VncState *vs, size_t len, char *text)
1028 static void check_pointer_type_change(VncState *vs, int absolute)
1030 if (vs->has_pointer_type_change && vs->absolute != absolute) {
1031 vnc_write_u8(vs, 0);
1032 vnc_write_u8(vs, 0);
1033 vnc_write_u16(vs, 1);
1034 vnc_framebuffer_update(vs, absolute, 0,
1035 vs->ds->width, vs->ds->height, -257);
1036 vnc_flush(vs);
1038 vs->absolute = absolute;
1041 static void pointer_event(VncState *vs, int button_mask, int x, int y)
1043 int buttons = 0;
1044 int dz = 0;
1046 if (button_mask & 0x01)
1047 buttons |= MOUSE_EVENT_LBUTTON;
1048 if (button_mask & 0x02)
1049 buttons |= MOUSE_EVENT_MBUTTON;
1050 if (button_mask & 0x04)
1051 buttons |= MOUSE_EVENT_RBUTTON;
1052 if (button_mask & 0x08)
1053 dz = -1;
1054 if (button_mask & 0x10)
1055 dz = 1;
1057 if (vs->absolute) {
1058 kbd_mouse_event(x * 0x7FFF / vs->ds->width,
1059 y * 0x7FFF / vs->ds->height,
1060 dz, buttons);
1061 } else if (vs->has_pointer_type_change) {
1062 x -= 0x7FFF;
1063 y -= 0x7FFF;
1065 kbd_mouse_event(x, y, dz, buttons);
1066 } else {
1067 if (vs->last_x != -1)
1068 kbd_mouse_event(x - vs->last_x,
1069 y - vs->last_y,
1070 dz, buttons);
1071 vs->last_x = x;
1072 vs->last_y = y;
1075 check_pointer_type_change(vs, kbd_mouse_is_absolute());
1078 static void reset_keys(VncState *vs)
1080 int i;
1081 for(i = 0; i < 256; i++) {
1082 if (vs->modifiers_state[i]) {
1083 if (i & 0x80)
1084 kbd_put_keycode(0xe0);
1085 kbd_put_keycode(i | 0x80);
1086 vs->modifiers_state[i] = 0;
1091 static void press_key(VncState *vs, int keysym)
1093 kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f);
1094 kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
1097 static void press_key_shift_down(VncState *vs, int down, int keycode)
1099 if (down)
1100 kbd_put_keycode(0x2a & 0x7f);
1102 if (keycode & 0x80)
1103 kbd_put_keycode(0xe0);
1104 if (down)
1105 kbd_put_keycode(keycode & 0x7f);
1106 else
1107 kbd_put_keycode(keycode | 0x80);
1109 if (!down)
1110 kbd_put_keycode(0x2a | 0x80);
1113 static void press_key_shift_up(VncState *vs, int down, int keycode)
1115 if (down) {
1116 if (vs->modifiers_state[0x2a])
1117 kbd_put_keycode(0x2a | 0x80);
1118 if (vs->modifiers_state[0x36])
1119 kbd_put_keycode(0x36 | 0x80);
1122 if (keycode & 0x80)
1123 kbd_put_keycode(0xe0);
1124 if (down)
1125 kbd_put_keycode(keycode & 0x7f);
1126 else
1127 kbd_put_keycode(keycode | 0x80);
1129 if (!down) {
1130 if (vs->modifiers_state[0x2a])
1131 kbd_put_keycode(0x2a & 0x7f);
1132 if (vs->modifiers_state[0x36])
1133 kbd_put_keycode(0x36 & 0x7f);
1137 static void do_key_event(VncState *vs, int down, uint32_t sym)
1139 int keycode;
1140 int shift_keys = 0;
1141 int shift = 0;
1143 if (is_graphic_console()) {
1144 if (sym >= 'A' && sym <= 'Z') {
1145 sym = sym - 'A' + 'a';
1146 shift = 1;
1148 else {
1149 shift = keysymIsShift(vs->kbd_layout, sym & 0xFFFF);
1152 shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36];
1154 keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
1155 if (keycode == 0) {
1156 fprintf(stderr, "Key lost : keysym=0x%x(%d)\n", sym, sym);
1157 return;
1160 /* QEMU console switch */
1161 switch(keycode) {
1162 case 0x2a: /* Left Shift */
1163 case 0x36: /* Right Shift */
1164 case 0x1d: /* Left CTRL */
1165 case 0x9d: /* Right CTRL */
1166 case 0x38: /* Left ALT */
1167 case 0xb8: /* Right ALT */
1168 if (down) {
1169 vs->modifiers_state[keycode] = 1;
1170 kbd_put_keycode(keycode & 0x7f);
1172 else {
1173 vs->modifiers_state[keycode] = 0;
1174 kbd_put_keycode(keycode | 0x80);
1176 return;
1177 case 0x02 ... 0x0a: /* '1' to '9' keys */
1178 if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1179 /* Reset the modifiers sent to the current console */
1180 reset_keys(vs);
1181 console_select(keycode - 0x02);
1182 return;
1184 break;
1185 case 0x45: /* NumLock */
1186 if (down) {
1187 kbd_put_keycode(keycode & 0x7f);
1189 else {
1190 vs->modifiers_state[keycode] ^= 1;
1191 kbd_put_keycode(keycode | 0x80);
1193 return;
1196 if (keycodeIsKeypad(vs->kbd_layout, keycode)) {
1197 /* If the numlock state needs to change then simulate an additional
1198 keypress before sending this one. This will happen if the user
1199 toggles numlock away from the VNC window.
1200 */
1201 if (keysymIsNumlock(vs->kbd_layout, sym & 0xFFFF)) {
1202 if (!vs->modifiers_state[0x45]) {
1203 vs->modifiers_state[0x45] = 1;
1204 press_key(vs, 0xff7f);
1206 } else {
1207 if (vs->modifiers_state[0x45]) {
1208 vs->modifiers_state[0x45] = 0;
1209 press_key(vs, 0xff7f);
1214 if (is_graphic_console()) {
1215 /* If the shift state needs to change then simulate an additional
1216 keypress before sending this one.
1217 */
1218 if (shift && !shift_keys) {
1219 press_key_shift_down(vs, down, keycode);
1220 return;
1222 else if (!shift && shift_keys) {
1223 press_key_shift_up(vs, down, keycode);
1224 return;
1227 if (keycode & 0x80)
1228 kbd_put_keycode(0xe0);
1229 if (down)
1230 kbd_put_keycode(keycode & 0x7f);
1231 else
1232 kbd_put_keycode(keycode | 0x80);
1233 } else {
1234 /* QEMU console emulation */
1235 if (down) {
1236 switch (keycode) {
1237 case 0x2a: /* Left Shift */
1238 case 0x36: /* Right Shift */
1239 case 0x1d: /* Left CTRL */
1240 case 0x9d: /* Right CTRL */
1241 case 0x38: /* Left ALT */
1242 case 0xb8: /* Right ALT */
1243 break;
1244 case 0xc8:
1245 kbd_put_keysym(QEMU_KEY_UP);
1246 break;
1247 case 0xd0:
1248 kbd_put_keysym(QEMU_KEY_DOWN);
1249 break;
1250 case 0xcb:
1251 kbd_put_keysym(QEMU_KEY_LEFT);
1252 break;
1253 case 0xcd:
1254 kbd_put_keysym(QEMU_KEY_RIGHT);
1255 break;
1256 case 0xd3:
1257 kbd_put_keysym(QEMU_KEY_DELETE);
1258 break;
1259 case 0xc7:
1260 kbd_put_keysym(QEMU_KEY_HOME);
1261 break;
1262 case 0xcf:
1263 kbd_put_keysym(QEMU_KEY_END);
1264 break;
1265 case 0xc9:
1266 kbd_put_keysym(QEMU_KEY_PAGEUP);
1267 break;
1268 case 0xd1:
1269 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1270 break;
1271 default:
1272 kbd_put_keysym(sym);
1273 break;
1279 static void key_event(VncState *vs, int down, uint32_t sym)
1281 do_key_event(vs, down, sym);
1284 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h)
1287 set_bits_in_row(vs, vs->update_row, x, y, w, h);
1289 vs->has_update = 1;
1292 static void framebuffer_update_request(VncState *vs, int incremental,
1293 int x_position, int y_position,
1294 int w, int h)
1296 if (!incremental)
1297 framebuffer_set_updated(vs, x_position, y_position, w, h);
1298 vs->visible_x = x_position;
1299 vs->visible_y = y_position;
1300 vs->visible_w = w;
1301 vs->visible_h = h;
1303 qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
1306 static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1308 int i;
1310 vs->has_hextile = 0;
1311 vs->has_resize = 0;
1312 vs->has_pointer_type_change = 0;
1313 vs->absolute = -1;
1314 vs->ds->dpy_copy = NULL;
1316 for (i = n_encodings - 1; i >= 0; i--) {
1317 switch (encodings[i]) {
1318 case 0: /* Raw */
1319 vs->has_hextile = 0;
1320 break;
1321 case 1: /* CopyRect */
1322 vs->ds->dpy_copy = vnc_copy;
1323 break;
1324 case 5: /* Hextile */
1325 vs->has_hextile = 1;
1326 break;
1327 case -223: /* DesktopResize */
1328 vs->has_resize = 1;
1329 break;
1330 case -257:
1331 vs->has_pointer_type_change = 1;
1332 break;
1333 default:
1334 break;
1338 check_pointer_type_change(vs, kbd_mouse_is_absolute());
1341 static void set_pixel_format(VncState *vs,
1342 int bits_per_pixel, int depth,
1343 int big_endian_flag, int true_color_flag,
1344 int red_max, int green_max, int blue_max,
1345 int red_shift, int green_shift, int blue_shift)
1347 int host_big_endian_flag;
1349 #ifdef WORDS_BIGENDIAN
1350 host_big_endian_flag = 1;
1351 #else
1352 host_big_endian_flag = 0;
1353 #endif
1354 if (!true_color_flag) {
1355 fail:
1356 vnc_client_error(vs);
1357 return;
1359 if (bits_per_pixel == 32 &&
1360 bits_per_pixel == vs->depth * 8 &&
1361 host_big_endian_flag == big_endian_flag &&
1362 red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1363 red_shift == 16 && green_shift == 8 && blue_shift == 0) {
1364 vs->write_pixels = vnc_write_pixels_copy;
1365 vs->send_hextile_tile = send_hextile_tile_32;
1366 } else
1367 if (bits_per_pixel == 16 &&
1368 bits_per_pixel == vs->depth * 8 &&
1369 host_big_endian_flag == big_endian_flag &&
1370 red_max == 31 && green_max == 63 && blue_max == 31 &&
1371 red_shift == 11 && green_shift == 5 && blue_shift == 0) {
1372 vs->write_pixels = vnc_write_pixels_copy;
1373 vs->send_hextile_tile = send_hextile_tile_16;
1374 } else
1375 if (bits_per_pixel == 8 &&
1376 bits_per_pixel == vs->depth * 8 &&
1377 red_max == 7 && green_max == 7 && blue_max == 3 &&
1378 red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1379 vs->depth = 1;
1380 vs->write_pixels = vnc_write_pixels_copy;
1381 vs->send_hextile_tile = send_hextile_tile_8;
1382 } else
1384 /* generic and slower case */
1385 if (bits_per_pixel != 8 &&
1386 bits_per_pixel != 16 &&
1387 bits_per_pixel != 32)
1388 goto fail;
1389 if (vs->depth == 4) {
1390 vs->send_hextile_tile = send_hextile_tile_generic_32;
1391 } else if (vs->depth == 2) {
1392 vs->send_hextile_tile = send_hextile_tile_generic_16;
1393 } else {
1394 vs->send_hextile_tile = send_hextile_tile_generic_8;
1397 vs->pix_big_endian = big_endian_flag;
1398 vs->write_pixels = vnc_write_pixels_generic;
1401 vs->red_shift = red_shift;
1402 vs->red_max = red_max;
1403 vs->green_shift = green_shift;
1404 vs->green_max = green_max;
1405 vs->blue_shift = blue_shift;
1406 vs->blue_max = blue_max;
1407 vs->pix_bpp = bits_per_pixel / 8;
1409 vga_hw_invalidate();
1410 vga_hw_update();
1413 static void vnc_dpy_colourdepth(DisplayState *ds, int depth)
1415 int host_big_endian_flag;
1416 struct VncState *vs;
1418 if (!depth) return;
1420 #ifdef WORDS_BIGENDIAN
1421 host_big_endian_flag = 1;
1422 #else
1423 host_big_endian_flag = 0;
1424 #endif
1425 vs = ds->opaque;
1427 switch (depth) {
1428 case 8:
1429 vs->depth = depth / 8;
1430 vs->red_max1 = 7;
1431 vs->green_max1 = 7;
1432 vs->blue_max1 = 3;
1433 vs->red_shift1 = 5;
1434 vs->green_shift1 = 2;
1435 vs->blue_shift1 = 0;
1436 break;
1437 case 16:
1438 vs->depth = depth / 8;
1439 vs->red_max1 = 31;
1440 vs->green_max1 = 63;
1441 vs->blue_max1 = 31;
1442 vs->red_shift1 = 11;
1443 vs->green_shift1 = 5;
1444 vs->blue_shift1 = 0;
1445 break;
1446 case 32:
1447 vs->depth = 4;
1448 vs->red_max1 = 255;
1449 vs->green_max1 = 255;
1450 vs->blue_max1 = 255;
1451 vs->red_shift1 = 16;
1452 vs->green_shift1 = 8;
1453 vs->blue_shift1 = 0;
1454 break;
1455 default:
1456 return;
1458 if (ds->switchbpp) {
1459 vnc_client_error(vs);
1460 } else {
1461 if (vs->pix_bpp == 4 && vs->depth == 4 &&
1462 host_big_endian_flag == vs->pix_big_endian &&
1463 vs->red_max == 0xff && vs->green_max == 0xff && vs->blue_max == 0xff &&
1464 vs->red_shift == 16 && vs->green_shift == 8 && vs->blue_shift == 0) {
1465 vs->write_pixels = vnc_write_pixels_copy;
1466 vs->send_hextile_tile = send_hextile_tile_32;
1467 } else if (vs->pix_bpp == 2 && vs->depth == 2 &&
1468 host_big_endian_flag == vs->pix_big_endian &&
1469 vs->red_max == 31 && vs->green_max == 63 && vs->blue_max == 31 &&
1470 vs->red_shift == 11 && vs->green_shift == 5 && vs->blue_shift == 0) {
1471 vs->write_pixels = vnc_write_pixels_copy;
1472 vs->send_hextile_tile = send_hextile_tile_16;
1473 } else if (vs->pix_bpp == 1 && vs->depth == 1 &&
1474 host_big_endian_flag == vs->pix_big_endian &&
1475 vs->red_max == 7 && vs->green_max == 7 && vs->blue_max == 3 &&
1476 vs->red_shift == 5 && vs->green_shift == 2 && vs->blue_shift == 0) {
1477 vs->write_pixels = vnc_write_pixels_copy;
1478 vs->send_hextile_tile = send_hextile_tile_8;
1479 } else {
1480 if (vs->depth == 4) {
1481 vs->send_hextile_tile = send_hextile_tile_generic_32;
1482 } else if (vs->depth == 2) {
1483 vs->send_hextile_tile = send_hextile_tile_generic_16;
1484 } else {
1485 vs->send_hextile_tile = send_hextile_tile_generic_8;
1487 vs->write_pixels = vnc_write_pixels_generic;
1491 vnc_dpy_resize(ds, ds->width, ds->height);
1494 static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1496 int i;
1497 uint16_t limit;
1499 switch (data[0]) {
1500 case 0:
1501 if (len == 1)
1502 return 20;
1504 set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1505 read_u8(data, 6), read_u8(data, 7),
1506 read_u16(data, 8), read_u16(data, 10),
1507 read_u16(data, 12), read_u8(data, 14),
1508 read_u8(data, 15), read_u8(data, 16));
1509 break;
1510 case 2:
1511 if (len == 1)
1512 return 4;
1514 if (len == 4) {
1515 uint16_t v;
1516 v = read_u16(data, 2);
1517 if (v)
1518 return 4 + v * 4;
1521 limit = read_u16(data, 2);
1522 for (i = 0; i < limit; i++) {
1523 int32_t val = read_s32(data, 4 + (i * 4));
1524 memcpy(data + 4 + (i * 4), &val, sizeof(val));
1527 set_encodings(vs, (int32_t *)(data + 4), limit);
1528 break;
1529 case 3:
1530 if (len == 1)
1531 return 10;
1533 framebuffer_update_request(vs,
1534 read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1535 read_u16(data, 6), read_u16(data, 8));
1536 break;
1537 case 4:
1538 if (len == 1)
1539 return 8;
1541 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1542 qemu_advance_timer(vs->timer,
1543 qemu_get_clock(rt_clock) + vs->timer_interval);
1544 key_event(vs, read_u8(data, 1), read_u32(data, 4));
1545 break;
1546 case 5:
1547 if (len == 1)
1548 return 6;
1550 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1551 qemu_advance_timer(vs->timer,
1552 qemu_get_clock(rt_clock) + vs->timer_interval);
1553 pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1554 break;
1555 case 6:
1556 if (len == 1)
1557 return 8;
1559 if (len == 8) {
1560 uint32_t v;
1561 v = read_u32(data, 4);
1562 if (v)
1563 return 8 + v;
1566 client_cut_text(vs, read_u32(data, 4), (char *)(data + 8));
1567 break;
1568 default:
1569 printf("Msg: %d\n", data[0]);
1570 vnc_client_error(vs);
1571 break;
1574 vnc_read_when(vs, protocol_client_msg, 1);
1575 return 0;
1578 static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1580 size_t l;
1581 char pad[3] = { 0, 0, 0 };
1583 vga_hw_update();
1585 vs->width = vs->ds->width;
1586 vs->height = vs->ds->height;
1587 vnc_write_u16(vs, vs->ds->width);
1588 vnc_write_u16(vs, vs->ds->height);
1590 vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1591 if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
1592 else vnc_write_u8(vs, vs->depth * 8); /* depth */
1594 #ifdef WORDS_BIGENDIAN
1595 vnc_write_u8(vs, 1); /* big-endian-flag */
1596 #else
1597 vnc_write_u8(vs, 0); /* big-endian-flag */
1598 #endif
1599 vnc_write_u8(vs, 1); /* true-color-flag */
1600 if (vs->depth == 4) {
1601 vnc_write_u16(vs, 0xFF); /* red-max */
1602 vnc_write_u16(vs, 0xFF); /* green-max */
1603 vnc_write_u16(vs, 0xFF); /* blue-max */
1604 vnc_write_u8(vs, 16); /* red-shift */
1605 vnc_write_u8(vs, 8); /* green-shift */
1606 vnc_write_u8(vs, 0); /* blue-shift */
1607 vs->send_hextile_tile = send_hextile_tile_32;
1608 } else if (vs->depth == 2) {
1609 vnc_write_u16(vs, 31); /* red-max */
1610 vnc_write_u16(vs, 63); /* green-max */
1611 vnc_write_u16(vs, 31); /* blue-max */
1612 vnc_write_u8(vs, 11); /* red-shift */
1613 vnc_write_u8(vs, 5); /* green-shift */
1614 vnc_write_u8(vs, 0); /* blue-shift */
1615 vs->send_hextile_tile = send_hextile_tile_16;
1616 } else if (vs->depth == 1) {
1617 /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
1618 vnc_write_u16(vs, 7); /* red-max */
1619 vnc_write_u16(vs, 7); /* green-max */
1620 vnc_write_u16(vs, 3); /* blue-max */
1621 vnc_write_u8(vs, 5); /* red-shift */
1622 vnc_write_u8(vs, 2); /* green-shift */
1623 vnc_write_u8(vs, 0); /* blue-shift */
1624 vs->send_hextile_tile = send_hextile_tile_8;
1626 vs->write_pixels = vnc_write_pixels_copy;
1628 vnc_write(vs, pad, 3); /* padding */
1630 l = strlen(domain_name);
1631 vnc_write_u32(vs, l);
1632 vnc_write(vs, domain_name, l);
1634 vnc_flush(vs);
1636 vnc_read_when(vs, protocol_client_msg, 1);
1638 return 0;
1642 static void make_challenge(VncState *vs)
1644 int i;
1646 srand(time(NULL)+getpid()+getpid()*987654+rand());
1648 for (i = 0 ; i < sizeof(vs->challenge) ; i++)
1649 vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1652 static int protocol_client_auth_vnc(VncState *vs, char *data, size_t len)
1654 char response[VNC_AUTH_CHALLENGE_SIZE];
1655 int i, j, pwlen;
1656 char key[8];
1658 if (!vs->password || !vs->password[0]) {
1659 VNC_DEBUG("No password configured on server");
1660 vnc_write_u32(vs, 1); /* Reject auth */
1661 if (vs->minor >= 8) {
1662 static const char err[] = "Authentication failed";
1663 vnc_write_u32(vs, sizeof(err));
1664 vnc_write(vs, err, sizeof(err));
1666 vnc_flush(vs);
1667 vnc_client_error(vs);
1668 return 0;
1671 memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
1673 /* Calculate the expected challenge response */
1674 pwlen = strlen(vs->password);
1675 for (i=0; i<sizeof(key); i++)
1676 key[i] = i<pwlen ? vs->password[i] : 0;
1677 deskey(key, EN0);
1678 for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
1679 des(response+j, response+j);
1681 /* Compare expected vs actual challenge response */
1682 if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
1683 VNC_DEBUG("Client challenge reponse did not match\n");
1684 vnc_write_u32(vs, 1); /* Reject auth */
1685 if (vs->minor >= 8) {
1686 static const char err[] = "Authentication failed";
1687 vnc_write_u32(vs, sizeof(err));
1688 vnc_write(vs, err, sizeof(err));
1690 vnc_flush(vs);
1691 vnc_client_error(vs);
1692 } else {
1693 VNC_DEBUG("Accepting VNC challenge response\n");
1694 vnc_write_u32(vs, 0); /* Accept auth */
1695 vnc_flush(vs);
1697 vnc_read_when(vs, protocol_client_init, 1);
1699 return 0;
1702 static int start_auth_vnc(VncState *vs)
1704 make_challenge(vs);
1705 /* Send client a 'random' challenge */
1706 vnc_write(vs, vs->challenge, sizeof(vs->challenge));
1707 vnc_flush(vs);
1709 vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
1710 return 0;
1714 #if CONFIG_VNC_TLS
1715 #define DH_BITS 1024
1716 static gnutls_dh_params_t dh_params;
1718 static int vnc_tls_initialize(void)
1720 static int tlsinitialized = 0;
1722 if (tlsinitialized)
1723 return 1;
1725 if (gnutls_global_init () < 0)
1726 return 0;
1728 /* XXX ought to re-generate diffie-hellmen params periodically */
1729 if (gnutls_dh_params_init (&dh_params) < 0)
1730 return 0;
1731 if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
1732 return 0;
1734 #if _VNC_DEBUG == 2
1735 gnutls_global_set_log_level(10);
1736 gnutls_global_set_log_function(vnc_debug_gnutls_log);
1737 #endif
1739 tlsinitialized = 1;
1741 return 1;
1744 static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
1746 gnutls_anon_server_credentials anon_cred;
1747 int ret;
1749 if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
1750 VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1751 return NULL;
1754 gnutls_anon_set_server_dh_params(anon_cred, dh_params);
1756 return anon_cred;
1760 static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *vs)
1762 gnutls_certificate_credentials_t x509_cred;
1763 int ret;
1765 if (!vs->x509cacert) {
1766 VNC_DEBUG("No CA x509 certificate specified\n");
1767 return NULL;
1769 if (!vs->x509cert) {
1770 VNC_DEBUG("No server x509 certificate specified\n");
1771 return NULL;
1773 if (!vs->x509key) {
1774 VNC_DEBUG("No server private key specified\n");
1775 return NULL;
1778 if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
1779 VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1780 return NULL;
1782 if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
1783 vs->x509cacert,
1784 GNUTLS_X509_FMT_PEM)) < 0) {
1785 VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
1786 gnutls_certificate_free_credentials(x509_cred);
1787 return NULL;
1790 if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
1791 vs->x509cert,
1792 vs->x509key,
1793 GNUTLS_X509_FMT_PEM)) < 0) {
1794 VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
1795 gnutls_certificate_free_credentials(x509_cred);
1796 return NULL;
1799 if (vs->x509cacrl) {
1800 if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
1801 vs->x509cacrl,
1802 GNUTLS_X509_FMT_PEM)) < 0) {
1803 VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
1804 gnutls_certificate_free_credentials(x509_cred);
1805 return NULL;
1809 gnutls_certificate_set_dh_params (x509_cred, dh_params);
1811 return x509_cred;
1814 static int vnc_validate_certificate(struct VncState *vs)
1816 int ret;
1817 unsigned int status;
1818 const gnutls_datum_t *certs;
1819 unsigned int nCerts, i;
1820 time_t now;
1822 VNC_DEBUG("Validating client certificate\n");
1823 if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) < 0) {
1824 VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
1825 return -1;
1828 if ((now = time(NULL)) == ((time_t)-1)) {
1829 return -1;
1832 if (status != 0) {
1833 if (status & GNUTLS_CERT_INVALID)
1834 VNC_DEBUG("The certificate is not trusted.\n");
1836 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1837 VNC_DEBUG("The certificate hasn't got a known issuer.\n");
1839 if (status & GNUTLS_CERT_REVOKED)
1840 VNC_DEBUG("The certificate has been revoked.\n");
1842 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1843 VNC_DEBUG("The certificate uses an insecure algorithm\n");
1845 return -1;
1846 } else {
1847 VNC_DEBUG("Certificate is valid!\n");
1850 /* Only support x509 for now */
1851 if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509)
1852 return -1;
1854 if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts)))
1855 return -1;
1857 for (i = 0 ; i < nCerts ; i++) {
1858 gnutls_x509_crt_t cert;
1859 VNC_DEBUG ("Checking certificate chain %d\n", i);
1860 if (gnutls_x509_crt_init (&cert) < 0)
1861 return -1;
1863 if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
1864 gnutls_x509_crt_deinit (cert);
1865 return -1;
1868 if (gnutls_x509_crt_get_expiration_time (cert) < now) {
1869 VNC_DEBUG("The certificate has expired\n");
1870 gnutls_x509_crt_deinit (cert);
1871 return -1;
1874 if (gnutls_x509_crt_get_activation_time (cert) > now) {
1875 VNC_DEBUG("The certificate is not yet activated\n");
1876 gnutls_x509_crt_deinit (cert);
1877 return -1;
1880 if (gnutls_x509_crt_get_activation_time (cert) > now) {
1881 VNC_DEBUG("The certificate is not yet activated\n");
1882 gnutls_x509_crt_deinit (cert);
1883 return -1;
1886 gnutls_x509_crt_deinit (cert);
1889 return 0;
1893 static int start_auth_vencrypt_subauth(VncState *vs)
1895 switch (vs->subauth) {
1896 case VNC_AUTH_VENCRYPT_TLSNONE:
1897 case VNC_AUTH_VENCRYPT_X509NONE:
1898 VNC_DEBUG("Accept TLS auth none\n");
1899 vnc_write_u32(vs, 0); /* Accept auth completion */
1900 vnc_read_when(vs, protocol_client_init, 1);
1901 break;
1903 case VNC_AUTH_VENCRYPT_TLSVNC:
1904 case VNC_AUTH_VENCRYPT_X509VNC:
1905 VNC_DEBUG("Start TLS auth VNC\n");
1906 return start_auth_vnc(vs);
1908 default: /* Should not be possible, but just in case */
1909 VNC_DEBUG("Reject auth %d\n", vs->auth);
1910 vnc_write_u8(vs, 1);
1911 if (vs->minor >= 8) {
1912 static const char err[] = "Unsupported authentication type";
1913 vnc_write_u32(vs, sizeof(err));
1914 vnc_write(vs, err, sizeof(err));
1916 vnc_client_error(vs);
1919 return 0;
1922 static void vnc_handshake_io(void *opaque);
1924 static int vnc_continue_handshake(struct VncState *vs) {
1925 int ret;
1927 if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
1928 if (!gnutls_error_is_fatal(ret)) {
1929 VNC_DEBUG("Handshake interrupted (blocking)\n");
1930 if (!gnutls_record_get_direction(vs->tls_session))
1931 qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
1932 else
1933 qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
1934 return 0;
1936 VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
1937 vnc_client_error(vs);
1938 return -1;
1941 if (vs->x509verify) {
1942 if (vnc_validate_certificate(vs) < 0) {
1943 VNC_DEBUG("Client verification failed\n");
1944 vnc_client_error(vs);
1945 return -1;
1946 } else {
1947 VNC_DEBUG("Client verification passed\n");
1951 VNC_DEBUG("Handshake done, switching to TLS data mode\n");
1952 vs->wiremode = VNC_WIREMODE_TLS;
1953 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1955 return start_auth_vencrypt_subauth(vs);
1958 static void vnc_handshake_io(void *opaque) {
1959 struct VncState *vs = (struct VncState *)opaque;
1961 VNC_DEBUG("Handshake IO continue\n");
1962 vnc_continue_handshake(vs);
1965 #define NEED_X509_AUTH(vs) \
1966 ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \
1967 (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \
1968 (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
1971 static int vnc_start_tls(struct VncState *vs) {
1972 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
1973 static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
1974 static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
1975 static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
1977 VNC_DEBUG("Do TLS setup\n");
1978 if (vnc_tls_initialize() < 0) {
1979 VNC_DEBUG("Failed to init TLS\n");
1980 vnc_client_error(vs);
1981 return -1;
1983 if (vs->tls_session == NULL) {
1984 if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
1985 vnc_client_error(vs);
1986 return -1;
1989 if (gnutls_set_default_priority(vs->tls_session) < 0) {
1990 gnutls_deinit(vs->tls_session);
1991 vs->tls_session = NULL;
1992 vnc_client_error(vs);
1993 return -1;
1996 if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) {
1997 gnutls_deinit(vs->tls_session);
1998 vs->tls_session = NULL;
1999 vnc_client_error(vs);
2000 return -1;
2003 if (gnutls_certificate_type_set_priority(vs->tls_session, cert_type_priority) < 0) {
2004 gnutls_deinit(vs->tls_session);
2005 vs->tls_session = NULL;
2006 vnc_client_error(vs);
2007 return -1;
2010 if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 0) {
2011 gnutls_deinit(vs->tls_session);
2012 vs->tls_session = NULL;
2013 vnc_client_error(vs);
2014 return -1;
2017 if (NEED_X509_AUTH(vs)) {
2018 gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs);
2019 if (!x509_cred) {
2020 gnutls_deinit(vs->tls_session);
2021 vs->tls_session = NULL;
2022 vnc_client_error(vs);
2023 return -1;
2025 if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
2026 gnutls_deinit(vs->tls_session);
2027 vs->tls_session = NULL;
2028 gnutls_certificate_free_credentials(x509_cred);
2029 vnc_client_error(vs);
2030 return -1;
2032 if (vs->x509verify) {
2033 VNC_DEBUG("Requesting a client certificate\n");
2034 gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST);
2037 } else {
2038 gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
2039 if (!anon_cred) {
2040 gnutls_deinit(vs->tls_session);
2041 vs->tls_session = NULL;
2042 vnc_client_error(vs);
2043 return -1;
2045 if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
2046 gnutls_deinit(vs->tls_session);
2047 vs->tls_session = NULL;
2048 gnutls_anon_free_server_credentials(anon_cred);
2049 vnc_client_error(vs);
2050 return -1;
2054 gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
2055 gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
2056 gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
2059 VNC_DEBUG("Start TLS handshake process\n");
2060 return vnc_continue_handshake(vs);
2063 static int protocol_client_vencrypt_auth(VncState *vs, char *data, size_t len)
2065 int auth = read_u32(data, 0);
2067 if (auth != vs->subauth) {
2068 VNC_DEBUG("Rejecting auth %d\n", auth);
2069 vnc_write_u8(vs, 0); /* Reject auth */
2070 vnc_flush(vs);
2071 vnc_client_error(vs);
2072 } else {
2073 VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
2074 vnc_write_u8(vs, 1); /* Accept auth */
2075 vnc_flush(vs);
2077 if (vnc_start_tls(vs) < 0) {
2078 VNC_DEBUG("Failed to complete TLS\n");
2079 return 0;
2082 if (vs->wiremode == VNC_WIREMODE_TLS) {
2083 VNC_DEBUG("Starting VeNCrypt subauth\n");
2084 return start_auth_vencrypt_subauth(vs);
2085 } else {
2086 VNC_DEBUG("TLS handshake blocked\n");
2087 return 0;
2090 return 0;
2093 static int protocol_client_vencrypt_init(VncState *vs, char *data, size_t len)
2095 if (data[0] != 0 ||
2096 data[1] != 2) {
2097 VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
2098 vnc_write_u8(vs, 1); /* Reject version */
2099 vnc_flush(vs);
2100 vnc_client_error(vs);
2101 } else {
2102 VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
2103 vnc_write_u8(vs, 0); /* Accept version */
2104 vnc_write_u8(vs, 1); /* Number of sub-auths */
2105 vnc_write_u32(vs, vs->subauth); /* The supported auth */
2106 vnc_flush(vs);
2107 vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
2109 return 0;
2112 static int start_auth_vencrypt(VncState *vs)
2114 /* Send VeNCrypt version 0.2 */
2115 vnc_write_u8(vs, 0);
2116 vnc_write_u8(vs, 2);
2118 vnc_read_when(vs, protocol_client_vencrypt_init, 2);
2119 return 0;
2121 #endif /* CONFIG_VNC_TLS */
2123 static int protocol_client_auth(VncState *vs, char *data, size_t len)
2125 /* We only advertise 1 auth scheme at a time, so client
2126 * must pick the one we sent. Verify this */
2127 if (data[0] != vs->auth) { /* Reject auth */
2128 VNC_DEBUG("Reject auth %d\n", (int)data[0]);
2129 vnc_write_u32(vs, 1);
2130 if (vs->minor >= 8) {
2131 static const char err[] = "Authentication failed";
2132 vnc_write_u32(vs, sizeof(err));
2133 vnc_write(vs, err, sizeof(err));
2135 vnc_client_error(vs);
2136 } else { /* Accept requested auth */
2137 VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2138 switch (vs->auth) {
2139 case VNC_AUTH_NONE:
2140 VNC_DEBUG("Accept auth none\n");
2141 if (vs->minor >= 8) {
2142 vnc_write_u32(vs, 0); /* Accept auth completion */
2143 vnc_flush(vs);
2145 vnc_read_when(vs, protocol_client_init, 1);
2146 break;
2148 case VNC_AUTH_VNC:
2149 VNC_DEBUG("Start VNC auth\n");
2150 return start_auth_vnc(vs);
2152 #if CONFIG_VNC_TLS
2153 case VNC_AUTH_VENCRYPT:
2154 VNC_DEBUG("Accept VeNCrypt auth\n");;
2155 return start_auth_vencrypt(vs);
2156 #endif /* CONFIG_VNC_TLS */
2158 default: /* Should not be possible, but just in case */
2159 VNC_DEBUG("Reject auth %d\n", vs->auth);
2160 vnc_write_u8(vs, 1);
2161 if (vs->minor >= 8) {
2162 static const char err[] = "Authentication failed";
2163 vnc_write_u32(vs, sizeof(err));
2164 vnc_write(vs, err, sizeof(err));
2166 vnc_client_error(vs);
2169 return 0;
2172 static int protocol_version(VncState *vs, char *version, size_t len)
2174 char local[13];
2176 memcpy(local, version, 12);
2177 local[12] = 0;
2179 if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
2180 VNC_DEBUG("Malformed protocol version %s\n", local);
2181 vnc_client_error(vs);
2182 return 0;
2184 VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2185 if (vs->major != 3 ||
2186 (vs->minor != 3 &&
2187 vs->minor != 4 &&
2188 vs->minor != 5 &&
2189 vs->minor != 7 &&
2190 vs->minor != 8)) {
2191 VNC_DEBUG("Unsupported client version\n");
2192 vnc_write_u32(vs, VNC_AUTH_INVALID);
2193 vnc_flush(vs);
2194 vnc_client_error(vs);
2195 return 0;
2197 /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
2198 * as equivalent to v3.3 by servers
2199 */
2200 if (vs->minor == 4 || vs->minor == 5)
2201 vs->minor = 3;
2203 if (vs->minor == 3) {
2204 if (vs->auth == VNC_AUTH_NONE) {
2205 VNC_DEBUG("Tell client auth none\n");
2206 vnc_write_u32(vs, vs->auth);
2207 vnc_flush(vs);
2208 vnc_read_when(vs, protocol_client_init, 1);
2209 } else if (vs->auth == VNC_AUTH_VNC) {
2210 VNC_DEBUG("Tell client VNC auth\n");
2211 vnc_write_u32(vs, vs->auth);
2212 vnc_flush(vs);
2213 start_auth_vnc(vs);
2214 } else {
2215 VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
2216 vnc_write_u32(vs, VNC_AUTH_INVALID);
2217 vnc_flush(vs);
2218 vnc_client_error(vs);
2220 } else {
2221 VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
2222 vnc_write_u8(vs, 1); /* num auth */
2223 vnc_write_u8(vs, vs->auth);
2224 vnc_read_when(vs, protocol_client_auth, 1);
2225 vnc_flush(vs);
2228 return 0;
2231 static void vnc_listen_read(void *opaque)
2233 VncState *vs = opaque;
2234 struct sockaddr_in addr;
2235 socklen_t addrlen = sizeof(addr);
2237 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2238 if (vs->csock != -1) {
2239 VNC_DEBUG("New client on socket %d\n", vs->csock);
2240 socket_set_nonblock(vs->csock);
2241 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
2242 vnc_write(vs, "RFB 003.008\n", 12);
2243 vnc_flush(vs);
2244 vnc_read_when(vs, protocol_version, 12);
2245 framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
2246 vs->has_resize = 0;
2247 vs->has_hextile = 0;
2248 vs->ds->dpy_copy = NULL;
2249 vnc_timer_init(vs);
2253 extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
2255 void vnc_display_init(DisplayState *ds)
2257 VncState *vs;
2259 vs = qemu_mallocz(sizeof(VncState));
2260 if (!vs)
2261 exit(1);
2263 ds->opaque = vs;
2264 vnc_state = vs;
2265 vs->display = NULL;
2266 vs->password = NULL;
2268 vs->lsock = -1;
2269 vs->csock = -1;
2270 vs->last_x = -1;
2271 vs->last_y = -1;
2273 vs->ds = ds;
2275 if (!keyboard_layout)
2276 keyboard_layout = "en-us";
2278 vs->kbd_layout = init_keyboard_layout(keyboard_layout);
2279 if (!vs->kbd_layout)
2280 exit(1);
2281 vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
2283 vs->ds->data = NULL;
2284 vs->ds->dpy_update = vnc_dpy_update;
2285 vs->ds->dpy_resize = vnc_dpy_resize;
2286 vs->ds->dpy_colourdepth = vnc_dpy_colourdepth;
2287 vs->ds->dpy_refresh = vnc_dpy_refresh;
2289 vs->ds->width = 640;
2290 vs->ds->height = 400;
2291 vnc_dpy_colourdepth(vs->ds, 32);
2294 #if CONFIG_VNC_TLS
2295 static int vnc_set_x509_credential(VncState *vs,
2296 const char *certdir,
2297 const char *filename,
2298 char **cred,
2299 int ignoreMissing)
2301 struct stat sb;
2303 if (*cred) {
2304 qemu_free(*cred);
2305 *cred = NULL;
2308 if (!(*cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2)))
2309 return -1;
2311 strcpy(*cred, certdir);
2312 strcat(*cred, "/");
2313 strcat(*cred, filename);
2315 VNC_DEBUG("Check %s\n", *cred);
2316 if (stat(*cred, &sb) < 0) {
2317 qemu_free(*cred);
2318 *cred = NULL;
2319 if (ignoreMissing && errno == ENOENT)
2320 return 0;
2321 return -1;
2324 return 0;
2327 static int vnc_set_x509_credential_dir(VncState *vs,
2328 const char *certdir)
2330 if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0)
2331 goto cleanup;
2332 if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 1) < 0)
2333 goto cleanup;
2334 if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, &vs->x509cert, 0) < 0)
2335 goto cleanup;
2336 if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, &vs->x509key, 0) < 0)
2337 goto cleanup;
2339 return 0;
2341 cleanup:
2342 qemu_free(vs->x509cacert);
2343 qemu_free(vs->x509cacrl);
2344 qemu_free(vs->x509cert);
2345 qemu_free(vs->x509key);
2346 vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
2347 return -1;
2349 #endif /* CONFIG_VNC_TLS */
2351 void vnc_display_close(DisplayState *ds)
2353 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2355 if (vs->display) {
2356 qemu_free(vs->display);
2357 vs->display = NULL;
2359 if (vs->lsock != -1) {
2360 qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2361 close(vs->lsock);
2362 vs->lsock = -1;
2364 if (vs->csock != -1) {
2365 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
2366 closesocket(vs->csock);
2367 vs->csock = -1;
2368 buffer_reset(&vs->input);
2369 buffer_reset(&vs->output);
2370 #if CONFIG_VNC_TLS
2371 if (vs->tls_session) {
2372 gnutls_deinit(vs->tls_session);
2373 vs->tls_session = NULL;
2375 vs->wiremode = VNC_WIREMODE_CLEAR;
2376 #endif /* CONFIG_VNC_TLS */
2378 vs->auth = VNC_AUTH_INVALID;
2379 #if CONFIG_VNC_TLS
2380 vs->subauth = VNC_AUTH_INVALID;
2381 vs->x509verify = 0;
2382 #endif
2385 int parse_host_port(struct sockaddr_in *saddr, const char *str);
2389 int vnc_display_password(DisplayState *ds, const char *password)
2391 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2393 if (vs->password) {
2394 qemu_free(vs->password);
2395 vs->password = NULL;
2397 if (password && password[0]) {
2398 if (!(vs->password = qemu_strdup(password)))
2399 return -1;
2402 return 0;
2405 int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
2407 struct sockaddr *addr;
2408 struct sockaddr_in iaddr;
2409 #ifndef NO_UNIX_SOCKETS
2410 struct sockaddr_un uaddr;
2411 #endif
2412 #ifndef CONFIG_STUBDOM
2413 int reuse_addr, ret;
2414 #endif
2415 socklen_t addrlen;
2416 const char *p;
2417 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2418 const char *options;
2419 int password = 0;
2420 #if CONFIG_VNC_TLS
2421 int tls = 0, x509 = 0;
2422 #endif
2424 if (display == NULL)
2425 display = "localhost:0";
2427 vnc_display_close(ds);
2428 if (strcmp(display, "none") == 0)
2429 return 0;
2431 if (!(vs->display = strdup(display)))
2432 return -1;
2434 options = display;
2435 while ((options = strchr(options, ','))) {
2436 options++;
2437 if (strncmp(options, "password", 8) == 0) {
2438 password = 1; /* Require password auth */
2439 #if CONFIG_VNC_TLS
2440 } else if (strncmp(options, "tls", 3) == 0) {
2441 tls = 1; /* Require TLS */
2442 } else if (strncmp(options, "x509", 4) == 0) {
2443 char *start, *end;
2444 x509 = 1; /* Require x509 certificates */
2445 if (strncmp(options, "x509verify", 10) == 0)
2446 vs->x509verify = 1; /* ...and verify client certs */
2448 /* Now check for 'x509=/some/path' postfix
2449 * and use that to setup x509 certificate/key paths */
2450 start = strchr(options, '=');
2451 end = strchr(options, ',');
2452 if (start && (!end || (start < end))) {
2453 int len = end ? end-(start+1) : strlen(start+1);
2454 char *path = qemu_malloc(len+1);
2455 strncpy(path, start+1, len);
2456 path[len] = '\0';
2457 VNC_DEBUG("Trying certificate path '%s'\n", path);
2458 if (vnc_set_x509_credential_dir(vs, path) < 0) {
2459 fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2460 qemu_free(path);
2461 qemu_free(vs->display);
2462 vs->display = NULL;
2463 return -1;
2465 qemu_free(path);
2466 } else {
2467 fprintf(stderr, "No certificate path provided\n");
2468 qemu_free(vs->display);
2469 vs->display = NULL;
2470 return -1;
2472 #endif
2476 if (password) {
2477 #if CONFIG_VNC_TLS
2478 if (tls) {
2479 vs->auth = VNC_AUTH_VENCRYPT;
2480 if (x509) {
2481 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
2482 vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
2483 } else {
2484 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
2485 vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
2487 } else {
2488 #endif
2489 VNC_DEBUG("Initializing VNC server with password auth\n");
2490 vs->auth = VNC_AUTH_VNC;
2491 #if CONFIG_VNC_TLS
2492 vs->subauth = VNC_AUTH_INVALID;
2494 #endif
2495 } else {
2496 #if CONFIG_VNC_TLS
2497 if (tls) {
2498 vs->auth = VNC_AUTH_VENCRYPT;
2499 if (x509) {
2500 VNC_DEBUG("Initializing VNC server with x509 no auth\n");
2501 vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
2502 } else {
2503 VNC_DEBUG("Initializing VNC server with TLS no auth\n");
2504 vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
2506 } else {
2507 #endif
2508 VNC_DEBUG("Initializing VNC server with no auth\n");
2509 vs->auth = VNC_AUTH_NONE;
2510 #if CONFIG_VNC_TLS
2511 vs->subauth = VNC_AUTH_INVALID;
2513 #endif
2515 #ifndef NO_UNIX_SOCKETS
2516 if (strstart(display, "unix:", &p)) {
2517 addr = (struct sockaddr *)&uaddr;
2518 addrlen = sizeof(uaddr);
2520 vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
2521 if (vs->lsock == -1) {
2522 fprintf(stderr, "Could not create socket\n");
2523 free(vs->display);
2524 vs->display = NULL;
2525 return -1;
2528 uaddr.sun_family = AF_UNIX;
2529 memset(uaddr.sun_path, 0, 108);
2530 snprintf(uaddr.sun_path, 108, "%s", p);
2532 unlink(uaddr.sun_path);
2533 } else
2534 #endif
2536 addr = (struct sockaddr *)&iaddr;
2537 addrlen = sizeof(iaddr);
2539 if (parse_host_port(&iaddr, display) < 0) {
2540 fprintf(stderr, "Could not parse VNC address\n");
2541 free(vs->display);
2542 vs->display = NULL;
2543 return -1;
2546 #ifdef CONFIG_STUBDOM
2548 struct ip_addr ipaddr = { iaddr.sin_addr.s_addr };
2549 struct ip_addr netmask = { 0 };
2550 struct ip_addr gw = { 0 };
2551 networking_set_addr(&ipaddr, &netmask, &gw);
2553 #endif
2555 iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
2557 vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
2558 if (vs->lsock == -1) {
2559 fprintf(stderr, "Could not create socket\n");
2560 free(vs->display);
2561 vs->display = NULL;
2562 return -1;
2565 #ifndef CONFIG_STUBDOM
2566 reuse_addr = 1;
2567 ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
2568 (const char *)&reuse_addr, sizeof(reuse_addr));
2569 if (ret == -1) {
2570 fprintf(stderr, "setsockopt() failed\n");
2571 close(vs->lsock);
2572 vs->lsock = -1;
2573 free(vs->display);
2574 vs->display = NULL;
2575 return -1;
2577 #endif
2580 while (bind(vs->lsock, addr, addrlen) == -1) {
2581 if (find_unused && errno == EADDRINUSE) {
2582 iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 1);
2583 continue;
2585 fprintf(stderr, "bind() failed\n");
2586 close(vs->lsock);
2587 vs->lsock = -1;
2588 free(vs->display);
2589 vs->display = NULL;
2590 return -1;
2593 if (listen(vs->lsock, 1) == -1) {
2594 fprintf(stderr, "listen() failed\n");
2595 close(vs->lsock);
2596 vs->lsock = -1;
2597 free(vs->display);
2598 vs->display = NULL;
2599 return -1;
2602 if (qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs) < 0)
2603 return -1;
2605 return ntohs(iaddr.sin_port);
2608 #ifndef CONFIG_STUBDOM
2609 int vnc_start_viewer(int port)
2611 int pid, i, open_max;
2612 char s[16];
2614 sprintf(s, ":%d", port);
2616 switch (pid = fork()) {
2617 case -1:
2618 fprintf(stderr, "vncviewer failed fork\n");
2619 exit(1);
2621 case 0: /* child */
2622 open_max = sysconf(_SC_OPEN_MAX);
2623 for (i = 0; i < open_max; i++)
2624 if (i != STDIN_FILENO &&
2625 i != STDOUT_FILENO &&
2626 i != STDERR_FILENO)
2627 close(i);
2628 execlp("vncviewer", "vncviewer", s, NULL);
2629 fprintf(stderr, "vncviewer execlp failed\n");
2630 exit(1);
2632 default:
2633 return pid;
2636 #endif