Commit 753b4053311ff1437d99726970b1e7e6bf38249b

Authored by aliguori
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
... ... @@ -90,12 +90,35 @@ typedef void VncSendHextileTile(VncState *vs,
90 90  
91 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 116 struct VncState
94 117 {
95 118 QEMUTimer *timer;
96   - int lsock;
97 119 int csock;
98 120 DisplayState *ds;
  121 + VncDisplay *vd;
99 122 int need_update;
100 123 uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
101 124 char *old_data;
... ... @@ -111,18 +134,6 @@ struct VncState
111 134 int major;
112 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 137 char challenge[VNC_AUTH_CHALLENGE_SIZE];
127 138  
128 139 #ifdef CONFIG_VNC_TLS
... ... @@ -132,7 +143,6 @@ struct VncState
132 143  
133 144 Buffer output;
134 145 Buffer input;
135   - kbd_layout_t *kbd_layout;
136 146 /* current output mode information */
137 147 VncWritePixels *write_pixels;
138 148 VncSendHextileTile *send_hextile_tile;
... ... @@ -149,21 +159,23 @@ struct VncState
149 159 Buffer zlib;
150 160 Buffer zlib_tmp;
151 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 167 static DisplayChangeListener *dcl;
156 168  
157 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 172 term_printf("VNC server disabled\n");
161 173 else {
162 174 term_printf("VNC server active on: ");
163   - term_print_filename(vnc_state->display);
  175 + term_print_filename(vnc_display->display);
164 176 term_printf("\n");
165 177  
166   - if (vnc_state->csock == -1)
  178 + if (vnc_display->clients == NULL)
167 179 term_printf("No client connected\n");
168 180 else
169 181 term_printf("Client connected\n");
... ... @@ -190,7 +202,7 @@ static void vnc_flush(VncState *vs);
190 202 static void vnc_update_client(void *opaque);
191 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 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 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 250 int i;
240 251  
241 252 h += y;
... ... @@ -257,6 +268,16 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
257 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 281 static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
261 282 int32_t encoding)
262 283 {
... ... @@ -301,10 +322,11 @@ static void buffer_append(Buffer *buffer, const void *data, size_t len)
301 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 329 int size_changed;
307   - VncState *vs = ds->opaque;
308 330  
309 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 337  
316 338 if (ds_get_bytes_per_pixel(ds) != vs->serverds.pf.bytes_per_pixel)
317 339 console_color_init(ds);
318   - vnc_colordepth(ds);
  340 + vnc_colordepth(vs);
319 341 size_changed = ds_get_width(ds) != vs->serverds.width ||
320 342 ds_get_height(ds) != vs->serverds.height;
321 343 vs->serverds = *(ds->surface);
... ... @@ -334,6 +356,16 @@ static void vnc_dpy_resize(DisplayState *ds)
334 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 369 /* fastest code */
338 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 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 636 vnc_update_client(vs);
607 637  
608 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 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 660 static int find_dirty_height(VncState *vs, int y, int last_x, int x)
618 661 {
619 662 int h;
... ... @@ -632,7 +675,6 @@ static int find_dirty_height(VncState *vs, int y, int last_x, int x)
632 675 static void vnc_update_client(void *opaque)
633 676 {
634 677 VncState *vs = opaque;
635   -
636 678 if (vs->need_update && vs->csock != -1) {
637 679 int y;
638 680 uint8_t *row;
... ... @@ -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 770 /* audio */
737 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 851 VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
818 852 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
819 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 858 #ifdef CONFIG_VNC_TLS
826 859 if (vs->tls_session) {
827 860 gnutls_deinit(vs->tls_session);
828 861 vs->tls_session = NULL;
829 862 }
830   - vs->wiremode = VNC_WIREMODE_CLEAR;
831 863 #endif /* CONFIG_VNC_TLS */
832 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 883 return 0;
834 884 }
835 885 return ret;
... ... @@ -1095,8 +1145,8 @@ static void reset_keys(VncState *vs)
1095 1145  
1096 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 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 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 1183 /* If the numlock state needs to change then simulate an additional
1134 1184 keypress before sending this one. This will happen if the user
1135 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 1188 if (!vs->modifiers_state[0x45]) {
1139 1189 vs->modifiers_state[0x45] = 1;
1140 1190 press_key(vs, 0xff7f);
... ... @@ -1207,7 +1257,7 @@ static void key_event(VncState *vs, int down, uint32_t sym)
1207 1257 if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
1208 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 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 1329 vs->tight_compression = 9;
1280 1330 vs->tight_quality = 9;
1281 1331 vs->absolute = -1;
1282   - dcl->dpy_copy = NULL;
1283 1332  
1284 1333 for (i = n_encodings - 1; i >= 0; i--) {
1285 1334 enc = encodings[i];
... ... @@ -1288,7 +1337,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1288 1337 vs->vnc_encoding = enc;
1289 1338 break;
1290 1339 case VNC_ENCODING_COPYRECT:
1291   - dcl->dpy_copy = vnc_copy;
  1340 + vs->features |= VNC_FEATURE_COPYRECT_MASK;
1292 1341 break;
1293 1342 case VNC_ENCODING_HEXTILE:
1294 1343 vs->features |= VNC_FEATURE_HEXTILE_MASK;
... ... @@ -1432,17 +1481,15 @@ static void vnc_dpy_setdata(DisplayState *ds)
1432 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 1487 /* Sending a WMVi message to notify the client*/
1441 1488 vnc_write_u8(vs, 0); /* msg id */
1442 1489 vnc_write_u8(vs, 0);
1443 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 1493 pixel_format_message(vs);
1447 1494 vnc_flush(vs);
1448 1495 } else {
... ... @@ -1626,7 +1673,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1626 1673 int i, j, pwlen;
1627 1674 unsigned char key[8];
1628 1675  
1629   - if (!vs->password || !vs->password[0]) {
  1676 + if (!vs->vd->password || !vs->vd->password[0]) {
1630 1677 VNC_DEBUG("No password configured on server");
1631 1678 vnc_write_u32(vs, 1); /* Reject auth */
1632 1679 if (vs->minor >= 8) {
... ... @@ -1642,9 +1689,9 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1642 1689 memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
1643 1690  
1644 1691 /* Calculate the expected challenge response */
1645   - pwlen = strlen(vs->password);
  1692 + pwlen = strlen(vs->vd->password);
1646 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 1695 deskey(key, EN0);
1649 1696 for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
1650 1697 des(response+j, response+j);
... ... @@ -1733,15 +1780,15 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v
1733 1780 gnutls_certificate_credentials_t x509_cred;
1734 1781 int ret;
1735 1782  
1736   - if (!vs->x509cacert) {
  1783 + if (!vs->vd->x509cacert) {
1737 1784 VNC_DEBUG("No CA x509 certificate specified\n");
1738 1785 return NULL;
1739 1786 }
1740   - if (!vs->x509cert) {
  1787 + if (!vs->vd->x509cert) {
1741 1788 VNC_DEBUG("No server x509 certificate specified\n");
1742 1789 return NULL;
1743 1790 }
1744   - if (!vs->x509key) {
  1791 + if (!vs->vd->x509key) {
1745 1792 VNC_DEBUG("No server private key specified\n");
1746 1793 return NULL;
1747 1794 }
... ... @@ -1751,7 +1798,7 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v
1751 1798 return NULL;
1752 1799 }
1753 1800 if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
1754   - vs->x509cacert,
  1801 + vs->vd->x509cacert,
1755 1802 GNUTLS_X509_FMT_PEM)) < 0) {
1756 1803 VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
1757 1804 gnutls_certificate_free_credentials(x509_cred);
... ... @@ -1759,17 +1806,17 @@ static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *v
1759 1806 }
1760 1807  
1761 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 1811 GNUTLS_X509_FMT_PEM)) < 0) {
1765 1812 VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
1766 1813 gnutls_certificate_free_credentials(x509_cred);
1767 1814 return NULL;
1768 1815 }
1769 1816  
1770   - if (vs->x509cacrl) {
  1817 + if (vs->vd->x509cacrl) {
1771 1818 if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
1772   - vs->x509cacrl,
  1819 + vs->vd->x509cacrl,
1773 1820 GNUTLS_X509_FMT_PEM)) < 0) {
1774 1821 VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
1775 1822 gnutls_certificate_free_credentials(x509_cred);
... ... @@ -1863,7 +1910,7 @@ static int vnc_validate_certificate(struct VncState *vs)
1863 1910  
1864 1911 static int start_auth_vencrypt_subauth(VncState *vs)
1865 1912 {
1866   - switch (vs->subauth) {
  1913 + switch (vs->vd->subauth) {
1867 1914 case VNC_AUTH_VENCRYPT_TLSNONE:
1868 1915 case VNC_AUTH_VENCRYPT_X509NONE:
1869 1916 VNC_DEBUG("Accept TLS auth none\n");
... ... @@ -1877,7 +1924,7 @@ static int start_auth_vencrypt_subauth(VncState *vs)
1877 1924 return start_auth_vnc(vs);
1878 1925  
1879 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 1928 vnc_write_u8(vs, 1);
1882 1929 if (vs->minor >= 8) {
1883 1930 static const char err[] = "Unsupported authentication type";
... ... @@ -1909,7 +1956,7 @@ static int vnc_continue_handshake(struct VncState *vs) {
1909 1956 return -1;
1910 1957 }
1911 1958  
1912   - if (vs->x509verify) {
  1959 + if (vs->vd->x509verify) {
1913 1960 if (vnc_validate_certificate(vs) < 0) {
1914 1961 VNC_DEBUG("Client verification failed\n");
1915 1962 vnc_client_error(vs);
... ... @@ -1934,9 +1981,9 @@ static void vnc_handshake_io(void *opaque) {
1934 1981 }
1935 1982  
1936 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 1989 static int vnc_start_tls(struct VncState *vs) {
... ... @@ -2000,7 +2047,7 @@ static int vnc_start_tls(struct VncState *vs) {
2000 2047 vnc_client_error(vs);
2001 2048 return -1;
2002 2049 }
2003   - if (vs->x509verify) {
  2050 + if (vs->vd->x509verify) {
2004 2051 VNC_DEBUG("Requesting a client certificate\n");
2005 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 2082 {
2036 2083 int auth = read_u32(data, 0);
2037 2084  
2038   - if (auth != vs->subauth) {
  2085 + if (auth != vs->vd->subauth) {
2039 2086 VNC_DEBUG("Rejecting auth %d\n", auth);
2040 2087 vnc_write_u8(vs, 0); /* Reject auth */
2041 2088 vnc_flush(vs);
... ... @@ -2070,10 +2117,10 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
2070 2117 vnc_flush(vs);
2071 2118 vnc_client_error(vs);
2072 2119 } else {
2073   - VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
  2120 + VNC_DEBUG("Sending allowed auth %d\n", vs->vd->subauth);
2074 2121 vnc_write_u8(vs, 0); /* Accept version */
2075 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 2124 vnc_flush(vs);
2078 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 2142 {
2096 2143 /* We only advertise 1 auth scheme at a time, so client
2097 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 2146 VNC_DEBUG("Reject auth %d\n", (int)data[0]);
2100 2147 vnc_write_u32(vs, 1);
2101 2148 if (vs->minor >= 8) {
... ... @@ -2106,7 +2153,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2106 2153 vnc_client_error(vs);
2107 2154 } else { /* Accept requested auth */
2108 2155 VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2109   - switch (vs->auth) {
  2156 + switch (vs->vd->auth) {
2110 2157 case VNC_AUTH_NONE:
2111 2158 VNC_DEBUG("Accept auth none\n");
2112 2159 if (vs->minor >= 8) {
... ... @@ -2127,7 +2174,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2127 2174 #endif /* CONFIG_VNC_TLS */
2128 2175  
2129 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 2178 vnc_write_u8(vs, 1);
2132 2179 if (vs->minor >= 8) {
2133 2180 static const char err[] = "Authentication failed";
... ... @@ -2172,26 +2219,26 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2172 2219 vs->minor = 3;
2173 2220  
2174 2221 if (vs->minor == 3) {
2175   - if (vs->auth == VNC_AUTH_NONE) {
  2222 + if (vs->vd->auth == VNC_AUTH_NONE) {
2176 2223 VNC_DEBUG("Tell client auth none\n");
2177   - vnc_write_u32(vs, vs->auth);
  2224 + vnc_write_u32(vs, vs->vd->auth);
2178 2225 vnc_flush(vs);
2179 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 2228 VNC_DEBUG("Tell client VNC auth\n");
2182   - vnc_write_u32(vs, vs->auth);
  2229 + vnc_write_u32(vs, vs->vd->auth);
2183 2230 vnc_flush(vs);
2184 2231 start_auth_vnc(vs);
2185 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 2234 vnc_write_u32(vs, VNC_AUTH_INVALID);
2188 2235 vnc_flush(vs);
2189 2236 vnc_client_error(vs);
2190 2237 }
2191 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 2240 vnc_write_u8(vs, 1); /* num auth */
2194   - vnc_write_u8(vs, vs->auth);
  2241 + vnc_write_u8(vs, vs->vd->auth);
2195 2242 vnc_read_when(vs, protocol_client_auth, 1);
2196 2243 vnc_flush(vs);
2197 2244 }
... ... @@ -2199,55 +2246,67 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2199 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 2255 dcl->idle = 0;
2206 2256 socket_set_nonblock(vs->csock);
2207 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 2271 vnc_write(vs, "RFB 003.008\n", 12);
2209 2272 vnc_flush(vs);
2210 2273 vnc_read_when(vs, protocol_version, 12);
2211 2274 memset(vs->old_data, 0, ds_get_linesize(vs->ds) * ds_get_height(vs->ds));
2212 2275 memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
2213   - vs->features = 0;
2214   - dcl->dpy_copy = NULL;
2215 2276 vnc_update_client(vs);
2216 2277 reset_keys(vs);
  2278 +
  2279 + vs->next = vd->clients;
  2280 + vd->clients = vs;
2217 2281 }
2218 2282  
2219 2283 static void vnc_listen_read(void *opaque)
2220 2284 {
2221   - VncState *vs = opaque;
  2285 + VncDisplay *vs = opaque;
2222 2286 struct sockaddr_in addr;
2223 2287 socklen_t addrlen = sizeof(addr);
2224 2288  
2225 2289 /* Catch-up */
2226 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 2298 void vnc_display_init(DisplayState *ds)
2235 2299 {
2236   - VncState *vs;
  2300 + VncDisplay *vs;
2237 2301  
2238 2302 vs = qemu_mallocz(sizeof(VncState));
2239 2303 dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2240 2304  
2241 2305 ds->opaque = vs;
2242 2306 dcl->idle = 1;
2243   - vnc_state = vs;
2244   - vs->display = NULL;
2245   - vs->password = NULL;
  2307 + vnc_display = vs;
2246 2308  
2247 2309 vs->lsock = -1;
2248   - vs->csock = -1;
2249   - vs->last_x = -1;
2250   - vs->last_y = -1;
2251 2310  
2252 2311 vs->ds = ds;
2253 2312  
... ... @@ -2259,22 +2318,15 @@ void vnc_display_init(DisplayState *ds)
2259 2318 if (!vs->kbd_layout)
2260 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 2322 dcl->dpy_update = vnc_dpy_update;
2265 2323 dcl->dpy_resize = vnc_dpy_resize;
2266 2324 dcl->dpy_setdata = vnc_dpy_setdata;
2267   - dcl->dpy_refresh = NULL;
2268 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 2328 #ifdef CONFIG_VNC_TLS
2277   -static int vnc_set_x509_credential(VncState *vs,
  2329 +static int vnc_set_x509_credential(VncDisplay *vs,
2278 2330 const char *certdir,
2279 2331 const char *filename,
2280 2332 char **cred,
... ... @@ -2305,7 +2357,7 @@ static int vnc_set_x509_credential(VncState *vs,
2305 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 2361 const char *certdir)
2310 2362 {
2311 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 2383  
2332 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 2388 if (!vs)
2337 2389 return;
... ... @@ -2344,32 +2396,16 @@ void vnc_display_close(DisplayState *ds)
2344 2396 close(vs->lsock);
2345 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 2399 vs->auth = VNC_AUTH_INVALID;
2363 2400 #ifdef CONFIG_VNC_TLS
2364 2401 vs->subauth = VNC_AUTH_INVALID;
2365 2402 vs->x509verify = 0;
2366 2403 #endif
2367   - audio_del(vs);
2368 2404 }
2369 2405  
2370 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 2410 if (vs->password) {
2375 2411 qemu_free(vs->password);
... ... @@ -2385,7 +2421,7 @@ int vnc_display_password(DisplayState *ds, const char *password)
2385 2421  
2386 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 2425 const char *options;
2390 2426 int password = 0;
2391 2427 int reverse = 0;
... ... @@ -2394,7 +2430,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
2394 2430 int tls = 0, x509 = 0;
2395 2431 #endif
2396 2432  
2397   - if (!vnc_state)
  2433 + if (!vnc_display)
2398 2434 return -1;
2399 2435 vnc_display_close(ds);
2400 2436 if (strcmp(display, "none") == 0)
... ... @@ -2499,9 +2535,9 @@ int vnc_display_open(DisplayState *ds, const char *display)
2499 2535 vs->display = NULL;
2500 2536 return -1;
2501 2537 } else {
2502   - vs->csock = vs->lsock;
  2538 + int csock = vs->lsock;
2503 2539 vs->lsock = -1;
2504   - vnc_connect(vs);
  2540 + vnc_connect(vs, csock);
2505 2541 }
2506 2542 return 0;
2507 2543  
... ... @@ -2523,6 +2559,5 @@ int vnc_display_open(DisplayState *ds, const char *display)
2523 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 }
... ...
... ... @@ -101,6 +101,7 @@ enum {
101 101 #define VNC_FEATURE_WMVI 3
102 102 #define VNC_FEATURE_TIGHT 4
103 103 #define VNC_FEATURE_ZLIB 5
  104 +#define VNC_FEATURE_COPYRECT 6
104 105  
105 106 #define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE)
106 107 #define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE)
... ... @@ -108,5 +109,6 @@ enum {
108 109 #define VNC_FEATURE_WMVI_MASK (1 << VNC_FEATURE_WMVI)
109 110 #define VNC_FEATURE_TIGHT_MASK (1 << VNC_FEATURE_TIGHT)
110 111 #define VNC_FEATURE_ZLIB_MASK (1 << VNC_FEATURE_ZLIB)
  112 +#define VNC_FEATURE_COPYRECT_MASK (1 << VNC_FEATURE_COPYRECT)
111 113  
112 114 #endif /* __VNCTIGHT_H */
... ...