Annotation of qemu/ui/vnc.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.