ia64/xen-unstable

view tools/ioemu/vnc.c @ 15068:5040a3ff50ee

[qemu] Remove no longer needed change.

Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
author Christian Limpach <Christian.Limpach@xensource.com>
date Thu May 10 15:10:16 2007 +0100 (2007-05-10)
parents 7da6d9c374be
children a6308744caae
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 do_key_event(VncState *vs, int down, uint32_t sym)
913 {
914 int keycode;
916 keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
918 /* QEMU console switch */
919 switch(keycode) {
920 case 0x2a: /* Left Shift */
921 case 0x36: /* Right Shift */
922 case 0x1d: /* Left CTRL */
923 case 0x9d: /* Right CTRL */
924 case 0x38: /* Left ALT */
925 case 0xb8: /* Right ALT */
926 if (down)
927 vs->modifiers_state[keycode] = 1;
928 else
929 vs->modifiers_state[keycode] = 0;
930 break;
931 case 0x02 ... 0x0a: /* '1' to '9' keys */
932 if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
933 /* Reset the modifiers sent to the current console */
934 reset_keys(vs);
935 console_select(keycode - 0x02);
936 return;
937 }
938 break;
939 }
941 if (is_graphic_console()) {
942 if (keycode & 0x80)
943 kbd_put_keycode(0xe0);
944 if (down)
945 kbd_put_keycode(keycode & 0x7f);
946 else
947 kbd_put_keycode(keycode | 0x80);
948 } else {
949 /* QEMU console emulation */
950 if (down) {
951 switch (keycode) {
952 case 0x2a: /* Left Shift */
953 case 0x36: /* Right Shift */
954 case 0x1d: /* Left CTRL */
955 case 0x9d: /* Right CTRL */
956 case 0x38: /* Left ALT */
957 case 0xb8: /* Right ALT */
958 break;
959 case 0xc8:
960 kbd_put_keysym(QEMU_KEY_UP);
961 break;
962 case 0xd0:
963 kbd_put_keysym(QEMU_KEY_DOWN);
964 break;
965 case 0xcb:
966 kbd_put_keysym(QEMU_KEY_LEFT);
967 break;
968 case 0xcd:
969 kbd_put_keysym(QEMU_KEY_RIGHT);
970 break;
971 case 0xd3:
972 kbd_put_keysym(QEMU_KEY_DELETE);
973 break;
974 case 0xc7:
975 kbd_put_keysym(QEMU_KEY_HOME);
976 break;
977 case 0xcf:
978 kbd_put_keysym(QEMU_KEY_END);
979 break;
980 case 0xc9:
981 kbd_put_keysym(QEMU_KEY_PAGEUP);
982 break;
983 case 0xd1:
984 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
985 break;
986 default:
987 kbd_put_keysym(sym);
988 break;
989 }
990 }
991 }
992 }
994 static void key_event(VncState *vs, int down, uint32_t sym)
995 {
996 if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
997 sym = sym - 'A' + 'a';
998 do_key_event(vs, down, sym);
999 }
1001 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h)
1004 set_bits_in_row(vs, vs->update_row, x, y, w, h);
1006 vs->has_update = 1;
1009 static void framebuffer_update_request(VncState *vs, int incremental,
1010 int x_position, int y_position,
1011 int w, int h)
1013 if (!incremental)
1014 framebuffer_set_updated(vs, x_position, y_position, w, h);
1015 vs->visible_x = x_position;
1016 vs->visible_y = y_position;
1017 vs->visible_w = w;
1018 vs->visible_h = h;
1020 qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
1023 static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1025 int i;
1027 vs->has_hextile = 0;
1028 vs->has_resize = 0;
1029 vs->has_pointer_type_change = 0;
1030 vs->absolute = -1;
1031 vs->ds->dpy_copy = NULL;
1033 for (i = n_encodings - 1; i >= 0; i--) {
1034 switch (encodings[i]) {
1035 case 0: /* Raw */
1036 vs->has_hextile = 0;
1037 break;
1038 case 1: /* CopyRect */
1039 vs->ds->dpy_copy = vnc_copy;
1040 break;
1041 case 5: /* Hextile */
1042 vs->has_hextile = 1;
1043 break;
1044 case -223: /* DesktopResize */
1045 vs->has_resize = 1;
1046 break;
1047 case -257:
1048 vs->has_pointer_type_change = 1;
1049 break;
1050 default:
1051 break;
1055 check_pointer_type_change(vs, kbd_mouse_is_absolute());
1058 static int compute_nbits(unsigned int val)
1060 int n;
1061 n = 0;
1062 while (val != 0) {
1063 n++;
1064 val >>= 1;
1066 return n;
1069 static void set_pixel_format(VncState *vs,
1070 int bits_per_pixel, int depth,
1071 int big_endian_flag, int true_color_flag,
1072 int red_max, int green_max, int blue_max,
1073 int red_shift, int green_shift, int blue_shift)
1075 int host_big_endian_flag;
1077 #ifdef WORDS_BIGENDIAN
1078 host_big_endian_flag = 1;
1079 #else
1080 host_big_endian_flag = 0;
1081 #endif
1082 if (!true_color_flag) {
1083 fail:
1084 vnc_client_error(vs);
1085 return;
1087 if (bits_per_pixel == 32 &&
1088 host_big_endian_flag == big_endian_flag &&
1089 red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1090 red_shift == 16 && green_shift == 8 && blue_shift == 0) {
1091 vs->depth = 4;
1092 vs->write_pixels = vnc_write_pixels_copy;
1093 vs->send_hextile_tile = send_hextile_tile_32;
1094 } else
1095 if (bits_per_pixel == 16 &&
1096 host_big_endian_flag == big_endian_flag &&
1097 red_max == 31 && green_max == 63 && blue_max == 31 &&
1098 red_shift == 11 && green_shift == 5 && blue_shift == 0) {
1099 vs->depth = 2;
1100 vs->write_pixels = vnc_write_pixels_copy;
1101 vs->send_hextile_tile = send_hextile_tile_16;
1102 } else
1103 if (bits_per_pixel == 8 &&
1104 red_max == 7 && green_max == 7 && blue_max == 3 &&
1105 red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1106 vs->depth = 1;
1107 vs->write_pixels = vnc_write_pixels_copy;
1108 vs->send_hextile_tile = send_hextile_tile_8;
1109 } else
1111 /* generic and slower case */
1112 if (bits_per_pixel != 8 &&
1113 bits_per_pixel != 16 &&
1114 bits_per_pixel != 32)
1115 goto fail;
1116 vs->depth = 4;
1117 vs->red_shift = red_shift;
1118 vs->red_max = red_max;
1119 vs->red_shift1 = 24 - compute_nbits(red_max);
1120 vs->green_shift = green_shift;
1121 vs->green_max = green_max;
1122 vs->green_shift1 = 16 - compute_nbits(green_max);
1123 vs->blue_shift = blue_shift;
1124 vs->blue_max = blue_max;
1125 vs->blue_shift1 = 8 - compute_nbits(blue_max);
1126 vs->pix_bpp = bits_per_pixel / 8;
1127 vs->pix_big_endian = big_endian_flag;
1128 vs->write_pixels = vnc_write_pixels_generic;
1129 vs->send_hextile_tile = send_hextile_tile_generic;
1132 vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
1134 vga_hw_invalidate();
1135 vga_hw_update();
1138 static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1140 int i;
1141 uint16_t limit;
1143 switch (data[0]) {
1144 case 0:
1145 if (len == 1)
1146 return 20;
1148 set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1149 read_u8(data, 6), read_u8(data, 7),
1150 read_u16(data, 8), read_u16(data, 10),
1151 read_u16(data, 12), read_u8(data, 14),
1152 read_u8(data, 15), read_u8(data, 16));
1153 break;
1154 case 2:
1155 if (len == 1)
1156 return 4;
1158 if (len == 4) {
1159 uint16_t v;
1160 v = read_u16(data, 2);
1161 if (v)
1162 return 4 + v * 4;
1165 limit = read_u16(data, 2);
1166 for (i = 0; i < limit; i++) {
1167 int32_t val = read_s32(data, 4 + (i * 4));
1168 memcpy(data + 4 + (i * 4), &val, sizeof(val));
1171 set_encodings(vs, (int32_t *)(data + 4), limit);
1172 break;
1173 case 3:
1174 if (len == 1)
1175 return 10;
1177 framebuffer_update_request(vs,
1178 read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1179 read_u16(data, 6), read_u16(data, 8));
1180 break;
1181 case 4:
1182 if (len == 1)
1183 return 8;
1185 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1186 qemu_advance_timer(vs->timer,
1187 qemu_get_clock(rt_clock) + vs->timer_interval);
1188 key_event(vs, read_u8(data, 1), read_u32(data, 4));
1189 break;
1190 case 5:
1191 if (len == 1)
1192 return 6;
1194 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1195 qemu_advance_timer(vs->timer,
1196 qemu_get_clock(rt_clock) + vs->timer_interval);
1197 pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1198 break;
1199 case 6:
1200 if (len == 1)
1201 return 8;
1203 if (len == 8) {
1204 uint32_t v;
1205 v = read_u32(data, 4);
1206 if (v)
1207 return 8 + v;
1210 client_cut_text(vs, read_u32(data, 4), (char *)(data + 8));
1211 break;
1212 default:
1213 printf("Msg: %d\n", data[0]);
1214 vnc_client_error(vs);
1215 break;
1218 vnc_read_when(vs, protocol_client_msg, 1);
1219 return 0;
1222 static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1224 size_t l;
1225 char pad[3] = { 0, 0, 0 };
1227 vga_hw_update();
1229 vs->width = vs->ds->width;
1230 vs->height = vs->ds->height;
1231 vnc_write_u16(vs, vs->ds->width);
1232 vnc_write_u16(vs, vs->ds->height);
1234 vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1235 vnc_write_u8(vs, vs->depth * 8); /* depth */
1236 #ifdef WORDS_BIGENDIAN
1237 vnc_write_u8(vs, 1); /* big-endian-flag */
1238 #else
1239 vnc_write_u8(vs, 0); /* big-endian-flag */
1240 #endif
1241 vnc_write_u8(vs, 1); /* true-color-flag */
1242 if (vs->depth == 4) {
1243 vnc_write_u16(vs, 0xFF); /* red-max */
1244 vnc_write_u16(vs, 0xFF); /* green-max */
1245 vnc_write_u16(vs, 0xFF); /* blue-max */
1246 vnc_write_u8(vs, 16); /* red-shift */
1247 vnc_write_u8(vs, 8); /* green-shift */
1248 vnc_write_u8(vs, 0); /* blue-shift */
1249 vs->send_hextile_tile = send_hextile_tile_32;
1250 } else if (vs->depth == 2) {
1251 vnc_write_u16(vs, 31); /* red-max */
1252 vnc_write_u16(vs, 63); /* green-max */
1253 vnc_write_u16(vs, 31); /* blue-max */
1254 vnc_write_u8(vs, 11); /* red-shift */
1255 vnc_write_u8(vs, 5); /* green-shift */
1256 vnc_write_u8(vs, 0); /* blue-shift */
1257 vs->send_hextile_tile = send_hextile_tile_16;
1258 } else if (vs->depth == 1) {
1259 /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
1260 vnc_write_u16(vs, 7); /* red-max */
1261 vnc_write_u16(vs, 7); /* green-max */
1262 vnc_write_u16(vs, 3); /* blue-max */
1263 vnc_write_u8(vs, 5); /* red-shift */
1264 vnc_write_u8(vs, 2); /* green-shift */
1265 vnc_write_u8(vs, 0); /* blue-shift */
1266 vs->send_hextile_tile = send_hextile_tile_8;
1268 vs->write_pixels = vnc_write_pixels_copy;
1270 vnc_write(vs, pad, 3); /* padding */
1272 l = strlen(domain_name);
1273 vnc_write_u32(vs, l);
1274 vnc_write(vs, domain_name, l);
1276 vnc_flush(vs);
1278 vnc_read_when(vs, protocol_client_msg, 1);
1280 return 0;
1283 static int protocol_response(VncState *vs, uint8_t *client_response, size_t len)
1285 extern char vncpasswd[64];
1286 extern unsigned char challenge[AUTHCHALLENGESIZE];
1287 unsigned char cryptchallenge[AUTHCHALLENGESIZE];
1288 unsigned char key[8];
1289 int passwdlen, i, j;
1291 memcpy(cryptchallenge, challenge, AUTHCHALLENGESIZE);
1293 /* Calculate the sent challenge */
1294 passwdlen = strlen(vncpasswd);
1295 for (i=0; i<8; i++)
1296 key[i] = i<passwdlen ? vncpasswd[i] : 0;
1297 deskey(key, EN0);
1298 for (j = 0; j < AUTHCHALLENGESIZE; j += 8)
1299 des(cryptchallenge+j, cryptchallenge+j);
1301 /* Check the actual response */
1302 if (memcmp(cryptchallenge, client_response, AUTHCHALLENGESIZE) != 0) {
1303 /* password error */
1304 vnc_write_u32(vs, 1);
1305 vnc_write_u32(vs, 22);
1306 vnc_write(vs, "Authentication failure", 22);
1307 vnc_flush(vs);
1308 fprintf(stderr, "VNC Password error.\n");
1309 vnc_client_error(vs);
1310 return 0;
1313 vnc_write_u32(vs, 0);
1314 vnc_flush(vs);
1316 vnc_read_when(vs, protocol_client_init, 1);
1318 return 0;
1321 static int protocol_version(VncState *vs, uint8_t *version, size_t len)
1323 extern char vncpasswd[64];
1324 extern unsigned char challenge[AUTHCHALLENGESIZE];
1325 char local[13];
1326 int support, maj, min;
1328 memcpy(local, version, 12);
1329 local[12] = 0;
1331 /* protocol version check */
1332 if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
1333 fprintf(stderr, "Protocol version error.\n");
1334 vnc_client_error(vs);
1335 return 0;
1339 support = 0;
1340 if (maj == 3) {
1341 if (min == 3 || min ==4) {
1342 support = 1;
1346 if (! support) {
1347 fprintf(stderr, "Client uses unsupported protocol version %d.%d.\n",
1348 maj, min);
1349 vnc_client_error(vs);
1350 return 0;
1353 if (*vncpasswd == '\0') {
1354 /* AuthType is None */
1355 vnc_write_u32(vs, 1);
1356 vnc_flush(vs);
1357 vnc_read_when(vs, protocol_client_init, 1);
1358 } else {
1359 /* AuthType is VncAuth */
1360 vnc_write_u32(vs, 2);
1362 /* Challenge-Responce authentication */
1363 /* Send Challenge */
1364 make_challenge(challenge, AUTHCHALLENGESIZE);
1365 vnc_write(vs, challenge, AUTHCHALLENGESIZE);
1366 vnc_flush(vs);
1367 vnc_read_when(vs, protocol_response, AUTHCHALLENGESIZE);
1370 return 0;
1373 static void vnc_listen_read(void *opaque)
1375 VncState *vs = opaque;
1376 struct sockaddr_in addr;
1377 socklen_t addrlen = sizeof(addr);
1379 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
1380 if (vs->csock != -1) {
1381 socket_set_nonblock(vs->csock);
1382 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
1383 vnc_write(vs, "RFB 003.003\n", 12);
1384 vnc_flush(vs);
1385 vnc_read_when(vs, protocol_version, 12);
1386 framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
1387 vs->has_resize = 0;
1388 vs->has_hextile = 0;
1389 vs->ds->dpy_copy = NULL;
1390 vnc_timer_init(vs);
1394 extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
1396 int vnc_display_init(DisplayState *ds, const char *arg, int find_unused, struct sockaddr_in *iaddr)
1398 struct sockaddr *addr;
1399 #ifndef _WIN32
1400 struct sockaddr_un uaddr;
1401 #endif
1402 int reuse_addr, ret;
1403 socklen_t addrlen;
1404 const char *p;
1405 VncState *vs;
1407 vs = qemu_mallocz(sizeof(VncState));
1408 if (!vs)
1409 exit(1);
1411 ds->opaque = vs;
1412 vnc_state = vs;
1413 vs->display = arg;
1415 vs->lsock = -1;
1416 vs->csock = -1;
1417 vs->depth = 4;
1418 vs->last_x = -1;
1419 vs->last_y = -1;
1421 vs->ds = ds;
1423 if (!keyboard_layout)
1424 keyboard_layout = "en-us";
1426 vs->kbd_layout = init_keyboard_layout(keyboard_layout);
1427 if (!vs->kbd_layout)
1428 exit(1);
1430 vs->ds->data = NULL;
1431 vs->ds->dpy_update = vnc_dpy_update;
1432 vs->ds->dpy_resize = vnc_dpy_resize;
1433 vs->ds->dpy_refresh = vnc_dpy_refresh;
1435 vnc_dpy_resize(vs->ds, 640, 400);
1437 if (arg == NULL)
1438 arg = "localhost:0";
1440 #ifndef _WIN32
1441 if (strstart(arg, "unix:", &p)) {
1442 addr = (struct sockaddr *)&uaddr;
1443 addrlen = sizeof(uaddr);
1445 vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
1446 if (vs->lsock == -1) {
1447 fprintf(stderr, "Could not create socket\n");
1448 exit(1);
1451 uaddr.sun_family = AF_UNIX;
1452 memset(uaddr.sun_path, 0, 108);
1453 snprintf(uaddr.sun_path, 108, "%s", p);
1455 unlink(uaddr.sun_path);
1456 } else
1457 #endif
1459 addr = (struct sockaddr *)iaddr;
1460 addrlen = sizeof(*iaddr);
1462 vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
1463 if (vs->lsock == -1) {
1464 fprintf(stderr, "Could not create socket\n");
1465 exit(1);
1468 if (parse_host_port(iaddr, arg) < 0) {
1469 fprintf(stderr, "Could not parse VNC address\n");
1470 exit(1);
1473 iaddr->sin_port = htons(ntohs(iaddr->sin_port) + 5900);
1475 reuse_addr = 1;
1476 ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
1477 (const char *)&reuse_addr, sizeof(reuse_addr));
1478 if (ret == -1) {
1479 fprintf(stderr, "setsockopt() failed\n");
1480 exit(1);
1484 while (bind(vs->lsock, addr, addrlen) == -1) {
1485 if (find_unused && errno == EADDRINUSE) {
1486 iaddr->sin_port = htons(ntohs(iaddr->sin_port) + 1);
1487 continue;
1489 fprintf(stderr, "bind() failed\n");
1490 exit(1);
1493 if (listen(vs->lsock, 1) == -1) {
1494 fprintf(stderr, "listen() failed\n");
1495 exit(1);
1498 ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
1499 if (ret == -1) {
1500 exit(1);
1503 return ntohs(iaddr->sin_port);
1506 int vnc_start_viewer(int port)
1508 int pid, i, open_max;
1509 char s[16];
1511 sprintf(s, ":%d", port);
1513 switch (pid = fork()) {
1514 case -1:
1515 fprintf(stderr, "vncviewer failed fork\n");
1516 exit(1);
1518 case 0: /* child */
1519 open_max = sysconf(_SC_OPEN_MAX);
1520 for (i = 0; i < open_max; i++)
1521 if (i != STDIN_FILENO &&
1522 i != STDOUT_FILENO &&
1523 i != STDERR_FILENO)
1524 close(i);
1525 execlp("vncviewer", "vncviewer", s, NULL);
1526 fprintf(stderr, "vncviewer execlp failed\n");
1527 exit(1);
1529 default:
1530 return pid;
1534 unsigned int seed;
1536 static int make_challenge(unsigned char *random, int size)
1539 set_seed(&seed);
1540 get_random(size, random);
1542 return 0;
1545 static void set_seed(unsigned int *seedp)
1547 *seedp += (unsigned int)(time(NULL)+getpid()+getpid()*987654+rand());
1548 srand(*seedp);
1550 return;
1553 static void get_random(int len, unsigned char *buf)
1555 int i;
1557 for (i=0; i<len; i++)
1558 buf[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1560 return;