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