Statistics
| Branch: | Revision:

root / vnc.c @ 283c7c63

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