]>
git.proxmox.com Git - mirror_qemu.git/blob - vnc.c
2 * QEMU VNC display driver
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 #include "qemu_socket.h"
29 #define VNC_REFRESH_INTERVAL (1000 / 30)
31 #include "vnc_keysym.h"
41 typedef struct VncState VncState
;
43 typedef int VncReadEvent(VncState
*vs
, char *data
, size_t len
);
54 uint64_t dirty_row
[768];
61 kbd_layout_t
*kbd_layout
;
63 VncReadEvent
*read_handler
;
64 size_t read_handler_expect
;
68 1) Get the queue working for IO.
69 2) there is some weirdness when using the -S option (the screen is grey
70 and not totally invalidated
74 static void vnc_write(VncState
*vs
, const void *data
, size_t len
);
75 static void vnc_write_u32(VncState
*vs
, uint32_t value
);
76 static void vnc_write_s32(VncState
*vs
, int32_t value
);
77 static void vnc_write_u16(VncState
*vs
, uint16_t value
);
78 static void vnc_write_u8(VncState
*vs
, uint8_t value
);
79 static void vnc_flush(VncState
*vs
);
80 static void vnc_update_client(void *opaque
);
81 static void vnc_client_read(void *opaque
);
83 static void vnc_dpy_update(DisplayState
*ds
, int x
, int y
, int w
, int h
)
85 VncState
*vs
= ds
->opaque
;
91 for (i
= 0; i
< w
; i
+= 16)
92 vs
->dirty_row
[y
] |= (1ULL << ((x
+ i
) / 16));
95 static void vnc_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
,
100 vnc_write_u16(vs
, w
);
101 vnc_write_u16(vs
, h
);
103 vnc_write_s32(vs
, encoding
);
106 static void vnc_dpy_resize(DisplayState
*ds
, int w
, int h
)
108 VncState
*vs
= ds
->opaque
;
110 ds
->data
= realloc(ds
->data
, w
* h
* vs
->depth
);
111 vs
->old_data
= realloc(vs
->old_data
, w
* h
* vs
->depth
);
113 if (ds
->data
== NULL
|| vs
->old_data
== NULL
) {
114 fprintf(stderr
, "vnc: memory allocation failed\n");
118 ds
->depth
= vs
->depth
* 8;
121 ds
->linesize
= w
* vs
->depth
;
122 if (vs
->csock
!= -1 && vs
->has_resize
) {
123 vnc_write_u8(vs
, 0); /* msg id */
125 vnc_write_u16(vs
, 1); /* number of rects */
126 vnc_framebuffer_update(vs
, 0, 0, ds
->width
, ds
->height
, -223);
128 vs
->width
= ds
->width
;
129 vs
->height
= ds
->height
;
133 static void send_framebuffer_update_raw(VncState
*vs
, int x
, int y
, int w
, int h
)
138 vnc_framebuffer_update(vs
, x
, y
, w
, h
, 0);
140 row
= vs
->ds
->data
+ y
* vs
->ds
->linesize
+ x
* vs
->depth
;
141 for (i
= 0; i
< h
; i
++) {
142 vnc_write(vs
, row
, w
* vs
->depth
);
143 row
+= vs
->ds
->linesize
;
147 static void hextile_enc_cord(uint8_t *ptr
, int x
, int y
, int w
, int h
)
149 ptr
[0] = ((x
& 0x0F) << 4) | (y
& 0x0F);
150 ptr
[1] = (((w
- 1) & 0x0F) << 4) | ((h
- 1) & 0x0F);
154 #include "vnchextile.h"
158 #include "vnchextile.h"
162 #include "vnchextile.h"
165 static void send_framebuffer_update_hextile(VncState
*vs
, int x
, int y
, int w
, int h
)
169 uint32_t last_fg32
, last_bg32
;
170 uint16_t last_fg16
, last_bg16
;
171 uint8_t last_fg8
, last_bg8
;
173 vnc_framebuffer_update(vs
, x
, y
, w
, h
, 5);
176 for (j
= y
; j
< (y
+ h
); j
+= 16) {
177 for (i
= x
; i
< (x
+ w
); i
+= 16) {
180 send_hextile_tile_8(vs
, i
, j
, MIN(16, x
+ w
- i
), MIN(16, y
+ h
- j
),
181 &last_bg8
, &last_fg8
, &has_bg
, &has_fg
);
184 send_hextile_tile_16(vs
, i
, j
, MIN(16, x
+ w
- i
), MIN(16, y
+ h
- j
),
185 &last_bg16
, &last_fg16
, &has_bg
, &has_fg
);
188 send_hextile_tile_32(vs
, i
, j
, MIN(16, x
+ w
- i
), MIN(16, y
+ h
- j
),
189 &last_bg32
, &last_fg32
, &has_bg
, &has_fg
);
198 static void send_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
)
201 send_framebuffer_update_hextile(vs
, x
, y
, w
, h
);
203 send_framebuffer_update_raw(vs
, x
, y
, w
, h
);
206 static void vnc_copy(DisplayState
*ds
, int src_x
, int src_y
, int dst_x
, int dst_y
, int w
, int h
)
213 int pitch
= ds
->linesize
;
214 VncState
*vs
= ds
->opaque
;
216 vnc_update_client(vs
);
223 src
= (ds
->linesize
* (src_y
+ y
) + vs
->depth
* src_x
);
224 dst
= (ds
->linesize
* (dst_y
+ y
) + vs
->depth
* dst_x
);
226 src_row
= ds
->data
+ src
;
227 dst_row
= ds
->data
+ dst
;
228 old_row
= vs
->old_data
+ dst
;
230 for (y
= 0; y
< h
; y
++) {
231 memmove(old_row
, src_row
, w
* vs
->depth
);
232 memmove(dst_row
, src_row
, w
* vs
->depth
);
238 vnc_write_u8(vs
, 0); /* msg id */
240 vnc_write_u16(vs
, 1); /* number of rects */
241 vnc_framebuffer_update(vs
, dst_x
, dst_y
, w
, h
, 1);
242 vnc_write_u16(vs
, src_x
);
243 vnc_write_u16(vs
, src_y
);
247 static int find_dirty_height(VncState
*vs
, int y
, int last_x
, int x
)
251 for (h
= 1; h
< (vs
->height
- y
); h
++) {
253 if (!(vs
->dirty_row
[y
+ h
] & (1ULL << last_x
)))
255 for (tmp_x
= last_x
; tmp_x
< x
; tmp_x
++)
256 vs
->dirty_row
[y
+ h
] &= ~(1ULL << tmp_x
);
262 static void vnc_update_client(void *opaque
)
264 VncState
*vs
= opaque
;
266 if (vs
->need_update
&& vs
->csock
!= -1) {
275 width_mask
= (1ULL << (vs
->width
/ 16)) - 1;
277 if (vs
->width
== 1024)
278 width_mask
= ~(0ULL);
280 /* Walk through the dirty map and eliminate tiles that
281 really aren't dirty */
283 old_row
= vs
->old_data
;
285 for (y
= 0; y
< vs
->height
; y
++) {
286 if (vs
->dirty_row
[y
] & width_mask
) {
293 for (x
= 0; x
< vs
->ds
->width
; x
+= 16) {
294 if (memcmp(old_ptr
, ptr
, 16 * vs
->depth
) == 0) {
295 vs
->dirty_row
[y
] &= ~(1ULL << (x
/ 16));
298 memcpy(old_ptr
, ptr
, 16 * vs
->depth
);
301 ptr
+= 16 * vs
->depth
;
302 old_ptr
+= 16 * vs
->depth
;
306 row
+= vs
->ds
->linesize
;
307 old_row
+= vs
->ds
->linesize
;
311 qemu_mod_timer(vs
->timer
, qemu_get_clock(rt_clock
) + VNC_REFRESH_INTERVAL
);
315 /* Count rectangles */
317 vnc_write_u8(vs
, 0); /* msg id */
319 saved_offset
= vs
->output
.offset
;
320 vnc_write_u16(vs
, 0);
322 for (y
= 0; y
< vs
->height
; y
++) {
325 for (x
= 0; x
< vs
->width
/ 16; x
++) {
326 if (vs
->dirty_row
[y
] & (1ULL << x
)) {
330 vs
->dirty_row
[y
] &= ~(1ULL << x
);
333 int h
= find_dirty_height(vs
, y
, last_x
, x
);
334 send_framebuffer_update(vs
, last_x
* 16, y
, (x
- last_x
) * 16, h
);
341 int h
= find_dirty_height(vs
, y
, last_x
, x
);
342 send_framebuffer_update(vs
, last_x
* 16, y
, (x
- last_x
) * 16, h
);
346 vs
->output
.buffer
[saved_offset
] = (n_rectangles
>> 8) & 0xFF;
347 vs
->output
.buffer
[saved_offset
+ 1] = n_rectangles
& 0xFF;
351 qemu_mod_timer(vs
->timer
, qemu_get_clock(rt_clock
) + VNC_REFRESH_INTERVAL
);
354 static void vnc_timer_init(VncState
*vs
)
356 if (vs
->timer
== NULL
) {
357 vs
->timer
= qemu_new_timer(rt_clock
, vnc_update_client
, vs
);
358 qemu_mod_timer(vs
->timer
, qemu_get_clock(rt_clock
));
362 static void vnc_dpy_refresh(DisplayState
*ds
)
364 VncState
*vs
= ds
->opaque
;
369 static int vnc_listen_poll(void *opaque
)
371 VncState
*vs
= opaque
;
377 static void buffer_reserve(Buffer
*buffer
, size_t len
)
379 if ((buffer
->capacity
- buffer
->offset
) < len
) {
380 buffer
->capacity
+= (len
+ 1024);
381 buffer
->buffer
= realloc(buffer
->buffer
, buffer
->capacity
);
382 if (buffer
->buffer
== NULL
) {
383 fprintf(stderr
, "vnc: out of memory\n");
389 static int buffer_empty(Buffer
*buffer
)
391 return buffer
->offset
== 0;
394 static char *buffer_end(Buffer
*buffer
)
396 return buffer
->buffer
+ buffer
->offset
;
399 static void buffer_reset(Buffer
*buffer
)
404 static void buffer_append(Buffer
*buffer
, const void *data
, size_t len
)
406 memcpy(buffer
->buffer
+ buffer
->offset
, data
, len
);
407 buffer
->offset
+= len
;
410 static int vnc_client_io_error(VncState
*vs
, int ret
, int last_errno
)
412 if (ret
== 0 || ret
== -1) {
413 if (ret
== -1 && (last_errno
== EINTR
|| last_errno
== EAGAIN
))
416 qemu_set_fd_handler2(vs
->csock
, NULL
, NULL
, NULL
, NULL
);
417 closesocket(vs
->csock
);
419 buffer_reset(&vs
->input
);
420 buffer_reset(&vs
->output
);
427 static void vnc_client_error(VncState
*vs
)
429 vnc_client_io_error(vs
, -1, EINVAL
);
432 static void vnc_client_write(void *opaque
)
435 VncState
*vs
= opaque
;
437 ret
= send(vs
->csock
, vs
->output
.buffer
, vs
->output
.offset
, 0);
438 ret
= vnc_client_io_error(vs
, ret
, socket_error());
442 memmove(vs
->output
.buffer
, vs
->output
.buffer
+ ret
, (vs
->output
.offset
- ret
));
443 vs
->output
.offset
-= ret
;
445 if (vs
->output
.offset
== 0) {
446 qemu_set_fd_handler2(vs
->csock
, NULL
, vnc_client_read
, NULL
, vs
);
450 static void vnc_read_when(VncState
*vs
, VncReadEvent
*func
, size_t expecting
)
452 vs
->read_handler
= func
;
453 vs
->read_handler_expect
= expecting
;
456 static void vnc_client_read(void *opaque
)
458 VncState
*vs
= opaque
;
461 buffer_reserve(&vs
->input
, 4096);
463 ret
= recv(vs
->csock
, buffer_end(&vs
->input
), 4096, 0);
464 ret
= vnc_client_io_error(vs
, ret
, socket_error());
468 vs
->input
.offset
+= ret
;
470 while (vs
->read_handler
&& vs
->input
.offset
>= vs
->read_handler_expect
) {
471 size_t len
= vs
->read_handler_expect
;
474 ret
= vs
->read_handler(vs
, vs
->input
.buffer
, len
);
479 memmove(vs
->input
.buffer
, vs
->input
.buffer
+ len
, (vs
->input
.offset
- len
));
480 vs
->input
.offset
-= len
;
482 vs
->read_handler_expect
= ret
;
487 static void vnc_write(VncState
*vs
, const void *data
, size_t len
)
489 buffer_reserve(&vs
->output
, len
);
491 if (buffer_empty(&vs
->output
)) {
492 qemu_set_fd_handler2(vs
->csock
, NULL
, vnc_client_read
, vnc_client_write
, vs
);
495 buffer_append(&vs
->output
, data
, len
);
498 static void vnc_write_s32(VncState
*vs
, int32_t value
)
500 vnc_write_u32(vs
, *(uint32_t *)&value
);
503 static void vnc_write_u32(VncState
*vs
, uint32_t value
)
507 buf
[0] = (value
>> 24) & 0xFF;
508 buf
[1] = (value
>> 16) & 0xFF;
509 buf
[2] = (value
>> 8) & 0xFF;
510 buf
[3] = value
& 0xFF;
512 vnc_write(vs
, buf
, 4);
515 static void vnc_write_u16(VncState
*vs
, uint16_t value
)
519 buf
[0] = (value
>> 8) & 0xFF;
520 buf
[1] = value
& 0xFF;
522 vnc_write(vs
, buf
, 2);
525 static void vnc_write_u8(VncState
*vs
, uint8_t value
)
527 vnc_write(vs
, (char *)&value
, 1);
530 static void vnc_flush(VncState
*vs
)
532 if (vs
->output
.offset
)
533 vnc_client_write(vs
);
536 static uint8_t read_u8(char *data
, size_t offset
)
541 static uint16_t read_u16(char *data
, size_t offset
)
543 return ((data
[offset
] & 0xFF) << 8) | (data
[offset
+ 1] & 0xFF);
546 static int32_t read_s32(char *data
, size_t offset
)
548 return (int32_t)((data
[offset
] << 24) | (data
[offset
+ 1] << 16) |
549 (data
[offset
+ 2] << 8) | data
[offset
+ 3]);
552 static uint32_t read_u32(char *data
, size_t offset
)
554 return ((data
[offset
] << 24) | (data
[offset
+ 1] << 16) |
555 (data
[offset
+ 2] << 8) | data
[offset
+ 3]);
558 static void client_cut_text(VncState
*vs
, size_t len
, char *text
)
562 static void pointer_event(VncState
*vs
, int button_mask
, int x
, int y
)
567 if (button_mask
& 0x01)
568 buttons
|= MOUSE_EVENT_LBUTTON
;
569 if (button_mask
& 0x02)
570 buttons
|= MOUSE_EVENT_MBUTTON
;
571 if (button_mask
& 0x04)
572 buttons
|= MOUSE_EVENT_RBUTTON
;
573 if (button_mask
& 0x08)
575 if (button_mask
& 0x10)
578 if (kbd_mouse_is_absolute()) {
579 kbd_mouse_event(x
* 0x7FFF / vs
->ds
->width
,
580 y
* 0x7FFF / vs
->ds
->height
,
583 static int last_x
= -1;
584 static int last_y
= -1;
587 kbd_mouse_event(x
- last_x
, y
- last_y
, dz
, buttons
);
594 static void do_key_event(VncState
*vs
, int down
, uint32_t sym
)
598 keycode
= keysym2scancode(vs
->kbd_layout
, sym
& 0xFFFF);
601 kbd_put_keycode(0xe0);
603 kbd_put_keycode(keycode
& 0x7f);
605 kbd_put_keycode(keycode
| 0x80);
608 static void key_event(VncState
*vs
, int down
, uint32_t sym
)
610 if (sym
>= 'A' && sym
<= 'Z')
611 sym
= sym
- 'A' + 'a';
612 do_key_event(vs
, down
, sym
);
615 static void framebuffer_update_request(VncState
*vs
, int incremental
,
616 int x_position
, int y_position
,
622 char *old_row
= vs
->old_data
+ y_position
* vs
->ds
->linesize
;
624 for (i
= 0; i
< h
; i
++) {
625 vs
->dirty_row
[y_position
+ i
] = (1ULL << (vs
->ds
->width
/ 16)) - 1;
626 if (vs
->ds
->width
== 1024) {
627 vs
->dirty_row
[y_position
+ i
] = ~(0ULL);
629 memset(old_row
, 42, vs
->ds
->width
* vs
->depth
);
630 old_row
+= vs
->ds
->linesize
;
635 static void set_encodings(VncState
*vs
, int32_t *encodings
, size_t n_encodings
)
641 vs
->ds
->dpy_copy
= NULL
;
643 for (i
= n_encodings
- 1; i
>= 0; i
--) {
644 switch (encodings
[i
]) {
648 case 1: /* CopyRect */
649 vs
->ds
->dpy_copy
= vnc_copy
;
651 case 5: /* Hextile */
654 case -223: /* DesktopResize */
663 static void set_pixel_format(VncState
*vs
,
664 int bits_per_pixel
, int depth
,
665 int big_endian_flag
, int true_color_flag
,
666 int red_max
, int green_max
, int blue_max
,
667 int red_shift
, int green_shift
, int blue_shift
)
669 switch (bits_per_pixel
) {
681 vnc_client_error(vs
);
685 if (!true_color_flag
)
686 vnc_client_error(vs
);
688 vnc_dpy_resize(vs
->ds
, vs
->ds
->width
, vs
->ds
->height
);
689 memset(vs
->dirty_row
, 0xFF, sizeof(vs
->dirty_row
));
690 memset(vs
->old_data
, 42, vs
->ds
->linesize
* vs
->ds
->height
);
696 static int protocol_client_msg(VncState
*vs
, char *data
, size_t len
)
706 set_pixel_format(vs
, read_u8(data
, 4), read_u8(data
, 5),
707 read_u8(data
, 6), read_u8(data
, 7),
708 read_u16(data
, 8), read_u16(data
, 10),
709 read_u16(data
, 12), read_u8(data
, 14),
710 read_u8(data
, 15), read_u8(data
, 16));
717 return 4 + (read_u16(data
, 2) * 4);
719 limit
= read_u16(data
, 2);
720 for (i
= 0; i
< limit
; i
++) {
721 int32_t val
= read_s32(data
, 4 + (i
* 4));
722 memcpy(data
+ 4 + (i
* 4), &val
, sizeof(val
));
725 set_encodings(vs
, (int32_t *)(data
+ 4), limit
);
731 framebuffer_update_request(vs
,
732 read_u8(data
, 1), read_u16(data
, 2), read_u16(data
, 4),
733 read_u16(data
, 6), read_u16(data
, 8));
739 key_event(vs
, read_u8(data
, 1), read_u32(data
, 4));
745 pointer_event(vs
, read_u8(data
, 1), read_u16(data
, 2), read_u16(data
, 4));
752 return 8 + read_u32(data
, 4);
754 client_cut_text(vs
, read_u32(data
, 4), data
+ 8);
757 printf("Msg: %d\n", data
[0]);
758 vnc_client_error(vs
);
762 vnc_read_when(vs
, protocol_client_msg
, 1);
766 static int protocol_client_init(VncState
*vs
, char *data
, size_t len
)
768 char pad
[3] = { 0, 0, 0 };
770 vs
->width
= vs
->ds
->width
;
771 vs
->height
= vs
->ds
->height
;
772 vnc_write_u16(vs
, vs
->ds
->width
);
773 vnc_write_u16(vs
, vs
->ds
->height
);
775 vnc_write_u8(vs
, vs
->depth
* 8); /* bits-per-pixel */
776 vnc_write_u8(vs
, vs
->depth
* 8); /* depth */
777 vnc_write_u8(vs
, 0); /* big-endian-flag */
778 vnc_write_u8(vs
, 1); /* true-color-flag */
779 if (vs
->depth
== 4) {
780 vnc_write_u16(vs
, 0xFF); /* red-max */
781 vnc_write_u16(vs
, 0xFF); /* green-max */
782 vnc_write_u16(vs
, 0xFF); /* blue-max */
783 vnc_write_u8(vs
, 16); /* red-shift */
784 vnc_write_u8(vs
, 8); /* green-shift */
785 vnc_write_u8(vs
, 0); /* blue-shift */
786 } else if (vs
->depth
== 2) {
787 vnc_write_u16(vs
, 31); /* red-max */
788 vnc_write_u16(vs
, 63); /* green-max */
789 vnc_write_u16(vs
, 31); /* blue-max */
790 vnc_write_u8(vs
, 11); /* red-shift */
791 vnc_write_u8(vs
, 5); /* green-shift */
792 vnc_write_u8(vs
, 0); /* blue-shift */
793 } else if (vs
->depth
== 1) {
794 vnc_write_u16(vs
, 3); /* red-max */
795 vnc_write_u16(vs
, 7); /* green-max */
796 vnc_write_u16(vs
, 3); /* blue-max */
797 vnc_write_u8(vs
, 5); /* red-shift */
798 vnc_write_u8(vs
, 2); /* green-shift */
799 vnc_write_u8(vs
, 0); /* blue-shift */
802 vnc_write(vs
, pad
, 3); /* padding */
804 vnc_write_u32(vs
, 4);
805 vnc_write(vs
, "QEMU", 4);
808 vnc_read_when(vs
, protocol_client_msg
, 1);
813 static int protocol_version(VncState
*vs
, char *version
, size_t len
)
818 memcpy(local
, version
, 12);
821 if (sscanf(local
, "RFB %03d.%03d\n", &maj
, &min
) != 2) {
822 vnc_client_error(vs
);
826 vnc_write_u32(vs
, 1); /* None */
829 vnc_read_when(vs
, protocol_client_init
, 1);
834 static void vnc_listen_read(void *opaque
)
836 VncState
*vs
= opaque
;
837 struct sockaddr_in addr
;
838 socklen_t addrlen
= sizeof(addr
);
840 vs
->csock
= accept(vs
->lsock
, (struct sockaddr
*)&addr
, &addrlen
);
841 if (vs
->csock
!= -1) {
842 socket_set_nonblock(vs
->csock
);
843 qemu_set_fd_handler2(vs
->csock
, NULL
, vnc_client_read
, NULL
, opaque
);
844 vnc_write(vs
, "RFB 003.003\n", 12);
846 vnc_read_when(vs
, protocol_version
, 12);
847 memset(vs
->old_data
, 0, vs
->ds
->linesize
* vs
->ds
->height
);
848 memset(vs
->dirty_row
, 0xFF, sizeof(vs
->dirty_row
));
851 vs
->ds
->dpy_copy
= NULL
;
855 void vnc_display_init(DisplayState
*ds
, int display
)
857 struct sockaddr_in addr
;
861 vs
= qemu_mallocz(sizeof(VncState
));
873 if (!keyboard_layout
)
874 keyboard_layout
= "en-us";
876 vs
->kbd_layout
= init_keyboard_layout(keyboard_layout
);
880 vs
->lsock
= socket(PF_INET
, SOCK_STREAM
, 0);
881 if (vs
->lsock
== -1) {
882 fprintf(stderr
, "Could not create socket\n");
886 addr
.sin_family
= AF_INET
;
887 addr
.sin_port
= htons(5900 + display
);
888 memset(&addr
.sin_addr
, 0, sizeof(addr
.sin_addr
));
891 ret
= setsockopt(vs
->lsock
, SOL_SOCKET
, SO_REUSEADDR
,
892 (const char *)&reuse_addr
, sizeof(reuse_addr
));
894 fprintf(stderr
, "setsockopt() failed\n");
898 if (bind(vs
->lsock
, (struct sockaddr
*)&addr
, sizeof(addr
)) == -1) {
899 fprintf(stderr
, "bind() failed\n");
903 if (listen(vs
->lsock
, 1) == -1) {
904 fprintf(stderr
, "listen() failed\n");
908 ret
= qemu_set_fd_handler2(vs
->lsock
, vnc_listen_poll
, vnc_listen_read
, NULL
, vs
);
914 vs
->ds
->dpy_update
= vnc_dpy_update
;
915 vs
->ds
->dpy_resize
= vnc_dpy_resize
;
916 vs
->ds
->dpy_refresh
= vnc_dpy_refresh
;
918 memset(vs
->dirty_row
, 0xFF, sizeof(vs
->dirty_row
));
920 vnc_dpy_resize(vs
->ds
, 640, 400);