Annotation of qemu/vnc.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * QEMU VNC display driver
                      3:  * 
                      4:  * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
                      5:  * Copyright (C) 2006 Fabrice Bellard
                      6:  * 
                      7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      8:  * of this software and associated documentation files (the "Software"), to deal
                      9:  * in the Software without restriction, including without limitation the rights
                     10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     11:  * copies of the Software, and to permit persons to whom the Software is
                     12:  * furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included in
                     15:  * all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     23:  * THE SOFTWARE.
                     24:  */
                     25: 
                     26: #include "vl.h"
                     27: #include "qemu_socket.h"
                     28: 
                     29: #define VNC_REFRESH_INTERVAL (1000 / 30)
                     30: 
                     31: #include "vnc_keysym.h"
                     32: #include "keymaps.c"
                     33: 
                     34: typedef struct Buffer
                     35: {
                     36:     size_t capacity;
                     37:     size_t offset;
                     38:     char *buffer;
                     39: } Buffer;
                     40: 
                     41: typedef struct VncState VncState;
                     42: 
                     43: typedef int VncReadEvent(VncState *vs, char *data, size_t len);
                     44: 
1.1.1.2   root       45: typedef void VncWritePixels(VncState *vs, void *data, int size);
                     46: 
                     47: typedef void VncSendHextileTile(VncState *vs,
                     48:                                 int x, int y, int w, int h,
                     49:                                 uint32_t *last_bg, 
                     50:                                 uint32_t *last_fg,
                     51:                                 int *has_bg, int *has_fg);
                     52: 
                     53: #define VNC_MAX_WIDTH 2048
                     54: #define VNC_MAX_HEIGHT 2048
                     55: #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
                     56: 
1.1       root       57: struct VncState
                     58: {
                     59:     QEMUTimer *timer;
                     60:     int lsock;
                     61:     int csock;
                     62:     DisplayState *ds;
                     63:     int need_update;
                     64:     int width;
                     65:     int height;
1.1.1.2   root       66:     uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
1.1       root       67:     char *old_data;
1.1.1.2   root       68:     int depth; /* internal VNC frame buffer byte per pixel */
1.1       root       69:     int has_resize;
                     70:     int has_hextile;
1.1.1.3 ! root       71:     int has_pointer_type_change;
        !            72:     int absolute;
        !            73:     int last_x;
        !            74:     int last_y;
        !            75: 
        !            76:     const char *display;
        !            77: 
1.1       root       78:     Buffer output;
                     79:     Buffer input;
                     80:     kbd_layout_t *kbd_layout;
1.1.1.2   root       81:     /* current output mode information */
                     82:     VncWritePixels *write_pixels;
                     83:     VncSendHextileTile *send_hextile_tile;
                     84:     int pix_bpp, pix_big_endian;
                     85:     int red_shift, red_max, red_shift1;
                     86:     int green_shift, green_max, green_shift1;
                     87:     int blue_shift, blue_max, blue_shift1;
1.1       root       88: 
                     89:     VncReadEvent *read_handler;
                     90:     size_t read_handler_expect;
1.1.1.3 ! root       91:     /* input */
        !            92:     uint8_t modifiers_state[256];
1.1       root       93: };
                     94: 
1.1.1.3 ! root       95: static VncState *vnc_state; /* needed for info vnc */
        !            96: 
        !            97: void do_info_vnc(void)
        !            98: {
        !            99:     if (vnc_state == NULL)
        !           100:        term_printf("VNC server disabled\n");
        !           101:     else {
        !           102:        term_printf("VNC server active on: ");
        !           103:        term_print_filename(vnc_state->display);
        !           104:        term_printf("\n");
        !           105: 
        !           106:        if (vnc_state->csock == -1)
        !           107:            term_printf("No client connected\n");
        !           108:        else
        !           109:            term_printf("Client connected\n");
        !           110:     }
        !           111: }
        !           112: 
1.1       root      113: /* TODO
                    114:    1) Get the queue working for IO.
                    115:    2) there is some weirdness when using the -S option (the screen is grey
                    116:       and not totally invalidated
                    117:    3) resolutions > 1024
                    118: */
                    119: 
                    120: static void vnc_write(VncState *vs, const void *data, size_t len);
                    121: static void vnc_write_u32(VncState *vs, uint32_t value);
                    122: static void vnc_write_s32(VncState *vs, int32_t value);
                    123: static void vnc_write_u16(VncState *vs, uint16_t value);
                    124: static void vnc_write_u8(VncState *vs, uint8_t value);
                    125: static void vnc_flush(VncState *vs);
                    126: static void vnc_update_client(void *opaque);
                    127: static void vnc_client_read(void *opaque);
                    128: 
1.1.1.2   root      129: static inline void vnc_set_bit(uint32_t *d, int k)
                    130: {
                    131:     d[k >> 5] |= 1 << (k & 0x1f);
                    132: }
                    133: 
                    134: static inline void vnc_clear_bit(uint32_t *d, int k)
                    135: {
                    136:     d[k >> 5] &= ~(1 << (k & 0x1f));
                    137: }
                    138: 
                    139: static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
                    140: {
                    141:     int j;
                    142: 
                    143:     j = 0;
                    144:     while (n >= 32) {
                    145:         d[j++] = -1;
                    146:         n -= 32;
                    147:     }
                    148:     if (n > 0) 
                    149:         d[j++] = (1 << n) - 1;
                    150:     while (j < nb_words)
                    151:         d[j++] = 0;
                    152: }
                    153: 
                    154: static inline int vnc_get_bit(const uint32_t *d, int k)
                    155: {
                    156:     return (d[k >> 5] >> (k & 0x1f)) & 1;
                    157: }
                    158: 
                    159: static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2, 
                    160:                                int nb_words)
                    161: {
                    162:     int i;
                    163:     for(i = 0; i < nb_words; i++) {
                    164:         if ((d1[i] & d2[i]) != 0)
                    165:             return 1;
                    166:     }
                    167:     return 0;
                    168: }
                    169: 
1.1       root      170: static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
                    171: {
                    172:     VncState *vs = ds->opaque;
                    173:     int i;
                    174: 
                    175:     h += y;
                    176: 
                    177:     for (; y < h; y++)
                    178:        for (i = 0; i < w; i += 16)
1.1.1.2   root      179:            vnc_set_bit(vs->dirty_row[y], (x + i) / 16);
1.1       root      180: }
                    181: 
                    182: static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
                    183:                                   int32_t encoding)
                    184: {
                    185:     vnc_write_u16(vs, x);
                    186:     vnc_write_u16(vs, y);
                    187:     vnc_write_u16(vs, w);
                    188:     vnc_write_u16(vs, h);
                    189: 
                    190:     vnc_write_s32(vs, encoding);
                    191: }
                    192: 
                    193: static void vnc_dpy_resize(DisplayState *ds, int w, int h)
                    194: {
1.1.1.3 ! root      195:     int size_changed;
1.1       root      196:     VncState *vs = ds->opaque;
                    197: 
                    198:     ds->data = realloc(ds->data, w * h * vs->depth);
                    199:     vs->old_data = realloc(vs->old_data, w * h * vs->depth);
                    200: 
                    201:     if (ds->data == NULL || vs->old_data == NULL) {
                    202:        fprintf(stderr, "vnc: memory allocation failed\n");
                    203:        exit(1);
                    204:     }
                    205: 
                    206:     ds->depth = vs->depth * 8;
1.1.1.3 ! root      207:     size_changed = ds->width != w || ds->height != h;
1.1       root      208:     ds->width = w;
                    209:     ds->height = h;
                    210:     ds->linesize = w * vs->depth;
1.1.1.3 ! root      211:     if (vs->csock != -1 && vs->has_resize && size_changed) {
1.1       root      212:        vnc_write_u8(vs, 0);  /* msg id */
                    213:        vnc_write_u8(vs, 0);
                    214:        vnc_write_u16(vs, 1); /* number of rects */
                    215:        vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
                    216:        vnc_flush(vs);
                    217:        vs->width = ds->width;
                    218:        vs->height = ds->height;
                    219:     }
                    220: }
                    221: 
1.1.1.2   root      222: /* fastest code */
                    223: static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
                    224: {
                    225:     vnc_write(vs, pixels, size);
                    226: }
                    227: 
                    228: /* slowest but generic code. */
                    229: static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
                    230: {
                    231:     unsigned int r, g, b;
                    232: 
                    233:     r = (v >> vs->red_shift1) & vs->red_max;
                    234:     g = (v >> vs->green_shift1) & vs->green_max;
                    235:     b = (v >> vs->blue_shift1) & vs->blue_max;
                    236:     v = (r << vs->red_shift) | 
                    237:         (g << vs->green_shift) | 
                    238:         (b << vs->blue_shift);
                    239:     switch(vs->pix_bpp) {
                    240:     case 1:
                    241:         buf[0] = v;
                    242:         break;
                    243:     case 2:
                    244:         if (vs->pix_big_endian) {
                    245:             buf[0] = v >> 8;
                    246:             buf[1] = v;
                    247:         } else {
                    248:             buf[1] = v >> 8;
                    249:             buf[0] = v;
                    250:         }
                    251:         break;
                    252:     default:
                    253:     case 4:
                    254:         if (vs->pix_big_endian) {
                    255:             buf[0] = v >> 24;
                    256:             buf[1] = v >> 16;
                    257:             buf[2] = v >> 8;
                    258:             buf[3] = v;
                    259:         } else {
                    260:             buf[3] = v >> 24;
                    261:             buf[2] = v >> 16;
                    262:             buf[1] = v >> 8;
                    263:             buf[0] = v;
                    264:         }
                    265:         break;
                    266:     }
                    267: }
                    268: 
                    269: static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
                    270: {
                    271:     uint32_t *pixels = pixels1;
                    272:     uint8_t buf[4];
                    273:     int n, i;
                    274: 
                    275:     n = size >> 2;
                    276:     for(i = 0; i < n; i++) {
                    277:         vnc_convert_pixel(vs, buf, pixels[i]);
                    278:         vnc_write(vs, buf, vs->pix_bpp);
                    279:     }
                    280: }
                    281: 
1.1       root      282: static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
                    283: {
                    284:     int i;
                    285:     char *row;
                    286: 
                    287:     vnc_framebuffer_update(vs, x, y, w, h, 0);
                    288: 
                    289:     row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
                    290:     for (i = 0; i < h; i++) {
1.1.1.2   root      291:        vs->write_pixels(vs, row, w * vs->depth);
1.1       root      292:        row += vs->ds->linesize;
                    293:     }
                    294: }
                    295: 
                    296: static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
                    297: {
                    298:     ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
                    299:     ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
                    300: }
                    301: 
                    302: #define BPP 8
                    303: #include "vnchextile.h"
                    304: #undef BPP
                    305: 
                    306: #define BPP 16
                    307: #include "vnchextile.h"
                    308: #undef BPP
                    309: 
                    310: #define BPP 32
                    311: #include "vnchextile.h"
                    312: #undef BPP
                    313: 
1.1.1.2   root      314: #define GENERIC
                    315: #define BPP 32
                    316: #include "vnchextile.h"
                    317: #undef BPP
                    318: #undef GENERIC
                    319: 
1.1       root      320: static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
                    321: {
                    322:     int i, j;
                    323:     int has_fg, has_bg;
                    324:     uint32_t last_fg32, last_bg32;
                    325: 
                    326:     vnc_framebuffer_update(vs, x, y, w, h, 5);
                    327: 
                    328:     has_fg = has_bg = 0;
                    329:     for (j = y; j < (y + h); j += 16) {
                    330:        for (i = x; i < (x + w); i += 16) {
1.1.1.2   root      331:             vs->send_hextile_tile(vs, i, j, 
                    332:                                   MIN(16, x + w - i), MIN(16, y + h - j),
                    333:                                   &last_bg32, &last_fg32, &has_bg, &has_fg);
1.1       root      334:        }
                    335:     }
                    336: }
                    337: 
                    338: static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
                    339: {
                    340:        if (vs->has_hextile)
                    341:            send_framebuffer_update_hextile(vs, x, y, w, h);
                    342:        else
                    343:            send_framebuffer_update_raw(vs, x, y, w, h);
                    344: }
                    345: 
                    346: static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
                    347: {
                    348:     int src, dst;
                    349:     char *src_row;
                    350:     char *dst_row;
                    351:     char *old_row;
                    352:     int y = 0;
                    353:     int pitch = ds->linesize;
                    354:     VncState *vs = ds->opaque;
                    355: 
                    356:     vnc_update_client(vs);
                    357: 
                    358:     if (dst_y > src_y) {
                    359:        y = h - 1;
                    360:        pitch = -pitch;
                    361:     }
                    362: 
                    363:     src = (ds->linesize * (src_y + y) + vs->depth * src_x);
                    364:     dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
                    365: 
                    366:     src_row = ds->data + src;
                    367:     dst_row = ds->data + dst;
                    368:     old_row = vs->old_data + dst;
                    369: 
                    370:     for (y = 0; y < h; y++) {
                    371:        memmove(old_row, src_row, w * vs->depth);
                    372:        memmove(dst_row, src_row, w * vs->depth);
                    373:        src_row += pitch;
                    374:        dst_row += pitch;
                    375:        old_row += pitch;
                    376:     }
                    377: 
                    378:     vnc_write_u8(vs, 0);  /* msg id */
                    379:     vnc_write_u8(vs, 0);
                    380:     vnc_write_u16(vs, 1); /* number of rects */
                    381:     vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
                    382:     vnc_write_u16(vs, src_x);
                    383:     vnc_write_u16(vs, src_y);
                    384:     vnc_flush(vs);
                    385: }
                    386: 
                    387: static int find_dirty_height(VncState *vs, int y, int last_x, int x)
                    388: {
                    389:     int h;
                    390: 
                    391:     for (h = 1; h < (vs->height - y); h++) {
                    392:        int tmp_x;
1.1.1.2   root      393:        if (!vnc_get_bit(vs->dirty_row[y + h], last_x))
1.1       root      394:            break;
                    395:        for (tmp_x = last_x; tmp_x < x; tmp_x++)
1.1.1.2   root      396:            vnc_clear_bit(vs->dirty_row[y + h], tmp_x);
1.1       root      397:     }
                    398: 
                    399:     return h;
                    400: }
                    401: 
                    402: static void vnc_update_client(void *opaque)
                    403: {
                    404:     VncState *vs = opaque;
                    405: 
                    406:     if (vs->need_update && vs->csock != -1) {
                    407:        int y;
                    408:        char *row;
                    409:        char *old_row;
1.1.1.2   root      410:        uint32_t width_mask[VNC_DIRTY_WORDS];
1.1       root      411:        int n_rectangles;
                    412:        int saved_offset;
                    413:        int has_dirty = 0;
                    414: 
1.1.1.2   root      415:         vnc_set_bits(width_mask, (vs->width / 16), VNC_DIRTY_WORDS);
1.1       root      416: 
                    417:        /* Walk through the dirty map and eliminate tiles that
                    418:           really aren't dirty */
                    419:        row = vs->ds->data;
                    420:        old_row = vs->old_data;
                    421: 
                    422:        for (y = 0; y < vs->height; y++) {
1.1.1.2   root      423:            if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) {
1.1       root      424:                int x;
                    425:                char *ptr, *old_ptr;
                    426: 
                    427:                ptr = row;
                    428:                old_ptr = old_row;
                    429: 
                    430:                for (x = 0; x < vs->ds->width; x += 16) {
                    431:                    if (memcmp(old_ptr, ptr, 16 * vs->depth) == 0) {
1.1.1.2   root      432:                        vnc_clear_bit(vs->dirty_row[y], (x / 16));
1.1       root      433:                    } else {
                    434:                        has_dirty = 1;
                    435:                        memcpy(old_ptr, ptr, 16 * vs->depth);
                    436:                    }
                    437: 
                    438:                    ptr += 16 * vs->depth;
                    439:                    old_ptr += 16 * vs->depth;
                    440:                }
                    441:            }
                    442: 
                    443:            row += vs->ds->linesize;
                    444:            old_row += vs->ds->linesize;
                    445:        }
                    446: 
                    447:        if (!has_dirty) {
                    448:            qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
                    449:            return;
                    450:        }
                    451: 
                    452:        /* Count rectangles */
                    453:        n_rectangles = 0;
                    454:        vnc_write_u8(vs, 0);  /* msg id */
                    455:        vnc_write_u8(vs, 0);
                    456:        saved_offset = vs->output.offset;
                    457:        vnc_write_u16(vs, 0);
                    458: 
                    459:        for (y = 0; y < vs->height; y++) {
                    460:            int x;
                    461:            int last_x = -1;
                    462:            for (x = 0; x < vs->width / 16; x++) {
1.1.1.2   root      463:                if (vnc_get_bit(vs->dirty_row[y], x)) {
1.1       root      464:                    if (last_x == -1) {
                    465:                        last_x = x;
                    466:                    }
1.1.1.2   root      467:                    vnc_clear_bit(vs->dirty_row[y], x);
1.1       root      468:                } else {
                    469:                    if (last_x != -1) {
                    470:                        int h = find_dirty_height(vs, y, last_x, x);
                    471:                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
                    472:                        n_rectangles++;
                    473:                    }
                    474:                    last_x = -1;
                    475:                }
                    476:            }
                    477:            if (last_x != -1) {
                    478:                int h = find_dirty_height(vs, y, last_x, x);
                    479:                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
                    480:                n_rectangles++;
                    481:            }
                    482:        }
                    483:        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
                    484:        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
                    485:        vnc_flush(vs);
                    486: 
                    487:     }
                    488:     qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
                    489: }
                    490: 
                    491: static void vnc_timer_init(VncState *vs)
                    492: {
                    493:     if (vs->timer == NULL) {
                    494:        vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
                    495:        qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
                    496:     }
                    497: }
                    498: 
                    499: static void vnc_dpy_refresh(DisplayState *ds)
                    500: {
                    501:     VncState *vs = ds->opaque;
                    502:     vnc_timer_init(vs);
                    503:     vga_hw_update();
                    504: }
                    505: 
                    506: static int vnc_listen_poll(void *opaque)
                    507: {
                    508:     VncState *vs = opaque;
                    509:     if (vs->csock == -1)
                    510:        return 1;
                    511:     return 0;
                    512: }
                    513: 
                    514: static void buffer_reserve(Buffer *buffer, size_t len)
                    515: {
                    516:     if ((buffer->capacity - buffer->offset) < len) {
                    517:        buffer->capacity += (len + 1024);
                    518:        buffer->buffer = realloc(buffer->buffer, buffer->capacity);
                    519:        if (buffer->buffer == NULL) {
                    520:            fprintf(stderr, "vnc: out of memory\n");
                    521:            exit(1);
                    522:        }
                    523:     }
                    524: }
                    525: 
                    526: static int buffer_empty(Buffer *buffer)
                    527: {
                    528:     return buffer->offset == 0;
                    529: }
                    530: 
                    531: static char *buffer_end(Buffer *buffer)
                    532: {
                    533:     return buffer->buffer + buffer->offset;
                    534: }
                    535: 
                    536: static void buffer_reset(Buffer *buffer)
                    537: {
                    538:        buffer->offset = 0;
                    539: }
                    540: 
                    541: static void buffer_append(Buffer *buffer, const void *data, size_t len)
                    542: {
                    543:     memcpy(buffer->buffer + buffer->offset, data, len);
                    544:     buffer->offset += len;
                    545: }
                    546: 
                    547: static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
                    548: {
                    549:     if (ret == 0 || ret == -1) {
                    550:        if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
                    551:            return 0;
                    552: 
                    553:        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
                    554:        closesocket(vs->csock);
                    555:        vs->csock = -1;
                    556:        buffer_reset(&vs->input);
                    557:        buffer_reset(&vs->output);
                    558:        vs->need_update = 0;
                    559:        return 0;
                    560:     }
                    561:     return ret;
                    562: }
                    563: 
                    564: static void vnc_client_error(VncState *vs)
                    565: {
                    566:     vnc_client_io_error(vs, -1, EINVAL);
                    567: }
                    568: 
                    569: static void vnc_client_write(void *opaque)
                    570: {
1.1.1.2   root      571:     long ret;
1.1       root      572:     VncState *vs = opaque;
                    573: 
                    574:     ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
                    575:     ret = vnc_client_io_error(vs, ret, socket_error());
                    576:     if (!ret)
                    577:        return;
                    578: 
                    579:     memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
                    580:     vs->output.offset -= ret;
                    581: 
                    582:     if (vs->output.offset == 0) {
                    583:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
                    584:     }
                    585: }
                    586: 
                    587: static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
                    588: {
                    589:     vs->read_handler = func;
                    590:     vs->read_handler_expect = expecting;
                    591: }
                    592: 
                    593: static void vnc_client_read(void *opaque)
                    594: {
                    595:     VncState *vs = opaque;
1.1.1.2   root      596:     long ret;
1.1       root      597: 
                    598:     buffer_reserve(&vs->input, 4096);
                    599: 
                    600:     ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
                    601:     ret = vnc_client_io_error(vs, ret, socket_error());
                    602:     if (!ret)
                    603:        return;
                    604: 
                    605:     vs->input.offset += ret;
                    606: 
                    607:     while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
                    608:        size_t len = vs->read_handler_expect;
                    609:        int ret;
                    610: 
                    611:        ret = vs->read_handler(vs, vs->input.buffer, len);
                    612:        if (vs->csock == -1)
                    613:            return;
                    614: 
                    615:        if (!ret) {
                    616:            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
                    617:            vs->input.offset -= len;
                    618:        } else {
                    619:            vs->read_handler_expect = ret;
                    620:        }
                    621:     }
                    622: }
                    623: 
                    624: static void vnc_write(VncState *vs, const void *data, size_t len)
                    625: {
                    626:     buffer_reserve(&vs->output, len);
                    627: 
                    628:     if (buffer_empty(&vs->output)) {
                    629:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
                    630:     }
                    631: 
                    632:     buffer_append(&vs->output, data, len);
                    633: }
                    634: 
                    635: static void vnc_write_s32(VncState *vs, int32_t value)
                    636: {
                    637:     vnc_write_u32(vs, *(uint32_t *)&value);
                    638: }
                    639: 
                    640: static void vnc_write_u32(VncState *vs, uint32_t value)
                    641: {
                    642:     uint8_t buf[4];
                    643: 
                    644:     buf[0] = (value >> 24) & 0xFF;
                    645:     buf[1] = (value >> 16) & 0xFF;
                    646:     buf[2] = (value >>  8) & 0xFF;
                    647:     buf[3] = value & 0xFF;
                    648: 
                    649:     vnc_write(vs, buf, 4);
                    650: }
                    651: 
                    652: static void vnc_write_u16(VncState *vs, uint16_t value)
                    653: {
1.1.1.3 ! root      654:     uint8_t buf[2];
1.1       root      655: 
                    656:     buf[0] = (value >> 8) & 0xFF;
                    657:     buf[1] = value & 0xFF;
                    658: 
                    659:     vnc_write(vs, buf, 2);
                    660: }
                    661: 
                    662: static void vnc_write_u8(VncState *vs, uint8_t value)
                    663: {
                    664:     vnc_write(vs, (char *)&value, 1);
                    665: }
                    666: 
                    667: static void vnc_flush(VncState *vs)
                    668: {
                    669:     if (vs->output.offset)
                    670:        vnc_client_write(vs);
                    671: }
                    672: 
1.1.1.3 ! root      673: static uint8_t read_u8(uint8_t *data, size_t offset)
1.1       root      674: {
                    675:     return data[offset];
                    676: }
                    677: 
1.1.1.3 ! root      678: static uint16_t read_u16(uint8_t *data, size_t offset)
1.1       root      679: {
                    680:     return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
                    681: }
                    682: 
1.1.1.3 ! root      683: static int32_t read_s32(uint8_t *data, size_t offset)
1.1       root      684: {
                    685:     return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
                    686:                     (data[offset + 2] << 8) | data[offset + 3]);
                    687: }
                    688: 
1.1.1.3 ! root      689: static uint32_t read_u32(uint8_t *data, size_t offset)
1.1       root      690: {
                    691:     return ((data[offset] << 24) | (data[offset + 1] << 16) |
                    692:            (data[offset + 2] << 8) | data[offset + 3]);
                    693: }
                    694: 
                    695: static void client_cut_text(VncState *vs, size_t len, char *text)
                    696: {
                    697: }
                    698: 
1.1.1.3 ! root      699: static void check_pointer_type_change(VncState *vs, int absolute)
        !           700: {
        !           701:     if (vs->has_pointer_type_change && vs->absolute != absolute) {
        !           702:        vnc_write_u8(vs, 0);
        !           703:        vnc_write_u8(vs, 0);
        !           704:        vnc_write_u16(vs, 1);
        !           705:        vnc_framebuffer_update(vs, absolute, 0,
        !           706:                               vs->ds->width, vs->ds->height, -257);
        !           707:        vnc_flush(vs);
        !           708:     }
        !           709:     vs->absolute = absolute;
        !           710: }
        !           711: 
1.1       root      712: static void pointer_event(VncState *vs, int button_mask, int x, int y)
                    713: {
                    714:     int buttons = 0;
                    715:     int dz = 0;
                    716: 
                    717:     if (button_mask & 0x01)
                    718:        buttons |= MOUSE_EVENT_LBUTTON;
                    719:     if (button_mask & 0x02)
                    720:        buttons |= MOUSE_EVENT_MBUTTON;
                    721:     if (button_mask & 0x04)
                    722:        buttons |= MOUSE_EVENT_RBUTTON;
                    723:     if (button_mask & 0x08)
                    724:        dz = -1;
                    725:     if (button_mask & 0x10)
                    726:        dz = 1;
1.1.1.3 ! root      727: 
        !           728:     if (vs->absolute) {
1.1       root      729:        kbd_mouse_event(x * 0x7FFF / vs->ds->width,
                    730:                        y * 0x7FFF / vs->ds->height,
                    731:                        dz, buttons);
1.1.1.3 ! root      732:     } else if (vs->has_pointer_type_change) {
        !           733:        x -= 0x7FFF;
        !           734:        y -= 0x7FFF;
        !           735: 
        !           736:        kbd_mouse_event(x, y, dz, buttons);
1.1       root      737:     } else {
1.1.1.3 ! root      738:        if (vs->last_x != -1)
        !           739:            kbd_mouse_event(x - vs->last_x,
        !           740:                            y - vs->last_y,
        !           741:                            dz, buttons);
        !           742:        vs->last_x = x;
        !           743:        vs->last_y = y;
        !           744:     }
1.1       root      745: 
1.1.1.3 ! root      746:     check_pointer_type_change(vs, kbd_mouse_is_absolute());
        !           747: }
1.1       root      748: 
1.1.1.3 ! root      749: static void reset_keys(VncState *vs)
        !           750: {
        !           751:     int i;
        !           752:     for(i = 0; i < 256; i++) {
        !           753:         if (vs->modifiers_state[i]) {
        !           754:             if (i & 0x80)
        !           755:                 kbd_put_keycode(0xe0);
        !           756:             kbd_put_keycode(i | 0x80);
        !           757:             vs->modifiers_state[i] = 0;
        !           758:         }
1.1       root      759:     }
                    760: }
                    761: 
                    762: static void do_key_event(VncState *vs, int down, uint32_t sym)
                    763: {
                    764:     int keycode;
                    765: 
                    766:     keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
1.1.1.3 ! root      767:     
        !           768:     /* QEMU console switch */
        !           769:     switch(keycode) {
        !           770:     case 0x2a:                          /* Left Shift */
        !           771:     case 0x36:                          /* Right Shift */
        !           772:     case 0x1d:                          /* Left CTRL */
        !           773:     case 0x9d:                          /* Right CTRL */
        !           774:     case 0x38:                          /* Left ALT */
        !           775:     case 0xb8:                          /* Right ALT */
        !           776:         if (down)
        !           777:             vs->modifiers_state[keycode] = 1;
        !           778:         else
        !           779:             vs->modifiers_state[keycode] = 0;
        !           780:         break;
        !           781:     case 0x02 ... 0x0a: /* '1' to '9' keys */ 
        !           782:         if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
        !           783:             /* Reset the modifiers sent to the current console */
        !           784:             reset_keys(vs);
        !           785:             console_select(keycode - 0x02);
        !           786:             return;
        !           787:         }
        !           788:         break;
        !           789:     }
1.1       root      790: 
1.1.1.3 ! root      791:     if (is_graphic_console()) {
        !           792:         if (keycode & 0x80)
        !           793:             kbd_put_keycode(0xe0);
        !           794:         if (down)
        !           795:             kbd_put_keycode(keycode & 0x7f);
        !           796:         else
        !           797:             kbd_put_keycode(keycode | 0x80);
        !           798:     } else {
        !           799:         /* QEMU console emulation */
        !           800:         if (down) {
        !           801:             switch (keycode) {
        !           802:             case 0x2a:                          /* Left Shift */
        !           803:             case 0x36:                          /* Right Shift */
        !           804:             case 0x1d:                          /* Left CTRL */
        !           805:             case 0x9d:                          /* Right CTRL */
        !           806:             case 0x38:                          /* Left ALT */
        !           807:             case 0xb8:                          /* Right ALT */
        !           808:                 break;
        !           809:             case 0xc8:
        !           810:                 kbd_put_keysym(QEMU_KEY_UP);
        !           811:                 break;
        !           812:             case 0xd0:
        !           813:                 kbd_put_keysym(QEMU_KEY_DOWN);
        !           814:                 break;
        !           815:             case 0xcb:
        !           816:                 kbd_put_keysym(QEMU_KEY_LEFT);
        !           817:                 break;
        !           818:             case 0xcd:
        !           819:                 kbd_put_keysym(QEMU_KEY_RIGHT);
        !           820:                 break;
        !           821:             case 0xd3:
        !           822:                 kbd_put_keysym(QEMU_KEY_DELETE);
        !           823:                 break;
        !           824:             case 0xc7:
        !           825:                 kbd_put_keysym(QEMU_KEY_HOME);
        !           826:                 break;
        !           827:             case 0xcf:
        !           828:                 kbd_put_keysym(QEMU_KEY_END);
        !           829:                 break;
        !           830:             case 0xc9:
        !           831:                 kbd_put_keysym(QEMU_KEY_PAGEUP);
        !           832:                 break;
        !           833:             case 0xd1:
        !           834:                 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
        !           835:                 break;
        !           836:             default:
        !           837:                 kbd_put_keysym(sym);
        !           838:                 break;
        !           839:             }
        !           840:         }
        !           841:     }
1.1       root      842: }
                    843: 
                    844: static void key_event(VncState *vs, int down, uint32_t sym)
                    845: {
                    846:     if (sym >= 'A' && sym <= 'Z')
                    847:        sym = sym - 'A' + 'a';
                    848:     do_key_event(vs, down, sym);
                    849: }
                    850: 
                    851: static void framebuffer_update_request(VncState *vs, int incremental,
                    852:                                       int x_position, int y_position,
                    853:                                       int w, int h)
                    854: {
                    855:     int i;
                    856:     vs->need_update = 1;
                    857:     if (!incremental) {
                    858:        char *old_row = vs->old_data + y_position * vs->ds->linesize;
                    859: 
                    860:        for (i = 0; i < h; i++) {
1.1.1.2   root      861:             vnc_set_bits(vs->dirty_row[y_position + i], 
                    862:                          (vs->ds->width / 16), VNC_DIRTY_WORDS);
1.1       root      863:            memset(old_row, 42, vs->ds->width * vs->depth);
                    864:            old_row += vs->ds->linesize;
                    865:        }
                    866:     }
                    867: }
                    868: 
                    869: static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
                    870: {
                    871:     int i;
                    872: 
                    873:     vs->has_hextile = 0;
                    874:     vs->has_resize = 0;
1.1.1.3 ! root      875:     vs->has_pointer_type_change = 0;
        !           876:     vs->absolute = -1;
1.1       root      877:     vs->ds->dpy_copy = NULL;
                    878: 
                    879:     for (i = n_encodings - 1; i >= 0; i--) {
                    880:        switch (encodings[i]) {
                    881:        case 0: /* Raw */
                    882:            vs->has_hextile = 0;
                    883:            break;
                    884:        case 1: /* CopyRect */
                    885:            vs->ds->dpy_copy = vnc_copy;
                    886:            break;
                    887:        case 5: /* Hextile */
                    888:            vs->has_hextile = 1;
                    889:            break;
                    890:        case -223: /* DesktopResize */
                    891:            vs->has_resize = 1;
                    892:            break;
1.1.1.3 ! root      893:        case -257:
        !           894:            vs->has_pointer_type_change = 1;
        !           895:            break;
1.1       root      896:        default:
                    897:            break;
                    898:        }
                    899:     }
1.1.1.3 ! root      900: 
        !           901:     check_pointer_type_change(vs, kbd_mouse_is_absolute());
1.1       root      902: }
                    903: 
1.1.1.2   root      904: static int compute_nbits(unsigned int val)
                    905: {
                    906:     int n;
                    907:     n = 0;
                    908:     while (val != 0) {
                    909:         n++;
                    910:         val >>= 1;
                    911:     }
                    912:     return n;
                    913: }
                    914: 
1.1       root      915: static void set_pixel_format(VncState *vs,
                    916:                             int bits_per_pixel, int depth,
                    917:                             int big_endian_flag, int true_color_flag,
                    918:                             int red_max, int green_max, int blue_max,
                    919:                             int red_shift, int green_shift, int blue_shift)
                    920: {
1.1.1.2   root      921:     int host_big_endian_flag;
1.1       root      922: 
1.1.1.2   root      923: #ifdef WORDS_BIGENDIAN
                    924:     host_big_endian_flag = 1;
                    925: #else
                    926:     host_big_endian_flag = 0;
                    927: #endif
                    928:     if (!true_color_flag) {
                    929:     fail:
1.1       root      930:        vnc_client_error(vs);
1.1.1.2   root      931:         return;
                    932:     }
                    933:     if (bits_per_pixel == 32 && 
                    934:         host_big_endian_flag == big_endian_flag &&
                    935:         red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
                    936:         red_shift == 16 && green_shift == 8 && blue_shift == 0) {
                    937:         vs->depth = 4;
                    938:         vs->write_pixels = vnc_write_pixels_copy;
                    939:         vs->send_hextile_tile = send_hextile_tile_32;
                    940:     } else 
                    941:     if (bits_per_pixel == 16 && 
                    942:         host_big_endian_flag == big_endian_flag &&
                    943:         red_max == 31 && green_max == 63 && blue_max == 31 &&
                    944:         red_shift == 11 && green_shift == 5 && blue_shift == 0) {
                    945:         vs->depth = 2;
                    946:         vs->write_pixels = vnc_write_pixels_copy;
                    947:         vs->send_hextile_tile = send_hextile_tile_16;
                    948:     } else 
                    949:     if (bits_per_pixel == 8 && 
                    950:         red_max == 7 && green_max == 7 && blue_max == 3 &&
                    951:         red_shift == 5 && green_shift == 2 && blue_shift == 0) {
                    952:         vs->depth = 1;
                    953:         vs->write_pixels = vnc_write_pixels_copy;
                    954:         vs->send_hextile_tile = send_hextile_tile_8;
                    955:     } else 
                    956:     {
                    957:         /* generic and slower case */
                    958:         if (bits_per_pixel != 8 &&
                    959:             bits_per_pixel != 16 &&
                    960:             bits_per_pixel != 32)
                    961:             goto fail;
                    962:         vs->depth = 4;
                    963:         vs->red_shift = red_shift;
                    964:         vs->red_max = red_max;
                    965:         vs->red_shift1 = 24 - compute_nbits(red_max);
                    966:         vs->green_shift = green_shift;
                    967:         vs->green_max = green_max;
                    968:         vs->green_shift1 = 16 - compute_nbits(green_max);
                    969:         vs->blue_shift = blue_shift;
                    970:         vs->blue_max = blue_max;
                    971:         vs->blue_shift1 = 8 - compute_nbits(blue_max);
                    972:         vs->pix_bpp = bits_per_pixel / 8;
                    973:         vs->pix_big_endian = big_endian_flag;
                    974:         vs->write_pixels = vnc_write_pixels_generic;
                    975:         vs->send_hextile_tile = send_hextile_tile_generic;
                    976:     }
1.1       root      977: 
                    978:     vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
                    979:     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
                    980:     memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height);
                    981: 
                    982:     vga_hw_invalidate();
                    983:     vga_hw_update();
                    984: }
                    985: 
                    986: static int protocol_client_msg(VncState *vs, char *data, size_t len)
                    987: {
                    988:     int i;
                    989:     uint16_t limit;
                    990: 
                    991:     switch (data[0]) {
                    992:     case 0:
                    993:        if (len == 1)
                    994:            return 20;
                    995: 
                    996:        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
                    997:                         read_u8(data, 6), read_u8(data, 7),
                    998:                         read_u16(data, 8), read_u16(data, 10),
                    999:                         read_u16(data, 12), read_u8(data, 14),
                   1000:                         read_u8(data, 15), read_u8(data, 16));
                   1001:        break;
                   1002:     case 2:
                   1003:        if (len == 1)
                   1004:            return 4;
                   1005: 
                   1006:        if (len == 4)
                   1007:            return 4 + (read_u16(data, 2) * 4);
                   1008: 
                   1009:        limit = read_u16(data, 2);
                   1010:        for (i = 0; i < limit; i++) {
                   1011:            int32_t val = read_s32(data, 4 + (i * 4));
                   1012:            memcpy(data + 4 + (i * 4), &val, sizeof(val));
                   1013:        }
                   1014: 
                   1015:        set_encodings(vs, (int32_t *)(data + 4), limit);
                   1016:        break;
                   1017:     case 3:
                   1018:        if (len == 1)
                   1019:            return 10;
                   1020: 
                   1021:        framebuffer_update_request(vs,
                   1022:                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
                   1023:                                   read_u16(data, 6), read_u16(data, 8));
                   1024:        break;
                   1025:     case 4:
                   1026:        if (len == 1)
                   1027:            return 8;
                   1028: 
                   1029:        key_event(vs, read_u8(data, 1), read_u32(data, 4));
                   1030:        break;
                   1031:     case 5:
                   1032:        if (len == 1)
                   1033:            return 6;
                   1034: 
                   1035:        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
                   1036:        break;
                   1037:     case 6:
                   1038:        if (len == 1)
                   1039:            return 8;
                   1040: 
                   1041:        if (len == 8)
                   1042:            return 8 + read_u32(data, 4);
                   1043: 
                   1044:        client_cut_text(vs, read_u32(data, 4), data + 8);
                   1045:        break;
                   1046:     default:
                   1047:        printf("Msg: %d\n", data[0]);
                   1048:        vnc_client_error(vs);
                   1049:        break;
                   1050:     }
                   1051:        
                   1052:     vnc_read_when(vs, protocol_client_msg, 1);
                   1053:     return 0;
                   1054: }
                   1055: 
                   1056: static int protocol_client_init(VncState *vs, char *data, size_t len)
                   1057: {
                   1058:     char pad[3] = { 0, 0, 0 };
                   1059: 
                   1060:     vs->width = vs->ds->width;
                   1061:     vs->height = vs->ds->height;
                   1062:     vnc_write_u16(vs, vs->ds->width);
                   1063:     vnc_write_u16(vs, vs->ds->height);
                   1064: 
                   1065:     vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
                   1066:     vnc_write_u8(vs, vs->depth * 8); /* depth */
1.1.1.2   root     1067: #ifdef WORDS_BIGENDIAN
                   1068:     vnc_write_u8(vs, 1);             /* big-endian-flag */
                   1069: #else
1.1       root     1070:     vnc_write_u8(vs, 0);             /* big-endian-flag */
1.1.1.2   root     1071: #endif
1.1       root     1072:     vnc_write_u8(vs, 1);             /* true-color-flag */
                   1073:     if (vs->depth == 4) {
                   1074:        vnc_write_u16(vs, 0xFF);     /* red-max */
                   1075:        vnc_write_u16(vs, 0xFF);     /* green-max */
                   1076:        vnc_write_u16(vs, 0xFF);     /* blue-max */
                   1077:        vnc_write_u8(vs, 16);        /* red-shift */
                   1078:        vnc_write_u8(vs, 8);         /* green-shift */
                   1079:        vnc_write_u8(vs, 0);         /* blue-shift */
1.1.1.2   root     1080:         vs->send_hextile_tile = send_hextile_tile_32;
1.1       root     1081:     } else if (vs->depth == 2) {
                   1082:        vnc_write_u16(vs, 31);       /* red-max */
                   1083:        vnc_write_u16(vs, 63);       /* green-max */
                   1084:        vnc_write_u16(vs, 31);       /* blue-max */
                   1085:        vnc_write_u8(vs, 11);        /* red-shift */
                   1086:        vnc_write_u8(vs, 5);         /* green-shift */
                   1087:        vnc_write_u8(vs, 0);         /* blue-shift */
1.1.1.2   root     1088:         vs->send_hextile_tile = send_hextile_tile_16;
1.1       root     1089:     } else if (vs->depth == 1) {
1.1.1.2   root     1090:         /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
                   1091:        vnc_write_u16(vs, 7);        /* red-max */
1.1       root     1092:        vnc_write_u16(vs, 7);        /* green-max */
                   1093:        vnc_write_u16(vs, 3);        /* blue-max */
                   1094:        vnc_write_u8(vs, 5);         /* red-shift */
                   1095:        vnc_write_u8(vs, 2);         /* green-shift */
                   1096:        vnc_write_u8(vs, 0);         /* blue-shift */
1.1.1.2   root     1097:         vs->send_hextile_tile = send_hextile_tile_8;
1.1       root     1098:     }
1.1.1.2   root     1099:     vs->write_pixels = vnc_write_pixels_copy;
1.1       root     1100:        
                   1101:     vnc_write(vs, pad, 3);           /* padding */
                   1102: 
                   1103:     vnc_write_u32(vs, 4);        
                   1104:     vnc_write(vs, "QEMU", 4);
                   1105:     vnc_flush(vs);
                   1106: 
                   1107:     vnc_read_when(vs, protocol_client_msg, 1);
                   1108: 
                   1109:     return 0;
                   1110: }
                   1111: 
                   1112: static int protocol_version(VncState *vs, char *version, size_t len)
                   1113: {
                   1114:     char local[13];
                   1115:     int maj, min;
                   1116: 
                   1117:     memcpy(local, version, 12);
                   1118:     local[12] = 0;
                   1119: 
                   1120:     if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
                   1121:        vnc_client_error(vs);
                   1122:        return 0;
                   1123:     }
                   1124: 
                   1125:     vnc_write_u32(vs, 1); /* None */
                   1126:     vnc_flush(vs);
                   1127: 
                   1128:     vnc_read_when(vs, protocol_client_init, 1);
                   1129: 
                   1130:     return 0;
                   1131: }
                   1132: 
                   1133: static void vnc_listen_read(void *opaque)
                   1134: {
                   1135:     VncState *vs = opaque;
                   1136:     struct sockaddr_in addr;
                   1137:     socklen_t addrlen = sizeof(addr);
                   1138: 
                   1139:     vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
                   1140:     if (vs->csock != -1) {
                   1141:         socket_set_nonblock(vs->csock);
                   1142:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
                   1143:        vnc_write(vs, "RFB 003.003\n", 12);
                   1144:        vnc_flush(vs);
                   1145:        vnc_read_when(vs, protocol_version, 12);
                   1146:        memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
                   1147:        memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
                   1148:        vs->has_resize = 0;
                   1149:        vs->has_hextile = 0;
                   1150:        vs->ds->dpy_copy = NULL;
                   1151:     }
                   1152: }
                   1153: 
1.1.1.3 ! root     1154: extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
        !          1155: 
        !          1156: void vnc_display_init(DisplayState *ds, const char *arg)
1.1       root     1157: {
1.1.1.3 ! root     1158:     struct sockaddr *addr;
        !          1159:     struct sockaddr_in iaddr;
        !          1160: #ifndef _WIN32
        !          1161:     struct sockaddr_un uaddr;
        !          1162: #endif
1.1       root     1163:     int reuse_addr, ret;
1.1.1.3 ! root     1164:     socklen_t addrlen;
        !          1165:     const char *p;
1.1       root     1166:     VncState *vs;
                   1167: 
                   1168:     vs = qemu_mallocz(sizeof(VncState));
                   1169:     if (!vs)
                   1170:        exit(1);
                   1171: 
                   1172:     ds->opaque = vs;
1.1.1.3 ! root     1173:     vnc_state = vs;
        !          1174:     vs->display = arg;
1.1       root     1175: 
                   1176:     vs->lsock = -1;
                   1177:     vs->csock = -1;
                   1178:     vs->depth = 4;
1.1.1.3 ! root     1179:     vs->last_x = -1;
        !          1180:     vs->last_y = -1;
1.1       root     1181: 
                   1182:     vs->ds = ds;
                   1183: 
                   1184:     if (!keyboard_layout)
                   1185:        keyboard_layout = "en-us";
                   1186: 
                   1187:     vs->kbd_layout = init_keyboard_layout(keyboard_layout);
                   1188:     if (!vs->kbd_layout)
                   1189:        exit(1);
                   1190: 
1.1.1.3 ! root     1191:     vs->ds->data = NULL;
        !          1192:     vs->ds->dpy_update = vnc_dpy_update;
        !          1193:     vs->ds->dpy_resize = vnc_dpy_resize;
        !          1194:     vs->ds->dpy_refresh = vnc_dpy_refresh;
1.1       root     1195: 
1.1.1.3 ! root     1196:     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
        !          1197: 
        !          1198:     vnc_dpy_resize(vs->ds, 640, 400);
        !          1199: 
        !          1200: #ifndef _WIN32
        !          1201:     if (strstart(arg, "unix:", &p)) {
        !          1202:        addr = (struct sockaddr *)&uaddr;
        !          1203:        addrlen = sizeof(uaddr);
        !          1204: 
        !          1205:        vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
        !          1206:        if (vs->lsock == -1) {
        !          1207:            fprintf(stderr, "Could not create socket\n");
        !          1208:            exit(1);
        !          1209:        }
        !          1210: 
        !          1211:        uaddr.sun_family = AF_UNIX;
        !          1212:        memset(uaddr.sun_path, 0, 108);
        !          1213:        snprintf(uaddr.sun_path, 108, "%s", p);
        !          1214: 
        !          1215:        unlink(uaddr.sun_path);
        !          1216:     } else
        !          1217: #endif
        !          1218:     {
        !          1219:        addr = (struct sockaddr *)&iaddr;
        !          1220:        addrlen = sizeof(iaddr);
        !          1221: 
        !          1222:        vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
        !          1223:        if (vs->lsock == -1) {
        !          1224:            fprintf(stderr, "Could not create socket\n");
        !          1225:            exit(1);
        !          1226:        }
        !          1227: 
        !          1228:        if (parse_host_port(&iaddr, arg) < 0) {
        !          1229:            fprintf(stderr, "Could not parse VNC address\n");
        !          1230:            exit(1);
        !          1231:        }
        !          1232:            
        !          1233:        iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
        !          1234: 
        !          1235:        reuse_addr = 1;
        !          1236:        ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
        !          1237:                         (const char *)&reuse_addr, sizeof(reuse_addr));
        !          1238:        if (ret == -1) {
        !          1239:            fprintf(stderr, "setsockopt() failed\n");
        !          1240:            exit(1);
        !          1241:        }
1.1       root     1242:     }
                   1243: 
1.1.1.3 ! root     1244:     if (bind(vs->lsock, addr, addrlen) == -1) {
1.1       root     1245:        fprintf(stderr, "bind() failed\n");
                   1246:        exit(1);
                   1247:     }
                   1248: 
                   1249:     if (listen(vs->lsock, 1) == -1) {
                   1250:        fprintf(stderr, "listen() failed\n");
                   1251:        exit(1);
                   1252:     }
                   1253: 
                   1254:     ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
                   1255:     if (ret == -1) {
                   1256:        exit(1);
                   1257:     }
                   1258: }

unix.superglobalmegacorp.com