ia64/xen-unstable

view tools/ioemu/vnc.c @ 15066:7da6d9c374be

[qemu] Fix shift key for non-graphical vnc displays (like the monitor).

Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
author Christian Limpach <Christian.Limpach@xensource.com>
date Thu May 10 14:44:45 2007 +0100 (2007-05-10)
parents 00618037d37d
children 5040a3ff50ee
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 #define XK_MISCELLANY
50 #define XK_LATIN1
51 #include <X11/keysymdef.h>
53 typedef struct Buffer
54 {
55 size_t capacity;
56 size_t offset;
57 uint8_t *buffer;
58 } Buffer;
60 typedef struct VncState VncState;
62 typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
64 typedef void VncWritePixels(VncState *vs, void *data, int size);
66 typedef void VncSendHextileTile(VncState *vs,
67 int x, int y, int w, int h,
68 uint32_t *last_bg,
69 uint32_t *last_fg,
70 int *has_bg, int *has_fg);
72 #if 0
73 #define VNC_MAX_WIDTH 2048
74 #define VNC_MAX_HEIGHT 2048
75 #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
76 #endif
78 struct VncState
79 {
80 QEMUTimer *timer;
81 int timer_interval;
82 int64_t last_update_time;
83 int lsock;
84 int csock;
85 DisplayState *ds;
86 int width;
87 int height;
88 uint64_t *dirty_row; /* screen regions which are possibly dirty */
89 int dirty_pixel_shift;
90 uint64_t *update_row; /* outstanding updates */
91 int has_update; /* there's outstanding updates in the
92 * visible area */
93 uint8_t *old_data;
94 int depth; /* internal VNC frame buffer byte per pixel */
95 int has_resize;
96 int has_hextile;
97 int has_pointer_type_change;
98 int absolute;
99 int last_x;
100 int last_y;
102 const char *display;
104 Buffer output;
105 Buffer input;
106 kbd_layout_t *kbd_layout;
107 /* current output mode information */
108 VncWritePixels *write_pixels;
109 VncSendHextileTile *send_hextile_tile;
110 int pix_bpp, pix_big_endian;
111 int red_shift, red_max, red_shift1;
112 int green_shift, green_max, green_shift1;
113 int blue_shift, blue_max, blue_shift1;
115 VncReadEvent *read_handler;
116 size_t read_handler_expect;
118 int visible_x;
119 int visible_y;
120 int visible_w;
121 int visible_h;
123 /* input */
124 uint8_t modifiers_state[256];
125 };
127 static VncState *vnc_state; /* needed for info vnc */
129 #define DIRTY_PIXEL_BITS 64
130 #define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift)
131 #define X2DP_UP(vs, x) \
132 (((x) + (1ULL << (vs)->dirty_pixel_shift) - 1) >> (vs)->dirty_pixel_shift)
133 #define DP2X(vs, x) ((x) << (vs)->dirty_pixel_shift)
135 void do_info_vnc(void)
136 {
137 if (vnc_state == NULL)
138 term_printf("VNC server disabled\n");
139 else {
140 term_printf("VNC server active on: ");
141 term_print_filename(vnc_state->display);
142 term_printf("\n");
144 if (vnc_state->csock == -1)
145 term_printf("No client connected\n");
146 else
147 term_printf("Client connected\n");
148 }
149 }
151 /* TODO
152 1) Get the queue working for IO.
153 2) there is some weirdness when using the -S option (the screen is grey
154 and not totally invalidated
155 3) resolutions > 1024
156 */
158 static void vnc_write(VncState *vs, const void *data, size_t len);
159 static void vnc_write_u32(VncState *vs, uint32_t value);
160 static void vnc_write_s32(VncState *vs, int32_t value);
161 static void vnc_write_u16(VncState *vs, uint16_t value);
162 static void vnc_write_u8(VncState *vs, uint8_t value);
163 static void vnc_flush(VncState *vs);
164 static void _vnc_update_client(void *opaque);
165 static void vnc_update_client(void *opaque);
166 static void vnc_client_read(void *opaque);
167 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
168 static int make_challenge(unsigned char *random, int size);
169 static void set_seed(unsigned int *seedp);
170 static void get_random(int len, unsigned char *buf);
172 #if 0
173 static inline void vnc_set_bit(uint32_t *d, int k)
174 {
175 d[k >> 5] |= 1 << (k & 0x1f);
176 }
178 static inline void vnc_clear_bit(uint32_t *d, int k)
179 {
180 d[k >> 5] &= ~(1 << (k & 0x1f));
181 }
183 static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
184 {
185 int j;
187 j = 0;
188 while (n >= 32) {
189 d[j++] = -1;
190 n -= 32;
191 }
192 if (n > 0)
193 d[j++] = (1 << n) - 1;
194 while (j < nb_words)
195 d[j++] = 0;
196 }
198 static inline int vnc_get_bit(const uint32_t *d, int k)
199 {
200 return (d[k >> 5] >> (k & 0x1f)) & 1;
201 }
203 static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
204 int nb_words)
205 {
206 int i;
207 for(i = 0; i < nb_words; i++) {
208 if ((d1[i] & d2[i]) != 0)
209 return 1;
210 }
211 return 0;
212 }
213 #endif
215 static void set_bits_in_row(VncState *vs, uint64_t *row,
216 int x, int y, int w, int h)
217 {
218 int x1, x2;
219 uint64_t mask;
221 if (w == 0)
222 return;
224 x1 = X2DP_DOWN(vs, x);
225 x2 = X2DP_UP(vs, x + w);
227 if (X2DP_UP(vs, w) != DIRTY_PIXEL_BITS)
228 mask = ((1ULL << (x2 - x1)) - 1) << x1;
229 else
230 mask = ~(0ULL);
232 h += y;
233 if (h > vs->ds->height)
234 h = vs->ds->height;
235 for (; y < h; y++)
236 row[y] |= mask;
237 }
239 static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
240 {
241 VncState *vs = ds->opaque;
243 set_bits_in_row(vs, vs->dirty_row, x, y, w, h);
244 }
246 static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
247 int32_t encoding)
248 {
249 vnc_write_u16(vs, x);
250 vnc_write_u16(vs, y);
251 vnc_write_u16(vs, w);
252 vnc_write_u16(vs, h);
254 vnc_write_s32(vs, encoding);
255 }
257 static void vnc_dpy_resize(DisplayState *ds, int w, int h)
258 {
259 int size_changed;
260 VncState *vs = ds->opaque;
261 int o;
263 ds->data = realloc(ds->data, w * h * vs->depth);
264 vs->old_data = realloc(vs->old_data, w * h * vs->depth);
265 vs->dirty_row = realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0]));
266 vs->update_row = realloc(vs->update_row, h * sizeof(vs->dirty_row[0]));
268 if (ds->data == NULL || vs->old_data == NULL ||
269 vs->dirty_row == NULL || vs->update_row == NULL) {
270 fprintf(stderr, "vnc: memory allocation failed\n");
271 exit(1);
272 }
274 if (ds->depth != vs->depth * 8) {
275 ds->depth = vs->depth * 8;
276 set_color_table(ds);
277 }
278 size_changed = ds->width != w || ds->height != h;
279 ds->width = w;
280 ds->height = h;
281 ds->linesize = w * vs->depth;
282 if (vs->csock != -1 && vs->has_resize && size_changed) {
283 vnc_write_u8(vs, 0); /* msg id */
284 vnc_write_u8(vs, 0);
285 vnc_write_u16(vs, 1); /* number of rects */
286 vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
287 vnc_flush(vs);
288 vs->width = ds->width;
289 vs->height = ds->height;
290 }
291 vs->dirty_pixel_shift = 0;
292 for (o = DIRTY_PIXEL_BITS; o < ds->width; o *= 2)
293 vs->dirty_pixel_shift++;
294 framebuffer_set_updated(vs, 0, 0, ds->width, ds->height);
295 }
297 /* fastest code */
298 static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
299 {
300 vnc_write(vs, pixels, size);
301 }
303 /* slowest but generic code. */
304 static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
305 {
306 unsigned int r, g, b;
308 r = (v >> vs->red_shift1) & vs->red_max;
309 g = (v >> vs->green_shift1) & vs->green_max;
310 b = (v >> vs->blue_shift1) & vs->blue_max;
311 v = (r << vs->red_shift) |
312 (g << vs->green_shift) |
313 (b << vs->blue_shift);
314 switch(vs->pix_bpp) {
315 case 1:
316 buf[0] = v;
317 break;
318 case 2:
319 if (vs->pix_big_endian) {
320 buf[0] = v >> 8;
321 buf[1] = v;
322 } else {
323 buf[1] = v >> 8;
324 buf[0] = v;
325 }
326 break;
327 default:
328 case 4:
329 if (vs->pix_big_endian) {
330 buf[0] = v >> 24;
331 buf[1] = v >> 16;
332 buf[2] = v >> 8;
333 buf[3] = v;
334 } else {
335 buf[3] = v >> 24;
336 buf[2] = v >> 16;
337 buf[1] = v >> 8;
338 buf[0] = v;
339 }
340 break;
341 }
342 }
344 static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
345 {
346 uint32_t *pixels = pixels1;
347 uint8_t buf[4];
348 int n, i;
350 n = size >> 2;
351 for(i = 0; i < n; i++) {
352 vnc_convert_pixel(vs, buf, pixels[i]);
353 vnc_write(vs, buf, vs->pix_bpp);
354 }
355 }
357 static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
358 {
359 int i;
360 uint8_t *row;
362 vnc_framebuffer_update(vs, x, y, w, h, 0);
364 row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
365 for (i = 0; i < h; i++) {
366 vs->write_pixels(vs, row, w * vs->depth);
367 row += vs->ds->linesize;
368 }
369 }
371 static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
372 {
373 ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
374 ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
375 }
377 #define BPP 8
378 #include "vnchextile.h"
379 #undef BPP
381 #define BPP 16
382 #include "vnchextile.h"
383 #undef BPP
385 #define BPP 32
386 #include "vnchextile.h"
387 #undef BPP
389 #define GENERIC
390 #define BPP 32
391 #include "vnchextile.h"
392 #undef BPP
393 #undef GENERIC
395 static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
396 {
397 int i, j;
398 int has_fg, has_bg;
399 uint32_t last_fg32, last_bg32;
401 vnc_framebuffer_update(vs, x, y, w, h, 5);
403 has_fg = has_bg = 0;
404 for (j = y; j < (y + h); j += 16) {
405 for (i = x; i < (x + w); i += 16) {
406 vs->send_hextile_tile(vs, i, j,
407 MIN(16, x + w - i), MIN(16, y + h - j),
408 &last_bg32, &last_fg32, &has_bg, &has_fg);
409 }
410 }
411 }
413 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
414 {
415 if (vs->has_hextile)
416 send_framebuffer_update_hextile(vs, x, y, w, h);
417 else
418 send_framebuffer_update_raw(vs, x, y, w, h);
419 }
421 static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
422 {
423 int src, dst;
424 uint8_t *src_row;
425 uint8_t *dst_row;
426 uint8_t *old_row;
427 int y = 0;
428 int pitch = ds->linesize;
429 VncState *vs = ds->opaque;
430 int updating_client = 1;
432 if (src_x < vs->visible_x || src_y < vs->visible_y ||
433 dst_x < vs->visible_x || dst_y < vs->visible_y ||
434 (src_x + w) > (vs->visible_x + vs->visible_w) ||
435 (src_y + h) > (vs->visible_y + vs->visible_h) ||
436 (dst_x + w) > (vs->visible_x + vs->visible_w) ||
437 (dst_y + h) > (vs->visible_y + vs->visible_h))
438 updating_client = 0;
440 if (updating_client)
441 _vnc_update_client(vs);
443 if (dst_y > src_y) {
444 y = h - 1;
445 pitch = -pitch;
446 }
448 src = (ds->linesize * (src_y + y) + vs->depth * src_x);
449 dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
451 src_row = ds->data + src;
452 dst_row = ds->data + dst;
453 old_row = vs->old_data + dst;
455 for (y = 0; y < h; y++) {
456 memmove(old_row, src_row, w * vs->depth);
457 memmove(dst_row, src_row, w * vs->depth);
458 src_row += pitch;
459 dst_row += pitch;
460 old_row += pitch;
461 }
463 if (updating_client && vs->csock != -1 && !vs->has_update) {
464 vnc_write_u8(vs, 0); /* msg id */
465 vnc_write_u8(vs, 0);
466 vnc_write_u16(vs, 1); /* number of rects */
467 vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
468 vnc_write_u16(vs, src_x);
469 vnc_write_u16(vs, src_y);
470 vnc_flush(vs);
471 } else
472 framebuffer_set_updated(vs, dst_x, dst_y, w, h);
473 }
475 static int find_update_height(VncState *vs, int y, int maxy, int last_x, int x)
476 {
477 int h;
479 for (h = 1; y + h < maxy; h++) {
480 int tmp_x;
481 if (!(vs->update_row[y + h] & (1ULL << last_x)))
482 break;
483 for (tmp_x = last_x; tmp_x < x; tmp_x++)
484 vs->update_row[y + h] &= ~(1ULL << tmp_x);
485 }
487 return h;
488 }
490 static void _vnc_update_client(void *opaque)
491 {
492 VncState *vs = opaque;
493 int64_t now;
494 int y;
495 uint8_t *row;
496 uint8_t *old_row;
497 uint64_t width_mask;
498 int n_rectangles;
499 int saved_offset;
500 int maxx, maxy;
501 int tile_bytes = vs->depth * DP2X(vs, 1);
503 if (vs->csock == -1)
504 return;
506 now = qemu_get_clock(rt_clock);
508 if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))
509 width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;
510 else
511 width_mask = ~(0ULL);
513 /* Walk through the dirty map and eliminate tiles that really
514 aren't dirty */
515 row = vs->ds->data;
516 old_row = vs->old_data;
518 for (y = 0; y < vs->ds->height; y++) {
519 if (vs->dirty_row[y] & width_mask) {
520 int x;
521 uint8_t *ptr, *old_ptr;
523 ptr = row;
524 old_ptr = old_row;
526 for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {
527 if (vs->dirty_row[y] & (1ULL << x)) {
528 if (memcmp(old_ptr, ptr, tile_bytes)) {
529 vs->has_update = 1;
530 vs->update_row[y] |= (1ULL << x);
531 memcpy(old_ptr, ptr, tile_bytes);
532 }
533 vs->dirty_row[y] &= ~(1ULL << x);
534 }
536 ptr += tile_bytes;
537 old_ptr += tile_bytes;
538 }
539 }
541 row += vs->ds->linesize;
542 old_row += vs->ds->linesize;
543 }
545 if (!vs->has_update || vs->visible_y >= vs->ds->height ||
546 vs->visible_x >= vs->ds->width)
547 goto backoff;
549 /* Count rectangles */
550 n_rectangles = 0;
551 vnc_write_u8(vs, 0); /* msg id */
552 vnc_write_u8(vs, 0);
553 saved_offset = vs->output.offset;
554 vnc_write_u16(vs, 0);
556 maxy = vs->visible_y + vs->visible_h;
557 if (maxy > vs->ds->height)
558 maxy = vs->ds->height;
559 maxx = vs->visible_x + vs->visible_w;
560 if (maxx > vs->ds->width)
561 maxx = vs->ds->width;
563 for (y = vs->visible_y; y < maxy; y++) {
564 int x;
565 int last_x = -1;
566 for (x = X2DP_DOWN(vs, vs->visible_x);
567 x < X2DP_UP(vs, maxx); x++) {
568 if (vs->update_row[y] & (1ULL << x)) {
569 if (last_x == -1)
570 last_x = x;
571 vs->update_row[y] &= ~(1ULL << x);
572 } else {
573 if (last_x != -1) {
574 int h = find_update_height(vs, y, maxy, last_x, x);
575 if (h != 0) {
576 send_framebuffer_update(vs, DP2X(vs, last_x), y,
577 DP2X(vs, (x - last_x)), h);
578 n_rectangles++;
579 }
580 }
581 last_x = -1;
582 }
583 }
584 if (last_x != -1) {
585 int h = find_update_height(vs, y, maxy, last_x, x);
586 if (h != 0) {
587 send_framebuffer_update(vs, DP2X(vs, last_x), y,
588 DP2X(vs, (x - last_x)), h);
589 n_rectangles++;
590 }
591 }
592 }
593 vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
594 vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
596 if (n_rectangles == 0)
597 goto backoff;
599 vs->has_update = 0;
600 vnc_flush(vs);
601 vs->last_update_time = now;
603 vs->timer_interval /= 2;
604 if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE)
605 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
607 return;
609 backoff:
610 /* No update -> back off a bit */
611 vs->timer_interval += VNC_REFRESH_INTERVAL_INC;
612 if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) {
613 vs->timer_interval = VNC_REFRESH_INTERVAL_MAX;
614 if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) {
615 /* Send a null update. If the client is no longer
616 interested (e.g. minimised) it'll ignore this, and we
617 can stop scanning the buffer until it sends another
618 update request. */
619 /* It turns out that there's a bug in realvncviewer 4.1.2
620 which means that if you send a proper null update (with
621 no update rectangles), it gets a bit out of sync and
622 never sends any further requests, regardless of whether
623 it needs one or not. Fix this by sending a single 1x1
624 update rectangle instead. */
625 vnc_write_u8(vs, 0);
626 vnc_write_u8(vs, 0);
627 vnc_write_u16(vs, 1);
628 send_framebuffer_update(vs, 0, 0, 1, 1);
629 vnc_flush(vs);
630 vs->last_update_time = now;
631 return;
632 }
633 }
634 qemu_mod_timer(vs->timer, now + vs->timer_interval);
635 return;
636 }
638 static void vnc_update_client(void *opaque)
639 {
640 VncState *vs = opaque;
642 vs->ds->dpy_refresh(vs->ds);
643 _vnc_update_client(vs);
644 }
646 static void vnc_timer_init(VncState *vs)
647 {
648 if (vs->timer == NULL) {
649 vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
650 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
651 }
652 }
654 static void vnc_dpy_refresh(DisplayState *ds)
655 {
656 vga_hw_update();
657 }
659 static int vnc_listen_poll(void *opaque)
660 {
661 VncState *vs = opaque;
662 if (vs->csock == -1)
663 return 1;
664 return 0;
665 }
667 static void buffer_reserve(Buffer *buffer, size_t len)
668 {
669 if ((buffer->capacity - buffer->offset) < len) {
670 buffer->capacity += (len + 1024);
671 buffer->buffer = realloc(buffer->buffer, buffer->capacity);
672 if (buffer->buffer == NULL) {
673 fprintf(stderr, "vnc: out of memory\n");
674 exit(1);
675 }
676 }
677 }
679 static int buffer_empty(Buffer *buffer)
680 {
681 return buffer->offset == 0;
682 }
684 static uint8_t *buffer_end(Buffer *buffer)
685 {
686 return buffer->buffer + buffer->offset;
687 }
689 static void buffer_reset(Buffer *buffer)
690 {
691 buffer->offset = 0;
692 }
694 static void buffer_append(Buffer *buffer, const void *data, size_t len)
695 {
696 memcpy(buffer->buffer + buffer->offset, data, len);
697 buffer->offset += len;
698 }
700 static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
701 {
702 if (ret == 0 || ret == -1) {
703 if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
704 return 0;
706 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
707 closesocket(vs->csock);
708 vs->csock = -1;
709 buffer_reset(&vs->input);
710 buffer_reset(&vs->output);
711 return 0;
712 }
713 return ret;
714 }
716 static void vnc_client_error(VncState *vs)
717 {
718 vnc_client_io_error(vs, -1, EINVAL);
719 }
721 static void vnc_client_write(void *opaque)
722 {
723 long ret;
724 VncState *vs = opaque;
726 ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
727 ret = vnc_client_io_error(vs, ret, socket_error());
728 if (!ret)
729 return;
731 memmove(vs->output.buffer, vs->output.buffer + ret,
732 vs->output.offset - ret);
733 vs->output.offset -= ret;
735 if (vs->output.offset == 0)
736 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
737 }
739 static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
740 {
741 vs->read_handler = func;
742 vs->read_handler_expect = expecting;
743 }
745 static void vnc_client_read(void *opaque)
746 {
747 VncState *vs = opaque;
748 long ret;
750 buffer_reserve(&vs->input, 4096);
752 ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
753 ret = vnc_client_io_error(vs, ret, socket_error());
754 if (!ret)
755 return;
757 vs->input.offset += ret;
759 while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
760 size_t len = vs->read_handler_expect;
761 int ret;
763 ret = vs->read_handler(vs, vs->input.buffer, len);
764 if (vs->csock == -1)
765 return;
767 if (!ret) {
768 memmove(vs->input.buffer, vs->input.buffer + len,
769 vs->input.offset - len);
770 vs->input.offset -= len;
771 } else {
772 assert(ret > vs->read_handler_expect);
773 vs->read_handler_expect = ret;
774 }
775 }
776 }
778 static void vnc_write(VncState *vs, const void *data, size_t len)
779 {
780 buffer_reserve(&vs->output, len);
782 if (buffer_empty(&vs->output))
783 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read,
784 vnc_client_write, vs);
786 buffer_append(&vs->output, data, len);
787 }
789 static void vnc_write_s32(VncState *vs, int32_t value)
790 {
791 vnc_write_u32(vs, *(uint32_t *)&value);
792 }
794 static void vnc_write_u32(VncState *vs, uint32_t value)
795 {
796 uint8_t buf[4];
798 buf[0] = (value >> 24) & 0xFF;
799 buf[1] = (value >> 16) & 0xFF;
800 buf[2] = (value >> 8) & 0xFF;
801 buf[3] = value & 0xFF;
803 vnc_write(vs, buf, 4);
804 }
806 static void vnc_write_u16(VncState *vs, uint16_t value)
807 {
808 uint8_t buf[2];
810 buf[0] = (value >> 8) & 0xFF;
811 buf[1] = value & 0xFF;
813 vnc_write(vs, buf, 2);
814 }
816 static void vnc_write_u8(VncState *vs, uint8_t value)
817 {
818 vnc_write(vs, &value, 1);
819 }
821 static void vnc_flush(VncState *vs)
822 {
823 if (vs->output.offset)
824 vnc_client_write(vs);
825 }
827 static uint8_t read_u8(uint8_t *data, size_t offset)
828 {
829 return data[offset];
830 }
832 static uint16_t read_u16(uint8_t *data, size_t offset)
833 {
834 return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
835 }
837 static int32_t read_s32(uint8_t *data, size_t offset)
838 {
839 return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
840 (data[offset + 2] << 8) | data[offset + 3]);
841 }
843 static uint32_t read_u32(uint8_t *data, size_t offset)
844 {
845 return ((data[offset] << 24) | (data[offset + 1] << 16) |
846 (data[offset + 2] << 8) | data[offset + 3]);
847 }
849 static void client_cut_text(VncState *vs, size_t len, char *text)
850 {
851 }
853 static void check_pointer_type_change(VncState *vs, int absolute)
854 {
855 if (vs->has_pointer_type_change && vs->absolute != absolute) {
856 vnc_write_u8(vs, 0);
857 vnc_write_u8(vs, 0);
858 vnc_write_u16(vs, 1);
859 vnc_framebuffer_update(vs, absolute, 0,
860 vs->ds->width, vs->ds->height, -257);
861 vnc_flush(vs);
862 }
863 vs->absolute = absolute;
864 }
866 static void pointer_event(VncState *vs, int button_mask, int x, int y)
867 {
868 int buttons = 0;
869 int dz = 0;
871 if (button_mask & 0x01)
872 buttons |= MOUSE_EVENT_LBUTTON;
873 if (button_mask & 0x02)
874 buttons |= MOUSE_EVENT_MBUTTON;
875 if (button_mask & 0x04)
876 buttons |= MOUSE_EVENT_RBUTTON;
877 if (button_mask & 0x08)
878 dz = -1;
879 if (button_mask & 0x10)
880 dz = 1;
882 if (vs->absolute) {
883 kbd_mouse_event(x * 0x7FFF / vs->ds->width,
884 y * 0x7FFF / vs->ds->height,
885 dz, buttons);
886 } else if (vs->has_pointer_type_change) {
887 x -= 0x7FFF;
888 y -= 0x7FFF;
890 kbd_mouse_event(x, y, dz, buttons);
891 } else {
892 if (vs->last_x != -1)
893 kbd_mouse_event(x - vs->last_x,
894 y - vs->last_y,
895 dz, buttons);
896 vs->last_x = x;
897 vs->last_y = y;
898 }
900 check_pointer_type_change(vs, kbd_mouse_is_absolute());
901 }
903 static void reset_keys(VncState *vs)
904 {
905 int i;
906 for(i = 0; i < 256; i++) {
907 if (vs->modifiers_state[i]) {
908 if (i & 0x80)
909 kbd_put_keycode(0xe0);
910 kbd_put_keycode(i | 0x80);
911 vs->modifiers_state[i] = 0;
912 }
913 }
914 }
916 static void do_key_event(VncState *vs, int down, uint32_t sym)
917 {
918 int keycode;
920 keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
922 /* QEMU console switch */
923 switch(keycode) {
924 case 0x2a: /* Left Shift */
925 case 0x36: /* Right Shift */
926 case 0x1d: /* Left CTRL */
927 case 0x9d: /* Right CTRL */
928 case 0x38: /* Left ALT */
929 case 0xb8: /* Right ALT */
930 if (down)
931 vs->modifiers_state[keycode] = 1;
932 else
933 vs->modifiers_state[keycode] = 0;
934 break;
935 case 0x02 ... 0x0a: /* '1' to '9' keys */
936 if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
937 /* Reset the modifiers sent to the current console */
938 reset_keys(vs);
939 console_select(keycode - 0x02);
940 return;
941 }
942 break;
943 }
945 if (is_graphic_console()) {
946 if (keycode & 0x80)
947 kbd_put_keycode(0xe0);
948 if (down)
949 kbd_put_keycode(keycode & 0x7f);
950 else
951 kbd_put_keycode(keycode | 0x80);
952 } else {
953 /* QEMU console emulation */
954 if (down) {
955 switch (keycode) {
956 case 0x2a: /* Left Shift */
957 case 0x36: /* Right Shift */
958 case 0x1d: /* Left CTRL */
959 case 0x9d: /* Right CTRL */
960 case 0x38: /* Left ALT */
961 case 0xb8: /* Right ALT */
962 break;
963 case 0xc8:
964 kbd_put_keysym(QEMU_KEY_UP);
965 break;
966 case 0xd0:
967 kbd_put_keysym(QEMU_KEY_DOWN);
968 break;
969 case 0xcb:
970 kbd_put_keysym(QEMU_KEY_LEFT);
971 break;
972 case 0xcd:
973 kbd_put_keysym(QEMU_KEY_RIGHT);
974 break;
975 case 0xd3:
976 kbd_put_keysym(QEMU_KEY_DELETE);
977 break;
978 case 0xc7:
979 kbd_put_keysym(QEMU_KEY_HOME);
980 break;
981 case 0xcf:
982 kbd_put_keysym(QEMU_KEY_END);
983 break;
984 case 0xc9:
985 kbd_put_keysym(QEMU_KEY_PAGEUP);
986 break;
987 case 0xd1:
988 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
989 break;
990 default:
991 kbd_put_keysym(sym);
992 break;
993 }
994 }
995 }
996 }
998 static void key_event(VncState *vs, int down, uint32_t sym)
999 {
1000 if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
1001 sym = sym - 'A' + 'a';
1002 do_key_event(vs, down, sym);
1005 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h)
1008 set_bits_in_row(vs, vs->update_row, x, y, w, h);
1010 vs->has_update = 1;
1013 static void framebuffer_update_request(VncState *vs, int incremental,
1014 int x_position, int y_position,
1015 int w, int h)
1017 if (!incremental)
1018 framebuffer_set_updated(vs, x_position, y_position, w, h);
1019 vs->visible_x = x_position;
1020 vs->visible_y = y_position;
1021 vs->visible_w = w;
1022 vs->visible_h = h;
1024 qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
1027 static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1029 int i;
1031 vs->has_hextile = 0;
1032 vs->has_resize = 0;
1033 vs->has_pointer_type_change = 0;
1034 vs->absolute = -1;
1035 vs->ds->dpy_copy = NULL;
1037 for (i = n_encodings - 1; i >= 0; i--) {
1038 switch (encodings[i]) {
1039 case 0: /* Raw */
1040 vs->has_hextile = 0;
1041 break;
1042 case 1: /* CopyRect */
1043 vs->ds->dpy_copy = vnc_copy;
1044 break;
1045 case 5: /* Hextile */
1046 vs->has_hextile = 1;
1047 break;
1048 case -223: /* DesktopResize */
1049 vs->has_resize = 1;
1050 break;
1051 case -257:
1052 vs->has_pointer_type_change = 1;
1053 break;
1054 default:
1055 break;
1059 check_pointer_type_change(vs, kbd_mouse_is_absolute());
1062 static int compute_nbits(unsigned int val)
1064 int n;
1065 n = 0;
1066 while (val != 0) {
1067 n++;
1068 val >>= 1;
1070 return n;
1073 static void set_pixel_format(VncState *vs,
1074 int bits_per_pixel, int depth,
1075 int big_endian_flag, int true_color_flag,
1076 int red_max, int green_max, int blue_max,
1077 int red_shift, int green_shift, int blue_shift)
1079 int host_big_endian_flag;
1081 #ifdef WORDS_BIGENDIAN
1082 host_big_endian_flag = 1;
1083 #else
1084 host_big_endian_flag = 0;
1085 #endif
1086 if (!true_color_flag) {
1087 fail:
1088 vnc_client_error(vs);
1089 return;
1091 if (bits_per_pixel == 32 &&
1092 host_big_endian_flag == big_endian_flag &&
1093 red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1094 red_shift == 16 && green_shift == 8 && blue_shift == 0) {
1095 vs->depth = 4;
1096 vs->write_pixels = vnc_write_pixels_copy;
1097 vs->send_hextile_tile = send_hextile_tile_32;
1098 } else
1099 if (bits_per_pixel == 16 &&
1100 host_big_endian_flag == big_endian_flag &&
1101 red_max == 31 && green_max == 63 && blue_max == 31 &&
1102 red_shift == 11 && green_shift == 5 && blue_shift == 0) {
1103 vs->depth = 2;
1104 vs->write_pixels = vnc_write_pixels_copy;
1105 vs->send_hextile_tile = send_hextile_tile_16;
1106 } else
1107 if (bits_per_pixel == 8 &&
1108 red_max == 7 && green_max == 7 && blue_max == 3 &&
1109 red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1110 vs->depth = 1;
1111 vs->write_pixels = vnc_write_pixels_copy;
1112 vs->send_hextile_tile = send_hextile_tile_8;
1113 } else
1115 /* generic and slower case */
1116 if (bits_per_pixel != 8 &&
1117 bits_per_pixel != 16 &&
1118 bits_per_pixel != 32)
1119 goto fail;
1120 vs->depth = 4;
1121 vs->red_shift = red_shift;
1122 vs->red_max = red_max;
1123 vs->red_shift1 = 24 - compute_nbits(red_max);
1124 vs->green_shift = green_shift;
1125 vs->green_max = green_max;
1126 vs->green_shift1 = 16 - compute_nbits(green_max);
1127 vs->blue_shift = blue_shift;
1128 vs->blue_max = blue_max;
1129 vs->blue_shift1 = 8 - compute_nbits(blue_max);
1130 vs->pix_bpp = bits_per_pixel / 8;
1131 vs->pix_big_endian = big_endian_flag;
1132 vs->write_pixels = vnc_write_pixels_generic;
1133 vs->send_hextile_tile = send_hextile_tile_generic;
1136 vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
1138 vga_hw_invalidate();
1139 vga_hw_update();
1142 static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1144 int i;
1145 uint16_t limit;
1147 switch (data[0]) {
1148 case 0:
1149 if (len == 1)
1150 return 20;
1152 set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1153 read_u8(data, 6), read_u8(data, 7),
1154 read_u16(data, 8), read_u16(data, 10),
1155 read_u16(data, 12), read_u8(data, 14),
1156 read_u8(data, 15), read_u8(data, 16));
1157 break;
1158 case 2:
1159 if (len == 1)
1160 return 4;
1162 if (len == 4) {
1163 uint16_t v;
1164 v = read_u16(data, 2);
1165 if (v)
1166 return 4 + v * 4;
1169 limit = read_u16(data, 2);
1170 for (i = 0; i < limit; i++) {
1171 int32_t val = read_s32(data, 4 + (i * 4));
1172 memcpy(data + 4 + (i * 4), &val, sizeof(val));
1175 set_encodings(vs, (int32_t *)(data + 4), limit);
1176 break;
1177 case 3:
1178 if (len == 1)
1179 return 10;
1181 framebuffer_update_request(vs,
1182 read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1183 read_u16(data, 6), read_u16(data, 8));
1184 break;
1185 case 4:
1186 if (len == 1)
1187 return 8;
1189 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1190 qemu_advance_timer(vs->timer,
1191 qemu_get_clock(rt_clock) + vs->timer_interval);
1192 key_event(vs, read_u8(data, 1), read_u32(data, 4));
1193 break;
1194 case 5:
1195 if (len == 1)
1196 return 6;
1198 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1199 qemu_advance_timer(vs->timer,
1200 qemu_get_clock(rt_clock) + vs->timer_interval);
1201 pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1202 break;
1203 case 6:
1204 if (len == 1)
1205 return 8;
1207 if (len == 8) {
1208 uint32_t v;
1209 v = read_u32(data, 4);
1210 if (v)
1211 return 8 + v;
1214 client_cut_text(vs, read_u32(data, 4), (char *)(data + 8));
1215 break;
1216 default:
1217 printf("Msg: %d\n", data[0]);
1218 vnc_client_error(vs);
1219 break;
1222 vnc_read_when(vs, protocol_client_msg, 1);
1223 return 0;
1226 static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1228 size_t l;
1229 char pad[3] = { 0, 0, 0 };
1231 vga_hw_update();
1233 vs->width = vs->ds->width;
1234 vs->height = vs->ds->height;
1235 vnc_write_u16(vs, vs->ds->width);
1236 vnc_write_u16(vs, vs->ds->height);
1238 vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1239 vnc_write_u8(vs, vs->depth * 8); /* depth */
1240 #ifdef WORDS_BIGENDIAN
1241 vnc_write_u8(vs, 1); /* big-endian-flag */
1242 #else
1243 vnc_write_u8(vs, 0); /* big-endian-flag */
1244 #endif
1245 vnc_write_u8(vs, 1); /* true-color-flag */
1246 if (vs->depth == 4) {
1247 vnc_write_u16(vs, 0xFF); /* red-max */
1248 vnc_write_u16(vs, 0xFF); /* green-max */
1249 vnc_write_u16(vs, 0xFF); /* blue-max */
1250 vnc_write_u8(vs, 16); /* red-shift */
1251 vnc_write_u8(vs, 8); /* green-shift */
1252 vnc_write_u8(vs, 0); /* blue-shift */
1253 vs->send_hextile_tile = send_hextile_tile_32;
1254 } else if (vs->depth == 2) {
1255 vnc_write_u16(vs, 31); /* red-max */
1256 vnc_write_u16(vs, 63); /* green-max */
1257 vnc_write_u16(vs, 31); /* blue-max */
1258 vnc_write_u8(vs, 11); /* red-shift */
1259 vnc_write_u8(vs, 5); /* green-shift */
1260 vnc_write_u8(vs, 0); /* blue-shift */
1261 vs->send_hextile_tile = send_hextile_tile_16;
1262 } else if (vs->depth == 1) {
1263 /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
1264 vnc_write_u16(vs, 7); /* red-max */
1265 vnc_write_u16(vs, 7); /* green-max */
1266 vnc_write_u16(vs, 3); /* blue-max */
1267 vnc_write_u8(vs, 5); /* red-shift */
1268 vnc_write_u8(vs, 2); /* green-shift */
1269 vnc_write_u8(vs, 0); /* blue-shift */
1270 vs->send_hextile_tile = send_hextile_tile_8;
1272 vs->write_pixels = vnc_write_pixels_copy;
1274 vnc_write(vs, pad, 3); /* padding */
1276 l = strlen(domain_name);
1277 vnc_write_u32(vs, l);
1278 vnc_write(vs, domain_name, l);
1280 vnc_flush(vs);
1282 vnc_read_when(vs, protocol_client_msg, 1);
1284 return 0;
1287 static int protocol_response(VncState *vs, uint8_t *client_response, size_t len)
1289 extern char vncpasswd[64];
1290 extern unsigned char challenge[AUTHCHALLENGESIZE];
1291 unsigned char cryptchallenge[AUTHCHALLENGESIZE];
1292 unsigned char key[8];
1293 int passwdlen, i, j;
1295 memcpy(cryptchallenge, challenge, AUTHCHALLENGESIZE);
1297 /* Calculate the sent challenge */
1298 passwdlen = strlen(vncpasswd);
1299 for (i=0; i<8; i++)
1300 key[i] = i<passwdlen ? vncpasswd[i] : 0;
1301 deskey(key, EN0);
1302 for (j = 0; j < AUTHCHALLENGESIZE; j += 8)
1303 des(cryptchallenge+j, cryptchallenge+j);
1305 /* Check the actual response */
1306 if (memcmp(cryptchallenge, client_response, AUTHCHALLENGESIZE) != 0) {
1307 /* password error */
1308 vnc_write_u32(vs, 1);
1309 vnc_write_u32(vs, 22);
1310 vnc_write(vs, "Authentication failure", 22);
1311 vnc_flush(vs);
1312 fprintf(stderr, "VNC Password error.\n");
1313 vnc_client_error(vs);
1314 return 0;
1317 vnc_write_u32(vs, 0);
1318 vnc_flush(vs);
1320 vnc_read_when(vs, protocol_client_init, 1);
1322 return 0;
1325 static int protocol_version(VncState *vs, uint8_t *version, size_t len)
1327 extern char vncpasswd[64];
1328 extern unsigned char challenge[AUTHCHALLENGESIZE];
1329 char local[13];
1330 int support, maj, min;
1332 memcpy(local, version, 12);
1333 local[12] = 0;
1335 /* protocol version check */
1336 if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
1337 fprintf(stderr, "Protocol version error.\n");
1338 vnc_client_error(vs);
1339 return 0;
1343 support = 0;
1344 if (maj == 3) {
1345 if (min == 3 || min ==4) {
1346 support = 1;
1350 if (! support) {
1351 fprintf(stderr, "Client uses unsupported protocol version %d.%d.\n",
1352 maj, min);
1353 vnc_client_error(vs);
1354 return 0;
1357 if (*vncpasswd == '\0') {
1358 /* AuthType is None */
1359 vnc_write_u32(vs, 1);
1360 vnc_flush(vs);
1361 vnc_read_when(vs, protocol_client_init, 1);
1362 } else {
1363 /* AuthType is VncAuth */
1364 vnc_write_u32(vs, 2);
1366 /* Challenge-Responce authentication */
1367 /* Send Challenge */
1368 make_challenge(challenge, AUTHCHALLENGESIZE);
1369 vnc_write(vs, challenge, AUTHCHALLENGESIZE);
1370 vnc_flush(vs);
1371 vnc_read_when(vs, protocol_response, AUTHCHALLENGESIZE);
1374 return 0;
1377 static void vnc_listen_read(void *opaque)
1379 VncState *vs = opaque;
1380 struct sockaddr_in addr;
1381 socklen_t addrlen = sizeof(addr);
1383 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
1384 if (vs->csock != -1) {
1385 socket_set_nonblock(vs->csock);
1386 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
1387 vnc_write(vs, "RFB 003.003\n", 12);
1388 vnc_flush(vs);
1389 vnc_read_when(vs, protocol_version, 12);
1390 framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
1391 vs->has_resize = 0;
1392 vs->has_hextile = 0;
1393 vs->ds->dpy_copy = NULL;
1394 vnc_timer_init(vs);
1398 extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
1400 int vnc_display_init(DisplayState *ds, const char *arg, int find_unused, struct sockaddr_in *iaddr)
1402 struct sockaddr *addr;
1403 #ifndef _WIN32
1404 struct sockaddr_un uaddr;
1405 #endif
1406 int reuse_addr, ret;
1407 socklen_t addrlen;
1408 const char *p;
1409 VncState *vs;
1411 vs = qemu_mallocz(sizeof(VncState));
1412 if (!vs)
1413 exit(1);
1415 ds->opaque = vs;
1416 vnc_state = vs;
1417 vs->display = arg;
1419 vs->lsock = -1;
1420 vs->csock = -1;
1421 vs->depth = 4;
1422 vs->last_x = -1;
1423 vs->last_y = -1;
1425 vs->ds = ds;
1427 if (!keyboard_layout)
1428 keyboard_layout = "en-us";
1430 vs->kbd_layout = init_keyboard_layout(keyboard_layout);
1431 if (!vs->kbd_layout)
1432 exit(1);
1434 vs->ds->data = NULL;
1435 vs->ds->dpy_update = vnc_dpy_update;
1436 vs->ds->dpy_resize = vnc_dpy_resize;
1437 vs->ds->dpy_refresh = vnc_dpy_refresh;
1439 vnc_dpy_resize(vs->ds, 640, 400);
1441 if (arg == NULL)
1442 arg = "localhost:0";
1444 #ifndef _WIN32
1445 if (strstart(arg, "unix:", &p)) {
1446 addr = (struct sockaddr *)&uaddr;
1447 addrlen = sizeof(uaddr);
1449 vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
1450 if (vs->lsock == -1) {
1451 fprintf(stderr, "Could not create socket\n");
1452 exit(1);
1455 uaddr.sun_family = AF_UNIX;
1456 memset(uaddr.sun_path, 0, 108);
1457 snprintf(uaddr.sun_path, 108, "%s", p);
1459 unlink(uaddr.sun_path);
1460 } else
1461 #endif
1463 addr = (struct sockaddr *)iaddr;
1464 addrlen = sizeof(*iaddr);
1466 vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
1467 if (vs->lsock == -1) {
1468 fprintf(stderr, "Could not create socket\n");
1469 exit(1);
1472 if (parse_host_port(iaddr, arg) < 0) {
1473 fprintf(stderr, "Could not parse VNC address\n");
1474 exit(1);
1477 iaddr->sin_port = htons(ntohs(iaddr->sin_port) + 5900);
1479 reuse_addr = 1;
1480 ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
1481 (const char *)&reuse_addr, sizeof(reuse_addr));
1482 if (ret == -1) {
1483 fprintf(stderr, "setsockopt() failed\n");
1484 exit(1);
1488 while (bind(vs->lsock, addr, addrlen) == -1) {
1489 if (find_unused && errno == EADDRINUSE) {
1490 iaddr->sin_port = htons(ntohs(iaddr->sin_port) + 1);
1491 continue;
1493 fprintf(stderr, "bind() failed\n");
1494 exit(1);
1497 if (listen(vs->lsock, 1) == -1) {
1498 fprintf(stderr, "listen() failed\n");
1499 exit(1);
1502 ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
1503 if (ret == -1) {
1504 exit(1);
1507 return ntohs(iaddr->sin_port);
1510 int vnc_start_viewer(int port)
1512 int pid, i, open_max;
1513 char s[16];
1515 sprintf(s, ":%d", port);
1517 switch (pid = fork()) {
1518 case -1:
1519 fprintf(stderr, "vncviewer failed fork\n");
1520 exit(1);
1522 case 0: /* child */
1523 open_max = sysconf(_SC_OPEN_MAX);
1524 for (i = 0; i < open_max; i++)
1525 if (i != STDIN_FILENO &&
1526 i != STDOUT_FILENO &&
1527 i != STDERR_FILENO)
1528 close(i);
1529 execlp("vncviewer", "vncviewer", s, NULL);
1530 fprintf(stderr, "vncviewer execlp failed\n");
1531 exit(1);
1533 default:
1534 return pid;
1538 unsigned int seed;
1540 static int make_challenge(unsigned char *random, int size)
1543 set_seed(&seed);
1544 get_random(size, random);
1546 return 0;
1549 static void set_seed(unsigned int *seedp)
1551 *seedp += (unsigned int)(time(NULL)+getpid()+getpid()*987654+rand());
1552 srand(*seedp);
1554 return;
1557 static void get_random(int len, unsigned char *buf)
1559 int i;
1561 for (i=0; i<len; i++)
1562 buf[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1564 return;