Commit 753b4053311ff1437d99726970b1e7e6bf38249b
1 parent
880fec5d
Support multiple VNC clients (Brian Kress)
Change structure associated with a display from VncState to a new structure VncDisplay. Remove client specific fields from VncDisplay. Remove display specific fields from VncState. Maintain a linked list of VncStates per VncDisplay structure, update as necessary. When updates/resizes/copies come in from the hardware, dispatch to all clients. Signed-off-by: Brian Kress <kressb@moose.net> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6621 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
172 additions
and
135 deletions
vnc.c
| @@ -90,12 +90,35 @@ typedef void VncSendHextileTile(VncState *vs, | @@ -90,12 +90,35 @@ typedef void VncSendHextileTile(VncState *vs, | ||
| 90 | 90 | ||
| 91 | #define VNC_AUTH_CHALLENGE_SIZE 16 | 91 | #define VNC_AUTH_CHALLENGE_SIZE 16 |
| 92 | 92 | ||
| 93 | +typedef struct VncDisplay VncDisplay; | ||
| 94 | + | ||
| 95 | +struct VncDisplay | ||
| 96 | +{ | ||
| 97 | + int lsock; | ||
| 98 | + DisplayState *ds; | ||
| 99 | + VncState *clients; | ||
| 100 | + kbd_layout_t *kbd_layout; | ||
| 101 | + | ||
| 102 | + char *display; | ||
| 103 | + char *password; | ||
| 104 | + int auth; | ||
| 105 | +#ifdef CONFIG_VNC_TLS | ||
| 106 | + int subauth; | ||
| 107 | + int x509verify; | ||
| 108 | + | ||
| 109 | + char *x509cacert; | ||
| 110 | + char *x509cacrl; | ||
| 111 | + char *x509cert; | ||
| 112 | + char *x509key; | ||
| 113 | +#endif | ||
| 114 | +}; | ||
| 115 | + | ||
| 93 | struct VncState | 116 | struct VncState |
| 94 | { | 117 | { |
| 95 | QEMUTimer *timer; | 118 | QEMUTimer *timer; |
| 96 | - int lsock; | ||
| 97 | int csock; | 119 | int csock; |
| 98 | DisplayState *ds; | 120 | DisplayState *ds; |
| 121 | + VncDisplay *vd; | ||
| 99 | int need_update; | 122 | int need_update; |
| 100 | uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS]; | 123 | uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS]; |
| 101 | char *old_data; | 124 | char *old_data; |
| @@ -111,18 +134,6 @@ struct VncState | @@ -111,18 +134,6 @@ struct VncState | ||
| 111 | int major; | 134 | int major; |
| 112 | int minor; | 135 | int minor; |
| 113 | 136 | ||
| 114 | - char *display; | ||
| 115 | - char *password; | ||
| 116 | - int auth; | ||
| 117 | -#ifdef CONFIG_VNC_TLS | ||
| 118 | - int subauth; | ||
| 119 | - int x509verify; | ||
| 120 | - | ||
| 121 | - char *x509cacert; | ||
| 122 | - char *x509cacrl; | ||
| 123 | - char *x509cert; | ||
| 124 | - char *x509key; | ||
| 125 | -#endif | ||
| 126 | char challenge[VNC_AUTH_CHALLENGE_SIZE]; | 137 | char challenge[VNC_AUTH_CHALLENGE_SIZE]; |
| 127 | 138 | ||
| 128 | #ifdef CONFIG_VNC_TLS | 139 | #ifdef CONFIG_VNC_TLS |
| @@ -132,7 +143,6 @@ struct VncState | @@ -132,7 +143,6 @@ struct VncState | ||
| 132 | 143 | ||
| 133 | Buffer output; | 144 | Buffer output; |
| 134 | Buffer input; | 145 | Buffer input; |
| 135 | - kbd_layout_t *kbd_layout; | ||
| 136 | /* current output mode information */ | 146 | /* current output mode information */ |
| 137 | VncWritePixels *write_pixels; | 147 | VncWritePixels *write_pixels; |
| 138 | VncSendHextileTile *send_hextile_tile; | 148 | VncSendHextileTile *send_hextile_tile; |
| @@ -149,21 +159,23 @@ struct VncState | @@ -149,21 +159,23 @@ struct VncState | ||
| 149 | Buffer zlib; | 159 | Buffer zlib; |
| 150 | Buffer zlib_tmp; | 160 | Buffer zlib_tmp; |
| 151 | z_stream zlib_stream[4]; | 161 | z_stream zlib_stream[4]; |
| 162 | + | ||
| 163 | + VncState *next; | ||
| 152 | }; | 164 | }; |
| 153 | 165 | ||
| 154 | -static VncState *vnc_state; /* needed for info vnc */ | 166 | +static VncDisplay *vnc_display; /* needed for info vnc */ |
| 155 | static DisplayChangeListener *dcl; | 167 | static DisplayChangeListener *dcl; |
| 156 | 168 | ||
| 157 | void do_info_vnc(void) | 169 | void do_info_vnc(void) |
| 158 | { | 170 | { |
| 159 | - if (vnc_state == NULL || vnc_state->display == NULL) | 171 | + if (vnc_display == NULL || vnc_display->display == NULL) |
| 160 | term_printf("VNC server disabled\n"); | 172 | term_printf("VNC server disabled\n"); |
| 161 | else { | 173 | else { |
| 162 | term_printf("VNC server active on: "); | 174 | term_printf("VNC server active on: "); |
| 163 | - term_print_filename(vnc_state->display); | 175 | + term_print_filename(vnc_display->display); |
| 164 | term_printf("\n"); | 176 | term_printf("\n"); |
| 165 | 177 | ||
| 166 | - if (vnc_state->csock == -1) | 178 | + if (vnc_display->clients == NULL) |
| 167 | term_printf("No client connected\n"); | 179 | term_printf("No client connected\n"); |
| 168 | else | 180 | else |
| 169 | term_printf("Client connected\n"); | 181 | term_printf("Client connected\n"); |
| @@ -190,7 +202,7 @@ static void vnc_flush(VncState *vs); | @@ -190,7 +202,7 @@ static void vnc_flush(VncState *vs); | ||
| 190 | static void vnc_update_client(void *opaque); | 202 | static void vnc_update_client(void *opaque); |
| 191 | static void vnc_client_read(void *opaque); | 203 | static void vnc_client_read(void *opaque); |
| 192 | 204 | ||
| 193 | -static void vnc_colordepth(DisplayState *ds); | 205 | +static void vnc_colordepth(VncState *vs); |
| 194 | 206 | ||
| 195 | static inline void vnc_set_bit(uint32_t *d, int k) | 207 | static inline void vnc_set_bit(uint32_t *d, int k) |
| 196 | { | 208 | { |
| @@ -233,9 +245,8 @@ static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2, | @@ -233,9 +245,8 @@ static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2, | ||
| 233 | return 0; | 245 | return 0; |
| 234 | } | 246 | } |
| 235 | 247 | ||
| 236 | -static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) | 248 | +static void vnc_update(VncState *vs, int x, int y, int w, int h) |
| 237 | { | 249 | { |
| 238 | - VncState *vs = ds->opaque; | ||
| 239 | int i; | 250 | int i; |
| 240 | 251 | ||
| 241 | h += y; | 252 | h += y; |
| @@ -257,6 +268,16 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) | @@ -257,6 +268,16 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) | ||
| 257 | vnc_set_bit(vs->dirty_row[y], (x + i) / 16); | 268 | vnc_set_bit(vs->dirty_row[y], (x + i) / 16); |
| 258 | } | 269 | } |
| 259 | 270 | ||
| 271 | +static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) | ||
| 272 | +{ | ||
| 273 | + VncDisplay *vd = ds->opaque; | ||
| 274 | + VncState *vs = vd->clients; | ||
| 275 | + while (vs != NULL) { | ||
| 276 | + vnc_update(vs, x, y, w, h); | ||
| 277 | + vs = vs->next; | ||
| 278 | + } | ||
| 279 | +} | ||
| 280 | + | ||
| 260 | static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, | 281 | static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, |
| 261 | int32_t encoding) | 282 | int32_t encoding) |
| 262 | { | 283 | { |
| @@ -301,10 +322,11 @@ static void buffer_append(Buffer *buffer, const void *data, size_t len) | @@ -301,10 +322,11 @@ static void buffer_append(Buffer *buffer, const void *data, size_t len) | ||
| 301 | buffer->offset += len; | 322 | buffer->offset += len; |
| 302 | } | 323 | } |
| 303 | 324 | ||
| 304 | -static void vnc_dpy_resize(DisplayState *ds) | 325 | +static void vnc_resize(VncState *vs) |
| 305 | { | 326 | { |
| 327 | + DisplayState *ds = vs->ds; | ||
| 328 | + | ||
| 306 | int size_changed; | 329 | int size_changed; |
| 307 | - VncState *vs = ds->opaque; | ||
| 308 | 330 | ||
| 309 | vs->old_data = qemu_realloc(vs->old_data, ds_get_linesize(ds) * ds_get_height(ds)); | 331 | vs->old_data = qemu_realloc(vs->old_data, ds_get_linesize(ds) * ds_get_height(ds)); |
| 310 | 332 | ||
| @@ -315,7 +337,7 @@ static void vnc_dpy_resize(DisplayState *ds) | @@ -315,7 +337,7 @@ static void vnc_dpy_resize(DisplayState *ds) | ||
| 315 | 337 | ||
| 316 | if (ds_get_bytes_per_pixel(ds) != vs->serverds.pf.bytes_per_pixel) | 338 | if (ds_get_bytes_per_pixel(ds) != vs->serverds.pf.bytes_per_pixel) |
| 317 | console_color_init(ds); | 339 | console_color_init(ds); |
| 318 | - vnc_colordepth(ds); | 340 | + vnc_colordepth(vs); |
| 319 | size_changed = ds_get_width(ds) != vs->serverds.width || | 341 | size_changed = ds_get_width(ds) != vs->serverds.width || |
| 320 | ds_get_height(ds) != vs->serverds.height; | 342 | ds_get_height(ds) != vs->serverds.height; |
| 321 | vs->serverds = *(ds->surface); | 343 | vs->serverds = *(ds->surface); |
| @@ -334,6 +356,16 @@ static void vnc_dpy_resize(DisplayState *ds) | @@ -334,6 +356,16 @@ static void vnc_dpy_resize(DisplayState *ds) | ||
| 334 | memset(vs->old_data, 42, ds_get_linesize(vs->ds) * ds_get_height(vs->ds)); | 356 | memset(vs->old_data, 42, ds_get_linesize(vs->ds) * ds_get_height(vs->ds)); |
| 335 | } | 357 | } |
| 336 | 358 | ||
| 359 | +static void vnc_dpy_resize(DisplayState *ds) | ||
| 360 | +{ | ||
| 361 | + VncDisplay *vd = ds->opaque; | ||
| 362 | + VncState *vs = vd->clients; | ||
| 363 | + while (vs != NULL) { | ||
| 364 | + vnc_resize(vs); | ||
| 365 | + vs = vs->next; | ||
| 366 | + } | ||
| 367 | +} | ||
| 368 | + | ||
| 337 | /* fastest code */ | 369 | /* fastest code */ |
| 338 | static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size) | 370 | static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size) |
| 339 | { | 371 | { |
| @@ -599,10 +631,8 @@ static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h) | @@ -599,10 +631,8 @@ static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h) | ||
| 599 | } | 631 | } |
| 600 | } | 632 | } |
| 601 | 633 | ||
| 602 | -static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) | 634 | +static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h) |
| 603 | { | 635 | { |
| 604 | - VncState *vs = ds->opaque; | ||
| 605 | - | ||
| 606 | vnc_update_client(vs); | 636 | vnc_update_client(vs); |
| 607 | 637 | ||
| 608 | vnc_write_u8(vs, 0); /* msg id */ | 638 | vnc_write_u8(vs, 0); /* msg id */ |
| @@ -614,6 +644,19 @@ static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_ | @@ -614,6 +644,19 @@ static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_ | ||
| 614 | vnc_flush(vs); | 644 | vnc_flush(vs); |
| 615 | } | 645 | } |
| 616 | 646 | ||
| 647 | +static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) | ||
| 648 | +{ | ||
| 649 | + VncDisplay *vd = ds->opaque; | ||
| 650 | + VncState *vs = vd->clients; | ||
| 651 | + while (vs != NULL) { | ||
| 652 | + if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) | ||
| 653 | + vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h); | ||
| 654 | + else /* TODO */ | ||
| 655 | + vnc_update(vs, dst_x, dst_y, w, h); | ||
| 656 | + vs = vs->next; | ||
| 657 | + } | ||
| 658 | +} | ||
| 659 | + | ||
| 617 | static int find_dirty_height(VncState *vs, int y, int last_x, int x) | 660 | static int find_dirty_height(VncState *vs, int y, int last_x, int x) |
| 618 | { | 661 | { |
| 619 | int h; | 662 | int h; |
| @@ -632,7 +675,6 @@ static int find_dirty_height(VncState *vs, int y, int last_x, int x) | @@ -632,7 +675,6 @@ static int find_dirty_height(VncState *vs, int y, int last_x, int x) | ||
| 632 | static void vnc_update_client(void *opaque) | 675 | static void vnc_update_client(void *opaque) |
| 633 | { | 676 | { |
| 634 | VncState *vs = opaque; | 677 | VncState *vs = opaque; |
| 635 | - | ||
| 636 | if (vs->need_update && vs->csock != -1) { | 678 | if (vs->need_update && vs->csock != -1) { |
| 637 | int y; | 679 | int y; |
| 638 | uint8_t *row; | 680 | uint8_t *row; |
| @@ -725,14 +767,6 @@ static void vnc_update_client(void *opaque) | @@ -725,14 +767,6 @@ static void vnc_update_client(void *opaque) | ||
| 725 | 767 | ||
| 726 | } | 768 | } |
| 727 | 769 | ||
| 728 | -static int vnc_listen_poll(void *opaque) | ||
| 729 | -{ | ||
| 730 | - VncState *vs = opaque; | ||
| 731 | - if (vs->csock == -1) | ||
| 732 | - return 1; | ||
| 733 | - return 0; | ||
| 734 | -} | ||
| 735 | - | ||
| 736 | /* audio */ | 770 | /* audio */ |
| 737 | static void audio_capture_notify(void *opaque, audcnotification_e cmd) | 771 | static void audio_capture_notify(void *opaque, audcnotification_e cmd) |
| 738 | { | 772 | { |
| @@ -817,19 +851,35 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno) | @@ -817,19 +851,35 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno) | ||
| 817 | VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0); | 851 | VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0); |
| 818 | qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); | 852 | qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); |
| 819 | closesocket(vs->csock); | 853 | closesocket(vs->csock); |
| 820 | - vs->csock = -1; | ||
| 821 | - dcl->idle = 1; | ||
| 822 | - buffer_reset(&vs->input); | ||
| 823 | - buffer_reset(&vs->output); | ||
| 824 | - vs->need_update = 0; | 854 | + qemu_del_timer(vs->timer); |
| 855 | + qemu_free_timer(vs->timer); | ||
| 856 | + if (vs->input.buffer) qemu_free(vs->input.buffer); | ||
| 857 | + if (vs->output.buffer) qemu_free(vs->output.buffer); | ||
| 825 | #ifdef CONFIG_VNC_TLS | 858 | #ifdef CONFIG_VNC_TLS |
| 826 | if (vs->tls_session) { | 859 | if (vs->tls_session) { |
| 827 | gnutls_deinit(vs->tls_session); | 860 | gnutls_deinit(vs->tls_session); |
| 828 | vs->tls_session = NULL; | 861 | vs->tls_session = NULL; |
| 829 | } | 862 | } |
| 830 | - vs->wiremode = VNC_WIREMODE_CLEAR; | ||
| 831 | #endif /* CONFIG_VNC_TLS */ | 863 | #endif /* CONFIG_VNC_TLS */ |
| 832 | audio_del(vs); | 864 | audio_del(vs); |
| 865 | + | ||
| 866 | + VncState *p, *parent = NULL; | ||
| 867 | + for (p = vs->vd->clients; p != NULL; p = p->next) { | ||
| 868 | + if (p == vs) { | ||
| 869 | + if (parent) | ||
| 870 | + parent->next = p->next; | ||
| 871 | + else | ||
| 872 | + vs->vd->clients = p->next; | ||
| 873 | + break; | ||
| 874 | + } | ||
| 875 | + parent = p; | ||
| 876 | + } | ||
| 877 | + if (!vs->vd->clients) | ||
| 878 | + dcl->idle = 1; | ||
| 879 | + | ||
| 880 | + qemu_free(vs->old_data); | ||
| 881 | + qemu_free(vs); | ||
| 882 | + | ||
| 833 | return 0; | 883 | return 0; |
| 834 | } | 884 | } |
| 835 | return ret; | 885 | return ret; |
| @@ -1095,8 +1145,8 @@ static void reset_keys(VncState *vs) | @@ -1095,8 +1145,8 @@ static void reset_keys(VncState *vs) | ||
| 1095 | 1145 | ||
| 1096 | static void press_key(VncState *vs, int keysym) | 1146 | static void press_key(VncState *vs, int keysym) |
| 1097 | { | 1147 | { |
| 1098 | - kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f); | ||
| 1099 | - kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80); | 1148 | + kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) & 0x7f); |
| 1149 | + kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) | 0x80); | ||
| 1100 | } | 1150 | } |
| 1101 | 1151 | ||
| 1102 | static void do_key_event(VncState *vs, int down, int keycode, int sym) | 1152 | static void do_key_event(VncState *vs, int down, int keycode, int sym) |
| @@ -1129,12 +1179,12 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym) | @@ -1129,12 +1179,12 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym) | ||
| 1129 | break; | 1179 | break; |
| 1130 | } | 1180 | } |
| 1131 | 1181 | ||
| 1132 | - if (keycode_is_keypad(vs->kbd_layout, keycode)) { | 1182 | + if (keycode_is_keypad(vs->vd->kbd_layout, keycode)) { |
| 1133 | /* If the numlock state needs to change then simulate an additional | 1183 | /* If the numlock state needs to change then simulate an additional |
| 1134 | keypress before sending this one. This will happen if the user | 1184 | keypress before sending this one. This will happen if the user |
| 1135 | toggles numlock away from the VNC window. | 1185 | toggles numlock away from the VNC window. |
| 1136 | */ | 1186 | */ |
| 1137 | - if (keysym_is_numlock(vs->kbd_layout, sym & 0xFFFF)) { | 1187 | + if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) { |
| 1138 | if (!vs->modifiers_state[0x45]) { | 1188 | if (!vs->modifiers_state[0x45]) { |
| 1139 | vs->modifiers_state[0x45] = 1; | 1189 | vs->modifiers_state[0x45] = 1; |
| 1140 | press_key(vs, 0xff7f); | 1190 | press_key(vs, 0xff7f); |
| @@ -1207,7 +1257,7 @@ static void key_event(VncState *vs, int down, uint32_t sym) | @@ -1207,7 +1257,7 @@ static void key_event(VncState *vs, int down, uint32_t sym) | ||
| 1207 | if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) | 1257 | if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) |
| 1208 | sym = sym - 'A' + 'a'; | 1258 | sym = sym - 'A' + 'a'; |
| 1209 | 1259 | ||
| 1210 | - keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF); | 1260 | + keycode = keysym2scancode(vs->vd->kbd_layout, sym & 0xFFFF); |
| 1211 | do_key_event(vs, down, keycode, sym); | 1261 | do_key_event(vs, down, keycode, sym); |
| 1212 | } | 1262 | } |
| 1213 | 1263 | ||
| @@ -1279,7 +1329,6 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) | @@ -1279,7 +1329,6 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) | ||
| 1279 | vs->tight_compression = 9; | 1329 | vs->tight_compression = 9; |
| 1280 | vs->tight_quality = 9; | 1330 | vs->tight_quality = 9; |
| 1281 | vs->absolute = -1; | 1331 | vs->absolute = -1; |
| 1282 | - dcl->dpy_copy = NULL; | ||
| 1283 | 1332 | ||
| 1284 | for (i = n_encodings - 1; i >= 0; i--) { | 1333 | for (i = n_encodings - 1; i >= 0; i--) { |
| 1285 | enc = encodings[i]; | 1334 | enc = encodings[i]; |
| @@ -1288,7 +1337,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) | @@ -1288,7 +1337,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) | ||
| 1288 | vs->vnc_encoding = enc; | 1337 | vs->vnc_encoding = enc; |
| 1289 | break; | 1338 | break; |
| 1290 | case VNC_ENCODING_COPYRECT: | 1339 | case VNC_ENCODING_COPYRECT: |
| 1291 | - dcl->dpy_copy = vnc_copy; | 1340 | + vs->features |= VNC_FEATURE_COPYRECT_MASK; |
| 1292 | break; | 1341 | break; |
| 1293 | case VNC_ENCODING_HEXTILE: | 1342 | case VNC_ENCODING_HEXTILE: |
| 1294 | vs->features |= VNC_FEATURE_HEXTILE_MASK; | 1343 | vs->features |= VNC_FEATURE_HEXTILE_MASK; |
| @@ -1432,17 +1481,15 @@ static void vnc_dpy_setdata(DisplayState *ds) | @@ -1432,17 +1481,15 @@ static void vnc_dpy_setdata(DisplayState *ds) | ||
| 1432 | /* We don't have to do anything */ | 1481 | /* We don't have to do anything */ |
| 1433 | } | 1482 | } |
| 1434 | 1483 | ||
| 1435 | -static void vnc_colordepth(DisplayState *ds) | 1484 | +static void vnc_colordepth(VncState *vs) |
| 1436 | { | 1485 | { |
| 1437 | - struct VncState *vs = ds->opaque; | ||
| 1438 | - | ||
| 1439 | - if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_WMVI)) { | 1486 | + if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) { |
| 1440 | /* Sending a WMVi message to notify the client*/ | 1487 | /* Sending a WMVi message to notify the client*/ |
| 1441 | vnc_write_u8(vs, 0); /* msg id */ | 1488 | vnc_write_u8(vs, 0); /* msg id */ |
| 1442 | vnc_write_u8(vs, 0); | 1489 | vnc_write_u8(vs, 0); |
| 1443 | vnc_write_u16(vs, 1); /* number of rects */ | 1490 | vnc_write_u16(vs, 1); /* number of rects */ |
| 1444 | - vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), | ||
| 1445 | - VNC_ENCODING_WMVi); | 1491 | + vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), |
| 1492 | + ds_get_height(vs->ds), VNC_ENCODING_WMVi); | ||
| 1446 | pixel_format_message(vs); | 1493 | pixel_format_message(vs); |
| 1447 | vnc_flush(vs); | 1494 | vnc_flush(vs); |
| 1448 | } else { | 1495 | } else { |
| @@ -1626,7 +1673,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len) | @@ -1626,7 +1673,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len) | ||
| 1626 | int i, j, pwlen; | 1673 | int i, j, pwlen; |
| 1627 | unsigned char key[8]; | 1674 | unsigned char key[8]; |
| 1628 | 1675 | ||
| 1629 | - if (!vs->password || !vs->password[0]) { | 1676 | + if (!vs->vd->password || !vs->vd->password[0]) { |
| 1630 | VNC_DEBUG("No password configured on server"); | 1677 | VNC_DEBUG("No password configured on server"); |
| 1631 | vnc_write_u32(vs, 1); /* Reject auth */ | 1678 | vnc_write_u32(vs, 1); /* Reject auth */ |
| 1632 | if (vs->minor >= 8) { | 1679 | if (vs->minor >= 8) { |
| @@ -1642,9 +1689,9 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len) | @@ -1642,9 +1689,9 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len) | ||
| 1642 | memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE); | 1689 | memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE); |
| 1643 | 1690 | ||
| 1644 | /* Calculate the expected challenge response */ | 1691 | /* Calculate the expected challenge response */ |
| 1645 | - pwlen = strlen(vs->password); | 1692 | + pwlen = strlen(vs->vd->password); |
| 1646 | for (i=0; i<sizeof(key); i++) | 1693 | for (i=0; i<sizeof(key); i++) |
| 1647 | - key[i] = i<pwlen ? vs->password[i] : 0; | 1694 | + key[i] = i<pwlen ? vs->vd->password[i] : 0; |
| 1648 | deskey(key, EN0); | 1695 | deskey(key, EN0); |
| 1649 | for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8) | 1696 | for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8) |
| 1650 | des(response+j, response+j); | 1697 | des(response+j, response+j); |
| @@ -1733,15 +1780,15 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v | @@ -1733,15 +1780,15 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v | ||
| 1733 | gnutls_certificate_credentials_t x509_cred; | 1780 | gnutls_certificate_credentials_t x509_cred; |
| 1734 | int ret; | 1781 | int ret; |
| 1735 | 1782 | ||
| 1736 | - if (!vs->x509cacert) { | 1783 | + if (!vs->vd->x509cacert) { |
| 1737 | VNC_DEBUG("No CA x509 certificate specified\n"); | 1784 | VNC_DEBUG("No CA x509 certificate specified\n"); |
| 1738 | return NULL; | 1785 | return NULL; |
| 1739 | } | 1786 | } |
| 1740 | - if (!vs->x509cert) { | 1787 | + if (!vs->vd->x509cert) { |
| 1741 | VNC_DEBUG("No server x509 certificate specified\n"); | 1788 | VNC_DEBUG("No server x509 certificate specified\n"); |
| 1742 | return NULL; | 1789 | return NULL; |
| 1743 | } | 1790 | } |
| 1744 | - if (!vs->x509key) { | 1791 | + if (!vs->vd->x509key) { |
| 1745 | VNC_DEBUG("No server private key specified\n"); | 1792 | VNC_DEBUG("No server private key specified\n"); |
| 1746 | return NULL; | 1793 | return NULL; |
| 1747 | } | 1794 | } |
| @@ -1751,7 +1798,7 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v | @@ -1751,7 +1798,7 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v | ||
| 1751 | return NULL; | 1798 | return NULL; |
| 1752 | } | 1799 | } |
| 1753 | if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, | 1800 | if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, |
| 1754 | - vs->x509cacert, | 1801 | + vs->vd->x509cacert, |
| 1755 | GNUTLS_X509_FMT_PEM)) < 0) { | 1802 | GNUTLS_X509_FMT_PEM)) < 0) { |
| 1756 | VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret)); | 1803 | VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret)); |
| 1757 | gnutls_certificate_free_credentials(x509_cred); | 1804 | gnutls_certificate_free_credentials(x509_cred); |
| @@ -1759,17 +1806,17 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v | @@ -1759,17 +1806,17 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v | ||
| 1759 | } | 1806 | } |
| 1760 | 1807 | ||
| 1761 | if ((ret = gnutls_certificate_set_x509_key_file (x509_cred, | 1808 | if ((ret = gnutls_certificate_set_x509_key_file (x509_cred, |
| 1762 | - vs->x509cert, | ||
| 1763 | - vs->x509key, | 1809 | + vs->vd->x509cert, |
| 1810 | + vs->vd->x509key, | ||
| 1764 | GNUTLS_X509_FMT_PEM)) < 0) { | 1811 | GNUTLS_X509_FMT_PEM)) < 0) { |
| 1765 | VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret)); | 1812 | VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret)); |
| 1766 | gnutls_certificate_free_credentials(x509_cred); | 1813 | gnutls_certificate_free_credentials(x509_cred); |
| 1767 | return NULL; | 1814 | return NULL; |
| 1768 | } | 1815 | } |
| 1769 | 1816 | ||
| 1770 | - if (vs->x509cacrl) { | 1817 | + if (vs->vd->x509cacrl) { |
| 1771 | if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, | 1818 | if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, |
| 1772 | - vs->x509cacrl, | 1819 | + vs->vd->x509cacrl, |
| 1773 | GNUTLS_X509_FMT_PEM)) < 0) { | 1820 | GNUTLS_X509_FMT_PEM)) < 0) { |
| 1774 | VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret)); | 1821 | VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret)); |
| 1775 | gnutls_certificate_free_credentials(x509_cred); | 1822 | gnutls_certificate_free_credentials(x509_cred); |
| @@ -1863,7 +1910,7 @@ static int vnc_validate_certificate(struct VncState *vs) | @@ -1863,7 +1910,7 @@ static int vnc_validate_certificate(struct VncState *vs) | ||
| 1863 | 1910 | ||
| 1864 | static int start_auth_vencrypt_subauth(VncState *vs) | 1911 | static int start_auth_vencrypt_subauth(VncState *vs) |
| 1865 | { | 1912 | { |
| 1866 | - switch (vs->subauth) { | 1913 | + switch (vs->vd->subauth) { |
| 1867 | case VNC_AUTH_VENCRYPT_TLSNONE: | 1914 | case VNC_AUTH_VENCRYPT_TLSNONE: |
| 1868 | case VNC_AUTH_VENCRYPT_X509NONE: | 1915 | case VNC_AUTH_VENCRYPT_X509NONE: |
| 1869 | VNC_DEBUG("Accept TLS auth none\n"); | 1916 | VNC_DEBUG("Accept TLS auth none\n"); |
| @@ -1877,7 +1924,7 @@ static int start_auth_vencrypt_subauth(VncState *vs) | @@ -1877,7 +1924,7 @@ static int start_auth_vencrypt_subauth(VncState *vs) | ||
| 1877 | return start_auth_vnc(vs); | 1924 | return start_auth_vnc(vs); |
| 1878 | 1925 | ||
| 1879 | default: /* Should not be possible, but just in case */ | 1926 | default: /* Should not be possible, but just in case */ |
| 1880 | - VNC_DEBUG("Reject auth %d\n", vs->auth); | 1927 | + VNC_DEBUG("Reject auth %d\n", vs->vd->auth); |
| 1881 | vnc_write_u8(vs, 1); | 1928 | vnc_write_u8(vs, 1); |
| 1882 | if (vs->minor >= 8) { | 1929 | if (vs->minor >= 8) { |
| 1883 | static const char err[] = "Unsupported authentication type"; | 1930 | static const char err[] = "Unsupported authentication type"; |
| @@ -1909,7 +1956,7 @@ static int vnc_continue_handshake(struct VncState *vs) { | @@ -1909,7 +1956,7 @@ static int vnc_continue_handshake(struct VncState *vs) { | ||
| 1909 | return -1; | 1956 | return -1; |
| 1910 | } | 1957 | } |
| 1911 | 1958 | ||
| 1912 | - if (vs->x509verify) { | 1959 | + if (vs->vd->x509verify) { |
| 1913 | if (vnc_validate_certificate(vs) < 0) { | 1960 | if (vnc_validate_certificate(vs) < 0) { |
| 1914 | VNC_DEBUG("Client verification failed\n"); | 1961 | VNC_DEBUG("Client verification failed\n"); |
| 1915 | vnc_client_error(vs); | 1962 | vnc_client_error(vs); |
| @@ -1934,9 +1981,9 @@ static void vnc_handshake_io(void *opaque) { | @@ -1934,9 +1981,9 @@ static void vnc_handshake_io(void *opaque) { | ||
| 1934 | } | 1981 | } |
| 1935 | 1982 | ||
| 1936 | #define NEED_X509_AUTH(vs) \ | 1983 | #define NEED_X509_AUTH(vs) \ |
| 1937 | - ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \ | ||
| 1938 | - (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \ | ||
| 1939 | - (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN) | 1984 | + ((vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509NONE || \ |
| 1985 | + (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509VNC || \ | ||
| 1986 | + (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509PLAIN) | ||
| 1940 | 1987 | ||
| 1941 | 1988 | ||
| 1942 | static int vnc_start_tls(struct VncState *vs) { | 1989 | static int vnc_start_tls(struct VncState *vs) { |
| @@ -2000,7 +2047,7 @@ static int vnc_start_tls(struct VncState *vs) { | @@ -2000,7 +2047,7 @@ static int vnc_start_tls(struct VncState *vs) { | ||
| 2000 | vnc_client_error(vs); | 2047 | vnc_client_error(vs); |
| 2001 | return -1; | 2048 | return -1; |
| 2002 | } | 2049 | } |
| 2003 | - if (vs->x509verify) { | 2050 | + if (vs->vd->x509verify) { |
| 2004 | VNC_DEBUG("Requesting a client certificate\n"); | 2051 | VNC_DEBUG("Requesting a client certificate\n"); |
| 2005 | gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST); | 2052 | gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST); |
| 2006 | } | 2053 | } |
| @@ -2035,7 +2082,7 @@ static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len | @@ -2035,7 +2082,7 @@ static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len | ||
| 2035 | { | 2082 | { |
| 2036 | int auth = read_u32(data, 0); | 2083 | int auth = read_u32(data, 0); |
| 2037 | 2084 | ||
| 2038 | - if (auth != vs->subauth) { | 2085 | + if (auth != vs->vd->subauth) { |
| 2039 | VNC_DEBUG("Rejecting auth %d\n", auth); | 2086 | VNC_DEBUG("Rejecting auth %d\n", auth); |
| 2040 | vnc_write_u8(vs, 0); /* Reject auth */ | 2087 | vnc_write_u8(vs, 0); /* Reject auth */ |
| 2041 | vnc_flush(vs); | 2088 | vnc_flush(vs); |
| @@ -2070,10 +2117,10 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len | @@ -2070,10 +2117,10 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len | ||
| 2070 | vnc_flush(vs); | 2117 | vnc_flush(vs); |
| 2071 | vnc_client_error(vs); | 2118 | vnc_client_error(vs); |
| 2072 | } else { | 2119 | } else { |
| 2073 | - VNC_DEBUG("Sending allowed auth %d\n", vs->subauth); | 2120 | + VNC_DEBUG("Sending allowed auth %d\n", vs->vd->subauth); |
| 2074 | vnc_write_u8(vs, 0); /* Accept version */ | 2121 | vnc_write_u8(vs, 0); /* Accept version */ |
| 2075 | vnc_write_u8(vs, 1); /* Number of sub-auths */ | 2122 | vnc_write_u8(vs, 1); /* Number of sub-auths */ |
| 2076 | - vnc_write_u32(vs, vs->subauth); /* The supported auth */ | 2123 | + vnc_write_u32(vs, vs->vd->subauth); /* The supported auth */ |
| 2077 | vnc_flush(vs); | 2124 | vnc_flush(vs); |
| 2078 | vnc_read_when(vs, protocol_client_vencrypt_auth, 4); | 2125 | vnc_read_when(vs, protocol_client_vencrypt_auth, 4); |
| 2079 | } | 2126 | } |
| @@ -2095,7 +2142,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len) | @@ -2095,7 +2142,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len) | ||
| 2095 | { | 2142 | { |
| 2096 | /* We only advertise 1 auth scheme at a time, so client | 2143 | /* We only advertise 1 auth scheme at a time, so client |
| 2097 | * must pick the one we sent. Verify this */ | 2144 | * must pick the one we sent. Verify this */ |
| 2098 | - if (data[0] != vs->auth) { /* Reject auth */ | 2145 | + if (data[0] != vs->vd->auth) { /* Reject auth */ |
| 2099 | VNC_DEBUG("Reject auth %d\n", (int)data[0]); | 2146 | VNC_DEBUG("Reject auth %d\n", (int)data[0]); |
| 2100 | vnc_write_u32(vs, 1); | 2147 | vnc_write_u32(vs, 1); |
| 2101 | if (vs->minor >= 8) { | 2148 | if (vs->minor >= 8) { |
| @@ -2106,7 +2153,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len) | @@ -2106,7 +2153,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len) | ||
| 2106 | vnc_client_error(vs); | 2153 | vnc_client_error(vs); |
| 2107 | } else { /* Accept requested auth */ | 2154 | } else { /* Accept requested auth */ |
| 2108 | VNC_DEBUG("Client requested auth %d\n", (int)data[0]); | 2155 | VNC_DEBUG("Client requested auth %d\n", (int)data[0]); |
| 2109 | - switch (vs->auth) { | 2156 | + switch (vs->vd->auth) { |
| 2110 | case VNC_AUTH_NONE: | 2157 | case VNC_AUTH_NONE: |
| 2111 | VNC_DEBUG("Accept auth none\n"); | 2158 | VNC_DEBUG("Accept auth none\n"); |
| 2112 | if (vs->minor >= 8) { | 2159 | if (vs->minor >= 8) { |
| @@ -2127,7 +2174,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len) | @@ -2127,7 +2174,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len) | ||
| 2127 | #endif /* CONFIG_VNC_TLS */ | 2174 | #endif /* CONFIG_VNC_TLS */ |
| 2128 | 2175 | ||
| 2129 | default: /* Should not be possible, but just in case */ | 2176 | default: /* Should not be possible, but just in case */ |
| 2130 | - VNC_DEBUG("Reject auth %d\n", vs->auth); | 2177 | + VNC_DEBUG("Reject auth %d\n", vs->vd->auth); |
| 2131 | vnc_write_u8(vs, 1); | 2178 | vnc_write_u8(vs, 1); |
| 2132 | if (vs->minor >= 8) { | 2179 | if (vs->minor >= 8) { |
| 2133 | static const char err[] = "Authentication failed"; | 2180 | static const char err[] = "Authentication failed"; |
| @@ -2172,26 +2219,26 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len) | @@ -2172,26 +2219,26 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len) | ||
| 2172 | vs->minor = 3; | 2219 | vs->minor = 3; |
| 2173 | 2220 | ||
| 2174 | if (vs->minor == 3) { | 2221 | if (vs->minor == 3) { |
| 2175 | - if (vs->auth == VNC_AUTH_NONE) { | 2222 | + if (vs->vd->auth == VNC_AUTH_NONE) { |
| 2176 | VNC_DEBUG("Tell client auth none\n"); | 2223 | VNC_DEBUG("Tell client auth none\n"); |
| 2177 | - vnc_write_u32(vs, vs->auth); | 2224 | + vnc_write_u32(vs, vs->vd->auth); |
| 2178 | vnc_flush(vs); | 2225 | vnc_flush(vs); |
| 2179 | vnc_read_when(vs, protocol_client_init, 1); | 2226 | vnc_read_when(vs, protocol_client_init, 1); |
| 2180 | - } else if (vs->auth == VNC_AUTH_VNC) { | 2227 | + } else if (vs->vd->auth == VNC_AUTH_VNC) { |
| 2181 | VNC_DEBUG("Tell client VNC auth\n"); | 2228 | VNC_DEBUG("Tell client VNC auth\n"); |
| 2182 | - vnc_write_u32(vs, vs->auth); | 2229 | + vnc_write_u32(vs, vs->vd->auth); |
| 2183 | vnc_flush(vs); | 2230 | vnc_flush(vs); |
| 2184 | start_auth_vnc(vs); | 2231 | start_auth_vnc(vs); |
| 2185 | } else { | 2232 | } else { |
| 2186 | - VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth); | 2233 | + VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth); |
| 2187 | vnc_write_u32(vs, VNC_AUTH_INVALID); | 2234 | vnc_write_u32(vs, VNC_AUTH_INVALID); |
| 2188 | vnc_flush(vs); | 2235 | vnc_flush(vs); |
| 2189 | vnc_client_error(vs); | 2236 | vnc_client_error(vs); |
| 2190 | } | 2237 | } |
| 2191 | } else { | 2238 | } else { |
| 2192 | - VNC_DEBUG("Telling client we support auth %d\n", vs->auth); | 2239 | + VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth); |
| 2193 | vnc_write_u8(vs, 1); /* num auth */ | 2240 | vnc_write_u8(vs, 1); /* num auth */ |
| 2194 | - vnc_write_u8(vs, vs->auth); | 2241 | + vnc_write_u8(vs, vs->vd->auth); |
| 2195 | vnc_read_when(vs, protocol_client_auth, 1); | 2242 | vnc_read_when(vs, protocol_client_auth, 1); |
| 2196 | vnc_flush(vs); | 2243 | vnc_flush(vs); |
| 2197 | } | 2244 | } |
| @@ -2199,55 +2246,67 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len) | @@ -2199,55 +2246,67 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len) | ||
| 2199 | return 0; | 2246 | return 0; |
| 2200 | } | 2247 | } |
| 2201 | 2248 | ||
| 2202 | -static void vnc_connect(VncState *vs) | 2249 | +static void vnc_connect(VncDisplay *vd, int csock) |
| 2203 | { | 2250 | { |
| 2204 | - VNC_DEBUG("New client on socket %d\n", vs->csock); | 2251 | + VncState *vs = qemu_mallocz(sizeof(VncState)); |
| 2252 | + vs->csock = csock; | ||
| 2253 | + | ||
| 2254 | + VNC_DEBUG("New client on socket %d\n", csock); | ||
| 2205 | dcl->idle = 0; | 2255 | dcl->idle = 0; |
| 2206 | socket_set_nonblock(vs->csock); | 2256 | socket_set_nonblock(vs->csock); |
| 2207 | qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); | 2257 | qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); |
| 2258 | + | ||
| 2259 | + vs->vd = vd; | ||
| 2260 | + vs->ds = vd->ds; | ||
| 2261 | + vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs); | ||
| 2262 | + vs->last_x = -1; | ||
| 2263 | + vs->last_y = -1; | ||
| 2264 | + | ||
| 2265 | + vs->as.freq = 44100; | ||
| 2266 | + vs->as.nchannels = 2; | ||
| 2267 | + vs->as.fmt = AUD_FMT_S16; | ||
| 2268 | + vs->as.endianness = 0; | ||
| 2269 | + | ||
| 2270 | + vnc_resize(vs); | ||
| 2208 | vnc_write(vs, "RFB 003.008\n", 12); | 2271 | vnc_write(vs, "RFB 003.008\n", 12); |
| 2209 | vnc_flush(vs); | 2272 | vnc_flush(vs); |
| 2210 | vnc_read_when(vs, protocol_version, 12); | 2273 | vnc_read_when(vs, protocol_version, 12); |
| 2211 | memset(vs->old_data, 0, ds_get_linesize(vs->ds) * ds_get_height(vs->ds)); | 2274 | memset(vs->old_data, 0, ds_get_linesize(vs->ds) * ds_get_height(vs->ds)); |
| 2212 | memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); | 2275 | memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); |
| 2213 | - vs->features = 0; | ||
| 2214 | - dcl->dpy_copy = NULL; | ||
| 2215 | vnc_update_client(vs); | 2276 | vnc_update_client(vs); |
| 2216 | reset_keys(vs); | 2277 | reset_keys(vs); |
| 2278 | + | ||
| 2279 | + vs->next = vd->clients; | ||
| 2280 | + vd->clients = vs; | ||
| 2217 | } | 2281 | } |
| 2218 | 2282 | ||
| 2219 | static void vnc_listen_read(void *opaque) | 2283 | static void vnc_listen_read(void *opaque) |
| 2220 | { | 2284 | { |
| 2221 | - VncState *vs = opaque; | 2285 | + VncDisplay *vs = opaque; |
| 2222 | struct sockaddr_in addr; | 2286 | struct sockaddr_in addr; |
| 2223 | socklen_t addrlen = sizeof(addr); | 2287 | socklen_t addrlen = sizeof(addr); |
| 2224 | 2288 | ||
| 2225 | /* Catch-up */ | 2289 | /* Catch-up */ |
| 2226 | vga_hw_update(); | 2290 | vga_hw_update(); |
| 2227 | 2291 | ||
| 2228 | - vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); | ||
| 2229 | - if (vs->csock != -1) { | ||
| 2230 | - vnc_connect(vs); | 2292 | + int csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); |
| 2293 | + if (csock != -1) { | ||
| 2294 | + vnc_connect(vs, csock); | ||
| 2231 | } | 2295 | } |
| 2232 | } | 2296 | } |
| 2233 | 2297 | ||
| 2234 | void vnc_display_init(DisplayState *ds) | 2298 | void vnc_display_init(DisplayState *ds) |
| 2235 | { | 2299 | { |
| 2236 | - VncState *vs; | 2300 | + VncDisplay *vs; |
| 2237 | 2301 | ||
| 2238 | vs = qemu_mallocz(sizeof(VncState)); | 2302 | vs = qemu_mallocz(sizeof(VncState)); |
| 2239 | dcl = qemu_mallocz(sizeof(DisplayChangeListener)); | 2303 | dcl = qemu_mallocz(sizeof(DisplayChangeListener)); |
| 2240 | 2304 | ||
| 2241 | ds->opaque = vs; | 2305 | ds->opaque = vs; |
| 2242 | dcl->idle = 1; | 2306 | dcl->idle = 1; |
| 2243 | - vnc_state = vs; | ||
| 2244 | - vs->display = NULL; | ||
| 2245 | - vs->password = NULL; | 2307 | + vnc_display = vs; |
| 2246 | 2308 | ||
| 2247 | vs->lsock = -1; | 2309 | vs->lsock = -1; |
| 2248 | - vs->csock = -1; | ||
| 2249 | - vs->last_x = -1; | ||
| 2250 | - vs->last_y = -1; | ||
| 2251 | 2310 | ||
| 2252 | vs->ds = ds; | 2311 | vs->ds = ds; |
| 2253 | 2312 | ||
| @@ -2259,22 +2318,15 @@ void vnc_display_init(DisplayState *ds) | @@ -2259,22 +2318,15 @@ void vnc_display_init(DisplayState *ds) | ||
| 2259 | if (!vs->kbd_layout) | 2318 | if (!vs->kbd_layout) |
| 2260 | exit(1); | 2319 | exit(1); |
| 2261 | 2320 | ||
| 2262 | - vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs); | ||
| 2263 | - | 2321 | + dcl->dpy_copy = vnc_dpy_copy; |
| 2264 | dcl->dpy_update = vnc_dpy_update; | 2322 | dcl->dpy_update = vnc_dpy_update; |
| 2265 | dcl->dpy_resize = vnc_dpy_resize; | 2323 | dcl->dpy_resize = vnc_dpy_resize; |
| 2266 | dcl->dpy_setdata = vnc_dpy_setdata; | 2324 | dcl->dpy_setdata = vnc_dpy_setdata; |
| 2267 | - dcl->dpy_refresh = NULL; | ||
| 2268 | register_displaychangelistener(ds, dcl); | 2325 | register_displaychangelistener(ds, dcl); |
| 2269 | - | ||
| 2270 | - vs->as.freq = 44100; | ||
| 2271 | - vs->as.nchannels = 2; | ||
| 2272 | - vs->as.fmt = AUD_FMT_S16; | ||
| 2273 | - vs->as.endianness = 0; | ||
| 2274 | } | 2326 | } |
| 2275 | 2327 | ||
| 2276 | #ifdef CONFIG_VNC_TLS | 2328 | #ifdef CONFIG_VNC_TLS |
| 2277 | -static int vnc_set_x509_credential(VncState *vs, | 2329 | +static int vnc_set_x509_credential(VncDisplay *vs, |
| 2278 | const char *certdir, | 2330 | const char *certdir, |
| 2279 | const char *filename, | 2331 | const char *filename, |
| 2280 | char **cred, | 2332 | char **cred, |
| @@ -2305,7 +2357,7 @@ static int vnc_set_x509_credential(VncState *vs, | @@ -2305,7 +2357,7 @@ static int vnc_set_x509_credential(VncState *vs, | ||
| 2305 | return 0; | 2357 | return 0; |
| 2306 | } | 2358 | } |
| 2307 | 2359 | ||
| 2308 | -static int vnc_set_x509_credential_dir(VncState *vs, | 2360 | +static int vnc_set_x509_credential_dir(VncDisplay *vs, |
| 2309 | const char *certdir) | 2361 | const char *certdir) |
| 2310 | { | 2362 | { |
| 2311 | if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0) | 2363 | if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0) |
| @@ -2331,7 +2383,7 @@ static int vnc_set_x509_credential_dir(VncState *vs, | @@ -2331,7 +2383,7 @@ static int vnc_set_x509_credential_dir(VncState *vs, | ||
| 2331 | 2383 | ||
| 2332 | void vnc_display_close(DisplayState *ds) | 2384 | void vnc_display_close(DisplayState *ds) |
| 2333 | { | 2385 | { |
| 2334 | - VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; | 2386 | + VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; |
| 2335 | 2387 | ||
| 2336 | if (!vs) | 2388 | if (!vs) |
| 2337 | return; | 2389 | return; |
| @@ -2344,32 +2396,16 @@ void vnc_display_close(DisplayState *ds) | @@ -2344,32 +2396,16 @@ void vnc_display_close(DisplayState *ds) | ||
| 2344 | close(vs->lsock); | 2396 | close(vs->lsock); |
| 2345 | vs->lsock = -1; | 2397 | vs->lsock = -1; |
| 2346 | } | 2398 | } |
| 2347 | - if (vs->csock != -1) { | ||
| 2348 | - qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); | ||
| 2349 | - closesocket(vs->csock); | ||
| 2350 | - vs->csock = -1; | ||
| 2351 | - buffer_reset(&vs->input); | ||
| 2352 | - buffer_reset(&vs->output); | ||
| 2353 | - vs->need_update = 0; | ||
| 2354 | -#ifdef CONFIG_VNC_TLS | ||
| 2355 | - if (vs->tls_session) { | ||
| 2356 | - gnutls_deinit(vs->tls_session); | ||
| 2357 | - vs->tls_session = NULL; | ||
| 2358 | - } | ||
| 2359 | - vs->wiremode = VNC_WIREMODE_CLEAR; | ||
| 2360 | -#endif /* CONFIG_VNC_TLS */ | ||
| 2361 | - } | ||
| 2362 | vs->auth = VNC_AUTH_INVALID; | 2399 | vs->auth = VNC_AUTH_INVALID; |
| 2363 | #ifdef CONFIG_VNC_TLS | 2400 | #ifdef CONFIG_VNC_TLS |
| 2364 | vs->subauth = VNC_AUTH_INVALID; | 2401 | vs->subauth = VNC_AUTH_INVALID; |
| 2365 | vs->x509verify = 0; | 2402 | vs->x509verify = 0; |
| 2366 | #endif | 2403 | #endif |
| 2367 | - audio_del(vs); | ||
| 2368 | } | 2404 | } |
| 2369 | 2405 | ||
| 2370 | int vnc_display_password(DisplayState *ds, const char *password) | 2406 | int vnc_display_password(DisplayState *ds, const char *password) |
| 2371 | { | 2407 | { |
| 2372 | - VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; | 2408 | + VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; |
| 2373 | 2409 | ||
| 2374 | if (vs->password) { | 2410 | if (vs->password) { |
| 2375 | qemu_free(vs->password); | 2411 | qemu_free(vs->password); |
| @@ -2385,7 +2421,7 @@ int vnc_display_password(DisplayState *ds, const char *password) | @@ -2385,7 +2421,7 @@ int vnc_display_password(DisplayState *ds, const char *password) | ||
| 2385 | 2421 | ||
| 2386 | int vnc_display_open(DisplayState *ds, const char *display) | 2422 | int vnc_display_open(DisplayState *ds, const char *display) |
| 2387 | { | 2423 | { |
| 2388 | - VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; | 2424 | + VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; |
| 2389 | const char *options; | 2425 | const char *options; |
| 2390 | int password = 0; | 2426 | int password = 0; |
| 2391 | int reverse = 0; | 2427 | int reverse = 0; |
| @@ -2394,7 +2430,7 @@ int vnc_display_open(DisplayState *ds, const char *display) | @@ -2394,7 +2430,7 @@ int vnc_display_open(DisplayState *ds, const char *display) | ||
| 2394 | int tls = 0, x509 = 0; | 2430 | int tls = 0, x509 = 0; |
| 2395 | #endif | 2431 | #endif |
| 2396 | 2432 | ||
| 2397 | - if (!vnc_state) | 2433 | + if (!vnc_display) |
| 2398 | return -1; | 2434 | return -1; |
| 2399 | vnc_display_close(ds); | 2435 | vnc_display_close(ds); |
| 2400 | if (strcmp(display, "none") == 0) | 2436 | if (strcmp(display, "none") == 0) |
| @@ -2499,9 +2535,9 @@ int vnc_display_open(DisplayState *ds, const char *display) | @@ -2499,9 +2535,9 @@ int vnc_display_open(DisplayState *ds, const char *display) | ||
| 2499 | vs->display = NULL; | 2535 | vs->display = NULL; |
| 2500 | return -1; | 2536 | return -1; |
| 2501 | } else { | 2537 | } else { |
| 2502 | - vs->csock = vs->lsock; | 2538 | + int csock = vs->lsock; |
| 2503 | vs->lsock = -1; | 2539 | vs->lsock = -1; |
| 2504 | - vnc_connect(vs); | 2540 | + vnc_connect(vs, csock); |
| 2505 | } | 2541 | } |
| 2506 | return 0; | 2542 | return 0; |
| 2507 | 2543 | ||
| @@ -2523,6 +2559,5 @@ int vnc_display_open(DisplayState *ds, const char *display) | @@ -2523,6 +2559,5 @@ int vnc_display_open(DisplayState *ds, const char *display) | ||
| 2523 | vs->display = dpy; | 2559 | vs->display = dpy; |
| 2524 | } | 2560 | } |
| 2525 | } | 2561 | } |
| 2526 | - | ||
| 2527 | - return qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs); | 2562 | + return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs); |
| 2528 | } | 2563 | } |
vnc.h
| @@ -101,6 +101,7 @@ enum { | @@ -101,6 +101,7 @@ enum { | ||
| 101 | #define VNC_FEATURE_WMVI 3 | 101 | #define VNC_FEATURE_WMVI 3 |
| 102 | #define VNC_FEATURE_TIGHT 4 | 102 | #define VNC_FEATURE_TIGHT 4 |
| 103 | #define VNC_FEATURE_ZLIB 5 | 103 | #define VNC_FEATURE_ZLIB 5 |
| 104 | +#define VNC_FEATURE_COPYRECT 6 | ||
| 104 | 105 | ||
| 105 | #define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE) | 106 | #define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE) |
| 106 | #define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE) | 107 | #define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE) |
| @@ -108,5 +109,6 @@ enum { | @@ -108,5 +109,6 @@ enum { | ||
| 108 | #define VNC_FEATURE_WMVI_MASK (1 << VNC_FEATURE_WMVI) | 109 | #define VNC_FEATURE_WMVI_MASK (1 << VNC_FEATURE_WMVI) |
| 109 | #define VNC_FEATURE_TIGHT_MASK (1 << VNC_FEATURE_TIGHT) | 110 | #define VNC_FEATURE_TIGHT_MASK (1 << VNC_FEATURE_TIGHT) |
| 110 | #define VNC_FEATURE_ZLIB_MASK (1 << VNC_FEATURE_ZLIB) | 111 | #define VNC_FEATURE_ZLIB_MASK (1 << VNC_FEATURE_ZLIB) |
| 112 | +#define VNC_FEATURE_COPYRECT_MASK (1 << VNC_FEATURE_COPYRECT) | ||
| 111 | 113 | ||
| 112 | #endif /* __VNCTIGHT_H */ | 114 | #endif /* __VNCTIGHT_H */ |