Statistics
| Branch: | Revision:

root / vnc.c @ b09ea7d5

History | View | Annotate | Download (69.1 kB)

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