Statistics
| Branch: | Revision:

root / vnc.c @ ac74d0f1

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