Statistics
| Branch: | Revision:

root / vnc.c @ 3cded540

History | View | Annotate | Download (66.8 kB)

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