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

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

unix.superglobalmegacorp.com

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