Statistics
| Branch: | Revision:

root / vnc.c @ a15fdf86

History | View | Annotate | Download (73.3 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 6b132502 Gerd Hoffmann
    if ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z')) {
1381 6b132502 Gerd Hoffmann
        /* If the capslock state needs to change then simulate an additional
1382 6b132502 Gerd Hoffmann
           keypress before sending this one.  This will happen if the user
1383 6b132502 Gerd Hoffmann
           toggles capslock away from the VNC window.
1384 6b132502 Gerd Hoffmann
        */
1385 6b132502 Gerd Hoffmann
        int uppercase = !!(sym >= 'A' && sym <= 'Z');
1386 6b132502 Gerd Hoffmann
        int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
1387 6b132502 Gerd Hoffmann
        int capslock = !!(vs->modifiers_state[0x3a]);
1388 6b132502 Gerd Hoffmann
        if (capslock) {
1389 6b132502 Gerd Hoffmann
            if (uppercase == shift) {
1390 6b132502 Gerd Hoffmann
                vs->modifiers_state[0x3a] = 0;
1391 6b132502 Gerd Hoffmann
                press_key(vs, 0xffe5);
1392 6b132502 Gerd Hoffmann
            }
1393 6b132502 Gerd Hoffmann
        } else {
1394 6b132502 Gerd Hoffmann
            if (uppercase != shift) {
1395 6b132502 Gerd Hoffmann
                vs->modifiers_state[0x3a] = 1;
1396 6b132502 Gerd Hoffmann
                press_key(vs, 0xffe5);
1397 6b132502 Gerd Hoffmann
            }
1398 6b132502 Gerd Hoffmann
        }
1399 6b132502 Gerd Hoffmann
    }
1400 6b132502 Gerd Hoffmann
1401 64f5a135 bellard
    if (is_graphic_console()) {
1402 64f5a135 bellard
        if (keycode & 0x80)
1403 64f5a135 bellard
            kbd_put_keycode(0xe0);
1404 64f5a135 bellard
        if (down)
1405 64f5a135 bellard
            kbd_put_keycode(keycode & 0x7f);
1406 64f5a135 bellard
        else
1407 64f5a135 bellard
            kbd_put_keycode(keycode | 0x80);
1408 64f5a135 bellard
    } else {
1409 64f5a135 bellard
        /* QEMU console emulation */
1410 64f5a135 bellard
        if (down) {
1411 bb0a18e1 Gerd Hoffmann
            int numlock = vs->modifiers_state[0x45];
1412 64f5a135 bellard
            switch (keycode) {
1413 64f5a135 bellard
            case 0x2a:                          /* Left Shift */
1414 64f5a135 bellard
            case 0x36:                          /* Right Shift */
1415 64f5a135 bellard
            case 0x1d:                          /* Left CTRL */
1416 64f5a135 bellard
            case 0x9d:                          /* Right CTRL */
1417 64f5a135 bellard
            case 0x38:                          /* Left ALT */
1418 64f5a135 bellard
            case 0xb8:                          /* Right ALT */
1419 64f5a135 bellard
                break;
1420 64f5a135 bellard
            case 0xc8:
1421 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_UP);
1422 64f5a135 bellard
                break;
1423 64f5a135 bellard
            case 0xd0:
1424 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DOWN);
1425 64f5a135 bellard
                break;
1426 64f5a135 bellard
            case 0xcb:
1427 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_LEFT);
1428 64f5a135 bellard
                break;
1429 64f5a135 bellard
            case 0xcd:
1430 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_RIGHT);
1431 64f5a135 bellard
                break;
1432 64f5a135 bellard
            case 0xd3:
1433 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DELETE);
1434 64f5a135 bellard
                break;
1435 64f5a135 bellard
            case 0xc7:
1436 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_HOME);
1437 64f5a135 bellard
                break;
1438 64f5a135 bellard
            case 0xcf:
1439 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_END);
1440 64f5a135 bellard
                break;
1441 64f5a135 bellard
            case 0xc9:
1442 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEUP);
1443 64f5a135 bellard
                break;
1444 64f5a135 bellard
            case 0xd1:
1445 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1446 64f5a135 bellard
                break;
1447 bb0a18e1 Gerd Hoffmann
1448 bb0a18e1 Gerd Hoffmann
            case 0x47:
1449 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
1450 bb0a18e1 Gerd Hoffmann
                break;
1451 bb0a18e1 Gerd Hoffmann
            case 0x48:
1452 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
1453 bb0a18e1 Gerd Hoffmann
                break;
1454 bb0a18e1 Gerd Hoffmann
            case 0x49:
1455 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
1456 bb0a18e1 Gerd Hoffmann
                break;
1457 bb0a18e1 Gerd Hoffmann
            case 0x4b:
1458 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
1459 bb0a18e1 Gerd Hoffmann
                break;
1460 bb0a18e1 Gerd Hoffmann
            case 0x4c:
1461 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('5');
1462 bb0a18e1 Gerd Hoffmann
                break;
1463 bb0a18e1 Gerd Hoffmann
            case 0x4d:
1464 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
1465 bb0a18e1 Gerd Hoffmann
                break;
1466 bb0a18e1 Gerd Hoffmann
            case 0x4f:
1467 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
1468 bb0a18e1 Gerd Hoffmann
                break;
1469 bb0a18e1 Gerd Hoffmann
            case 0x50:
1470 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
1471 bb0a18e1 Gerd Hoffmann
                break;
1472 bb0a18e1 Gerd Hoffmann
            case 0x51:
1473 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
1474 bb0a18e1 Gerd Hoffmann
                break;
1475 bb0a18e1 Gerd Hoffmann
            case 0x52:
1476 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('0');
1477 bb0a18e1 Gerd Hoffmann
                break;
1478 bb0a18e1 Gerd Hoffmann
            case 0x53:
1479 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
1480 bb0a18e1 Gerd Hoffmann
                break;
1481 bb0a18e1 Gerd Hoffmann
1482 bb0a18e1 Gerd Hoffmann
            case 0xb5:
1483 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('/');
1484 bb0a18e1 Gerd Hoffmann
                break;
1485 bb0a18e1 Gerd Hoffmann
            case 0x37:
1486 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('*');
1487 bb0a18e1 Gerd Hoffmann
                break;
1488 bb0a18e1 Gerd Hoffmann
            case 0x4a:
1489 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('-');
1490 bb0a18e1 Gerd Hoffmann
                break;
1491 bb0a18e1 Gerd Hoffmann
            case 0x4e:
1492 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('+');
1493 bb0a18e1 Gerd Hoffmann
                break;
1494 bb0a18e1 Gerd Hoffmann
            case 0x9c:
1495 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('\n');
1496 bb0a18e1 Gerd Hoffmann
                break;
1497 bb0a18e1 Gerd Hoffmann
1498 64f5a135 bellard
            default:
1499 64f5a135 bellard
                kbd_put_keysym(sym);
1500 64f5a135 bellard
                break;
1501 64f5a135 bellard
            }
1502 64f5a135 bellard
        }
1503 64f5a135 bellard
    }
1504 24236869 bellard
}
1505 24236869 bellard
1506 bdbd7676 bellard
static void key_event(VncState *vs, int down, uint32_t sym)
1507 bdbd7676 bellard
{
1508 9ca313aa aliguori
    int keycode;
1509 9ca313aa aliguori
1510 a528b80c balrog
    if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
1511 28a76be8 aliguori
        sym = sym - 'A' + 'a';
1512 9ca313aa aliguori
1513 753b4053 aliguori
    keycode = keysym2scancode(vs->vd->kbd_layout, sym & 0xFFFF);
1514 9ca313aa aliguori
    do_key_event(vs, down, keycode, sym);
1515 9ca313aa aliguori
}
1516 9ca313aa aliguori
1517 9ca313aa aliguori
static void ext_key_event(VncState *vs, int down,
1518 9ca313aa aliguori
                          uint32_t sym, uint16_t keycode)
1519 9ca313aa aliguori
{
1520 9ca313aa aliguori
    /* if the user specifies a keyboard layout, always use it */
1521 9ca313aa aliguori
    if (keyboard_layout)
1522 9ca313aa aliguori
        key_event(vs, down, sym);
1523 9ca313aa aliguori
    else
1524 9ca313aa aliguori
        do_key_event(vs, down, keycode, sym);
1525 bdbd7676 bellard
}
1526 bdbd7676 bellard
1527 24236869 bellard
static void framebuffer_update_request(VncState *vs, int incremental,
1528 28a76be8 aliguori
                                       int x_position, int y_position,
1529 28a76be8 aliguori
                                       int w, int h)
1530 24236869 bellard
{
1531 0e1f5a0c aliguori
    if (x_position > ds_get_width(vs->ds))
1532 0e1f5a0c aliguori
        x_position = ds_get_width(vs->ds);
1533 0e1f5a0c aliguori
    if (y_position > ds_get_height(vs->ds))
1534 0e1f5a0c aliguori
        y_position = ds_get_height(vs->ds);
1535 0e1f5a0c aliguori
    if (x_position + w >= ds_get_width(vs->ds))
1536 0e1f5a0c aliguori
        w = ds_get_width(vs->ds)  - x_position;
1537 0e1f5a0c aliguori
    if (y_position + h >= ds_get_height(vs->ds))
1538 0e1f5a0c aliguori
        h = ds_get_height(vs->ds) - y_position;
1539 cf2d385c ths
1540 24236869 bellard
    int i;
1541 24236869 bellard
    vs->need_update = 1;
1542 24236869 bellard
    if (!incremental) {
1543 24cf0a6e Gerd Hoffmann
        vs->force_update = 1;
1544 28a76be8 aliguori
        for (i = 0; i < h; i++) {
1545 1fc62412 Stefano Stabellini
            vnc_set_bits(vs->dirty[y_position + i],
1546 0e1f5a0c aliguori
                         (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1547 28a76be8 aliguori
        }
1548 24236869 bellard
    }
1549 24236869 bellard
}
1550 24236869 bellard
1551 9ca313aa aliguori
static void send_ext_key_event_ack(VncState *vs)
1552 9ca313aa aliguori
{
1553 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1554 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1555 9ca313aa aliguori
    vnc_write_u16(vs, 1);
1556 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1557 29fa4ed9 aliguori
                           VNC_ENCODING_EXT_KEY_EVENT);
1558 9ca313aa aliguori
    vnc_flush(vs);
1559 9ca313aa aliguori
}
1560 9ca313aa aliguori
1561 429a8ed3 malc
static void send_ext_audio_ack(VncState *vs)
1562 429a8ed3 malc
{
1563 429a8ed3 malc
    vnc_write_u8(vs, 0);
1564 429a8ed3 malc
    vnc_write_u8(vs, 0);
1565 429a8ed3 malc
    vnc_write_u16(vs, 1);
1566 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1567 29fa4ed9 aliguori
                           VNC_ENCODING_AUDIO);
1568 429a8ed3 malc
    vnc_flush(vs);
1569 429a8ed3 malc
}
1570 429a8ed3 malc
1571 24236869 bellard
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1572 24236869 bellard
{
1573 24236869 bellard
    int i;
1574 29fa4ed9 aliguori
    unsigned int enc = 0;
1575 24236869 bellard
1576 059cef40 aliguori
    vnc_zlib_init(vs);
1577 29fa4ed9 aliguori
    vs->features = 0;
1578 fb437313 aliguori
    vs->vnc_encoding = 0;
1579 fb437313 aliguori
    vs->tight_compression = 9;
1580 fb437313 aliguori
    vs->tight_quality = 9;
1581 564c337e bellard
    vs->absolute = -1;
1582 24236869 bellard
1583 24236869 bellard
    for (i = n_encodings - 1; i >= 0; i--) {
1584 29fa4ed9 aliguori
        enc = encodings[i];
1585 29fa4ed9 aliguori
        switch (enc) {
1586 29fa4ed9 aliguori
        case VNC_ENCODING_RAW:
1587 fb437313 aliguori
            vs->vnc_encoding = enc;
1588 29fa4ed9 aliguori
            break;
1589 29fa4ed9 aliguori
        case VNC_ENCODING_COPYRECT:
1590 753b4053 aliguori
            vs->features |= VNC_FEATURE_COPYRECT_MASK;
1591 29fa4ed9 aliguori
            break;
1592 29fa4ed9 aliguori
        case VNC_ENCODING_HEXTILE:
1593 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_HEXTILE_MASK;
1594 fb437313 aliguori
            vs->vnc_encoding = enc;
1595 29fa4ed9 aliguori
            break;
1596 059cef40 aliguori
        case VNC_ENCODING_ZLIB:
1597 059cef40 aliguori
            vs->features |= VNC_FEATURE_ZLIB_MASK;
1598 059cef40 aliguori
            vs->vnc_encoding = enc;
1599 059cef40 aliguori
            break;
1600 29fa4ed9 aliguori
        case VNC_ENCODING_DESKTOPRESIZE:
1601 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_RESIZE_MASK;
1602 29fa4ed9 aliguori
            break;
1603 29fa4ed9 aliguori
        case VNC_ENCODING_POINTER_TYPE_CHANGE:
1604 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
1605 29fa4ed9 aliguori
            break;
1606 29fa4ed9 aliguori
        case VNC_ENCODING_EXT_KEY_EVENT:
1607 9ca313aa aliguori
            send_ext_key_event_ack(vs);
1608 9ca313aa aliguori
            break;
1609 29fa4ed9 aliguori
        case VNC_ENCODING_AUDIO:
1610 429a8ed3 malc
            send_ext_audio_ack(vs);
1611 429a8ed3 malc
            break;
1612 29fa4ed9 aliguori
        case VNC_ENCODING_WMVi:
1613 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_WMVI_MASK;
1614 ca4cca4d aliguori
            break;
1615 fb437313 aliguori
        case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
1616 fb437313 aliguori
            vs->tight_compression = (enc & 0x0F);
1617 fb437313 aliguori
            break;
1618 fb437313 aliguori
        case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
1619 fb437313 aliguori
            vs->tight_quality = (enc & 0x0F);
1620 fb437313 aliguori
            break;
1621 29fa4ed9 aliguori
        default:
1622 29fa4ed9 aliguori
            VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
1623 29fa4ed9 aliguori
            break;
1624 29fa4ed9 aliguori
        }
1625 24236869 bellard
    }
1626 564c337e bellard
1627 564c337e bellard
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
1628 24236869 bellard
}
1629 24236869 bellard
1630 6cec5487 aliguori
static void set_pixel_conversion(VncState *vs)
1631 6cec5487 aliguori
{
1632 6cec5487 aliguori
    if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
1633 6cec5487 aliguori
        (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && 
1634 6cec5487 aliguori
        !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
1635 6cec5487 aliguori
        vs->write_pixels = vnc_write_pixels_copy;
1636 6cec5487 aliguori
        switch (vs->ds->surface->pf.bits_per_pixel) {
1637 6cec5487 aliguori
            case 8:
1638 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_8;
1639 6cec5487 aliguori
                break;
1640 6cec5487 aliguori
            case 16:
1641 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_16;
1642 6cec5487 aliguori
                break;
1643 6cec5487 aliguori
            case 32:
1644 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_32;
1645 6cec5487 aliguori
                break;
1646 6cec5487 aliguori
        }
1647 6cec5487 aliguori
    } else {
1648 6cec5487 aliguori
        vs->write_pixels = vnc_write_pixels_generic;
1649 6cec5487 aliguori
        switch (vs->ds->surface->pf.bits_per_pixel) {
1650 6cec5487 aliguori
            case 8:
1651 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_8;
1652 6cec5487 aliguori
                break;
1653 6cec5487 aliguori
            case 16:
1654 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_16;
1655 6cec5487 aliguori
                break;
1656 6cec5487 aliguori
            case 32:
1657 6cec5487 aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_32;
1658 6cec5487 aliguori
                break;
1659 6cec5487 aliguori
        }
1660 6cec5487 aliguori
    }
1661 6cec5487 aliguori
}
1662 6cec5487 aliguori
1663 24236869 bellard
static void set_pixel_format(VncState *vs,
1664 28a76be8 aliguori
                             int bits_per_pixel, int depth,
1665 28a76be8 aliguori
                             int big_endian_flag, int true_color_flag,
1666 28a76be8 aliguori
                             int red_max, int green_max, int blue_max,
1667 28a76be8 aliguori
                             int red_shift, int green_shift, int blue_shift)
1668 24236869 bellard
{
1669 3512779a bellard
    if (!true_color_flag) {
1670 28a76be8 aliguori
        vnc_client_error(vs);
1671 3512779a bellard
        return;
1672 3512779a bellard
    }
1673 24236869 bellard
1674 1fc62412 Stefano Stabellini
    vs->clientds = *(vs->vd->guest.ds);
1675 6cec5487 aliguori
    vs->clientds.pf.rmax = red_max;
1676 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.rbits, red_max);
1677 6cec5487 aliguori
    vs->clientds.pf.rshift = red_shift;
1678 6cec5487 aliguori
    vs->clientds.pf.rmask = red_max << red_shift;
1679 6cec5487 aliguori
    vs->clientds.pf.gmax = green_max;
1680 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.gbits, green_max);
1681 6cec5487 aliguori
    vs->clientds.pf.gshift = green_shift;
1682 6cec5487 aliguori
    vs->clientds.pf.gmask = green_max << green_shift;
1683 6cec5487 aliguori
    vs->clientds.pf.bmax = blue_max;
1684 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.bbits, blue_max);
1685 6cec5487 aliguori
    vs->clientds.pf.bshift = blue_shift;
1686 6cec5487 aliguori
    vs->clientds.pf.bmask = blue_max << blue_shift;
1687 6cec5487 aliguori
    vs->clientds.pf.bits_per_pixel = bits_per_pixel;
1688 6cec5487 aliguori
    vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8;
1689 6cec5487 aliguori
    vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
1690 6cec5487 aliguori
    vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00;
1691 6cec5487 aliguori
1692 6cec5487 aliguori
    set_pixel_conversion(vs);
1693 24236869 bellard
1694 24236869 bellard
    vga_hw_invalidate();
1695 24236869 bellard
    vga_hw_update();
1696 24236869 bellard
}
1697 24236869 bellard
1698 ca4cca4d aliguori
static void pixel_format_message (VncState *vs) {
1699 ca4cca4d aliguori
    char pad[3] = { 0, 0, 0 };
1700 ca4cca4d aliguori
1701 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */
1702 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */
1703 ca4cca4d aliguori
1704 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
1705 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* big-endian-flag */
1706 ca4cca4d aliguori
#else
1707 ca4cca4d aliguori
    vnc_write_u8(vs, 0);             /* big-endian-flag */
1708 ca4cca4d aliguori
#endif
1709 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* true-color-flag */
1710 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.rmax);     /* red-max */
1711 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.gmax);     /* green-max */
1712 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.bmax);     /* blue-max */
1713 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.rshift);    /* red-shift */
1714 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.gshift);    /* green-shift */
1715 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.bshift);    /* blue-shift */
1716 6cec5487 aliguori
    if (vs->ds->surface->pf.bits_per_pixel == 32)
1717 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_32;
1718 6cec5487 aliguori
    else if (vs->ds->surface->pf.bits_per_pixel == 16)
1719 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_16;
1720 6cec5487 aliguori
    else if (vs->ds->surface->pf.bits_per_pixel == 8)
1721 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_8;
1722 6cec5487 aliguori
    vs->clientds = *(vs->ds->surface);
1723 3cded540 aurel32
    vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG;
1724 ca4cca4d aliguori
    vs->write_pixels = vnc_write_pixels_copy;
1725 ca4cca4d aliguori
1726 ca4cca4d aliguori
    vnc_write(vs, pad, 3);           /* padding */
1727 ca4cca4d aliguori
}
1728 ca4cca4d aliguori
1729 7d957bd8 aliguori
static void vnc_dpy_setdata(DisplayState *ds)
1730 7d957bd8 aliguori
{
1731 7d957bd8 aliguori
    /* We don't have to do anything */
1732 7d957bd8 aliguori
}
1733 7d957bd8 aliguori
1734 753b4053 aliguori
static void vnc_colordepth(VncState *vs)
1735 7eac3a87 aliguori
{
1736 753b4053 aliguori
    if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
1737 ca4cca4d aliguori
        /* Sending a WMVi message to notify the client*/
1738 ca4cca4d aliguori
        vnc_write_u8(vs, 0);  /* msg id */
1739 ca4cca4d aliguori
        vnc_write_u8(vs, 0);
1740 ca4cca4d aliguori
        vnc_write_u16(vs, 1); /* number of rects */
1741 753b4053 aliguori
        vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), 
1742 753b4053 aliguori
                               ds_get_height(vs->ds), VNC_ENCODING_WMVi);
1743 ca4cca4d aliguori
        pixel_format_message(vs);
1744 ca4cca4d aliguori
        vnc_flush(vs);
1745 7eac3a87 aliguori
    } else {
1746 6cec5487 aliguori
        set_pixel_conversion(vs);
1747 7eac3a87 aliguori
    }
1748 7eac3a87 aliguori
}
1749 7eac3a87 aliguori
1750 60fe76f3 ths
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1751 24236869 bellard
{
1752 24236869 bellard
    int i;
1753 24236869 bellard
    uint16_t limit;
1754 2430ffe4 Stefano Stabellini
    VncDisplay *vd = vs->vd;
1755 2430ffe4 Stefano Stabellini
1756 2430ffe4 Stefano Stabellini
    if (data[0] > 3) {
1757 2430ffe4 Stefano Stabellini
        vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1758 2430ffe4 Stefano Stabellini
        if (!qemu_timer_expired(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval))
1759 2430ffe4 Stefano Stabellini
            qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
1760 2430ffe4 Stefano Stabellini
    }
1761 24236869 bellard
1762 24236869 bellard
    switch (data[0]) {
1763 24236869 bellard
    case 0:
1764 28a76be8 aliguori
        if (len == 1)
1765 28a76be8 aliguori
            return 20;
1766 28a76be8 aliguori
1767 28a76be8 aliguori
        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1768 28a76be8 aliguori
                         read_u8(data, 6), read_u8(data, 7),
1769 28a76be8 aliguori
                         read_u16(data, 8), read_u16(data, 10),
1770 28a76be8 aliguori
                         read_u16(data, 12), read_u8(data, 14),
1771 28a76be8 aliguori
                         read_u8(data, 15), read_u8(data, 16));
1772 28a76be8 aliguori
        break;
1773 24236869 bellard
    case 2:
1774 28a76be8 aliguori
        if (len == 1)
1775 28a76be8 aliguori
            return 4;
1776 24236869 bellard
1777 28a76be8 aliguori
        if (len == 4) {
1778 69dd5c9f aliguori
            limit = read_u16(data, 2);
1779 69dd5c9f aliguori
            if (limit > 0)
1780 69dd5c9f aliguori
                return 4 + (limit * 4);
1781 69dd5c9f aliguori
        } else
1782 69dd5c9f aliguori
            limit = read_u16(data, 2);
1783 24236869 bellard
1784 28a76be8 aliguori
        for (i = 0; i < limit; i++) {
1785 28a76be8 aliguori
            int32_t val = read_s32(data, 4 + (i * 4));
1786 28a76be8 aliguori
            memcpy(data + 4 + (i * 4), &val, sizeof(val));
1787 28a76be8 aliguori
        }
1788 24236869 bellard
1789 28a76be8 aliguori
        set_encodings(vs, (int32_t *)(data + 4), limit);
1790 28a76be8 aliguori
        break;
1791 24236869 bellard
    case 3:
1792 28a76be8 aliguori
        if (len == 1)
1793 28a76be8 aliguori
            return 10;
1794 24236869 bellard
1795 28a76be8 aliguori
        framebuffer_update_request(vs,
1796 28a76be8 aliguori
                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1797 28a76be8 aliguori
                                   read_u16(data, 6), read_u16(data, 8));
1798 28a76be8 aliguori
        break;
1799 24236869 bellard
    case 4:
1800 28a76be8 aliguori
        if (len == 1)
1801 28a76be8 aliguori
            return 8;
1802 24236869 bellard
1803 28a76be8 aliguori
        key_event(vs, read_u8(data, 1), read_u32(data, 4));
1804 28a76be8 aliguori
        break;
1805 24236869 bellard
    case 5:
1806 28a76be8 aliguori
        if (len == 1)
1807 28a76be8 aliguori
            return 6;
1808 24236869 bellard
1809 28a76be8 aliguori
        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1810 28a76be8 aliguori
        break;
1811 24236869 bellard
    case 6:
1812 28a76be8 aliguori
        if (len == 1)
1813 28a76be8 aliguori
            return 8;
1814 24236869 bellard
1815 28a76be8 aliguori
        if (len == 8) {
1816 baa7666c ths
            uint32_t dlen = read_u32(data, 4);
1817 baa7666c ths
            if (dlen > 0)
1818 baa7666c ths
                return 8 + dlen;
1819 baa7666c ths
        }
1820 24236869 bellard
1821 28a76be8 aliguori
        client_cut_text(vs, read_u32(data, 4), data + 8);
1822 28a76be8 aliguori
        break;
1823 9ca313aa aliguori
    case 255:
1824 9ca313aa aliguori
        if (len == 1)
1825 9ca313aa aliguori
            return 2;
1826 9ca313aa aliguori
1827 9ca313aa aliguori
        switch (read_u8(data, 1)) {
1828 9ca313aa aliguori
        case 0:
1829 9ca313aa aliguori
            if (len == 2)
1830 9ca313aa aliguori
                return 12;
1831 9ca313aa aliguori
1832 9ca313aa aliguori
            ext_key_event(vs, read_u16(data, 2),
1833 9ca313aa aliguori
                          read_u32(data, 4), read_u32(data, 8));
1834 9ca313aa aliguori
            break;
1835 429a8ed3 malc
        case 1:
1836 429a8ed3 malc
            if (len == 2)
1837 429a8ed3 malc
                return 4;
1838 429a8ed3 malc
1839 429a8ed3 malc
            switch (read_u16 (data, 2)) {
1840 429a8ed3 malc
            case 0:
1841 429a8ed3 malc
                audio_add(vs);
1842 429a8ed3 malc
                break;
1843 429a8ed3 malc
            case 1:
1844 429a8ed3 malc
                audio_del(vs);
1845 429a8ed3 malc
                break;
1846 429a8ed3 malc
            case 2:
1847 429a8ed3 malc
                if (len == 4)
1848 429a8ed3 malc
                    return 10;
1849 429a8ed3 malc
                switch (read_u8(data, 4)) {
1850 429a8ed3 malc
                case 0: vs->as.fmt = AUD_FMT_U8; break;
1851 429a8ed3 malc
                case 1: vs->as.fmt = AUD_FMT_S8; break;
1852 429a8ed3 malc
                case 2: vs->as.fmt = AUD_FMT_U16; break;
1853 429a8ed3 malc
                case 3: vs->as.fmt = AUD_FMT_S16; break;
1854 429a8ed3 malc
                case 4: vs->as.fmt = AUD_FMT_U32; break;
1855 429a8ed3 malc
                case 5: vs->as.fmt = AUD_FMT_S32; break;
1856 429a8ed3 malc
                default:
1857 429a8ed3 malc
                    printf("Invalid audio format %d\n", read_u8(data, 4));
1858 429a8ed3 malc
                    vnc_client_error(vs);
1859 429a8ed3 malc
                    break;
1860 429a8ed3 malc
                }
1861 429a8ed3 malc
                vs->as.nchannels = read_u8(data, 5);
1862 429a8ed3 malc
                if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
1863 429a8ed3 malc
                    printf("Invalid audio channel coount %d\n",
1864 429a8ed3 malc
                           read_u8(data, 5));
1865 429a8ed3 malc
                    vnc_client_error(vs);
1866 429a8ed3 malc
                    break;
1867 429a8ed3 malc
                }
1868 429a8ed3 malc
                vs->as.freq = read_u32(data, 6);
1869 429a8ed3 malc
                break;
1870 429a8ed3 malc
            default:
1871 429a8ed3 malc
                printf ("Invalid audio message %d\n", read_u8(data, 4));
1872 429a8ed3 malc
                vnc_client_error(vs);
1873 429a8ed3 malc
                break;
1874 429a8ed3 malc
            }
1875 429a8ed3 malc
            break;
1876 429a8ed3 malc
1877 9ca313aa aliguori
        default:
1878 9ca313aa aliguori
            printf("Msg: %d\n", read_u16(data, 0));
1879 9ca313aa aliguori
            vnc_client_error(vs);
1880 9ca313aa aliguori
            break;
1881 9ca313aa aliguori
        }
1882 9ca313aa aliguori
        break;
1883 24236869 bellard
    default:
1884 28a76be8 aliguori
        printf("Msg: %d\n", data[0]);
1885 28a76be8 aliguori
        vnc_client_error(vs);
1886 28a76be8 aliguori
        break;
1887 24236869 bellard
    }
1888 5fafdf24 ths
1889 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1890 24236869 bellard
    return 0;
1891 24236869 bellard
}
1892 24236869 bellard
1893 60fe76f3 ths
static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1894 24236869 bellard
{
1895 c35734b2 ths
    char buf[1024];
1896 c35734b2 ths
    int size;
1897 24236869 bellard
1898 0e1f5a0c aliguori
    vnc_write_u16(vs, ds_get_width(vs->ds));
1899 0e1f5a0c aliguori
    vnc_write_u16(vs, ds_get_height(vs->ds));
1900 24236869 bellard
1901 ca4cca4d aliguori
    pixel_format_message(vs);
1902 24236869 bellard
1903 c35734b2 ths
    if (qemu_name)
1904 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
1905 c35734b2 ths
    else
1906 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU");
1907 c35734b2 ths
1908 c35734b2 ths
    vnc_write_u32(vs, size);
1909 c35734b2 ths
    vnc_write(vs, buf, size);
1910 24236869 bellard
    vnc_flush(vs);
1911 24236869 bellard
1912 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1913 24236869 bellard
1914 24236869 bellard
    return 0;
1915 24236869 bellard
}
1916 24236869 bellard
1917 5fb6c7a8 aliguori
void start_client_init(VncState *vs)
1918 5fb6c7a8 aliguori
{
1919 5fb6c7a8 aliguori
    vnc_read_when(vs, protocol_client_init, 1);
1920 5fb6c7a8 aliguori
}
1921 5fb6c7a8 aliguori
1922 70848515 ths
static void make_challenge(VncState *vs)
1923 70848515 ths
{
1924 70848515 ths
    int i;
1925 70848515 ths
1926 70848515 ths
    srand(time(NULL)+getpid()+getpid()*987654+rand());
1927 70848515 ths
1928 70848515 ths
    for (i = 0 ; i < sizeof(vs->challenge) ; i++)
1929 70848515 ths
        vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1930 70848515 ths
}
1931 70848515 ths
1932 60fe76f3 ths
static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1933 70848515 ths
{
1934 60fe76f3 ths
    unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
1935 70848515 ths
    int i, j, pwlen;
1936 60fe76f3 ths
    unsigned char key[8];
1937 70848515 ths
1938 753b4053 aliguori
    if (!vs->vd->password || !vs->vd->password[0]) {
1939 28a76be8 aliguori
        VNC_DEBUG("No password configured on server");
1940 28a76be8 aliguori
        vnc_write_u32(vs, 1); /* Reject auth */
1941 28a76be8 aliguori
        if (vs->minor >= 8) {
1942 28a76be8 aliguori
            static const char err[] = "Authentication failed";
1943 28a76be8 aliguori
            vnc_write_u32(vs, sizeof(err));
1944 28a76be8 aliguori
            vnc_write(vs, err, sizeof(err));
1945 28a76be8 aliguori
        }
1946 28a76be8 aliguori
        vnc_flush(vs);
1947 28a76be8 aliguori
        vnc_client_error(vs);
1948 28a76be8 aliguori
        return 0;
1949 70848515 ths
    }
1950 70848515 ths
1951 70848515 ths
    memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
1952 70848515 ths
1953 70848515 ths
    /* Calculate the expected challenge response */
1954 753b4053 aliguori
    pwlen = strlen(vs->vd->password);
1955 70848515 ths
    for (i=0; i<sizeof(key); i++)
1956 753b4053 aliguori
        key[i] = i<pwlen ? vs->vd->password[i] : 0;
1957 70848515 ths
    deskey(key, EN0);
1958 70848515 ths
    for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
1959 70848515 ths
        des(response+j, response+j);
1960 70848515 ths
1961 70848515 ths
    /* Compare expected vs actual challenge response */
1962 70848515 ths
    if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
1963 28a76be8 aliguori
        VNC_DEBUG("Client challenge reponse did not match\n");
1964 28a76be8 aliguori
        vnc_write_u32(vs, 1); /* Reject auth */
1965 28a76be8 aliguori
        if (vs->minor >= 8) {
1966 28a76be8 aliguori
            static const char err[] = "Authentication failed";
1967 28a76be8 aliguori
            vnc_write_u32(vs, sizeof(err));
1968 28a76be8 aliguori
            vnc_write(vs, err, sizeof(err));
1969 28a76be8 aliguori
        }
1970 28a76be8 aliguori
        vnc_flush(vs);
1971 28a76be8 aliguori
        vnc_client_error(vs);
1972 70848515 ths
    } else {
1973 28a76be8 aliguori
        VNC_DEBUG("Accepting VNC challenge response\n");
1974 28a76be8 aliguori
        vnc_write_u32(vs, 0); /* Accept auth */
1975 28a76be8 aliguori
        vnc_flush(vs);
1976 70848515 ths
1977 5fb6c7a8 aliguori
        start_client_init(vs);
1978 70848515 ths
    }
1979 70848515 ths
    return 0;
1980 70848515 ths
}
1981 70848515 ths
1982 5fb6c7a8 aliguori
void start_auth_vnc(VncState *vs)
1983 70848515 ths
{
1984 70848515 ths
    make_challenge(vs);
1985 70848515 ths
    /* Send client a 'random' challenge */
1986 70848515 ths
    vnc_write(vs, vs->challenge, sizeof(vs->challenge));
1987 70848515 ths
    vnc_flush(vs);
1988 70848515 ths
1989 70848515 ths
    vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
1990 469b15c6 ths
}
1991 469b15c6 ths
1992 469b15c6 ths
1993 60fe76f3 ths
static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
1994 70848515 ths
{
1995 70848515 ths
    /* We only advertise 1 auth scheme at a time, so client
1996 70848515 ths
     * must pick the one we sent. Verify this */
1997 753b4053 aliguori
    if (data[0] != vs->vd->auth) { /* Reject auth */
1998 1263b7d6 aliguori
       VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
1999 70848515 ths
       vnc_write_u32(vs, 1);
2000 70848515 ths
       if (vs->minor >= 8) {
2001 70848515 ths
           static const char err[] = "Authentication failed";
2002 70848515 ths
           vnc_write_u32(vs, sizeof(err));
2003 70848515 ths
           vnc_write(vs, err, sizeof(err));
2004 70848515 ths
       }
2005 70848515 ths
       vnc_client_error(vs);
2006 70848515 ths
    } else { /* Accept requested auth */
2007 70848515 ths
       VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2008 753b4053 aliguori
       switch (vs->vd->auth) {
2009 70848515 ths
       case VNC_AUTH_NONE:
2010 70848515 ths
           VNC_DEBUG("Accept auth none\n");
2011 a26c97ad balrog
           if (vs->minor >= 8) {
2012 a26c97ad balrog
               vnc_write_u32(vs, 0); /* Accept auth completion */
2013 a26c97ad balrog
               vnc_flush(vs);
2014 a26c97ad balrog
           }
2015 5fb6c7a8 aliguori
           start_client_init(vs);
2016 70848515 ths
           break;
2017 70848515 ths
2018 70848515 ths
       case VNC_AUTH_VNC:
2019 70848515 ths
           VNC_DEBUG("Start VNC auth\n");
2020 5fb6c7a8 aliguori
           start_auth_vnc(vs);
2021 5fb6c7a8 aliguori
           break;
2022 70848515 ths
2023 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2024 8d5d2d4c ths
       case VNC_AUTH_VENCRYPT:
2025 8d5d2d4c ths
           VNC_DEBUG("Accept VeNCrypt auth\n");;
2026 5fb6c7a8 aliguori
           start_auth_vencrypt(vs);
2027 5fb6c7a8 aliguori
           break;
2028 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2029 8d5d2d4c ths
2030 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2031 2f9606b3 aliguori
       case VNC_AUTH_SASL:
2032 2f9606b3 aliguori
           VNC_DEBUG("Accept SASL auth\n");
2033 2f9606b3 aliguori
           start_auth_sasl(vs);
2034 2f9606b3 aliguori
           break;
2035 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
2036 2f9606b3 aliguori
2037 70848515 ths
       default: /* Should not be possible, but just in case */
2038 1263b7d6 aliguori
           VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth);
2039 70848515 ths
           vnc_write_u8(vs, 1);
2040 70848515 ths
           if (vs->minor >= 8) {
2041 70848515 ths
               static const char err[] = "Authentication failed";
2042 70848515 ths
               vnc_write_u32(vs, sizeof(err));
2043 70848515 ths
               vnc_write(vs, err, sizeof(err));
2044 70848515 ths
           }
2045 70848515 ths
           vnc_client_error(vs);
2046 70848515 ths
       }
2047 70848515 ths
    }
2048 70848515 ths
    return 0;
2049 70848515 ths
}
2050 70848515 ths
2051 60fe76f3 ths
static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2052 24236869 bellard
{
2053 24236869 bellard
    char local[13];
2054 24236869 bellard
2055 24236869 bellard
    memcpy(local, version, 12);
2056 24236869 bellard
    local[12] = 0;
2057 24236869 bellard
2058 70848515 ths
    if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
2059 28a76be8 aliguori
        VNC_DEBUG("Malformed protocol version %s\n", local);
2060 28a76be8 aliguori
        vnc_client_error(vs);
2061 28a76be8 aliguori
        return 0;
2062 24236869 bellard
    }
2063 70848515 ths
    VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2064 70848515 ths
    if (vs->major != 3 ||
2065 28a76be8 aliguori
        (vs->minor != 3 &&
2066 28a76be8 aliguori
         vs->minor != 4 &&
2067 28a76be8 aliguori
         vs->minor != 5 &&
2068 28a76be8 aliguori
         vs->minor != 7 &&
2069 28a76be8 aliguori
         vs->minor != 8)) {
2070 28a76be8 aliguori
        VNC_DEBUG("Unsupported client version\n");
2071 28a76be8 aliguori
        vnc_write_u32(vs, VNC_AUTH_INVALID);
2072 28a76be8 aliguori
        vnc_flush(vs);
2073 28a76be8 aliguori
        vnc_client_error(vs);
2074 28a76be8 aliguori
        return 0;
2075 70848515 ths
    }
2076 b0566f4f ths
    /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
2077 70848515 ths
     * as equivalent to v3.3 by servers
2078 70848515 ths
     */
2079 b0566f4f ths
    if (vs->minor == 4 || vs->minor == 5)
2080 28a76be8 aliguori
        vs->minor = 3;
2081 70848515 ths
2082 70848515 ths
    if (vs->minor == 3) {
2083 28a76be8 aliguori
        if (vs->vd->auth == VNC_AUTH_NONE) {
2084 70848515 ths
            VNC_DEBUG("Tell client auth none\n");
2085 753b4053 aliguori
            vnc_write_u32(vs, vs->vd->auth);
2086 70848515 ths
            vnc_flush(vs);
2087 28a76be8 aliguori
            start_client_init(vs);
2088 753b4053 aliguori
       } else if (vs->vd->auth == VNC_AUTH_VNC) {
2089 70848515 ths
            VNC_DEBUG("Tell client VNC auth\n");
2090 753b4053 aliguori
            vnc_write_u32(vs, vs->vd->auth);
2091 70848515 ths
            vnc_flush(vs);
2092 70848515 ths
            start_auth_vnc(vs);
2093 70848515 ths
       } else {
2094 753b4053 aliguori
            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth);
2095 70848515 ths
            vnc_write_u32(vs, VNC_AUTH_INVALID);
2096 70848515 ths
            vnc_flush(vs);
2097 70848515 ths
            vnc_client_error(vs);
2098 70848515 ths
       }
2099 70848515 ths
    } else {
2100 28a76be8 aliguori
        VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth);
2101 28a76be8 aliguori
        vnc_write_u8(vs, 1); /* num auth */
2102 28a76be8 aliguori
        vnc_write_u8(vs, vs->vd->auth);
2103 28a76be8 aliguori
        vnc_read_when(vs, protocol_client_auth, 1);
2104 28a76be8 aliguori
        vnc_flush(vs);
2105 70848515 ths
    }
2106 24236869 bellard
2107 24236869 bellard
    return 0;
2108 24236869 bellard
}
2109 24236869 bellard
2110 1fc62412 Stefano Stabellini
static int vnc_refresh_server_surface(VncDisplay *vd)
2111 1fc62412 Stefano Stabellini
{
2112 1fc62412 Stefano Stabellini
    int y;
2113 1fc62412 Stefano Stabellini
    uint8_t *guest_row;
2114 1fc62412 Stefano Stabellini
    uint8_t *server_row;
2115 1fc62412 Stefano Stabellini
    int cmp_bytes;
2116 1fc62412 Stefano Stabellini
    uint32_t width_mask[VNC_DIRTY_WORDS];
2117 1fc62412 Stefano Stabellini
    VncState *vs = NULL;
2118 1fc62412 Stefano Stabellini
    int has_dirty = 0;
2119 1fc62412 Stefano Stabellini
2120 1fc62412 Stefano Stabellini
    /*
2121 1fc62412 Stefano Stabellini
     * Walk through the guest dirty map.
2122 1fc62412 Stefano Stabellini
     * Check and copy modified bits from guest to server surface.
2123 1fc62412 Stefano Stabellini
     * Update server dirty map.
2124 1fc62412 Stefano Stabellini
     */
2125 1fc62412 Stefano Stabellini
    vnc_set_bits(width_mask, (ds_get_width(vd->ds) / 16), VNC_DIRTY_WORDS);
2126 1fc62412 Stefano Stabellini
    cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
2127 1fc62412 Stefano Stabellini
    guest_row  = vd->guest.ds->data;
2128 1fc62412 Stefano Stabellini
    server_row = vd->server->data;
2129 1fc62412 Stefano Stabellini
    for (y = 0; y < vd->guest.ds->height; y++) {
2130 1fc62412 Stefano Stabellini
        if (vnc_and_bits(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
2131 1fc62412 Stefano Stabellini
            int x;
2132 1fc62412 Stefano Stabellini
            uint8_t *guest_ptr;
2133 1fc62412 Stefano Stabellini
            uint8_t *server_ptr;
2134 1fc62412 Stefano Stabellini
2135 1fc62412 Stefano Stabellini
            guest_ptr  = guest_row;
2136 1fc62412 Stefano Stabellini
            server_ptr = server_row;
2137 1fc62412 Stefano Stabellini
2138 1fc62412 Stefano Stabellini
            for (x = 0; x < vd->guest.ds->width;
2139 1fc62412 Stefano Stabellini
                    x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
2140 1fc62412 Stefano Stabellini
                if (!vnc_get_bit(vd->guest.dirty[y], (x / 16)))
2141 1fc62412 Stefano Stabellini
                    continue;
2142 1fc62412 Stefano Stabellini
                vnc_clear_bit(vd->guest.dirty[y], (x / 16));
2143 1fc62412 Stefano Stabellini
                if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
2144 1fc62412 Stefano Stabellini
                    continue;
2145 1fc62412 Stefano Stabellini
                memcpy(server_ptr, guest_ptr, cmp_bytes);
2146 1fc62412 Stefano Stabellini
                vs = vd->clients;
2147 1fc62412 Stefano Stabellini
                while (vs != NULL) {
2148 1fc62412 Stefano Stabellini
                    vnc_set_bit(vs->dirty[y], (x / 16));
2149 1fc62412 Stefano Stabellini
                    vs = vs->next;
2150 1fc62412 Stefano Stabellini
                }
2151 1fc62412 Stefano Stabellini
                has_dirty++;
2152 1fc62412 Stefano Stabellini
            }
2153 1fc62412 Stefano Stabellini
        }
2154 1fc62412 Stefano Stabellini
        guest_row  += ds_get_linesize(vd->ds);
2155 1fc62412 Stefano Stabellini
        server_row += ds_get_linesize(vd->ds);
2156 1fc62412 Stefano Stabellini
    }
2157 1fc62412 Stefano Stabellini
    return has_dirty;
2158 1fc62412 Stefano Stabellini
}
2159 1fc62412 Stefano Stabellini
2160 703bc68f Stefano Stabellini
static void vnc_refresh(void *opaque)
2161 703bc68f Stefano Stabellini
{
2162 703bc68f Stefano Stabellini
    VncDisplay *vd = opaque;
2163 1fc62412 Stefano Stabellini
    VncState *vs = NULL;
2164 2430ffe4 Stefano Stabellini
    int has_dirty = 0, rects = 0;
2165 703bc68f Stefano Stabellini
2166 703bc68f Stefano Stabellini
    vga_hw_update();
2167 703bc68f Stefano Stabellini
2168 1fc62412 Stefano Stabellini
    has_dirty = vnc_refresh_server_surface(vd);
2169 1fc62412 Stefano Stabellini
2170 1fc62412 Stefano Stabellini
    vs = vd->clients;
2171 703bc68f Stefano Stabellini
    while (vs != NULL) {
2172 2430ffe4 Stefano Stabellini
        rects += vnc_update_client(vs, has_dirty);
2173 703bc68f Stefano Stabellini
        vs = vs->next;
2174 703bc68f Stefano Stabellini
    }
2175 703bc68f Stefano Stabellini
2176 2430ffe4 Stefano Stabellini
    if (has_dirty && rects) {
2177 2430ffe4 Stefano Stabellini
        vd->timer_interval /= 2;
2178 2430ffe4 Stefano Stabellini
        if (vd->timer_interval < VNC_REFRESH_INTERVAL_BASE)
2179 2430ffe4 Stefano Stabellini
            vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
2180 2430ffe4 Stefano Stabellini
    } else {
2181 2430ffe4 Stefano Stabellini
        vd->timer_interval += VNC_REFRESH_INTERVAL_INC;
2182 2430ffe4 Stefano Stabellini
        if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX)
2183 2430ffe4 Stefano Stabellini
            vd->timer_interval = VNC_REFRESH_INTERVAL_MAX;
2184 2430ffe4 Stefano Stabellini
    }
2185 2430ffe4 Stefano Stabellini
    qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
2186 703bc68f Stefano Stabellini
}
2187 703bc68f Stefano Stabellini
2188 703bc68f Stefano Stabellini
static void vnc_init_timer(VncDisplay *vd)
2189 703bc68f Stefano Stabellini
{
2190 2430ffe4 Stefano Stabellini
    vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
2191 703bc68f Stefano Stabellini
    if (vd->timer == NULL && vd->clients != NULL) {
2192 703bc68f Stefano Stabellini
        vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
2193 1fc62412 Stefano Stabellini
        vnc_refresh(vd);
2194 703bc68f Stefano Stabellini
    }
2195 703bc68f Stefano Stabellini
}
2196 703bc68f Stefano Stabellini
2197 703bc68f Stefano Stabellini
static void vnc_remove_timer(VncDisplay *vd)
2198 703bc68f Stefano Stabellini
{
2199 703bc68f Stefano Stabellini
    if (vd->timer != NULL && vd->clients == NULL) {
2200 703bc68f Stefano Stabellini
        qemu_del_timer(vd->timer);
2201 703bc68f Stefano Stabellini
        qemu_free_timer(vd->timer);
2202 703bc68f Stefano Stabellini
        vd->timer = NULL;
2203 703bc68f Stefano Stabellini
    }
2204 703bc68f Stefano Stabellini
}
2205 703bc68f Stefano Stabellini
2206 753b4053 aliguori
static void vnc_connect(VncDisplay *vd, int csock)
2207 3aa3eea3 balrog
{
2208 753b4053 aliguori
    VncState *vs = qemu_mallocz(sizeof(VncState));
2209 753b4053 aliguori
    vs->csock = csock;
2210 753b4053 aliguori
2211 753b4053 aliguori
    VNC_DEBUG("New client on socket %d\n", csock);
2212 7d957bd8 aliguori
    dcl->idle = 0;
2213 3aa3eea3 balrog
    socket_set_nonblock(vs->csock);
2214 3aa3eea3 balrog
    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
2215 753b4053 aliguori
2216 753b4053 aliguori
    vs->vd = vd;
2217 753b4053 aliguori
    vs->ds = vd->ds;
2218 753b4053 aliguori
    vs->last_x = -1;
2219 753b4053 aliguori
    vs->last_y = -1;
2220 753b4053 aliguori
2221 753b4053 aliguori
    vs->as.freq = 44100;
2222 753b4053 aliguori
    vs->as.nchannels = 2;
2223 753b4053 aliguori
    vs->as.fmt = AUD_FMT_S16;
2224 753b4053 aliguori
    vs->as.endianness = 0;
2225 753b4053 aliguori
2226 1fc62412 Stefano Stabellini
    vs->next = vd->clients;
2227 1fc62412 Stefano Stabellini
    vd->clients = vs;
2228 1fc62412 Stefano Stabellini
2229 1fc62412 Stefano Stabellini
    vga_hw_update();
2230 1fc62412 Stefano Stabellini
2231 3aa3eea3 balrog
    vnc_write(vs, "RFB 003.008\n", 12);
2232 3aa3eea3 balrog
    vnc_flush(vs);
2233 3aa3eea3 balrog
    vnc_read_when(vs, protocol_version, 12);
2234 53762ddb malc
    reset_keys(vs);
2235 753b4053 aliguori
2236 703bc68f Stefano Stabellini
    vnc_init_timer(vd);
2237 1fc62412 Stefano Stabellini
2238 198a0039 Gerd Hoffmann
    /* vs might be free()ed here */
2239 3aa3eea3 balrog
}
2240 3aa3eea3 balrog
2241 24236869 bellard
static void vnc_listen_read(void *opaque)
2242 24236869 bellard
{
2243 753b4053 aliguori
    VncDisplay *vs = opaque;
2244 24236869 bellard
    struct sockaddr_in addr;
2245 24236869 bellard
    socklen_t addrlen = sizeof(addr);
2246 24236869 bellard
2247 9f60ad50 balrog
    /* Catch-up */
2248 9f60ad50 balrog
    vga_hw_update();
2249 9f60ad50 balrog
2250 753b4053 aliguori
    int csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2251 753b4053 aliguori
    if (csock != -1) {
2252 753b4053 aliguori
        vnc_connect(vs, csock);
2253 24236869 bellard
    }
2254 24236869 bellard
}
2255 24236869 bellard
2256 71cab5ca ths
void vnc_display_init(DisplayState *ds)
2257 24236869 bellard
{
2258 afd32160 Stefan Weil
    VncDisplay *vs = qemu_mallocz(sizeof(*vs));
2259 24236869 bellard
2260 7d957bd8 aliguori
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2261 24236869 bellard
2262 24236869 bellard
    ds->opaque = vs;
2263 7d957bd8 aliguori
    dcl->idle = 1;
2264 753b4053 aliguori
    vnc_display = vs;
2265 24236869 bellard
2266 24236869 bellard
    vs->lsock = -1;
2267 24236869 bellard
2268 24236869 bellard
    vs->ds = ds;
2269 24236869 bellard
2270 9ca313aa aliguori
    if (keyboard_layout)
2271 0483755a aliguori
        vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
2272 9ca313aa aliguori
    else
2273 0483755a aliguori
        vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us");
2274 24236869 bellard
2275 24236869 bellard
    if (!vs->kbd_layout)
2276 28a76be8 aliguori
        exit(1);
2277 24236869 bellard
2278 753b4053 aliguori
    dcl->dpy_copy = vnc_dpy_copy;
2279 7d957bd8 aliguori
    dcl->dpy_update = vnc_dpy_update;
2280 7d957bd8 aliguori
    dcl->dpy_resize = vnc_dpy_resize;
2281 7d957bd8 aliguori
    dcl->dpy_setdata = vnc_dpy_setdata;
2282 7d957bd8 aliguori
    register_displaychangelistener(ds, dcl);
2283 71cab5ca ths
}
2284 71cab5ca ths
2285 6f43024c ths
2286 71cab5ca ths
void vnc_display_close(DisplayState *ds)
2287 71cab5ca ths
{
2288 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2289 71cab5ca ths
2290 452b4d88 aliguori
    if (!vs)
2291 452b4d88 aliguori
        return;
2292 71cab5ca ths
    if (vs->display) {
2293 28a76be8 aliguori
        qemu_free(vs->display);
2294 28a76be8 aliguori
        vs->display = NULL;
2295 71cab5ca ths
    }
2296 71cab5ca ths
    if (vs->lsock != -1) {
2297 28a76be8 aliguori
        qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2298 28a76be8 aliguori
        close(vs->lsock);
2299 28a76be8 aliguori
        vs->lsock = -1;
2300 71cab5ca ths
    }
2301 70848515 ths
    vs->auth = VNC_AUTH_INVALID;
2302 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2303 8d5d2d4c ths
    vs->subauth = VNC_AUTH_INVALID;
2304 5fb6c7a8 aliguori
    vs->tls.x509verify = 0;
2305 8d5d2d4c ths
#endif
2306 70848515 ths
}
2307 70848515 ths
2308 70848515 ths
int vnc_display_password(DisplayState *ds, const char *password)
2309 70848515 ths
{
2310 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2311 70848515 ths
2312 7ef92331 Zachary Amsden
    if (!vs) {
2313 7ef92331 Zachary Amsden
        return -1;
2314 7ef92331 Zachary Amsden
    }
2315 7ef92331 Zachary Amsden
2316 70848515 ths
    if (vs->password) {
2317 28a76be8 aliguori
        qemu_free(vs->password);
2318 28a76be8 aliguori
        vs->password = NULL;
2319 70848515 ths
    }
2320 70848515 ths
    if (password && password[0]) {
2321 28a76be8 aliguori
        if (!(vs->password = qemu_strdup(password)))
2322 28a76be8 aliguori
            return -1;
2323 52c18be9 Zachary Amsden
        if (vs->auth == VNC_AUTH_NONE) {
2324 52c18be9 Zachary Amsden
            vs->auth = VNC_AUTH_VNC;
2325 52c18be9 Zachary Amsden
        }
2326 52c18be9 Zachary Amsden
    } else {
2327 52c18be9 Zachary Amsden
        vs->auth = VNC_AUTH_NONE;
2328 70848515 ths
    }
2329 70848515 ths
2330 70848515 ths
    return 0;
2331 71cab5ca ths
}
2332 71cab5ca ths
2333 f92f8afe Anthony Liguori
char *vnc_display_local_addr(DisplayState *ds)
2334 f92f8afe Anthony Liguori
{
2335 f92f8afe Anthony Liguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2336 f92f8afe Anthony Liguori
    
2337 f92f8afe Anthony Liguori
    return vnc_socket_local_addr("%s:%s", vs->lsock);
2338 f92f8afe Anthony Liguori
}
2339 f92f8afe Anthony Liguori
2340 70848515 ths
int vnc_display_open(DisplayState *ds, const char *display)
2341 71cab5ca ths
{
2342 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2343 70848515 ths
    const char *options;
2344 70848515 ths
    int password = 0;
2345 3aa3eea3 balrog
    int reverse = 0;
2346 9712ecaf aliguori
    int to_port = 0;
2347 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2348 3a702699 ths
    int tls = 0, x509 = 0;
2349 8d5d2d4c ths
#endif
2350 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2351 2f9606b3 aliguori
    int sasl = 0;
2352 2f9606b3 aliguori
    int saslErr;
2353 2f9606b3 aliguori
#endif
2354 76655d6d aliguori
    int acl = 0;
2355 71cab5ca ths
2356 753b4053 aliguori
    if (!vnc_display)
2357 452b4d88 aliguori
        return -1;
2358 71cab5ca ths
    vnc_display_close(ds);
2359 70848515 ths
    if (strcmp(display, "none") == 0)
2360 28a76be8 aliguori
        return 0;
2361 24236869 bellard
2362 70848515 ths
    if (!(vs->display = strdup(display)))
2363 28a76be8 aliguori
        return -1;
2364 70848515 ths
2365 70848515 ths
    options = display;
2366 70848515 ths
    while ((options = strchr(options, ','))) {
2367 28a76be8 aliguori
        options++;
2368 28a76be8 aliguori
        if (strncmp(options, "password", 8) == 0) {
2369 28a76be8 aliguori
            password = 1; /* Require password auth */
2370 28a76be8 aliguori
        } else if (strncmp(options, "reverse", 7) == 0) {
2371 28a76be8 aliguori
            reverse = 1;
2372 28a76be8 aliguori
        } else if (strncmp(options, "to=", 3) == 0) {
2373 9712ecaf aliguori
            to_port = atoi(options+3) + 5900;
2374 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2375 28a76be8 aliguori
        } else if (strncmp(options, "sasl", 4) == 0) {
2376 28a76be8 aliguori
            sasl = 1; /* Require SASL auth */
2377 2f9606b3 aliguori
#endif
2378 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2379 28a76be8 aliguori
        } else if (strncmp(options, "tls", 3) == 0) {
2380 28a76be8 aliguori
            tls = 1; /* Require TLS */
2381 28a76be8 aliguori
        } else if (strncmp(options, "x509", 4) == 0) {
2382 28a76be8 aliguori
            char *start, *end;
2383 28a76be8 aliguori
            x509 = 1; /* Require x509 certificates */
2384 28a76be8 aliguori
            if (strncmp(options, "x509verify", 10) == 0)
2385 28a76be8 aliguori
                vs->tls.x509verify = 1; /* ...and verify client certs */
2386 28a76be8 aliguori
2387 28a76be8 aliguori
            /* Now check for 'x509=/some/path' postfix
2388 28a76be8 aliguori
             * and use that to setup x509 certificate/key paths */
2389 28a76be8 aliguori
            start = strchr(options, '=');
2390 28a76be8 aliguori
            end = strchr(options, ',');
2391 28a76be8 aliguori
            if (start && (!end || (start < end))) {
2392 28a76be8 aliguori
                int len = end ? end-(start+1) : strlen(start+1);
2393 28a76be8 aliguori
                char *path = qemu_strndup(start + 1, len);
2394 28a76be8 aliguori
2395 28a76be8 aliguori
                VNC_DEBUG("Trying certificate path '%s'\n", path);
2396 28a76be8 aliguori
                if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
2397 28a76be8 aliguori
                    fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2398 28a76be8 aliguori
                    qemu_free(path);
2399 28a76be8 aliguori
                    qemu_free(vs->display);
2400 28a76be8 aliguori
                    vs->display = NULL;
2401 28a76be8 aliguori
                    return -1;
2402 28a76be8 aliguori
                }
2403 28a76be8 aliguori
                qemu_free(path);
2404 28a76be8 aliguori
            } else {
2405 28a76be8 aliguori
                fprintf(stderr, "No certificate path provided\n");
2406 28a76be8 aliguori
                qemu_free(vs->display);
2407 28a76be8 aliguori
                vs->display = NULL;
2408 28a76be8 aliguori
                return -1;
2409 28a76be8 aliguori
            }
2410 8d5d2d4c ths
#endif
2411 28a76be8 aliguori
        } else if (strncmp(options, "acl", 3) == 0) {
2412 28a76be8 aliguori
            acl = 1;
2413 28a76be8 aliguori
        }
2414 70848515 ths
    }
2415 70848515 ths
2416 76655d6d aliguori
#ifdef CONFIG_VNC_TLS
2417 76655d6d aliguori
    if (acl && x509 && vs->tls.x509verify) {
2418 28a76be8 aliguori
        if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) {
2419 28a76be8 aliguori
            fprintf(stderr, "Failed to create x509 dname ACL\n");
2420 28a76be8 aliguori
            exit(1);
2421 28a76be8 aliguori
        }
2422 76655d6d aliguori
    }
2423 76655d6d aliguori
#endif
2424 76655d6d aliguori
#ifdef CONFIG_VNC_SASL
2425 76655d6d aliguori
    if (acl && sasl) {
2426 28a76be8 aliguori
        if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) {
2427 28a76be8 aliguori
            fprintf(stderr, "Failed to create username ACL\n");
2428 28a76be8 aliguori
            exit(1);
2429 28a76be8 aliguori
        }
2430 76655d6d aliguori
    }
2431 76655d6d aliguori
#endif
2432 76655d6d aliguori
2433 2f9606b3 aliguori
    /*
2434 2f9606b3 aliguori
     * Combinations we support here:
2435 2f9606b3 aliguori
     *
2436 2f9606b3 aliguori
     *  - no-auth                (clear text, no auth)
2437 2f9606b3 aliguori
     *  - password               (clear text, weak auth)
2438 2f9606b3 aliguori
     *  - sasl                   (encrypt, good auth *IF* using Kerberos via GSSAPI)
2439 2f9606b3 aliguori
     *  - tls                    (encrypt, weak anonymous creds, no auth)
2440 2f9606b3 aliguori
     *  - tls + password         (encrypt, weak anonymous creds, weak auth)
2441 2f9606b3 aliguori
     *  - tls + sasl             (encrypt, weak anonymous creds, good auth)
2442 2f9606b3 aliguori
     *  - tls + x509             (encrypt, good x509 creds, no auth)
2443 2f9606b3 aliguori
     *  - tls + x509 + password  (encrypt, good x509 creds, weak auth)
2444 2f9606b3 aliguori
     *  - tls + x509 + sasl      (encrypt, good x509 creds, good auth)
2445 2f9606b3 aliguori
     *
2446 2f9606b3 aliguori
     * NB1. TLS is a stackable auth scheme.
2447 2f9606b3 aliguori
     * NB2. the x509 schemes have option to validate a client cert dname
2448 2f9606b3 aliguori
     */
2449 70848515 ths
    if (password) {
2450 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2451 28a76be8 aliguori
        if (tls) {
2452 28a76be8 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2453 28a76be8 aliguori
            if (x509) {
2454 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 password auth\n");
2455 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
2456 28a76be8 aliguori
            } else {
2457 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS password auth\n");
2458 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
2459 28a76be8 aliguori
            }
2460 28a76be8 aliguori
        } else {
2461 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2462 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with password auth\n");
2463 28a76be8 aliguori
            vs->auth = VNC_AUTH_VNC;
2464 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2465 28a76be8 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2466 28a76be8 aliguori
        }
2467 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2468 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2469 2f9606b3 aliguori
    } else if (sasl) {
2470 2f9606b3 aliguori
#ifdef CONFIG_VNC_TLS
2471 2f9606b3 aliguori
        if (tls) {
2472 2f9606b3 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2473 2f9606b3 aliguori
            if (x509) {
2474 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 SASL auth\n");
2475 2f9606b3 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509SASL;
2476 2f9606b3 aliguori
            } else {
2477 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS SASL auth\n");
2478 2f9606b3 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL;
2479 2f9606b3 aliguori
            }
2480 2f9606b3 aliguori
        } else {
2481 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2482 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with SASL auth\n");
2483 2f9606b3 aliguori
            vs->auth = VNC_AUTH_SASL;
2484 2f9606b3 aliguori
#ifdef CONFIG_VNC_TLS
2485 2f9606b3 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2486 2f9606b3 aliguori
        }
2487 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2488 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
2489 70848515 ths
    } else {
2490 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2491 28a76be8 aliguori
        if (tls) {
2492 28a76be8 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2493 28a76be8 aliguori
            if (x509) {
2494 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 no auth\n");
2495 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
2496 28a76be8 aliguori
            } else {
2497 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS no auth\n");
2498 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
2499 28a76be8 aliguori
            }
2500 28a76be8 aliguori
        } else {
2501 8d5d2d4c ths
#endif
2502 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with no auth\n");
2503 28a76be8 aliguori
            vs->auth = VNC_AUTH_NONE;
2504 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2505 28a76be8 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2506 28a76be8 aliguori
        }
2507 8d5d2d4c ths
#endif
2508 70848515 ths
    }
2509 24236869 bellard
2510 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2511 2f9606b3 aliguori
    if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) {
2512 2f9606b3 aliguori
        fprintf(stderr, "Failed to initialize SASL auth %s",
2513 2f9606b3 aliguori
                sasl_errstring(saslErr, NULL, NULL));
2514 2f9606b3 aliguori
        free(vs->display);
2515 2f9606b3 aliguori
        vs->display = NULL;
2516 2f9606b3 aliguori
        return -1;
2517 2f9606b3 aliguori
    }
2518 2f9606b3 aliguori
#endif
2519 2f9606b3 aliguori
2520 3aa3eea3 balrog
    if (reverse) {
2521 9712ecaf aliguori
        /* connect to viewer */
2522 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0)
2523 9712ecaf aliguori
            vs->lsock = unix_connect(display+5);
2524 9712ecaf aliguori
        else
2525 9712ecaf aliguori
            vs->lsock = inet_connect(display, SOCK_STREAM);
2526 9712ecaf aliguori
        if (-1 == vs->lsock) {
2527 3aa3eea3 balrog
            free(vs->display);
2528 3aa3eea3 balrog
            vs->display = NULL;
2529 3aa3eea3 balrog
            return -1;
2530 3aa3eea3 balrog
        } else {
2531 753b4053 aliguori
            int csock = vs->lsock;
2532 3aa3eea3 balrog
            vs->lsock = -1;
2533 753b4053 aliguori
            vnc_connect(vs, csock);
2534 3aa3eea3 balrog
        }
2535 9712ecaf aliguori
        return 0;
2536 24236869 bellard
2537 9712ecaf aliguori
    } else {
2538 9712ecaf aliguori
        /* listen for connects */
2539 9712ecaf aliguori
        char *dpy;
2540 9712ecaf aliguori
        dpy = qemu_malloc(256);
2541 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0) {
2542 bc575e95 blueswir1
            pstrcpy(dpy, 256, "unix:");
2543 4a55bfdf aliguori
            vs->lsock = unix_listen(display+5, dpy+5, 256-5);
2544 9712ecaf aliguori
        } else {
2545 9712ecaf aliguori
            vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
2546 9712ecaf aliguori
        }
2547 9712ecaf aliguori
        if (-1 == vs->lsock) {
2548 9712ecaf aliguori
            free(dpy);
2549 d0513623 balrog
            return -1;
2550 9712ecaf aliguori
        } else {
2551 9712ecaf aliguori
            free(vs->display);
2552 9712ecaf aliguori
            vs->display = dpy;
2553 9712ecaf aliguori
        }
2554 24236869 bellard
    }
2555 753b4053 aliguori
    return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs);
2556 24236869 bellard
}