Statistics
| Branch: | Revision:

root / vnc.c @ 07ef34c3

History | View | Annotate | Download (67.5 kB)

1 7d510b8c bellard
/*
2 7d510b8c bellard
 * QEMU VNC display driver
3 5fafdf24 ths
 *
4 7d510b8c bellard
 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 7d510b8c bellard
 * Copyright (C) 2006 Fabrice Bellard
6 5fafdf24 ths
 *
7 7d510b8c bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 7d510b8c bellard
 * of this software and associated documentation files (the "Software"), to deal
9 7d510b8c bellard
 * in the Software without restriction, including without limitation the rights
10 7d510b8c bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 7d510b8c bellard
 * copies of the Software, and to permit persons to whom the Software is
12 7d510b8c bellard
 * furnished to do so, subject to the following conditions:
13 7d510b8c bellard
 *
14 7d510b8c bellard
 * The above copyright notice and this permission notice shall be included in
15 7d510b8c bellard
 * all copies or substantial portions of the Software.
16 7d510b8c bellard
 *
17 7d510b8c bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 7d510b8c bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 7d510b8c bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 7d510b8c bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 7d510b8c bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 7d510b8c bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 7d510b8c bellard
 * THE SOFTWARE.
24 7d510b8c bellard
 */
25 7d510b8c bellard
26 87ecb68b pbrook
#include "qemu-common.h"
27 87ecb68b pbrook
#include "console.h"
28 87ecb68b pbrook
#include "sysemu.h"
29 6ca957f0 bellard
#include "qemu_socket.h"
30 87ecb68b pbrook
#include "qemu-timer.h"
31 429a8ed3 malc
#include "audio/audio.h"
32 24236869 bellard
33 24236869 bellard
#define VNC_REFRESH_INTERVAL (1000 / 30)
34 24236869 bellard
35 24236869 bellard
#include "vnc_keysym.h"
36 24236869 bellard
#include "keymaps.c"
37 70848515 ths
#include "d3des.h"
38 70848515 ths
39 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
40 8d5d2d4c ths
#include <gnutls/gnutls.h>
41 8d5d2d4c ths
#include <gnutls/x509.h>
42 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
43 70848515 ths
44 8d5d2d4c ths
// #define _VNC_DEBUG 1
45 8d5d2d4c ths
46 eb38c52c blueswir1
#ifdef _VNC_DEBUG
47 70848515 ths
#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
48 8d5d2d4c ths
49 8d5d2d4c ths
#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
50 8d5d2d4c ths
/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
51 8d5d2d4c ths
static void vnc_debug_gnutls_log(int level, const char* str) {
52 8d5d2d4c ths
    VNC_DEBUG("%d %s", level, str);
53 8d5d2d4c ths
}
54 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
55 70848515 ths
#else
56 70848515 ths
#define VNC_DEBUG(fmt, ...) do { } while (0)
57 70848515 ths
#endif
58 24236869 bellard
59 8d5d2d4c ths
60 24236869 bellard
typedef struct Buffer
61 24236869 bellard
{
62 24236869 bellard
    size_t capacity;
63 24236869 bellard
    size_t offset;
64 60fe76f3 ths
    uint8_t *buffer;
65 24236869 bellard
} Buffer;
66 24236869 bellard
67 24236869 bellard
typedef struct VncState VncState;
68 24236869 bellard
69 60fe76f3 ths
typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
70 24236869 bellard
71 3512779a bellard
typedef void VncWritePixels(VncState *vs, void *data, int size);
72 3512779a bellard
73 3512779a bellard
typedef void VncSendHextileTile(VncState *vs,
74 3512779a bellard
                                int x, int y, int w, int h,
75 7eac3a87 aliguori
                                void *last_bg,
76 7eac3a87 aliguori
                                void *last_fg,
77 3512779a bellard
                                int *has_bg, int *has_fg);
78 3512779a bellard
79 99589bdc bellard
#define VNC_MAX_WIDTH 2048
80 99589bdc bellard
#define VNC_MAX_HEIGHT 2048
81 99589bdc bellard
#define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
82 99589bdc bellard
83 70848515 ths
#define VNC_AUTH_CHALLENGE_SIZE 16
84 70848515 ths
85 70848515 ths
enum {
86 70848515 ths
    VNC_AUTH_INVALID = 0,
87 70848515 ths
    VNC_AUTH_NONE = 1,
88 70848515 ths
    VNC_AUTH_VNC = 2,
89 70848515 ths
    VNC_AUTH_RA2 = 5,
90 70848515 ths
    VNC_AUTH_RA2NE = 6,
91 70848515 ths
    VNC_AUTH_TIGHT = 16,
92 70848515 ths
    VNC_AUTH_ULTRA = 17,
93 70848515 ths
    VNC_AUTH_TLS = 18,
94 70848515 ths
    VNC_AUTH_VENCRYPT = 19
95 70848515 ths
};
96 70848515 ths
97 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
98 8d5d2d4c ths
enum {
99 8d5d2d4c ths
    VNC_WIREMODE_CLEAR,
100 8d5d2d4c ths
    VNC_WIREMODE_TLS,
101 8d5d2d4c ths
};
102 8d5d2d4c ths
103 8d5d2d4c ths
enum {
104 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_PLAIN = 256,
105 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_TLSNONE = 257,
106 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_TLSVNC = 258,
107 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
108 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_X509NONE = 260,
109 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_X509VNC = 261,
110 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_X509PLAIN = 262,
111 8d5d2d4c ths
};
112 3a702699 ths
113 3a702699 ths
#define X509_CA_CERT_FILE "ca-cert.pem"
114 3a702699 ths
#define X509_CA_CRL_FILE "ca-crl.pem"
115 3a702699 ths
#define X509_SERVER_KEY_FILE "server-key.pem"
116 3a702699 ths
#define X509_SERVER_CERT_FILE "server-cert.pem"
117 3a702699 ths
118 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
119 8d5d2d4c ths
120 24236869 bellard
struct VncState
121 24236869 bellard
{
122 24236869 bellard
    QEMUTimer *timer;
123 24236869 bellard
    int lsock;
124 24236869 bellard
    int csock;
125 24236869 bellard
    DisplayState *ds;
126 24236869 bellard
    int need_update;
127 24236869 bellard
    int width;
128 24236869 bellard
    int height;
129 99589bdc bellard
    uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
130 24236869 bellard
    char *old_data;
131 3512779a bellard
    int depth; /* internal VNC frame buffer byte per pixel */
132 24236869 bellard
    int has_resize;
133 24236869 bellard
    int has_hextile;
134 564c337e bellard
    int has_pointer_type_change;
135 ca4cca4d aliguori
    int has_WMVi;
136 564c337e bellard
    int absolute;
137 564c337e bellard
    int last_x;
138 564c337e bellard
    int last_y;
139 564c337e bellard
140 70848515 ths
    int major;
141 70848515 ths
    int minor;
142 70848515 ths
143 71cab5ca ths
    char *display;
144 70848515 ths
    char *password;
145 70848515 ths
    int auth;
146 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
147 8d5d2d4c ths
    int subauth;
148 469b15c6 ths
    int x509verify;
149 6f43024c ths
150 6f43024c ths
    char *x509cacert;
151 6f43024c ths
    char *x509cacrl;
152 6f43024c ths
    char *x509cert;
153 6f43024c ths
    char *x509key;
154 8d5d2d4c ths
#endif
155 70848515 ths
    char challenge[VNC_AUTH_CHALLENGE_SIZE];
156 a9ce8590 bellard
157 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
158 8d5d2d4c ths
    int wiremode;
159 8d5d2d4c ths
    gnutls_session_t tls_session;
160 8d5d2d4c ths
#endif
161 8d5d2d4c ths
162 24236869 bellard
    Buffer output;
163 24236869 bellard
    Buffer input;
164 24236869 bellard
    kbd_layout_t *kbd_layout;
165 3512779a bellard
    /* current output mode information */
166 3512779a bellard
    VncWritePixels *write_pixels;
167 3512779a bellard
    VncSendHextileTile *send_hextile_tile;
168 3512779a bellard
    int pix_bpp, pix_big_endian;
169 7eac3a87 aliguori
    int client_red_shift, client_red_max, server_red_shift, server_red_max;
170 7eac3a87 aliguori
    int client_green_shift, client_green_max, server_green_shift, server_green_max;
171 7eac3a87 aliguori
    int client_blue_shift, client_blue_max, server_blue_shift, server_blue_max;
172 24236869 bellard
173 429a8ed3 malc
    CaptureVoiceOut *audio_cap;
174 1ea879e5 malc
    struct audsettings as;
175 429a8ed3 malc
176 24236869 bellard
    VncReadEvent *read_handler;
177 24236869 bellard
    size_t read_handler_expect;
178 64f5a135 bellard
    /* input */
179 64f5a135 bellard
    uint8_t modifiers_state[256];
180 24236869 bellard
};
181 24236869 bellard
182 a9ce8590 bellard
static VncState *vnc_state; /* needed for info vnc */
183 a9ce8590 bellard
184 a9ce8590 bellard
void do_info_vnc(void)
185 a9ce8590 bellard
{
186 13412c9d aurel32
    if (vnc_state == NULL || vnc_state->display == NULL)
187 a9ce8590 bellard
        term_printf("VNC server disabled\n");
188 a9ce8590 bellard
    else {
189 a9ce8590 bellard
        term_printf("VNC server active on: ");
190 a9ce8590 bellard
        term_print_filename(vnc_state->display);
191 a9ce8590 bellard
        term_printf("\n");
192 a9ce8590 bellard
193 a9ce8590 bellard
        if (vnc_state->csock == -1)
194 a9ce8590 bellard
            term_printf("No client connected\n");
195 a9ce8590 bellard
        else
196 a9ce8590 bellard
            term_printf("Client connected\n");
197 a9ce8590 bellard
    }
198 a9ce8590 bellard
}
199 a9ce8590 bellard
200 24236869 bellard
/* TODO
201 24236869 bellard
   1) Get the queue working for IO.
202 24236869 bellard
   2) there is some weirdness when using the -S option (the screen is grey
203 24236869 bellard
      and not totally invalidated
204 24236869 bellard
   3) resolutions > 1024
205 24236869 bellard
*/
206 24236869 bellard
207 24236869 bellard
static void vnc_write(VncState *vs, const void *data, size_t len);
208 24236869 bellard
static void vnc_write_u32(VncState *vs, uint32_t value);
209 24236869 bellard
static void vnc_write_s32(VncState *vs, int32_t value);
210 24236869 bellard
static void vnc_write_u16(VncState *vs, uint16_t value);
211 24236869 bellard
static void vnc_write_u8(VncState *vs, uint8_t value);
212 24236869 bellard
static void vnc_flush(VncState *vs);
213 24236869 bellard
static void vnc_update_client(void *opaque);
214 24236869 bellard
static void vnc_client_read(void *opaque);
215 24236869 bellard
216 7eac3a87 aliguori
static void vnc_colordepth(DisplayState *ds, int depth);
217 7eac3a87 aliguori
218 99589bdc bellard
static inline void vnc_set_bit(uint32_t *d, int k)
219 99589bdc bellard
{
220 99589bdc bellard
    d[k >> 5] |= 1 << (k & 0x1f);
221 99589bdc bellard
}
222 99589bdc bellard
223 99589bdc bellard
static inline void vnc_clear_bit(uint32_t *d, int k)
224 99589bdc bellard
{
225 99589bdc bellard
    d[k >> 5] &= ~(1 << (k & 0x1f));
226 99589bdc bellard
}
227 99589bdc bellard
228 99589bdc bellard
static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
229 99589bdc bellard
{
230 99589bdc bellard
    int j;
231 99589bdc bellard
232 99589bdc bellard
    j = 0;
233 99589bdc bellard
    while (n >= 32) {
234 99589bdc bellard
        d[j++] = -1;
235 99589bdc bellard
        n -= 32;
236 99589bdc bellard
    }
237 5fafdf24 ths
    if (n > 0)
238 99589bdc bellard
        d[j++] = (1 << n) - 1;
239 99589bdc bellard
    while (j < nb_words)
240 99589bdc bellard
        d[j++] = 0;
241 99589bdc bellard
}
242 99589bdc bellard
243 99589bdc bellard
static inline int vnc_get_bit(const uint32_t *d, int k)
244 99589bdc bellard
{
245 99589bdc bellard
    return (d[k >> 5] >> (k & 0x1f)) & 1;
246 99589bdc bellard
}
247 99589bdc bellard
248 5fafdf24 ths
static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
249 99589bdc bellard
                               int nb_words)
250 99589bdc bellard
{
251 99589bdc bellard
    int i;
252 99589bdc bellard
    for(i = 0; i < nb_words; i++) {
253 99589bdc bellard
        if ((d1[i] & d2[i]) != 0)
254 99589bdc bellard
            return 1;
255 99589bdc bellard
    }
256 99589bdc bellard
    return 0;
257 99589bdc bellard
}
258 99589bdc bellard
259 24236869 bellard
static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
260 24236869 bellard
{
261 24236869 bellard
    VncState *vs = ds->opaque;
262 24236869 bellard
    int i;
263 24236869 bellard
264 24236869 bellard
    h += y;
265 24236869 bellard
266 0486e8a7 balrog
    /* round x down to ensure the loop only spans one 16-pixel block per,
267 0486e8a7 balrog
       iteration.  otherwise, if (x % 16) != 0, the last iteration may span
268 0486e8a7 balrog
       two 16-pixel blocks but we only mark the first as dirty
269 0486e8a7 balrog
    */
270 0486e8a7 balrog
    w += (x % 16);
271 0486e8a7 balrog
    x -= (x % 16);
272 0486e8a7 balrog
273 788abf8e balrog
    x = MIN(x, vs->width);
274 788abf8e balrog
    y = MIN(y, vs->height);
275 788abf8e balrog
    w = MIN(x + w, vs->width) - x;
276 731dd637 balrog
    h = MIN(h, vs->height);
277 788abf8e balrog
278 24236869 bellard
    for (; y < h; y++)
279 24236869 bellard
        for (i = 0; i < w; i += 16)
280 99589bdc bellard
            vnc_set_bit(vs->dirty_row[y], (x + i) / 16);
281 24236869 bellard
}
282 24236869 bellard
283 24236869 bellard
static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
284 24236869 bellard
                                   int32_t encoding)
285 24236869 bellard
{
286 24236869 bellard
    vnc_write_u16(vs, x);
287 24236869 bellard
    vnc_write_u16(vs, y);
288 24236869 bellard
    vnc_write_u16(vs, w);
289 24236869 bellard
    vnc_write_u16(vs, h);
290 24236869 bellard
291 24236869 bellard
    vnc_write_s32(vs, encoding);
292 24236869 bellard
}
293 24236869 bellard
294 24236869 bellard
static void vnc_dpy_resize(DisplayState *ds, int w, int h)
295 24236869 bellard
{
296 73e14b62 ths
    int size_changed;
297 24236869 bellard
    VncState *vs = ds->opaque;
298 24236869 bellard
299 2137b4cc ths
    ds->data = qemu_realloc(ds->data, w * h * vs->depth);
300 2137b4cc ths
    vs->old_data = qemu_realloc(vs->old_data, w * h * vs->depth);
301 24236869 bellard
302 24236869 bellard
    if (ds->data == NULL || vs->old_data == NULL) {
303 24236869 bellard
        fprintf(stderr, "vnc: memory allocation failed\n");
304 24236869 bellard
        exit(1);
305 24236869 bellard
    }
306 24236869 bellard
307 a528b80c balrog
    if (ds->depth != vs->depth * 8) {
308 a528b80c balrog
        ds->depth = vs->depth * 8;
309 a528b80c balrog
        console_color_init(ds);
310 a528b80c balrog
    }
311 73e14b62 ths
    size_changed = ds->width != w || ds->height != h;
312 24236869 bellard
    ds->width = w;
313 24236869 bellard
    ds->height = h;
314 24236869 bellard
    ds->linesize = w * vs->depth;
315 b94eb43f balrog
    if (size_changed) {
316 b94eb43f balrog
        vs->width = ds->width;
317 b94eb43f balrog
        vs->height = ds->height;
318 b94eb43f balrog
        if (vs->csock != -1 && vs->has_resize) {
319 b94eb43f balrog
            vnc_write_u8(vs, 0);  /* msg id */
320 b94eb43f balrog
            vnc_write_u8(vs, 0);
321 b94eb43f balrog
            vnc_write_u16(vs, 1); /* number of rects */
322 b94eb43f balrog
            vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
323 b94eb43f balrog
            vnc_flush(vs);
324 b94eb43f balrog
        }
325 24236869 bellard
    }
326 8bba5c81 balrog
327 8bba5c81 balrog
    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
328 0e1f5a0c aliguori
    memset(vs->old_data, 42, ds_get_linesize(vs->ds) * ds_get_height(vs->ds));
329 24236869 bellard
}
330 24236869 bellard
331 3512779a bellard
/* fastest code */
332 3512779a bellard
static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
333 3512779a bellard
{
334 3512779a bellard
    vnc_write(vs, pixels, size);
335 3512779a bellard
}
336 3512779a bellard
337 3512779a bellard
/* slowest but generic code. */
338 3512779a bellard
static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
339 3512779a bellard
{
340 7eac3a87 aliguori
    uint8_t r, g, b;
341 7eac3a87 aliguori
342 7eac3a87 aliguori
    r = ((v >> vs->server_red_shift) & vs->server_red_max) * (vs->client_red_max + 1) /
343 7eac3a87 aliguori
        (vs->server_red_max + 1);
344 7eac3a87 aliguori
    g = ((v >> vs->server_green_shift) & vs->server_green_max) * (vs->client_green_max + 1) /
345 7eac3a87 aliguori
        (vs->server_green_max + 1);
346 7eac3a87 aliguori
    b = ((v >> vs->server_blue_shift) & vs->server_blue_max) * (vs->client_blue_max + 1) /
347 7eac3a87 aliguori
        (vs->server_blue_max + 1);
348 7eac3a87 aliguori
    v = (r << vs->client_red_shift) |
349 7eac3a87 aliguori
        (g << vs->client_green_shift) |
350 7eac3a87 aliguori
        (b << vs->client_blue_shift);
351 3512779a bellard
    switch(vs->pix_bpp) {
352 3512779a bellard
    case 1:
353 3512779a bellard
        buf[0] = v;
354 3512779a bellard
        break;
355 3512779a bellard
    case 2:
356 3512779a bellard
        if (vs->pix_big_endian) {
357 3512779a bellard
            buf[0] = v >> 8;
358 3512779a bellard
            buf[1] = v;
359 3512779a bellard
        } else {
360 3512779a bellard
            buf[1] = v >> 8;
361 3512779a bellard
            buf[0] = v;
362 3512779a bellard
        }
363 3512779a bellard
        break;
364 3512779a bellard
    default:
365 3512779a bellard
    case 4:
366 3512779a bellard
        if (vs->pix_big_endian) {
367 3512779a bellard
            buf[0] = v >> 24;
368 3512779a bellard
            buf[1] = v >> 16;
369 3512779a bellard
            buf[2] = v >> 8;
370 3512779a bellard
            buf[3] = v;
371 3512779a bellard
        } else {
372 3512779a bellard
            buf[3] = v >> 24;
373 3512779a bellard
            buf[2] = v >> 16;
374 3512779a bellard
            buf[1] = v >> 8;
375 3512779a bellard
            buf[0] = v;
376 3512779a bellard
        }
377 3512779a bellard
        break;
378 3512779a bellard
    }
379 3512779a bellard
}
380 3512779a bellard
381 3512779a bellard
static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
382 3512779a bellard
{
383 3512779a bellard
    uint8_t buf[4];
384 3512779a bellard
385 7eac3a87 aliguori
    if (vs->depth == 4) {
386 7eac3a87 aliguori
        uint32_t *pixels = pixels1;
387 7eac3a87 aliguori
        int n, i;
388 7eac3a87 aliguori
        n = size >> 2;
389 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
390 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
391 7eac3a87 aliguori
            vnc_write(vs, buf, vs->pix_bpp);
392 7eac3a87 aliguori
        }
393 7eac3a87 aliguori
    } else if (vs->depth == 2) {
394 7eac3a87 aliguori
        uint16_t *pixels = pixels1;
395 7eac3a87 aliguori
        int n, i;
396 7eac3a87 aliguori
        n = size >> 1;
397 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
398 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
399 7eac3a87 aliguori
            vnc_write(vs, buf, vs->pix_bpp);
400 7eac3a87 aliguori
        }
401 7eac3a87 aliguori
    } else if (vs->depth == 1) {
402 7eac3a87 aliguori
        uint8_t *pixels = pixels1;
403 7eac3a87 aliguori
        int n, i;
404 7eac3a87 aliguori
        n = size;
405 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
406 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
407 7eac3a87 aliguori
            vnc_write(vs, buf, vs->pix_bpp);
408 7eac3a87 aliguori
        }
409 7eac3a87 aliguori
    } else {
410 7eac3a87 aliguori
        fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
411 3512779a bellard
    }
412 3512779a bellard
}
413 3512779a bellard
414 24236869 bellard
static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
415 24236869 bellard
{
416 24236869 bellard
    int i;
417 60fe76f3 ths
    uint8_t *row;
418 24236869 bellard
419 24236869 bellard
    vnc_framebuffer_update(vs, x, y, w, h, 0);
420 24236869 bellard
421 0e1f5a0c aliguori
    row = ds_get_data(vs->ds) + y * ds_get_linesize(vs->ds) + x * vs->depth;
422 24236869 bellard
    for (i = 0; i < h; i++) {
423 3512779a bellard
        vs->write_pixels(vs, row, w * vs->depth);
424 0e1f5a0c aliguori
        row += ds_get_linesize(vs->ds);
425 24236869 bellard
    }
426 24236869 bellard
}
427 24236869 bellard
428 24236869 bellard
static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
429 24236869 bellard
{
430 24236869 bellard
    ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
431 24236869 bellard
    ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
432 24236869 bellard
}
433 24236869 bellard
434 24236869 bellard
#define BPP 8
435 24236869 bellard
#include "vnchextile.h"
436 24236869 bellard
#undef BPP
437 24236869 bellard
438 24236869 bellard
#define BPP 16
439 24236869 bellard
#include "vnchextile.h"
440 24236869 bellard
#undef BPP
441 24236869 bellard
442 24236869 bellard
#define BPP 32
443 24236869 bellard
#include "vnchextile.h"
444 24236869 bellard
#undef BPP
445 24236869 bellard
446 3512779a bellard
#define GENERIC
447 7eac3a87 aliguori
#define BPP 8
448 7eac3a87 aliguori
#include "vnchextile.h"
449 7eac3a87 aliguori
#undef BPP
450 7eac3a87 aliguori
#undef GENERIC
451 7eac3a87 aliguori
452 7eac3a87 aliguori
#define GENERIC
453 7eac3a87 aliguori
#define BPP 16
454 7eac3a87 aliguori
#include "vnchextile.h"
455 7eac3a87 aliguori
#undef BPP
456 7eac3a87 aliguori
#undef GENERIC
457 7eac3a87 aliguori
458 7eac3a87 aliguori
#define GENERIC
459 3512779a bellard
#define BPP 32
460 3512779a bellard
#include "vnchextile.h"
461 3512779a bellard
#undef BPP
462 3512779a bellard
#undef GENERIC
463 3512779a bellard
464 24236869 bellard
static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
465 24236869 bellard
{
466 24236869 bellard
    int i, j;
467 24236869 bellard
    int has_fg, has_bg;
468 7eac3a87 aliguori
    uint8_t *last_fg, *last_bg;
469 24236869 bellard
470 24236869 bellard
    vnc_framebuffer_update(vs, x, y, w, h, 5);
471 24236869 bellard
472 7eac3a87 aliguori
    last_fg = (uint8_t *) malloc(vs->depth);
473 7eac3a87 aliguori
    last_bg = (uint8_t *) malloc(vs->depth);
474 24236869 bellard
    has_fg = has_bg = 0;
475 24236869 bellard
    for (j = y; j < (y + h); j += 16) {
476 24236869 bellard
        for (i = x; i < (x + w); i += 16) {
477 5fafdf24 ths
            vs->send_hextile_tile(vs, i, j,
478 3512779a bellard
                                  MIN(16, x + w - i), MIN(16, y + h - j),
479 7eac3a87 aliguori
                                  last_bg, last_fg, &has_bg, &has_fg);
480 24236869 bellard
        }
481 24236869 bellard
    }
482 7eac3a87 aliguori
    free(last_fg);
483 7eac3a87 aliguori
    free(last_bg);
484 7eac3a87 aliguori
485 24236869 bellard
}
486 24236869 bellard
487 24236869 bellard
static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
488 24236869 bellard
{
489 24236869 bellard
        if (vs->has_hextile)
490 24236869 bellard
            send_framebuffer_update_hextile(vs, x, y, w, h);
491 24236869 bellard
        else
492 24236869 bellard
            send_framebuffer_update_raw(vs, x, y, w, h);
493 24236869 bellard
}
494 24236869 bellard
495 24236869 bellard
static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
496 24236869 bellard
{
497 24236869 bellard
    int src, dst;
498 60fe76f3 ths
    uint8_t *src_row;
499 60fe76f3 ths
    uint8_t *dst_row;
500 24236869 bellard
    char *old_row;
501 24236869 bellard
    int y = 0;
502 0e1f5a0c aliguori
    int pitch = ds_get_linesize(ds);
503 24236869 bellard
    VncState *vs = ds->opaque;
504 24236869 bellard
505 24236869 bellard
    vnc_update_client(vs);
506 24236869 bellard
507 24236869 bellard
    if (dst_y > src_y) {
508 24236869 bellard
        y = h - 1;
509 24236869 bellard
        pitch = -pitch;
510 24236869 bellard
    }
511 24236869 bellard
512 0e1f5a0c aliguori
    src = (ds_get_linesize(ds) * (src_y + y) + vs->depth * src_x);
513 0e1f5a0c aliguori
    dst = (ds_get_linesize(ds) * (dst_y + y) + vs->depth * dst_x);
514 24236869 bellard
515 0e1f5a0c aliguori
    src_row = ds_get_data(ds) + src;
516 0e1f5a0c aliguori
    dst_row = ds_get_data(ds) + dst;
517 24236869 bellard
    old_row = vs->old_data + dst;
518 24236869 bellard
519 24236869 bellard
    for (y = 0; y < h; y++) {
520 24236869 bellard
        memmove(old_row, src_row, w * vs->depth);
521 24236869 bellard
        memmove(dst_row, src_row, w * vs->depth);
522 24236869 bellard
        src_row += pitch;
523 24236869 bellard
        dst_row += pitch;
524 24236869 bellard
        old_row += pitch;
525 24236869 bellard
    }
526 24236869 bellard
527 24236869 bellard
    vnc_write_u8(vs, 0);  /* msg id */
528 24236869 bellard
    vnc_write_u8(vs, 0);
529 24236869 bellard
    vnc_write_u16(vs, 1); /* number of rects */
530 24236869 bellard
    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
531 24236869 bellard
    vnc_write_u16(vs, src_x);
532 24236869 bellard
    vnc_write_u16(vs, src_y);
533 24236869 bellard
    vnc_flush(vs);
534 24236869 bellard
}
535 24236869 bellard
536 24236869 bellard
static int find_dirty_height(VncState *vs, int y, int last_x, int x)
537 24236869 bellard
{
538 24236869 bellard
    int h;
539 24236869 bellard
540 24236869 bellard
    for (h = 1; h < (vs->height - y); h++) {
541 24236869 bellard
        int tmp_x;
542 99589bdc bellard
        if (!vnc_get_bit(vs->dirty_row[y + h], last_x))
543 24236869 bellard
            break;
544 24236869 bellard
        for (tmp_x = last_x; tmp_x < x; tmp_x++)
545 99589bdc bellard
            vnc_clear_bit(vs->dirty_row[y + h], tmp_x);
546 24236869 bellard
    }
547 24236869 bellard
548 24236869 bellard
    return h;
549 24236869 bellard
}
550 24236869 bellard
551 24236869 bellard
static void vnc_update_client(void *opaque)
552 24236869 bellard
{
553 24236869 bellard
    VncState *vs = opaque;
554 24236869 bellard
555 24236869 bellard
    if (vs->need_update && vs->csock != -1) {
556 24236869 bellard
        int y;
557 60fe76f3 ths
        uint8_t *row;
558 24236869 bellard
        char *old_row;
559 99589bdc bellard
        uint32_t width_mask[VNC_DIRTY_WORDS];
560 24236869 bellard
        int n_rectangles;
561 24236869 bellard
        int saved_offset;
562 24236869 bellard
        int has_dirty = 0;
563 24236869 bellard
564 a0ecfb73 balrog
        vga_hw_update();
565 a0ecfb73 balrog
566 99589bdc bellard
        vnc_set_bits(width_mask, (vs->width / 16), VNC_DIRTY_WORDS);
567 24236869 bellard
568 24236869 bellard
        /* Walk through the dirty map and eliminate tiles that
569 24236869 bellard
           really aren't dirty */
570 0e1f5a0c aliguori
        row = ds_get_data(vs->ds);
571 24236869 bellard
        old_row = vs->old_data;
572 24236869 bellard
573 24236869 bellard
        for (y = 0; y < vs->height; y++) {
574 99589bdc bellard
            if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) {
575 24236869 bellard
                int x;
576 60fe76f3 ths
                uint8_t *ptr;
577 60fe76f3 ths
                char *old_ptr;
578 24236869 bellard
579 24236869 bellard
                ptr = row;
580 60fe76f3 ths
                old_ptr = (char*)old_row;
581 24236869 bellard
582 0e1f5a0c aliguori
                for (x = 0; x < ds_get_width(vs->ds); x += 16) {
583 24236869 bellard
                    if (memcmp(old_ptr, ptr, 16 * vs->depth) == 0) {
584 99589bdc bellard
                        vnc_clear_bit(vs->dirty_row[y], (x / 16));
585 24236869 bellard
                    } else {
586 24236869 bellard
                        has_dirty = 1;
587 24236869 bellard
                        memcpy(old_ptr, ptr, 16 * vs->depth);
588 24236869 bellard
                    }
589 24236869 bellard
590 24236869 bellard
                    ptr += 16 * vs->depth;
591 24236869 bellard
                    old_ptr += 16 * vs->depth;
592 24236869 bellard
                }
593 24236869 bellard
            }
594 24236869 bellard
595 0e1f5a0c aliguori
            row += ds_get_linesize(vs->ds);
596 0e1f5a0c aliguori
            old_row += ds_get_linesize(vs->ds);
597 24236869 bellard
        }
598 24236869 bellard
599 429a8ed3 malc
        if (!has_dirty && !vs->audio_cap) {
600 24236869 bellard
            qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
601 24236869 bellard
            return;
602 24236869 bellard
        }
603 24236869 bellard
604 24236869 bellard
        /* Count rectangles */
605 24236869 bellard
        n_rectangles = 0;
606 24236869 bellard
        vnc_write_u8(vs, 0);  /* msg id */
607 24236869 bellard
        vnc_write_u8(vs, 0);
608 24236869 bellard
        saved_offset = vs->output.offset;
609 24236869 bellard
        vnc_write_u16(vs, 0);
610 24236869 bellard
611 24236869 bellard
        for (y = 0; y < vs->height; y++) {
612 24236869 bellard
            int x;
613 24236869 bellard
            int last_x = -1;
614 24236869 bellard
            for (x = 0; x < vs->width / 16; x++) {
615 99589bdc bellard
                if (vnc_get_bit(vs->dirty_row[y], x)) {
616 24236869 bellard
                    if (last_x == -1) {
617 24236869 bellard
                        last_x = x;
618 24236869 bellard
                    }
619 99589bdc bellard
                    vnc_clear_bit(vs->dirty_row[y], x);
620 24236869 bellard
                } else {
621 24236869 bellard
                    if (last_x != -1) {
622 24236869 bellard
                        int h = find_dirty_height(vs, y, last_x, x);
623 24236869 bellard
                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
624 24236869 bellard
                        n_rectangles++;
625 24236869 bellard
                    }
626 24236869 bellard
                    last_x = -1;
627 24236869 bellard
                }
628 24236869 bellard
            }
629 24236869 bellard
            if (last_x != -1) {
630 24236869 bellard
                int h = find_dirty_height(vs, y, last_x, x);
631 24236869 bellard
                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
632 24236869 bellard
                n_rectangles++;
633 24236869 bellard
            }
634 24236869 bellard
        }
635 24236869 bellard
        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
636 24236869 bellard
        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
637 24236869 bellard
        vnc_flush(vs);
638 24236869 bellard
639 24236869 bellard
    }
640 24236869 bellard
641 a0ecfb73 balrog
    if (vs->csock != -1) {
642 a0ecfb73 balrog
        qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
643 24236869 bellard
    }
644 24236869 bellard
645 24236869 bellard
}
646 24236869 bellard
647 24236869 bellard
static int vnc_listen_poll(void *opaque)
648 24236869 bellard
{
649 24236869 bellard
    VncState *vs = opaque;
650 24236869 bellard
    if (vs->csock == -1)
651 24236869 bellard
        return 1;
652 24236869 bellard
    return 0;
653 24236869 bellard
}
654 24236869 bellard
655 24236869 bellard
static void buffer_reserve(Buffer *buffer, size_t len)
656 24236869 bellard
{
657 24236869 bellard
    if ((buffer->capacity - buffer->offset) < len) {
658 24236869 bellard
        buffer->capacity += (len + 1024);
659 2137b4cc ths
        buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity);
660 24236869 bellard
        if (buffer->buffer == NULL) {
661 24236869 bellard
            fprintf(stderr, "vnc: out of memory\n");
662 24236869 bellard
            exit(1);
663 24236869 bellard
        }
664 24236869 bellard
    }
665 24236869 bellard
}
666 24236869 bellard
667 24236869 bellard
static int buffer_empty(Buffer *buffer)
668 24236869 bellard
{
669 24236869 bellard
    return buffer->offset == 0;
670 24236869 bellard
}
671 24236869 bellard
672 60fe76f3 ths
static uint8_t *buffer_end(Buffer *buffer)
673 24236869 bellard
{
674 24236869 bellard
    return buffer->buffer + buffer->offset;
675 24236869 bellard
}
676 24236869 bellard
677 24236869 bellard
static void buffer_reset(Buffer *buffer)
678 24236869 bellard
{
679 24236869 bellard
        buffer->offset = 0;
680 24236869 bellard
}
681 24236869 bellard
682 24236869 bellard
static void buffer_append(Buffer *buffer, const void *data, size_t len)
683 24236869 bellard
{
684 24236869 bellard
    memcpy(buffer->buffer + buffer->offset, data, len);
685 24236869 bellard
    buffer->offset += len;
686 24236869 bellard
}
687 24236869 bellard
688 429a8ed3 malc
/* audio */
689 429a8ed3 malc
static void audio_capture_notify(void *opaque, audcnotification_e cmd)
690 429a8ed3 malc
{
691 429a8ed3 malc
    VncState *vs = opaque;
692 429a8ed3 malc
693 429a8ed3 malc
    switch (cmd) {
694 429a8ed3 malc
    case AUD_CNOTIFY_DISABLE:
695 429a8ed3 malc
        vnc_write_u8(vs, 255);
696 429a8ed3 malc
        vnc_write_u8(vs, 1);
697 429a8ed3 malc
        vnc_write_u16(vs, 0);
698 429a8ed3 malc
        vnc_flush(vs);
699 429a8ed3 malc
        break;
700 429a8ed3 malc
701 429a8ed3 malc
    case AUD_CNOTIFY_ENABLE:
702 429a8ed3 malc
        vnc_write_u8(vs, 255);
703 429a8ed3 malc
        vnc_write_u8(vs, 1);
704 429a8ed3 malc
        vnc_write_u16(vs, 1);
705 429a8ed3 malc
        vnc_flush(vs);
706 429a8ed3 malc
        break;
707 429a8ed3 malc
    }
708 429a8ed3 malc
}
709 429a8ed3 malc
710 429a8ed3 malc
static void audio_capture_destroy(void *opaque)
711 429a8ed3 malc
{
712 429a8ed3 malc
}
713 429a8ed3 malc
714 429a8ed3 malc
static void audio_capture(void *opaque, void *buf, int size)
715 429a8ed3 malc
{
716 429a8ed3 malc
    VncState *vs = opaque;
717 429a8ed3 malc
718 429a8ed3 malc
    vnc_write_u8(vs, 255);
719 429a8ed3 malc
    vnc_write_u8(vs, 1);
720 429a8ed3 malc
    vnc_write_u16(vs, 2);
721 429a8ed3 malc
    vnc_write_u32(vs, size);
722 429a8ed3 malc
    vnc_write(vs, buf, size);
723 429a8ed3 malc
    vnc_flush(vs);
724 429a8ed3 malc
}
725 429a8ed3 malc
726 429a8ed3 malc
static void audio_add(VncState *vs)
727 429a8ed3 malc
{
728 429a8ed3 malc
    struct audio_capture_ops ops;
729 429a8ed3 malc
730 429a8ed3 malc
    if (vs->audio_cap) {
731 429a8ed3 malc
        term_printf ("audio already running\n");
732 429a8ed3 malc
        return;
733 429a8ed3 malc
    }
734 429a8ed3 malc
735 429a8ed3 malc
    ops.notify = audio_capture_notify;
736 429a8ed3 malc
    ops.destroy = audio_capture_destroy;
737 429a8ed3 malc
    ops.capture = audio_capture;
738 429a8ed3 malc
739 429a8ed3 malc
    vs->audio_cap = AUD_add_capture(NULL, &vs->as, &ops, vs);
740 429a8ed3 malc
    if (!vs->audio_cap) {
741 429a8ed3 malc
        term_printf ("Failed to add audio capture\n");
742 429a8ed3 malc
    }
743 429a8ed3 malc
}
744 429a8ed3 malc
745 429a8ed3 malc
static void audio_del(VncState *vs)
746 429a8ed3 malc
{
747 429a8ed3 malc
    if (vs->audio_cap) {
748 429a8ed3 malc
        AUD_del_capture(vs->audio_cap, vs);
749 429a8ed3 malc
        vs->audio_cap = NULL;
750 429a8ed3 malc
    }
751 429a8ed3 malc
}
752 429a8ed3 malc
753 6ca957f0 bellard
static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
754 24236869 bellard
{
755 24236869 bellard
    if (ret == 0 || ret == -1) {
756 ea01e5fd balrog
        if (ret == -1) {
757 ea01e5fd balrog
            switch (last_errno) {
758 ea01e5fd balrog
                case EINTR:
759 ea01e5fd balrog
                case EAGAIN:
760 ea01e5fd balrog
#ifdef _WIN32
761 ea01e5fd balrog
                case WSAEWOULDBLOCK:
762 ea01e5fd balrog
#endif
763 ea01e5fd balrog
                    return 0;
764 ea01e5fd balrog
                default:
765 ea01e5fd balrog
                    break;
766 ea01e5fd balrog
            }
767 ea01e5fd balrog
        }
768 24236869 bellard
769 8d5d2d4c ths
        VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
770 24236869 bellard
        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
771 6ca957f0 bellard
        closesocket(vs->csock);
772 24236869 bellard
        vs->csock = -1;
773 bcfad70f aliguori
        vs->ds->idle = 1;
774 24236869 bellard
        buffer_reset(&vs->input);
775 24236869 bellard
        buffer_reset(&vs->output);
776 24236869 bellard
        vs->need_update = 0;
777 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
778 8d5d2d4c ths
        if (vs->tls_session) {
779 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
780 8d5d2d4c ths
            vs->tls_session = NULL;
781 8d5d2d4c ths
        }
782 8d5d2d4c ths
        vs->wiremode = VNC_WIREMODE_CLEAR;
783 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
784 429a8ed3 malc
        audio_del(vs);
785 24236869 bellard
        return 0;
786 24236869 bellard
    }
787 24236869 bellard
    return ret;
788 24236869 bellard
}
789 24236869 bellard
790 24236869 bellard
static void vnc_client_error(VncState *vs)
791 24236869 bellard
{
792 6ca957f0 bellard
    vnc_client_io_error(vs, -1, EINVAL);
793 24236869 bellard
}
794 24236869 bellard
795 24236869 bellard
static void vnc_client_write(void *opaque)
796 24236869 bellard
{
797 ceb5caaf bellard
    long ret;
798 24236869 bellard
    VncState *vs = opaque;
799 24236869 bellard
800 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
801 8d5d2d4c ths
    if (vs->tls_session) {
802 8d5d2d4c ths
        ret = gnutls_write(vs->tls_session, vs->output.buffer, vs->output.offset);
803 8d5d2d4c ths
        if (ret < 0) {
804 8d5d2d4c ths
            if (ret == GNUTLS_E_AGAIN)
805 8d5d2d4c ths
                errno = EAGAIN;
806 8d5d2d4c ths
            else
807 8d5d2d4c ths
                errno = EIO;
808 8d5d2d4c ths
            ret = -1;
809 8d5d2d4c ths
        }
810 8d5d2d4c ths
    } else
811 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
812 8d5d2d4c ths
        ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
813 6ca957f0 bellard
    ret = vnc_client_io_error(vs, ret, socket_error());
814 24236869 bellard
    if (!ret)
815 24236869 bellard
        return;
816 24236869 bellard
817 24236869 bellard
    memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
818 24236869 bellard
    vs->output.offset -= ret;
819 24236869 bellard
820 24236869 bellard
    if (vs->output.offset == 0) {
821 24236869 bellard
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
822 24236869 bellard
    }
823 24236869 bellard
}
824 24236869 bellard
825 24236869 bellard
static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
826 24236869 bellard
{
827 24236869 bellard
    vs->read_handler = func;
828 24236869 bellard
    vs->read_handler_expect = expecting;
829 24236869 bellard
}
830 24236869 bellard
831 24236869 bellard
static void vnc_client_read(void *opaque)
832 24236869 bellard
{
833 24236869 bellard
    VncState *vs = opaque;
834 ceb5caaf bellard
    long ret;
835 24236869 bellard
836 24236869 bellard
    buffer_reserve(&vs->input, 4096);
837 24236869 bellard
838 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
839 8d5d2d4c ths
    if (vs->tls_session) {
840 8d5d2d4c ths
        ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
841 8d5d2d4c ths
        if (ret < 0) {
842 8d5d2d4c ths
            if (ret == GNUTLS_E_AGAIN)
843 8d5d2d4c ths
                errno = EAGAIN;
844 8d5d2d4c ths
            else
845 8d5d2d4c ths
                errno = EIO;
846 8d5d2d4c ths
            ret = -1;
847 8d5d2d4c ths
        }
848 8d5d2d4c ths
    } else
849 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
850 8d5d2d4c ths
        ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
851 6ca957f0 bellard
    ret = vnc_client_io_error(vs, ret, socket_error());
852 24236869 bellard
    if (!ret)
853 24236869 bellard
        return;
854 24236869 bellard
855 24236869 bellard
    vs->input.offset += ret;
856 24236869 bellard
857 24236869 bellard
    while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
858 24236869 bellard
        size_t len = vs->read_handler_expect;
859 24236869 bellard
        int ret;
860 24236869 bellard
861 24236869 bellard
        ret = vs->read_handler(vs, vs->input.buffer, len);
862 24236869 bellard
        if (vs->csock == -1)
863 24236869 bellard
            return;
864 24236869 bellard
865 24236869 bellard
        if (!ret) {
866 24236869 bellard
            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
867 24236869 bellard
            vs->input.offset -= len;
868 24236869 bellard
        } else {
869 24236869 bellard
            vs->read_handler_expect = ret;
870 24236869 bellard
        }
871 24236869 bellard
    }
872 24236869 bellard
}
873 24236869 bellard
874 24236869 bellard
static void vnc_write(VncState *vs, const void *data, size_t len)
875 24236869 bellard
{
876 24236869 bellard
    buffer_reserve(&vs->output, len);
877 24236869 bellard
878 24236869 bellard
    if (buffer_empty(&vs->output)) {
879 24236869 bellard
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
880 24236869 bellard
    }
881 24236869 bellard
882 24236869 bellard
    buffer_append(&vs->output, data, len);
883 24236869 bellard
}
884 24236869 bellard
885 24236869 bellard
static void vnc_write_s32(VncState *vs, int32_t value)
886 24236869 bellard
{
887 24236869 bellard
    vnc_write_u32(vs, *(uint32_t *)&value);
888 24236869 bellard
}
889 24236869 bellard
890 24236869 bellard
static void vnc_write_u32(VncState *vs, uint32_t value)
891 24236869 bellard
{
892 24236869 bellard
    uint8_t buf[4];
893 24236869 bellard
894 24236869 bellard
    buf[0] = (value >> 24) & 0xFF;
895 24236869 bellard
    buf[1] = (value >> 16) & 0xFF;
896 24236869 bellard
    buf[2] = (value >>  8) & 0xFF;
897 24236869 bellard
    buf[3] = value & 0xFF;
898 24236869 bellard
899 24236869 bellard
    vnc_write(vs, buf, 4);
900 24236869 bellard
}
901 24236869 bellard
902 24236869 bellard
static void vnc_write_u16(VncState *vs, uint16_t value)
903 24236869 bellard
{
904 64f5a135 bellard
    uint8_t buf[2];
905 24236869 bellard
906 24236869 bellard
    buf[0] = (value >> 8) & 0xFF;
907 24236869 bellard
    buf[1] = value & 0xFF;
908 24236869 bellard
909 24236869 bellard
    vnc_write(vs, buf, 2);
910 24236869 bellard
}
911 24236869 bellard
912 24236869 bellard
static void vnc_write_u8(VncState *vs, uint8_t value)
913 24236869 bellard
{
914 24236869 bellard
    vnc_write(vs, (char *)&value, 1);
915 24236869 bellard
}
916 24236869 bellard
917 24236869 bellard
static void vnc_flush(VncState *vs)
918 24236869 bellard
{
919 24236869 bellard
    if (vs->output.offset)
920 24236869 bellard
        vnc_client_write(vs);
921 24236869 bellard
}
922 24236869 bellard
923 64f5a135 bellard
static uint8_t read_u8(uint8_t *data, size_t offset)
924 24236869 bellard
{
925 24236869 bellard
    return data[offset];
926 24236869 bellard
}
927 24236869 bellard
928 64f5a135 bellard
static uint16_t read_u16(uint8_t *data, size_t offset)
929 24236869 bellard
{
930 24236869 bellard
    return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
931 24236869 bellard
}
932 24236869 bellard
933 64f5a135 bellard
static int32_t read_s32(uint8_t *data, size_t offset)
934 24236869 bellard
{
935 24236869 bellard
    return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
936 24236869 bellard
                     (data[offset + 2] << 8) | data[offset + 3]);
937 24236869 bellard
}
938 24236869 bellard
939 64f5a135 bellard
static uint32_t read_u32(uint8_t *data, size_t offset)
940 24236869 bellard
{
941 24236869 bellard
    return ((data[offset] << 24) | (data[offset + 1] << 16) |
942 24236869 bellard
            (data[offset + 2] << 8) | data[offset + 3]);
943 24236869 bellard
}
944 24236869 bellard
945 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
946 9596ebb7 pbrook
static ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
947 9596ebb7 pbrook
                            const void *data,
948 9596ebb7 pbrook
                            size_t len) {
949 8d5d2d4c ths
    struct VncState *vs = (struct VncState *)transport;
950 8d5d2d4c ths
    int ret;
951 8d5d2d4c ths
952 8d5d2d4c ths
 retry:
953 8d5d2d4c ths
    ret = send(vs->csock, data, len, 0);
954 8d5d2d4c ths
    if (ret < 0) {
955 8d5d2d4c ths
        if (errno == EINTR)
956 8d5d2d4c ths
            goto retry;
957 8d5d2d4c ths
        return -1;
958 8d5d2d4c ths
    }
959 8d5d2d4c ths
    return ret;
960 8d5d2d4c ths
}
961 8d5d2d4c ths
962 8d5d2d4c ths
963 9596ebb7 pbrook
static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
964 9596ebb7 pbrook
                            void *data,
965 9596ebb7 pbrook
                            size_t len) {
966 8d5d2d4c ths
    struct VncState *vs = (struct VncState *)transport;
967 8d5d2d4c ths
    int ret;
968 8d5d2d4c ths
969 8d5d2d4c ths
 retry:
970 8d5d2d4c ths
    ret = recv(vs->csock, data, len, 0);
971 8d5d2d4c ths
    if (ret < 0) {
972 8d5d2d4c ths
        if (errno == EINTR)
973 8d5d2d4c ths
            goto retry;
974 8d5d2d4c ths
        return -1;
975 8d5d2d4c ths
    }
976 8d5d2d4c ths
    return ret;
977 8d5d2d4c ths
}
978 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
979 8d5d2d4c ths
980 60fe76f3 ths
static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
981 24236869 bellard
{
982 24236869 bellard
}
983 24236869 bellard
984 564c337e bellard
static void check_pointer_type_change(VncState *vs, int absolute)
985 564c337e bellard
{
986 564c337e bellard
    if (vs->has_pointer_type_change && vs->absolute != absolute) {
987 564c337e bellard
        vnc_write_u8(vs, 0);
988 564c337e bellard
        vnc_write_u8(vs, 0);
989 564c337e bellard
        vnc_write_u16(vs, 1);
990 564c337e bellard
        vnc_framebuffer_update(vs, absolute, 0,
991 0e1f5a0c aliguori
                               ds_get_width(vs->ds), ds_get_height(vs->ds), -257);
992 564c337e bellard
        vnc_flush(vs);
993 564c337e bellard
    }
994 564c337e bellard
    vs->absolute = absolute;
995 564c337e bellard
}
996 564c337e bellard
997 24236869 bellard
static void pointer_event(VncState *vs, int button_mask, int x, int y)
998 24236869 bellard
{
999 24236869 bellard
    int buttons = 0;
1000 24236869 bellard
    int dz = 0;
1001 24236869 bellard
1002 24236869 bellard
    if (button_mask & 0x01)
1003 24236869 bellard
        buttons |= MOUSE_EVENT_LBUTTON;
1004 24236869 bellard
    if (button_mask & 0x02)
1005 24236869 bellard
        buttons |= MOUSE_EVENT_MBUTTON;
1006 24236869 bellard
    if (button_mask & 0x04)
1007 24236869 bellard
        buttons |= MOUSE_EVENT_RBUTTON;
1008 24236869 bellard
    if (button_mask & 0x08)
1009 24236869 bellard
        dz = -1;
1010 24236869 bellard
    if (button_mask & 0x10)
1011 24236869 bellard
        dz = 1;
1012 564c337e bellard
1013 564c337e bellard
    if (vs->absolute) {
1014 0e1f5a0c aliguori
        kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1),
1015 0e1f5a0c aliguori
                        y * 0x7FFF / (ds_get_height(vs->ds) - 1),
1016 24236869 bellard
                        dz, buttons);
1017 564c337e bellard
    } else if (vs->has_pointer_type_change) {
1018 564c337e bellard
        x -= 0x7FFF;
1019 564c337e bellard
        y -= 0x7FFF;
1020 24236869 bellard
1021 564c337e bellard
        kbd_mouse_event(x, y, dz, buttons);
1022 564c337e bellard
    } else {
1023 564c337e bellard
        if (vs->last_x != -1)
1024 564c337e bellard
            kbd_mouse_event(x - vs->last_x,
1025 564c337e bellard
                            y - vs->last_y,
1026 564c337e bellard
                            dz, buttons);
1027 564c337e bellard
        vs->last_x = x;
1028 564c337e bellard
        vs->last_y = y;
1029 24236869 bellard
    }
1030 564c337e bellard
1031 564c337e bellard
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
1032 24236869 bellard
}
1033 24236869 bellard
1034 64f5a135 bellard
static void reset_keys(VncState *vs)
1035 64f5a135 bellard
{
1036 64f5a135 bellard
    int i;
1037 64f5a135 bellard
    for(i = 0; i < 256; i++) {
1038 64f5a135 bellard
        if (vs->modifiers_state[i]) {
1039 64f5a135 bellard
            if (i & 0x80)
1040 64f5a135 bellard
                kbd_put_keycode(0xe0);
1041 64f5a135 bellard
            kbd_put_keycode(i | 0x80);
1042 64f5a135 bellard
            vs->modifiers_state[i] = 0;
1043 64f5a135 bellard
        }
1044 64f5a135 bellard
    }
1045 64f5a135 bellard
}
1046 64f5a135 bellard
1047 a528b80c balrog
static void press_key(VncState *vs, int keysym)
1048 a528b80c balrog
{
1049 a528b80c balrog
    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f);
1050 a528b80c balrog
    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
1051 a528b80c balrog
}
1052 a528b80c balrog
1053 9ca313aa aliguori
static void do_key_event(VncState *vs, int down, int keycode, int sym)
1054 24236869 bellard
{
1055 64f5a135 bellard
    /* QEMU console switch */
1056 64f5a135 bellard
    switch(keycode) {
1057 64f5a135 bellard
    case 0x2a:                          /* Left Shift */
1058 64f5a135 bellard
    case 0x36:                          /* Right Shift */
1059 64f5a135 bellard
    case 0x1d:                          /* Left CTRL */
1060 64f5a135 bellard
    case 0x9d:                          /* Right CTRL */
1061 64f5a135 bellard
    case 0x38:                          /* Left ALT */
1062 64f5a135 bellard
    case 0xb8:                          /* Right ALT */
1063 64f5a135 bellard
        if (down)
1064 64f5a135 bellard
            vs->modifiers_state[keycode] = 1;
1065 64f5a135 bellard
        else
1066 64f5a135 bellard
            vs->modifiers_state[keycode] = 0;
1067 64f5a135 bellard
        break;
1068 5fafdf24 ths
    case 0x02 ... 0x0a: /* '1' to '9' keys */
1069 64f5a135 bellard
        if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1070 64f5a135 bellard
            /* Reset the modifiers sent to the current console */
1071 64f5a135 bellard
            reset_keys(vs);
1072 64f5a135 bellard
            console_select(keycode - 0x02);
1073 64f5a135 bellard
            return;
1074 64f5a135 bellard
        }
1075 64f5a135 bellard
        break;
1076 4d3b6f6e balrog
    case 0x3a:                        /* CapsLock */
1077 a528b80c balrog
    case 0x45:                        /* NumLock */
1078 a528b80c balrog
        if (!down)
1079 a528b80c balrog
            vs->modifiers_state[keycode] ^= 1;
1080 a528b80c balrog
        break;
1081 a528b80c balrog
    }
1082 a528b80c balrog
1083 a528b80c balrog
    if (keycode_is_keypad(vs->kbd_layout, keycode)) {
1084 a528b80c balrog
        /* If the numlock state needs to change then simulate an additional
1085 a528b80c balrog
           keypress before sending this one.  This will happen if the user
1086 a528b80c balrog
           toggles numlock away from the VNC window.
1087 a528b80c balrog
        */
1088 a528b80c balrog
        if (keysym_is_numlock(vs->kbd_layout, sym & 0xFFFF)) {
1089 a528b80c balrog
            if (!vs->modifiers_state[0x45]) {
1090 a528b80c balrog
                vs->modifiers_state[0x45] = 1;
1091 a528b80c balrog
                press_key(vs, 0xff7f);
1092 a528b80c balrog
            }
1093 a528b80c balrog
        } else {
1094 a528b80c balrog
            if (vs->modifiers_state[0x45]) {
1095 a528b80c balrog
                vs->modifiers_state[0x45] = 0;
1096 a528b80c balrog
                press_key(vs, 0xff7f);
1097 a528b80c balrog
            }
1098 a528b80c balrog
        }
1099 64f5a135 bellard
    }
1100 24236869 bellard
1101 64f5a135 bellard
    if (is_graphic_console()) {
1102 64f5a135 bellard
        if (keycode & 0x80)
1103 64f5a135 bellard
            kbd_put_keycode(0xe0);
1104 64f5a135 bellard
        if (down)
1105 64f5a135 bellard
            kbd_put_keycode(keycode & 0x7f);
1106 64f5a135 bellard
        else
1107 64f5a135 bellard
            kbd_put_keycode(keycode | 0x80);
1108 64f5a135 bellard
    } else {
1109 64f5a135 bellard
        /* QEMU console emulation */
1110 64f5a135 bellard
        if (down) {
1111 64f5a135 bellard
            switch (keycode) {
1112 64f5a135 bellard
            case 0x2a:                          /* Left Shift */
1113 64f5a135 bellard
            case 0x36:                          /* Right Shift */
1114 64f5a135 bellard
            case 0x1d:                          /* Left CTRL */
1115 64f5a135 bellard
            case 0x9d:                          /* Right CTRL */
1116 64f5a135 bellard
            case 0x38:                          /* Left ALT */
1117 64f5a135 bellard
            case 0xb8:                          /* Right ALT */
1118 64f5a135 bellard
                break;
1119 64f5a135 bellard
            case 0xc8:
1120 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_UP);
1121 64f5a135 bellard
                break;
1122 64f5a135 bellard
            case 0xd0:
1123 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DOWN);
1124 64f5a135 bellard
                break;
1125 64f5a135 bellard
            case 0xcb:
1126 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_LEFT);
1127 64f5a135 bellard
                break;
1128 64f5a135 bellard
            case 0xcd:
1129 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_RIGHT);
1130 64f5a135 bellard
                break;
1131 64f5a135 bellard
            case 0xd3:
1132 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DELETE);
1133 64f5a135 bellard
                break;
1134 64f5a135 bellard
            case 0xc7:
1135 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_HOME);
1136 64f5a135 bellard
                break;
1137 64f5a135 bellard
            case 0xcf:
1138 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_END);
1139 64f5a135 bellard
                break;
1140 64f5a135 bellard
            case 0xc9:
1141 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEUP);
1142 64f5a135 bellard
                break;
1143 64f5a135 bellard
            case 0xd1:
1144 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1145 64f5a135 bellard
                break;
1146 64f5a135 bellard
            default:
1147 64f5a135 bellard
                kbd_put_keysym(sym);
1148 64f5a135 bellard
                break;
1149 64f5a135 bellard
            }
1150 64f5a135 bellard
        }
1151 64f5a135 bellard
    }
1152 24236869 bellard
}
1153 24236869 bellard
1154 bdbd7676 bellard
static void key_event(VncState *vs, int down, uint32_t sym)
1155 bdbd7676 bellard
{
1156 9ca313aa aliguori
    int keycode;
1157 9ca313aa aliguori
1158 a528b80c balrog
    if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
1159 bdbd7676 bellard
        sym = sym - 'A' + 'a';
1160 9ca313aa aliguori
1161 9ca313aa aliguori
    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
1162 9ca313aa aliguori
    do_key_event(vs, down, keycode, sym);
1163 9ca313aa aliguori
}
1164 9ca313aa aliguori
1165 9ca313aa aliguori
static void ext_key_event(VncState *vs, int down,
1166 9ca313aa aliguori
                          uint32_t sym, uint16_t keycode)
1167 9ca313aa aliguori
{
1168 9ca313aa aliguori
    /* if the user specifies a keyboard layout, always use it */
1169 9ca313aa aliguori
    if (keyboard_layout)
1170 9ca313aa aliguori
        key_event(vs, down, sym);
1171 9ca313aa aliguori
    else
1172 9ca313aa aliguori
        do_key_event(vs, down, keycode, sym);
1173 bdbd7676 bellard
}
1174 bdbd7676 bellard
1175 24236869 bellard
static void framebuffer_update_request(VncState *vs, int incremental,
1176 24236869 bellard
                                       int x_position, int y_position,
1177 24236869 bellard
                                       int w, int h)
1178 24236869 bellard
{
1179 0e1f5a0c aliguori
    if (x_position > ds_get_width(vs->ds))
1180 0e1f5a0c aliguori
        x_position = ds_get_width(vs->ds);
1181 0e1f5a0c aliguori
    if (y_position > ds_get_height(vs->ds))
1182 0e1f5a0c aliguori
        y_position = ds_get_height(vs->ds);
1183 0e1f5a0c aliguori
    if (x_position + w >= ds_get_width(vs->ds))
1184 0e1f5a0c aliguori
        w = ds_get_width(vs->ds)  - x_position;
1185 0e1f5a0c aliguori
    if (y_position + h >= ds_get_height(vs->ds))
1186 0e1f5a0c aliguori
        h = ds_get_height(vs->ds) - y_position;
1187 cf2d385c ths
1188 24236869 bellard
    int i;
1189 24236869 bellard
    vs->need_update = 1;
1190 24236869 bellard
    if (!incremental) {
1191 0e1f5a0c aliguori
        char *old_row = vs->old_data + y_position * ds_get_linesize(vs->ds);
1192 24236869 bellard
1193 24236869 bellard
        for (i = 0; i < h; i++) {
1194 5fafdf24 ths
            vnc_set_bits(vs->dirty_row[y_position + i],
1195 0e1f5a0c aliguori
                         (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1196 0e1f5a0c aliguori
            memset(old_row, 42, ds_get_width(vs->ds) * vs->depth);
1197 0e1f5a0c aliguori
            old_row += ds_get_linesize(vs->ds);
1198 24236869 bellard
        }
1199 24236869 bellard
    }
1200 24236869 bellard
}
1201 24236869 bellard
1202 9ca313aa aliguori
static void send_ext_key_event_ack(VncState *vs)
1203 9ca313aa aliguori
{
1204 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1205 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1206 9ca313aa aliguori
    vnc_write_u16(vs, 1);
1207 0e1f5a0c aliguori
    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), -258);
1208 9ca313aa aliguori
    vnc_flush(vs);
1209 9ca313aa aliguori
}
1210 9ca313aa aliguori
1211 429a8ed3 malc
static void send_ext_audio_ack(VncState *vs)
1212 429a8ed3 malc
{
1213 429a8ed3 malc
    vnc_write_u8(vs, 0);
1214 429a8ed3 malc
    vnc_write_u8(vs, 0);
1215 429a8ed3 malc
    vnc_write_u16(vs, 1);
1216 429a8ed3 malc
    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), -259);
1217 429a8ed3 malc
    vnc_flush(vs);
1218 429a8ed3 malc
}
1219 429a8ed3 malc
1220 24236869 bellard
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1221 24236869 bellard
{
1222 24236869 bellard
    int i;
1223 24236869 bellard
1224 24236869 bellard
    vs->has_hextile = 0;
1225 24236869 bellard
    vs->has_resize = 0;
1226 564c337e bellard
    vs->has_pointer_type_change = 0;
1227 ca4cca4d aliguori
    vs->has_WMVi = 0;
1228 564c337e bellard
    vs->absolute = -1;
1229 24236869 bellard
    vs->ds->dpy_copy = NULL;
1230 24236869 bellard
1231 24236869 bellard
    for (i = n_encodings - 1; i >= 0; i--) {
1232 24236869 bellard
        switch (encodings[i]) {
1233 24236869 bellard
        case 0: /* Raw */
1234 24236869 bellard
            vs->has_hextile = 0;
1235 24236869 bellard
            break;
1236 24236869 bellard
        case 1: /* CopyRect */
1237 24236869 bellard
            vs->ds->dpy_copy = vnc_copy;
1238 24236869 bellard
            break;
1239 24236869 bellard
        case 5: /* Hextile */
1240 24236869 bellard
            vs->has_hextile = 1;
1241 24236869 bellard
            break;
1242 24236869 bellard
        case -223: /* DesktopResize */
1243 24236869 bellard
            vs->has_resize = 1;
1244 24236869 bellard
            break;
1245 564c337e bellard
        case -257:
1246 564c337e bellard
            vs->has_pointer_type_change = 1;
1247 564c337e bellard
            break;
1248 9ca313aa aliguori
        case -258:
1249 9ca313aa aliguori
            send_ext_key_event_ack(vs);
1250 9ca313aa aliguori
            break;
1251 429a8ed3 malc
        case -259:
1252 429a8ed3 malc
            send_ext_audio_ack(vs);
1253 429a8ed3 malc
            break;
1254 ca4cca4d aliguori
        case 0x574D5669:
1255 ca4cca4d aliguori
            vs->has_WMVi = 1;
1256 ca4cca4d aliguori
            break;
1257 24236869 bellard
        default:
1258 24236869 bellard
            break;
1259 24236869 bellard
        }
1260 24236869 bellard
    }
1261 564c337e bellard
1262 564c337e bellard
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
1263 24236869 bellard
}
1264 24236869 bellard
1265 24236869 bellard
static void set_pixel_format(VncState *vs,
1266 24236869 bellard
                             int bits_per_pixel, int depth,
1267 24236869 bellard
                             int big_endian_flag, int true_color_flag,
1268 24236869 bellard
                             int red_max, int green_max, int blue_max,
1269 24236869 bellard
                             int red_shift, int green_shift, int blue_shift)
1270 24236869 bellard
{
1271 3512779a bellard
    int host_big_endian_flag;
1272 24236869 bellard
1273 3512779a bellard
#ifdef WORDS_BIGENDIAN
1274 3512779a bellard
    host_big_endian_flag = 1;
1275 3512779a bellard
#else
1276 3512779a bellard
    host_big_endian_flag = 0;
1277 3512779a bellard
#endif
1278 3512779a bellard
    if (!true_color_flag) {
1279 3512779a bellard
    fail:
1280 24236869 bellard
        vnc_client_error(vs);
1281 3512779a bellard
        return;
1282 3512779a bellard
    }
1283 5fafdf24 ths
    if (bits_per_pixel == 32 &&
1284 7eac3a87 aliguori
        bits_per_pixel == vs->depth * 8 &&
1285 3512779a bellard
        host_big_endian_flag == big_endian_flag &&
1286 3512779a bellard
        red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1287 3512779a bellard
        red_shift == 16 && green_shift == 8 && blue_shift == 0) {
1288 3512779a bellard
        vs->depth = 4;
1289 3512779a bellard
        vs->write_pixels = vnc_write_pixels_copy;
1290 3512779a bellard
        vs->send_hextile_tile = send_hextile_tile_32;
1291 5fafdf24 ths
    } else
1292 5fafdf24 ths
    if (bits_per_pixel == 16 &&
1293 7eac3a87 aliguori
        bits_per_pixel == vs->depth * 8 && 
1294 3512779a bellard
        host_big_endian_flag == big_endian_flag &&
1295 3512779a bellard
        red_max == 31 && green_max == 63 && blue_max == 31 &&
1296 3512779a bellard
        red_shift == 11 && green_shift == 5 && blue_shift == 0) {
1297 3512779a bellard
        vs->depth = 2;
1298 3512779a bellard
        vs->write_pixels = vnc_write_pixels_copy;
1299 3512779a bellard
        vs->send_hextile_tile = send_hextile_tile_16;
1300 5fafdf24 ths
    } else
1301 5fafdf24 ths
    if (bits_per_pixel == 8 &&
1302 7eac3a87 aliguori
        bits_per_pixel == vs->depth * 8 &&
1303 3512779a bellard
        red_max == 7 && green_max == 7 && blue_max == 3 &&
1304 3512779a bellard
        red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1305 3512779a bellard
        vs->depth = 1;
1306 3512779a bellard
        vs->write_pixels = vnc_write_pixels_copy;
1307 3512779a bellard
        vs->send_hextile_tile = send_hextile_tile_8;
1308 5fafdf24 ths
    } else
1309 3512779a bellard
    {
1310 3512779a bellard
        /* generic and slower case */
1311 3512779a bellard
        if (bits_per_pixel != 8 &&
1312 3512779a bellard
            bits_per_pixel != 16 &&
1313 3512779a bellard
            bits_per_pixel != 32)
1314 3512779a bellard
            goto fail;
1315 7eac3a87 aliguori
        if (vs->depth == 4) {
1316 7eac3a87 aliguori
            vs->send_hextile_tile = send_hextile_tile_generic_32;
1317 7eac3a87 aliguori
        } else if (vs->depth == 2) {
1318 7eac3a87 aliguori
           vs->send_hextile_tile = send_hextile_tile_generic_16;
1319 7eac3a87 aliguori
        } else {
1320 7eac3a87 aliguori
            vs->send_hextile_tile = send_hextile_tile_generic_8;
1321 7eac3a87 aliguori
        }
1322 7eac3a87 aliguori
1323 3512779a bellard
        vs->pix_big_endian = big_endian_flag;
1324 3512779a bellard
        vs->write_pixels = vnc_write_pixels_generic;
1325 3512779a bellard
    }
1326 24236869 bellard
1327 7eac3a87 aliguori
    vs->client_red_shift = red_shift;
1328 7eac3a87 aliguori
    vs->client_red_max = red_max;
1329 7eac3a87 aliguori
    vs->client_green_shift = green_shift;
1330 7eac3a87 aliguori
    vs->client_green_max = green_max;
1331 7eac3a87 aliguori
    vs->client_blue_shift = blue_shift;
1332 7eac3a87 aliguori
    vs->client_blue_max = blue_max;
1333 7eac3a87 aliguori
    vs->pix_bpp = bits_per_pixel / 8;
1334 24236869 bellard
1335 24236869 bellard
    vga_hw_invalidate();
1336 24236869 bellard
    vga_hw_update();
1337 24236869 bellard
}
1338 24236869 bellard
1339 ca4cca4d aliguori
static void pixel_format_message (VncState *vs) {
1340 ca4cca4d aliguori
    char pad[3] = { 0, 0, 0 };
1341 ca4cca4d aliguori
1342 ca4cca4d aliguori
    vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1343 ca4cca4d aliguori
    if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
1344 ca4cca4d aliguori
    else vnc_write_u8(vs, vs->depth * 8); /* depth */
1345 ca4cca4d aliguori
1346 ca4cca4d aliguori
#ifdef WORDS_BIGENDIAN
1347 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* big-endian-flag */
1348 ca4cca4d aliguori
#else
1349 ca4cca4d aliguori
    vnc_write_u8(vs, 0);             /* big-endian-flag */
1350 ca4cca4d aliguori
#endif
1351 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* true-color-flag */
1352 ca4cca4d aliguori
    if (vs->depth == 4) {
1353 ca4cca4d aliguori
        vnc_write_u16(vs, 0xFF);     /* red-max */
1354 ca4cca4d aliguori
        vnc_write_u16(vs, 0xFF);     /* green-max */
1355 ca4cca4d aliguori
        vnc_write_u16(vs, 0xFF);     /* blue-max */
1356 ca4cca4d aliguori
        vnc_write_u8(vs, 16);        /* red-shift */
1357 ca4cca4d aliguori
        vnc_write_u8(vs, 8);         /* green-shift */
1358 ca4cca4d aliguori
        vnc_write_u8(vs, 0);         /* blue-shift */
1359 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_32;
1360 ca4cca4d aliguori
    } else if (vs->depth == 2) {
1361 ca4cca4d aliguori
        vnc_write_u16(vs, 31);       /* red-max */
1362 ca4cca4d aliguori
        vnc_write_u16(vs, 63);       /* green-max */
1363 ca4cca4d aliguori
        vnc_write_u16(vs, 31);       /* blue-max */
1364 ca4cca4d aliguori
        vnc_write_u8(vs, 11);        /* red-shift */
1365 ca4cca4d aliguori
        vnc_write_u8(vs, 5);         /* green-shift */
1366 ca4cca4d aliguori
        vnc_write_u8(vs, 0);         /* blue-shift */
1367 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_16;
1368 ca4cca4d aliguori
    } else if (vs->depth == 1) {
1369 ca4cca4d aliguori
        /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
1370 ca4cca4d aliguori
        vnc_write_u16(vs, 7);        /* red-max */
1371 ca4cca4d aliguori
        vnc_write_u16(vs, 7);        /* green-max */
1372 ca4cca4d aliguori
        vnc_write_u16(vs, 3);        /* blue-max */
1373 ca4cca4d aliguori
        vnc_write_u8(vs, 5);         /* red-shift */
1374 ca4cca4d aliguori
        vnc_write_u8(vs, 2);         /* green-shift */
1375 ca4cca4d aliguori
        vnc_write_u8(vs, 0);         /* blue-shift */
1376 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_8;
1377 ca4cca4d aliguori
    }
1378 ca4cca4d aliguori
    vs->client_red_max = vs->server_red_max;
1379 ca4cca4d aliguori
    vs->client_green_max = vs->server_green_max;
1380 ca4cca4d aliguori
    vs->client_blue_max = vs->server_blue_max;
1381 ca4cca4d aliguori
    vs->client_red_shift = vs->server_red_shift;
1382 ca4cca4d aliguori
    vs->client_green_shift = vs->server_green_shift;
1383 ca4cca4d aliguori
    vs->client_blue_shift = vs->server_blue_shift;
1384 ca4cca4d aliguori
    vs->pix_bpp = vs->depth * 8;
1385 ca4cca4d aliguori
    vs->write_pixels = vnc_write_pixels_copy;
1386 ca4cca4d aliguori
1387 ca4cca4d aliguori
    vnc_write(vs, pad, 3);           /* padding */
1388 ca4cca4d aliguori
}
1389 ca4cca4d aliguori
1390 7eac3a87 aliguori
static void vnc_colordepth(DisplayState *ds, int depth)
1391 7eac3a87 aliguori
{
1392 7eac3a87 aliguori
    int host_big_endian_flag;
1393 7eac3a87 aliguori
    struct VncState *vs = ds->opaque;
1394 7eac3a87 aliguori
1395 7eac3a87 aliguori
    switch (depth) {
1396 7eac3a87 aliguori
        case 24:
1397 7eac3a87 aliguori
            if (ds->depth == 32) return;
1398 7eac3a87 aliguori
            depth = 32;
1399 7eac3a87 aliguori
            break;
1400 7eac3a87 aliguori
        case 15:
1401 7eac3a87 aliguori
        case 8:
1402 7eac3a87 aliguori
        case 0:
1403 7eac3a87 aliguori
            return;
1404 7eac3a87 aliguori
        default:
1405 7eac3a87 aliguori
            break;
1406 7eac3a87 aliguori
    }
1407 7eac3a87 aliguori
1408 7eac3a87 aliguori
#ifdef WORDS_BIGENDIAN
1409 7eac3a87 aliguori
    host_big_endian_flag = 1;
1410 7eac3a87 aliguori
#else
1411 7eac3a87 aliguori
    host_big_endian_flag = 0;
1412 7eac3a87 aliguori
#endif   
1413 7eac3a87 aliguori
    
1414 7eac3a87 aliguori
    switch (depth) {
1415 7eac3a87 aliguori
        case 8:
1416 7eac3a87 aliguori
            vs->depth = depth / 8;
1417 7eac3a87 aliguori
            vs->server_red_max = 7;
1418 7eac3a87 aliguori
            vs->server_green_max = 7;
1419 7eac3a87 aliguori
            vs->server_blue_max = 3;
1420 7eac3a87 aliguori
            vs->server_red_shift = 5;
1421 7eac3a87 aliguori
            vs->server_green_shift = 2;
1422 7eac3a87 aliguori
            vs->server_blue_shift = 0;
1423 7eac3a87 aliguori
            break;
1424 7eac3a87 aliguori
        case 16:
1425 7eac3a87 aliguori
            vs->depth = depth / 8;
1426 7eac3a87 aliguori
            vs->server_red_max = 31;
1427 7eac3a87 aliguori
            vs->server_green_max = 63;
1428 7eac3a87 aliguori
            vs->server_blue_max = 31;
1429 7eac3a87 aliguori
            vs->server_red_shift = 11;
1430 7eac3a87 aliguori
            vs->server_green_shift = 5;
1431 7eac3a87 aliguori
            vs->server_blue_shift = 0;
1432 7eac3a87 aliguori
            break;
1433 7eac3a87 aliguori
        case 32:
1434 7eac3a87 aliguori
            vs->depth = 4;
1435 7eac3a87 aliguori
            vs->server_red_max = 255;
1436 7eac3a87 aliguori
            vs->server_green_max = 255;
1437 7eac3a87 aliguori
            vs->server_blue_max = 255;
1438 7eac3a87 aliguori
            vs->server_red_shift = 16;
1439 7eac3a87 aliguori
            vs->server_green_shift = 8;
1440 7eac3a87 aliguori
            vs->server_blue_shift = 0;
1441 7eac3a87 aliguori
            break;
1442 7eac3a87 aliguori
        default:
1443 7eac3a87 aliguori
            return;
1444 7eac3a87 aliguori
    }
1445 7eac3a87 aliguori
1446 ca4cca4d aliguori
    if (vs->csock != -1 && vs->has_WMVi) {
1447 ca4cca4d aliguori
        /* Sending a WMVi message to notify the client*/
1448 ca4cca4d aliguori
        vnc_write_u8(vs, 0);  /* msg id */
1449 ca4cca4d aliguori
        vnc_write_u8(vs, 0);
1450 ca4cca4d aliguori
        vnc_write_u16(vs, 1); /* number of rects */
1451 ca4cca4d aliguori
        vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669);
1452 ca4cca4d aliguori
        pixel_format_message(vs);
1453 ca4cca4d aliguori
        vnc_flush(vs);
1454 7eac3a87 aliguori
    } else {
1455 ca4cca4d aliguori
        if (vs->pix_bpp == 4 && vs->depth == 4 &&
1456 ca4cca4d aliguori
                host_big_endian_flag == vs->pix_big_endian &&
1457 ca4cca4d aliguori
                vs->client_red_max == 0xff && vs->client_green_max == 0xff && vs->client_blue_max == 0xff &&
1458 ca4cca4d aliguori
                vs->client_red_shift == 16 && vs->client_green_shift == 8 && vs->client_blue_shift == 0) {
1459 ca4cca4d aliguori
            vs->write_pixels = vnc_write_pixels_copy;
1460 ca4cca4d aliguori
            vs->send_hextile_tile = send_hextile_tile_32;
1461 ca4cca4d aliguori
        } else if (vs->pix_bpp == 2 && vs->depth == 2 &&
1462 ca4cca4d aliguori
                host_big_endian_flag == vs->pix_big_endian &&
1463 ca4cca4d aliguori
                vs->client_red_max == 31 && vs->client_green_max == 63 && vs->client_blue_max == 31 &&
1464 ca4cca4d aliguori
                vs->client_red_shift == 11 && vs->client_green_shift == 5 && vs->client_blue_shift == 0) {
1465 ca4cca4d aliguori
            vs->write_pixels = vnc_write_pixels_copy;
1466 ca4cca4d aliguori
            vs->send_hextile_tile = send_hextile_tile_16;
1467 ca4cca4d aliguori
        } else if (vs->pix_bpp == 1 && vs->depth == 1 &&
1468 ca4cca4d aliguori
                host_big_endian_flag == vs->pix_big_endian &&
1469 ca4cca4d aliguori
                vs->client_red_max == 7 && vs->client_green_max == 7 && vs->client_blue_max == 3 &&
1470 ca4cca4d aliguori
                vs->client_red_shift == 5 && vs->client_green_shift == 2 && vs->client_blue_shift == 0) {
1471 ca4cca4d aliguori
            vs->write_pixels = vnc_write_pixels_copy;
1472 ca4cca4d aliguori
            vs->send_hextile_tile = send_hextile_tile_8;
1473 7eac3a87 aliguori
        } else {
1474 ca4cca4d aliguori
            if (vs->depth == 4) {
1475 ca4cca4d aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_32;
1476 ca4cca4d aliguori
            } else if (vs->depth == 2) {
1477 ca4cca4d aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_16;
1478 ca4cca4d aliguori
            } else {
1479 ca4cca4d aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_8;
1480 ca4cca4d aliguori
            }
1481 ca4cca4d aliguori
            vs->write_pixels = vnc_write_pixels_generic;
1482 7eac3a87 aliguori
        }
1483 7eac3a87 aliguori
    }
1484 7eac3a87 aliguori
}
1485 7eac3a87 aliguori
1486 60fe76f3 ths
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1487 24236869 bellard
{
1488 24236869 bellard
    int i;
1489 24236869 bellard
    uint16_t limit;
1490 24236869 bellard
1491 24236869 bellard
    switch (data[0]) {
1492 24236869 bellard
    case 0:
1493 24236869 bellard
        if (len == 1)
1494 24236869 bellard
            return 20;
1495 24236869 bellard
1496 24236869 bellard
        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1497 24236869 bellard
                         read_u8(data, 6), read_u8(data, 7),
1498 24236869 bellard
                         read_u16(data, 8), read_u16(data, 10),
1499 24236869 bellard
                         read_u16(data, 12), read_u8(data, 14),
1500 24236869 bellard
                         read_u8(data, 15), read_u8(data, 16));
1501 24236869 bellard
        break;
1502 24236869 bellard
    case 2:
1503 24236869 bellard
        if (len == 1)
1504 24236869 bellard
            return 4;
1505 24236869 bellard
1506 69dd5c9f aliguori
        if (len == 4) {
1507 69dd5c9f aliguori
            limit = read_u16(data, 2);
1508 69dd5c9f aliguori
            if (limit > 0)
1509 69dd5c9f aliguori
                return 4 + (limit * 4);
1510 69dd5c9f aliguori
        } else
1511 69dd5c9f aliguori
            limit = read_u16(data, 2);
1512 24236869 bellard
1513 24236869 bellard
        for (i = 0; i < limit; i++) {
1514 24236869 bellard
            int32_t val = read_s32(data, 4 + (i * 4));
1515 24236869 bellard
            memcpy(data + 4 + (i * 4), &val, sizeof(val));
1516 24236869 bellard
        }
1517 24236869 bellard
1518 24236869 bellard
        set_encodings(vs, (int32_t *)(data + 4), limit);
1519 24236869 bellard
        break;
1520 24236869 bellard
    case 3:
1521 24236869 bellard
        if (len == 1)
1522 24236869 bellard
            return 10;
1523 24236869 bellard
1524 24236869 bellard
        framebuffer_update_request(vs,
1525 24236869 bellard
                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1526 24236869 bellard
                                   read_u16(data, 6), read_u16(data, 8));
1527 24236869 bellard
        break;
1528 24236869 bellard
    case 4:
1529 24236869 bellard
        if (len == 1)
1530 24236869 bellard
            return 8;
1531 24236869 bellard
1532 24236869 bellard
        key_event(vs, read_u8(data, 1), read_u32(data, 4));
1533 24236869 bellard
        break;
1534 24236869 bellard
    case 5:
1535 24236869 bellard
        if (len == 1)
1536 24236869 bellard
            return 6;
1537 24236869 bellard
1538 24236869 bellard
        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1539 24236869 bellard
        break;
1540 24236869 bellard
    case 6:
1541 24236869 bellard
        if (len == 1)
1542 24236869 bellard
            return 8;
1543 24236869 bellard
1544 baa7666c ths
        if (len == 8) {
1545 baa7666c ths
            uint32_t dlen = read_u32(data, 4);
1546 baa7666c ths
            if (dlen > 0)
1547 baa7666c ths
                return 8 + dlen;
1548 baa7666c ths
        }
1549 24236869 bellard
1550 24236869 bellard
        client_cut_text(vs, read_u32(data, 4), data + 8);
1551 24236869 bellard
        break;
1552 9ca313aa aliguori
    case 255:
1553 9ca313aa aliguori
        if (len == 1)
1554 9ca313aa aliguori
            return 2;
1555 9ca313aa aliguori
1556 9ca313aa aliguori
        switch (read_u8(data, 1)) {
1557 9ca313aa aliguori
        case 0:
1558 9ca313aa aliguori
            if (len == 2)
1559 9ca313aa aliguori
                return 12;
1560 9ca313aa aliguori
1561 9ca313aa aliguori
            ext_key_event(vs, read_u16(data, 2),
1562 9ca313aa aliguori
                          read_u32(data, 4), read_u32(data, 8));
1563 9ca313aa aliguori
            break;
1564 429a8ed3 malc
        case 1:
1565 429a8ed3 malc
            if (len == 2)
1566 429a8ed3 malc
                return 4;
1567 429a8ed3 malc
1568 429a8ed3 malc
            switch (read_u16 (data, 2)) {
1569 429a8ed3 malc
            case 0:
1570 429a8ed3 malc
                audio_add(vs);
1571 429a8ed3 malc
                break;
1572 429a8ed3 malc
            case 1:
1573 429a8ed3 malc
                audio_del(vs);
1574 429a8ed3 malc
                break;
1575 429a8ed3 malc
            case 2:
1576 429a8ed3 malc
                if (len == 4)
1577 429a8ed3 malc
                    return 10;
1578 429a8ed3 malc
                switch (read_u8(data, 4)) {
1579 429a8ed3 malc
                case 0: vs->as.fmt = AUD_FMT_U8; break;
1580 429a8ed3 malc
                case 1: vs->as.fmt = AUD_FMT_S8; break;
1581 429a8ed3 malc
                case 2: vs->as.fmt = AUD_FMT_U16; break;
1582 429a8ed3 malc
                case 3: vs->as.fmt = AUD_FMT_S16; break;
1583 429a8ed3 malc
                case 4: vs->as.fmt = AUD_FMT_U32; break;
1584 429a8ed3 malc
                case 5: vs->as.fmt = AUD_FMT_S32; break;
1585 429a8ed3 malc
                default:
1586 429a8ed3 malc
                    printf("Invalid audio format %d\n", read_u8(data, 4));
1587 429a8ed3 malc
                    vnc_client_error(vs);
1588 429a8ed3 malc
                    break;
1589 429a8ed3 malc
                }
1590 429a8ed3 malc
                vs->as.nchannels = read_u8(data, 5);
1591 429a8ed3 malc
                if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
1592 429a8ed3 malc
                    printf("Invalid audio channel coount %d\n",
1593 429a8ed3 malc
                           read_u8(data, 5));
1594 429a8ed3 malc
                    vnc_client_error(vs);
1595 429a8ed3 malc
                    break;
1596 429a8ed3 malc
                }
1597 429a8ed3 malc
                vs->as.freq = read_u32(data, 6);
1598 429a8ed3 malc
                break;
1599 429a8ed3 malc
            default:
1600 429a8ed3 malc
                printf ("Invalid audio message %d\n", read_u8(data, 4));
1601 429a8ed3 malc
                vnc_client_error(vs);
1602 429a8ed3 malc
                break;
1603 429a8ed3 malc
            }
1604 429a8ed3 malc
            break;
1605 429a8ed3 malc
1606 9ca313aa aliguori
        default:
1607 9ca313aa aliguori
            printf("Msg: %d\n", read_u16(data, 0));
1608 9ca313aa aliguori
            vnc_client_error(vs);
1609 9ca313aa aliguori
            break;
1610 9ca313aa aliguori
        }
1611 9ca313aa aliguori
        break;
1612 24236869 bellard
    default:
1613 24236869 bellard
        printf("Msg: %d\n", data[0]);
1614 24236869 bellard
        vnc_client_error(vs);
1615 24236869 bellard
        break;
1616 24236869 bellard
    }
1617 5fafdf24 ths
1618 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1619 24236869 bellard
    return 0;
1620 24236869 bellard
}
1621 24236869 bellard
1622 60fe76f3 ths
static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1623 24236869 bellard
{
1624 c35734b2 ths
    char buf[1024];
1625 c35734b2 ths
    int size;
1626 24236869 bellard
1627 0e1f5a0c aliguori
    vs->width = ds_get_width(vs->ds);
1628 0e1f5a0c aliguori
    vs->height = ds_get_height(vs->ds);
1629 0e1f5a0c aliguori
    vnc_write_u16(vs, ds_get_width(vs->ds));
1630 0e1f5a0c aliguori
    vnc_write_u16(vs, ds_get_height(vs->ds));
1631 24236869 bellard
1632 ca4cca4d aliguori
    pixel_format_message(vs);
1633 24236869 bellard
1634 c35734b2 ths
    if (qemu_name)
1635 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
1636 c35734b2 ths
    else
1637 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU");
1638 c35734b2 ths
1639 c35734b2 ths
    vnc_write_u32(vs, size);
1640 c35734b2 ths
    vnc_write(vs, buf, size);
1641 24236869 bellard
    vnc_flush(vs);
1642 24236869 bellard
1643 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1644 24236869 bellard
1645 24236869 bellard
    return 0;
1646 24236869 bellard
}
1647 24236869 bellard
1648 70848515 ths
static void make_challenge(VncState *vs)
1649 70848515 ths
{
1650 70848515 ths
    int i;
1651 70848515 ths
1652 70848515 ths
    srand(time(NULL)+getpid()+getpid()*987654+rand());
1653 70848515 ths
1654 70848515 ths
    for (i = 0 ; i < sizeof(vs->challenge) ; i++)
1655 70848515 ths
        vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1656 70848515 ths
}
1657 70848515 ths
1658 60fe76f3 ths
static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1659 70848515 ths
{
1660 60fe76f3 ths
    unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
1661 70848515 ths
    int i, j, pwlen;
1662 60fe76f3 ths
    unsigned char key[8];
1663 70848515 ths
1664 70848515 ths
    if (!vs->password || !vs->password[0]) {
1665 70848515 ths
        VNC_DEBUG("No password configured on server");
1666 70848515 ths
        vnc_write_u32(vs, 1); /* Reject auth */
1667 70848515 ths
        if (vs->minor >= 8) {
1668 70848515 ths
            static const char err[] = "Authentication failed";
1669 70848515 ths
            vnc_write_u32(vs, sizeof(err));
1670 70848515 ths
            vnc_write(vs, err, sizeof(err));
1671 70848515 ths
        }
1672 70848515 ths
        vnc_flush(vs);
1673 70848515 ths
        vnc_client_error(vs);
1674 70848515 ths
        return 0;
1675 70848515 ths
    }
1676 70848515 ths
1677 70848515 ths
    memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
1678 70848515 ths
1679 70848515 ths
    /* Calculate the expected challenge response */
1680 70848515 ths
    pwlen = strlen(vs->password);
1681 70848515 ths
    for (i=0; i<sizeof(key); i++)
1682 70848515 ths
        key[i] = i<pwlen ? vs->password[i] : 0;
1683 70848515 ths
    deskey(key, EN0);
1684 70848515 ths
    for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
1685 70848515 ths
        des(response+j, response+j);
1686 70848515 ths
1687 70848515 ths
    /* Compare expected vs actual challenge response */
1688 70848515 ths
    if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
1689 70848515 ths
        VNC_DEBUG("Client challenge reponse did not match\n");
1690 70848515 ths
        vnc_write_u32(vs, 1); /* Reject auth */
1691 70848515 ths
        if (vs->minor >= 8) {
1692 70848515 ths
            static const char err[] = "Authentication failed";
1693 70848515 ths
            vnc_write_u32(vs, sizeof(err));
1694 70848515 ths
            vnc_write(vs, err, sizeof(err));
1695 70848515 ths
        }
1696 70848515 ths
        vnc_flush(vs);
1697 70848515 ths
        vnc_client_error(vs);
1698 70848515 ths
    } else {
1699 70848515 ths
        VNC_DEBUG("Accepting VNC challenge response\n");
1700 70848515 ths
        vnc_write_u32(vs, 0); /* Accept auth */
1701 70848515 ths
        vnc_flush(vs);
1702 70848515 ths
1703 70848515 ths
        vnc_read_when(vs, protocol_client_init, 1);
1704 70848515 ths
    }
1705 70848515 ths
    return 0;
1706 70848515 ths
}
1707 70848515 ths
1708 70848515 ths
static int start_auth_vnc(VncState *vs)
1709 70848515 ths
{
1710 70848515 ths
    make_challenge(vs);
1711 70848515 ths
    /* Send client a 'random' challenge */
1712 70848515 ths
    vnc_write(vs, vs->challenge, sizeof(vs->challenge));
1713 70848515 ths
    vnc_flush(vs);
1714 70848515 ths
1715 70848515 ths
    vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
1716 70848515 ths
    return 0;
1717 70848515 ths
}
1718 70848515 ths
1719 8d5d2d4c ths
1720 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
1721 8d5d2d4c ths
#define DH_BITS 1024
1722 8d5d2d4c ths
static gnutls_dh_params_t dh_params;
1723 8d5d2d4c ths
1724 8d5d2d4c ths
static int vnc_tls_initialize(void)
1725 8d5d2d4c ths
{
1726 8d5d2d4c ths
    static int tlsinitialized = 0;
1727 8d5d2d4c ths
1728 8d5d2d4c ths
    if (tlsinitialized)
1729 8d5d2d4c ths
        return 1;
1730 8d5d2d4c ths
1731 8d5d2d4c ths
    if (gnutls_global_init () < 0)
1732 8d5d2d4c ths
        return 0;
1733 8d5d2d4c ths
1734 8d5d2d4c ths
    /* XXX ought to re-generate diffie-hellmen params periodically */
1735 8d5d2d4c ths
    if (gnutls_dh_params_init (&dh_params) < 0)
1736 8d5d2d4c ths
        return 0;
1737 8d5d2d4c ths
    if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
1738 8d5d2d4c ths
        return 0;
1739 8d5d2d4c ths
1740 234c9bcd ths
#if defined(_VNC_DEBUG) && _VNC_DEBUG >= 2
1741 8d5d2d4c ths
    gnutls_global_set_log_level(10);
1742 8d5d2d4c ths
    gnutls_global_set_log_function(vnc_debug_gnutls_log);
1743 8d5d2d4c ths
#endif
1744 8d5d2d4c ths
1745 8d5d2d4c ths
    tlsinitialized = 1;
1746 8d5d2d4c ths
1747 8d5d2d4c ths
    return 1;
1748 8d5d2d4c ths
}
1749 8d5d2d4c ths
1750 8d5d2d4c ths
static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
1751 8d5d2d4c ths
{
1752 8d5d2d4c ths
    gnutls_anon_server_credentials anon_cred;
1753 8d5d2d4c ths
    int ret;
1754 8d5d2d4c ths
1755 8d5d2d4c ths
    if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
1756 8d5d2d4c ths
        VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1757 8d5d2d4c ths
        return NULL;
1758 8d5d2d4c ths
    }
1759 8d5d2d4c ths
1760 8d5d2d4c ths
    gnutls_anon_set_server_dh_params(anon_cred, dh_params);
1761 8d5d2d4c ths
1762 8d5d2d4c ths
    return anon_cred;
1763 8d5d2d4c ths
}
1764 8d5d2d4c ths
1765 8d5d2d4c ths
1766 6f43024c ths
static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *vs)
1767 3a702699 ths
{
1768 3a702699 ths
    gnutls_certificate_credentials_t x509_cred;
1769 3a702699 ths
    int ret;
1770 6f43024c ths
1771 6f43024c ths
    if (!vs->x509cacert) {
1772 6f43024c ths
        VNC_DEBUG("No CA x509 certificate specified\n");
1773 6f43024c ths
        return NULL;
1774 6f43024c ths
    }
1775 6f43024c ths
    if (!vs->x509cert) {
1776 6f43024c ths
        VNC_DEBUG("No server x509 certificate specified\n");
1777 6f43024c ths
        return NULL;
1778 6f43024c ths
    }
1779 6f43024c ths
    if (!vs->x509key) {
1780 6f43024c ths
        VNC_DEBUG("No server private key specified\n");
1781 6f43024c ths
        return NULL;
1782 6f43024c ths
    }
1783 3a702699 ths
1784 3a702699 ths
    if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
1785 3a702699 ths
        VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1786 3a702699 ths
        return NULL;
1787 3a702699 ths
    }
1788 6f43024c ths
    if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
1789 6f43024c ths
                                                      vs->x509cacert,
1790 6f43024c ths
                                                      GNUTLS_X509_FMT_PEM)) < 0) {
1791 3a702699 ths
        VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
1792 3a702699 ths
        gnutls_certificate_free_credentials(x509_cred);
1793 3a702699 ths
        return NULL;
1794 3a702699 ths
    }
1795 3a702699 ths
1796 6f43024c ths
    if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
1797 6f43024c ths
                                                     vs->x509cert,
1798 6f43024c ths
                                                     vs->x509key,
1799 3a702699 ths
                                                     GNUTLS_X509_FMT_PEM)) < 0) {
1800 3a702699 ths
        VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
1801 3a702699 ths
        gnutls_certificate_free_credentials(x509_cred);
1802 3a702699 ths
        return NULL;
1803 3a702699 ths
    }
1804 3a702699 ths
1805 6f43024c ths
    if (vs->x509cacrl) {
1806 6f43024c ths
        if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
1807 6f43024c ths
                                                        vs->x509cacrl,
1808 6f43024c ths
                                                        GNUTLS_X509_FMT_PEM)) < 0) {
1809 3a702699 ths
            VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
1810 3a702699 ths
            gnutls_certificate_free_credentials(x509_cred);
1811 3a702699 ths
            return NULL;
1812 3a702699 ths
        }
1813 3a702699 ths
    }
1814 3a702699 ths
1815 3a702699 ths
    gnutls_certificate_set_dh_params (x509_cred, dh_params);
1816 3a702699 ths
1817 3a702699 ths
    return x509_cred;
1818 3a702699 ths
}
1819 3a702699 ths
1820 469b15c6 ths
static int vnc_validate_certificate(struct VncState *vs)
1821 469b15c6 ths
{
1822 469b15c6 ths
    int ret;
1823 469b15c6 ths
    unsigned int status;
1824 469b15c6 ths
    const gnutls_datum_t *certs;
1825 469b15c6 ths
    unsigned int nCerts, i;
1826 469b15c6 ths
    time_t now;
1827 469b15c6 ths
1828 469b15c6 ths
    VNC_DEBUG("Validating client certificate\n");
1829 469b15c6 ths
    if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) < 0) {
1830 469b15c6 ths
        VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
1831 469b15c6 ths
        return -1;
1832 469b15c6 ths
    }
1833 469b15c6 ths
1834 469b15c6 ths
    if ((now = time(NULL)) == ((time_t)-1)) {
1835 469b15c6 ths
        return -1;
1836 469b15c6 ths
    }
1837 469b15c6 ths
1838 469b15c6 ths
    if (status != 0) {
1839 469b15c6 ths
        if (status & GNUTLS_CERT_INVALID)
1840 469b15c6 ths
            VNC_DEBUG("The certificate is not trusted.\n");
1841 469b15c6 ths
1842 469b15c6 ths
        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1843 469b15c6 ths
            VNC_DEBUG("The certificate hasn't got a known issuer.\n");
1844 469b15c6 ths
1845 469b15c6 ths
        if (status & GNUTLS_CERT_REVOKED)
1846 469b15c6 ths
            VNC_DEBUG("The certificate has been revoked.\n");
1847 469b15c6 ths
1848 469b15c6 ths
        if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1849 469b15c6 ths
            VNC_DEBUG("The certificate uses an insecure algorithm\n");
1850 469b15c6 ths
1851 469b15c6 ths
        return -1;
1852 469b15c6 ths
    } else {
1853 469b15c6 ths
        VNC_DEBUG("Certificate is valid!\n");
1854 469b15c6 ths
    }
1855 469b15c6 ths
1856 469b15c6 ths
    /* Only support x509 for now */
1857 469b15c6 ths
    if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509)
1858 469b15c6 ths
        return -1;
1859 469b15c6 ths
1860 469b15c6 ths
    if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts)))
1861 469b15c6 ths
        return -1;
1862 469b15c6 ths
1863 469b15c6 ths
    for (i = 0 ; i < nCerts ; i++) {
1864 469b15c6 ths
        gnutls_x509_crt_t cert;
1865 469b15c6 ths
        VNC_DEBUG ("Checking certificate chain %d\n", i);
1866 469b15c6 ths
        if (gnutls_x509_crt_init (&cert) < 0)
1867 469b15c6 ths
            return -1;
1868 469b15c6 ths
1869 469b15c6 ths
        if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
1870 469b15c6 ths
            gnutls_x509_crt_deinit (cert);
1871 469b15c6 ths
            return -1;
1872 469b15c6 ths
        }
1873 469b15c6 ths
1874 469b15c6 ths
        if (gnutls_x509_crt_get_expiration_time (cert) < now) {
1875 469b15c6 ths
            VNC_DEBUG("The certificate has expired\n");
1876 469b15c6 ths
            gnutls_x509_crt_deinit (cert);
1877 469b15c6 ths
            return -1;
1878 469b15c6 ths
        }
1879 469b15c6 ths
1880 469b15c6 ths
        if (gnutls_x509_crt_get_activation_time (cert) > now) {
1881 469b15c6 ths
            VNC_DEBUG("The certificate is not yet activated\n");
1882 469b15c6 ths
            gnutls_x509_crt_deinit (cert);
1883 469b15c6 ths
            return -1;
1884 469b15c6 ths
        }
1885 469b15c6 ths
1886 469b15c6 ths
        if (gnutls_x509_crt_get_activation_time (cert) > now) {
1887 469b15c6 ths
            VNC_DEBUG("The certificate is not yet activated\n");
1888 469b15c6 ths
            gnutls_x509_crt_deinit (cert);
1889 469b15c6 ths
            return -1;
1890 469b15c6 ths
        }
1891 469b15c6 ths
1892 469b15c6 ths
        gnutls_x509_crt_deinit (cert);
1893 469b15c6 ths
    }
1894 469b15c6 ths
1895 469b15c6 ths
    return 0;
1896 469b15c6 ths
}
1897 469b15c6 ths
1898 469b15c6 ths
1899 8d5d2d4c ths
static int start_auth_vencrypt_subauth(VncState *vs)
1900 8d5d2d4c ths
{
1901 8d5d2d4c ths
    switch (vs->subauth) {
1902 8d5d2d4c ths
    case VNC_AUTH_VENCRYPT_TLSNONE:
1903 3a702699 ths
    case VNC_AUTH_VENCRYPT_X509NONE:
1904 8d5d2d4c ths
       VNC_DEBUG("Accept TLS auth none\n");
1905 8d5d2d4c ths
       vnc_write_u32(vs, 0); /* Accept auth completion */
1906 8d5d2d4c ths
       vnc_read_when(vs, protocol_client_init, 1);
1907 8d5d2d4c ths
       break;
1908 8d5d2d4c ths
1909 8d5d2d4c ths
    case VNC_AUTH_VENCRYPT_TLSVNC:
1910 3a702699 ths
    case VNC_AUTH_VENCRYPT_X509VNC:
1911 8d5d2d4c ths
       VNC_DEBUG("Start TLS auth VNC\n");
1912 8d5d2d4c ths
       return start_auth_vnc(vs);
1913 8d5d2d4c ths
1914 8d5d2d4c ths
    default: /* Should not be possible, but just in case */
1915 8d5d2d4c ths
       VNC_DEBUG("Reject auth %d\n", vs->auth);
1916 8d5d2d4c ths
       vnc_write_u8(vs, 1);
1917 8d5d2d4c ths
       if (vs->minor >= 8) {
1918 8d5d2d4c ths
           static const char err[] = "Unsupported authentication type";
1919 8d5d2d4c ths
           vnc_write_u32(vs, sizeof(err));
1920 8d5d2d4c ths
           vnc_write(vs, err, sizeof(err));
1921 8d5d2d4c ths
       }
1922 8d5d2d4c ths
       vnc_client_error(vs);
1923 8d5d2d4c ths
    }
1924 8d5d2d4c ths
1925 8d5d2d4c ths
    return 0;
1926 8d5d2d4c ths
}
1927 8d5d2d4c ths
1928 8d5d2d4c ths
static void vnc_handshake_io(void *opaque);
1929 8d5d2d4c ths
1930 8d5d2d4c ths
static int vnc_continue_handshake(struct VncState *vs) {
1931 8d5d2d4c ths
    int ret;
1932 8d5d2d4c ths
1933 8d5d2d4c ths
    if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
1934 8d5d2d4c ths
       if (!gnutls_error_is_fatal(ret)) {
1935 8d5d2d4c ths
           VNC_DEBUG("Handshake interrupted (blocking)\n");
1936 8d5d2d4c ths
           if (!gnutls_record_get_direction(vs->tls_session))
1937 8d5d2d4c ths
               qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
1938 8d5d2d4c ths
           else
1939 8d5d2d4c ths
               qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
1940 8d5d2d4c ths
           return 0;
1941 8d5d2d4c ths
       }
1942 8d5d2d4c ths
       VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
1943 8d5d2d4c ths
       vnc_client_error(vs);
1944 8d5d2d4c ths
       return -1;
1945 8d5d2d4c ths
    }
1946 8d5d2d4c ths
1947 469b15c6 ths
    if (vs->x509verify) {
1948 469b15c6 ths
        if (vnc_validate_certificate(vs) < 0) {
1949 469b15c6 ths
            VNC_DEBUG("Client verification failed\n");
1950 469b15c6 ths
            vnc_client_error(vs);
1951 469b15c6 ths
            return -1;
1952 469b15c6 ths
        } else {
1953 469b15c6 ths
            VNC_DEBUG("Client verification passed\n");
1954 469b15c6 ths
        }
1955 469b15c6 ths
    }
1956 469b15c6 ths
1957 8d5d2d4c ths
    VNC_DEBUG("Handshake done, switching to TLS data mode\n");
1958 8d5d2d4c ths
    vs->wiremode = VNC_WIREMODE_TLS;
1959 8d5d2d4c ths
    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1960 8d5d2d4c ths
1961 8d5d2d4c ths
    return start_auth_vencrypt_subauth(vs);
1962 8d5d2d4c ths
}
1963 8d5d2d4c ths
1964 8d5d2d4c ths
static void vnc_handshake_io(void *opaque) {
1965 8d5d2d4c ths
    struct VncState *vs = (struct VncState *)opaque;
1966 8d5d2d4c ths
1967 8d5d2d4c ths
    VNC_DEBUG("Handshake IO continue\n");
1968 8d5d2d4c ths
    vnc_continue_handshake(vs);
1969 8d5d2d4c ths
}
1970 8d5d2d4c ths
1971 3a702699 ths
#define NEED_X509_AUTH(vs)                              \
1972 3a702699 ths
    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
1973 3a702699 ths
     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
1974 3a702699 ths
     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
1975 3a702699 ths
1976 3a702699 ths
1977 8d5d2d4c ths
static int vnc_start_tls(struct VncState *vs) {
1978 8d5d2d4c ths
    static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
1979 8d5d2d4c ths
    static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
1980 8d5d2d4c ths
    static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
1981 3a702699 ths
    static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
1982 8d5d2d4c ths
1983 8d5d2d4c ths
    VNC_DEBUG("Do TLS setup\n");
1984 8d5d2d4c ths
    if (vnc_tls_initialize() < 0) {
1985 8d5d2d4c ths
        VNC_DEBUG("Failed to init TLS\n");
1986 8d5d2d4c ths
        vnc_client_error(vs);
1987 8d5d2d4c ths
        return -1;
1988 8d5d2d4c ths
    }
1989 8d5d2d4c ths
    if (vs->tls_session == NULL) {
1990 8d5d2d4c ths
        if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
1991 8d5d2d4c ths
            vnc_client_error(vs);
1992 8d5d2d4c ths
            return -1;
1993 8d5d2d4c ths
        }
1994 8d5d2d4c ths
1995 8d5d2d4c ths
        if (gnutls_set_default_priority(vs->tls_session) < 0) {
1996 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
1997 8d5d2d4c ths
            vs->tls_session = NULL;
1998 8d5d2d4c ths
            vnc_client_error(vs);
1999 8d5d2d4c ths
            return -1;
2000 8d5d2d4c ths
        }
2001 8d5d2d4c ths
2002 3a702699 ths
        if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) {
2003 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
2004 8d5d2d4c ths
            vs->tls_session = NULL;
2005 8d5d2d4c ths
            vnc_client_error(vs);
2006 8d5d2d4c ths
            return -1;
2007 8d5d2d4c ths
        }
2008 8d5d2d4c ths
2009 8d5d2d4c ths
        if (gnutls_certificate_type_set_priority(vs->tls_session, cert_type_priority) < 0) {
2010 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
2011 8d5d2d4c ths
            vs->tls_session = NULL;
2012 8d5d2d4c ths
            vnc_client_error(vs);
2013 8d5d2d4c ths
            return -1;
2014 8d5d2d4c ths
        }
2015 8d5d2d4c ths
2016 8d5d2d4c ths
        if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 0) {
2017 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
2018 8d5d2d4c ths
            vs->tls_session = NULL;
2019 8d5d2d4c ths
            vnc_client_error(vs);
2020 8d5d2d4c ths
            return -1;
2021 8d5d2d4c ths
        }
2022 8d5d2d4c ths
2023 3a702699 ths
        if (NEED_X509_AUTH(vs)) {
2024 6f43024c ths
            gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs);
2025 3a702699 ths
            if (!x509_cred) {
2026 3a702699 ths
                gnutls_deinit(vs->tls_session);
2027 3a702699 ths
                vs->tls_session = NULL;
2028 3a702699 ths
                vnc_client_error(vs);
2029 3a702699 ths
                return -1;
2030 3a702699 ths
            }
2031 3a702699 ths
            if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
2032 3a702699 ths
                gnutls_deinit(vs->tls_session);
2033 3a702699 ths
                vs->tls_session = NULL;
2034 3a702699 ths
                gnutls_certificate_free_credentials(x509_cred);
2035 3a702699 ths
                vnc_client_error(vs);
2036 3a702699 ths
                return -1;
2037 3a702699 ths
            }
2038 469b15c6 ths
            if (vs->x509verify) {
2039 469b15c6 ths
                VNC_DEBUG("Requesting a client certificate\n");
2040 469b15c6 ths
                gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST);
2041 469b15c6 ths
            }
2042 469b15c6 ths
2043 3a702699 ths
        } else {
2044 3a702699 ths
            gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
2045 3a702699 ths
            if (!anon_cred) {
2046 3a702699 ths
                gnutls_deinit(vs->tls_session);
2047 3a702699 ths
                vs->tls_session = NULL;
2048 3a702699 ths
                vnc_client_error(vs);
2049 3a702699 ths
                return -1;
2050 3a702699 ths
            }
2051 3a702699 ths
            if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
2052 3a702699 ths
                gnutls_deinit(vs->tls_session);
2053 3a702699 ths
                vs->tls_session = NULL;
2054 3a702699 ths
                gnutls_anon_free_server_credentials(anon_cred);
2055 3a702699 ths
                vnc_client_error(vs);
2056 3a702699 ths
                return -1;
2057 3a702699 ths
            }
2058 8d5d2d4c ths
        }
2059 8d5d2d4c ths
2060 8d5d2d4c ths
        gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
2061 8d5d2d4c ths
        gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
2062 8d5d2d4c ths
        gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
2063 8d5d2d4c ths
    }
2064 8d5d2d4c ths
2065 8d5d2d4c ths
    VNC_DEBUG("Start TLS handshake process\n");
2066 8d5d2d4c ths
    return vnc_continue_handshake(vs);
2067 8d5d2d4c ths
}
2068 8d5d2d4c ths
2069 60fe76f3 ths
static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
2070 8d5d2d4c ths
{
2071 8d5d2d4c ths
    int auth = read_u32(data, 0);
2072 8d5d2d4c ths
2073 8d5d2d4c ths
    if (auth != vs->subauth) {
2074 8d5d2d4c ths
        VNC_DEBUG("Rejecting auth %d\n", auth);
2075 8d5d2d4c ths
        vnc_write_u8(vs, 0); /* Reject auth */
2076 8d5d2d4c ths
        vnc_flush(vs);
2077 8d5d2d4c ths
        vnc_client_error(vs);
2078 8d5d2d4c ths
    } else {
2079 8d5d2d4c ths
        VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
2080 8d5d2d4c ths
        vnc_write_u8(vs, 1); /* Accept auth */
2081 8d5d2d4c ths
        vnc_flush(vs);
2082 8d5d2d4c ths
2083 8d5d2d4c ths
        if (vnc_start_tls(vs) < 0) {
2084 8d5d2d4c ths
            VNC_DEBUG("Failed to complete TLS\n");
2085 8d5d2d4c ths
            return 0;
2086 8d5d2d4c ths
        }
2087 8d5d2d4c ths
2088 8d5d2d4c ths
        if (vs->wiremode == VNC_WIREMODE_TLS) {
2089 8d5d2d4c ths
            VNC_DEBUG("Starting VeNCrypt subauth\n");
2090 8d5d2d4c ths
            return start_auth_vencrypt_subauth(vs);
2091 8d5d2d4c ths
        } else {
2092 8d5d2d4c ths
            VNC_DEBUG("TLS handshake blocked\n");
2093 8d5d2d4c ths
            return 0;
2094 8d5d2d4c ths
        }
2095 8d5d2d4c ths
    }
2096 8d5d2d4c ths
    return 0;
2097 8d5d2d4c ths
}
2098 8d5d2d4c ths
2099 60fe76f3 ths
static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len)
2100 8d5d2d4c ths
{
2101 8d5d2d4c ths
    if (data[0] != 0 ||
2102 8d5d2d4c ths
        data[1] != 2) {
2103 8d5d2d4c ths
        VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
2104 8d5d2d4c ths
        vnc_write_u8(vs, 1); /* Reject version */
2105 8d5d2d4c ths
        vnc_flush(vs);
2106 8d5d2d4c ths
        vnc_client_error(vs);
2107 8d5d2d4c ths
    } else {
2108 8d5d2d4c ths
        VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
2109 8d5d2d4c ths
        vnc_write_u8(vs, 0); /* Accept version */
2110 8d5d2d4c ths
        vnc_write_u8(vs, 1); /* Number of sub-auths */
2111 8d5d2d4c ths
        vnc_write_u32(vs, vs->subauth); /* The supported auth */
2112 8d5d2d4c ths
        vnc_flush(vs);
2113 8d5d2d4c ths
        vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
2114 8d5d2d4c ths
    }
2115 8d5d2d4c ths
    return 0;
2116 8d5d2d4c ths
}
2117 8d5d2d4c ths
2118 8d5d2d4c ths
static int start_auth_vencrypt(VncState *vs)
2119 8d5d2d4c ths
{
2120 8d5d2d4c ths
    /* Send VeNCrypt version 0.2 */
2121 8d5d2d4c ths
    vnc_write_u8(vs, 0);
2122 8d5d2d4c ths
    vnc_write_u8(vs, 2);
2123 8d5d2d4c ths
2124 8d5d2d4c ths
    vnc_read_when(vs, protocol_client_vencrypt_init, 2);
2125 8d5d2d4c ths
    return 0;
2126 8d5d2d4c ths
}
2127 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2128 8d5d2d4c ths
2129 60fe76f3 ths
static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2130 70848515 ths
{
2131 70848515 ths
    /* We only advertise 1 auth scheme at a time, so client
2132 70848515 ths
     * must pick the one we sent. Verify this */
2133 70848515 ths
    if (data[0] != vs->auth) { /* Reject auth */
2134 70848515 ths
       VNC_DEBUG("Reject auth %d\n", (int)data[0]);
2135 70848515 ths
       vnc_write_u32(vs, 1);
2136 70848515 ths
       if (vs->minor >= 8) {
2137 70848515 ths
           static const char err[] = "Authentication failed";
2138 70848515 ths
           vnc_write_u32(vs, sizeof(err));
2139 70848515 ths
           vnc_write(vs, err, sizeof(err));
2140 70848515 ths
       }
2141 70848515 ths
       vnc_client_error(vs);
2142 70848515 ths
    } else { /* Accept requested auth */
2143 70848515 ths
       VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2144 70848515 ths
       switch (vs->auth) {
2145 70848515 ths
       case VNC_AUTH_NONE:
2146 70848515 ths
           VNC_DEBUG("Accept auth none\n");
2147 a26c97ad balrog
           if (vs->minor >= 8) {
2148 a26c97ad balrog
               vnc_write_u32(vs, 0); /* Accept auth completion */
2149 a26c97ad balrog
               vnc_flush(vs);
2150 a26c97ad balrog
           }
2151 70848515 ths
           vnc_read_when(vs, protocol_client_init, 1);
2152 70848515 ths
           break;
2153 70848515 ths
2154 70848515 ths
       case VNC_AUTH_VNC:
2155 70848515 ths
           VNC_DEBUG("Start VNC auth\n");
2156 70848515 ths
           return start_auth_vnc(vs);
2157 70848515 ths
2158 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2159 8d5d2d4c ths
       case VNC_AUTH_VENCRYPT:
2160 8d5d2d4c ths
           VNC_DEBUG("Accept VeNCrypt auth\n");;
2161 8d5d2d4c ths
           return start_auth_vencrypt(vs);
2162 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2163 8d5d2d4c ths
2164 70848515 ths
       default: /* Should not be possible, but just in case */
2165 70848515 ths
           VNC_DEBUG("Reject auth %d\n", vs->auth);
2166 70848515 ths
           vnc_write_u8(vs, 1);
2167 70848515 ths
           if (vs->minor >= 8) {
2168 70848515 ths
               static const char err[] = "Authentication failed";
2169 70848515 ths
               vnc_write_u32(vs, sizeof(err));
2170 70848515 ths
               vnc_write(vs, err, sizeof(err));
2171 70848515 ths
           }
2172 70848515 ths
           vnc_client_error(vs);
2173 70848515 ths
       }
2174 70848515 ths
    }
2175 70848515 ths
    return 0;
2176 70848515 ths
}
2177 70848515 ths
2178 60fe76f3 ths
static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2179 24236869 bellard
{
2180 24236869 bellard
    char local[13];
2181 24236869 bellard
2182 24236869 bellard
    memcpy(local, version, 12);
2183 24236869 bellard
    local[12] = 0;
2184 24236869 bellard
2185 70848515 ths
    if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
2186 70848515 ths
        VNC_DEBUG("Malformed protocol version %s\n", local);
2187 24236869 bellard
        vnc_client_error(vs);
2188 24236869 bellard
        return 0;
2189 24236869 bellard
    }
2190 70848515 ths
    VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2191 70848515 ths
    if (vs->major != 3 ||
2192 70848515 ths
        (vs->minor != 3 &&
2193 b0566f4f ths
         vs->minor != 4 &&
2194 70848515 ths
         vs->minor != 5 &&
2195 70848515 ths
         vs->minor != 7 &&
2196 70848515 ths
         vs->minor != 8)) {
2197 70848515 ths
        VNC_DEBUG("Unsupported client version\n");
2198 70848515 ths
        vnc_write_u32(vs, VNC_AUTH_INVALID);
2199 70848515 ths
        vnc_flush(vs);
2200 70848515 ths
        vnc_client_error(vs);
2201 70848515 ths
        return 0;
2202 70848515 ths
    }
2203 b0566f4f ths
    /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
2204 70848515 ths
     * as equivalent to v3.3 by servers
2205 70848515 ths
     */
2206 b0566f4f ths
    if (vs->minor == 4 || vs->minor == 5)
2207 70848515 ths
        vs->minor = 3;
2208 70848515 ths
2209 70848515 ths
    if (vs->minor == 3) {
2210 70848515 ths
        if (vs->auth == VNC_AUTH_NONE) {
2211 70848515 ths
            VNC_DEBUG("Tell client auth none\n");
2212 70848515 ths
            vnc_write_u32(vs, vs->auth);
2213 70848515 ths
            vnc_flush(vs);
2214 70848515 ths
            vnc_read_when(vs, protocol_client_init, 1);
2215 70848515 ths
       } else if (vs->auth == VNC_AUTH_VNC) {
2216 70848515 ths
            VNC_DEBUG("Tell client VNC auth\n");
2217 70848515 ths
            vnc_write_u32(vs, vs->auth);
2218 70848515 ths
            vnc_flush(vs);
2219 70848515 ths
            start_auth_vnc(vs);
2220 70848515 ths
       } else {
2221 70848515 ths
            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
2222 70848515 ths
            vnc_write_u32(vs, VNC_AUTH_INVALID);
2223 70848515 ths
            vnc_flush(vs);
2224 70848515 ths
            vnc_client_error(vs);
2225 70848515 ths
       }
2226 70848515 ths
    } else {
2227 70848515 ths
        VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
2228 70848515 ths
        vnc_write_u8(vs, 1); /* num auth */
2229 70848515 ths
        vnc_write_u8(vs, vs->auth);
2230 70848515 ths
        vnc_read_when(vs, protocol_client_auth, 1);
2231 70848515 ths
        vnc_flush(vs);
2232 70848515 ths
    }
2233 24236869 bellard
2234 24236869 bellard
    return 0;
2235 24236869 bellard
}
2236 24236869 bellard
2237 3aa3eea3 balrog
static void vnc_connect(VncState *vs)
2238 3aa3eea3 balrog
{
2239 3aa3eea3 balrog
    VNC_DEBUG("New client on socket %d\n", vs->csock);
2240 bcfad70f aliguori
    vs->ds->idle = 0;
2241 3aa3eea3 balrog
    socket_set_nonblock(vs->csock);
2242 3aa3eea3 balrog
    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
2243 3aa3eea3 balrog
    vnc_write(vs, "RFB 003.008\n", 12);
2244 3aa3eea3 balrog
    vnc_flush(vs);
2245 3aa3eea3 balrog
    vnc_read_when(vs, protocol_version, 12);
2246 0e1f5a0c aliguori
    memset(vs->old_data, 0, ds_get_linesize(vs->ds) * ds_get_height(vs->ds));
2247 3aa3eea3 balrog
    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
2248 3aa3eea3 balrog
    vs->has_resize = 0;
2249 3aa3eea3 balrog
    vs->has_hextile = 0;
2250 3aa3eea3 balrog
    vs->ds->dpy_copy = NULL;
2251 3aa3eea3 balrog
    vnc_update_client(vs);
2252 53762ddb malc
    reset_keys(vs);
2253 3aa3eea3 balrog
}
2254 3aa3eea3 balrog
2255 24236869 bellard
static void vnc_listen_read(void *opaque)
2256 24236869 bellard
{
2257 24236869 bellard
    VncState *vs = opaque;
2258 24236869 bellard
    struct sockaddr_in addr;
2259 24236869 bellard
    socklen_t addrlen = sizeof(addr);
2260 24236869 bellard
2261 9f60ad50 balrog
    /* Catch-up */
2262 9f60ad50 balrog
    vga_hw_update();
2263 9f60ad50 balrog
2264 24236869 bellard
    vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2265 24236869 bellard
    if (vs->csock != -1) {
2266 3aa3eea3 balrog
        vnc_connect(vs);
2267 24236869 bellard
    }
2268 24236869 bellard
}
2269 24236869 bellard
2270 71cab5ca ths
void vnc_display_init(DisplayState *ds)
2271 24236869 bellard
{
2272 24236869 bellard
    VncState *vs;
2273 24236869 bellard
2274 24236869 bellard
    vs = qemu_mallocz(sizeof(VncState));
2275 24236869 bellard
    if (!vs)
2276 24236869 bellard
        exit(1);
2277 24236869 bellard
2278 24236869 bellard
    ds->opaque = vs;
2279 bcfad70f aliguori
    ds->idle = 1;
2280 a9ce8590 bellard
    vnc_state = vs;
2281 71cab5ca ths
    vs->display = NULL;
2282 70848515 ths
    vs->password = NULL;
2283 24236869 bellard
2284 24236869 bellard
    vs->lsock = -1;
2285 24236869 bellard
    vs->csock = -1;
2286 564c337e bellard
    vs->last_x = -1;
2287 564c337e bellard
    vs->last_y = -1;
2288 24236869 bellard
2289 24236869 bellard
    vs->ds = ds;
2290 24236869 bellard
2291 9ca313aa aliguori
    if (keyboard_layout)
2292 9ca313aa aliguori
        vs->kbd_layout = init_keyboard_layout(keyboard_layout);
2293 9ca313aa aliguori
    else
2294 9ca313aa aliguori
        vs->kbd_layout = init_keyboard_layout("en-us");
2295 24236869 bellard
2296 24236869 bellard
    if (!vs->kbd_layout)
2297 24236869 bellard
        exit(1);
2298 24236869 bellard
2299 a0ecfb73 balrog
    vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
2300 a0ecfb73 balrog
2301 73fc9742 ths
    vs->ds->data = NULL;
2302 73fc9742 ths
    vs->ds->dpy_update = vnc_dpy_update;
2303 73fc9742 ths
    vs->ds->dpy_resize = vnc_dpy_resize;
2304 a0ecfb73 balrog
    vs->ds->dpy_refresh = NULL;
2305 73fc9742 ths
2306 7eac3a87 aliguori
    vnc_colordepth(vs->ds, 32);
2307 73fc9742 ths
    vnc_dpy_resize(vs->ds, 640, 400);
2308 429a8ed3 malc
2309 429a8ed3 malc
    vs->as.freq = 44100;
2310 429a8ed3 malc
    vs->as.nchannels = 2;
2311 429a8ed3 malc
    vs->as.fmt = AUD_FMT_S16;
2312 429a8ed3 malc
    vs->as.endianness = 0;
2313 71cab5ca ths
}
2314 71cab5ca ths
2315 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2316 6f43024c ths
static int vnc_set_x509_credential(VncState *vs,
2317 6f43024c ths
                                   const char *certdir,
2318 6f43024c ths
                                   const char *filename,
2319 6f43024c ths
                                   char **cred,
2320 6f43024c ths
                                   int ignoreMissing)
2321 6f43024c ths
{
2322 6f43024c ths
    struct stat sb;
2323 6f43024c ths
2324 6f43024c ths
    if (*cred) {
2325 6f43024c ths
        qemu_free(*cred);
2326 6f43024c ths
        *cred = NULL;
2327 6f43024c ths
    }
2328 6f43024c ths
2329 6f43024c ths
    if (!(*cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2)))
2330 6f43024c ths
        return -1;
2331 6f43024c ths
2332 6f43024c ths
    strcpy(*cred, certdir);
2333 6f43024c ths
    strcat(*cred, "/");
2334 6f43024c ths
    strcat(*cred, filename);
2335 6f43024c ths
2336 6f43024c ths
    VNC_DEBUG("Check %s\n", *cred);
2337 6f43024c ths
    if (stat(*cred, &sb) < 0) {
2338 6f43024c ths
        qemu_free(*cred);
2339 6f43024c ths
        *cred = NULL;
2340 6f43024c ths
        if (ignoreMissing && errno == ENOENT)
2341 6f43024c ths
            return 0;
2342 6f43024c ths
        return -1;
2343 6f43024c ths
    }
2344 6f43024c ths
2345 6f43024c ths
    return 0;
2346 6f43024c ths
}
2347 6f43024c ths
2348 6f43024c ths
static int vnc_set_x509_credential_dir(VncState *vs,
2349 6f43024c ths
                                       const char *certdir)
2350 6f43024c ths
{
2351 6f43024c ths
    if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0)
2352 6f43024c ths
        goto cleanup;
2353 6f43024c ths
    if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 1) < 0)
2354 6f43024c ths
        goto cleanup;
2355 6f43024c ths
    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, &vs->x509cert, 0) < 0)
2356 6f43024c ths
        goto cleanup;
2357 6f43024c ths
    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, &vs->x509key, 0) < 0)
2358 6f43024c ths
        goto cleanup;
2359 6f43024c ths
2360 6f43024c ths
    return 0;
2361 6f43024c ths
2362 6f43024c ths
 cleanup:
2363 6f43024c ths
    qemu_free(vs->x509cacert);
2364 6f43024c ths
    qemu_free(vs->x509cacrl);
2365 6f43024c ths
    qemu_free(vs->x509cert);
2366 6f43024c ths
    qemu_free(vs->x509key);
2367 6f43024c ths
    vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
2368 6f43024c ths
    return -1;
2369 6f43024c ths
}
2370 6f43024c ths
#endif /* CONFIG_VNC_TLS */
2371 6f43024c ths
2372 71cab5ca ths
void vnc_display_close(DisplayState *ds)
2373 71cab5ca ths
{
2374 e25a5822 ths
    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2375 71cab5ca ths
2376 71cab5ca ths
    if (vs->display) {
2377 71cab5ca ths
        qemu_free(vs->display);
2378 71cab5ca ths
        vs->display = NULL;
2379 71cab5ca ths
    }
2380 71cab5ca ths
    if (vs->lsock != -1) {
2381 71cab5ca ths
        qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2382 71cab5ca ths
        close(vs->lsock);
2383 71cab5ca ths
        vs->lsock = -1;
2384 71cab5ca ths
    }
2385 71cab5ca ths
    if (vs->csock != -1) {
2386 71cab5ca ths
        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
2387 71cab5ca ths
        closesocket(vs->csock);
2388 71cab5ca ths
        vs->csock = -1;
2389 71cab5ca ths
        buffer_reset(&vs->input);
2390 71cab5ca ths
        buffer_reset(&vs->output);
2391 71cab5ca ths
        vs->need_update = 0;
2392 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2393 8d5d2d4c ths
        if (vs->tls_session) {
2394 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
2395 8d5d2d4c ths
            vs->tls_session = NULL;
2396 8d5d2d4c ths
        }
2397 8d5d2d4c ths
        vs->wiremode = VNC_WIREMODE_CLEAR;
2398 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2399 71cab5ca ths
    }
2400 70848515 ths
    vs->auth = VNC_AUTH_INVALID;
2401 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2402 8d5d2d4c ths
    vs->subauth = VNC_AUTH_INVALID;
2403 469b15c6 ths
    vs->x509verify = 0;
2404 8d5d2d4c ths
#endif
2405 429a8ed3 malc
    audio_del(vs);
2406 70848515 ths
}
2407 70848515 ths
2408 70848515 ths
int vnc_display_password(DisplayState *ds, const char *password)
2409 70848515 ths
{
2410 70848515 ths
    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2411 70848515 ths
2412 70848515 ths
    if (vs->password) {
2413 70848515 ths
        qemu_free(vs->password);
2414 70848515 ths
        vs->password = NULL;
2415 70848515 ths
    }
2416 70848515 ths
    if (password && password[0]) {
2417 70848515 ths
        if (!(vs->password = qemu_strdup(password)))
2418 70848515 ths
            return -1;
2419 70848515 ths
    }
2420 70848515 ths
2421 70848515 ths
    return 0;
2422 71cab5ca ths
}
2423 71cab5ca ths
2424 70848515 ths
int vnc_display_open(DisplayState *ds, const char *display)
2425 71cab5ca ths
{
2426 e25a5822 ths
    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2427 70848515 ths
    const char *options;
2428 70848515 ths
    int password = 0;
2429 3aa3eea3 balrog
    int reverse = 0;
2430 9712ecaf aliguori
    int to_port = 0;
2431 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2432 3a702699 ths
    int tls = 0, x509 = 0;
2433 8d5d2d4c ths
#endif
2434 71cab5ca ths
2435 71cab5ca ths
    vnc_display_close(ds);
2436 70848515 ths
    if (strcmp(display, "none") == 0)
2437 71cab5ca ths
        return 0;
2438 24236869 bellard
2439 70848515 ths
    if (!(vs->display = strdup(display)))
2440 71cab5ca ths
        return -1;
2441 70848515 ths
2442 70848515 ths
    options = display;
2443 70848515 ths
    while ((options = strchr(options, ','))) {
2444 70848515 ths
        options++;
2445 469b15c6 ths
        if (strncmp(options, "password", 8) == 0) {
2446 70848515 ths
            password = 1; /* Require password auth */
2447 3aa3eea3 balrog
        } else if (strncmp(options, "reverse", 7) == 0) {
2448 3aa3eea3 balrog
            reverse = 1;
2449 9712ecaf aliguori
        } else if (strncmp(options, "to=", 3) == 0) {
2450 9712ecaf aliguori
            to_port = atoi(options+3) + 5900;
2451 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2452 469b15c6 ths
        } else if (strncmp(options, "tls", 3) == 0) {
2453 8d5d2d4c ths
            tls = 1; /* Require TLS */
2454 469b15c6 ths
        } else if (strncmp(options, "x509", 4) == 0) {
2455 6f43024c ths
            char *start, *end;
2456 3a702699 ths
            x509 = 1; /* Require x509 certificates */
2457 6f43024c ths
            if (strncmp(options, "x509verify", 10) == 0)
2458 6f43024c ths
                vs->x509verify = 1; /* ...and verify client certs */
2459 6f43024c ths
2460 6f43024c ths
            /* Now check for 'x509=/some/path' postfix
2461 6f43024c ths
             * and use that to setup x509 certificate/key paths */
2462 6f43024c ths
            start = strchr(options, '=');
2463 6f43024c ths
            end = strchr(options, ',');
2464 6f43024c ths
            if (start && (!end || (start < end))) {
2465 6f43024c ths
                int len = end ? end-(start+1) : strlen(start+1);
2466 be351261 balrog
                char *path = qemu_strndup(start + 1, len);
2467 be15b141 blueswir1
2468 6f43024c ths
                VNC_DEBUG("Trying certificate path '%s'\n", path);
2469 6f43024c ths
                if (vnc_set_x509_credential_dir(vs, path) < 0) {
2470 6f43024c ths
                    fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2471 6f43024c ths
                    qemu_free(path);
2472 6f43024c ths
                    qemu_free(vs->display);
2473 6f43024c ths
                    vs->display = NULL;
2474 6f43024c ths
                    return -1;
2475 6f43024c ths
                }
2476 6f43024c ths
                qemu_free(path);
2477 6f43024c ths
            } else {
2478 6f43024c ths
                fprintf(stderr, "No certificate path provided\n");
2479 6f43024c ths
                qemu_free(vs->display);
2480 6f43024c ths
                vs->display = NULL;
2481 6f43024c ths
                return -1;
2482 6f43024c ths
            }
2483 8d5d2d4c ths
#endif
2484 469b15c6 ths
        }
2485 70848515 ths
    }
2486 70848515 ths
2487 70848515 ths
    if (password) {
2488 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2489 8d5d2d4c ths
        if (tls) {
2490 8d5d2d4c ths
            vs->auth = VNC_AUTH_VENCRYPT;
2491 3a702699 ths
            if (x509) {
2492 3a702699 ths
                VNC_DEBUG("Initializing VNC server with x509 password auth\n");
2493 3a702699 ths
                vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
2494 3a702699 ths
            } else {
2495 3a702699 ths
                VNC_DEBUG("Initializing VNC server with TLS password auth\n");
2496 3a702699 ths
                vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
2497 3a702699 ths
            }
2498 8d5d2d4c ths
        } else {
2499 8d5d2d4c ths
#endif
2500 8d5d2d4c ths
            VNC_DEBUG("Initializing VNC server with password auth\n");
2501 8d5d2d4c ths
            vs->auth = VNC_AUTH_VNC;
2502 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2503 8d5d2d4c ths
            vs->subauth = VNC_AUTH_INVALID;
2504 8d5d2d4c ths
        }
2505 8d5d2d4c ths
#endif
2506 70848515 ths
    } else {
2507 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2508 8d5d2d4c ths
        if (tls) {
2509 8d5d2d4c ths
            vs->auth = VNC_AUTH_VENCRYPT;
2510 3a702699 ths
            if (x509) {
2511 3a702699 ths
                VNC_DEBUG("Initializing VNC server with x509 no auth\n");
2512 3a702699 ths
                vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
2513 3a702699 ths
            } else {
2514 3a702699 ths
                VNC_DEBUG("Initializing VNC server with TLS no auth\n");
2515 3a702699 ths
                vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
2516 3a702699 ths
            }
2517 8d5d2d4c ths
        } else {
2518 8d5d2d4c ths
#endif
2519 8d5d2d4c ths
            VNC_DEBUG("Initializing VNC server with no auth\n");
2520 8d5d2d4c ths
            vs->auth = VNC_AUTH_NONE;
2521 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2522 8d5d2d4c ths
            vs->subauth = VNC_AUTH_INVALID;
2523 8d5d2d4c ths
        }
2524 8d5d2d4c ths
#endif
2525 70848515 ths
    }
2526 24236869 bellard
2527 3aa3eea3 balrog
    if (reverse) {
2528 9712ecaf aliguori
        /* connect to viewer */
2529 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0)
2530 9712ecaf aliguori
            vs->lsock = unix_connect(display+5);
2531 9712ecaf aliguori
        else
2532 9712ecaf aliguori
            vs->lsock = inet_connect(display, SOCK_STREAM);
2533 9712ecaf aliguori
        if (-1 == vs->lsock) {
2534 3aa3eea3 balrog
            free(vs->display);
2535 3aa3eea3 balrog
            vs->display = NULL;
2536 3aa3eea3 balrog
            return -1;
2537 3aa3eea3 balrog
        } else {
2538 3aa3eea3 balrog
            vs->csock = vs->lsock;
2539 3aa3eea3 balrog
            vs->lsock = -1;
2540 3aa3eea3 balrog
            vnc_connect(vs);
2541 3aa3eea3 balrog
        }
2542 9712ecaf aliguori
        return 0;
2543 24236869 bellard
2544 9712ecaf aliguori
    } else {
2545 9712ecaf aliguori
        /* listen for connects */
2546 9712ecaf aliguori
        char *dpy;
2547 9712ecaf aliguori
        dpy = qemu_malloc(256);
2548 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0) {
2549 9712ecaf aliguori
            strcpy(dpy, "unix:");
2550 4a55bfdf aliguori
            vs->lsock = unix_listen(display+5, dpy+5, 256-5);
2551 9712ecaf aliguori
        } else {
2552 9712ecaf aliguori
            vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
2553 9712ecaf aliguori
        }
2554 9712ecaf aliguori
        if (-1 == vs->lsock) {
2555 9712ecaf aliguori
            free(dpy);
2556 d0513623 balrog
            return -1;
2557 9712ecaf aliguori
        } else {
2558 9712ecaf aliguori
            free(vs->display);
2559 9712ecaf aliguori
            vs->display = dpy;
2560 9712ecaf aliguori
        }
2561 24236869 bellard
    }
2562 24236869 bellard
2563 71cab5ca ths
    return qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
2564 24236869 bellard
}