Statistics
| Branch: | Revision:

root / vnc.c @ 5fb6c7a8

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