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