ia64/xen-unstable

view tools/ioemu/vnc.c @ 15841:c5f735271e22

[IA64] Foreign p2m: Fix vti domain builder.

It should set arch_domain::convmem_end.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Thu Sep 06 13:48:43 2007 -0600 (2007-09-06)
parents c64f2a0dc2d7
children 04cc0e22a20a
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 "vl.h"
28 #include "qemu_socket.h"
29 #include <assert.h>
31 /* The refresh interval starts at BASE. If we scan the buffer and
32 find no change, we increase by INC, up to MAX. If the mouse moves
33 or we get a keypress, the interval is set back to BASE. If we find
34 an update, halve the interval.
36 All times in milliseconds. */
37 #define VNC_REFRESH_INTERVAL_BASE 30
38 #define VNC_REFRESH_INTERVAL_INC 50
39 #define VNC_REFRESH_INTERVAL_MAX 2000
41 /* Wait at most one second between updates, so that we can detect a
42 minimised vncviewer reasonably quickly. */
43 #define VNC_MAX_UPDATE_INTERVAL 5000
45 #include "vnc_keysym.h"
46 #include "keymaps.c"
47 #include "d3des.h"
49 typedef struct Buffer
50 {
51 size_t capacity;
52 size_t offset;
53 uint8_t *buffer;
54 } Buffer;
56 typedef struct VncState VncState;
58 typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
60 typedef void VncWritePixels(VncState *vs, void *data, int size);
62 typedef void VncSendHextileTile(VncState *vs,
63 int x, int y, int w, int h,
64 uint32_t *last_bg,
65 uint32_t *last_fg,
66 int *has_bg, int *has_fg);
68 #if 0
69 #define VNC_MAX_WIDTH 2048
70 #define VNC_MAX_HEIGHT 2048
71 #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
72 #endif
74 struct VncState
75 {
76 QEMUTimer *timer;
77 int timer_interval;
78 int64_t last_update_time;
79 int lsock;
80 int csock;
81 DisplayState *ds;
82 int width;
83 int height;
84 uint64_t *dirty_row; /* screen regions which are possibly dirty */
85 int dirty_pixel_shift;
86 uint64_t *update_row; /* outstanding updates */
87 int has_update; /* there's outstanding updates in the
88 * visible area */
89 uint8_t *old_data;
90 int depth; /* internal VNC frame buffer byte per pixel */
91 int has_resize;
92 int has_hextile;
93 int has_pointer_type_change;
94 int absolute;
95 int last_x;
96 int last_y;
98 const char *display;
100 Buffer output;
101 Buffer input;
102 kbd_layout_t *kbd_layout;
103 /* current output mode information */
104 VncWritePixels *write_pixels;
105 VncSendHextileTile *send_hextile_tile;
106 int pix_bpp, pix_big_endian;
107 int red_shift, red_max, red_shift1;
108 int green_shift, green_max, green_shift1;
109 int blue_shift, blue_max, blue_shift1;
111 VncReadEvent *read_handler;
112 size_t read_handler_expect;
114 int visible_x;
115 int visible_y;
116 int visible_w;
117 int visible_h;
119 /* input */
120 uint8_t modifiers_state[256];
121 };
123 static VncState *vnc_state; /* needed for info vnc */
125 #define DIRTY_PIXEL_BITS 64
126 #define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift)
127 #define X2DP_UP(vs, x) \
128 (((x) + (1ULL << (vs)->dirty_pixel_shift) - 1) >> (vs)->dirty_pixel_shift)
129 #define DP2X(vs, x) ((x) << (vs)->dirty_pixel_shift)
131 void do_info_vnc(void)
132 {
133 if (vnc_state == NULL)
134 term_printf("VNC server disabled\n");
135 else {
136 term_printf("VNC server active on: ");
137 term_print_filename(vnc_state->display);
138 term_printf("\n");
140 if (vnc_state->csock == -1)
141 term_printf("No client connected\n");
142 else
143 term_printf("Client connected\n");
144 }
145 }
147 /* TODO
148 1) Get the queue working for IO.
149 2) there is some weirdness when using the -S option (the screen is grey
150 and not totally invalidated
151 3) resolutions > 1024
152 */
154 static void vnc_write(VncState *vs, const void *data, size_t len);
155 static void vnc_write_u32(VncState *vs, uint32_t value);
156 static void vnc_write_s32(VncState *vs, int32_t value);
157 static void vnc_write_u16(VncState *vs, uint16_t value);
158 static void vnc_write_u8(VncState *vs, uint8_t value);
159 static void vnc_flush(VncState *vs);
160 static void _vnc_update_client(void *opaque);
161 static void vnc_update_client(void *opaque);
162 static void vnc_client_read(void *opaque);
163 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
164 static int make_challenge(unsigned char *random, int size);
165 static void set_seed(unsigned int *seedp);
166 static void get_random(int len, unsigned char *buf);
168 #if 0
169 static inline void vnc_set_bit(uint32_t *d, int k)
170 {
171 d[k >> 5] |= 1 << (k & 0x1f);
172 }
174 static inline void vnc_clear_bit(uint32_t *d, int k)
175 {
176 d[k >> 5] &= ~(1 << (k & 0x1f));
177 }
179 static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
180 {
181 int j;
183 j = 0;
184 while (n >= 32) {
185 d[j++] = -1;
186 n -= 32;
187 }
188 if (n > 0)
189 d[j++] = (1 << n) - 1;
190 while (j < nb_words)
191 d[j++] = 0;
192 }
194 static inline int vnc_get_bit(const uint32_t *d, int k)
195 {
196 return (d[k >> 5] >> (k & 0x1f)) & 1;
197 }
199 static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
200 int nb_words)
201 {
202 int i;
203 for(i = 0; i < nb_words; i++) {
204 if ((d1[i] & d2[i]) != 0)
205 return 1;
206 }
207 return 0;
208 }
209 #endif
211 static void set_bits_in_row(VncState *vs, uint64_t *row,
212 int x, int y, int w, int h)
213 {
214 int x1, x2;
215 uint64_t mask;
217 if (w == 0)
218 return;
220 x1 = X2DP_DOWN(vs, x);
221 x2 = X2DP_UP(vs, x + w);
223 if (X2DP_UP(vs, w) != DIRTY_PIXEL_BITS)
224 mask = ((1ULL << (x2 - x1)) - 1) << x1;
225 else
226 mask = ~(0ULL);
228 h += y;
229 if (h > vs->ds->height)
230 h = vs->ds->height;
231 for (; y < h; y++)
232 row[y] |= mask;
233 }
235 static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
236 {
237 VncState *vs = ds->opaque;
239 set_bits_in_row(vs, vs->dirty_row, x, y, w, h);
240 }
242 static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
243 int32_t encoding)
244 {
245 vnc_write_u16(vs, x);
246 vnc_write_u16(vs, y);
247 vnc_write_u16(vs, w);
248 vnc_write_u16(vs, h);
250 vnc_write_s32(vs, encoding);
251 }
253 static void vnc_dpy_resize(DisplayState *ds, int w, int h)
254 {
255 int size_changed;
256 VncState *vs = ds->opaque;
257 int o;
259 ds->data = realloc(ds->data, w * h * vs->depth);
260 vs->old_data = realloc(vs->old_data, w * h * vs->depth);
261 vs->dirty_row = realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0]));
262 vs->update_row = realloc(vs->update_row, h * sizeof(vs->dirty_row[0]));
264 if (ds->data == NULL || vs->old_data == NULL ||
265 vs->dirty_row == NULL || vs->update_row == NULL) {
266 fprintf(stderr, "vnc: memory allocation failed\n");
267 exit(1);
268 }
270 if (ds->depth != vs->depth * 8) {
271 ds->depth = vs->depth * 8;
272 set_color_table(ds);
273 }
274 size_changed = ds->width != w || ds->height != h;
275 ds->width = w;
276 ds->height = h;
277 ds->linesize = w * vs->depth;
278 if (vs->csock != -1 && vs->has_resize && size_changed) {
279 vnc_write_u8(vs, 0); /* msg id */
280 vnc_write_u8(vs, 0);
281 vnc_write_u16(vs, 1); /* number of rects */
282 vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
283 vnc_flush(vs);
284 vs->width = ds->width;
285 vs->height = ds->height;
286 }
287 vs->dirty_pixel_shift = 0;
288 for (o = DIRTY_PIXEL_BITS; o < ds->width; o *= 2)
289 vs->dirty_pixel_shift++;
290 framebuffer_set_updated(vs, 0, 0, ds->width, ds->height);
291 }
293 /* fastest code */
294 static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
295 {
296 vnc_write(vs, pixels, size);
297 }
299 /* slowest but generic code. */
300 static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
301 {
302 unsigned int r, g, b;
304 r = (v >> vs->red_shift1) & vs->red_max;
305 g = (v >> vs->green_shift1) & vs->green_max;
306 b = (v >> vs->blue_shift1) & vs->blue_max;
307 v = (r << vs->red_shift) |
308 (g << vs->green_shift) |
309 (b << vs->blue_shift);
310 switch(vs->pix_bpp) {
311 case 1:
312 buf[0] = v;
313 break;
314 case 2:
315 if (vs->pix_big_endian) {
316 buf[0] = v >> 8;
317 buf[1] = v;
318 } else {
319 buf[1] = v >> 8;
320 buf[0] = v;
321 }
322 break;
323 default:
324 case 4:
325 if (vs->pix_big_endian) {
326 buf[0] = v >> 24;
327 buf[1] = v >> 16;
328 buf[2] = v >> 8;
329 buf[3] = v;
330 } else {
331 buf[3] = v >> 24;
332 buf[2] = v >> 16;
333 buf[1] = v >> 8;
334 buf[0] = v;
335 }
336 break;
337 }
338 }
340 static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
341 {
342 uint32_t *pixels = pixels1;
343 uint8_t buf[4];
344 int n, i;
346 n = size >> 2;
347 for(i = 0; i < n; i++) {
348 vnc_convert_pixel(vs, buf, pixels[i]);
349 vnc_write(vs, buf, vs->pix_bpp);
350 }
351 }
353 static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
354 {
355 int i;
356 uint8_t *row;
358 vnc_framebuffer_update(vs, x, y, w, h, 0);
360 row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
361 for (i = 0; i < h; i++) {
362 vs->write_pixels(vs, row, w * vs->depth);
363 row += vs->ds->linesize;
364 }
365 }
367 static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
368 {
369 ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
370 ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
371 }
373 #define BPP 8
374 #include "vnchextile.h"
375 #undef BPP
377 #define BPP 16
378 #include "vnchextile.h"
379 #undef BPP
381 #define BPP 32
382 #include "vnchextile.h"
383 #undef BPP
385 #define GENERIC
386 #define BPP 32
387 #include "vnchextile.h"
388 #undef BPP
389 #undef GENERIC
391 static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
392 {
393 int i, j;
394 int has_fg, has_bg;
395 uint32_t last_fg32, last_bg32;
397 vnc_framebuffer_update(vs, x, y, w, h, 5);
399 has_fg = has_bg = 0;
400 for (j = y; j < (y + h); j += 16) {
401 for (i = x; i < (x + w); i += 16) {
402 vs->send_hextile_tile(vs, i, j,
403 MIN(16, x + w - i), MIN(16, y + h - j),
404 &last_bg32, &last_fg32, &has_bg, &has_fg);
405 }
406 }
407 }
409 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
410 {
411 if (vs->has_hextile)
412 send_framebuffer_update_hextile(vs, x, y, w, h);
413 else
414 send_framebuffer_update_raw(vs, x, y, w, h);
415 }
417 static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
418 {
419 int src, dst;
420 uint8_t *src_row;
421 uint8_t *dst_row;
422 uint8_t *old_row;
423 int y = 0;
424 int pitch = ds->linesize;
425 VncState *vs = ds->opaque;
426 int updating_client = 1;
428 if (src_x < vs->visible_x || src_y < vs->visible_y ||
429 dst_x < vs->visible_x || dst_y < vs->visible_y ||
430 (src_x + w) > (vs->visible_x + vs->visible_w) ||
431 (src_y + h) > (vs->visible_y + vs->visible_h) ||
432 (dst_x + w) > (vs->visible_x + vs->visible_w) ||
433 (dst_y + h) > (vs->visible_y + vs->visible_h))
434 updating_client = 0;
436 if (updating_client)
437 _vnc_update_client(vs);
439 if (dst_y > src_y) {
440 y = h - 1;
441 pitch = -pitch;
442 }
444 src = (ds->linesize * (src_y + y) + vs->depth * src_x);
445 dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
447 src_row = ds->data + src;
448 dst_row = ds->data + dst;
449 old_row = vs->old_data + dst;
451 for (y = 0; y < h; y++) {
452 memmove(old_row, src_row, w * vs->depth);
453 memmove(dst_row, src_row, w * vs->depth);
454 src_row += pitch;
455 dst_row += pitch;
456 old_row += pitch;
457 }
459 if (updating_client && vs->csock != -1 && !vs->has_update) {
460 vnc_write_u8(vs, 0); /* msg id */
461 vnc_write_u8(vs, 0);
462 vnc_write_u16(vs, 1); /* number of rects */
463 vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
464 vnc_write_u16(vs, src_x);
465 vnc_write_u16(vs, src_y);
466 vnc_flush(vs);
467 } else
468 framebuffer_set_updated(vs, dst_x, dst_y, w, h);
469 }
471 static int find_update_height(VncState *vs, int y, int maxy, int last_x, int x)
472 {
473 int h;
475 for (h = 1; y + h < maxy; h++) {
476 int tmp_x;
477 if (!(vs->update_row[y + h] & (1ULL << last_x)))
478 break;
479 for (tmp_x = last_x; tmp_x < x; tmp_x++)
480 vs->update_row[y + h] &= ~(1ULL << tmp_x);
481 }
483 return h;
484 }
486 static void _vnc_update_client(void *opaque)
487 {
488 VncState *vs = opaque;
489 int64_t now;
490 int y;
491 uint8_t *row;
492 uint8_t *old_row;
493 uint64_t width_mask;
494 int n_rectangles;
495 int saved_offset;
496 int maxx, maxy;
497 int tile_bytes = vs->depth * DP2X(vs, 1);
499 if (vs->csock == -1)
500 return;
502 now = qemu_get_clock(rt_clock);
504 if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))
505 width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;
506 else
507 width_mask = ~(0ULL);
509 /* Walk through the dirty map and eliminate tiles that really
510 aren't dirty */
511 row = vs->ds->data;
512 old_row = vs->old_data;
514 for (y = 0; y < vs->ds->height; y++) {
515 if (vs->dirty_row[y] & width_mask) {
516 int x;
517 uint8_t *ptr, *old_ptr;
519 ptr = row;
520 old_ptr = old_row;
522 for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {
523 if (vs->dirty_row[y] & (1ULL << x)) {
524 if (memcmp(old_ptr, ptr, tile_bytes)) {
525 vs->has_update = 1;
526 vs->update_row[y] |= (1ULL << x);
527 memcpy(old_ptr, ptr, tile_bytes);
528 }
529 vs->dirty_row[y] &= ~(1ULL << x);
530 }
532 ptr += tile_bytes;
533 old_ptr += tile_bytes;
534 }
535 }
537 row += vs->ds->linesize;
538 old_row += vs->ds->linesize;
539 }
541 if (!vs->has_update || vs->visible_y >= vs->ds->height ||
542 vs->visible_x >= vs->ds->width)
543 goto backoff;
545 /* Count rectangles */
546 n_rectangles = 0;
547 vnc_write_u8(vs, 0); /* msg id */
548 vnc_write_u8(vs, 0);
549 saved_offset = vs->output.offset;
550 vnc_write_u16(vs, 0);
552 maxy = vs->visible_y + vs->visible_h;
553 if (maxy > vs->ds->height)
554 maxy = vs->ds->height;
555 maxx = vs->visible_x + vs->visible_w;
556 if (maxx > vs->ds->width)
557 maxx = vs->ds->width;
559 for (y = vs->visible_y; y < maxy; y++) {
560 int x;
561 int last_x = -1;
562 for (x = X2DP_DOWN(vs, vs->visible_x);
563 x < X2DP_UP(vs, maxx); x++) {
564 if (vs->update_row[y] & (1ULL << x)) {
565 if (last_x == -1)
566 last_x = x;
567 vs->update_row[y] &= ~(1ULL << x);
568 } else {
569 if (last_x != -1) {
570 int h = find_update_height(vs, y, maxy, last_x, x);
571 if (h != 0) {
572 send_framebuffer_update(vs, DP2X(vs, last_x), y,
573 DP2X(vs, (x - last_x)), h);
574 n_rectangles++;
575 }
576 }
577 last_x = -1;
578 }
579 }
580 if (last_x != -1) {
581 int h = find_update_height(vs, y, maxy, last_x, x);
582 if (h != 0) {
583 send_framebuffer_update(vs, DP2X(vs, last_x), y,
584 DP2X(vs, (x - last_x)), h);
585 n_rectangles++;
586 }
587 }
588 }
589 vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
590 vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
592 if (n_rectangles == 0)
593 goto backoff;
595 vs->has_update = 0;
596 vnc_flush(vs);
597 vs->last_update_time = now;
599 vs->timer_interval /= 2;
600 if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE)
601 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
603 return;
605 backoff:
606 /* No update -> back off a bit */
607 vs->timer_interval += VNC_REFRESH_INTERVAL_INC;
608 if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) {
609 vs->timer_interval = VNC_REFRESH_INTERVAL_MAX;
610 if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) {
611 /* Send a null update. If the client is no longer
612 interested (e.g. minimised) it'll ignore this, and we
613 can stop scanning the buffer until it sends another
614 update request. */
615 /* It turns out that there's a bug in realvncviewer 4.1.2
616 which means that if you send a proper null update (with
617 no update rectangles), it gets a bit out of sync and
618 never sends any further requests, regardless of whether
619 it needs one or not. Fix this by sending a single 1x1
620 update rectangle instead. */
621 vnc_write_u8(vs, 0);
622 vnc_write_u8(vs, 0);
623 vnc_write_u16(vs, 1);
624 send_framebuffer_update(vs, 0, 0, 1, 1);
625 vnc_flush(vs);
626 vs->last_update_time = now;
627 return;
628 }
629 }
630 qemu_mod_timer(vs->timer, now + vs->timer_interval);
631 return;
632 }
634 static void vnc_update_client(void *opaque)
635 {
636 VncState *vs = opaque;
638 vs->ds->dpy_refresh(vs->ds);
639 _vnc_update_client(vs);
640 }
642 static void vnc_timer_init(VncState *vs)
643 {
644 if (vs->timer == NULL) {
645 vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
646 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
647 }
648 }
650 static void vnc_dpy_refresh(DisplayState *ds)
651 {
652 vga_hw_update();
653 }
655 static int vnc_listen_poll(void *opaque)
656 {
657 VncState *vs = opaque;
658 if (vs->csock == -1)
659 return 1;
660 return 0;
661 }
663 static void buffer_reserve(Buffer *buffer, size_t len)
664 {
665 if ((buffer->capacity - buffer->offset) < len) {
666 buffer->capacity += (len + 1024);
667 buffer->buffer = realloc(buffer->buffer, buffer->capacity);
668 if (buffer->buffer == NULL) {
669 fprintf(stderr, "vnc: out of memory\n");
670 exit(1);
671 }
672 }
673 }
675 static int buffer_empty(Buffer *buffer)
676 {
677 return buffer->offset == 0;
678 }
680 static uint8_t *buffer_end(Buffer *buffer)
681 {
682 return buffer->buffer + buffer->offset;
683 }
685 static void buffer_reset(Buffer *buffer)
686 {
687 buffer->offset = 0;
688 }
690 static void buffer_append(Buffer *buffer, const void *data, size_t len)
691 {
692 memcpy(buffer->buffer + buffer->offset, data, len);
693 buffer->offset += len;
694 }
696 static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
697 {
698 if (ret == 0 || ret == -1) {
699 if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
700 return 0;
702 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
703 closesocket(vs->csock);
704 vs->csock = -1;
705 buffer_reset(&vs->input);
706 buffer_reset(&vs->output);
707 return 0;
708 }
709 return ret;
710 }
712 static void vnc_client_error(VncState *vs)
713 {
714 vnc_client_io_error(vs, -1, EINVAL);
715 }
717 static void vnc_client_write(void *opaque)
718 {
719 long ret;
720 VncState *vs = opaque;
722 ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
723 ret = vnc_client_io_error(vs, ret, socket_error());
724 if (!ret)
725 return;
727 memmove(vs->output.buffer, vs->output.buffer + ret,
728 vs->output.offset - ret);
729 vs->output.offset -= ret;
731 if (vs->output.offset == 0)
732 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
733 }
735 static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
736 {
737 vs->read_handler = func;
738 vs->read_handler_expect = expecting;
739 }
741 static void vnc_client_read(void *opaque)
742 {
743 VncState *vs = opaque;
744 long ret;
746 buffer_reserve(&vs->input, 4096);
748 ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
749 ret = vnc_client_io_error(vs, ret, socket_error());
750 if (!ret)
751 return;
753 vs->input.offset += ret;
755 while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
756 size_t len = vs->read_handler_expect;
757 int ret;
759 ret = vs->read_handler(vs, vs->input.buffer, len);
760 if (vs->csock == -1)
761 return;
763 if (!ret) {
764 memmove(vs->input.buffer, vs->input.buffer + len,
765 vs->input.offset - len);
766 vs->input.offset -= len;
767 } else {
768 assert(ret > vs->read_handler_expect);
769 vs->read_handler_expect = ret;
770 }
771 }
772 }
774 static void vnc_write(VncState *vs, const void *data, size_t len)
775 {
776 buffer_reserve(&vs->output, len);
778 if (buffer_empty(&vs->output))
779 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read,
780 vnc_client_write, vs);
782 buffer_append(&vs->output, data, len);
783 }
785 static void vnc_write_s32(VncState *vs, int32_t value)
786 {
787 vnc_write_u32(vs, *(uint32_t *)&value);
788 }
790 static void vnc_write_u32(VncState *vs, uint32_t value)
791 {
792 uint8_t buf[4];
794 buf[0] = (value >> 24) & 0xFF;
795 buf[1] = (value >> 16) & 0xFF;
796 buf[2] = (value >> 8) & 0xFF;
797 buf[3] = value & 0xFF;
799 vnc_write(vs, buf, 4);
800 }
802 static void vnc_write_u16(VncState *vs, uint16_t value)
803 {
804 uint8_t buf[2];
806 buf[0] = (value >> 8) & 0xFF;
807 buf[1] = value & 0xFF;
809 vnc_write(vs, buf, 2);
810 }
812 static void vnc_write_u8(VncState *vs, uint8_t value)
813 {
814 vnc_write(vs, &value, 1);
815 }
817 static void vnc_flush(VncState *vs)
818 {
819 if (vs->output.offset)
820 vnc_client_write(vs);
821 }
823 static uint8_t read_u8(uint8_t *data, size_t offset)
824 {
825 return data[offset];
826 }
828 static uint16_t read_u16(uint8_t *data, size_t offset)
829 {
830 return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
831 }
833 static int32_t read_s32(uint8_t *data, size_t offset)
834 {
835 return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
836 (data[offset + 2] << 8) | data[offset + 3]);
837 }
839 static uint32_t read_u32(uint8_t *data, size_t offset)
840 {
841 return ((data[offset] << 24) | (data[offset + 1] << 16) |
842 (data[offset + 2] << 8) | data[offset + 3]);
843 }
845 static void client_cut_text(VncState *vs, size_t len, char *text)
846 {
847 }
849 static void check_pointer_type_change(VncState *vs, int absolute)
850 {
851 if (vs->has_pointer_type_change && vs->absolute != absolute) {
852 vnc_write_u8(vs, 0);
853 vnc_write_u8(vs, 0);
854 vnc_write_u16(vs, 1);
855 vnc_framebuffer_update(vs, absolute, 0,
856 vs->ds->width, vs->ds->height, -257);
857 vnc_flush(vs);
858 }
859 vs->absolute = absolute;
860 }
862 static void pointer_event(VncState *vs, int button_mask, int x, int y)
863 {
864 int buttons = 0;
865 int dz = 0;
867 if (button_mask & 0x01)
868 buttons |= MOUSE_EVENT_LBUTTON;
869 if (button_mask & 0x02)
870 buttons |= MOUSE_EVENT_MBUTTON;
871 if (button_mask & 0x04)
872 buttons |= MOUSE_EVENT_RBUTTON;
873 if (button_mask & 0x08)
874 dz = -1;
875 if (button_mask & 0x10)
876 dz = 1;
878 if (vs->absolute) {
879 kbd_mouse_event(x * 0x7FFF / vs->ds->width,
880 y * 0x7FFF / vs->ds->height,
881 dz, buttons);
882 } else if (vs->has_pointer_type_change) {
883 x -= 0x7FFF;
884 y -= 0x7FFF;
886 kbd_mouse_event(x, y, dz, buttons);
887 } else {
888 if (vs->last_x != -1)
889 kbd_mouse_event(x - vs->last_x,
890 y - vs->last_y,
891 dz, buttons);
892 vs->last_x = x;
893 vs->last_y = y;
894 }
896 check_pointer_type_change(vs, kbd_mouse_is_absolute());
897 }
899 static void reset_keys(VncState *vs)
900 {
901 int i;
902 for(i = 0; i < 256; i++) {
903 if (vs->modifiers_state[i]) {
904 if (i & 0x80)
905 kbd_put_keycode(0xe0);
906 kbd_put_keycode(i | 0x80);
907 vs->modifiers_state[i] = 0;
908 }
909 }
910 }
912 static void press_key(VncState *vs, int keysym)
913 {
914 kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f);
915 kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
916 }
918 static void press_key_shift_down(VncState *vs, int down, int keycode)
919 {
920 if (down)
921 kbd_put_keycode(0x2a & 0x7f);
923 if (keycode & 0x80)
924 kbd_put_keycode(0xe0);
925 if (down)
926 kbd_put_keycode(keycode & 0x7f);
927 else
928 kbd_put_keycode(keycode | 0x80);
930 if (!down)
931 kbd_put_keycode(0x2a | 0x80);
932 }
934 static void press_key_shift_up(VncState *vs, int down, int keycode)
935 {
936 if (down) {
937 if (vs->modifiers_state[0x2a])
938 kbd_put_keycode(0x2a | 0x80);
939 if (vs->modifiers_state[0x36])
940 kbd_put_keycode(0x36 | 0x80);
941 }
943 if (keycode & 0x80)
944 kbd_put_keycode(0xe0);
945 if (down)
946 kbd_put_keycode(keycode & 0x7f);
947 else
948 kbd_put_keycode(keycode | 0x80);
950 if (!down) {
951 if (vs->modifiers_state[0x2a])
952 kbd_put_keycode(0x2a & 0x7f);
953 if (vs->modifiers_state[0x36])
954 kbd_put_keycode(0x36 & 0x7f);
955 }
956 }
958 static void do_key_event(VncState *vs, int down, uint32_t sym)
959 {
960 int keycode;
961 int shift_keys = 0;
962 int shift = 0;
964 if (is_graphic_console()) {
965 if (sym >= 'A' && sym <= 'Z') {
966 sym = sym - 'A' + 'a';
967 shift = 1;
968 }
969 else {
970 shift = keysymIsShift(vs->kbd_layout, sym & 0xFFFF);
971 }
972 }
973 shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36];
975 keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
976 if (keycode == 0) {
977 fprintf(stderr, "Key lost : keysym=0x%x(%d)\n", sym, sym);
978 return;
979 }
981 /* QEMU console switch */
982 switch(keycode) {
983 case 0x2a: /* Left Shift */
984 case 0x36: /* Right Shift */
985 case 0x1d: /* Left CTRL */
986 case 0x9d: /* Right CTRL */
987 case 0x38: /* Left ALT */
988 case 0xb8: /* Right ALT */
989 if (down) {
990 vs->modifiers_state[keycode] = 1;
991 kbd_put_keycode(keycode & 0x7f);
992 }
993 else {
994 vs->modifiers_state[keycode] = 0;
995 kbd_put_keycode(keycode | 0x80);
996 }
997 return;
998 case 0x02 ... 0x0a: /* '1' to '9' keys */
999 if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1000 /* Reset the modifiers sent to the current console */
1001 reset_keys(vs);
1002 console_select(keycode - 0x02);
1003 return;
1005 break;
1006 case 0x45: /* NumLock */
1007 if (down) {
1008 kbd_put_keycode(keycode & 0x7f);
1010 else {
1011 vs->modifiers_state[keycode] ^= 1;
1012 kbd_put_keycode(keycode | 0x80);
1014 return;
1017 if (keycodeIsKeypad(vs->kbd_layout, keycode)) {
1018 /* If the numlock state needs to change then simulate an additional
1019 keypress before sending this one. This will happen if the user
1020 toggles numlock away from the VNC window.
1021 */
1022 if (keysymIsNumlock(vs->kbd_layout, sym & 0xFFFF)) {
1023 if (!vs->modifiers_state[0x45]) {
1024 vs->modifiers_state[0x45] = 1;
1025 press_key(vs, 0xff7f);
1027 } else {
1028 if (vs->modifiers_state[0x45]) {
1029 vs->modifiers_state[0x45] = 0;
1030 press_key(vs, 0xff7f);
1035 if (is_graphic_console()) {
1036 /* If the shift state needs to change then simulate an additional
1037 keypress before sending this one.
1038 */
1039 if (shift && !shift_keys) {
1040 press_key_shift_down(vs, down, keycode);
1041 return;
1043 else if (!shift && shift_keys) {
1044 press_key_shift_up(vs, down, keycode);
1045 return;
1048 if (keycode & 0x80)
1049 kbd_put_keycode(0xe0);
1050 if (down)
1051 kbd_put_keycode(keycode & 0x7f);
1052 else
1053 kbd_put_keycode(keycode | 0x80);
1054 } else {
1055 /* QEMU console emulation */
1056 if (down) {
1057 switch (keycode) {
1058 case 0x2a: /* Left Shift */
1059 case 0x36: /* Right Shift */
1060 case 0x1d: /* Left CTRL */
1061 case 0x9d: /* Right CTRL */
1062 case 0x38: /* Left ALT */
1063 case 0xb8: /* Right ALT */
1064 break;
1065 case 0xc8:
1066 kbd_put_keysym(QEMU_KEY_UP);
1067 break;
1068 case 0xd0:
1069 kbd_put_keysym(QEMU_KEY_DOWN);
1070 break;
1071 case 0xcb:
1072 kbd_put_keysym(QEMU_KEY_LEFT);
1073 break;
1074 case 0xcd:
1075 kbd_put_keysym(QEMU_KEY_RIGHT);
1076 break;
1077 case 0xd3:
1078 kbd_put_keysym(QEMU_KEY_DELETE);
1079 break;
1080 case 0xc7:
1081 kbd_put_keysym(QEMU_KEY_HOME);
1082 break;
1083 case 0xcf:
1084 kbd_put_keysym(QEMU_KEY_END);
1085 break;
1086 case 0xc9:
1087 kbd_put_keysym(QEMU_KEY_PAGEUP);
1088 break;
1089 case 0xd1:
1090 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1091 break;
1092 default:
1093 kbd_put_keysym(sym);
1094 break;
1100 static void key_event(VncState *vs, int down, uint32_t sym)
1102 do_key_event(vs, down, sym);
1105 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h)
1108 set_bits_in_row(vs, vs->update_row, x, y, w, h);
1110 vs->has_update = 1;
1113 static void framebuffer_update_request(VncState *vs, int incremental,
1114 int x_position, int y_position,
1115 int w, int h)
1117 if (!incremental)
1118 framebuffer_set_updated(vs, x_position, y_position, w, h);
1119 vs->visible_x = x_position;
1120 vs->visible_y = y_position;
1121 vs->visible_w = w;
1122 vs->visible_h = h;
1124 qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
1127 static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1129 int i;
1131 vs->has_hextile = 0;
1132 vs->has_resize = 0;
1133 vs->has_pointer_type_change = 0;
1134 vs->absolute = -1;
1135 vs->ds->dpy_copy = NULL;
1137 for (i = n_encodings - 1; i >= 0; i--) {
1138 switch (encodings[i]) {
1139 case 0: /* Raw */
1140 vs->has_hextile = 0;
1141 break;
1142 case 1: /* CopyRect */
1143 vs->ds->dpy_copy = vnc_copy;
1144 break;
1145 case 5: /* Hextile */
1146 vs->has_hextile = 1;
1147 break;
1148 case -223: /* DesktopResize */
1149 vs->has_resize = 1;
1150 break;
1151 case -257:
1152 vs->has_pointer_type_change = 1;
1153 break;
1154 default:
1155 break;
1159 check_pointer_type_change(vs, kbd_mouse_is_absolute());
1162 static int compute_nbits(unsigned int val)
1164 int n;
1165 n = 0;
1166 while (val != 0) {
1167 n++;
1168 val >>= 1;
1170 return n;
1173 static void set_pixel_format(VncState *vs,
1174 int bits_per_pixel, int depth,
1175 int big_endian_flag, int true_color_flag,
1176 int red_max, int green_max, int blue_max,
1177 int red_shift, int green_shift, int blue_shift)
1179 int host_big_endian_flag;
1181 #ifdef WORDS_BIGENDIAN
1182 host_big_endian_flag = 1;
1183 #else
1184 host_big_endian_flag = 0;
1185 #endif
1186 if (!true_color_flag) {
1187 fail:
1188 vnc_client_error(vs);
1189 return;
1191 if (bits_per_pixel == 32 &&
1192 host_big_endian_flag == big_endian_flag &&
1193 red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1194 red_shift == 16 && green_shift == 8 && blue_shift == 0) {
1195 vs->depth = 4;
1196 vs->write_pixels = vnc_write_pixels_copy;
1197 vs->send_hextile_tile = send_hextile_tile_32;
1198 } else
1199 if (bits_per_pixel == 16 &&
1200 host_big_endian_flag == big_endian_flag &&
1201 red_max == 31 && green_max == 63 && blue_max == 31 &&
1202 red_shift == 11 && green_shift == 5 && blue_shift == 0) {
1203 vs->depth = 2;
1204 vs->write_pixels = vnc_write_pixels_copy;
1205 vs->send_hextile_tile = send_hextile_tile_16;
1206 } else
1207 if (bits_per_pixel == 8 &&
1208 red_max == 7 && green_max == 7 && blue_max == 3 &&
1209 red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1210 vs->depth = 1;
1211 vs->write_pixels = vnc_write_pixels_copy;
1212 vs->send_hextile_tile = send_hextile_tile_8;
1213 } else
1215 /* generic and slower case */
1216 if (bits_per_pixel != 8 &&
1217 bits_per_pixel != 16 &&
1218 bits_per_pixel != 32)
1219 goto fail;
1220 vs->depth = 4;
1221 vs->red_shift = red_shift;
1222 vs->red_max = red_max;
1223 vs->red_shift1 = 24 - compute_nbits(red_max);
1224 vs->green_shift = green_shift;
1225 vs->green_max = green_max;
1226 vs->green_shift1 = 16 - compute_nbits(green_max);
1227 vs->blue_shift = blue_shift;
1228 vs->blue_max = blue_max;
1229 vs->blue_shift1 = 8 - compute_nbits(blue_max);
1230 vs->pix_bpp = bits_per_pixel / 8;
1231 vs->pix_big_endian = big_endian_flag;
1232 vs->write_pixels = vnc_write_pixels_generic;
1233 vs->send_hextile_tile = send_hextile_tile_generic;
1236 vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
1238 vga_hw_invalidate();
1239 vga_hw_update();
1242 static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1244 int i;
1245 uint16_t limit;
1247 switch (data[0]) {
1248 case 0:
1249 if (len == 1)
1250 return 20;
1252 set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1253 read_u8(data, 6), read_u8(data, 7),
1254 read_u16(data, 8), read_u16(data, 10),
1255 read_u16(data, 12), read_u8(data, 14),
1256 read_u8(data, 15), read_u8(data, 16));
1257 break;
1258 case 2:
1259 if (len == 1)
1260 return 4;
1262 if (len == 4) {
1263 uint16_t v;
1264 v = read_u16(data, 2);
1265 if (v)
1266 return 4 + v * 4;
1269 limit = read_u16(data, 2);
1270 for (i = 0; i < limit; i++) {
1271 int32_t val = read_s32(data, 4 + (i * 4));
1272 memcpy(data + 4 + (i * 4), &val, sizeof(val));
1275 set_encodings(vs, (int32_t *)(data + 4), limit);
1276 break;
1277 case 3:
1278 if (len == 1)
1279 return 10;
1281 framebuffer_update_request(vs,
1282 read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1283 read_u16(data, 6), read_u16(data, 8));
1284 break;
1285 case 4:
1286 if (len == 1)
1287 return 8;
1289 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1290 qemu_advance_timer(vs->timer,
1291 qemu_get_clock(rt_clock) + vs->timer_interval);
1292 key_event(vs, read_u8(data, 1), read_u32(data, 4));
1293 break;
1294 case 5:
1295 if (len == 1)
1296 return 6;
1298 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1299 qemu_advance_timer(vs->timer,
1300 qemu_get_clock(rt_clock) + vs->timer_interval);
1301 pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1302 break;
1303 case 6:
1304 if (len == 1)
1305 return 8;
1307 if (len == 8) {
1308 uint32_t v;
1309 v = read_u32(data, 4);
1310 if (v)
1311 return 8 + v;
1314 client_cut_text(vs, read_u32(data, 4), (char *)(data + 8));
1315 break;
1316 default:
1317 printf("Msg: %d\n", data[0]);
1318 vnc_client_error(vs);
1319 break;
1322 vnc_read_when(vs, protocol_client_msg, 1);
1323 return 0;
1326 static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1328 size_t l;
1329 char pad[3] = { 0, 0, 0 };
1331 vga_hw_update();
1333 vs->width = vs->ds->width;
1334 vs->height = vs->ds->height;
1335 vnc_write_u16(vs, vs->ds->width);
1336 vnc_write_u16(vs, vs->ds->height);
1338 vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1339 vnc_write_u8(vs, vs->depth * 8); /* depth */
1340 #ifdef WORDS_BIGENDIAN
1341 vnc_write_u8(vs, 1); /* big-endian-flag */
1342 #else
1343 vnc_write_u8(vs, 0); /* big-endian-flag */
1344 #endif
1345 vnc_write_u8(vs, 1); /* true-color-flag */
1346 if (vs->depth == 4) {
1347 vnc_write_u16(vs, 0xFF); /* red-max */
1348 vnc_write_u16(vs, 0xFF); /* green-max */
1349 vnc_write_u16(vs, 0xFF); /* blue-max */
1350 vnc_write_u8(vs, 16); /* red-shift */
1351 vnc_write_u8(vs, 8); /* green-shift */
1352 vnc_write_u8(vs, 0); /* blue-shift */
1353 vs->send_hextile_tile = send_hextile_tile_32;
1354 } else if (vs->depth == 2) {
1355 vnc_write_u16(vs, 31); /* red-max */
1356 vnc_write_u16(vs, 63); /* green-max */
1357 vnc_write_u16(vs, 31); /* blue-max */
1358 vnc_write_u8(vs, 11); /* red-shift */
1359 vnc_write_u8(vs, 5); /* green-shift */
1360 vnc_write_u8(vs, 0); /* blue-shift */
1361 vs->send_hextile_tile = send_hextile_tile_16;
1362 } else if (vs->depth == 1) {
1363 /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
1364 vnc_write_u16(vs, 7); /* red-max */
1365 vnc_write_u16(vs, 7); /* green-max */
1366 vnc_write_u16(vs, 3); /* blue-max */
1367 vnc_write_u8(vs, 5); /* red-shift */
1368 vnc_write_u8(vs, 2); /* green-shift */
1369 vnc_write_u8(vs, 0); /* blue-shift */
1370 vs->send_hextile_tile = send_hextile_tile_8;
1372 vs->write_pixels = vnc_write_pixels_copy;
1374 vnc_write(vs, pad, 3); /* padding */
1376 l = strlen(domain_name);
1377 vnc_write_u32(vs, l);
1378 vnc_write(vs, domain_name, l);
1380 vnc_flush(vs);
1382 vnc_read_when(vs, protocol_client_msg, 1);
1384 return 0;
1387 static int protocol_response(VncState *vs, uint8_t *client_response, size_t len)
1389 extern char vncpasswd[64];
1390 extern unsigned char challenge[AUTHCHALLENGESIZE];
1391 unsigned char cryptchallenge[AUTHCHALLENGESIZE];
1392 unsigned char key[8];
1393 int passwdlen, i, j;
1395 memcpy(cryptchallenge, challenge, AUTHCHALLENGESIZE);
1397 /* Calculate the sent challenge */
1398 passwdlen = strlen(vncpasswd);
1399 for (i=0; i<8; i++)
1400 key[i] = i<passwdlen ? vncpasswd[i] : 0;
1401 deskey(key, EN0);
1402 for (j = 0; j < AUTHCHALLENGESIZE; j += 8)
1403 des(cryptchallenge+j, cryptchallenge+j);
1405 /* Check the actual response */
1406 if (memcmp(cryptchallenge, client_response, AUTHCHALLENGESIZE) != 0) {
1407 /* password error */
1408 vnc_write_u32(vs, 1);
1409 vnc_write_u32(vs, 22);
1410 vnc_write(vs, "Authentication failure", 22);
1411 vnc_flush(vs);
1412 fprintf(stderr, "VNC Password error.\n");
1413 vnc_client_error(vs);
1414 return 0;
1417 vnc_write_u32(vs, 0);
1418 vnc_flush(vs);
1420 vnc_read_when(vs, protocol_client_init, 1);
1422 return 0;
1425 static int protocol_version(VncState *vs, uint8_t *version, size_t len)
1427 extern char vncpasswd[64];
1428 extern unsigned char challenge[AUTHCHALLENGESIZE];
1429 char local[13];
1430 int support, maj, min;
1432 memcpy(local, version, 12);
1433 local[12] = 0;
1435 /* protocol version check */
1436 if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
1437 fprintf(stderr, "Protocol version error.\n");
1438 vnc_client_error(vs);
1439 return 0;
1443 support = 0;
1444 if (maj == 3) {
1445 if (min == 3 || min ==4) {
1446 support = 1;
1450 if (! support) {
1451 fprintf(stderr, "Client uses unsupported protocol version %d.%d.\n",
1452 maj, min);
1453 vnc_client_error(vs);
1454 return 0;
1457 if (*vncpasswd == '\0') {
1458 /* AuthType is None */
1459 vnc_write_u32(vs, 1);
1460 vnc_flush(vs);
1461 vnc_read_when(vs, protocol_client_init, 1);
1462 } else {
1463 /* AuthType is VncAuth */
1464 vnc_write_u32(vs, 2);
1466 /* Challenge-Responce authentication */
1467 /* Send Challenge */
1468 make_challenge(challenge, AUTHCHALLENGESIZE);
1469 vnc_write(vs, challenge, AUTHCHALLENGESIZE);
1470 vnc_flush(vs);
1471 vnc_read_when(vs, protocol_response, AUTHCHALLENGESIZE);
1474 return 0;
1477 static void vnc_listen_read(void *opaque)
1479 VncState *vs = opaque;
1480 struct sockaddr_in addr;
1481 socklen_t addrlen = sizeof(addr);
1483 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
1484 if (vs->csock != -1) {
1485 socket_set_nonblock(vs->csock);
1486 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
1487 vnc_write(vs, "RFB 003.003\n", 12);
1488 vnc_flush(vs);
1489 vnc_read_when(vs, protocol_version, 12);
1490 framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
1491 vs->has_resize = 0;
1492 vs->has_hextile = 0;
1493 vs->ds->dpy_copy = NULL;
1494 vnc_timer_init(vs);
1498 extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
1500 int vnc_display_init(DisplayState *ds, const char *arg, int find_unused)
1502 struct sockaddr *addr;
1503 struct sockaddr_in iaddr;
1504 #ifndef _WIN32
1505 struct sockaddr_un uaddr;
1506 #endif
1507 int reuse_addr, ret;
1508 socklen_t addrlen;
1509 const char *p;
1510 VncState *vs;
1512 vs = qemu_mallocz(sizeof(VncState));
1513 if (!vs)
1514 exit(1);
1516 ds->opaque = vs;
1517 vnc_state = vs;
1518 vs->display = arg;
1520 vs->lsock = -1;
1521 vs->csock = -1;
1522 vs->depth = 4;
1523 vs->last_x = -1;
1524 vs->last_y = -1;
1526 vs->ds = ds;
1528 if (!keyboard_layout)
1529 keyboard_layout = "en-us";
1531 vs->kbd_layout = init_keyboard_layout(keyboard_layout);
1532 if (!vs->kbd_layout)
1533 exit(1);
1534 vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
1536 vs->ds->data = NULL;
1537 vs->ds->dpy_update = vnc_dpy_update;
1538 vs->ds->dpy_resize = vnc_dpy_resize;
1539 vs->ds->dpy_refresh = vnc_dpy_refresh;
1541 vnc_dpy_resize(vs->ds, 640, 400);
1543 if (arg == NULL)
1544 arg = "localhost:0";
1546 #ifndef _WIN32
1547 if (strstart(arg, "unix:", &p)) {
1548 addr = (struct sockaddr *)&uaddr;
1549 addrlen = sizeof(uaddr);
1551 vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
1552 if (vs->lsock == -1) {
1553 fprintf(stderr, "Could not create socket\n");
1554 exit(1);
1557 uaddr.sun_family = AF_UNIX;
1558 memset(uaddr.sun_path, 0, 108);
1559 snprintf(uaddr.sun_path, 108, "%s", p);
1561 unlink(uaddr.sun_path);
1562 } else
1563 #endif
1565 addr = (struct sockaddr *)&iaddr;
1566 addrlen = sizeof(iaddr);
1568 vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
1569 if (vs->lsock == -1) {
1570 fprintf(stderr, "Could not create socket\n");
1571 exit(1);
1574 if (parse_host_port(&iaddr, arg) < 0) {
1575 fprintf(stderr, "Could not parse VNC address\n");
1576 exit(1);
1579 iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
1581 reuse_addr = 1;
1582 ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
1583 (const char *)&reuse_addr, sizeof(reuse_addr));
1584 if (ret == -1) {
1585 fprintf(stderr, "setsockopt() failed\n");
1586 exit(1);
1590 while (bind(vs->lsock, addr, addrlen) == -1) {
1591 if (find_unused && errno == EADDRINUSE) {
1592 iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 1);
1593 continue;
1595 fprintf(stderr, "bind() failed\n");
1596 exit(1);
1599 if (listen(vs->lsock, 1) == -1) {
1600 fprintf(stderr, "listen() failed\n");
1601 exit(1);
1604 ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
1605 if (ret == -1) {
1606 exit(1);
1609 return ntohs(iaddr.sin_port);
1612 int vnc_start_viewer(int port)
1614 int pid, i, open_max;
1615 char s[16];
1617 sprintf(s, ":%d", port);
1619 switch (pid = fork()) {
1620 case -1:
1621 fprintf(stderr, "vncviewer failed fork\n");
1622 exit(1);
1624 case 0: /* child */
1625 open_max = sysconf(_SC_OPEN_MAX);
1626 for (i = 0; i < open_max; i++)
1627 if (i != STDIN_FILENO &&
1628 i != STDOUT_FILENO &&
1629 i != STDERR_FILENO)
1630 close(i);
1631 execlp("vncviewer", "vncviewer", s, NULL);
1632 fprintf(stderr, "vncviewer execlp failed\n");
1633 exit(1);
1635 default:
1636 return pid;
1640 unsigned int seed;
1642 static int make_challenge(unsigned char *random, int size)
1645 set_seed(&seed);
1646 get_random(size, random);
1648 return 0;
1651 static void set_seed(unsigned int *seedp)
1653 *seedp += (unsigned int)(time(NULL)+getpid()+getpid()*987654+rand());
1654 srand(*seedp);
1656 return;
1659 static void get_random(int len, unsigned char *buf)
1661 int i;
1663 for (i=0; i<len; i++)
1664 buf[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1666 return;