]> git.proxmox.com Git - mirror_qemu.git/blame - ui/vnc.c
vnc: Limit r/w access to size of allocated memory
[mirror_qemu.git] / ui / vnc.c
CommitLineData
7d510b8c
FB
1/*
2 * QEMU VNC display driver
5fafdf24 3 *
7d510b8c
FB
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
19a490bf 6 * Copyright (C) 2009 Red Hat, Inc
5fafdf24 7 *
7d510b8c
FB
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
19a490bf 27#include "vnc.h"
bd023f95 28#include "vnc-jobs.h"
87ecb68b 29#include "sysemu.h"
6ca957f0 30#include "qemu_socket.h"
87ecb68b 31#include "qemu-timer.h"
76655d6d 32#include "acl.h"
d96fd29c 33#include "qemu-objects.h"
2b54aa87 34#include "qmp-commands.h"
24236869 35
2430ffe4
SS
36#define VNC_REFRESH_INTERVAL_BASE 30
37#define VNC_REFRESH_INTERVAL_INC 50
38#define VNC_REFRESH_INTERVAL_MAX 2000
999342a0
CC
39static const struct timeval VNC_REFRESH_STATS = { 0, 500000 };
40static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
24236869
FB
41
42#include "vnc_keysym.h"
70848515
TS
43#include "d3des.h"
44
753b4053 45static VncDisplay *vnc_display; /* needed for info vnc */
7d957bd8 46static DisplayChangeListener *dcl;
a9ce8590 47
d467b679 48static int vnc_cursor_define(VncState *vs);
7bc9318b 49static void vnc_release_modifiers(VncState *vs);
d467b679 50
8cf36489
GH
51static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
52{
53#ifdef _VNC_DEBUG
54 static const char *mn[] = {
55 [0] = "undefined",
56 [VNC_SHARE_MODE_CONNECTING] = "connecting",
57 [VNC_SHARE_MODE_SHARED] = "shared",
58 [VNC_SHARE_MODE_EXCLUSIVE] = "exclusive",
59 [VNC_SHARE_MODE_DISCONNECTED] = "disconnected",
60 };
61 fprintf(stderr, "%s/%d: %s -> %s\n", __func__,
62 vs->csock, mn[vs->share_mode], mn[mode]);
63#endif
64
65 if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
66 vs->vd->num_exclusive--;
67 }
68 vs->share_mode = mode;
69 if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
70 vs->vd->num_exclusive++;
71 }
72}
73
1ff7df1a
AL
74static char *addr_to_string(const char *format,
75 struct sockaddr_storage *sa,
76 socklen_t salen) {
77 char *addr;
78 char host[NI_MAXHOST];
79 char serv[NI_MAXSERV];
80 int err;
457772e6 81 size_t addrlen;
1ff7df1a
AL
82
83 if ((err = getnameinfo((struct sockaddr *)sa, salen,
84 host, sizeof(host),
85 serv, sizeof(serv),
86 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
87 VNC_DEBUG("Cannot resolve address %d: %s\n",
88 err, gai_strerror(err));
89 return NULL;
90 }
91
457772e6 92 /* Enough for the existing format + the 2 vars we're
f425c278 93 * substituting in. */
457772e6 94 addrlen = strlen(format) + strlen(host) + strlen(serv);
7267c094 95 addr = g_malloc(addrlen + 1);
457772e6
AL
96 snprintf(addr, addrlen, format, host, serv);
97 addr[addrlen] = '\0';
1ff7df1a
AL
98
99 return addr;
100}
101
2f9606b3
AL
102
103char *vnc_socket_local_addr(const char *format, int fd) {
1ff7df1a
AL
104 struct sockaddr_storage sa;
105 socklen_t salen;
106
107 salen = sizeof(sa);
108 if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0)
109 return NULL;
110
111 return addr_to_string(format, &sa, salen);
112}
113
2f9606b3 114char *vnc_socket_remote_addr(const char *format, int fd) {
1ff7df1a
AL
115 struct sockaddr_storage sa;
116 socklen_t salen;
117
118 salen = sizeof(sa);
119 if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0)
120 return NULL;
121
122 return addr_to_string(format, &sa, salen);
123}
124
d96fd29c
LC
125static int put_addr_qdict(QDict *qdict, struct sockaddr_storage *sa,
126 socklen_t salen)
127{
128 char host[NI_MAXHOST];
129 char serv[NI_MAXSERV];
130 int err;
131
132 if ((err = getnameinfo((struct sockaddr *)sa, salen,
133 host, sizeof(host),
134 serv, sizeof(serv),
135 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
136 VNC_DEBUG("Cannot resolve address %d: %s\n",
137 err, gai_strerror(err));
138 return -1;
139 }
140
141 qdict_put(qdict, "host", qstring_from_str(host));
142 qdict_put(qdict, "service", qstring_from_str(serv));
dc0d4efc 143 qdict_put(qdict, "family",qstring_from_str(inet_strfamily(sa->ss_family)));
d96fd29c
LC
144
145 return 0;
146}
147
a7789382 148static int vnc_server_addr_put(QDict *qdict, int fd)
d96fd29c
LC
149{
150 struct sockaddr_storage sa;
151 socklen_t salen;
152
153 salen = sizeof(sa);
154 if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) {
155 return -1;
156 }
157
158 return put_addr_qdict(qdict, &sa, salen);
159}
160
161static int vnc_qdict_remote_addr(QDict *qdict, int fd)
162{
163 struct sockaddr_storage sa;
164 socklen_t salen;
165
166 salen = sizeof(sa);
167 if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) {
168 return -1;
169 }
170
171 return put_addr_qdict(qdict, &sa, salen);
172}
173
1ff7df1a
AL
174static const char *vnc_auth_name(VncDisplay *vd) {
175 switch (vd->auth) {
176 case VNC_AUTH_INVALID:
177 return "invalid";
178 case VNC_AUTH_NONE:
179 return "none";
180 case VNC_AUTH_VNC:
181 return "vnc";
182 case VNC_AUTH_RA2:
183 return "ra2";
184 case VNC_AUTH_RA2NE:
185 return "ra2ne";
186 case VNC_AUTH_TIGHT:
187 return "tight";
188 case VNC_AUTH_ULTRA:
189 return "ultra";
190 case VNC_AUTH_TLS:
191 return "tls";
192 case VNC_AUTH_VENCRYPT:
193#ifdef CONFIG_VNC_TLS
194 switch (vd->subauth) {
195 case VNC_AUTH_VENCRYPT_PLAIN:
196 return "vencrypt+plain";
197 case VNC_AUTH_VENCRYPT_TLSNONE:
198 return "vencrypt+tls+none";
199 case VNC_AUTH_VENCRYPT_TLSVNC:
200 return "vencrypt+tls+vnc";
201 case VNC_AUTH_VENCRYPT_TLSPLAIN:
202 return "vencrypt+tls+plain";
203 case VNC_AUTH_VENCRYPT_X509NONE:
204 return "vencrypt+x509+none";
205 case VNC_AUTH_VENCRYPT_X509VNC:
206 return "vencrypt+x509+vnc";
207 case VNC_AUTH_VENCRYPT_X509PLAIN:
208 return "vencrypt+x509+plain";
28a76be8
AL
209 case VNC_AUTH_VENCRYPT_TLSSASL:
210 return "vencrypt+tls+sasl";
211 case VNC_AUTH_VENCRYPT_X509SASL:
212 return "vencrypt+x509+sasl";
1ff7df1a
AL
213 default:
214 return "vencrypt";
215 }
216#else
217 return "vencrypt";
218#endif
2f9606b3 219 case VNC_AUTH_SASL:
28a76be8 220 return "sasl";
1ff7df1a
AL
221 }
222 return "unknown";
223}
224
a7789382
LC
225static int vnc_server_info_put(QDict *qdict)
226{
227 if (vnc_server_addr_put(qdict, vnc_display->lsock) < 0) {
228 return -1;
229 }
230
231 qdict_put(qdict, "auth", qstring_from_str(vnc_auth_name(vnc_display)));
232 return 0;
233}
234
4a80dba3 235static void vnc_client_cache_auth(VncState *client)
1ff7df1a 236{
2ded6ad7 237#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
d96fd29c 238 QDict *qdict;
2ded6ad7 239#endif
1ff7df1a 240
4a80dba3
LC
241 if (!client->info) {
242 return;
d96fd29c 243 }
1263b7d6 244
2ded6ad7 245#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
4a80dba3 246 qdict = qobject_to_qdict(client->info);
2ded6ad7 247#endif
4a80dba3 248
1263b7d6
AL
249#ifdef CONFIG_VNC_TLS
250 if (client->tls.session &&
d96fd29c
LC
251 client->tls.dname) {
252 qdict_put(qdict, "x509_dname", qstring_from_str(client->tls.dname));
253 }
1263b7d6
AL
254#endif
255#ifdef CONFIG_VNC_SASL
256 if (client->sasl.conn &&
d96fd29c 257 client->sasl.username) {
76825067
LC
258 qdict_put(qdict, "sasl_username",
259 qstring_from_str(client->sasl.username));
d96fd29c 260 }
1263b7d6 261#endif
4a80dba3 262}
d96fd29c 263
4a80dba3
LC
264static void vnc_client_cache_addr(VncState *client)
265{
266 QDict *qdict;
267
268 qdict = qdict_new();
269 if (vnc_qdict_remote_addr(qdict, client->csock) < 0) {
270 QDECREF(qdict);
271 /* XXX: how to report the error? */
272 return;
273 }
274
275 client->info = QOBJECT(qdict);
1ff7df1a
AL
276}
277
586153d9
LC
278static void vnc_qmp_event(VncState *vs, MonitorEvent event)
279{
280 QDict *server;
281 QObject *data;
282
283 if (!vs->info) {
284 return;
285 }
286
287 server = qdict_new();
288 if (vnc_server_info_put(server) < 0) {
289 QDECREF(server);
290 return;
291 }
292
293 data = qobject_from_jsonf("{ 'client': %p, 'server': %p }",
294 vs->info, QOBJECT(server));
295
296 monitor_protocol_event(event, data);
297
298 qobject_incref(vs->info);
299 qobject_decref(data);
300}
301
2b54aa87 302static VncClientInfo *qmp_query_vnc_client(const VncState *client)
a9ce8590 303{
2b54aa87
LC
304 struct sockaddr_storage sa;
305 socklen_t salen = sizeof(sa);
306 char host[NI_MAXHOST];
307 char serv[NI_MAXSERV];
308 VncClientInfo *info;
309
310 if (getpeername(client->csock, (struct sockaddr *)&sa, &salen) < 0) {
311 return NULL;
312 }
313
314 if (getnameinfo((struct sockaddr *)&sa, salen,
315 host, sizeof(host),
316 serv, sizeof(serv),
317 NI_NUMERICHOST | NI_NUMERICSERV) < 0) {
318 return NULL;
319 }
d96fd29c 320
2b54aa87
LC
321 info = g_malloc0(sizeof(*info));
322 info->host = g_strdup(host);
323 info->service = g_strdup(serv);
324 info->family = g_strdup(inet_strfamily(sa.ss_family));
d96fd29c
LC
325
326#ifdef CONFIG_VNC_TLS
2b54aa87
LC
327 if (client->tls.session && client->tls.dname) {
328 info->has_x509_dname = true;
329 info->x509_dname = g_strdup(client->tls.dname);
330 }
d96fd29c
LC
331#endif
332#ifdef CONFIG_VNC_SASL
2b54aa87
LC
333 if (client->sasl.conn && client->sasl.username) {
334 info->has_sasl_username = true;
335 info->sasl_username = g_strdup(client->sasl.username);
d96fd29c 336 }
2b54aa87 337#endif
1ff7df1a 338
2b54aa87 339 return info;
d96fd29c 340}
1ff7df1a 341
2b54aa87 342VncInfo *qmp_query_vnc(Error **errp)
d96fd29c 343{
2b54aa87
LC
344 VncInfo *info = g_malloc0(sizeof(*info));
345
d96fd29c 346 if (vnc_display == NULL || vnc_display->display == NULL) {
2b54aa87 347 info->enabled = false;
d96fd29c 348 } else {
2b54aa87
LC
349 VncClientInfoList *cur_item = NULL;
350 struct sockaddr_storage sa;
351 socklen_t salen = sizeof(sa);
352 char host[NI_MAXHOST];
353 char serv[NI_MAXSERV];
41b4bef6 354 VncState *client;
1ff7df1a 355
2b54aa87
LC
356 info->enabled = true;
357
358 /* for compatibility with the original command */
359 info->has_clients = true;
360
41b4bef6 361 QTAILQ_FOREACH(client, &vnc_display->clients, next) {
2b54aa87
LC
362 VncClientInfoList *cinfo = g_malloc0(sizeof(*info));
363 cinfo->value = qmp_query_vnc_client(client);
364
365 /* XXX: waiting for the qapi to support GSList */
366 if (!cur_item) {
367 info->clients = cur_item = cinfo;
368 } else {
369 cur_item->next = cinfo;
370 cur_item = cinfo;
1ff7df1a 371 }
d96fd29c
LC
372 }
373
2b54aa87
LC
374 if (getsockname(vnc_display->lsock, (struct sockaddr *)&sa,
375 &salen) == -1) {
376 error_set(errp, QERR_UNDEFINED_ERROR);
377 goto out_error;
378 }
d96fd29c 379
2b54aa87
LC
380 if (getnameinfo((struct sockaddr *)&sa, salen,
381 host, sizeof(host),
382 serv, sizeof(serv),
383 NI_NUMERICHOST | NI_NUMERICSERV) < 0) {
384 error_set(errp, QERR_UNDEFINED_ERROR);
385 goto out_error;
1ff7df1a 386 }
2b54aa87
LC
387
388 info->has_host = true;
389 info->host = g_strdup(host);
390
391 info->has_service = true;
392 info->service = g_strdup(serv);
393
394 info->has_family = true;
395 info->family = g_strdup(inet_strfamily(sa.ss_family));
396
397 info->has_auth = true;
398 info->auth = g_strdup(vnc_auth_name(vnc_display));
a9ce8590 399 }
2b54aa87
LC
400
401 return info;
402
403out_error:
404 qapi_free_VncInfo(info);
405 return NULL;
a9ce8590
FB
406}
407
24236869
FB
408/* TODO
409 1) Get the queue working for IO.
410 2) there is some weirdness when using the -S option (the screen is grey
411 and not totally invalidated
412 3) resolutions > 1024
413*/
414
2430ffe4 415static int vnc_update_client(VncState *vs, int has_dirty);
bd023f95 416static int vnc_update_client_sync(VncState *vs, int has_dirty);
198a0039
GH
417static void vnc_disconnect_start(VncState *vs);
418static void vnc_disconnect_finish(VncState *vs);
703bc68f
SS
419static void vnc_init_timer(VncDisplay *vd);
420static void vnc_remove_timer(VncDisplay *vd);
24236869 421
753b4053 422static void vnc_colordepth(VncState *vs);
1fc62412
SS
423static void framebuffer_update_request(VncState *vs, int incremental,
424 int x_position, int y_position,
425 int w, int h);
426static void vnc_refresh(void *opaque);
427static int vnc_refresh_server_surface(VncDisplay *vd);
7eac3a87 428
1fc62412 429static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
24236869 430{
24236869 431 int i;
1fc62412
SS
432 VncDisplay *vd = ds->opaque;
433 struct VncSurface *s = &vd->guest;
24236869
FB
434
435 h += y;
436
0486e8a7
AZ
437 /* round x down to ensure the loop only spans one 16-pixel block per,
438 iteration. otherwise, if (x % 16) != 0, the last iteration may span
439 two 16-pixel blocks but we only mark the first as dirty
440 */
441 w += (x % 16);
442 x -= (x % 16);
443
6baebed7
AL
444 x = MIN(x, s->ds->width);
445 y = MIN(y, s->ds->height);
446 w = MIN(x + w, s->ds->width) - x;
447 h = MIN(h, s->ds->height);
788abf8e 448
24236869 449 for (; y < h; y++)
28a76be8 450 for (i = 0; i < w; i += 16)
bc2429b9 451 set_bit((x + i) / 16, s->dirty[y]);
24236869
FB
452}
453
70a4568f
CC
454void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
455 int32_t encoding)
24236869
FB
456{
457 vnc_write_u16(vs, x);
458 vnc_write_u16(vs, y);
459 vnc_write_u16(vs, w);
460 vnc_write_u16(vs, h);
461
462 vnc_write_s32(vs, encoding);
463}
464
2f9606b3 465void buffer_reserve(Buffer *buffer, size_t len)
89064286
AL
466{
467 if ((buffer->capacity - buffer->offset) < len) {
28a76be8 468 buffer->capacity += (len + 1024);
7267c094 469 buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
28a76be8
AL
470 if (buffer->buffer == NULL) {
471 fprintf(stderr, "vnc: out of memory\n");
472 exit(1);
473 }
89064286
AL
474 }
475}
476
2f9606b3 477int buffer_empty(Buffer *buffer)
89064286
AL
478{
479 return buffer->offset == 0;
480}
481
2f9606b3 482uint8_t *buffer_end(Buffer *buffer)
89064286
AL
483{
484 return buffer->buffer + buffer->offset;
485}
486
2f9606b3 487void buffer_reset(Buffer *buffer)
89064286 488{
28a76be8 489 buffer->offset = 0;
89064286
AL
490}
491
5d418e3b
CC
492void buffer_free(Buffer *buffer)
493{
7267c094 494 g_free(buffer->buffer);
5d418e3b
CC
495 buffer->offset = 0;
496 buffer->capacity = 0;
497 buffer->buffer = NULL;
498}
499
2f9606b3 500void buffer_append(Buffer *buffer, const void *data, size_t len)
89064286
AL
501{
502 memcpy(buffer->buffer + buffer->offset, data, len);
503 buffer->offset += len;
504}
505
621aaeb9
GH
506static void vnc_desktop_resize(VncState *vs)
507{
508 DisplayState *ds = vs->ds;
509
510 if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
511 return;
512 }
1d4b638a
GH
513 if (vs->client_width == ds_get_width(ds) &&
514 vs->client_height == ds_get_height(ds)) {
515 return;
516 }
5862d195
GH
517 vs->client_width = ds_get_width(ds);
518 vs->client_height = ds_get_height(ds);
bd023f95 519 vnc_lock_output(vs);
621aaeb9
GH
520 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
521 vnc_write_u8(vs, 0);
522 vnc_write_u16(vs, 1); /* number of rects */
5862d195 523 vnc_framebuffer_update(vs, 0, 0, vs->client_width, vs->client_height,
621aaeb9 524 VNC_ENCODING_DESKTOPRESIZE);
bd023f95 525 vnc_unlock_output(vs);
621aaeb9
GH
526 vnc_flush(vs);
527}
528
bd023f95
CC
529#ifdef CONFIG_VNC_THREAD
530static void vnc_abort_display_jobs(VncDisplay *vd)
531{
532 VncState *vs;
533
534 QTAILQ_FOREACH(vs, &vd->clients, next) {
535 vnc_lock_output(vs);
536 vs->abort = true;
537 vnc_unlock_output(vs);
538 }
539 QTAILQ_FOREACH(vs, &vd->clients, next) {
540 vnc_jobs_join(vs);
541 }
542 QTAILQ_FOREACH(vs, &vd->clients, next) {
543 vnc_lock_output(vs);
544 vs->abort = false;
545 vnc_unlock_output(vs);
546 }
547}
548#else
549static void vnc_abort_display_jobs(VncDisplay *vd)
550{
551}
552#endif
553
1fc62412 554static void vnc_dpy_resize(DisplayState *ds)
24236869 555{
1fc62412 556 VncDisplay *vd = ds->opaque;
41b4bef6 557 VncState *vs;
1fc62412 558
bd023f95
CC
559 vnc_abort_display_jobs(vd);
560
1fc62412
SS
561 /* server surface */
562 if (!vd->server)
7267c094 563 vd->server = g_malloc0(sizeof(*vd->server));
1fc62412 564 if (vd->server->data)
7267c094 565 g_free(vd->server->data);
1fc62412 566 *(vd->server) = *(ds->surface);
7267c094 567 vd->server->data = g_malloc0(vd->server->linesize *
1fc62412 568 vd->server->height);
24236869 569
6baebed7 570 /* guest surface */
1fc62412 571 if (!vd->guest.ds)
7267c094 572 vd->guest.ds = g_malloc0(sizeof(*vd->guest.ds));
1fc62412 573 if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel)
a528b80c 574 console_color_init(ds);
1fc62412
SS
575 *(vd->guest.ds) = *(ds->surface);
576 memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
24236869 577
41b4bef6 578 QTAILQ_FOREACH(vs, &vd->clients, next) {
1fc62412 579 vnc_colordepth(vs);
1d4b638a 580 vnc_desktop_resize(vs);
d467b679
GH
581 if (vs->vd->cursor) {
582 vnc_cursor_define(vs);
583 }
1fc62412 584 memset(vs->dirty, 0xFF, sizeof(vs->dirty));
753b4053
AL
585 }
586}
587
3512779a 588/* fastest code */
d467b679
GH
589static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf,
590 void *pixels, int size)
3512779a
FB
591{
592 vnc_write(vs, pixels, size);
593}
594
595/* slowest but generic code. */
70a4568f 596void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
3512779a 597{
7eac3a87 598 uint8_t r, g, b;
1fc62412
SS
599 VncDisplay *vd = vs->vd;
600
601 r = ((((v & vd->server->pf.rmask) >> vd->server->pf.rshift) << vs->clientds.pf.rbits) >>
602 vd->server->pf.rbits);
603 g = ((((v & vd->server->pf.gmask) >> vd->server->pf.gshift) << vs->clientds.pf.gbits) >>
604 vd->server->pf.gbits);
605 b = ((((v & vd->server->pf.bmask) >> vd->server->pf.bshift) << vs->clientds.pf.bbits) >>
606 vd->server->pf.bbits);
6cec5487
AL
607 v = (r << vs->clientds.pf.rshift) |
608 (g << vs->clientds.pf.gshift) |
609 (b << vs->clientds.pf.bshift);
610 switch(vs->clientds.pf.bytes_per_pixel) {
3512779a
FB
611 case 1:
612 buf[0] = v;
613 break;
614 case 2:
6cec5487 615 if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) {
3512779a
FB
616 buf[0] = v >> 8;
617 buf[1] = v;
618 } else {
619 buf[1] = v >> 8;
620 buf[0] = v;
621 }
622 break;
623 default:
624 case 4:
6cec5487 625 if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) {
3512779a
FB
626 buf[0] = v >> 24;
627 buf[1] = v >> 16;
628 buf[2] = v >> 8;
629 buf[3] = v;
630 } else {
631 buf[3] = v >> 24;
632 buf[2] = v >> 16;
633 buf[1] = v >> 8;
634 buf[0] = v;
635 }
636 break;
637 }
638}
639
d467b679
GH
640static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf,
641 void *pixels1, int size)
3512779a 642{
3512779a 643 uint8_t buf[4];
3512779a 644
d467b679 645 if (pf->bytes_per_pixel == 4) {
7eac3a87
AL
646 uint32_t *pixels = pixels1;
647 int n, i;
648 n = size >> 2;
649 for(i = 0; i < n; i++) {
650 vnc_convert_pixel(vs, buf, pixels[i]);
6cec5487 651 vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
7eac3a87 652 }
d467b679 653 } else if (pf->bytes_per_pixel == 2) {
7eac3a87
AL
654 uint16_t *pixels = pixels1;
655 int n, i;
656 n = size >> 1;
657 for(i = 0; i < n; i++) {
658 vnc_convert_pixel(vs, buf, pixels[i]);
6cec5487 659 vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
7eac3a87 660 }
d467b679 661 } else if (pf->bytes_per_pixel == 1) {
7eac3a87
AL
662 uint8_t *pixels = pixels1;
663 int n, i;
664 n = size;
665 for(i = 0; i < n; i++) {
666 vnc_convert_pixel(vs, buf, pixels[i]);
6cec5487 667 vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
7eac3a87
AL
668 }
669 } else {
670 fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
3512779a
FB
671 }
672}
673
a885211e 674int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
24236869
FB
675{
676 int i;
60fe76f3 677 uint8_t *row;
1fc62412 678 VncDisplay *vd = vs->vd;
24236869 679
1fc62412 680 row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
24236869 681 for (i = 0; i < h; i++) {
d467b679 682 vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds));
28a76be8 683 row += ds_get_linesize(vs->ds);
24236869 684 }
a885211e 685 return 1;
24236869
FB
686}
687
bd023f95 688int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
24236869 689{
a885211e
CC
690 int n = 0;
691
fb437313 692 switch(vs->vnc_encoding) {
28a76be8 693 case VNC_ENCODING_ZLIB:
a885211e 694 n = vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
28a76be8
AL
695 break;
696 case VNC_ENCODING_HEXTILE:
697 vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
a885211e 698 n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
28a76be8 699 break;
380282b0
CC
700 case VNC_ENCODING_TIGHT:
701 n = vnc_tight_send_framebuffer_update(vs, x, y, w, h);
702 break;
efe556ad
CC
703 case VNC_ENCODING_TIGHT_PNG:
704 n = vnc_tight_png_send_framebuffer_update(vs, x, y, w, h);
705 break;
148954fa
CC
706 case VNC_ENCODING_ZRLE:
707 n = vnc_zrle_send_framebuffer_update(vs, x, y, w, h);
708 break;
709 case VNC_ENCODING_ZYWRLE:
710 n = vnc_zywrle_send_framebuffer_update(vs, x, y, w, h);
711 break;
28a76be8
AL
712 default:
713 vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
a885211e 714 n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
28a76be8 715 break;
fb437313 716 }
a885211e 717 return n;
24236869
FB
718}
719
753b4053 720static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
24236869 721{
3e28c9ad 722 /* send bitblit op to the vnc client */
bd023f95 723 vnc_lock_output(vs);
46a183da 724 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
24236869
FB
725 vnc_write_u8(vs, 0);
726 vnc_write_u16(vs, 1); /* number of rects */
29fa4ed9 727 vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
24236869
FB
728 vnc_write_u16(vs, src_x);
729 vnc_write_u16(vs, src_y);
bd023f95 730 vnc_unlock_output(vs);
24236869
FB
731 vnc_flush(vs);
732}
733
753b4053
AL
734static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
735{
736 VncDisplay *vd = ds->opaque;
198a0039 737 VncState *vs, *vn;
1fc62412
SS
738 uint8_t *src_row;
739 uint8_t *dst_row;
740 int i,x,y,pitch,depth,inc,w_lim,s;
741 int cmp_bytes;
198a0039 742
1fc62412 743 vnc_refresh_server_surface(vd);
41b4bef6 744 QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
198a0039
GH
745 if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
746 vs->force_update = 1;
bd023f95 747 vnc_update_client_sync(vs, 1);
198a0039
GH
748 /* vs might be free()ed here */
749 }
750 }
751
1fc62412
SS
752 /* do bitblit op on the local surface too */
753 pitch = ds_get_linesize(vd->ds);
754 depth = ds_get_bytes_per_pixel(vd->ds);
755 src_row = vd->server->data + pitch * src_y + depth * src_x;
756 dst_row = vd->server->data + pitch * dst_y + depth * dst_x;
757 y = dst_y;
758 inc = 1;
759 if (dst_y > src_y) {
760 /* copy backwards */
761 src_row += pitch * (h-1);
762 dst_row += pitch * (h-1);
763 pitch = -pitch;
764 y = dst_y + h - 1;
765 inc = -1;
766 }
767 w_lim = w - (16 - (dst_x % 16));
768 if (w_lim < 0)
769 w_lim = w;
770 else
771 w_lim = w - (w_lim % 16);
772 for (i = 0; i < h; i++) {
773 for (x = 0; x <= w_lim;
774 x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
775 if (x == w_lim) {
776 if ((s = w - w_lim) == 0)
777 break;
778 } else if (!x) {
779 s = (16 - (dst_x % 16));
780 s = MIN(s, w_lim);
781 } else {
782 s = 16;
783 }
784 cmp_bytes = s * depth;
785 if (memcmp(src_row, dst_row, cmp_bytes) == 0)
786 continue;
787 memmove(dst_row, src_row, cmp_bytes);
41b4bef6
AS
788 QTAILQ_FOREACH(vs, &vd->clients, next) {
789 if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
bc2429b9 790 set_bit(((x + dst_x) / 16), vs->dirty[y]);
41b4bef6 791 }
1fc62412
SS
792 }
793 }
794 src_row += pitch - w * depth;
795 dst_row += pitch - w * depth;
796 y += inc;
797 }
798
41b4bef6
AS
799 QTAILQ_FOREACH(vs, &vd->clients, next) {
800 if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
753b4053 801 vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
41b4bef6 802 }
753b4053
AL
803 }
804}
805
d467b679
GH
806static void vnc_mouse_set(int x, int y, int visible)
807{
808 /* can we ask the client(s) to move the pointer ??? */
809}
810
811static int vnc_cursor_define(VncState *vs)
812{
813 QEMUCursor *c = vs->vd->cursor;
814 PixelFormat pf = qemu_default_pixelformat(32);
815 int isize;
816
817 if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) {
d01f9595 818 vnc_lock_output(vs);
d467b679
GH
819 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
820 vnc_write_u8(vs, 0); /* padding */
821 vnc_write_u16(vs, 1); /* # of rects */
822 vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
823 VNC_ENCODING_RICH_CURSOR);
824 isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel;
825 vnc_write_pixels_generic(vs, &pf, c->data, isize);
826 vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
d01f9595 827 vnc_unlock_output(vs);
d467b679
GH
828 return 0;
829 }
830 return -1;
831}
832
833static void vnc_dpy_cursor_define(QEMUCursor *c)
834{
835 VncDisplay *vd = vnc_display;
836 VncState *vs;
837
838 cursor_put(vd->cursor);
7267c094 839 g_free(vd->cursor_mask);
d467b679
GH
840
841 vd->cursor = c;
842 cursor_get(vd->cursor);
843 vd->cursor_msize = cursor_get_mono_bpl(c) * c->height;
7267c094 844 vd->cursor_mask = g_malloc0(vd->cursor_msize);
d467b679
GH
845 cursor_get_mono_mask(c, 0, vd->cursor_mask);
846
847 QTAILQ_FOREACH(vs, &vd->clients, next) {
848 vnc_cursor_define(vs);
849 }
850}
851
1fc62412 852static int find_and_clear_dirty_height(struct VncState *vs,
6c71a539 853 int y, int last_x, int x, int height)
24236869
FB
854{
855 int h;
856
6c71a539 857 for (h = 1; h < (height - y); h++) {
28a76be8 858 int tmp_x;
bc2429b9 859 if (!test_bit(last_x, vs->dirty[y + h])) {
28a76be8 860 break;
bc2429b9
CC
861 }
862 for (tmp_x = last_x; tmp_x < x; tmp_x++) {
863 clear_bit(tmp_x, vs->dirty[y + h]);
864 }
24236869
FB
865 }
866
867 return h;
868}
869
bd023f95
CC
870#ifdef CONFIG_VNC_THREAD
871static int vnc_update_client_sync(VncState *vs, int has_dirty)
872{
873 int ret = vnc_update_client(vs, has_dirty);
874 vnc_jobs_join(vs);
875 return ret;
876}
877#else
878static int vnc_update_client_sync(VncState *vs, int has_dirty)
879{
880 return vnc_update_client(vs, has_dirty);
881}
882#endif
883
2430ffe4 884static int vnc_update_client(VncState *vs, int has_dirty)
24236869 885{
24236869 886 if (vs->need_update && vs->csock != -1) {
1fc62412 887 VncDisplay *vd = vs->vd;
bd023f95 888 VncJob *job;
28a76be8 889 int y;
847ce6a1 890 int width, height;
bd023f95
CC
891 int n = 0;
892
24236869 893
703bc68f 894 if (vs->output.offset && !vs->audio_cap && !vs->force_update)
c522d0e2 895 /* kernel send buffers are full -> drop frames to throttle */
2430ffe4 896 return 0;
a0ecfb73 897
703bc68f 898 if (!has_dirty && !vs->audio_cap && !vs->force_update)
2430ffe4 899 return 0;
28a76be8 900
6baebed7
AL
901 /*
902 * Send screen updates to the vnc client using the server
903 * surface and server dirty map. guest surface updates
904 * happening in parallel don't disturb us, the next pass will
905 * send them to the client.
906 */
bd023f95 907 job = vnc_job_new(vs);
28a76be8 908
847ce6a1
GH
909 width = MIN(vd->server->width, vs->client_width);
910 height = MIN(vd->server->height, vs->client_height);
911
912 for (y = 0; y < height; y++) {
28a76be8
AL
913 int x;
914 int last_x = -1;
847ce6a1 915 for (x = 0; x < width / 16; x++) {
bc2429b9 916 if (test_and_clear_bit(x, vs->dirty[y])) {
28a76be8
AL
917 if (last_x == -1) {
918 last_x = x;
919 }
28a76be8
AL
920 } else {
921 if (last_x != -1) {
6c71a539
CC
922 int h = find_and_clear_dirty_height(vs, y, last_x, x,
923 height);
bd023f95
CC
924
925 n += vnc_job_add_rect(job, last_x * 16, y,
926 (x - last_x) * 16, h);
28a76be8
AL
927 }
928 last_x = -1;
929 }
930 }
931 if (last_x != -1) {
6c71a539 932 int h = find_and_clear_dirty_height(vs, y, last_x, x, height);
bd023f95
CC
933 n += vnc_job_add_rect(job, last_x * 16, y,
934 (x - last_x) * 16, h);
28a76be8
AL
935 }
936 }
bd023f95
CC
937
938 vnc_job_push(job);
c522d0e2 939 vs->force_update = 0;
bd023f95 940 return n;
24236869 941 }
24236869 942
703bc68f 943 if (vs->csock == -1)
198a0039 944 vnc_disconnect_finish(vs);
2430ffe4
SS
945
946 return 0;
24236869
FB
947}
948
429a8ed3 949/* audio */
950static void audio_capture_notify(void *opaque, audcnotification_e cmd)
951{
952 VncState *vs = opaque;
953
954 switch (cmd) {
955 case AUD_CNOTIFY_DISABLE:
bd023f95 956 vnc_lock_output(vs);
46a183da
DB
957 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
958 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
959 vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_END);
bd023f95 960 vnc_unlock_output(vs);
429a8ed3 961 vnc_flush(vs);
962 break;
963
964 case AUD_CNOTIFY_ENABLE:
bd023f95 965 vnc_lock_output(vs);
46a183da
DB
966 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
967 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
968 vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_BEGIN);
bd023f95 969 vnc_unlock_output(vs);
429a8ed3 970 vnc_flush(vs);
971 break;
972 }
973}
974
975static void audio_capture_destroy(void *opaque)
976{
977}
978
979static void audio_capture(void *opaque, void *buf, int size)
980{
981 VncState *vs = opaque;
982
bd023f95 983 vnc_lock_output(vs);
46a183da
DB
984 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
985 vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
986 vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA);
429a8ed3 987 vnc_write_u32(vs, size);
988 vnc_write(vs, buf, size);
bd023f95 989 vnc_unlock_output(vs);
429a8ed3 990 vnc_flush(vs);
991}
992
993static void audio_add(VncState *vs)
994{
995 struct audio_capture_ops ops;
996
997 if (vs->audio_cap) {
8631b608 998 monitor_printf(default_mon, "audio already running\n");
429a8ed3 999 return;
1000 }
1001
1002 ops.notify = audio_capture_notify;
1003 ops.destroy = audio_capture_destroy;
1004 ops.capture = audio_capture;
1005
1a7dafce 1006 vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
429a8ed3 1007 if (!vs->audio_cap) {
8631b608 1008 monitor_printf(default_mon, "Failed to add audio capture\n");
429a8ed3 1009 }
1010}
1011
1012static void audio_del(VncState *vs)
1013{
1014 if (vs->audio_cap) {
1015 AUD_del_capture(vs->audio_cap, vs);
1016 vs->audio_cap = NULL;
1017 }
1018}
1019
198a0039
GH
1020static void vnc_disconnect_start(VncState *vs)
1021{
1022 if (vs->csock == -1)
1023 return;
8cf36489 1024 vnc_set_share_mode(vs, VNC_SHARE_MODE_DISCONNECTED);
198a0039
GH
1025 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
1026 closesocket(vs->csock);
1027 vs->csock = -1;
1028}
1029
1030static void vnc_disconnect_finish(VncState *vs)
1031{
7d964c9d
CC
1032 int i;
1033
bd023f95
CC
1034 vnc_jobs_join(vs); /* Wait encoding jobs */
1035
1036 vnc_lock_output(vs);
0d72f3d3
LC
1037 vnc_qmp_event(vs, QEVENT_VNC_DISCONNECTED);
1038
5d418e3b
CC
1039 buffer_free(&vs->input);
1040 buffer_free(&vs->output);
4a80dba3
LC
1041
1042 qobject_decref(vs->info);
1043
161c4f20 1044 vnc_zlib_clear(vs);
380282b0 1045 vnc_tight_clear(vs);
148954fa 1046 vnc_zrle_clear(vs);
161c4f20 1047
198a0039
GH
1048#ifdef CONFIG_VNC_TLS
1049 vnc_tls_client_cleanup(vs);
1050#endif /* CONFIG_VNC_TLS */
1051#ifdef CONFIG_VNC_SASL
1052 vnc_sasl_client_cleanup(vs);
1053#endif /* CONFIG_VNC_SASL */
1054 audio_del(vs);
7bc9318b 1055 vnc_release_modifiers(vs);
198a0039 1056
41b4bef6
AS
1057 QTAILQ_REMOVE(&vs->vd->clients, vs, next);
1058
1059 if (QTAILQ_EMPTY(&vs->vd->clients)) {
198a0039 1060 dcl->idle = 1;
41b4bef6 1061 }
198a0039 1062
37c34d9d 1063 qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
703bc68f 1064 vnc_remove_timer(vs->vd);
3a0558b5
GH
1065 if (vs->vd->lock_key_sync)
1066 qemu_remove_led_event_handler(vs->led);
bd023f95
CC
1067 vnc_unlock_output(vs);
1068
1069#ifdef CONFIG_VNC_THREAD
1070 qemu_mutex_destroy(&vs->output_mutex);
175b2a6e
CC
1071 qemu_bh_delete(vs->bh);
1072 buffer_free(&vs->jobs_buffer);
bd023f95 1073#endif
175b2a6e 1074
7d964c9d 1075 for (i = 0; i < VNC_STAT_ROWS; ++i) {
7267c094 1076 g_free(vs->lossy_rect[i]);
7d964c9d 1077 }
7267c094
AL
1078 g_free(vs->lossy_rect);
1079 g_free(vs);
198a0039 1080}
2f9606b3
AL
1081
1082int vnc_client_io_error(VncState *vs, int ret, int last_errno)
24236869
FB
1083{
1084 if (ret == 0 || ret == -1) {
ea01e5fd
AZ
1085 if (ret == -1) {
1086 switch (last_errno) {
1087 case EINTR:
1088 case EAGAIN:
1089#ifdef _WIN32
1090 case WSAEWOULDBLOCK:
1091#endif
1092 return 0;
1093 default:
1094 break;
1095 }
1096 }
24236869 1097
198a0039
GH
1098 VNC_DEBUG("Closing down client sock: ret %d, errno %d\n",
1099 ret, ret < 0 ? last_errno : 0);
1100 vnc_disconnect_start(vs);
6baebed7 1101
28a76be8 1102 return 0;
24236869
FB
1103 }
1104 return ret;
1105}
1106
5fb6c7a8
AL
1107
1108void vnc_client_error(VncState *vs)
24236869 1109{
198a0039
GH
1110 VNC_DEBUG("Closing down client sock: protocol error\n");
1111 vnc_disconnect_start(vs);
24236869
FB
1112}
1113
2f9606b3
AL
1114
1115/*
1116 * Called to write a chunk of data to the client socket. The data may
1117 * be the raw data, or may have already been encoded by SASL.
1118 * The data will be written either straight onto the socket, or
1119 * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1120 *
1121 * NB, it is theoretically possible to have 2 layers of encryption,
1122 * both SASL, and this TLS layer. It is highly unlikely in practice
1123 * though, since SASL encryption will typically be a no-op if TLS
1124 * is active
1125 *
1126 * Returns the number of bytes written, which may be less than
1127 * the requested 'datalen' if the socket would block. Returns
1128 * -1 on error, and disconnects the client socket.
1129 */
1130long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
24236869 1131{
ceb5caaf 1132 long ret;
eb38c52c 1133#ifdef CONFIG_VNC_TLS
5fb6c7a8 1134 if (vs->tls.session) {
28a76be8
AL
1135 ret = gnutls_write(vs->tls.session, data, datalen);
1136 if (ret < 0) {
1137 if (ret == GNUTLS_E_AGAIN)
1138 errno = EAGAIN;
1139 else
1140 errno = EIO;
1141 ret = -1;
1142 }
8d5d2d4c
TS
1143 } else
1144#endif /* CONFIG_VNC_TLS */
70503264 1145 ret = send(vs->csock, (const void *)data, datalen, 0);
23decc87 1146 VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret);
2f9606b3
AL
1147 return vnc_client_io_error(vs, ret, socket_error());
1148}
1149
1150
1151/*
1152 * Called to write buffered data to the client socket, when not
1153 * using any SASL SSF encryption layers. Will write as much data
1154 * as possible without blocking. If all buffered data is written,
1155 * will switch the FD poll() handler back to read monitoring.
1156 *
1157 * Returns the number of bytes written, which may be less than
1158 * the buffered output data if the socket would block. Returns
1159 * -1 on error, and disconnects the client socket.
1160 */
1161static long vnc_client_write_plain(VncState *vs)
1162{
1163 long ret;
1164
1165#ifdef CONFIG_VNC_SASL
23decc87 1166 VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n",
2f9606b3
AL
1167 vs->output.buffer, vs->output.capacity, vs->output.offset,
1168 vs->sasl.waitWriteSSF);
1169
1170 if (vs->sasl.conn &&
1171 vs->sasl.runSSF &&
1172 vs->sasl.waitWriteSSF) {
1173 ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF);
1174 if (ret)
1175 vs->sasl.waitWriteSSF -= ret;
1176 } else
1177#endif /* CONFIG_VNC_SASL */
1178 ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset);
24236869 1179 if (!ret)
2f9606b3 1180 return 0;
24236869
FB
1181
1182 memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
1183 vs->output.offset -= ret;
1184
1185 if (vs->output.offset == 0) {
28a76be8 1186 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
24236869 1187 }
2f9606b3
AL
1188
1189 return ret;
1190}
1191
1192
1193/*
1194 * First function called whenever there is data to be written to
1195 * the client socket. Will delegate actual work according to whether
1196 * SASL SSF layers are enabled (thus requiring encryption calls)
1197 */
bd023f95 1198static void vnc_client_write_locked(void *opaque)
2f9606b3 1199{
2f9606b3
AL
1200 VncState *vs = opaque;
1201
1202#ifdef CONFIG_VNC_SASL
1203 if (vs->sasl.conn &&
1204 vs->sasl.runSSF &&
9678d950
BS
1205 !vs->sasl.waitWriteSSF) {
1206 vnc_client_write_sasl(vs);
1207 } else
2f9606b3 1208#endif /* CONFIG_VNC_SASL */
9678d950 1209 vnc_client_write_plain(vs);
24236869
FB
1210}
1211
bd023f95
CC
1212void vnc_client_write(void *opaque)
1213{
1214 VncState *vs = opaque;
1215
1216 vnc_lock_output(vs);
1217 if (vs->output.offset) {
1218 vnc_client_write_locked(opaque);
ac71103d 1219 } else if (vs->csock != -1) {
bd023f95
CC
1220 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
1221 }
1222 vnc_unlock_output(vs);
1223}
1224
5fb6c7a8 1225void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
24236869
FB
1226{
1227 vs->read_handler = func;
1228 vs->read_handler_expect = expecting;
1229}
1230
2f9606b3
AL
1231
1232/*
1233 * Called to read a chunk of data from the client socket. The data may
1234 * be the raw data, or may need to be further decoded by SASL.
1235 * The data will be read either straight from to the socket, or
1236 * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1237 *
1238 * NB, it is theoretically possible to have 2 layers of encryption,
1239 * both SASL, and this TLS layer. It is highly unlikely in practice
1240 * though, since SASL encryption will typically be a no-op if TLS
1241 * is active
1242 *
1243 * Returns the number of bytes read, which may be less than
1244 * the requested 'datalen' if the socket would block. Returns
1245 * -1 on error, and disconnects the client socket.
1246 */
1247long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
24236869 1248{
ceb5caaf 1249 long ret;
eb38c52c 1250#ifdef CONFIG_VNC_TLS
5fb6c7a8 1251 if (vs->tls.session) {
28a76be8
AL
1252 ret = gnutls_read(vs->tls.session, data, datalen);
1253 if (ret < 0) {
1254 if (ret == GNUTLS_E_AGAIN)
1255 errno = EAGAIN;
1256 else
1257 errno = EIO;
1258 ret = -1;
1259 }
8d5d2d4c
TS
1260 } else
1261#endif /* CONFIG_VNC_TLS */
00aa0040 1262 ret = qemu_recv(vs->csock, data, datalen, 0);
23decc87 1263 VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret);
2f9606b3
AL
1264 return vnc_client_io_error(vs, ret, socket_error());
1265}
24236869 1266
2f9606b3
AL
1267
1268/*
1269 * Called to read data from the client socket to the input buffer,
1270 * when not using any SASL SSF encryption layers. Will read as much
1271 * data as possible without blocking.
1272 *
1273 * Returns the number of bytes read. Returns -1 on error, and
1274 * disconnects the client socket.
1275 */
1276static long vnc_client_read_plain(VncState *vs)
1277{
1278 int ret;
23decc87 1279 VNC_DEBUG("Read plain %p size %zd offset %zd\n",
2f9606b3
AL
1280 vs->input.buffer, vs->input.capacity, vs->input.offset);
1281 buffer_reserve(&vs->input, 4096);
1282 ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096);
1283 if (!ret)
1284 return 0;
24236869 1285 vs->input.offset += ret;
2f9606b3
AL
1286 return ret;
1287}
1288
175b2a6e
CC
1289#ifdef CONFIG_VNC_THREAD
1290static void vnc_jobs_bh(void *opaque)
1291{
1292 VncState *vs = opaque;
1293
1294 vnc_jobs_consume_buffer(vs);
1295}
1296#endif
2f9606b3
AL
1297
1298/*
1299 * First function called whenever there is more data to be read from
1300 * the client socket. Will delegate actual work according to whether
1301 * SASL SSF layers are enabled (thus requiring decryption calls)
1302 */
1303void vnc_client_read(void *opaque)
1304{
1305 VncState *vs = opaque;
1306 long ret;
1307
1308#ifdef CONFIG_VNC_SASL
1309 if (vs->sasl.conn && vs->sasl.runSSF)
1310 ret = vnc_client_read_sasl(vs);
1311 else
1312#endif /* CONFIG_VNC_SASL */
1313 ret = vnc_client_read_plain(vs);
198a0039
GH
1314 if (!ret) {
1315 if (vs->csock == -1)
1316 vnc_disconnect_finish(vs);
28a76be8 1317 return;
198a0039 1318 }
24236869
FB
1319
1320 while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
28a76be8
AL
1321 size_t len = vs->read_handler_expect;
1322 int ret;
1323
1324 ret = vs->read_handler(vs, vs->input.buffer, len);
198a0039
GH
1325 if (vs->csock == -1) {
1326 vnc_disconnect_finish(vs);
28a76be8 1327 return;
198a0039 1328 }
28a76be8
AL
1329
1330 if (!ret) {
1331 memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
1332 vs->input.offset -= len;
1333 } else {
1334 vs->read_handler_expect = ret;
1335 }
24236869
FB
1336 }
1337}
1338
5fb6c7a8 1339void vnc_write(VncState *vs, const void *data, size_t len)
24236869
FB
1340{
1341 buffer_reserve(&vs->output, len);
1342
198a0039 1343 if (vs->csock != -1 && buffer_empty(&vs->output)) {
28a76be8 1344 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
24236869
FB
1345 }
1346
1347 buffer_append(&vs->output, data, len);
1348}
1349
5fb6c7a8 1350void vnc_write_s32(VncState *vs, int32_t value)
24236869
FB
1351{
1352 vnc_write_u32(vs, *(uint32_t *)&value);
1353}
1354
5fb6c7a8 1355void vnc_write_u32(VncState *vs, uint32_t value)
24236869
FB
1356{
1357 uint8_t buf[4];
1358
1359 buf[0] = (value >> 24) & 0xFF;
1360 buf[1] = (value >> 16) & 0xFF;
1361 buf[2] = (value >> 8) & 0xFF;
1362 buf[3] = value & 0xFF;
1363
1364 vnc_write(vs, buf, 4);
1365}
1366
5fb6c7a8 1367void vnc_write_u16(VncState *vs, uint16_t value)
24236869 1368{
64f5a135 1369 uint8_t buf[2];
24236869
FB
1370
1371 buf[0] = (value >> 8) & 0xFF;
1372 buf[1] = value & 0xFF;
1373
1374 vnc_write(vs, buf, 2);
1375}
1376
5fb6c7a8 1377void vnc_write_u8(VncState *vs, uint8_t value)
24236869
FB
1378{
1379 vnc_write(vs, (char *)&value, 1);
1380}
1381
5fb6c7a8 1382void vnc_flush(VncState *vs)
24236869 1383{
bd023f95
CC
1384 vnc_lock_output(vs);
1385 if (vs->csock != -1 && vs->output.offset) {
1386 vnc_client_write_locked(vs);
1387 }
1388 vnc_unlock_output(vs);
24236869
FB
1389}
1390
5fb6c7a8 1391uint8_t read_u8(uint8_t *data, size_t offset)
24236869
FB
1392{
1393 return data[offset];
1394}
1395
5fb6c7a8 1396uint16_t read_u16(uint8_t *data, size_t offset)
24236869
FB
1397{
1398 return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
1399}
1400
5fb6c7a8 1401int32_t read_s32(uint8_t *data, size_t offset)
24236869
FB
1402{
1403 return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
28a76be8 1404 (data[offset + 2] << 8) | data[offset + 3]);
24236869
FB
1405}
1406
5fb6c7a8 1407uint32_t read_u32(uint8_t *data, size_t offset)
24236869
FB
1408{
1409 return ((data[offset] << 24) | (data[offset + 1] << 16) |
28a76be8 1410 (data[offset + 2] << 8) | data[offset + 3]);
24236869
FB
1411}
1412
60fe76f3 1413static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
24236869
FB
1414{
1415}
1416
9e8dd451 1417static void check_pointer_type_change(Notifier *notifier, void *data)
564c337e 1418{
37c34d9d
AL
1419 VncState *vs = container_of(notifier, VncState, mouse_mode_notifier);
1420 int absolute = kbd_mouse_is_absolute();
1421
29fa4ed9 1422 if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) {
bd023f95 1423 vnc_lock_output(vs);
46a183da 1424 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
28a76be8
AL
1425 vnc_write_u8(vs, 0);
1426 vnc_write_u16(vs, 1);
1427 vnc_framebuffer_update(vs, absolute, 0,
1428 ds_get_width(vs->ds), ds_get_height(vs->ds),
29fa4ed9 1429 VNC_ENCODING_POINTER_TYPE_CHANGE);
bd023f95 1430 vnc_unlock_output(vs);
28a76be8 1431 vnc_flush(vs);
564c337e
FB
1432 }
1433 vs->absolute = absolute;
1434}
1435
24236869
FB
1436static void pointer_event(VncState *vs, int button_mask, int x, int y)
1437{
1438 int buttons = 0;
1439 int dz = 0;
1440
1441 if (button_mask & 0x01)
28a76be8 1442 buttons |= MOUSE_EVENT_LBUTTON;
24236869 1443 if (button_mask & 0x02)
28a76be8 1444 buttons |= MOUSE_EVENT_MBUTTON;
24236869 1445 if (button_mask & 0x04)
28a76be8 1446 buttons |= MOUSE_EVENT_RBUTTON;
24236869 1447 if (button_mask & 0x08)
28a76be8 1448 dz = -1;
24236869 1449 if (button_mask & 0x10)
28a76be8 1450 dz = 1;
564c337e
FB
1451
1452 if (vs->absolute) {
cc39a92c
CW
1453 kbd_mouse_event(ds_get_width(vs->ds) > 1 ?
1454 x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000,
1455 ds_get_height(vs->ds) > 1 ?
1456 y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000,
28a76be8 1457 dz, buttons);
29fa4ed9 1458 } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
28a76be8
AL
1459 x -= 0x7FFF;
1460 y -= 0x7FFF;
24236869 1461
28a76be8 1462 kbd_mouse_event(x, y, dz, buttons);
564c337e 1463 } else {
28a76be8
AL
1464 if (vs->last_x != -1)
1465 kbd_mouse_event(x - vs->last_x,
1466 y - vs->last_y,
1467 dz, buttons);
1468 vs->last_x = x;
1469 vs->last_y = y;
24236869
FB
1470 }
1471}
1472
64f5a135
FB
1473static void reset_keys(VncState *vs)
1474{
1475 int i;
1476 for(i = 0; i < 256; i++) {
1477 if (vs->modifiers_state[i]) {
44bb61c8
ST
1478 if (i & SCANCODE_GREY)
1479 kbd_put_keycode(SCANCODE_EMUL0);
1480 kbd_put_keycode(i | SCANCODE_UP);
64f5a135
FB
1481 vs->modifiers_state[i] = 0;
1482 }
1483 }
1484}
1485
a528b80c
AZ
1486static void press_key(VncState *vs, int keysym)
1487{
44bb61c8
ST
1488 int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
1489 if (keycode & SCANCODE_GREY)
1490 kbd_put_keycode(SCANCODE_EMUL0);
1491 kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
1492 if (keycode & SCANCODE_GREY)
1493 kbd_put_keycode(SCANCODE_EMUL0);
1494 kbd_put_keycode(keycode | SCANCODE_UP);
a528b80c
AZ
1495}
1496
7ffb82ca
GH
1497static void kbd_leds(void *opaque, int ledstate)
1498{
1499 VncState *vs = opaque;
1500 int caps, num;
1501
1502 caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0;
1503 num = ledstate & QEMU_NUM_LOCK_LED ? 1 : 0;
1504
1505 if (vs->modifiers_state[0x3a] != caps) {
1506 vs->modifiers_state[0x3a] = caps;
1507 }
1508 if (vs->modifiers_state[0x45] != num) {
1509 vs->modifiers_state[0x45] = num;
1510 }
1511}
1512
9ca313aa 1513static void do_key_event(VncState *vs, int down, int keycode, int sym)
24236869 1514{
64f5a135
FB
1515 /* QEMU console switch */
1516 switch(keycode) {
1517 case 0x2a: /* Left Shift */
1518 case 0x36: /* Right Shift */
1519 case 0x1d: /* Left CTRL */
1520 case 0x9d: /* Right CTRL */
1521 case 0x38: /* Left ALT */
1522 case 0xb8: /* Right ALT */
1523 if (down)
1524 vs->modifiers_state[keycode] = 1;
1525 else
1526 vs->modifiers_state[keycode] = 0;
1527 break;
5fafdf24 1528 case 0x02 ... 0x0a: /* '1' to '9' keys */
64f5a135
FB
1529 if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1530 /* Reset the modifiers sent to the current console */
1531 reset_keys(vs);
1532 console_select(keycode - 0x02);
1533 return;
1534 }
1535 break;
28a76be8
AL
1536 case 0x3a: /* CapsLock */
1537 case 0x45: /* NumLock */
7ffb82ca 1538 if (down)
a528b80c
AZ
1539 vs->modifiers_state[keycode] ^= 1;
1540 break;
1541 }
1542
9892088b 1543 if (down && vs->vd->lock_key_sync &&
3a0558b5 1544 keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
a528b80c
AZ
1545 /* If the numlock state needs to change then simulate an additional
1546 keypress before sending this one. This will happen if the user
1547 toggles numlock away from the VNC window.
1548 */
753b4053 1549 if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
a528b80c
AZ
1550 if (!vs->modifiers_state[0x45]) {
1551 vs->modifiers_state[0x45] = 1;
1552 press_key(vs, 0xff7f);
1553 }
1554 } else {
1555 if (vs->modifiers_state[0x45]) {
1556 vs->modifiers_state[0x45] = 0;
1557 press_key(vs, 0xff7f);
1558 }
1559 }
64f5a135 1560 }
24236869 1561
9892088b 1562 if (down && vs->vd->lock_key_sync &&
3a0558b5 1563 ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
6b132502
GH
1564 /* If the capslock state needs to change then simulate an additional
1565 keypress before sending this one. This will happen if the user
1566 toggles capslock away from the VNC window.
1567 */
1568 int uppercase = !!(sym >= 'A' && sym <= 'Z');
1569 int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
1570 int capslock = !!(vs->modifiers_state[0x3a]);
1571 if (capslock) {
1572 if (uppercase == shift) {
1573 vs->modifiers_state[0x3a] = 0;
1574 press_key(vs, 0xffe5);
1575 }
1576 } else {
1577 if (uppercase != shift) {
1578 vs->modifiers_state[0x3a] = 1;
1579 press_key(vs, 0xffe5);
1580 }
1581 }
1582 }
1583
64f5a135 1584 if (is_graphic_console()) {
44bb61c8
ST
1585 if (keycode & SCANCODE_GREY)
1586 kbd_put_keycode(SCANCODE_EMUL0);
64f5a135 1587 if (down)
44bb61c8 1588 kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
64f5a135 1589 else
44bb61c8 1590 kbd_put_keycode(keycode | SCANCODE_UP);
64f5a135 1591 } else {
e26437c2
GH
1592 bool numlock = vs->modifiers_state[0x45];
1593 bool control = (vs->modifiers_state[0x1d] ||
1594 vs->modifiers_state[0x9d]);
64f5a135
FB
1595 /* QEMU console emulation */
1596 if (down) {
1597 switch (keycode) {
1598 case 0x2a: /* Left Shift */
1599 case 0x36: /* Right Shift */
1600 case 0x1d: /* Left CTRL */
1601 case 0x9d: /* Right CTRL */
1602 case 0x38: /* Left ALT */
1603 case 0xb8: /* Right ALT */
1604 break;
1605 case 0xc8:
1606 kbd_put_keysym(QEMU_KEY_UP);
1607 break;
1608 case 0xd0:
1609 kbd_put_keysym(QEMU_KEY_DOWN);
1610 break;
1611 case 0xcb:
1612 kbd_put_keysym(QEMU_KEY_LEFT);
1613 break;
1614 case 0xcd:
1615 kbd_put_keysym(QEMU_KEY_RIGHT);
1616 break;
1617 case 0xd3:
1618 kbd_put_keysym(QEMU_KEY_DELETE);
1619 break;
1620 case 0xc7:
1621 kbd_put_keysym(QEMU_KEY_HOME);
1622 break;
1623 case 0xcf:
1624 kbd_put_keysym(QEMU_KEY_END);
1625 break;
1626 case 0xc9:
1627 kbd_put_keysym(QEMU_KEY_PAGEUP);
1628 break;
1629 case 0xd1:
1630 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1631 break;
bb0a18e1
GH
1632
1633 case 0x47:
1634 kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
1635 break;
1636 case 0x48:
1637 kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
1638 break;
1639 case 0x49:
1640 kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
1641 break;
1642 case 0x4b:
1643 kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
1644 break;
1645 case 0x4c:
1646 kbd_put_keysym('5');
1647 break;
1648 case 0x4d:
1649 kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
1650 break;
1651 case 0x4f:
1652 kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
1653 break;
1654 case 0x50:
1655 kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
1656 break;
1657 case 0x51:
1658 kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
1659 break;
1660 case 0x52:
1661 kbd_put_keysym('0');
1662 break;
1663 case 0x53:
1664 kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
1665 break;
1666
1667 case 0xb5:
1668 kbd_put_keysym('/');
1669 break;
1670 case 0x37:
1671 kbd_put_keysym('*');
1672 break;
1673 case 0x4a:
1674 kbd_put_keysym('-');
1675 break;
1676 case 0x4e:
1677 kbd_put_keysym('+');
1678 break;
1679 case 0x9c:
1680 kbd_put_keysym('\n');
1681 break;
1682
64f5a135 1683 default:
e26437c2
GH
1684 if (control) {
1685 kbd_put_keysym(sym & 0x1f);
1686 } else {
1687 kbd_put_keysym(sym);
1688 }
64f5a135
FB
1689 break;
1690 }
1691 }
1692 }
24236869
FB
1693}
1694
7bc9318b
GH
1695static void vnc_release_modifiers(VncState *vs)
1696{
1697 static const int keycodes[] = {
1698 /* shift, control, alt keys, both left & right */
1699 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
1700 };
1701 int i, keycode;
1702
1703 if (!is_graphic_console()) {
1704 return;
1705 }
1706 for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
1707 keycode = keycodes[i];
1708 if (!vs->modifiers_state[keycode]) {
1709 continue;
1710 }
1711 if (keycode & SCANCODE_GREY) {
1712 kbd_put_keycode(SCANCODE_EMUL0);
1713 }
1714 kbd_put_keycode(keycode | SCANCODE_UP);
1715 }
1716}
1717
bdbd7676
FB
1718static void key_event(VncState *vs, int down, uint32_t sym)
1719{
9ca313aa 1720 int keycode;
4a93fe17 1721 int lsym = sym;
9ca313aa 1722
4a93fe17
GH
1723 if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) {
1724 lsym = lsym - 'A' + 'a';
1725 }
9ca313aa 1726
44bb61c8 1727 keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK;
9ca313aa
AL
1728 do_key_event(vs, down, keycode, sym);
1729}
1730
1731static void ext_key_event(VncState *vs, int down,
1732 uint32_t sym, uint16_t keycode)
1733{
1734 /* if the user specifies a keyboard layout, always use it */
1735 if (keyboard_layout)
1736 key_event(vs, down, sym);
1737 else
1738 do_key_event(vs, down, keycode, sym);
bdbd7676
FB
1739}
1740
24236869 1741static void framebuffer_update_request(VncState *vs, int incremental,
28a76be8
AL
1742 int x_position, int y_position,
1743 int w, int h)
24236869 1744{
6ed391bf
WC
1745 int i;
1746 const size_t width = ds_get_width(vs->ds) / 16;
1747
0e1f5a0c
AL
1748 if (y_position > ds_get_height(vs->ds))
1749 y_position = ds_get_height(vs->ds);
0e1f5a0c
AL
1750 if (y_position + h >= ds_get_height(vs->ds))
1751 h = ds_get_height(vs->ds) - y_position;
cf2d385c 1752
24236869
FB
1753 vs->need_update = 1;
1754 if (!incremental) {
24cf0a6e 1755 vs->force_update = 1;
28a76be8 1756 for (i = 0; i < h; i++) {
6ed391bf
WC
1757 bitmap_set(vs->dirty[y_position + i], 0, width);
1758 bitmap_clear(vs->dirty[y_position + i], width,
a0843a68 1759 VNC_DIRTY_BITS - width);
28a76be8 1760 }
24236869
FB
1761 }
1762}
1763
9ca313aa
AL
1764static void send_ext_key_event_ack(VncState *vs)
1765{
bd023f95 1766 vnc_lock_output(vs);
46a183da 1767 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
9ca313aa
AL
1768 vnc_write_u8(vs, 0);
1769 vnc_write_u16(vs, 1);
29fa4ed9
AL
1770 vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1771 VNC_ENCODING_EXT_KEY_EVENT);
bd023f95 1772 vnc_unlock_output(vs);
9ca313aa
AL
1773 vnc_flush(vs);
1774}
1775
429a8ed3 1776static void send_ext_audio_ack(VncState *vs)
1777{
bd023f95 1778 vnc_lock_output(vs);
46a183da 1779 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
429a8ed3 1780 vnc_write_u8(vs, 0);
1781 vnc_write_u16(vs, 1);
29fa4ed9
AL
1782 vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1783 VNC_ENCODING_AUDIO);
bd023f95 1784 vnc_unlock_output(vs);
429a8ed3 1785 vnc_flush(vs);
1786}
1787
24236869
FB
1788static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1789{
1790 int i;
29fa4ed9 1791 unsigned int enc = 0;
24236869 1792
29fa4ed9 1793 vs->features = 0;
a9f20d31 1794 vs->vnc_encoding = 0;
d1af0e05
CC
1795 vs->tight.compression = 9;
1796 vs->tight.quality = -1; /* Lossless by default */
564c337e 1797 vs->absolute = -1;
24236869 1798
8a0f0d0c
CC
1799 /*
1800 * Start from the end because the encodings are sent in order of preference.
e5bed759 1801 * This way the preferred encoding (first encoding defined in the array)
8a0f0d0c
CC
1802 * will be set at the end of the loop.
1803 */
24236869 1804 for (i = n_encodings - 1; i >= 0; i--) {
29fa4ed9
AL
1805 enc = encodings[i];
1806 switch (enc) {
1807 case VNC_ENCODING_RAW:
a9f20d31 1808 vs->vnc_encoding = enc;
29fa4ed9
AL
1809 break;
1810 case VNC_ENCODING_COPYRECT:
753b4053 1811 vs->features |= VNC_FEATURE_COPYRECT_MASK;
29fa4ed9
AL
1812 break;
1813 case VNC_ENCODING_HEXTILE:
1814 vs->features |= VNC_FEATURE_HEXTILE_MASK;
a9f20d31 1815 vs->vnc_encoding = enc;
29fa4ed9 1816 break;
380282b0
CC
1817 case VNC_ENCODING_TIGHT:
1818 vs->features |= VNC_FEATURE_TIGHT_MASK;
1819 vs->vnc_encoding = enc;
1820 break;
efe556ad
CC
1821 case VNC_ENCODING_TIGHT_PNG:
1822 vs->features |= VNC_FEATURE_TIGHT_PNG_MASK;
1823 vs->vnc_encoding = enc;
1824 break;
059cef40
AL
1825 case VNC_ENCODING_ZLIB:
1826 vs->features |= VNC_FEATURE_ZLIB_MASK;
a9f20d31 1827 vs->vnc_encoding = enc;
059cef40 1828 break;
148954fa
CC
1829 case VNC_ENCODING_ZRLE:
1830 vs->features |= VNC_FEATURE_ZRLE_MASK;
1831 vs->vnc_encoding = enc;
1832 break;
1833 case VNC_ENCODING_ZYWRLE:
1834 vs->features |= VNC_FEATURE_ZYWRLE_MASK;
1835 vs->vnc_encoding = enc;
1836 break;
29fa4ed9
AL
1837 case VNC_ENCODING_DESKTOPRESIZE:
1838 vs->features |= VNC_FEATURE_RESIZE_MASK;
1839 break;
1840 case VNC_ENCODING_POINTER_TYPE_CHANGE:
1841 vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
1842 break;
d467b679
GH
1843 case VNC_ENCODING_RICH_CURSOR:
1844 vs->features |= VNC_FEATURE_RICH_CURSOR_MASK;
1845 break;
29fa4ed9 1846 case VNC_ENCODING_EXT_KEY_EVENT:
9ca313aa
AL
1847 send_ext_key_event_ack(vs);
1848 break;
29fa4ed9 1849 case VNC_ENCODING_AUDIO:
429a8ed3 1850 send_ext_audio_ack(vs);
1851 break;
29fa4ed9
AL
1852 case VNC_ENCODING_WMVi:
1853 vs->features |= VNC_FEATURE_WMVI_MASK;
ca4cca4d 1854 break;
fb437313 1855 case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
d1af0e05 1856 vs->tight.compression = (enc & 0x0F);
fb437313
AL
1857 break;
1858 case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
b31f519e
CC
1859 if (vs->vd->lossy) {
1860 vs->tight.quality = (enc & 0x0F);
1861 }
fb437313 1862 break;
29fa4ed9
AL
1863 default:
1864 VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
1865 break;
1866 }
24236869 1867 }
6356e472 1868 vnc_desktop_resize(vs);
9e8dd451 1869 check_pointer_type_change(&vs->mouse_mode_notifier, NULL);
24236869
FB
1870}
1871
6cec5487
AL
1872static void set_pixel_conversion(VncState *vs)
1873{
1874 if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
1875 (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
1876 !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
1877 vs->write_pixels = vnc_write_pixels_copy;
70a4568f 1878 vnc_hextile_set_pixel_conversion(vs, 0);
6cec5487
AL
1879 } else {
1880 vs->write_pixels = vnc_write_pixels_generic;
70a4568f 1881 vnc_hextile_set_pixel_conversion(vs, 1);
6cec5487
AL
1882 }
1883}
1884
24236869 1885static void set_pixel_format(VncState *vs,
28a76be8
AL
1886 int bits_per_pixel, int depth,
1887 int big_endian_flag, int true_color_flag,
1888 int red_max, int green_max, int blue_max,
1889 int red_shift, int green_shift, int blue_shift)
24236869 1890{
3512779a 1891 if (!true_color_flag) {
28a76be8 1892 vnc_client_error(vs);
3512779a
FB
1893 return;
1894 }
24236869 1895
1fc62412 1896 vs->clientds = *(vs->vd->guest.ds);
6cec5487 1897 vs->clientds.pf.rmax = red_max;
bc2429b9 1898 vs->clientds.pf.rbits = hweight_long(red_max);
6cec5487
AL
1899 vs->clientds.pf.rshift = red_shift;
1900 vs->clientds.pf.rmask = red_max << red_shift;
1901 vs->clientds.pf.gmax = green_max;
bc2429b9 1902 vs->clientds.pf.gbits = hweight_long(green_max);
6cec5487
AL
1903 vs->clientds.pf.gshift = green_shift;
1904 vs->clientds.pf.gmask = green_max << green_shift;
1905 vs->clientds.pf.bmax = blue_max;
bc2429b9 1906 vs->clientds.pf.bbits = hweight_long(blue_max);
6cec5487
AL
1907 vs->clientds.pf.bshift = blue_shift;
1908 vs->clientds.pf.bmask = blue_max << blue_shift;
1909 vs->clientds.pf.bits_per_pixel = bits_per_pixel;
1910 vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8;
1911 vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
1912 vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00;
1913
1914 set_pixel_conversion(vs);
24236869
FB
1915
1916 vga_hw_invalidate();
1917 vga_hw_update();
1918}
1919
ca4cca4d
AL
1920static void pixel_format_message (VncState *vs) {
1921 char pad[3] = { 0, 0, 0 };
1922
6cec5487
AL
1923 vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */
1924 vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */
ca4cca4d 1925
e2542fe2 1926#ifdef HOST_WORDS_BIGENDIAN
ca4cca4d
AL
1927 vnc_write_u8(vs, 1); /* big-endian-flag */
1928#else
1929 vnc_write_u8(vs, 0); /* big-endian-flag */
1930#endif
1931 vnc_write_u8(vs, 1); /* true-color-flag */
6cec5487
AL
1932 vnc_write_u16(vs, vs->ds->surface->pf.rmax); /* red-max */
1933 vnc_write_u16(vs, vs->ds->surface->pf.gmax); /* green-max */
1934 vnc_write_u16(vs, vs->ds->surface->pf.bmax); /* blue-max */
1935 vnc_write_u8(vs, vs->ds->surface->pf.rshift); /* red-shift */
1936 vnc_write_u8(vs, vs->ds->surface->pf.gshift); /* green-shift */
1937 vnc_write_u8(vs, vs->ds->surface->pf.bshift); /* blue-shift */
70a4568f
CC
1938
1939 vnc_hextile_set_pixel_conversion(vs, 0);
1940
6cec5487 1941 vs->clientds = *(vs->ds->surface);
3cded540 1942 vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG;
ca4cca4d
AL
1943 vs->write_pixels = vnc_write_pixels_copy;
1944
1945 vnc_write(vs, pad, 3); /* padding */
1946}
1947
7d957bd8
AL
1948static void vnc_dpy_setdata(DisplayState *ds)
1949{
1d3323de
GH
1950 VncDisplay *vd = ds->opaque;
1951
1952 *(vd->guest.ds) = *(ds->surface);
1953 vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
7d957bd8
AL
1954}
1955
753b4053 1956static void vnc_colordepth(VncState *vs)
7eac3a87 1957{
753b4053 1958 if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
ca4cca4d 1959 /* Sending a WMVi message to notify the client*/
bd023f95 1960 vnc_lock_output(vs);
46a183da 1961 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
ca4cca4d
AL
1962 vnc_write_u8(vs, 0);
1963 vnc_write_u16(vs, 1); /* number of rects */
753b4053
AL
1964 vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
1965 ds_get_height(vs->ds), VNC_ENCODING_WMVi);
ca4cca4d 1966 pixel_format_message(vs);
bd023f95 1967 vnc_unlock_output(vs);
ca4cca4d 1968 vnc_flush(vs);
7eac3a87 1969 } else {
6cec5487 1970 set_pixel_conversion(vs);
7eac3a87
AL
1971 }
1972}
1973
60fe76f3 1974static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
24236869
FB
1975{
1976 int i;
1977 uint16_t limit;
2430ffe4
SS
1978 VncDisplay *vd = vs->vd;
1979
1980 if (data[0] > 3) {
1981 vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
7bd427d8
PB
1982 if (!qemu_timer_expired(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval))
1983 qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval);
2430ffe4 1984 }
24236869
FB
1985
1986 switch (data[0]) {
46a183da 1987 case VNC_MSG_CLIENT_SET_PIXEL_FORMAT:
28a76be8
AL
1988 if (len == 1)
1989 return 20;
1990
1991 set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1992 read_u8(data, 6), read_u8(data, 7),
1993 read_u16(data, 8), read_u16(data, 10),
1994 read_u16(data, 12), read_u8(data, 14),
1995 read_u8(data, 15), read_u8(data, 16));
1996 break;
46a183da 1997 case VNC_MSG_CLIENT_SET_ENCODINGS:
28a76be8
AL
1998 if (len == 1)
1999 return 4;
24236869 2000
28a76be8 2001 if (len == 4) {
69dd5c9f
AL
2002 limit = read_u16(data, 2);
2003 if (limit > 0)
2004 return 4 + (limit * 4);
2005 } else
2006 limit = read_u16(data, 2);
24236869 2007
28a76be8
AL
2008 for (i = 0; i < limit; i++) {
2009 int32_t val = read_s32(data, 4 + (i * 4));
2010 memcpy(data + 4 + (i * 4), &val, sizeof(val));
2011 }
24236869 2012
28a76be8
AL
2013 set_encodings(vs, (int32_t *)(data + 4), limit);
2014 break;
46a183da 2015 case VNC_MSG_CLIENT_FRAMEBUFFER_UPDATE_REQUEST:
28a76be8
AL
2016 if (len == 1)
2017 return 10;
24236869 2018
28a76be8
AL
2019 framebuffer_update_request(vs,
2020 read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
2021 read_u16(data, 6), read_u16(data, 8));
2022 break;
46a183da 2023 case VNC_MSG_CLIENT_KEY_EVENT:
28a76be8
AL
2024 if (len == 1)
2025 return 8;
24236869 2026
28a76be8
AL
2027 key_event(vs, read_u8(data, 1), read_u32(data, 4));
2028 break;
46a183da 2029 case VNC_MSG_CLIENT_POINTER_EVENT:
28a76be8
AL
2030 if (len == 1)
2031 return 6;
24236869 2032
28a76be8
AL
2033 pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
2034 break;
46a183da 2035 case VNC_MSG_CLIENT_CUT_TEXT:
28a76be8
AL
2036 if (len == 1)
2037 return 8;
24236869 2038
28a76be8 2039 if (len == 8) {
baa7666c
TS
2040 uint32_t dlen = read_u32(data, 4);
2041 if (dlen > 0)
2042 return 8 + dlen;
2043 }
24236869 2044
28a76be8
AL
2045 client_cut_text(vs, read_u32(data, 4), data + 8);
2046 break;
46a183da 2047 case VNC_MSG_CLIENT_QEMU:
9ca313aa
AL
2048 if (len == 1)
2049 return 2;
2050
2051 switch (read_u8(data, 1)) {
46a183da 2052 case VNC_MSG_CLIENT_QEMU_EXT_KEY_EVENT:
9ca313aa
AL
2053 if (len == 2)
2054 return 12;
2055
2056 ext_key_event(vs, read_u16(data, 2),
2057 read_u32(data, 4), read_u32(data, 8));
2058 break;
46a183da 2059 case VNC_MSG_CLIENT_QEMU_AUDIO:
429a8ed3 2060 if (len == 2)
2061 return 4;
2062
2063 switch (read_u16 (data, 2)) {
46a183da 2064 case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE:
429a8ed3 2065 audio_add(vs);
2066 break;
46a183da 2067 case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE:
429a8ed3 2068 audio_del(vs);
2069 break;
46a183da 2070 case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT:
429a8ed3 2071 if (len == 4)
2072 return 10;
2073 switch (read_u8(data, 4)) {
2074 case 0: vs->as.fmt = AUD_FMT_U8; break;
2075 case 1: vs->as.fmt = AUD_FMT_S8; break;
2076 case 2: vs->as.fmt = AUD_FMT_U16; break;
2077 case 3: vs->as.fmt = AUD_FMT_S16; break;
2078 case 4: vs->as.fmt = AUD_FMT_U32; break;
2079 case 5: vs->as.fmt = AUD_FMT_S32; break;
2080 default:
2081 printf("Invalid audio format %d\n", read_u8(data, 4));
2082 vnc_client_error(vs);
2083 break;
2084 }
2085 vs->as.nchannels = read_u8(data, 5);
2086 if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
2087 printf("Invalid audio channel coount %d\n",
2088 read_u8(data, 5));
2089 vnc_client_error(vs);
2090 break;
2091 }
2092 vs->as.freq = read_u32(data, 6);
2093 break;
2094 default:
2095 printf ("Invalid audio message %d\n", read_u8(data, 4));
2096 vnc_client_error(vs);
2097 break;
2098 }
2099 break;
2100
9ca313aa
AL
2101 default:
2102 printf("Msg: %d\n", read_u16(data, 0));
2103 vnc_client_error(vs);
2104 break;
2105 }
2106 break;
24236869 2107 default:
28a76be8
AL
2108 printf("Msg: %d\n", data[0]);
2109 vnc_client_error(vs);
2110 break;
24236869 2111 }
5fafdf24 2112
24236869
FB
2113 vnc_read_when(vs, protocol_client_msg, 1);
2114 return 0;
2115}
2116
60fe76f3 2117static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
24236869 2118{
c35734b2 2119 char buf[1024];
8cf36489 2120 VncShareMode mode;
c35734b2 2121 int size;
24236869 2122
8cf36489
GH
2123 mode = data[0] ? VNC_SHARE_MODE_SHARED : VNC_SHARE_MODE_EXCLUSIVE;
2124 switch (vs->vd->share_policy) {
2125 case VNC_SHARE_POLICY_IGNORE:
2126 /*
2127 * Ignore the shared flag. Nothing to do here.
2128 *
2129 * Doesn't conform to the rfb spec but is traditional qemu
2130 * behavior, thus left here as option for compatibility
2131 * reasons.
2132 */
2133 break;
2134 case VNC_SHARE_POLICY_ALLOW_EXCLUSIVE:
2135 /*
2136 * Policy: Allow clients ask for exclusive access.
2137 *
2138 * Implementation: When a client asks for exclusive access,
2139 * disconnect all others. Shared connects are allowed as long
2140 * as no exclusive connection exists.
2141 *
2142 * This is how the rfb spec suggests to handle the shared flag.
2143 */
2144 if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
2145 VncState *client;
2146 QTAILQ_FOREACH(client, &vs->vd->clients, next) {
2147 if (vs == client) {
2148 continue;
2149 }
2150 if (client->share_mode != VNC_SHARE_MODE_EXCLUSIVE &&
2151 client->share_mode != VNC_SHARE_MODE_SHARED) {
2152 continue;
2153 }
2154 vnc_disconnect_start(client);
2155 }
2156 }
2157 if (mode == VNC_SHARE_MODE_SHARED) {
2158 if (vs->vd->num_exclusive > 0) {
2159 vnc_disconnect_start(vs);
2160 return 0;
2161 }
2162 }
2163 break;
2164 case VNC_SHARE_POLICY_FORCE_SHARED:
2165 /*
2166 * Policy: Shared connects only.
2167 * Implementation: Disallow clients asking for exclusive access.
2168 *
2169 * Useful for shared desktop sessions where you don't want
2170 * someone forgetting to say -shared when running the vnc
2171 * client disconnect everybody else.
2172 */
2173 if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
2174 vnc_disconnect_start(vs);
2175 return 0;
2176 }
2177 break;
2178 }
2179 vnc_set_share_mode(vs, mode);
2180
5862d195
GH
2181 vs->client_width = ds_get_width(vs->ds);
2182 vs->client_height = ds_get_height(vs->ds);
2183 vnc_write_u16(vs, vs->client_width);
2184 vnc_write_u16(vs, vs->client_height);
24236869 2185
ca4cca4d 2186 pixel_format_message(vs);
24236869 2187
c35734b2
TS
2188 if (qemu_name)
2189 size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
2190 else
2191 size = snprintf(buf, sizeof(buf), "QEMU");
2192
2193 vnc_write_u32(vs, size);
2194 vnc_write(vs, buf, size);
24236869
FB
2195 vnc_flush(vs);
2196
4a80dba3 2197 vnc_client_cache_auth(vs);
0d2ed46a 2198 vnc_qmp_event(vs, QEVENT_VNC_INITIALIZED);
4a80dba3 2199
24236869
FB
2200 vnc_read_when(vs, protocol_client_msg, 1);
2201
2202 return 0;
2203}
2204
5fb6c7a8
AL
2205void start_client_init(VncState *vs)
2206{
2207 vnc_read_when(vs, protocol_client_init, 1);
2208}
2209
70848515
TS
2210static void make_challenge(VncState *vs)
2211{
2212 int i;
2213
2214 srand(time(NULL)+getpid()+getpid()*987654+rand());
2215
2216 for (i = 0 ; i < sizeof(vs->challenge) ; i++)
2217 vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
2218}
2219
60fe76f3 2220static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
70848515 2221{
60fe76f3 2222 unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
70848515 2223 int i, j, pwlen;
60fe76f3 2224 unsigned char key[8];
3c9405a0 2225 time_t now = time(NULL);
70848515 2226
1cd20f8b 2227 if (!vs->vd->password) {
28a76be8 2228 VNC_DEBUG("No password configured on server");
6bffdf0f 2229 goto reject;
70848515 2230 }
3c9405a0
GH
2231 if (vs->vd->expires < now) {
2232 VNC_DEBUG("Password is expired");
2233 goto reject;
2234 }
70848515
TS
2235
2236 memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
2237
2238 /* Calculate the expected challenge response */
753b4053 2239 pwlen = strlen(vs->vd->password);
70848515 2240 for (i=0; i<sizeof(key); i++)
753b4053 2241 key[i] = i<pwlen ? vs->vd->password[i] : 0;
70848515
TS
2242 deskey(key, EN0);
2243 for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
2244 des(response+j, response+j);
2245
2246 /* Compare expected vs actual challenge response */
2247 if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
e5bed759 2248 VNC_DEBUG("Client challenge response did not match\n");
6bffdf0f 2249 goto reject;
70848515 2250 } else {
28a76be8
AL
2251 VNC_DEBUG("Accepting VNC challenge response\n");
2252 vnc_write_u32(vs, 0); /* Accept auth */
2253 vnc_flush(vs);
70848515 2254
5fb6c7a8 2255 start_client_init(vs);
70848515
TS
2256 }
2257 return 0;
6bffdf0f
GH
2258
2259reject:
2260 vnc_write_u32(vs, 1); /* Reject auth */
2261 if (vs->minor >= 8) {
2262 static const char err[] = "Authentication failed";
2263 vnc_write_u32(vs, sizeof(err));
2264 vnc_write(vs, err, sizeof(err));
2265 }
2266 vnc_flush(vs);
2267 vnc_client_error(vs);
2268 return 0;
70848515
TS
2269}
2270
5fb6c7a8 2271void start_auth_vnc(VncState *vs)
70848515
TS
2272{
2273 make_challenge(vs);
2274 /* Send client a 'random' challenge */
2275 vnc_write(vs, vs->challenge, sizeof(vs->challenge));
2276 vnc_flush(vs);
2277
2278 vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
469b15c6
TS
2279}
2280
2281
60fe76f3 2282static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
70848515
TS
2283{
2284 /* We only advertise 1 auth scheme at a time, so client
2285 * must pick the one we sent. Verify this */
7e7e2ebc 2286 if (data[0] != vs->auth) { /* Reject auth */
1263b7d6 2287 VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
70848515
TS
2288 vnc_write_u32(vs, 1);
2289 if (vs->minor >= 8) {
2290 static const char err[] = "Authentication failed";
2291 vnc_write_u32(vs, sizeof(err));
2292 vnc_write(vs, err, sizeof(err));
2293 }
2294 vnc_client_error(vs);
2295 } else { /* Accept requested auth */
2296 VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
7e7e2ebc 2297 switch (vs->auth) {
70848515
TS
2298 case VNC_AUTH_NONE:
2299 VNC_DEBUG("Accept auth none\n");
a26c97ad
AZ
2300 if (vs->minor >= 8) {
2301 vnc_write_u32(vs, 0); /* Accept auth completion */
2302 vnc_flush(vs);
2303 }
5fb6c7a8 2304 start_client_init(vs);
70848515
TS
2305 break;
2306
2307 case VNC_AUTH_VNC:
2308 VNC_DEBUG("Start VNC auth\n");
5fb6c7a8
AL
2309 start_auth_vnc(vs);
2310 break;
70848515 2311
eb38c52c 2312#ifdef CONFIG_VNC_TLS
8d5d2d4c 2313 case VNC_AUTH_VENCRYPT:
3a93113a 2314 VNC_DEBUG("Accept VeNCrypt auth\n");
5fb6c7a8
AL
2315 start_auth_vencrypt(vs);
2316 break;
8d5d2d4c
TS
2317#endif /* CONFIG_VNC_TLS */
2318
2f9606b3
AL
2319#ifdef CONFIG_VNC_SASL
2320 case VNC_AUTH_SASL:
2321 VNC_DEBUG("Accept SASL auth\n");
2322 start_auth_sasl(vs);
2323 break;
2324#endif /* CONFIG_VNC_SASL */
2325
70848515 2326 default: /* Should not be possible, but just in case */
7e7e2ebc 2327 VNC_DEBUG("Reject auth %d server code bug\n", vs->auth);
70848515
TS
2328 vnc_write_u8(vs, 1);
2329 if (vs->minor >= 8) {
2330 static const char err[] = "Authentication failed";
2331 vnc_write_u32(vs, sizeof(err));
2332 vnc_write(vs, err, sizeof(err));
2333 }
2334 vnc_client_error(vs);
2335 }
2336 }
2337 return 0;
2338}
2339
60fe76f3 2340static int protocol_version(VncState *vs, uint8_t *version, size_t len)
24236869
FB
2341{
2342 char local[13];
24236869
FB
2343
2344 memcpy(local, version, 12);
2345 local[12] = 0;
2346
70848515 2347 if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
28a76be8
AL
2348 VNC_DEBUG("Malformed protocol version %s\n", local);
2349 vnc_client_error(vs);
2350 return 0;
24236869 2351 }
70848515
TS
2352 VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2353 if (vs->major != 3 ||
28a76be8
AL
2354 (vs->minor != 3 &&
2355 vs->minor != 4 &&
2356 vs->minor != 5 &&
2357 vs->minor != 7 &&
2358 vs->minor != 8)) {
2359 VNC_DEBUG("Unsupported client version\n");
2360 vnc_write_u32(vs, VNC_AUTH_INVALID);
2361 vnc_flush(vs);
2362 vnc_client_error(vs);
2363 return 0;
70848515 2364 }
b0566f4f 2365 /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
70848515
TS
2366 * as equivalent to v3.3 by servers
2367 */
b0566f4f 2368 if (vs->minor == 4 || vs->minor == 5)
28a76be8 2369 vs->minor = 3;
70848515
TS
2370
2371 if (vs->minor == 3) {
7e7e2ebc 2372 if (vs->auth == VNC_AUTH_NONE) {
70848515 2373 VNC_DEBUG("Tell client auth none\n");
7e7e2ebc 2374 vnc_write_u32(vs, vs->auth);
70848515 2375 vnc_flush(vs);
28a76be8 2376 start_client_init(vs);
7e7e2ebc 2377 } else if (vs->auth == VNC_AUTH_VNC) {
70848515 2378 VNC_DEBUG("Tell client VNC auth\n");
7e7e2ebc 2379 vnc_write_u32(vs, vs->auth);
70848515
TS
2380 vnc_flush(vs);
2381 start_auth_vnc(vs);
2382 } else {
7e7e2ebc 2383 VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
70848515
TS
2384 vnc_write_u32(vs, VNC_AUTH_INVALID);
2385 vnc_flush(vs);
2386 vnc_client_error(vs);
2387 }
2388 } else {
7e7e2ebc 2389 VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
28a76be8 2390 vnc_write_u8(vs, 1); /* num auth */
7e7e2ebc 2391 vnc_write_u8(vs, vs->auth);
28a76be8
AL
2392 vnc_read_when(vs, protocol_client_auth, 1);
2393 vnc_flush(vs);
70848515 2394 }
24236869
FB
2395
2396 return 0;
2397}
2398
999342a0
CC
2399static VncRectStat *vnc_stat_rect(VncDisplay *vd, int x, int y)
2400{
2401 struct VncSurface *vs = &vd->guest;
2402
2403 return &vs->stats[y / VNC_STAT_RECT][x / VNC_STAT_RECT];
2404}
2405
7d964c9d
CC
2406void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h)
2407{
2408 int i, j;
2409
2410 w = (x + w) / VNC_STAT_RECT;
2411 h = (y + h) / VNC_STAT_RECT;
2412 x /= VNC_STAT_RECT;
2413 y /= VNC_STAT_RECT;
2414
207f328a
CC
2415 for (j = y; j <= h; j++) {
2416 for (i = x; i <= w; i++) {
7d964c9d
CC
2417 vs->lossy_rect[j][i] = 1;
2418 }
2419 }
2420}
2421
2422static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
2423{
2424 VncState *vs;
2425 int sty = y / VNC_STAT_RECT;
2426 int stx = x / VNC_STAT_RECT;
2427 int has_dirty = 0;
2428
2429 y = y / VNC_STAT_RECT * VNC_STAT_RECT;
2430 x = x / VNC_STAT_RECT * VNC_STAT_RECT;
2431
2432 QTAILQ_FOREACH(vs, &vd->clients, next) {
bc2429b9 2433 int j;
7d964c9d
CC
2434
2435 /* kernel send buffers are full -> refresh later */
2436 if (vs->output.offset) {
2437 continue;
2438 }
2439
2440 if (!vs->lossy_rect[sty][stx]) {
2441 continue;
2442 }
207f328a 2443
7d964c9d
CC
2444 vs->lossy_rect[sty][stx] = 0;
2445 for (j = 0; j < VNC_STAT_RECT; ++j) {
bc2429b9 2446 bitmap_set(vs->dirty[y + j], x / 16, VNC_STAT_RECT / 16);
7d964c9d
CC
2447 }
2448 has_dirty++;
2449 }
207f328a 2450
7d964c9d
CC
2451 return has_dirty;
2452}
2453
2454static int vnc_update_stats(VncDisplay *vd, struct timeval * tv)
999342a0
CC
2455{
2456 int x, y;
2457 struct timeval res;
7d964c9d 2458 int has_dirty = 0;
999342a0
CC
2459
2460 for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) {
2461 for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) {
2462 VncRectStat *rect = vnc_stat_rect(vd, x, y);
2463
2464 rect->updated = false;
2465 }
2466 }
2467
ad620c29 2468 qemu_timersub(tv, &VNC_REFRESH_STATS, &res);
999342a0
CC
2469
2470 if (timercmp(&vd->guest.last_freq_check, &res, >)) {
7d964c9d 2471 return has_dirty;
999342a0
CC
2472 }
2473 vd->guest.last_freq_check = *tv;
2474
2475 for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) {
2476 for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) {
2477 VncRectStat *rect= vnc_stat_rect(vd, x, y);
2478 int count = ARRAY_SIZE(rect->times);
2479 struct timeval min, max;
2480
2481 if (!timerisset(&rect->times[count - 1])) {
2482 continue ;
2483 }
2484
2485 max = rect->times[(rect->idx + count - 1) % count];
ad620c29 2486 qemu_timersub(tv, &max, &res);
999342a0
CC
2487
2488 if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) {
2489 rect->freq = 0;
7d964c9d 2490 has_dirty += vnc_refresh_lossy_rect(vd, x, y);
999342a0
CC
2491 memset(rect->times, 0, sizeof (rect->times));
2492 continue ;
2493 }
2494
2495 min = rect->times[rect->idx];
2496 max = rect->times[(rect->idx + count - 1) % count];
ad620c29 2497 qemu_timersub(&max, &min, &res);
999342a0
CC
2498
2499 rect->freq = res.tv_sec + res.tv_usec / 1000000.;
2500 rect->freq /= count;
2501 rect->freq = 1. / rect->freq;
2502 }
2503 }
7d964c9d 2504 return has_dirty;
999342a0
CC
2505}
2506
2507double vnc_update_freq(VncState *vs, int x, int y, int w, int h)
2508{
2509 int i, j;
2510 double total = 0;
2511 int num = 0;
2512
2513 x = (x / VNC_STAT_RECT) * VNC_STAT_RECT;
2514 y = (y / VNC_STAT_RECT) * VNC_STAT_RECT;
2515
2516 for (j = y; j <= y + h; j += VNC_STAT_RECT) {
2517 for (i = x; i <= x + w; i += VNC_STAT_RECT) {
2518 total += vnc_stat_rect(vs->vd, i, j)->freq;
2519 num++;
2520 }
2521 }
2522
2523 if (num) {
2524 return total / num;
2525 } else {
2526 return 0;
2527 }
2528}
2529
2530static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv)
2531{
2532 VncRectStat *rect;
2533
2534 rect = vnc_stat_rect(vd, x, y);
2535 if (rect->updated) {
2536 return ;
2537 }
2538 rect->times[rect->idx] = *tv;
2539 rect->idx = (rect->idx + 1) % ARRAY_SIZE(rect->times);
2540 rect->updated = true;
2541}
2542
1fc62412
SS
2543static int vnc_refresh_server_surface(VncDisplay *vd)
2544{
2545 int y;
2546 uint8_t *guest_row;
2547 uint8_t *server_row;
2548 int cmp_bytes;
41b4bef6 2549 VncState *vs;
1fc62412
SS
2550 int has_dirty = 0;
2551
80e0c8c3 2552 struct timeval tv = { 0, 0 };
999342a0 2553
80e0c8c3
CC
2554 if (!vd->non_adaptive) {
2555 gettimeofday(&tv, NULL);
2556 has_dirty = vnc_update_stats(vd, &tv);
2557 }
999342a0 2558
1fc62412
SS
2559 /*
2560 * Walk through the guest dirty map.
2561 * Check and copy modified bits from guest to server surface.
2562 * Update server dirty map.
2563 */
1fc62412 2564 cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
9e4dd565
SW
2565 if (cmp_bytes > vd->ds->surface->linesize) {
2566 cmp_bytes = vd->ds->surface->linesize;
2567 }
1fc62412
SS
2568 guest_row = vd->guest.ds->data;
2569 server_row = vd->server->data;
2570 for (y = 0; y < vd->guest.ds->height; y++) {
23bfe28f 2571 if (!bitmap_empty(vd->guest.dirty[y], VNC_DIRTY_BITS)) {
1fc62412
SS
2572 int x;
2573 uint8_t *guest_ptr;
2574 uint8_t *server_ptr;
2575
2576 guest_ptr = guest_row;
2577 server_ptr = server_row;
2578
ce3e1417 2579 for (x = 0; x + 15 < vd->guest.ds->width;
1fc62412 2580 x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
bc2429b9 2581 if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
1fc62412 2582 continue;
1fc62412
SS
2583 if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
2584 continue;
2585 memcpy(server_ptr, guest_ptr, cmp_bytes);
80e0c8c3
CC
2586 if (!vd->non_adaptive)
2587 vnc_rect_updated(vd, x, y, &tv);
41b4bef6 2588 QTAILQ_FOREACH(vs, &vd->clients, next) {
bc2429b9 2589 set_bit((x / 16), vs->dirty[y]);
1fc62412
SS
2590 }
2591 has_dirty++;
2592 }
2593 }
2594 guest_row += ds_get_linesize(vd->ds);
2595 server_row += ds_get_linesize(vd->ds);
2596 }
2597 return has_dirty;
2598}
2599
703bc68f
SS
2600static void vnc_refresh(void *opaque)
2601{
2602 VncDisplay *vd = opaque;
41b4bef6
AS
2603 VncState *vs, *vn;
2604 int has_dirty, rects = 0;
703bc68f
SS
2605
2606 vga_hw_update();
2607
bd023f95
CC
2608 if (vnc_trylock_display(vd)) {
2609 vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
7bd427d8 2610 qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) +
bd023f95
CC
2611 vd->timer_interval);
2612 return;
2613 }
2614
1fc62412 2615 has_dirty = vnc_refresh_server_surface(vd);
bd023f95 2616 vnc_unlock_display(vd);
1fc62412 2617
41b4bef6 2618 QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
2430ffe4 2619 rects += vnc_update_client(vs, has_dirty);
6185c578 2620 /* vs might be free()ed here */
703bc68f 2621 }
bd023f95 2622
83755c17
SS
2623 /* vd->timer could be NULL now if the last client disconnected,
2624 * in this case don't update the timer */
2625 if (vd->timer == NULL)
2626 return;
703bc68f 2627
2430ffe4
SS
2628 if (has_dirty && rects) {
2629 vd->timer_interval /= 2;
2630 if (vd->timer_interval < VNC_REFRESH_INTERVAL_BASE)
2631 vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
2632 } else {
2633 vd->timer_interval += VNC_REFRESH_INTERVAL_INC;
2634 if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX)
2635 vd->timer_interval = VNC_REFRESH_INTERVAL_MAX;
2636 }
7bd427d8 2637 qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval);
703bc68f
SS
2638}
2639
2640static void vnc_init_timer(VncDisplay *vd)
2641{
2430ffe4 2642 vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
41b4bef6 2643 if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) {
7bd427d8 2644 vd->timer = qemu_new_timer_ms(rt_clock, vnc_refresh, vd);
5db8378a 2645 vnc_dpy_resize(vd->ds);
1fc62412 2646 vnc_refresh(vd);
703bc68f
SS
2647 }
2648}
2649
2650static void vnc_remove_timer(VncDisplay *vd)
2651{
41b4bef6 2652 if (vd->timer != NULL && QTAILQ_EMPTY(&vd->clients)) {
703bc68f
SS
2653 qemu_del_timer(vd->timer);
2654 qemu_free_timer(vd->timer);
2655 vd->timer = NULL;
2656 }
2657}
2658
7e7e2ebc 2659static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
3aa3eea3 2660{
7267c094 2661 VncState *vs = g_malloc0(sizeof(VncState));
7d964c9d
CC
2662 int i;
2663
753b4053 2664 vs->csock = csock;
7e7e2ebc
DB
2665
2666 if (skipauth) {
2667 vs->auth = VNC_AUTH_NONE;
2668#ifdef CONFIG_VNC_TLS
2669 vs->subauth = VNC_AUTH_INVALID;
2670#endif
2671 } else {
2672 vs->auth = vd->auth;
2673#ifdef CONFIG_VNC_TLS
2674 vs->subauth = vd->subauth;
2675#endif
2676 }
2677
7267c094 2678 vs->lossy_rect = g_malloc0(VNC_STAT_ROWS * sizeof (*vs->lossy_rect));
7d964c9d 2679 for (i = 0; i < VNC_STAT_ROWS; ++i) {
7267c094 2680 vs->lossy_rect[i] = g_malloc0(VNC_STAT_COLS * sizeof (uint8_t));
7d964c9d 2681 }
753b4053
AL
2682
2683 VNC_DEBUG("New client on socket %d\n", csock);
7d957bd8 2684 dcl->idle = 0;
3aa3eea3
AZ
2685 socket_set_nonblock(vs->csock);
2686 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
753b4053 2687
4a80dba3 2688 vnc_client_cache_addr(vs);
586153d9 2689 vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
8cf36489 2690 vnc_set_share_mode(vs, VNC_SHARE_MODE_CONNECTING);
4a80dba3 2691
753b4053
AL
2692 vs->vd = vd;
2693 vs->ds = vd->ds;
753b4053
AL
2694 vs->last_x = -1;
2695 vs->last_y = -1;
2696
2697 vs->as.freq = 44100;
2698 vs->as.nchannels = 2;
2699 vs->as.fmt = AUD_FMT_S16;
2700 vs->as.endianness = 0;
2701
bd023f95
CC
2702#ifdef CONFIG_VNC_THREAD
2703 qemu_mutex_init(&vs->output_mutex);
175b2a6e 2704 vs->bh = qemu_bh_new(vnc_jobs_bh, vs);
bd023f95
CC
2705#endif
2706
41b4bef6 2707 QTAILQ_INSERT_HEAD(&vd->clients, vs, next);
1fc62412
SS
2708
2709 vga_hw_update();
2710
3aa3eea3
AZ
2711 vnc_write(vs, "RFB 003.008\n", 12);
2712 vnc_flush(vs);
2713 vnc_read_when(vs, protocol_version, 12);
53762ddb 2714 reset_keys(vs);
3a0558b5
GH
2715 if (vs->vd->lock_key_sync)
2716 vs->led = qemu_add_led_event_handler(kbd_leds, vs);
753b4053 2717
37c34d9d
AL
2718 vs->mouse_mode_notifier.notify = check_pointer_type_change;
2719 qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
2720
703bc68f 2721 vnc_init_timer(vd);
1fc62412 2722
198a0039 2723 /* vs might be free()ed here */
3aa3eea3
AZ
2724}
2725
24236869
FB
2726static void vnc_listen_read(void *opaque)
2727{
753b4053 2728 VncDisplay *vs = opaque;
24236869
FB
2729 struct sockaddr_in addr;
2730 socklen_t addrlen = sizeof(addr);
2731
9f60ad50
AZ
2732 /* Catch-up */
2733 vga_hw_update();
2734
40ff6d7e 2735 int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
753b4053 2736 if (csock != -1) {
7e7e2ebc 2737 vnc_connect(vs, csock, 0);
24236869
FB
2738 }
2739}
2740
71cab5ca 2741void vnc_display_init(DisplayState *ds)
24236869 2742{
7267c094 2743 VncDisplay *vs = g_malloc0(sizeof(*vs));
24236869 2744
7267c094 2745 dcl = g_malloc0(sizeof(DisplayChangeListener));
24236869
FB
2746
2747 ds->opaque = vs;
7d957bd8 2748 dcl->idle = 1;
753b4053 2749 vnc_display = vs;
24236869
FB
2750
2751 vs->lsock = -1;
24236869
FB
2752
2753 vs->ds = ds;
41b4bef6 2754 QTAILQ_INIT(&vs->clients);
3c9405a0 2755 vs->expires = TIME_MAX;
24236869 2756
9ca313aa 2757 if (keyboard_layout)
0483755a 2758 vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
9ca313aa 2759 else
0483755a 2760 vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us");
24236869 2761
24236869 2762 if (!vs->kbd_layout)
28a76be8 2763 exit(1);
24236869 2764
bd023f95
CC
2765#ifdef CONFIG_VNC_THREAD
2766 qemu_mutex_init(&vs->mutex);
2767 vnc_start_worker_thread();
2768#endif
2769
753b4053 2770 dcl->dpy_copy = vnc_dpy_copy;
7d957bd8
AL
2771 dcl->dpy_update = vnc_dpy_update;
2772 dcl->dpy_resize = vnc_dpy_resize;
2773 dcl->dpy_setdata = vnc_dpy_setdata;
7d957bd8 2774 register_displaychangelistener(ds, dcl);
d467b679
GH
2775 ds->mouse_set = vnc_mouse_set;
2776 ds->cursor_define = vnc_dpy_cursor_define;
71cab5ca
TS
2777}
2778
6f43024c 2779
71cab5ca
TS
2780void vnc_display_close(DisplayState *ds)
2781{
753b4053 2782 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
71cab5ca 2783
452b4d88
AL
2784 if (!vs)
2785 return;
71cab5ca 2786 if (vs->display) {
7267c094 2787 g_free(vs->display);
28a76be8 2788 vs->display = NULL;
71cab5ca
TS
2789 }
2790 if (vs->lsock != -1) {
28a76be8
AL
2791 qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2792 close(vs->lsock);
2793 vs->lsock = -1;
71cab5ca 2794 }
70848515 2795 vs->auth = VNC_AUTH_INVALID;
eb38c52c 2796#ifdef CONFIG_VNC_TLS
8d5d2d4c 2797 vs->subauth = VNC_AUTH_INVALID;
5fb6c7a8 2798 vs->tls.x509verify = 0;
8d5d2d4c 2799#endif
70848515
TS
2800}
2801
1cd20f8b
AL
2802int vnc_display_disable_login(DisplayState *ds)
2803{
2804 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2805
2806 if (!vs) {
2807 return -1;
2808 }
2809
2810 if (vs->password) {
7267c094 2811 g_free(vs->password);
1cd20f8b
AL
2812 }
2813
2814 vs->password = NULL;
7dfbfc79
DB
2815 if (vs->auth == VNC_AUTH_NONE) {
2816 vs->auth = VNC_AUTH_VNC;
2817 }
1cd20f8b
AL
2818
2819 return 0;
2820}
2821
70848515
TS
2822int vnc_display_password(DisplayState *ds, const char *password)
2823{
753b4053 2824 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
70848515 2825
7ef92331 2826 if (!vs) {
a6aa9d3e 2827 return -EINVAL;
7ef92331
ZA
2828 }
2829
1cd20f8b
AL
2830 if (!password) {
2831 /* This is not the intention of this interface but err on the side
2832 of being safe */
a6aa9d3e 2833 return vnc_display_disable_login(ds);
1cd20f8b
AL
2834 }
2835
70848515 2836 if (vs->password) {
7267c094 2837 g_free(vs->password);
28a76be8 2838 vs->password = NULL;
70848515 2839 }
7267c094 2840 vs->password = g_strdup(password);
7dfbfc79
DB
2841 if (vs->auth == VNC_AUTH_NONE) {
2842 vs->auth = VNC_AUTH_VNC;
2843 }
a6aa9d3e
LC
2844
2845 return 0;
71cab5ca
TS
2846}
2847
3c9405a0
GH
2848int vnc_display_pw_expire(DisplayState *ds, time_t expires)
2849{
2850 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2851
2852 vs->expires = expires;
2853 return 0;
2854}
2855
f92f8afe
AL
2856char *vnc_display_local_addr(DisplayState *ds)
2857{
2858 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2859
2860 return vnc_socket_local_addr("%s:%s", vs->lsock);
2861}
2862
70848515 2863int vnc_display_open(DisplayState *ds, const char *display)
71cab5ca 2864{
753b4053 2865 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
70848515
TS
2866 const char *options;
2867 int password = 0;
3aa3eea3 2868 int reverse = 0;
eb38c52c 2869#ifdef CONFIG_VNC_TLS
3a702699 2870 int tls = 0, x509 = 0;
8d5d2d4c 2871#endif
2f9606b3
AL
2872#ifdef CONFIG_VNC_SASL
2873 int sasl = 0;
2874 int saslErr;
2875#endif
2ded6ad7 2876#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
76655d6d 2877 int acl = 0;
2ded6ad7 2878#endif
3a0558b5 2879 int lock_key_sync = 1;
71cab5ca 2880
753b4053 2881 if (!vnc_display)
452b4d88 2882 return -1;
71cab5ca 2883 vnc_display_close(ds);
70848515 2884 if (strcmp(display, "none") == 0)
28a76be8 2885 return 0;
24236869 2886
70848515 2887 if (!(vs->display = strdup(display)))
28a76be8 2888 return -1;
8cf36489 2889 vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
70848515
TS
2890
2891 options = display;
2892 while ((options = strchr(options, ','))) {
28a76be8
AL
2893 options++;
2894 if (strncmp(options, "password", 8) == 0) {
2895 password = 1; /* Require password auth */
2896 } else if (strncmp(options, "reverse", 7) == 0) {
2897 reverse = 1;
cee8e6ad 2898 } else if (strncmp(options, "no-lock-key-sync", 16) == 0) {
3a0558b5 2899 lock_key_sync = 0;
2f9606b3 2900#ifdef CONFIG_VNC_SASL
28a76be8
AL
2901 } else if (strncmp(options, "sasl", 4) == 0) {
2902 sasl = 1; /* Require SASL auth */
2f9606b3 2903#endif
eb38c52c 2904#ifdef CONFIG_VNC_TLS
28a76be8
AL
2905 } else if (strncmp(options, "tls", 3) == 0) {
2906 tls = 1; /* Require TLS */
2907 } else if (strncmp(options, "x509", 4) == 0) {
2908 char *start, *end;
2909 x509 = 1; /* Require x509 certificates */
2910 if (strncmp(options, "x509verify", 10) == 0)
2911 vs->tls.x509verify = 1; /* ...and verify client certs */
2912
2913 /* Now check for 'x509=/some/path' postfix
2914 * and use that to setup x509 certificate/key paths */
2915 start = strchr(options, '=');
2916 end = strchr(options, ',');
2917 if (start && (!end || (start < end))) {
2918 int len = end ? end-(start+1) : strlen(start+1);
7267c094 2919 char *path = g_strndup(start + 1, len);
28a76be8
AL
2920
2921 VNC_DEBUG("Trying certificate path '%s'\n", path);
2922 if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
2923 fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
7267c094
AL
2924 g_free(path);
2925 g_free(vs->display);
28a76be8
AL
2926 vs->display = NULL;
2927 return -1;
2928 }
7267c094 2929 g_free(path);
28a76be8
AL
2930 } else {
2931 fprintf(stderr, "No certificate path provided\n");
7267c094 2932 g_free(vs->display);
28a76be8
AL
2933 vs->display = NULL;
2934 return -1;
2935 }
8d5d2d4c 2936#endif
2ded6ad7 2937#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
28a76be8
AL
2938 } else if (strncmp(options, "acl", 3) == 0) {
2939 acl = 1;
2ded6ad7 2940#endif
6f9c78c1
CC
2941 } else if (strncmp(options, "lossy", 5) == 0) {
2942 vs->lossy = true;
80e0c8c3
CC
2943 } else if (strncmp(options, "non-adapative", 13) == 0) {
2944 vs->non_adaptive = true;
8cf36489
GH
2945 } else if (strncmp(options, "share=", 6) == 0) {
2946 if (strncmp(options+6, "ignore", 6) == 0) {
2947 vs->share_policy = VNC_SHARE_POLICY_IGNORE;
2948 } else if (strncmp(options+6, "allow-exclusive", 15) == 0) {
2949 vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
2950 } else if (strncmp(options+6, "force-shared", 12) == 0) {
2951 vs->share_policy = VNC_SHARE_POLICY_FORCE_SHARED;
2952 } else {
2953 fprintf(stderr, "unknown vnc share= option\n");
2954 g_free(vs->display);
2955 vs->display = NULL;
2956 return -1;
2957 }
28a76be8 2958 }
70848515
TS
2959 }
2960
76655d6d
AL
2961#ifdef CONFIG_VNC_TLS
2962 if (acl && x509 && vs->tls.x509verify) {
28a76be8
AL
2963 if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) {
2964 fprintf(stderr, "Failed to create x509 dname ACL\n");
2965 exit(1);
2966 }
76655d6d
AL
2967 }
2968#endif
2969#ifdef CONFIG_VNC_SASL
2970 if (acl && sasl) {
28a76be8
AL
2971 if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) {
2972 fprintf(stderr, "Failed to create username ACL\n");
2973 exit(1);
2974 }
76655d6d
AL
2975 }
2976#endif
2977
2f9606b3
AL
2978 /*
2979 * Combinations we support here:
2980 *
2981 * - no-auth (clear text, no auth)
2982 * - password (clear text, weak auth)
2983 * - sasl (encrypt, good auth *IF* using Kerberos via GSSAPI)
2984 * - tls (encrypt, weak anonymous creds, no auth)
2985 * - tls + password (encrypt, weak anonymous creds, weak auth)
2986 * - tls + sasl (encrypt, weak anonymous creds, good auth)
2987 * - tls + x509 (encrypt, good x509 creds, no auth)
2988 * - tls + x509 + password (encrypt, good x509 creds, weak auth)
2989 * - tls + x509 + sasl (encrypt, good x509 creds, good auth)
2990 *
2991 * NB1. TLS is a stackable auth scheme.
2992 * NB2. the x509 schemes have option to validate a client cert dname
2993 */
70848515 2994 if (password) {
eb38c52c 2995#ifdef CONFIG_VNC_TLS
28a76be8
AL
2996 if (tls) {
2997 vs->auth = VNC_AUTH_VENCRYPT;
2998 if (x509) {
2999 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
3000 vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
3001 } else {
3002 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
3003 vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
3004 }
3005 } else {
2f9606b3 3006#endif /* CONFIG_VNC_TLS */
28a76be8
AL
3007 VNC_DEBUG("Initializing VNC server with password auth\n");
3008 vs->auth = VNC_AUTH_VNC;
eb38c52c 3009#ifdef CONFIG_VNC_TLS
28a76be8
AL
3010 vs->subauth = VNC_AUTH_INVALID;
3011 }
2f9606b3
AL
3012#endif /* CONFIG_VNC_TLS */
3013#ifdef CONFIG_VNC_SASL
3014 } else if (sasl) {
3015#ifdef CONFIG_VNC_TLS
3016 if (tls) {
3017 vs->auth = VNC_AUTH_VENCRYPT;
3018 if (x509) {
28a76be8 3019 VNC_DEBUG("Initializing VNC server with x509 SASL auth\n");
2f9606b3
AL
3020 vs->subauth = VNC_AUTH_VENCRYPT_X509SASL;
3021 } else {
28a76be8 3022 VNC_DEBUG("Initializing VNC server with TLS SASL auth\n");
2f9606b3
AL
3023 vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL;
3024 }
3025 } else {
3026#endif /* CONFIG_VNC_TLS */
28a76be8 3027 VNC_DEBUG("Initializing VNC server with SASL auth\n");
2f9606b3
AL
3028 vs->auth = VNC_AUTH_SASL;
3029#ifdef CONFIG_VNC_TLS
3030 vs->subauth = VNC_AUTH_INVALID;
3031 }
3032#endif /* CONFIG_VNC_TLS */
3033#endif /* CONFIG_VNC_SASL */
70848515 3034 } else {
eb38c52c 3035#ifdef CONFIG_VNC_TLS
28a76be8
AL
3036 if (tls) {
3037 vs->auth = VNC_AUTH_VENCRYPT;
3038 if (x509) {
3039 VNC_DEBUG("Initializing VNC server with x509 no auth\n");
3040 vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
3041 } else {
3042 VNC_DEBUG("Initializing VNC server with TLS no auth\n");
3043 vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
3044 }
3045 } else {
8d5d2d4c 3046#endif
28a76be8
AL
3047 VNC_DEBUG("Initializing VNC server with no auth\n");
3048 vs->auth = VNC_AUTH_NONE;
eb38c52c 3049#ifdef CONFIG_VNC_TLS
28a76be8
AL
3050 vs->subauth = VNC_AUTH_INVALID;
3051 }
8d5d2d4c 3052#endif
70848515 3053 }
24236869 3054
2f9606b3
AL
3055#ifdef CONFIG_VNC_SASL
3056 if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) {
3057 fprintf(stderr, "Failed to initialize SASL auth %s",
3058 sasl_errstring(saslErr, NULL, NULL));
ae878b17 3059 g_free(vs->display);
2f9606b3
AL
3060 vs->display = NULL;
3061 return -1;
3062 }
3063#endif
3a0558b5 3064 vs->lock_key_sync = lock_key_sync;
2f9606b3 3065
3aa3eea3 3066 if (reverse) {
9712ecaf
AL
3067 /* connect to viewer */
3068 if (strncmp(display, "unix:", 5) == 0)
3069 vs->lsock = unix_connect(display+5);
3070 else
3071 vs->lsock = inet_connect(display, SOCK_STREAM);
3072 if (-1 == vs->lsock) {
ae878b17 3073 g_free(vs->display);
3aa3eea3
AZ
3074 vs->display = NULL;
3075 return -1;
3076 } else {
753b4053 3077 int csock = vs->lsock;
3aa3eea3 3078 vs->lsock = -1;
7e7e2ebc 3079 vnc_connect(vs, csock, 0);
3aa3eea3 3080 }
9712ecaf 3081 return 0;
24236869 3082
9712ecaf
AL
3083 } else {
3084 /* listen for connects */
3085 char *dpy;
7267c094 3086 dpy = g_malloc(256);
9712ecaf 3087 if (strncmp(display, "unix:", 5) == 0) {
bc575e95 3088 pstrcpy(dpy, 256, "unix:");
4a55bfdf 3089 vs->lsock = unix_listen(display+5, dpy+5, 256-5);
9712ecaf
AL
3090 } else {
3091 vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
3092 }
3093 if (-1 == vs->lsock) {
ae878b17 3094 g_free(dpy);
d0513623 3095 return -1;
9712ecaf 3096 } else {
ae878b17 3097 g_free(vs->display);
9712ecaf
AL
3098 vs->display = dpy;
3099 }
24236869 3100 }
753b4053 3101 return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs);
24236869 3102}
13661089
DB
3103
3104void vnc_display_add_client(DisplayState *ds, int csock, int skipauth)
3105{
3106 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
3107
3108 return vnc_connect(vs, csock, skipauth);
3109}