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