Statistics
| Branch: | Revision:

root / vnc.c @ 1536ff64

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