Statistics
| Branch: | Revision:

root / vnc.c @ 151f7749

History | View | Annotate | Download (67 kB)

1 7d510b8c bellard
/*
2 7d510b8c bellard
 * QEMU VNC display driver
3 5fafdf24 ths
 *
4 7d510b8c bellard
 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 7d510b8c bellard
 * Copyright (C) 2006 Fabrice Bellard
6 19a490bf aliguori
 * Copyright (C) 2009 Red Hat, Inc
7 5fafdf24 ths
 *
8 7d510b8c bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 7d510b8c bellard
 * of this software and associated documentation files (the "Software"), to deal
10 7d510b8c bellard
 * in the Software without restriction, including without limitation the rights
11 7d510b8c bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 7d510b8c bellard
 * copies of the Software, and to permit persons to whom the Software is
13 7d510b8c bellard
 * furnished to do so, subject to the following conditions:
14 7d510b8c bellard
 *
15 7d510b8c bellard
 * The above copyright notice and this permission notice shall be included in
16 7d510b8c bellard
 * all copies or substantial portions of the Software.
17 7d510b8c bellard
 *
18 7d510b8c bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 7d510b8c bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 7d510b8c bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 7d510b8c bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 7d510b8c bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 7d510b8c bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 7d510b8c bellard
 * THE SOFTWARE.
25 7d510b8c bellard
 */
26 7d510b8c bellard
27 19a490bf aliguori
#include "vnc.h"
28 87ecb68b pbrook
#include "sysemu.h"
29 6ca957f0 bellard
#include "qemu_socket.h"
30 87ecb68b pbrook
#include "qemu-timer.h"
31 76655d6d aliguori
#include "acl.h"
32 24236869 bellard
33 24236869 bellard
#define VNC_REFRESH_INTERVAL (1000 / 30)
34 24236869 bellard
35 24236869 bellard
#include "vnc_keysym.h"
36 70848515 ths
#include "d3des.h"
37 70848515 ths
38 90a1e3c0 aliguori
#define count_bits(c, v) { \
39 90a1e3c0 aliguori
    for (c = 0; v; v >>= 1) \
40 90a1e3c0 aliguori
    { \
41 90a1e3c0 aliguori
        c += v & 1; \
42 90a1e3c0 aliguori
    } \
43 90a1e3c0 aliguori
}
44 8d5d2d4c ths
45 24236869 bellard
46 753b4053 aliguori
static VncDisplay *vnc_display; /* needed for info vnc */
47 7d957bd8 aliguori
static DisplayChangeListener *dcl;
48 a9ce8590 bellard
49 1ff7df1a aliguori
static char *addr_to_string(const char *format,
50 1ff7df1a aliguori
                            struct sockaddr_storage *sa,
51 1ff7df1a aliguori
                            socklen_t salen) {
52 1ff7df1a aliguori
    char *addr;
53 1ff7df1a aliguori
    char host[NI_MAXHOST];
54 1ff7df1a aliguori
    char serv[NI_MAXSERV];
55 1ff7df1a aliguori
    int err;
56 457772e6 aliguori
    size_t addrlen;
57 1ff7df1a aliguori
58 1ff7df1a aliguori
    if ((err = getnameinfo((struct sockaddr *)sa, salen,
59 1ff7df1a aliguori
                           host, sizeof(host),
60 1ff7df1a aliguori
                           serv, sizeof(serv),
61 1ff7df1a aliguori
                           NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
62 1ff7df1a aliguori
        VNC_DEBUG("Cannot resolve address %d: %s\n",
63 1ff7df1a aliguori
                  err, gai_strerror(err));
64 1ff7df1a aliguori
        return NULL;
65 1ff7df1a aliguori
    }
66 1ff7df1a aliguori
67 457772e6 aliguori
    /* Enough for the existing format + the 2 vars we're
68 457772e6 aliguori
     * subsituting in. */
69 457772e6 aliguori
    addrlen = strlen(format) + strlen(host) + strlen(serv);
70 457772e6 aliguori
    addr = qemu_malloc(addrlen + 1);
71 457772e6 aliguori
    snprintf(addr, addrlen, format, host, serv);
72 457772e6 aliguori
    addr[addrlen] = '\0';
73 1ff7df1a aliguori
74 1ff7df1a aliguori
    return addr;
75 1ff7df1a aliguori
}
76 1ff7df1a aliguori
77 2f9606b3 aliguori
78 2f9606b3 aliguori
char *vnc_socket_local_addr(const char *format, int fd) {
79 1ff7df1a aliguori
    struct sockaddr_storage sa;
80 1ff7df1a aliguori
    socklen_t salen;
81 1ff7df1a aliguori
82 1ff7df1a aliguori
    salen = sizeof(sa);
83 1ff7df1a aliguori
    if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0)
84 1ff7df1a aliguori
        return NULL;
85 1ff7df1a aliguori
86 1ff7df1a aliguori
    return addr_to_string(format, &sa, salen);
87 1ff7df1a aliguori
}
88 1ff7df1a aliguori
89 2f9606b3 aliguori
char *vnc_socket_remote_addr(const char *format, int fd) {
90 1ff7df1a aliguori
    struct sockaddr_storage sa;
91 1ff7df1a aliguori
    socklen_t salen;
92 1ff7df1a aliguori
93 1ff7df1a aliguori
    salen = sizeof(sa);
94 1ff7df1a aliguori
    if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0)
95 1ff7df1a aliguori
        return NULL;
96 1ff7df1a aliguori
97 1ff7df1a aliguori
    return addr_to_string(format, &sa, salen);
98 1ff7df1a aliguori
}
99 1ff7df1a aliguori
100 1ff7df1a aliguori
static const char *vnc_auth_name(VncDisplay *vd) {
101 1ff7df1a aliguori
    switch (vd->auth) {
102 1ff7df1a aliguori
    case VNC_AUTH_INVALID:
103 1ff7df1a aliguori
        return "invalid";
104 1ff7df1a aliguori
    case VNC_AUTH_NONE:
105 1ff7df1a aliguori
        return "none";
106 1ff7df1a aliguori
    case VNC_AUTH_VNC:
107 1ff7df1a aliguori
        return "vnc";
108 1ff7df1a aliguori
    case VNC_AUTH_RA2:
109 1ff7df1a aliguori
        return "ra2";
110 1ff7df1a aliguori
    case VNC_AUTH_RA2NE:
111 1ff7df1a aliguori
        return "ra2ne";
112 1ff7df1a aliguori
    case VNC_AUTH_TIGHT:
113 1ff7df1a aliguori
        return "tight";
114 1ff7df1a aliguori
    case VNC_AUTH_ULTRA:
115 1ff7df1a aliguori
        return "ultra";
116 1ff7df1a aliguori
    case VNC_AUTH_TLS:
117 1ff7df1a aliguori
        return "tls";
118 1ff7df1a aliguori
    case VNC_AUTH_VENCRYPT:
119 1ff7df1a aliguori
#ifdef CONFIG_VNC_TLS
120 1ff7df1a aliguori
        switch (vd->subauth) {
121 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_PLAIN:
122 1ff7df1a aliguori
            return "vencrypt+plain";
123 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_TLSNONE:
124 1ff7df1a aliguori
            return "vencrypt+tls+none";
125 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_TLSVNC:
126 1ff7df1a aliguori
            return "vencrypt+tls+vnc";
127 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_TLSPLAIN:
128 1ff7df1a aliguori
            return "vencrypt+tls+plain";
129 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_X509NONE:
130 1ff7df1a aliguori
            return "vencrypt+x509+none";
131 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_X509VNC:
132 1ff7df1a aliguori
            return "vencrypt+x509+vnc";
133 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_X509PLAIN:
134 1ff7df1a aliguori
            return "vencrypt+x509+plain";
135 28a76be8 aliguori
        case VNC_AUTH_VENCRYPT_TLSSASL:
136 28a76be8 aliguori
            return "vencrypt+tls+sasl";
137 28a76be8 aliguori
        case VNC_AUTH_VENCRYPT_X509SASL:
138 28a76be8 aliguori
            return "vencrypt+x509+sasl";
139 1ff7df1a aliguori
        default:
140 1ff7df1a aliguori
            return "vencrypt";
141 1ff7df1a aliguori
        }
142 1ff7df1a aliguori
#else
143 1ff7df1a aliguori
        return "vencrypt";
144 1ff7df1a aliguori
#endif
145 2f9606b3 aliguori
    case VNC_AUTH_SASL:
146 28a76be8 aliguori
        return "sasl";
147 1ff7df1a aliguori
    }
148 1ff7df1a aliguori
    return "unknown";
149 1ff7df1a aliguori
}
150 1ff7df1a aliguori
151 1ff7df1a aliguori
static void do_info_vnc_client(Monitor *mon, VncState *client)
152 1ff7df1a aliguori
{
153 1ff7df1a aliguori
    char *clientAddr =
154 1ff7df1a aliguori
        vnc_socket_remote_addr("     address: %s:%s\n",
155 1ff7df1a aliguori
                               client->csock);
156 1ff7df1a aliguori
    if (!clientAddr)
157 1ff7df1a aliguori
        return;
158 1ff7df1a aliguori
159 1ff7df1a aliguori
    monitor_printf(mon, "Client:\n");
160 1ff7df1a aliguori
    monitor_printf(mon, "%s", clientAddr);
161 1ff7df1a aliguori
    free(clientAddr);
162 1263b7d6 aliguori
163 1263b7d6 aliguori
#ifdef CONFIG_VNC_TLS
164 1263b7d6 aliguori
    if (client->tls.session &&
165 28a76be8 aliguori
        client->tls.dname)
166 28a76be8 aliguori
        monitor_printf(mon, "  x509 dname: %s\n", client->tls.dname);
167 1263b7d6 aliguori
    else
168 28a76be8 aliguori
        monitor_printf(mon, "  x509 dname: none\n");
169 1263b7d6 aliguori
#endif
170 1263b7d6 aliguori
#ifdef CONFIG_VNC_SASL
171 1263b7d6 aliguori
    if (client->sasl.conn &&
172 28a76be8 aliguori
        client->sasl.username)
173 28a76be8 aliguori
        monitor_printf(mon, "    username: %s\n", client->sasl.username);
174 1263b7d6 aliguori
    else
175 28a76be8 aliguori
        monitor_printf(mon, "    username: none\n");
176 1263b7d6 aliguori
#endif
177 1ff7df1a aliguori
}
178 1ff7df1a aliguori
179 376253ec aliguori
void do_info_vnc(Monitor *mon)
180 a9ce8590 bellard
{
181 1ff7df1a aliguori
    if (vnc_display == NULL || vnc_display->display == NULL) {
182 1ff7df1a aliguori
        monitor_printf(mon, "Server: disabled\n");
183 1ff7df1a aliguori
    } else {
184 1ff7df1a aliguori
        char *serverAddr = vnc_socket_local_addr("     address: %s:%s\n",
185 1ff7df1a aliguori
                                                 vnc_display->lsock);
186 1ff7df1a aliguori
187 1ff7df1a aliguori
        if (!serverAddr)
188 1ff7df1a aliguori
            return;
189 1ff7df1a aliguori
190 1ff7df1a aliguori
        monitor_printf(mon, "Server:\n");
191 1ff7df1a aliguori
        monitor_printf(mon, "%s", serverAddr);
192 1ff7df1a aliguori
        free(serverAddr);
193 1ff7df1a aliguori
        monitor_printf(mon, "        auth: %s\n", vnc_auth_name(vnc_display));
194 1ff7df1a aliguori
195 1ff7df1a aliguori
        if (vnc_display->clients) {
196 1ff7df1a aliguori
            VncState *client = vnc_display->clients;
197 1ff7df1a aliguori
            while (client) {
198 1ff7df1a aliguori
                do_info_vnc_client(mon, client);
199 1ff7df1a aliguori
                client = client->next;
200 1ff7df1a aliguori
            }
201 1ff7df1a aliguori
        } else {
202 1ff7df1a aliguori
            monitor_printf(mon, "Client: none\n");
203 1ff7df1a aliguori
        }
204 a9ce8590 bellard
    }
205 a9ce8590 bellard
}
206 a9ce8590 bellard
207 29fa4ed9 aliguori
static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
208 29fa4ed9 aliguori
    return (vs->features & (1 << feature));
209 29fa4ed9 aliguori
}
210 29fa4ed9 aliguori
211 24236869 bellard
/* TODO
212 24236869 bellard
   1) Get the queue working for IO.
213 24236869 bellard
   2) there is some weirdness when using the -S option (the screen is grey
214 24236869 bellard
      and not totally invalidated
215 24236869 bellard
   3) resolutions > 1024
216 24236869 bellard
*/
217 24236869 bellard
218 24236869 bellard
static void vnc_update_client(void *opaque);
219 24236869 bellard
220 753b4053 aliguori
static void vnc_colordepth(VncState *vs);
221 7eac3a87 aliguori
222 99589bdc bellard
static inline void vnc_set_bit(uint32_t *d, int k)
223 99589bdc bellard
{
224 99589bdc bellard
    d[k >> 5] |= 1 << (k & 0x1f);
225 99589bdc bellard
}
226 99589bdc bellard
227 99589bdc bellard
static inline void vnc_clear_bit(uint32_t *d, int k)
228 99589bdc bellard
{
229 99589bdc bellard
    d[k >> 5] &= ~(1 << (k & 0x1f));
230 99589bdc bellard
}
231 99589bdc bellard
232 99589bdc bellard
static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
233 99589bdc bellard
{
234 99589bdc bellard
    int j;
235 99589bdc bellard
236 99589bdc bellard
    j = 0;
237 99589bdc bellard
    while (n >= 32) {
238 99589bdc bellard
        d[j++] = -1;
239 99589bdc bellard
        n -= 32;
240 99589bdc bellard
    }
241 5fafdf24 ths
    if (n > 0)
242 99589bdc bellard
        d[j++] = (1 << n) - 1;
243 99589bdc bellard
    while (j < nb_words)
244 99589bdc bellard
        d[j++] = 0;
245 99589bdc bellard
}
246 99589bdc bellard
247 99589bdc bellard
static inline int vnc_get_bit(const uint32_t *d, int k)
248 99589bdc bellard
{
249 99589bdc bellard
    return (d[k >> 5] >> (k & 0x1f)) & 1;
250 99589bdc bellard
}
251 99589bdc bellard
252 5fafdf24 ths
static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
253 99589bdc bellard
                               int nb_words)
254 99589bdc bellard
{
255 99589bdc bellard
    int i;
256 99589bdc bellard
    for(i = 0; i < nb_words; i++) {
257 99589bdc bellard
        if ((d1[i] & d2[i]) != 0)
258 99589bdc bellard
            return 1;
259 99589bdc bellard
    }
260 99589bdc bellard
    return 0;
261 99589bdc bellard
}
262 99589bdc bellard
263 753b4053 aliguori
static void vnc_update(VncState *vs, int x, int y, int w, int h)
264 24236869 bellard
{
265 6baebed7 aliguori
    struct VncSurface *s = &vs->guest;
266 24236869 bellard
    int i;
267 24236869 bellard
268 24236869 bellard
    h += y;
269 24236869 bellard
270 0486e8a7 balrog
    /* round x down to ensure the loop only spans one 16-pixel block per,
271 0486e8a7 balrog
       iteration.  otherwise, if (x % 16) != 0, the last iteration may span
272 0486e8a7 balrog
       two 16-pixel blocks but we only mark the first as dirty
273 0486e8a7 balrog
    */
274 0486e8a7 balrog
    w += (x % 16);
275 0486e8a7 balrog
    x -= (x % 16);
276 0486e8a7 balrog
277 6baebed7 aliguori
    x = MIN(x, s->ds->width);
278 6baebed7 aliguori
    y = MIN(y, s->ds->height);
279 6baebed7 aliguori
    w = MIN(x + w, s->ds->width) - x;
280 6baebed7 aliguori
    h = MIN(h, s->ds->height);
281 788abf8e balrog
282 24236869 bellard
    for (; y < h; y++)
283 28a76be8 aliguori
        for (i = 0; i < w; i += 16)
284 6baebed7 aliguori
            vnc_set_bit(s->dirty[y], (x + i) / 16);
285 24236869 bellard
}
286 24236869 bellard
287 753b4053 aliguori
static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
288 753b4053 aliguori
{
289 753b4053 aliguori
    VncDisplay *vd = ds->opaque;
290 753b4053 aliguori
    VncState *vs = vd->clients;
291 753b4053 aliguori
    while (vs != NULL) {
292 753b4053 aliguori
        vnc_update(vs, x, y, w, h);
293 753b4053 aliguori
        vs = vs->next;
294 753b4053 aliguori
    }
295 753b4053 aliguori
}
296 753b4053 aliguori
297 24236869 bellard
static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
298 28a76be8 aliguori
                                   int32_t encoding)
299 24236869 bellard
{
300 24236869 bellard
    vnc_write_u16(vs, x);
301 24236869 bellard
    vnc_write_u16(vs, y);
302 24236869 bellard
    vnc_write_u16(vs, w);
303 24236869 bellard
    vnc_write_u16(vs, h);
304 24236869 bellard
305 24236869 bellard
    vnc_write_s32(vs, encoding);
306 24236869 bellard
}
307 24236869 bellard
308 2f9606b3 aliguori
void buffer_reserve(Buffer *buffer, size_t len)
309 89064286 aliguori
{
310 89064286 aliguori
    if ((buffer->capacity - buffer->offset) < len) {
311 28a76be8 aliguori
        buffer->capacity += (len + 1024);
312 28a76be8 aliguori
        buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity);
313 28a76be8 aliguori
        if (buffer->buffer == NULL) {
314 28a76be8 aliguori
            fprintf(stderr, "vnc: out of memory\n");
315 28a76be8 aliguori
            exit(1);
316 28a76be8 aliguori
        }
317 89064286 aliguori
    }
318 89064286 aliguori
}
319 89064286 aliguori
320 2f9606b3 aliguori
int buffer_empty(Buffer *buffer)
321 89064286 aliguori
{
322 89064286 aliguori
    return buffer->offset == 0;
323 89064286 aliguori
}
324 89064286 aliguori
325 2f9606b3 aliguori
uint8_t *buffer_end(Buffer *buffer)
326 89064286 aliguori
{
327 89064286 aliguori
    return buffer->buffer + buffer->offset;
328 89064286 aliguori
}
329 89064286 aliguori
330 2f9606b3 aliguori
void buffer_reset(Buffer *buffer)
331 89064286 aliguori
{
332 28a76be8 aliguori
        buffer->offset = 0;
333 89064286 aliguori
}
334 89064286 aliguori
335 2f9606b3 aliguori
void buffer_append(Buffer *buffer, const void *data, size_t len)
336 89064286 aliguori
{
337 89064286 aliguori
    memcpy(buffer->buffer + buffer->offset, data, len);
338 89064286 aliguori
    buffer->offset += len;
339 89064286 aliguori
}
340 89064286 aliguori
341 753b4053 aliguori
static void vnc_resize(VncState *vs)
342 24236869 bellard
{
343 753b4053 aliguori
    DisplayState *ds = vs->ds;
344 73e14b62 ths
    int size_changed;
345 24236869 bellard
346 6baebed7 aliguori
    /* guest surface */
347 6baebed7 aliguori
    if (!vs->guest.ds)
348 6baebed7 aliguori
        vs->guest.ds = qemu_mallocz(sizeof(*vs->guest.ds));
349 6baebed7 aliguori
    if (ds_get_bytes_per_pixel(ds) != vs->guest.ds->pf.bytes_per_pixel)
350 a528b80c balrog
        console_color_init(ds);
351 753b4053 aliguori
    vnc_colordepth(vs);
352 6baebed7 aliguori
    size_changed = ds_get_width(ds) != vs->guest.ds->width ||
353 6baebed7 aliguori
                   ds_get_height(ds) != vs->guest.ds->height;
354 6baebed7 aliguori
    *(vs->guest.ds) = *(ds->surface);
355 b94eb43f balrog
    if (size_changed) {
356 29fa4ed9 aliguori
        if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
357 b94eb43f balrog
            vnc_write_u8(vs, 0);  /* msg id */
358 b94eb43f balrog
            vnc_write_u8(vs, 0);
359 b94eb43f balrog
            vnc_write_u16(vs, 1); /* number of rects */
360 29fa4ed9 aliguori
            vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
361 29fa4ed9 aliguori
                                   VNC_ENCODING_DESKTOPRESIZE);
362 b94eb43f balrog
            vnc_flush(vs);
363 b94eb43f balrog
        }
364 24236869 bellard
    }
365 6baebed7 aliguori
    memset(vs->guest.dirty, 0xFF, sizeof(vs->guest.dirty));
366 8bba5c81 balrog
367 6baebed7 aliguori
    /* server surface */
368 89ee676e Gerd Hoffmann
    if (!vs->server.ds)
369 89ee676e Gerd Hoffmann
        vs->server.ds = qemu_mallocz(sizeof(*vs->server.ds));
370 89ee676e Gerd Hoffmann
    if (vs->server.ds->data)
371 89ee676e Gerd Hoffmann
        qemu_free(vs->server.ds->data);
372 89ee676e Gerd Hoffmann
    *(vs->server.ds) = *(ds->surface);
373 89ee676e Gerd Hoffmann
    vs->server.ds->data = qemu_mallocz(vs->server.ds->linesize *
374 89ee676e Gerd Hoffmann
                                       vs->server.ds->height);
375 6baebed7 aliguori
    memset(vs->server.dirty, 0xFF, sizeof(vs->guest.dirty));
376 24236869 bellard
}
377 24236869 bellard
378 753b4053 aliguori
static void vnc_dpy_resize(DisplayState *ds)
379 753b4053 aliguori
{
380 753b4053 aliguori
    VncDisplay *vd = ds->opaque;
381 753b4053 aliguori
    VncState *vs = vd->clients;
382 753b4053 aliguori
    while (vs != NULL) {
383 753b4053 aliguori
        vnc_resize(vs);
384 753b4053 aliguori
        vs = vs->next;
385 753b4053 aliguori
    }
386 753b4053 aliguori
}
387 753b4053 aliguori
388 3512779a bellard
/* fastest code */
389 3512779a bellard
static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
390 3512779a bellard
{
391 3512779a bellard
    vnc_write(vs, pixels, size);
392 3512779a bellard
}
393 3512779a bellard
394 3512779a bellard
/* slowest but generic code. */
395 3512779a bellard
static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
396 3512779a bellard
{
397 7eac3a87 aliguori
    uint8_t r, g, b;
398 7eac3a87 aliguori
399 6baebed7 aliguori
    r = ((((v & vs->server.ds->pf.rmask) >> vs->server.ds->pf.rshift) << vs->clientds.pf.rbits) >>
400 6baebed7 aliguori
        vs->server.ds->pf.rbits);
401 6baebed7 aliguori
    g = ((((v & vs->server.ds->pf.gmask) >> vs->server.ds->pf.gshift) << vs->clientds.pf.gbits) >>
402 6baebed7 aliguori
        vs->server.ds->pf.gbits);
403 6baebed7 aliguori
    b = ((((v & vs->server.ds->pf.bmask) >> vs->server.ds->pf.bshift) << vs->clientds.pf.bbits) >>
404 6baebed7 aliguori
        vs->server.ds->pf.bbits);
405 6cec5487 aliguori
    v = (r << vs->clientds.pf.rshift) |
406 6cec5487 aliguori
        (g << vs->clientds.pf.gshift) |
407 6cec5487 aliguori
        (b << vs->clientds.pf.bshift);
408 6cec5487 aliguori
    switch(vs->clientds.pf.bytes_per_pixel) {
409 3512779a bellard
    case 1:
410 3512779a bellard
        buf[0] = v;
411 3512779a bellard
        break;
412 3512779a bellard
    case 2:
413 6cec5487 aliguori
        if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) {
414 3512779a bellard
            buf[0] = v >> 8;
415 3512779a bellard
            buf[1] = v;
416 3512779a bellard
        } else {
417 3512779a bellard
            buf[1] = v >> 8;
418 3512779a bellard
            buf[0] = v;
419 3512779a bellard
        }
420 3512779a bellard
        break;
421 3512779a bellard
    default:
422 3512779a bellard
    case 4:
423 6cec5487 aliguori
        if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) {
424 3512779a bellard
            buf[0] = v >> 24;
425 3512779a bellard
            buf[1] = v >> 16;
426 3512779a bellard
            buf[2] = v >> 8;
427 3512779a bellard
            buf[3] = v;
428 3512779a bellard
        } else {
429 3512779a bellard
            buf[3] = v >> 24;
430 3512779a bellard
            buf[2] = v >> 16;
431 3512779a bellard
            buf[1] = v >> 8;
432 3512779a bellard
            buf[0] = v;
433 3512779a bellard
        }
434 3512779a bellard
        break;
435 3512779a bellard
    }
436 3512779a bellard
}
437 3512779a bellard
438 3512779a bellard
static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
439 3512779a bellard
{
440 3512779a bellard
    uint8_t buf[4];
441 3512779a bellard
442 6baebed7 aliguori
    if (vs->server.ds->pf.bytes_per_pixel == 4) {
443 7eac3a87 aliguori
        uint32_t *pixels = pixels1;
444 7eac3a87 aliguori
        int n, i;
445 7eac3a87 aliguori
        n = size >> 2;
446 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
447 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
448 6cec5487 aliguori
            vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
449 7eac3a87 aliguori
        }
450 6baebed7 aliguori
    } else if (vs->server.ds->pf.bytes_per_pixel == 2) {
451 7eac3a87 aliguori
        uint16_t *pixels = pixels1;
452 7eac3a87 aliguori
        int n, i;
453 7eac3a87 aliguori
        n = size >> 1;
454 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
455 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
456 6cec5487 aliguori
            vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
457 7eac3a87 aliguori
        }
458 6baebed7 aliguori
    } else if (vs->server.ds->pf.bytes_per_pixel == 1) {
459 7eac3a87 aliguori
        uint8_t *pixels = pixels1;
460 7eac3a87 aliguori
        int n, i;
461 7eac3a87 aliguori
        n = size;
462 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
463 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
464 6cec5487 aliguori
            vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
465 7eac3a87 aliguori
        }
466 7eac3a87 aliguori
    } else {
467 7eac3a87 aliguori
        fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
468 3512779a bellard
    }
469 3512779a bellard
}
470 3512779a bellard
471 24236869 bellard
static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
472 24236869 bellard
{
473 24236869 bellard
    int i;
474 60fe76f3 ths
    uint8_t *row;
475 24236869 bellard
476 6baebed7 aliguori
    row = vs->server.ds->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
477 24236869 bellard
    for (i = 0; i < h; i++) {
478 28a76be8 aliguori
        vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
479 28a76be8 aliguori
        row += ds_get_linesize(vs->ds);
480 24236869 bellard
    }
481 24236869 bellard
}
482 24236869 bellard
483 24236869 bellard
static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
484 24236869 bellard
{
485 24236869 bellard
    ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
486 24236869 bellard
    ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
487 24236869 bellard
}
488 24236869 bellard
489 24236869 bellard
#define BPP 8
490 24236869 bellard
#include "vnchextile.h"
491 24236869 bellard
#undef BPP
492 24236869 bellard
493 24236869 bellard
#define BPP 16
494 24236869 bellard
#include "vnchextile.h"
495 24236869 bellard
#undef BPP
496 24236869 bellard
497 24236869 bellard
#define BPP 32
498 24236869 bellard
#include "vnchextile.h"
499 24236869 bellard
#undef BPP
500 24236869 bellard
501 3512779a bellard
#define GENERIC
502 7eac3a87 aliguori
#define BPP 8
503 7eac3a87 aliguori
#include "vnchextile.h"
504 7eac3a87 aliguori
#undef BPP
505 7eac3a87 aliguori
#undef GENERIC
506 7eac3a87 aliguori
507 7eac3a87 aliguori
#define GENERIC
508 7eac3a87 aliguori
#define BPP 16
509 7eac3a87 aliguori
#include "vnchextile.h"
510 7eac3a87 aliguori
#undef BPP
511 7eac3a87 aliguori
#undef GENERIC
512 7eac3a87 aliguori
513 7eac3a87 aliguori
#define GENERIC
514 3512779a bellard
#define BPP 32
515 3512779a bellard
#include "vnchextile.h"
516 3512779a bellard
#undef BPP
517 3512779a bellard
#undef GENERIC
518 3512779a bellard
519 24236869 bellard
static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
520 24236869 bellard
{
521 24236869 bellard
    int i, j;
522 24236869 bellard
    int has_fg, has_bg;
523 7eac3a87 aliguori
    uint8_t *last_fg, *last_bg;
524 24236869 bellard
525 6baebed7 aliguori
    last_fg = (uint8_t *) qemu_malloc(vs->server.ds->pf.bytes_per_pixel);
526 6baebed7 aliguori
    last_bg = (uint8_t *) qemu_malloc(vs->server.ds->pf.bytes_per_pixel);
527 24236869 bellard
    has_fg = has_bg = 0;
528 24236869 bellard
    for (j = y; j < (y + h); j += 16) {
529 28a76be8 aliguori
        for (i = x; i < (x + w); i += 16) {
530 5fafdf24 ths
            vs->send_hextile_tile(vs, i, j,
531 3512779a bellard
                                  MIN(16, x + w - i), MIN(16, y + h - j),
532 7eac3a87 aliguori
                                  last_bg, last_fg, &has_bg, &has_fg);
533 28a76be8 aliguori
        }
534 24236869 bellard
    }
535 7eac3a87 aliguori
    free(last_fg);
536 7eac3a87 aliguori
    free(last_bg);
537 7eac3a87 aliguori
538 24236869 bellard
}
539 24236869 bellard
540 059cef40 aliguori
static void vnc_zlib_init(VncState *vs)
541 059cef40 aliguori
{
542 059cef40 aliguori
    int i;
543 059cef40 aliguori
    for (i=0; i<(sizeof(vs->zlib_stream) / sizeof(z_stream)); i++)
544 059cef40 aliguori
        vs->zlib_stream[i].opaque = NULL;
545 059cef40 aliguori
}
546 059cef40 aliguori
547 059cef40 aliguori
static void vnc_zlib_start(VncState *vs)
548 059cef40 aliguori
{
549 059cef40 aliguori
    buffer_reset(&vs->zlib);
550 059cef40 aliguori
551 059cef40 aliguori
    // make the output buffer be the zlib buffer, so we can compress it later
552 059cef40 aliguori
    vs->zlib_tmp = vs->output;
553 059cef40 aliguori
    vs->output = vs->zlib;
554 059cef40 aliguori
}
555 059cef40 aliguori
556 059cef40 aliguori
static int vnc_zlib_stop(VncState *vs, int stream_id)
557 059cef40 aliguori
{
558 059cef40 aliguori
    z_streamp zstream = &vs->zlib_stream[stream_id];
559 059cef40 aliguori
    int previous_out;
560 059cef40 aliguori
561 059cef40 aliguori
    // switch back to normal output/zlib buffers
562 059cef40 aliguori
    vs->zlib = vs->output;
563 059cef40 aliguori
    vs->output = vs->zlib_tmp;
564 059cef40 aliguori
565 059cef40 aliguori
    // compress the zlib buffer
566 059cef40 aliguori
567 059cef40 aliguori
    // initialize the stream
568 059cef40 aliguori
    // XXX need one stream per session
569 059cef40 aliguori
    if (zstream->opaque != vs) {
570 059cef40 aliguori
        int err;
571 059cef40 aliguori
572 059cef40 aliguori
        VNC_DEBUG("VNC: initializing zlib stream %d\n", stream_id);
573 059cef40 aliguori
        VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream->opaque, vs);
574 059cef40 aliguori
        zstream->zalloc = Z_NULL;
575 059cef40 aliguori
        zstream->zfree = Z_NULL;
576 059cef40 aliguori
577 059cef40 aliguori
        err = deflateInit2(zstream, vs->tight_compression, Z_DEFLATED, MAX_WBITS,
578 059cef40 aliguori
                           MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
579 059cef40 aliguori
580 059cef40 aliguori
        if (err != Z_OK) {
581 059cef40 aliguori
            fprintf(stderr, "VNC: error initializing zlib\n");
582 059cef40 aliguori
            return -1;
583 059cef40 aliguori
        }
584 059cef40 aliguori
585 059cef40 aliguori
        zstream->opaque = vs;
586 059cef40 aliguori
    }
587 059cef40 aliguori
588 059cef40 aliguori
    // XXX what to do if tight_compression changed in between?
589 059cef40 aliguori
590 059cef40 aliguori
    // reserve memory in output buffer
591 059cef40 aliguori
    buffer_reserve(&vs->output, vs->zlib.offset + 64);
592 059cef40 aliguori
593 059cef40 aliguori
    // set pointers
594 059cef40 aliguori
    zstream->next_in = vs->zlib.buffer;
595 059cef40 aliguori
    zstream->avail_in = vs->zlib.offset;
596 059cef40 aliguori
    zstream->next_out = vs->output.buffer + vs->output.offset;
597 059cef40 aliguori
    zstream->avail_out = vs->output.capacity - vs->output.offset;
598 059cef40 aliguori
    zstream->data_type = Z_BINARY;
599 059cef40 aliguori
    previous_out = zstream->total_out;
600 059cef40 aliguori
601 059cef40 aliguori
    // start encoding
602 059cef40 aliguori
    if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
603 059cef40 aliguori
        fprintf(stderr, "VNC: error during zlib compression\n");
604 059cef40 aliguori
        return -1;
605 059cef40 aliguori
    }
606 059cef40 aliguori
607 059cef40 aliguori
    vs->output.offset = vs->output.capacity - zstream->avail_out;
608 059cef40 aliguori
    return zstream->total_out - previous_out;
609 059cef40 aliguori
}
610 059cef40 aliguori
611 059cef40 aliguori
static void send_framebuffer_update_zlib(VncState *vs, int x, int y, int w, int h)
612 059cef40 aliguori
{
613 059cef40 aliguori
    int old_offset, new_offset, bytes_written;
614 059cef40 aliguori
615 059cef40 aliguori
    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_ZLIB);
616 059cef40 aliguori
617 059cef40 aliguori
    // remember where we put in the follow-up size
618 059cef40 aliguori
    old_offset = vs->output.offset;
619 059cef40 aliguori
    vnc_write_s32(vs, 0);
620 059cef40 aliguori
621 059cef40 aliguori
    // compress the stream
622 059cef40 aliguori
    vnc_zlib_start(vs);
623 059cef40 aliguori
    send_framebuffer_update_raw(vs, x, y, w, h);
624 059cef40 aliguori
    bytes_written = vnc_zlib_stop(vs, 0);
625 059cef40 aliguori
626 059cef40 aliguori
    if (bytes_written == -1)
627 059cef40 aliguori
        return;
628 059cef40 aliguori
629 059cef40 aliguori
    // hack in the size
630 059cef40 aliguori
    new_offset = vs->output.offset;
631 059cef40 aliguori
    vs->output.offset = old_offset;
632 059cef40 aliguori
    vnc_write_u32(vs, bytes_written);
633 059cef40 aliguori
    vs->output.offset = new_offset;
634 059cef40 aliguori
}
635 059cef40 aliguori
636 24236869 bellard
static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
637 24236869 bellard
{
638 fb437313 aliguori
    switch(vs->vnc_encoding) {
639 28a76be8 aliguori
        case VNC_ENCODING_ZLIB:
640 28a76be8 aliguori
            send_framebuffer_update_zlib(vs, x, y, w, h);
641 28a76be8 aliguori
            break;
642 28a76be8 aliguori
        case VNC_ENCODING_HEXTILE:
643 28a76be8 aliguori
            vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
644 28a76be8 aliguori
            send_framebuffer_update_hextile(vs, x, y, w, h);
645 28a76be8 aliguori
            break;
646 28a76be8 aliguori
        default:
647 28a76be8 aliguori
            vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
648 28a76be8 aliguori
            send_framebuffer_update_raw(vs, x, y, w, h);
649 28a76be8 aliguori
            break;
650 fb437313 aliguori
    }
651 24236869 bellard
}
652 24236869 bellard
653 753b4053 aliguori
static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
654 24236869 bellard
{
655 c522d0e2 aliguori
    vs->force_update = 1;
656 24236869 bellard
    vnc_update_client(vs);
657 24236869 bellard
658 24236869 bellard
    vnc_write_u8(vs, 0);  /* msg id */
659 24236869 bellard
    vnc_write_u8(vs, 0);
660 24236869 bellard
    vnc_write_u16(vs, 1); /* number of rects */
661 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
662 24236869 bellard
    vnc_write_u16(vs, src_x);
663 24236869 bellard
    vnc_write_u16(vs, src_y);
664 24236869 bellard
    vnc_flush(vs);
665 24236869 bellard
}
666 24236869 bellard
667 753b4053 aliguori
static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
668 753b4053 aliguori
{
669 753b4053 aliguori
    VncDisplay *vd = ds->opaque;
670 753b4053 aliguori
    VncState *vs = vd->clients;
671 753b4053 aliguori
    while (vs != NULL) {
672 753b4053 aliguori
        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT))
673 753b4053 aliguori
            vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
674 753b4053 aliguori
        else /* TODO */
675 753b4053 aliguori
            vnc_update(vs, dst_x, dst_y, w, h);
676 753b4053 aliguori
        vs = vs->next;
677 753b4053 aliguori
    }
678 753b4053 aliguori
}
679 753b4053 aliguori
680 6baebed7 aliguori
static int find_and_clear_dirty_height(struct VncSurface *s,
681 6baebed7 aliguori
                                       int y, int last_x, int x)
682 24236869 bellard
{
683 24236869 bellard
    int h;
684 24236869 bellard
685 8563d5b3 Gerd Hoffmann
    for (h = 1; h < (s->ds->height - y); h++) {
686 28a76be8 aliguori
        int tmp_x;
687 6baebed7 aliguori
        if (!vnc_get_bit(s->dirty[y + h], last_x))
688 28a76be8 aliguori
            break;
689 28a76be8 aliguori
        for (tmp_x = last_x; tmp_x < x; tmp_x++)
690 6baebed7 aliguori
            vnc_clear_bit(s->dirty[y + h], tmp_x);
691 24236869 bellard
    }
692 24236869 bellard
693 24236869 bellard
    return h;
694 24236869 bellard
}
695 24236869 bellard
696 24236869 bellard
static void vnc_update_client(void *opaque)
697 24236869 bellard
{
698 24236869 bellard
    VncState *vs = opaque;
699 24236869 bellard
    if (vs->need_update && vs->csock != -1) {
700 28a76be8 aliguori
        int y;
701 6baebed7 aliguori
        uint8_t *guest_row;
702 6baebed7 aliguori
        uint8_t *server_row;
703 bee1b010 Gerd Hoffmann
        int cmp_bytes;
704 28a76be8 aliguori
        uint32_t width_mask[VNC_DIRTY_WORDS];
705 28a76be8 aliguori
        int n_rectangles;
706 28a76be8 aliguori
        int saved_offset;
707 28a76be8 aliguori
        int has_dirty = 0;
708 24236869 bellard
709 c522d0e2 aliguori
        if (vs->output.offset && !vs->audio_cap && !vs->force_update) {
710 c522d0e2 aliguori
            /* kernel send buffers are full -> drop frames to throttle */
711 c522d0e2 aliguori
            qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
712 c522d0e2 aliguori
            return;
713 c522d0e2 aliguori
        }
714 c522d0e2 aliguori
715 a0ecfb73 balrog
        vga_hw_update();
716 a0ecfb73 balrog
717 6baebed7 aliguori
        /*
718 6baebed7 aliguori
         * Walk through the guest dirty map.
719 6baebed7 aliguori
         * Check and copy modified bits from guest to server surface.
720 6baebed7 aliguori
         * Update server dirty map.
721 6baebed7 aliguori
         */
722 6cec5487 aliguori
        vnc_set_bits(width_mask, (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
723 bee1b010 Gerd Hoffmann
        cmp_bytes = 16 * ds_get_bytes_per_pixel(vs->ds);
724 6baebed7 aliguori
        guest_row  = vs->guest.ds->data;
725 6baebed7 aliguori
        server_row = vs->server.ds->data;
726 6baebed7 aliguori
        for (y = 0; y < vs->guest.ds->height; y++) {
727 6baebed7 aliguori
            if (vnc_and_bits(vs->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
728 28a76be8 aliguori
                int x;
729 6baebed7 aliguori
                uint8_t *guest_ptr;
730 6baebed7 aliguori
                uint8_t *server_ptr;
731 6baebed7 aliguori
732 6baebed7 aliguori
                guest_ptr  = guest_row;
733 6baebed7 aliguori
                server_ptr = server_row;
734 6baebed7 aliguori
735 6baebed7 aliguori
                for (x = 0; x < vs->guest.ds->width;
736 6baebed7 aliguori
                     x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
737 6baebed7 aliguori
                    if (!vnc_get_bit(vs->guest.dirty[y], (x / 16)))
738 6baebed7 aliguori
                        continue;
739 6baebed7 aliguori
                    vnc_clear_bit(vs->guest.dirty[y], (x / 16));
740 6baebed7 aliguori
                    if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
741 6baebed7 aliguori
                        continue;
742 6baebed7 aliguori
                    memcpy(server_ptr, guest_ptr, cmp_bytes);
743 6baebed7 aliguori
                    vnc_set_bit(vs->server.dirty[y], (x / 16));
744 6baebed7 aliguori
                    has_dirty++;
745 28a76be8 aliguori
                }
746 28a76be8 aliguori
            }
747 6baebed7 aliguori
            guest_row  += ds_get_linesize(vs->ds);
748 6baebed7 aliguori
            server_row += ds_get_linesize(vs->ds);
749 28a76be8 aliguori
        }
750 28a76be8 aliguori
751 c522d0e2 aliguori
        if (!has_dirty && !vs->audio_cap && !vs->force_update) {
752 28a76be8 aliguori
            qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
753 28a76be8 aliguori
            return;
754 28a76be8 aliguori
        }
755 28a76be8 aliguori
756 6baebed7 aliguori
        /*
757 6baebed7 aliguori
         * Send screen updates to the vnc client using the server
758 6baebed7 aliguori
         * surface and server dirty map.  guest surface updates
759 6baebed7 aliguori
         * happening in parallel don't disturb us, the next pass will
760 6baebed7 aliguori
         * send them to the client.
761 6baebed7 aliguori
         */
762 28a76be8 aliguori
        n_rectangles = 0;
763 28a76be8 aliguori
        vnc_write_u8(vs, 0);  /* msg id */
764 28a76be8 aliguori
        vnc_write_u8(vs, 0);
765 28a76be8 aliguori
        saved_offset = vs->output.offset;
766 28a76be8 aliguori
        vnc_write_u16(vs, 0);
767 28a76be8 aliguori
768 6baebed7 aliguori
        for (y = 0; y < vs->server.ds->height; y++) {
769 28a76be8 aliguori
            int x;
770 28a76be8 aliguori
            int last_x = -1;
771 6baebed7 aliguori
            for (x = 0; x < vs->server.ds->width / 16; x++) {
772 6baebed7 aliguori
                if (vnc_get_bit(vs->server.dirty[y], x)) {
773 28a76be8 aliguori
                    if (last_x == -1) {
774 28a76be8 aliguori
                        last_x = x;
775 28a76be8 aliguori
                    }
776 6baebed7 aliguori
                    vnc_clear_bit(vs->server.dirty[y], x);
777 28a76be8 aliguori
                } else {
778 28a76be8 aliguori
                    if (last_x != -1) {
779 6baebed7 aliguori
                        int h = find_and_clear_dirty_height(&vs->server, y, last_x, x);
780 28a76be8 aliguori
                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
781 28a76be8 aliguori
                        n_rectangles++;
782 28a76be8 aliguori
                    }
783 28a76be8 aliguori
                    last_x = -1;
784 28a76be8 aliguori
                }
785 28a76be8 aliguori
            }
786 28a76be8 aliguori
            if (last_x != -1) {
787 6baebed7 aliguori
                int h = find_and_clear_dirty_height(&vs->server, y, last_x, x);
788 28a76be8 aliguori
                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
789 28a76be8 aliguori
                n_rectangles++;
790 28a76be8 aliguori
            }
791 28a76be8 aliguori
        }
792 28a76be8 aliguori
        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
793 28a76be8 aliguori
        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
794 28a76be8 aliguori
        vnc_flush(vs);
795 c522d0e2 aliguori
        vs->force_update = 0;
796 24236869 bellard
797 24236869 bellard
    }
798 24236869 bellard
799 a0ecfb73 balrog
    if (vs->csock != -1) {
800 a0ecfb73 balrog
        qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
801 24236869 bellard
    }
802 24236869 bellard
803 24236869 bellard
}
804 24236869 bellard
805 429a8ed3 malc
/* audio */
806 429a8ed3 malc
static void audio_capture_notify(void *opaque, audcnotification_e cmd)
807 429a8ed3 malc
{
808 429a8ed3 malc
    VncState *vs = opaque;
809 429a8ed3 malc
810 429a8ed3 malc
    switch (cmd) {
811 429a8ed3 malc
    case AUD_CNOTIFY_DISABLE:
812 429a8ed3 malc
        vnc_write_u8(vs, 255);
813 429a8ed3 malc
        vnc_write_u8(vs, 1);
814 429a8ed3 malc
        vnc_write_u16(vs, 0);
815 429a8ed3 malc
        vnc_flush(vs);
816 429a8ed3 malc
        break;
817 429a8ed3 malc
818 429a8ed3 malc
    case AUD_CNOTIFY_ENABLE:
819 429a8ed3 malc
        vnc_write_u8(vs, 255);
820 429a8ed3 malc
        vnc_write_u8(vs, 1);
821 429a8ed3 malc
        vnc_write_u16(vs, 1);
822 429a8ed3 malc
        vnc_flush(vs);
823 429a8ed3 malc
        break;
824 429a8ed3 malc
    }
825 429a8ed3 malc
}
826 429a8ed3 malc
827 429a8ed3 malc
static void audio_capture_destroy(void *opaque)
828 429a8ed3 malc
{
829 429a8ed3 malc
}
830 429a8ed3 malc
831 429a8ed3 malc
static void audio_capture(void *opaque, void *buf, int size)
832 429a8ed3 malc
{
833 429a8ed3 malc
    VncState *vs = opaque;
834 429a8ed3 malc
835 429a8ed3 malc
    vnc_write_u8(vs, 255);
836 429a8ed3 malc
    vnc_write_u8(vs, 1);
837 429a8ed3 malc
    vnc_write_u16(vs, 2);
838 429a8ed3 malc
    vnc_write_u32(vs, size);
839 429a8ed3 malc
    vnc_write(vs, buf, size);
840 429a8ed3 malc
    vnc_flush(vs);
841 429a8ed3 malc
}
842 429a8ed3 malc
843 429a8ed3 malc
static void audio_add(VncState *vs)
844 429a8ed3 malc
{
845 376253ec aliguori
    Monitor *mon = cur_mon;
846 429a8ed3 malc
    struct audio_capture_ops ops;
847 429a8ed3 malc
848 429a8ed3 malc
    if (vs->audio_cap) {
849 376253ec aliguori
        monitor_printf(mon, "audio already running\n");
850 429a8ed3 malc
        return;
851 429a8ed3 malc
    }
852 429a8ed3 malc
853 429a8ed3 malc
    ops.notify = audio_capture_notify;
854 429a8ed3 malc
    ops.destroy = audio_capture_destroy;
855 429a8ed3 malc
    ops.capture = audio_capture;
856 429a8ed3 malc
857 1a7dafce malc
    vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
858 429a8ed3 malc
    if (!vs->audio_cap) {
859 376253ec aliguori
        monitor_printf(mon, "Failed to add audio capture\n");
860 429a8ed3 malc
    }
861 429a8ed3 malc
}
862 429a8ed3 malc
863 429a8ed3 malc
static void audio_del(VncState *vs)
864 429a8ed3 malc
{
865 429a8ed3 malc
    if (vs->audio_cap) {
866 429a8ed3 malc
        AUD_del_capture(vs->audio_cap, vs);
867 429a8ed3 malc
        vs->audio_cap = NULL;
868 429a8ed3 malc
    }
869 429a8ed3 malc
}
870 429a8ed3 malc
871 2f9606b3 aliguori
872 2f9606b3 aliguori
int vnc_client_io_error(VncState *vs, int ret, int last_errno)
873 24236869 bellard
{
874 24236869 bellard
    if (ret == 0 || ret == -1) {
875 ea01e5fd balrog
        if (ret == -1) {
876 ea01e5fd balrog
            switch (last_errno) {
877 ea01e5fd balrog
                case EINTR:
878 ea01e5fd balrog
                case EAGAIN:
879 ea01e5fd balrog
#ifdef _WIN32
880 ea01e5fd balrog
                case WSAEWOULDBLOCK:
881 ea01e5fd balrog
#endif
882 ea01e5fd balrog
                    return 0;
883 ea01e5fd balrog
                default:
884 ea01e5fd balrog
                    break;
885 ea01e5fd balrog
            }
886 ea01e5fd balrog
        }
887 24236869 bellard
888 28a76be8 aliguori
        VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
889 28a76be8 aliguori
        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
890 28a76be8 aliguori
        closesocket(vs->csock);
891 753b4053 aliguori
        qemu_del_timer(vs->timer);
892 753b4053 aliguori
        qemu_free_timer(vs->timer);
893 753b4053 aliguori
        if (vs->input.buffer) qemu_free(vs->input.buffer);
894 753b4053 aliguori
        if (vs->output.buffer) qemu_free(vs->output.buffer);
895 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
896 28a76be8 aliguori
        vnc_tls_client_cleanup(vs);
897 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
898 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
899 2f9606b3 aliguori
        vnc_sasl_client_cleanup(vs);
900 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
901 429a8ed3 malc
        audio_del(vs);
902 753b4053 aliguori
903 753b4053 aliguori
        VncState *p, *parent = NULL;
904 753b4053 aliguori
        for (p = vs->vd->clients; p != NULL; p = p->next) {
905 753b4053 aliguori
            if (p == vs) {
906 753b4053 aliguori
                if (parent)
907 753b4053 aliguori
                    parent->next = p->next;
908 753b4053 aliguori
                else
909 753b4053 aliguori
                    vs->vd->clients = p->next;
910 753b4053 aliguori
                break;
911 753b4053 aliguori
            }
912 753b4053 aliguori
            parent = p;
913 753b4053 aliguori
        }
914 753b4053 aliguori
        if (!vs->vd->clients)
915 753b4053 aliguori
            dcl->idle = 1;
916 753b4053 aliguori
917 89ee676e Gerd Hoffmann
        qemu_free(vs->server.ds->data);
918 89ee676e Gerd Hoffmann
        qemu_free(vs->server.ds);
919 6baebed7 aliguori
        qemu_free(vs->guest.ds);
920 753b4053 aliguori
        qemu_free(vs);
921 6baebed7 aliguori
922 28a76be8 aliguori
        return 0;
923 24236869 bellard
    }
924 24236869 bellard
    return ret;
925 24236869 bellard
}
926 24236869 bellard
927 5fb6c7a8 aliguori
928 5fb6c7a8 aliguori
void vnc_client_error(VncState *vs)
929 24236869 bellard
{
930 6ca957f0 bellard
    vnc_client_io_error(vs, -1, EINVAL);
931 24236869 bellard
}
932 24236869 bellard
933 2f9606b3 aliguori
934 2f9606b3 aliguori
/*
935 2f9606b3 aliguori
 * Called to write a chunk of data to the client socket. The data may
936 2f9606b3 aliguori
 * be the raw data, or may have already been encoded by SASL.
937 2f9606b3 aliguori
 * The data will be written either straight onto the socket, or
938 2f9606b3 aliguori
 * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled
939 2f9606b3 aliguori
 *
940 2f9606b3 aliguori
 * NB, it is theoretically possible to have 2 layers of encryption,
941 2f9606b3 aliguori
 * both SASL, and this TLS layer. It is highly unlikely in practice
942 2f9606b3 aliguori
 * though, since SASL encryption will typically be a no-op if TLS
943 2f9606b3 aliguori
 * is active
944 2f9606b3 aliguori
 *
945 2f9606b3 aliguori
 * Returns the number of bytes written, which may be less than
946 2f9606b3 aliguori
 * the requested 'datalen' if the socket would block. Returns
947 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
948 2f9606b3 aliguori
 */
949 2f9606b3 aliguori
long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
950 24236869 bellard
{
951 ceb5caaf bellard
    long ret;
952 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
953 5fb6c7a8 aliguori
    if (vs->tls.session) {
954 28a76be8 aliguori
        ret = gnutls_write(vs->tls.session, data, datalen);
955 28a76be8 aliguori
        if (ret < 0) {
956 28a76be8 aliguori
            if (ret == GNUTLS_E_AGAIN)
957 28a76be8 aliguori
                errno = EAGAIN;
958 28a76be8 aliguori
            else
959 28a76be8 aliguori
                errno = EIO;
960 28a76be8 aliguori
            ret = -1;
961 28a76be8 aliguori
        }
962 8d5d2d4c ths
    } else
963 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
964 28a76be8 aliguori
        ret = send(vs->csock, data, datalen, 0);
965 23decc87 aliguori
    VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret);
966 2f9606b3 aliguori
    return vnc_client_io_error(vs, ret, socket_error());
967 2f9606b3 aliguori
}
968 2f9606b3 aliguori
969 2f9606b3 aliguori
970 2f9606b3 aliguori
/*
971 2f9606b3 aliguori
 * Called to write buffered data to the client socket, when not
972 2f9606b3 aliguori
 * using any SASL SSF encryption layers. Will write as much data
973 2f9606b3 aliguori
 * as possible without blocking. If all buffered data is written,
974 2f9606b3 aliguori
 * will switch the FD poll() handler back to read monitoring.
975 2f9606b3 aliguori
 *
976 2f9606b3 aliguori
 * Returns the number of bytes written, which may be less than
977 2f9606b3 aliguori
 * the buffered output data if the socket would block. Returns
978 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
979 2f9606b3 aliguori
 */
980 2f9606b3 aliguori
static long vnc_client_write_plain(VncState *vs)
981 2f9606b3 aliguori
{
982 2f9606b3 aliguori
    long ret;
983 2f9606b3 aliguori
984 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
985 23decc87 aliguori
    VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n",
986 2f9606b3 aliguori
              vs->output.buffer, vs->output.capacity, vs->output.offset,
987 2f9606b3 aliguori
              vs->sasl.waitWriteSSF);
988 2f9606b3 aliguori
989 2f9606b3 aliguori
    if (vs->sasl.conn &&
990 2f9606b3 aliguori
        vs->sasl.runSSF &&
991 2f9606b3 aliguori
        vs->sasl.waitWriteSSF) {
992 2f9606b3 aliguori
        ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF);
993 2f9606b3 aliguori
        if (ret)
994 2f9606b3 aliguori
            vs->sasl.waitWriteSSF -= ret;
995 2f9606b3 aliguori
    } else
996 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
997 2f9606b3 aliguori
        ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset);
998 24236869 bellard
    if (!ret)
999 2f9606b3 aliguori
        return 0;
1000 24236869 bellard
1001 24236869 bellard
    memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
1002 24236869 bellard
    vs->output.offset -= ret;
1003 24236869 bellard
1004 24236869 bellard
    if (vs->output.offset == 0) {
1005 28a76be8 aliguori
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
1006 24236869 bellard
    }
1007 2f9606b3 aliguori
1008 2f9606b3 aliguori
    return ret;
1009 2f9606b3 aliguori
}
1010 2f9606b3 aliguori
1011 2f9606b3 aliguori
1012 2f9606b3 aliguori
/*
1013 2f9606b3 aliguori
 * First function called whenever there is data to be written to
1014 2f9606b3 aliguori
 * the client socket. Will delegate actual work according to whether
1015 2f9606b3 aliguori
 * SASL SSF layers are enabled (thus requiring encryption calls)
1016 2f9606b3 aliguori
 */
1017 2f9606b3 aliguori
void vnc_client_write(void *opaque)
1018 2f9606b3 aliguori
{
1019 2f9606b3 aliguori
    long ret;
1020 2f9606b3 aliguori
    VncState *vs = opaque;
1021 2f9606b3 aliguori
1022 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1023 2f9606b3 aliguori
    if (vs->sasl.conn &&
1024 2f9606b3 aliguori
        vs->sasl.runSSF &&
1025 2f9606b3 aliguori
        !vs->sasl.waitWriteSSF)
1026 2f9606b3 aliguori
        ret = vnc_client_write_sasl(vs);
1027 2f9606b3 aliguori
    else
1028 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1029 2f9606b3 aliguori
        ret = vnc_client_write_plain(vs);
1030 24236869 bellard
}
1031 24236869 bellard
1032 5fb6c7a8 aliguori
void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
1033 24236869 bellard
{
1034 24236869 bellard
    vs->read_handler = func;
1035 24236869 bellard
    vs->read_handler_expect = expecting;
1036 24236869 bellard
}
1037 24236869 bellard
1038 2f9606b3 aliguori
1039 2f9606b3 aliguori
/*
1040 2f9606b3 aliguori
 * Called to read a chunk of data from the client socket. The data may
1041 2f9606b3 aliguori
 * be the raw data, or may need to be further decoded by SASL.
1042 2f9606b3 aliguori
 * The data will be read either straight from to the socket, or
1043 2f9606b3 aliguori
 * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1044 2f9606b3 aliguori
 *
1045 2f9606b3 aliguori
 * NB, it is theoretically possible to have 2 layers of encryption,
1046 2f9606b3 aliguori
 * both SASL, and this TLS layer. It is highly unlikely in practice
1047 2f9606b3 aliguori
 * though, since SASL encryption will typically be a no-op if TLS
1048 2f9606b3 aliguori
 * is active
1049 2f9606b3 aliguori
 *
1050 2f9606b3 aliguori
 * Returns the number of bytes read, which may be less than
1051 2f9606b3 aliguori
 * the requested 'datalen' if the socket would block. Returns
1052 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
1053 2f9606b3 aliguori
 */
1054 2f9606b3 aliguori
long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
1055 24236869 bellard
{
1056 ceb5caaf bellard
    long ret;
1057 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
1058 5fb6c7a8 aliguori
    if (vs->tls.session) {
1059 28a76be8 aliguori
        ret = gnutls_read(vs->tls.session, data, datalen);
1060 28a76be8 aliguori
        if (ret < 0) {
1061 28a76be8 aliguori
            if (ret == GNUTLS_E_AGAIN)
1062 28a76be8 aliguori
                errno = EAGAIN;
1063 28a76be8 aliguori
            else
1064 28a76be8 aliguori
                errno = EIO;
1065 28a76be8 aliguori
            ret = -1;
1066 28a76be8 aliguori
        }
1067 8d5d2d4c ths
    } else
1068 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
1069 28a76be8 aliguori
        ret = recv(vs->csock, data, datalen, 0);
1070 23decc87 aliguori
    VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret);
1071 2f9606b3 aliguori
    return vnc_client_io_error(vs, ret, socket_error());
1072 2f9606b3 aliguori
}
1073 24236869 bellard
1074 2f9606b3 aliguori
1075 2f9606b3 aliguori
/*
1076 2f9606b3 aliguori
 * Called to read data from the client socket to the input buffer,
1077 2f9606b3 aliguori
 * when not using any SASL SSF encryption layers. Will read as much
1078 2f9606b3 aliguori
 * data as possible without blocking.
1079 2f9606b3 aliguori
 *
1080 2f9606b3 aliguori
 * Returns the number of bytes read. Returns -1 on error, and
1081 2f9606b3 aliguori
 * disconnects the client socket.
1082 2f9606b3 aliguori
 */
1083 2f9606b3 aliguori
static long vnc_client_read_plain(VncState *vs)
1084 2f9606b3 aliguori
{
1085 2f9606b3 aliguori
    int ret;
1086 23decc87 aliguori
    VNC_DEBUG("Read plain %p size %zd offset %zd\n",
1087 2f9606b3 aliguori
              vs->input.buffer, vs->input.capacity, vs->input.offset);
1088 2f9606b3 aliguori
    buffer_reserve(&vs->input, 4096);
1089 2f9606b3 aliguori
    ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096);
1090 2f9606b3 aliguori
    if (!ret)
1091 2f9606b3 aliguori
        return 0;
1092 24236869 bellard
    vs->input.offset += ret;
1093 2f9606b3 aliguori
    return ret;
1094 2f9606b3 aliguori
}
1095 2f9606b3 aliguori
1096 2f9606b3 aliguori
1097 2f9606b3 aliguori
/*
1098 2f9606b3 aliguori
 * First function called whenever there is more data to be read from
1099 2f9606b3 aliguori
 * the client socket. Will delegate actual work according to whether
1100 2f9606b3 aliguori
 * SASL SSF layers are enabled (thus requiring decryption calls)
1101 2f9606b3 aliguori
 */
1102 2f9606b3 aliguori
void vnc_client_read(void *opaque)
1103 2f9606b3 aliguori
{
1104 2f9606b3 aliguori
    VncState *vs = opaque;
1105 2f9606b3 aliguori
    long ret;
1106 2f9606b3 aliguori
1107 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1108 2f9606b3 aliguori
    if (vs->sasl.conn && vs->sasl.runSSF)
1109 2f9606b3 aliguori
        ret = vnc_client_read_sasl(vs);
1110 2f9606b3 aliguori
    else
1111 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1112 2f9606b3 aliguori
        ret = vnc_client_read_plain(vs);
1113 2f9606b3 aliguori
    if (!ret)
1114 28a76be8 aliguori
        return;
1115 24236869 bellard
1116 24236869 bellard
    while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
1117 28a76be8 aliguori
        size_t len = vs->read_handler_expect;
1118 28a76be8 aliguori
        int ret;
1119 28a76be8 aliguori
1120 28a76be8 aliguori
        ret = vs->read_handler(vs, vs->input.buffer, len);
1121 28a76be8 aliguori
        if (vs->csock == -1)
1122 28a76be8 aliguori
            return;
1123 28a76be8 aliguori
1124 28a76be8 aliguori
        if (!ret) {
1125 28a76be8 aliguori
            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
1126 28a76be8 aliguori
            vs->input.offset -= len;
1127 28a76be8 aliguori
        } else {
1128 28a76be8 aliguori
            vs->read_handler_expect = ret;
1129 28a76be8 aliguori
        }
1130 24236869 bellard
    }
1131 24236869 bellard
}
1132 24236869 bellard
1133 5fb6c7a8 aliguori
void vnc_write(VncState *vs, const void *data, size_t len)
1134 24236869 bellard
{
1135 24236869 bellard
    buffer_reserve(&vs->output, len);
1136 24236869 bellard
1137 24236869 bellard
    if (buffer_empty(&vs->output)) {
1138 28a76be8 aliguori
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1139 24236869 bellard
    }
1140 24236869 bellard
1141 24236869 bellard
    buffer_append(&vs->output, data, len);
1142 24236869 bellard
}
1143 24236869 bellard
1144 5fb6c7a8 aliguori
void vnc_write_s32(VncState *vs, int32_t value)
1145 24236869 bellard
{
1146 24236869 bellard
    vnc_write_u32(vs, *(uint32_t *)&value);
1147 24236869 bellard
}
1148 24236869 bellard
1149 5fb6c7a8 aliguori
void vnc_write_u32(VncState *vs, uint32_t value)
1150 24236869 bellard
{
1151 24236869 bellard
    uint8_t buf[4];
1152 24236869 bellard
1153 24236869 bellard
    buf[0] = (value >> 24) & 0xFF;
1154 24236869 bellard
    buf[1] = (value >> 16) & 0xFF;
1155 24236869 bellard
    buf[2] = (value >>  8) & 0xFF;
1156 24236869 bellard
    buf[3] = value & 0xFF;
1157 24236869 bellard
1158 24236869 bellard
    vnc_write(vs, buf, 4);
1159 24236869 bellard
}
1160 24236869 bellard
1161 5fb6c7a8 aliguori
void vnc_write_u16(VncState *vs, uint16_t value)
1162 24236869 bellard
{
1163 64f5a135 bellard
    uint8_t buf[2];
1164 24236869 bellard
1165 24236869 bellard
    buf[0] = (value >> 8) & 0xFF;
1166 24236869 bellard
    buf[1] = value & 0xFF;
1167 24236869 bellard
1168 24236869 bellard
    vnc_write(vs, buf, 2);
1169 24236869 bellard
}
1170 24236869 bellard
1171 5fb6c7a8 aliguori
void vnc_write_u8(VncState *vs, uint8_t value)
1172 24236869 bellard
{
1173 24236869 bellard
    vnc_write(vs, (char *)&value, 1);
1174 24236869 bellard
}
1175 24236869 bellard
1176 5fb6c7a8 aliguori
void vnc_flush(VncState *vs)
1177 24236869 bellard
{
1178 24236869 bellard
    if (vs->output.offset)
1179 28a76be8 aliguori
        vnc_client_write(vs);
1180 24236869 bellard
}
1181 24236869 bellard
1182 5fb6c7a8 aliguori
uint8_t read_u8(uint8_t *data, size_t offset)
1183 24236869 bellard
{
1184 24236869 bellard
    return data[offset];
1185 24236869 bellard
}
1186 24236869 bellard
1187 5fb6c7a8 aliguori
uint16_t read_u16(uint8_t *data, size_t offset)
1188 24236869 bellard
{
1189 24236869 bellard
    return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
1190 24236869 bellard
}
1191 24236869 bellard
1192 5fb6c7a8 aliguori
int32_t read_s32(uint8_t *data, size_t offset)
1193 24236869 bellard
{
1194 24236869 bellard
    return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
1195 28a76be8 aliguori
                     (data[offset + 2] << 8) | data[offset + 3]);
1196 24236869 bellard
}
1197 24236869 bellard
1198 5fb6c7a8 aliguori
uint32_t read_u32(uint8_t *data, size_t offset)
1199 24236869 bellard
{
1200 24236869 bellard
    return ((data[offset] << 24) | (data[offset + 1] << 16) |
1201 28a76be8 aliguori
            (data[offset + 2] << 8) | data[offset + 3]);
1202 24236869 bellard
}
1203 24236869 bellard
1204 60fe76f3 ths
static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
1205 24236869 bellard
{
1206 24236869 bellard
}
1207 24236869 bellard
1208 564c337e bellard
static void check_pointer_type_change(VncState *vs, int absolute)
1209 564c337e bellard
{
1210 29fa4ed9 aliguori
    if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) {
1211 28a76be8 aliguori
        vnc_write_u8(vs, 0);
1212 28a76be8 aliguori
        vnc_write_u8(vs, 0);
1213 28a76be8 aliguori
        vnc_write_u16(vs, 1);
1214 28a76be8 aliguori
        vnc_framebuffer_update(vs, absolute, 0,
1215 28a76be8 aliguori
                               ds_get_width(vs->ds), ds_get_height(vs->ds),
1216 29fa4ed9 aliguori
                               VNC_ENCODING_POINTER_TYPE_CHANGE);
1217 28a76be8 aliguori
        vnc_flush(vs);
1218 564c337e bellard
    }
1219 564c337e bellard
    vs->absolute = absolute;
1220 564c337e bellard
}
1221 564c337e bellard
1222 24236869 bellard
static void pointer_event(VncState *vs, int button_mask, int x, int y)
1223 24236869 bellard
{
1224 24236869 bellard
    int buttons = 0;
1225 24236869 bellard
    int dz = 0;
1226 24236869 bellard
1227 24236869 bellard
    if (button_mask & 0x01)
1228 28a76be8 aliguori
        buttons |= MOUSE_EVENT_LBUTTON;
1229 24236869 bellard
    if (button_mask & 0x02)
1230 28a76be8 aliguori
        buttons |= MOUSE_EVENT_MBUTTON;
1231 24236869 bellard
    if (button_mask & 0x04)
1232 28a76be8 aliguori
        buttons |= MOUSE_EVENT_RBUTTON;
1233 24236869 bellard
    if (button_mask & 0x08)
1234 28a76be8 aliguori
        dz = -1;
1235 24236869 bellard
    if (button_mask & 0x10)
1236 28a76be8 aliguori
        dz = 1;
1237 564c337e bellard
1238 564c337e bellard
    if (vs->absolute) {
1239 28a76be8 aliguori
        kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1),
1240 28a76be8 aliguori
                        y * 0x7FFF / (ds_get_height(vs->ds) - 1),
1241 28a76be8 aliguori
                        dz, buttons);
1242 29fa4ed9 aliguori
    } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
1243 28a76be8 aliguori
        x -= 0x7FFF;
1244 28a76be8 aliguori
        y -= 0x7FFF;
1245 24236869 bellard
1246 28a76be8 aliguori
        kbd_mouse_event(x, y, dz, buttons);
1247 564c337e bellard
    } else {
1248 28a76be8 aliguori
        if (vs->last_x != -1)
1249 28a76be8 aliguori
            kbd_mouse_event(x - vs->last_x,
1250 28a76be8 aliguori
                            y - vs->last_y,
1251 28a76be8 aliguori
                            dz, buttons);
1252 28a76be8 aliguori
        vs->last_x = x;
1253 28a76be8 aliguori
        vs->last_y = y;
1254 24236869 bellard
    }
1255 564c337e bellard
1256 564c337e bellard
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
1257 24236869 bellard
}
1258 24236869 bellard
1259 64f5a135 bellard
static void reset_keys(VncState *vs)
1260 64f5a135 bellard
{
1261 64f5a135 bellard
    int i;
1262 64f5a135 bellard
    for(i = 0; i < 256; i++) {
1263 64f5a135 bellard
        if (vs->modifiers_state[i]) {
1264 64f5a135 bellard
            if (i & 0x80)
1265 64f5a135 bellard
                kbd_put_keycode(0xe0);
1266 64f5a135 bellard
            kbd_put_keycode(i | 0x80);
1267 64f5a135 bellard
            vs->modifiers_state[i] = 0;
1268 64f5a135 bellard
        }
1269 64f5a135 bellard
    }
1270 64f5a135 bellard
}
1271 64f5a135 bellard
1272 a528b80c balrog
static void press_key(VncState *vs, int keysym)
1273 a528b80c balrog
{
1274 753b4053 aliguori
    kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) & 0x7f);
1275 753b4053 aliguori
    kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) | 0x80);
1276 a528b80c balrog
}
1277 a528b80c balrog
1278 9ca313aa aliguori
static void do_key_event(VncState *vs, int down, int keycode, int sym)
1279 24236869 bellard
{
1280 64f5a135 bellard
    /* QEMU console switch */
1281 64f5a135 bellard
    switch(keycode) {
1282 64f5a135 bellard
    case 0x2a:                          /* Left Shift */
1283 64f5a135 bellard
    case 0x36:                          /* Right Shift */
1284 64f5a135 bellard
    case 0x1d:                          /* Left CTRL */
1285 64f5a135 bellard
    case 0x9d:                          /* Right CTRL */
1286 64f5a135 bellard
    case 0x38:                          /* Left ALT */
1287 64f5a135 bellard
    case 0xb8:                          /* Right ALT */
1288 64f5a135 bellard
        if (down)
1289 64f5a135 bellard
            vs->modifiers_state[keycode] = 1;
1290 64f5a135 bellard
        else
1291 64f5a135 bellard
            vs->modifiers_state[keycode] = 0;
1292 64f5a135 bellard
        break;
1293 5fafdf24 ths
    case 0x02 ... 0x0a: /* '1' to '9' keys */
1294 64f5a135 bellard
        if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1295 64f5a135 bellard
            /* Reset the modifiers sent to the current console */
1296 64f5a135 bellard
            reset_keys(vs);
1297 64f5a135 bellard
            console_select(keycode - 0x02);
1298 64f5a135 bellard
            return;
1299 64f5a135 bellard
        }
1300 64f5a135 bellard
        break;
1301 28a76be8 aliguori
    case 0x3a:                        /* CapsLock */
1302 28a76be8 aliguori
    case 0x45:                        /* NumLock */
1303 a528b80c balrog
        if (!down)
1304 a528b80c balrog
            vs->modifiers_state[keycode] ^= 1;
1305 a528b80c balrog
        break;
1306 a528b80c balrog
    }
1307 a528b80c balrog
1308 753b4053 aliguori
    if (keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
1309 a528b80c balrog
        /* If the numlock state needs to change then simulate an additional
1310 a528b80c balrog
           keypress before sending this one.  This will happen if the user
1311 a528b80c balrog
           toggles numlock away from the VNC window.
1312 a528b80c balrog
        */
1313 753b4053 aliguori
        if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
1314 a528b80c balrog
            if (!vs->modifiers_state[0x45]) {
1315 a528b80c balrog
                vs->modifiers_state[0x45] = 1;
1316 a528b80c balrog
                press_key(vs, 0xff7f);
1317 a528b80c balrog
            }
1318 a528b80c balrog
        } else {
1319 a528b80c balrog
            if (vs->modifiers_state[0x45]) {
1320 a528b80c balrog
                vs->modifiers_state[0x45] = 0;
1321 a528b80c balrog
                press_key(vs, 0xff7f);
1322 a528b80c balrog
            }
1323 a528b80c balrog
        }
1324 64f5a135 bellard
    }
1325 24236869 bellard
1326 64f5a135 bellard
    if (is_graphic_console()) {
1327 64f5a135 bellard
        if (keycode & 0x80)
1328 64f5a135 bellard
            kbd_put_keycode(0xe0);
1329 64f5a135 bellard
        if (down)
1330 64f5a135 bellard
            kbd_put_keycode(keycode & 0x7f);
1331 64f5a135 bellard
        else
1332 64f5a135 bellard
            kbd_put_keycode(keycode | 0x80);
1333 64f5a135 bellard
    } else {
1334 64f5a135 bellard
        /* QEMU console emulation */
1335 64f5a135 bellard
        if (down) {
1336 64f5a135 bellard
            switch (keycode) {
1337 64f5a135 bellard
            case 0x2a:                          /* Left Shift */
1338 64f5a135 bellard
            case 0x36:                          /* Right Shift */
1339 64f5a135 bellard
            case 0x1d:                          /* Left CTRL */
1340 64f5a135 bellard
            case 0x9d:                          /* Right CTRL */
1341 64f5a135 bellard
            case 0x38:                          /* Left ALT */
1342 64f5a135 bellard
            case 0xb8:                          /* Right ALT */
1343 64f5a135 bellard
                break;
1344 64f5a135 bellard
            case 0xc8:
1345 0fc8e0ec Gerd Hoffmann
            case 0x48:
1346 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_UP);
1347 64f5a135 bellard
                break;
1348 64f5a135 bellard
            case 0xd0:
1349 0fc8e0ec Gerd Hoffmann
            case 0x50:
1350 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DOWN);
1351 64f5a135 bellard
                break;
1352 64f5a135 bellard
            case 0xcb:
1353 0fc8e0ec Gerd Hoffmann
            case 0x4b:
1354 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_LEFT);
1355 64f5a135 bellard
                break;
1356 64f5a135 bellard
            case 0xcd:
1357 0fc8e0ec Gerd Hoffmann
            case 0x4d:
1358 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_RIGHT);
1359 64f5a135 bellard
                break;
1360 64f5a135 bellard
            case 0xd3:
1361 0fc8e0ec Gerd Hoffmann
            case 0x53:
1362 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DELETE);
1363 64f5a135 bellard
                break;
1364 64f5a135 bellard
            case 0xc7:
1365 0fc8e0ec Gerd Hoffmann
            case 0x47:
1366 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_HOME);
1367 64f5a135 bellard
                break;
1368 64f5a135 bellard
            case 0xcf:
1369 0fc8e0ec Gerd Hoffmann
            case 0x4f:
1370 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_END);
1371 64f5a135 bellard
                break;
1372 64f5a135 bellard
            case 0xc9:
1373 0fc8e0ec Gerd Hoffmann
            case 0x49:
1374 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEUP);
1375 64f5a135 bellard
                break;
1376 64f5a135 bellard
            case 0xd1:
1377 0fc8e0ec Gerd Hoffmann
            case 0x51:
1378 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1379 64f5a135 bellard
                break;
1380 64f5a135 bellard
            default:
1381 64f5a135 bellard
                kbd_put_keysym(sym);
1382 64f5a135 bellard
                break;
1383 64f5a135 bellard
            }
1384 64f5a135 bellard
        }
1385 64f5a135 bellard
    }
1386 24236869 bellard
}
1387 24236869 bellard
1388 bdbd7676 bellard
static void key_event(VncState *vs, int down, uint32_t sym)
1389 bdbd7676 bellard
{
1390 9ca313aa aliguori
    int keycode;
1391 9ca313aa aliguori
1392 a528b80c balrog
    if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
1393 28a76be8 aliguori
        sym = sym - 'A' + 'a';
1394 9ca313aa aliguori
1395 753b4053 aliguori
    keycode = keysym2scancode(vs->vd->kbd_layout, sym & 0xFFFF);
1396 9ca313aa aliguori
    do_key_event(vs, down, keycode, sym);
1397 9ca313aa aliguori
}
1398 9ca313aa aliguori
1399 9ca313aa aliguori
static void ext_key_event(VncState *vs, int down,
1400 9ca313aa aliguori
                          uint32_t sym, uint16_t keycode)
1401 9ca313aa aliguori
{
1402 9ca313aa aliguori
    /* if the user specifies a keyboard layout, always use it */
1403 9ca313aa aliguori
    if (keyboard_layout)
1404 9ca313aa aliguori
        key_event(vs, down, sym);
1405 9ca313aa aliguori
    else
1406 9ca313aa aliguori
        do_key_event(vs, down, keycode, sym);
1407 bdbd7676 bellard
}
1408 bdbd7676 bellard
1409 24236869 bellard
static void framebuffer_update_request(VncState *vs, int incremental,
1410 28a76be8 aliguori
                                       int x_position, int y_position,
1411 28a76be8 aliguori
                                       int w, int h)
1412 24236869 bellard
{
1413 0e1f5a0c aliguori
    if (x_position > ds_get_width(vs->ds))
1414 0e1f5a0c aliguori
        x_position = ds_get_width(vs->ds);
1415 0e1f5a0c aliguori
    if (y_position > ds_get_height(vs->ds))
1416 0e1f5a0c aliguori
        y_position = ds_get_height(vs->ds);
1417 0e1f5a0c aliguori
    if (x_position + w >= ds_get_width(vs->ds))
1418 0e1f5a0c aliguori
        w = ds_get_width(vs->ds)  - x_position;
1419 0e1f5a0c aliguori
    if (y_position + h >= ds_get_height(vs->ds))
1420 0e1f5a0c aliguori
        h = ds_get_height(vs->ds) - y_position;
1421 cf2d385c ths
1422 24236869 bellard
    int i;
1423 24236869 bellard
    vs->need_update = 1;
1424 24236869 bellard
    if (!incremental) {
1425 24cf0a6e Gerd Hoffmann
        vs->force_update = 1;
1426 28a76be8 aliguori
        for (i = 0; i < h; i++) {
1427 6baebed7 aliguori
            vnc_set_bits(vs->guest.dirty[y_position + i],
1428 6baebed7 aliguori
                         (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1429 6baebed7 aliguori
            vnc_set_bits(vs->server.dirty[y_position + i],
1430 0e1f5a0c aliguori
                         (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1431 28a76be8 aliguori
        }
1432 24236869 bellard
    }
1433 24236869 bellard
}
1434 24236869 bellard
1435 9ca313aa aliguori
static void send_ext_key_event_ack(VncState *vs)
1436 9ca313aa aliguori
{
1437 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1438 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1439 9ca313aa aliguori
    vnc_write_u16(vs, 1);
1440 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1441 29fa4ed9 aliguori
                           VNC_ENCODING_EXT_KEY_EVENT);
1442 9ca313aa aliguori
    vnc_flush(vs);
1443 9ca313aa aliguori
}
1444 9ca313aa aliguori
1445 429a8ed3 malc
static void send_ext_audio_ack(VncState *vs)
1446 429a8ed3 malc
{
1447 429a8ed3 malc
    vnc_write_u8(vs, 0);
1448 429a8ed3 malc
    vnc_write_u8(vs, 0);
1449 429a8ed3 malc
    vnc_write_u16(vs, 1);
1450 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1451 29fa4ed9 aliguori
                           VNC_ENCODING_AUDIO);
1452 429a8ed3 malc
    vnc_flush(vs);
1453 429a8ed3 malc
}
1454 429a8ed3 malc
1455 24236869 bellard
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1456 24236869 bellard
{
1457 24236869 bellard
    int i;
1458 29fa4ed9 aliguori
    unsigned int enc = 0;
1459 24236869 bellard
1460 059cef40 aliguori
    vnc_zlib_init(vs);
1461 29fa4ed9 aliguori
    vs->features = 0;
1462 fb437313 aliguori
    vs->vnc_encoding = 0;
1463 fb437313 aliguori
    vs->tight_compression = 9;
1464 fb437313 aliguori
    vs->tight_quality = 9;
1465 564c337e bellard
    vs->absolute = -1;
1466 24236869 bellard
1467 24236869 bellard
    for (i = n_encodings - 1; i >= 0; i--) {
1468 29fa4ed9 aliguori
        enc = encodings[i];
1469 29fa4ed9 aliguori
        switch (enc) {
1470 29fa4ed9 aliguori
        case VNC_ENCODING_RAW:
1471 fb437313 aliguori
            vs->vnc_encoding = enc;
1472 29fa4ed9 aliguori
            break;
1473 29fa4ed9 aliguori
        case VNC_ENCODING_COPYRECT:
1474 753b4053 aliguori
            vs->features |= VNC_FEATURE_COPYRECT_MASK;
1475 29fa4ed9 aliguori
            break;
1476 29fa4ed9 aliguori
        case VNC_ENCODING_HEXTILE:
1477 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_HEXTILE_MASK;
1478 fb437313 aliguori
            vs->vnc_encoding = enc;
1479 29fa4ed9 aliguori
            break;
1480 059cef40 aliguori
        case VNC_ENCODING_ZLIB:
1481 059cef40 aliguori
            vs->features |= VNC_FEATURE_ZLIB_MASK;
1482 059cef40 aliguori
            vs->vnc_encoding = enc;
1483 059cef40 aliguori
            break;
1484 29fa4ed9 aliguori
        case VNC_ENCODING_DESKTOPRESIZE:
1485 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_RESIZE_MASK;
1486 29fa4ed9 aliguori
            break;
1487 29fa4ed9 aliguori
        case VNC_ENCODING_POINTER_TYPE_CHANGE:
1488 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
1489 29fa4ed9 aliguori
            break;
1490 29fa4ed9 aliguori
        case VNC_ENCODING_EXT_KEY_EVENT:
1491 9ca313aa aliguori
            send_ext_key_event_ack(vs);
1492 9ca313aa aliguori
            break;
1493 29fa4ed9 aliguori
        case VNC_ENCODING_AUDIO:
1494 429a8ed3 malc
            send_ext_audio_ack(vs);
1495 429a8ed3 malc
            break;
1496 29fa4ed9 aliguori
        case VNC_ENCODING_WMVi:
1497 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_WMVI_MASK;
1498 ca4cca4d aliguori
            break;
1499 fb437313 aliguori
        case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
1500 fb437313 aliguori
            vs->tight_compression = (enc & 0x0F);
1501 fb437313 aliguori
            break;
1502 fb437313 aliguori
        case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
1503 fb437313 aliguori
            vs->tight_quality = (enc & 0x0F);
1504 fb437313 aliguori
            break;
1505 29fa4ed9 aliguori
        default:
1506 29fa4ed9 aliguori
            VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
1507 29fa4ed9 aliguori
            break;
1508 29fa4ed9 aliguori
        }
1509 24236869 bellard
    }
1510 564c337e bellard
1511 564c337e bellard
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
1512 24236869 bellard
}
1513 24236869 bellard
1514 6cec5487 aliguori
static void set_pixel_conversion(VncState *vs)
1515 6cec5487 aliguori
{
1516 6cec5487 aliguori
    if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
1517 6cec5487 aliguori
        (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && 
1518 6cec5487 aliguori
        !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
1519 6cec5487 aliguori
        vs->write_pixels = vnc_write_pixels_copy;
1520 6cec5487 aliguori
        switch (vs->ds->surface->pf.bits_per_pixel) {
1521 6cec5487 aliguori
            case 8:
1522 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_8;
1523 6cec5487 aliguori
                break;
1524 6cec5487 aliguori
            case 16:
1525 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_16;
1526 6cec5487 aliguori
                break;
1527 6cec5487 aliguori
            case 32:
1528 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_32;
1529 6cec5487 aliguori
                break;
1530 6cec5487 aliguori
        }
1531 6cec5487 aliguori
    } else {
1532 6cec5487 aliguori
        vs->write_pixels = vnc_write_pixels_generic;
1533 6cec5487 aliguori
        switch (vs->ds->surface->pf.bits_per_pixel) {
1534 6cec5487 aliguori
            case 8:
1535 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_8;
1536 6cec5487 aliguori
                break;
1537 6cec5487 aliguori
            case 16:
1538 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_16;
1539 6cec5487 aliguori
                break;
1540 6cec5487 aliguori
            case 32:
1541 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_32;
1542 6cec5487 aliguori
                break;
1543 6cec5487 aliguori
        }
1544 6cec5487 aliguori
    }
1545 6cec5487 aliguori
}
1546 6cec5487 aliguori
1547 24236869 bellard
static void set_pixel_format(VncState *vs,
1548 28a76be8 aliguori
                             int bits_per_pixel, int depth,
1549 28a76be8 aliguori
                             int big_endian_flag, int true_color_flag,
1550 28a76be8 aliguori
                             int red_max, int green_max, int blue_max,
1551 28a76be8 aliguori
                             int red_shift, int green_shift, int blue_shift)
1552 24236869 bellard
{
1553 3512779a bellard
    if (!true_color_flag) {
1554 28a76be8 aliguori
        vnc_client_error(vs);
1555 3512779a bellard
        return;
1556 3512779a bellard
    }
1557 24236869 bellard
1558 6baebed7 aliguori
    vs->clientds = *(vs->guest.ds);
1559 6cec5487 aliguori
    vs->clientds.pf.rmax = red_max;
1560 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.rbits, red_max);
1561 6cec5487 aliguori
    vs->clientds.pf.rshift = red_shift;
1562 6cec5487 aliguori
    vs->clientds.pf.rmask = red_max << red_shift;
1563 6cec5487 aliguori
    vs->clientds.pf.gmax = green_max;
1564 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.gbits, green_max);
1565 6cec5487 aliguori
    vs->clientds.pf.gshift = green_shift;
1566 6cec5487 aliguori
    vs->clientds.pf.gmask = green_max << green_shift;
1567 6cec5487 aliguori
    vs->clientds.pf.bmax = blue_max;
1568 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.bbits, blue_max);
1569 6cec5487 aliguori
    vs->clientds.pf.bshift = blue_shift;
1570 6cec5487 aliguori
    vs->clientds.pf.bmask = blue_max << blue_shift;
1571 6cec5487 aliguori
    vs->clientds.pf.bits_per_pixel = bits_per_pixel;
1572 6cec5487 aliguori
    vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8;
1573 6cec5487 aliguori
    vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
1574 6cec5487 aliguori
    vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00;
1575 6cec5487 aliguori
1576 6cec5487 aliguori
    set_pixel_conversion(vs);
1577 24236869 bellard
1578 24236869 bellard
    vga_hw_invalidate();
1579 24236869 bellard
    vga_hw_update();
1580 24236869 bellard
}
1581 24236869 bellard
1582 ca4cca4d aliguori
static void pixel_format_message (VncState *vs) {
1583 ca4cca4d aliguori
    char pad[3] = { 0, 0, 0 };
1584 ca4cca4d aliguori
1585 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */
1586 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */
1587 ca4cca4d aliguori
1588 ca4cca4d aliguori
#ifdef WORDS_BIGENDIAN
1589 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* big-endian-flag */
1590 ca4cca4d aliguori
#else
1591 ca4cca4d aliguori
    vnc_write_u8(vs, 0);             /* big-endian-flag */
1592 ca4cca4d aliguori
#endif
1593 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* true-color-flag */
1594 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.rmax);     /* red-max */
1595 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.gmax);     /* green-max */
1596 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.bmax);     /* blue-max */
1597 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.rshift);    /* red-shift */
1598 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.gshift);    /* green-shift */
1599 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.bshift);    /* blue-shift */
1600 6cec5487 aliguori
    if (vs->ds->surface->pf.bits_per_pixel == 32)
1601 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_32;
1602 6cec5487 aliguori
    else if (vs->ds->surface->pf.bits_per_pixel == 16)
1603 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_16;
1604 6cec5487 aliguori
    else if (vs->ds->surface->pf.bits_per_pixel == 8)
1605 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_8;
1606 6cec5487 aliguori
    vs->clientds = *(vs->ds->surface);
1607 3cded540 aurel32
    vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG;
1608 ca4cca4d aliguori
    vs->write_pixels = vnc_write_pixels_copy;
1609 ca4cca4d aliguori
1610 ca4cca4d aliguori
    vnc_write(vs, pad, 3);           /* padding */
1611 ca4cca4d aliguori
}
1612 ca4cca4d aliguori
1613 7d957bd8 aliguori
static void vnc_dpy_setdata(DisplayState *ds)
1614 7d957bd8 aliguori
{
1615 7d957bd8 aliguori
    /* We don't have to do anything */
1616 7d957bd8 aliguori
}
1617 7d957bd8 aliguori
1618 753b4053 aliguori
static void vnc_colordepth(VncState *vs)
1619 7eac3a87 aliguori
{
1620 753b4053 aliguori
    if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
1621 ca4cca4d aliguori
        /* Sending a WMVi message to notify the client*/
1622 ca4cca4d aliguori
        vnc_write_u8(vs, 0);  /* msg id */
1623 ca4cca4d aliguori
        vnc_write_u8(vs, 0);
1624 ca4cca4d aliguori
        vnc_write_u16(vs, 1); /* number of rects */
1625 753b4053 aliguori
        vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), 
1626 753b4053 aliguori
                               ds_get_height(vs->ds), VNC_ENCODING_WMVi);
1627 ca4cca4d aliguori
        pixel_format_message(vs);
1628 ca4cca4d aliguori
        vnc_flush(vs);
1629 7eac3a87 aliguori
    } else {
1630 6cec5487 aliguori
        set_pixel_conversion(vs);
1631 7eac3a87 aliguori
    }
1632 7eac3a87 aliguori
}
1633 7eac3a87 aliguori
1634 60fe76f3 ths
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1635 24236869 bellard
{
1636 24236869 bellard
    int i;
1637 24236869 bellard
    uint16_t limit;
1638 24236869 bellard
1639 24236869 bellard
    switch (data[0]) {
1640 24236869 bellard
    case 0:
1641 28a76be8 aliguori
        if (len == 1)
1642 28a76be8 aliguori
            return 20;
1643 28a76be8 aliguori
1644 28a76be8 aliguori
        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1645 28a76be8 aliguori
                         read_u8(data, 6), read_u8(data, 7),
1646 28a76be8 aliguori
                         read_u16(data, 8), read_u16(data, 10),
1647 28a76be8 aliguori
                         read_u16(data, 12), read_u8(data, 14),
1648 28a76be8 aliguori
                         read_u8(data, 15), read_u8(data, 16));
1649 28a76be8 aliguori
        break;
1650 24236869 bellard
    case 2:
1651 28a76be8 aliguori
        if (len == 1)
1652 28a76be8 aliguori
            return 4;
1653 24236869 bellard
1654 28a76be8 aliguori
        if (len == 4) {
1655 69dd5c9f aliguori
            limit = read_u16(data, 2);
1656 69dd5c9f aliguori
            if (limit > 0)
1657 69dd5c9f aliguori
                return 4 + (limit * 4);
1658 69dd5c9f aliguori
        } else
1659 69dd5c9f aliguori
            limit = read_u16(data, 2);
1660 24236869 bellard
1661 28a76be8 aliguori
        for (i = 0; i < limit; i++) {
1662 28a76be8 aliguori
            int32_t val = read_s32(data, 4 + (i * 4));
1663 28a76be8 aliguori
            memcpy(data + 4 + (i * 4), &val, sizeof(val));
1664 28a76be8 aliguori
        }
1665 24236869 bellard
1666 28a76be8 aliguori
        set_encodings(vs, (int32_t *)(data + 4), limit);
1667 28a76be8 aliguori
        break;
1668 24236869 bellard
    case 3:
1669 28a76be8 aliguori
        if (len == 1)
1670 28a76be8 aliguori
            return 10;
1671 24236869 bellard
1672 28a76be8 aliguori
        framebuffer_update_request(vs,
1673 28a76be8 aliguori
                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1674 28a76be8 aliguori
                                   read_u16(data, 6), read_u16(data, 8));
1675 28a76be8 aliguori
        break;
1676 24236869 bellard
    case 4:
1677 28a76be8 aliguori
        if (len == 1)
1678 28a76be8 aliguori
            return 8;
1679 24236869 bellard
1680 28a76be8 aliguori
        key_event(vs, read_u8(data, 1), read_u32(data, 4));
1681 28a76be8 aliguori
        break;
1682 24236869 bellard
    case 5:
1683 28a76be8 aliguori
        if (len == 1)
1684 28a76be8 aliguori
            return 6;
1685 24236869 bellard
1686 28a76be8 aliguori
        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1687 28a76be8 aliguori
        break;
1688 24236869 bellard
    case 6:
1689 28a76be8 aliguori
        if (len == 1)
1690 28a76be8 aliguori
            return 8;
1691 24236869 bellard
1692 28a76be8 aliguori
        if (len == 8) {
1693 baa7666c ths
            uint32_t dlen = read_u32(data, 4);
1694 baa7666c ths
            if (dlen > 0)
1695 baa7666c ths
                return 8 + dlen;
1696 baa7666c ths
        }
1697 24236869 bellard
1698 28a76be8 aliguori
        client_cut_text(vs, read_u32(data, 4), data + 8);
1699 28a76be8 aliguori
        break;
1700 9ca313aa aliguori
    case 255:
1701 9ca313aa aliguori
        if (len == 1)
1702 9ca313aa aliguori
            return 2;
1703 9ca313aa aliguori
1704 9ca313aa aliguori
        switch (read_u8(data, 1)) {
1705 9ca313aa aliguori
        case 0:
1706 9ca313aa aliguori
            if (len == 2)
1707 9ca313aa aliguori
                return 12;
1708 9ca313aa aliguori
1709 9ca313aa aliguori
            ext_key_event(vs, read_u16(data, 2),
1710 9ca313aa aliguori
                          read_u32(data, 4), read_u32(data, 8));
1711 9ca313aa aliguori
            break;
1712 429a8ed3 malc
        case 1:
1713 429a8ed3 malc
            if (len == 2)
1714 429a8ed3 malc
                return 4;
1715 429a8ed3 malc
1716 429a8ed3 malc
            switch (read_u16 (data, 2)) {
1717 429a8ed3 malc
            case 0:
1718 429a8ed3 malc
                audio_add(vs);
1719 429a8ed3 malc
                break;
1720 429a8ed3 malc
            case 1:
1721 429a8ed3 malc
                audio_del(vs);
1722 429a8ed3 malc
                break;
1723 429a8ed3 malc
            case 2:
1724 429a8ed3 malc
                if (len == 4)
1725 429a8ed3 malc
                    return 10;
1726 429a8ed3 malc
                switch (read_u8(data, 4)) {
1727 429a8ed3 malc
                case 0: vs->as.fmt = AUD_FMT_U8; break;
1728 429a8ed3 malc
                case 1: vs->as.fmt = AUD_FMT_S8; break;
1729 429a8ed3 malc
                case 2: vs->as.fmt = AUD_FMT_U16; break;
1730 429a8ed3 malc
                case 3: vs->as.fmt = AUD_FMT_S16; break;
1731 429a8ed3 malc
                case 4: vs->as.fmt = AUD_FMT_U32; break;
1732 429a8ed3 malc
                case 5: vs->as.fmt = AUD_FMT_S32; break;
1733 429a8ed3 malc
                default:
1734 429a8ed3 malc
                    printf("Invalid audio format %d\n", read_u8(data, 4));
1735 429a8ed3 malc
                    vnc_client_error(vs);
1736 429a8ed3 malc
                    break;
1737 429a8ed3 malc
                }
1738 429a8ed3 malc
                vs->as.nchannels = read_u8(data, 5);
1739 429a8ed3 malc
                if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
1740 429a8ed3 malc
                    printf("Invalid audio channel coount %d\n",
1741 429a8ed3 malc
                           read_u8(data, 5));
1742 429a8ed3 malc
                    vnc_client_error(vs);
1743 429a8ed3 malc
                    break;
1744 429a8ed3 malc
                }
1745 429a8ed3 malc
                vs->as.freq = read_u32(data, 6);
1746 429a8ed3 malc
                break;
1747 429a8ed3 malc
            default:
1748 429a8ed3 malc
                printf ("Invalid audio message %d\n", read_u8(data, 4));
1749 429a8ed3 malc
                vnc_client_error(vs);
1750 429a8ed3 malc
                break;
1751 429a8ed3 malc
            }
1752 429a8ed3 malc
            break;
1753 429a8ed3 malc
1754 9ca313aa aliguori
        default:
1755 9ca313aa aliguori
            printf("Msg: %d\n", read_u16(data, 0));
1756 9ca313aa aliguori
            vnc_client_error(vs);
1757 9ca313aa aliguori
            break;
1758 9ca313aa aliguori
        }
1759 9ca313aa aliguori
        break;
1760 24236869 bellard
    default:
1761 28a76be8 aliguori
        printf("Msg: %d\n", data[0]);
1762 28a76be8 aliguori
        vnc_client_error(vs);
1763 28a76be8 aliguori
        break;
1764 24236869 bellard
    }
1765 5fafdf24 ths
1766 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1767 24236869 bellard
    return 0;
1768 24236869 bellard
}
1769 24236869 bellard
1770 60fe76f3 ths
static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1771 24236869 bellard
{
1772 c35734b2 ths
    char buf[1024];
1773 c35734b2 ths
    int size;
1774 24236869 bellard
1775 0e1f5a0c aliguori
    vnc_write_u16(vs, ds_get_width(vs->ds));
1776 0e1f5a0c aliguori
    vnc_write_u16(vs, ds_get_height(vs->ds));
1777 24236869 bellard
1778 ca4cca4d aliguori
    pixel_format_message(vs);
1779 24236869 bellard
1780 c35734b2 ths
    if (qemu_name)
1781 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
1782 c35734b2 ths
    else
1783 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU");
1784 c35734b2 ths
1785 c35734b2 ths
    vnc_write_u32(vs, size);
1786 c35734b2 ths
    vnc_write(vs, buf, size);
1787 24236869 bellard
    vnc_flush(vs);
1788 24236869 bellard
1789 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1790 24236869 bellard
1791 24236869 bellard
    return 0;
1792 24236869 bellard
}
1793 24236869 bellard
1794 5fb6c7a8 aliguori
void start_client_init(VncState *vs)
1795 5fb6c7a8 aliguori
{
1796 5fb6c7a8 aliguori
    vnc_read_when(vs, protocol_client_init, 1);
1797 5fb6c7a8 aliguori
}
1798 5fb6c7a8 aliguori
1799 70848515 ths
static void make_challenge(VncState *vs)
1800 70848515 ths
{
1801 70848515 ths
    int i;
1802 70848515 ths
1803 70848515 ths
    srand(time(NULL)+getpid()+getpid()*987654+rand());
1804 70848515 ths
1805 70848515 ths
    for (i = 0 ; i < sizeof(vs->challenge) ; i++)
1806 70848515 ths
        vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1807 70848515 ths
}
1808 70848515 ths
1809 60fe76f3 ths
static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1810 70848515 ths
{
1811 60fe76f3 ths
    unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
1812 70848515 ths
    int i, j, pwlen;
1813 60fe76f3 ths
    unsigned char key[8];
1814 70848515 ths
1815 753b4053 aliguori
    if (!vs->vd->password || !vs->vd->password[0]) {
1816 28a76be8 aliguori
        VNC_DEBUG("No password configured on server");
1817 28a76be8 aliguori
        vnc_write_u32(vs, 1); /* Reject auth */
1818 28a76be8 aliguori
        if (vs->minor >= 8) {
1819 28a76be8 aliguori
            static const char err[] = "Authentication failed";
1820 28a76be8 aliguori
            vnc_write_u32(vs, sizeof(err));
1821 28a76be8 aliguori
            vnc_write(vs, err, sizeof(err));
1822 28a76be8 aliguori
        }
1823 28a76be8 aliguori
        vnc_flush(vs);
1824 28a76be8 aliguori
        vnc_client_error(vs);
1825 28a76be8 aliguori
        return 0;
1826 70848515 ths
    }
1827 70848515 ths
1828 70848515 ths
    memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
1829 70848515 ths
1830 70848515 ths
    /* Calculate the expected challenge response */
1831 753b4053 aliguori
    pwlen = strlen(vs->vd->password);
1832 70848515 ths
    for (i=0; i<sizeof(key); i++)
1833 753b4053 aliguori
        key[i] = i<pwlen ? vs->vd->password[i] : 0;
1834 70848515 ths
    deskey(key, EN0);
1835 70848515 ths
    for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
1836 70848515 ths
        des(response+j, response+j);
1837 70848515 ths
1838 70848515 ths
    /* Compare expected vs actual challenge response */
1839 70848515 ths
    if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
1840 28a76be8 aliguori
        VNC_DEBUG("Client challenge reponse did not match\n");
1841 28a76be8 aliguori
        vnc_write_u32(vs, 1); /* Reject auth */
1842 28a76be8 aliguori
        if (vs->minor >= 8) {
1843 28a76be8 aliguori
            static const char err[] = "Authentication failed";
1844 28a76be8 aliguori
            vnc_write_u32(vs, sizeof(err));
1845 28a76be8 aliguori
            vnc_write(vs, err, sizeof(err));
1846 28a76be8 aliguori
        }
1847 28a76be8 aliguori
        vnc_flush(vs);
1848 28a76be8 aliguori
        vnc_client_error(vs);
1849 70848515 ths
    } else {
1850 28a76be8 aliguori
        VNC_DEBUG("Accepting VNC challenge response\n");
1851 28a76be8 aliguori
        vnc_write_u32(vs, 0); /* Accept auth */
1852 28a76be8 aliguori
        vnc_flush(vs);
1853 70848515 ths
1854 5fb6c7a8 aliguori
        start_client_init(vs);
1855 70848515 ths
    }
1856 70848515 ths
    return 0;
1857 70848515 ths
}
1858 70848515 ths
1859 5fb6c7a8 aliguori
void start_auth_vnc(VncState *vs)
1860 70848515 ths
{
1861 70848515 ths
    make_challenge(vs);
1862 70848515 ths
    /* Send client a 'random' challenge */
1863 70848515 ths
    vnc_write(vs, vs->challenge, sizeof(vs->challenge));
1864 70848515 ths
    vnc_flush(vs);
1865 70848515 ths
1866 70848515 ths
    vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
1867 469b15c6 ths
}
1868 469b15c6 ths
1869 469b15c6 ths
1870 60fe76f3 ths
static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
1871 70848515 ths
{
1872 70848515 ths
    /* We only advertise 1 auth scheme at a time, so client
1873 70848515 ths
     * must pick the one we sent. Verify this */
1874 753b4053 aliguori
    if (data[0] != vs->vd->auth) { /* Reject auth */
1875 1263b7d6 aliguori
       VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
1876 70848515 ths
       vnc_write_u32(vs, 1);
1877 70848515 ths
       if (vs->minor >= 8) {
1878 70848515 ths
           static const char err[] = "Authentication failed";
1879 70848515 ths
           vnc_write_u32(vs, sizeof(err));
1880 70848515 ths
           vnc_write(vs, err, sizeof(err));
1881 70848515 ths
       }
1882 70848515 ths
       vnc_client_error(vs);
1883 70848515 ths
    } else { /* Accept requested auth */
1884 70848515 ths
       VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
1885 753b4053 aliguori
       switch (vs->vd->auth) {
1886 70848515 ths
       case VNC_AUTH_NONE:
1887 70848515 ths
           VNC_DEBUG("Accept auth none\n");
1888 a26c97ad balrog
           if (vs->minor >= 8) {
1889 a26c97ad balrog
               vnc_write_u32(vs, 0); /* Accept auth completion */
1890 a26c97ad balrog
               vnc_flush(vs);
1891 a26c97ad balrog
           }
1892 5fb6c7a8 aliguori
           start_client_init(vs);
1893 70848515 ths
           break;
1894 70848515 ths
1895 70848515 ths
       case VNC_AUTH_VNC:
1896 70848515 ths
           VNC_DEBUG("Start VNC auth\n");
1897 5fb6c7a8 aliguori
           start_auth_vnc(vs);
1898 5fb6c7a8 aliguori
           break;
1899 70848515 ths
1900 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
1901 8d5d2d4c ths
       case VNC_AUTH_VENCRYPT:
1902 8d5d2d4c ths
           VNC_DEBUG("Accept VeNCrypt auth\n");;
1903 5fb6c7a8 aliguori
           start_auth_vencrypt(vs);
1904 5fb6c7a8 aliguori
           break;
1905 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
1906 8d5d2d4c ths
1907 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1908 2f9606b3 aliguori
       case VNC_AUTH_SASL:
1909 2f9606b3 aliguori
           VNC_DEBUG("Accept SASL auth\n");
1910 2f9606b3 aliguori
           start_auth_sasl(vs);
1911 2f9606b3 aliguori
           break;
1912 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1913 2f9606b3 aliguori
1914 70848515 ths
       default: /* Should not be possible, but just in case */
1915 1263b7d6 aliguori
           VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth);
1916 70848515 ths
           vnc_write_u8(vs, 1);
1917 70848515 ths
           if (vs->minor >= 8) {
1918 70848515 ths
               static const char err[] = "Authentication failed";
1919 70848515 ths
               vnc_write_u32(vs, sizeof(err));
1920 70848515 ths
               vnc_write(vs, err, sizeof(err));
1921 70848515 ths
           }
1922 70848515 ths
           vnc_client_error(vs);
1923 70848515 ths
       }
1924 70848515 ths
    }
1925 70848515 ths
    return 0;
1926 70848515 ths
}
1927 70848515 ths
1928 60fe76f3 ths
static int protocol_version(VncState *vs, uint8_t *version, size_t len)
1929 24236869 bellard
{
1930 24236869 bellard
    char local[13];
1931 24236869 bellard
1932 24236869 bellard
    memcpy(local, version, 12);
1933 24236869 bellard
    local[12] = 0;
1934 24236869 bellard
1935 70848515 ths
    if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
1936 28a76be8 aliguori
        VNC_DEBUG("Malformed protocol version %s\n", local);
1937 28a76be8 aliguori
        vnc_client_error(vs);
1938 28a76be8 aliguori
        return 0;
1939 24236869 bellard
    }
1940 70848515 ths
    VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
1941 70848515 ths
    if (vs->major != 3 ||
1942 28a76be8 aliguori
        (vs->minor != 3 &&
1943 28a76be8 aliguori
         vs->minor != 4 &&
1944 28a76be8 aliguori
         vs->minor != 5 &&
1945 28a76be8 aliguori
         vs->minor != 7 &&
1946 28a76be8 aliguori
         vs->minor != 8)) {
1947 28a76be8 aliguori
        VNC_DEBUG("Unsupported client version\n");
1948 28a76be8 aliguori
        vnc_write_u32(vs, VNC_AUTH_INVALID);
1949 28a76be8 aliguori
        vnc_flush(vs);
1950 28a76be8 aliguori
        vnc_client_error(vs);
1951 28a76be8 aliguori
        return 0;
1952 70848515 ths
    }
1953 b0566f4f ths
    /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
1954 70848515 ths
     * as equivalent to v3.3 by servers
1955 70848515 ths
     */
1956 b0566f4f ths
    if (vs->minor == 4 || vs->minor == 5)
1957 28a76be8 aliguori
        vs->minor = 3;
1958 70848515 ths
1959 70848515 ths
    if (vs->minor == 3) {
1960 28a76be8 aliguori
        if (vs->vd->auth == VNC_AUTH_NONE) {
1961 70848515 ths
            VNC_DEBUG("Tell client auth none\n");
1962 753b4053 aliguori
            vnc_write_u32(vs, vs->vd->auth);
1963 70848515 ths
            vnc_flush(vs);
1964 28a76be8 aliguori
            start_client_init(vs);
1965 753b4053 aliguori
       } else if (vs->vd->auth == VNC_AUTH_VNC) {
1966 70848515 ths
            VNC_DEBUG("Tell client VNC auth\n");
1967 753b4053 aliguori
            vnc_write_u32(vs, vs->vd->auth);
1968 70848515 ths
            vnc_flush(vs);
1969 70848515 ths
            start_auth_vnc(vs);
1970 70848515 ths
       } else {
1971 753b4053 aliguori
            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth);
1972 70848515 ths
            vnc_write_u32(vs, VNC_AUTH_INVALID);
1973 70848515 ths
            vnc_flush(vs);
1974 70848515 ths
            vnc_client_error(vs);
1975 70848515 ths
       }
1976 70848515 ths
    } else {
1977 28a76be8 aliguori
        VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth);
1978 28a76be8 aliguori
        vnc_write_u8(vs, 1); /* num auth */
1979 28a76be8 aliguori
        vnc_write_u8(vs, vs->vd->auth);
1980 28a76be8 aliguori
        vnc_read_when(vs, protocol_client_auth, 1);
1981 28a76be8 aliguori
        vnc_flush(vs);
1982 70848515 ths
    }
1983 24236869 bellard
1984 24236869 bellard
    return 0;
1985 24236869 bellard
}
1986 24236869 bellard
1987 753b4053 aliguori
static void vnc_connect(VncDisplay *vd, int csock)
1988 3aa3eea3 balrog
{
1989 753b4053 aliguori
    VncState *vs = qemu_mallocz(sizeof(VncState));
1990 753b4053 aliguori
    vs->csock = csock;
1991 753b4053 aliguori
1992 753b4053 aliguori
    VNC_DEBUG("New client on socket %d\n", csock);
1993 7d957bd8 aliguori
    dcl->idle = 0;
1994 3aa3eea3 balrog
    socket_set_nonblock(vs->csock);
1995 3aa3eea3 balrog
    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
1996 753b4053 aliguori
1997 753b4053 aliguori
    vs->vd = vd;
1998 753b4053 aliguori
    vs->ds = vd->ds;
1999 753b4053 aliguori
    vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
2000 753b4053 aliguori
    vs->last_x = -1;
2001 753b4053 aliguori
    vs->last_y = -1;
2002 753b4053 aliguori
2003 753b4053 aliguori
    vs->as.freq = 44100;
2004 753b4053 aliguori
    vs->as.nchannels = 2;
2005 753b4053 aliguori
    vs->as.fmt = AUD_FMT_S16;
2006 753b4053 aliguori
    vs->as.endianness = 0;
2007 753b4053 aliguori
2008 753b4053 aliguori
    vnc_resize(vs);
2009 3aa3eea3 balrog
    vnc_write(vs, "RFB 003.008\n", 12);
2010 3aa3eea3 balrog
    vnc_flush(vs);
2011 3aa3eea3 balrog
    vnc_read_when(vs, protocol_version, 12);
2012 3aa3eea3 balrog
    vnc_update_client(vs);
2013 53762ddb malc
    reset_keys(vs);
2014 753b4053 aliguori
2015 753b4053 aliguori
    vs->next = vd->clients;
2016 753b4053 aliguori
    vd->clients = vs;
2017 3aa3eea3 balrog
}
2018 3aa3eea3 balrog
2019 24236869 bellard
static void vnc_listen_read(void *opaque)
2020 24236869 bellard
{
2021 753b4053 aliguori
    VncDisplay *vs = opaque;
2022 24236869 bellard
    struct sockaddr_in addr;
2023 24236869 bellard
    socklen_t addrlen = sizeof(addr);
2024 24236869 bellard
2025 9f60ad50 balrog
    /* Catch-up */
2026 9f60ad50 balrog
    vga_hw_update();
2027 9f60ad50 balrog
2028 753b4053 aliguori
    int csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2029 753b4053 aliguori
    if (csock != -1) {
2030 753b4053 aliguori
        vnc_connect(vs, csock);
2031 24236869 bellard
    }
2032 24236869 bellard
}
2033 24236869 bellard
2034 71cab5ca ths
void vnc_display_init(DisplayState *ds)
2035 24236869 bellard
{
2036 753b4053 aliguori
    VncDisplay *vs;
2037 24236869 bellard
2038 24236869 bellard
    vs = qemu_mallocz(sizeof(VncState));
2039 7d957bd8 aliguori
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2040 24236869 bellard
2041 24236869 bellard
    ds->opaque = vs;
2042 7d957bd8 aliguori
    dcl->idle = 1;
2043 753b4053 aliguori
    vnc_display = vs;
2044 24236869 bellard
2045 24236869 bellard
    vs->lsock = -1;
2046 24236869 bellard
2047 24236869 bellard
    vs->ds = ds;
2048 24236869 bellard
2049 9ca313aa aliguori
    if (keyboard_layout)
2050 0483755a aliguori
        vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
2051 9ca313aa aliguori
    else
2052 0483755a aliguori
        vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us");
2053 24236869 bellard
2054 24236869 bellard
    if (!vs->kbd_layout)
2055 28a76be8 aliguori
        exit(1);
2056 24236869 bellard
2057 753b4053 aliguori
    dcl->dpy_copy = vnc_dpy_copy;
2058 7d957bd8 aliguori
    dcl->dpy_update = vnc_dpy_update;
2059 7d957bd8 aliguori
    dcl->dpy_resize = vnc_dpy_resize;
2060 7d957bd8 aliguori
    dcl->dpy_setdata = vnc_dpy_setdata;
2061 7d957bd8 aliguori
    register_displaychangelistener(ds, dcl);
2062 71cab5ca ths
}
2063 71cab5ca ths
2064 6f43024c ths
2065 71cab5ca ths
void vnc_display_close(DisplayState *ds)
2066 71cab5ca ths
{
2067 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2068 71cab5ca ths
2069 452b4d88 aliguori
    if (!vs)
2070 452b4d88 aliguori
        return;
2071 71cab5ca ths
    if (vs->display) {
2072 28a76be8 aliguori
        qemu_free(vs->display);
2073 28a76be8 aliguori
        vs->display = NULL;
2074 71cab5ca ths
    }
2075 71cab5ca ths
    if (vs->lsock != -1) {
2076 28a76be8 aliguori
        qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2077 28a76be8 aliguori
        close(vs->lsock);
2078 28a76be8 aliguori
        vs->lsock = -1;
2079 71cab5ca ths
    }
2080 70848515 ths
    vs->auth = VNC_AUTH_INVALID;
2081 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2082 8d5d2d4c ths
    vs->subauth = VNC_AUTH_INVALID;
2083 5fb6c7a8 aliguori
    vs->tls.x509verify = 0;
2084 8d5d2d4c ths
#endif
2085 70848515 ths
}
2086 70848515 ths
2087 70848515 ths
int vnc_display_password(DisplayState *ds, const char *password)
2088 70848515 ths
{
2089 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2090 70848515 ths
2091 70848515 ths
    if (vs->password) {
2092 28a76be8 aliguori
        qemu_free(vs->password);
2093 28a76be8 aliguori
        vs->password = NULL;
2094 70848515 ths
    }
2095 70848515 ths
    if (password && password[0]) {
2096 28a76be8 aliguori
        if (!(vs->password = qemu_strdup(password)))
2097 28a76be8 aliguori
            return -1;
2098 70848515 ths
    }
2099 70848515 ths
2100 70848515 ths
    return 0;
2101 71cab5ca ths
}
2102 71cab5ca ths
2103 f92f8afe Anthony Liguori
char *vnc_display_local_addr(DisplayState *ds)
2104 f92f8afe Anthony Liguori
{
2105 f92f8afe Anthony Liguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2106 f92f8afe Anthony Liguori
    
2107 f92f8afe Anthony Liguori
    return vnc_socket_local_addr("%s:%s", vs->lsock);
2108 f92f8afe Anthony Liguori
}
2109 f92f8afe Anthony Liguori
2110 70848515 ths
int vnc_display_open(DisplayState *ds, const char *display)
2111 71cab5ca ths
{
2112 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2113 70848515 ths
    const char *options;
2114 70848515 ths
    int password = 0;
2115 3aa3eea3 balrog
    int reverse = 0;
2116 9712ecaf aliguori
    int to_port = 0;
2117 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2118 3a702699 ths
    int tls = 0, x509 = 0;
2119 8d5d2d4c ths
#endif
2120 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2121 2f9606b3 aliguori
    int sasl = 0;
2122 2f9606b3 aliguori
    int saslErr;
2123 2f9606b3 aliguori
#endif
2124 76655d6d aliguori
    int acl = 0;
2125 71cab5ca ths
2126 753b4053 aliguori
    if (!vnc_display)
2127 452b4d88 aliguori
        return -1;
2128 71cab5ca ths
    vnc_display_close(ds);
2129 70848515 ths
    if (strcmp(display, "none") == 0)
2130 28a76be8 aliguori
        return 0;
2131 24236869 bellard
2132 70848515 ths
    if (!(vs->display = strdup(display)))
2133 28a76be8 aliguori
        return -1;
2134 70848515 ths
2135 70848515 ths
    options = display;
2136 70848515 ths
    while ((options = strchr(options, ','))) {
2137 28a76be8 aliguori
        options++;
2138 28a76be8 aliguori
        if (strncmp(options, "password", 8) == 0) {
2139 28a76be8 aliguori
            password = 1; /* Require password auth */
2140 28a76be8 aliguori
        } else if (strncmp(options, "reverse", 7) == 0) {
2141 28a76be8 aliguori
            reverse = 1;
2142 28a76be8 aliguori
        } else if (strncmp(options, "to=", 3) == 0) {
2143 9712ecaf aliguori
            to_port = atoi(options+3) + 5900;
2144 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2145 28a76be8 aliguori
        } else if (strncmp(options, "sasl", 4) == 0) {
2146 28a76be8 aliguori
            sasl = 1; /* Require SASL auth */
2147 2f9606b3 aliguori
#endif
2148 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2149 28a76be8 aliguori
        } else if (strncmp(options, "tls", 3) == 0) {
2150 28a76be8 aliguori
            tls = 1; /* Require TLS */
2151 28a76be8 aliguori
        } else if (strncmp(options, "x509", 4) == 0) {
2152 28a76be8 aliguori
            char *start, *end;
2153 28a76be8 aliguori
            x509 = 1; /* Require x509 certificates */
2154 28a76be8 aliguori
            if (strncmp(options, "x509verify", 10) == 0)
2155 28a76be8 aliguori
                vs->tls.x509verify = 1; /* ...and verify client certs */
2156 28a76be8 aliguori
2157 28a76be8 aliguori
            /* Now check for 'x509=/some/path' postfix
2158 28a76be8 aliguori
             * and use that to setup x509 certificate/key paths */
2159 28a76be8 aliguori
            start = strchr(options, '=');
2160 28a76be8 aliguori
            end = strchr(options, ',');
2161 28a76be8 aliguori
            if (start && (!end || (start < end))) {
2162 28a76be8 aliguori
                int len = end ? end-(start+1) : strlen(start+1);
2163 28a76be8 aliguori
                char *path = qemu_strndup(start + 1, len);
2164 28a76be8 aliguori
2165 28a76be8 aliguori
                VNC_DEBUG("Trying certificate path '%s'\n", path);
2166 28a76be8 aliguori
                if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
2167 28a76be8 aliguori
                    fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2168 28a76be8 aliguori
                    qemu_free(path);
2169 28a76be8 aliguori
                    qemu_free(vs->display);
2170 28a76be8 aliguori
                    vs->display = NULL;
2171 28a76be8 aliguori
                    return -1;
2172 28a76be8 aliguori
                }
2173 28a76be8 aliguori
                qemu_free(path);
2174 28a76be8 aliguori
            } else {
2175 28a76be8 aliguori
                fprintf(stderr, "No certificate path provided\n");
2176 28a76be8 aliguori
                qemu_free(vs->display);
2177 28a76be8 aliguori
                vs->display = NULL;
2178 28a76be8 aliguori
                return -1;
2179 28a76be8 aliguori
            }
2180 8d5d2d4c ths
#endif
2181 28a76be8 aliguori
        } else if (strncmp(options, "acl", 3) == 0) {
2182 28a76be8 aliguori
            acl = 1;
2183 28a76be8 aliguori
        }
2184 70848515 ths
    }
2185 70848515 ths
2186 76655d6d aliguori
#ifdef CONFIG_VNC_TLS
2187 76655d6d aliguori
    if (acl && x509 && vs->tls.x509verify) {
2188 28a76be8 aliguori
        if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) {
2189 28a76be8 aliguori
            fprintf(stderr, "Failed to create x509 dname ACL\n");
2190 28a76be8 aliguori
            exit(1);
2191 28a76be8 aliguori
        }
2192 76655d6d aliguori
    }
2193 76655d6d aliguori
#endif
2194 76655d6d aliguori
#ifdef CONFIG_VNC_SASL
2195 76655d6d aliguori
    if (acl && sasl) {
2196 28a76be8 aliguori
        if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) {
2197 28a76be8 aliguori
            fprintf(stderr, "Failed to create username ACL\n");
2198 28a76be8 aliguori
            exit(1);
2199 28a76be8 aliguori
        }
2200 76655d6d aliguori
    }
2201 76655d6d aliguori
#endif
2202 76655d6d aliguori
2203 2f9606b3 aliguori
    /*
2204 2f9606b3 aliguori
     * Combinations we support here:
2205 2f9606b3 aliguori
     *
2206 2f9606b3 aliguori
     *  - no-auth                (clear text, no auth)
2207 2f9606b3 aliguori
     *  - password               (clear text, weak auth)
2208 2f9606b3 aliguori
     *  - sasl                   (encrypt, good auth *IF* using Kerberos via GSSAPI)
2209 2f9606b3 aliguori
     *  - tls                    (encrypt, weak anonymous creds, no auth)
2210 2f9606b3 aliguori
     *  - tls + password         (encrypt, weak anonymous creds, weak auth)
2211 2f9606b3 aliguori
     *  - tls + sasl             (encrypt, weak anonymous creds, good auth)
2212 2f9606b3 aliguori
     *  - tls + x509             (encrypt, good x509 creds, no auth)
2213 2f9606b3 aliguori
     *  - tls + x509 + password  (encrypt, good x509 creds, weak auth)
2214 2f9606b3 aliguori
     *  - tls + x509 + sasl      (encrypt, good x509 creds, good auth)
2215 2f9606b3 aliguori
     *
2216 2f9606b3 aliguori
     * NB1. TLS is a stackable auth scheme.
2217 2f9606b3 aliguori
     * NB2. the x509 schemes have option to validate a client cert dname
2218 2f9606b3 aliguori
     */
2219 70848515 ths
    if (password) {
2220 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2221 28a76be8 aliguori
        if (tls) {
2222 28a76be8 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2223 28a76be8 aliguori
            if (x509) {
2224 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 password auth\n");
2225 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
2226 28a76be8 aliguori
            } else {
2227 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS password auth\n");
2228 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
2229 28a76be8 aliguori
            }
2230 28a76be8 aliguori
        } else {
2231 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2232 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with password auth\n");
2233 28a76be8 aliguori
            vs->auth = VNC_AUTH_VNC;
2234 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2235 28a76be8 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2236 28a76be8 aliguori
        }
2237 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2238 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2239 2f9606b3 aliguori
    } else if (sasl) {
2240 2f9606b3 aliguori
#ifdef CONFIG_VNC_TLS
2241 2f9606b3 aliguori
        if (tls) {
2242 2f9606b3 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2243 2f9606b3 aliguori
            if (x509) {
2244 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 SASL auth\n");
2245 2f9606b3 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509SASL;
2246 2f9606b3 aliguori
            } else {
2247 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS SASL auth\n");
2248 2f9606b3 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL;
2249 2f9606b3 aliguori
            }
2250 2f9606b3 aliguori
        } else {
2251 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2252 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with SASL auth\n");
2253 2f9606b3 aliguori
            vs->auth = VNC_AUTH_SASL;
2254 2f9606b3 aliguori
#ifdef CONFIG_VNC_TLS
2255 2f9606b3 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2256 2f9606b3 aliguori
        }
2257 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2258 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
2259 70848515 ths
    } else {
2260 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2261 28a76be8 aliguori
        if (tls) {
2262 28a76be8 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2263 28a76be8 aliguori
            if (x509) {
2264 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 no auth\n");
2265 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
2266 28a76be8 aliguori
            } else {
2267 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS no auth\n");
2268 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
2269 28a76be8 aliguori
            }
2270 28a76be8 aliguori
        } else {
2271 8d5d2d4c ths
#endif
2272 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with no auth\n");
2273 28a76be8 aliguori
            vs->auth = VNC_AUTH_NONE;
2274 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2275 28a76be8 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2276 28a76be8 aliguori
        }
2277 8d5d2d4c ths
#endif
2278 70848515 ths
    }
2279 24236869 bellard
2280 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2281 2f9606b3 aliguori
    if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) {
2282 2f9606b3 aliguori
        fprintf(stderr, "Failed to initialize SASL auth %s",
2283 2f9606b3 aliguori
                sasl_errstring(saslErr, NULL, NULL));
2284 2f9606b3 aliguori
        free(vs->display);
2285 2f9606b3 aliguori
        vs->display = NULL;
2286 2f9606b3 aliguori
        return -1;
2287 2f9606b3 aliguori
    }
2288 2f9606b3 aliguori
#endif
2289 2f9606b3 aliguori
2290 3aa3eea3 balrog
    if (reverse) {
2291 9712ecaf aliguori
        /* connect to viewer */
2292 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0)
2293 9712ecaf aliguori
            vs->lsock = unix_connect(display+5);
2294 9712ecaf aliguori
        else
2295 9712ecaf aliguori
            vs->lsock = inet_connect(display, SOCK_STREAM);
2296 9712ecaf aliguori
        if (-1 == vs->lsock) {
2297 3aa3eea3 balrog
            free(vs->display);
2298 3aa3eea3 balrog
            vs->display = NULL;
2299 3aa3eea3 balrog
            return -1;
2300 3aa3eea3 balrog
        } else {
2301 753b4053 aliguori
            int csock = vs->lsock;
2302 3aa3eea3 balrog
            vs->lsock = -1;
2303 753b4053 aliguori
            vnc_connect(vs, csock);
2304 3aa3eea3 balrog
        }
2305 9712ecaf aliguori
        return 0;
2306 24236869 bellard
2307 9712ecaf aliguori
    } else {
2308 9712ecaf aliguori
        /* listen for connects */
2309 9712ecaf aliguori
        char *dpy;
2310 9712ecaf aliguori
        dpy = qemu_malloc(256);
2311 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0) {
2312 bc575e95 blueswir1
            pstrcpy(dpy, 256, "unix:");
2313 4a55bfdf aliguori
            vs->lsock = unix_listen(display+5, dpy+5, 256-5);
2314 9712ecaf aliguori
        } else {
2315 9712ecaf aliguori
            vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
2316 9712ecaf aliguori
        }
2317 9712ecaf aliguori
        if (-1 == vs->lsock) {
2318 9712ecaf aliguori
            free(dpy);
2319 d0513623 balrog
            return -1;
2320 9712ecaf aliguori
        } else {
2321 9712ecaf aliguori
            free(vs->display);
2322 9712ecaf aliguori
            vs->display = dpy;
2323 9712ecaf aliguori
        }
2324 24236869 bellard
    }
2325 753b4053 aliguori
    return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs);
2326 24236869 bellard
}