Statistics
| Branch: | Revision:

root / vnc.c @ 6ca957f0

History | View | Annotate | Download (20.1 kB)

1
#include "vl.h"
2
#include "qemu_socket.h"
3

    
4
#define VNC_REFRESH_INTERVAL (1000 / 30)
5

    
6
#include "vnc_keysym.h"
7
#include "keymaps.c"
8

    
9
typedef struct Buffer
10
{
11
    size_t capacity;
12
    size_t offset;
13
    char *buffer;
14
} Buffer;
15

    
16
typedef struct VncState VncState;
17

    
18
typedef int VncReadEvent(VncState *vs, char *data, size_t len);
19

    
20
struct VncState
21
{
22
    QEMUTimer *timer;
23
    int lsock;
24
    int csock;
25
    DisplayState *ds;
26
    int need_update;
27
    int width;
28
    int height;
29
    uint64_t dirty_row[768];
30
    char *old_data;
31
    int depth;
32
    int has_resize;
33
    int has_hextile;
34
    Buffer output;
35
    Buffer input;
36
    kbd_layout_t *kbd_layout;
37

    
38
    VncReadEvent *read_handler;
39
    size_t read_handler_expect;
40
};
41

    
42
/* TODO
43
   1) Get the queue working for IO.
44
   2) there is some weirdness when using the -S option (the screen is grey
45
      and not totally invalidated
46
   3) resolutions > 1024
47
*/
48

    
49
static void vnc_write(VncState *vs, const void *data, size_t len);
50
static void vnc_write_u32(VncState *vs, uint32_t value);
51
static void vnc_write_s32(VncState *vs, int32_t value);
52
static void vnc_write_u16(VncState *vs, uint16_t value);
53
static void vnc_write_u8(VncState *vs, uint8_t value);
54
static void vnc_flush(VncState *vs);
55
static void vnc_update_client(void *opaque);
56
static void vnc_client_read(void *opaque);
57

    
58
static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
59
{
60
    VncState *vs = ds->opaque;
61
    int i;
62

    
63
    h += y;
64

    
65
    for (; y < h; y++)
66
        for (i = 0; i < w; i += 16)
67
            vs->dirty_row[y] |= (1ULL << ((x + i) / 16));
68
}
69

    
70
static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
71
                                   int32_t encoding)
72
{
73
    vnc_write_u16(vs, x);
74
    vnc_write_u16(vs, y);
75
    vnc_write_u16(vs, w);
76
    vnc_write_u16(vs, h);
77

    
78
    vnc_write_s32(vs, encoding);
79
}
80

    
81
static void vnc_dpy_resize(DisplayState *ds, int w, int h)
82
{
83
    VncState *vs = ds->opaque;
84

    
85
    ds->data = realloc(ds->data, w * h * vs->depth);
86
    vs->old_data = realloc(vs->old_data, w * h * vs->depth);
87

    
88
    if (ds->data == NULL || vs->old_data == NULL) {
89
        fprintf(stderr, "vnc: memory allocation failed\n");
90
        exit(1);
91
    }
92

    
93
    ds->depth = vs->depth * 8;
94
    ds->width = w;
95
    ds->height = h;
96
    ds->linesize = w * vs->depth;
97
    if (vs->csock != -1 && vs->has_resize) {
98
        vnc_write_u8(vs, 0);  /* msg id */
99
        vnc_write_u8(vs, 0);
100
        vnc_write_u16(vs, 1); /* number of rects */
101
        vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
102
        vnc_flush(vs);
103
        vs->width = ds->width;
104
        vs->height = ds->height;
105
    }
106
}
107

    
108
static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
109
{
110
    int i;
111
    char *row;
112

    
113
    vnc_framebuffer_update(vs, x, y, w, h, 0);
114

    
115
    row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
116
    for (i = 0; i < h; i++) {
117
        vnc_write(vs, row, w * vs->depth);
118
        row += vs->ds->linesize;
119
    }
120
}
121

    
122
static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
123
{
124
    ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
125
    ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
126
}
127

    
128
#define BPP 8
129
#include "vnchextile.h"
130
#undef BPP
131

    
132
#define BPP 16
133
#include "vnchextile.h"
134
#undef BPP
135

    
136
#define BPP 32
137
#include "vnchextile.h"
138
#undef BPP
139

    
140
static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
141
{
142
    int i, j;
143
    int has_fg, has_bg;
144
    uint32_t last_fg32, last_bg32;
145
    uint16_t last_fg16, last_bg16;
146
    uint8_t last_fg8, last_bg8;
147

    
148
    vnc_framebuffer_update(vs, x, y, w, h, 5);
149

    
150
    has_fg = has_bg = 0;
151
    for (j = y; j < (y + h); j += 16) {
152
        for (i = x; i < (x + w); i += 16) {
153
            switch (vs->depth) {
154
            case 1:
155
                send_hextile_tile_8(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
156
                                    &last_bg8, &last_fg8, &has_bg, &has_fg);
157
                break;
158
            case 2:
159
                send_hextile_tile_16(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
160
                                     &last_bg16, &last_fg16, &has_bg, &has_fg);
161
                break;
162
            case 4:
163
                send_hextile_tile_32(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
164
                                     &last_bg32, &last_fg32, &has_bg, &has_fg);
165
                break;
166
            default:
167
                break;
168
            }
169
        }
170
    }
171
}
172

    
173
static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
174
{
175
        if (vs->has_hextile)
176
            send_framebuffer_update_hextile(vs, x, y, w, h);
177
        else
178
            send_framebuffer_update_raw(vs, x, y, w, h);
179
}
180

    
181
static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
182
{
183
    int src, dst;
184
    char *src_row;
185
    char *dst_row;
186
    char *old_row;
187
    int y = 0;
188
    int pitch = ds->linesize;
189
    VncState *vs = ds->opaque;
190

    
191
    vnc_update_client(vs);
192

    
193
    if (dst_y > src_y) {
194
        y = h - 1;
195
        pitch = -pitch;
196
    }
197

    
198
    src = (ds->linesize * (src_y + y) + vs->depth * src_x);
199
    dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
200

    
201
    src_row = ds->data + src;
202
    dst_row = ds->data + dst;
203
    old_row = vs->old_data + dst;
204

    
205
    for (y = 0; y < h; y++) {
206
        memmove(old_row, src_row, w * vs->depth);
207
        memmove(dst_row, src_row, w * vs->depth);
208
        src_row += pitch;
209
        dst_row += pitch;
210
        old_row += pitch;
211
    }
212

    
213
    vnc_write_u8(vs, 0);  /* msg id */
214
    vnc_write_u8(vs, 0);
215
    vnc_write_u16(vs, 1); /* number of rects */
216
    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
217
    vnc_write_u16(vs, src_x);
218
    vnc_write_u16(vs, src_y);
219
    vnc_flush(vs);
220
}
221

    
222
static int find_dirty_height(VncState *vs, int y, int last_x, int x)
223
{
224
    int h;
225

    
226
    for (h = 1; h < (vs->height - y); h++) {
227
        int tmp_x;
228
        if (!(vs->dirty_row[y + h] & (1ULL << last_x)))
229
            break;
230
        for (tmp_x = last_x; tmp_x < x; tmp_x++)
231
            vs->dirty_row[y + h] &= ~(1ULL << tmp_x);
232
    }
233

    
234
    return h;
235
}
236

    
237
static void vnc_update_client(void *opaque)
238
{
239
    VncState *vs = opaque;
240

    
241
    if (vs->need_update && vs->csock != -1) {
242
        int y;
243
        char *row;
244
        char *old_row;
245
        uint64_t width_mask;
246
        int n_rectangles;
247
        int saved_offset;
248
        int has_dirty = 0;
249

    
250
        width_mask = (1ULL << (vs->width / 16)) - 1;
251

    
252
        if (vs->width == 1024)
253
            width_mask = ~(0ULL);
254

    
255
        /* Walk through the dirty map and eliminate tiles that
256
           really aren't dirty */
257
        row = vs->ds->data;
258
        old_row = vs->old_data;
259

    
260
        for (y = 0; y < vs->height; y++) {
261
            if (vs->dirty_row[y] & width_mask) {
262
                int x;
263
                char *ptr, *old_ptr;
264

    
265
                ptr = row;
266
                old_ptr = old_row;
267

    
268
                for (x = 0; x < vs->ds->width; x += 16) {
269
                    if (memcmp(old_ptr, ptr, 16 * vs->depth) == 0) {
270
                        vs->dirty_row[y] &= ~(1ULL << (x / 16));
271
                    } else {
272
                        has_dirty = 1;
273
                        memcpy(old_ptr, ptr, 16 * vs->depth);
274
                    }
275

    
276
                    ptr += 16 * vs->depth;
277
                    old_ptr += 16 * vs->depth;
278
                }
279
            }
280

    
281
            row += vs->ds->linesize;
282
            old_row += vs->ds->linesize;
283
        }
284

    
285
        if (!has_dirty) {
286
            qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
287
            return;
288
        }
289

    
290
        /* Count rectangles */
291
        n_rectangles = 0;
292
        vnc_write_u8(vs, 0);  /* msg id */
293
        vnc_write_u8(vs, 0);
294
        saved_offset = vs->output.offset;
295
        vnc_write_u16(vs, 0);
296

    
297
        for (y = 0; y < vs->height; y++) {
298
            int x;
299
            int last_x = -1;
300
            for (x = 0; x < vs->width / 16; x++) {
301
                if (vs->dirty_row[y] & (1ULL << x)) {
302
                    if (last_x == -1) {
303
                        last_x = x;
304
                    }
305
                    vs->dirty_row[y] &= ~(1ULL << x);
306
                } else {
307
                    if (last_x != -1) {
308
                        int h = find_dirty_height(vs, y, last_x, x);
309
                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
310
                        n_rectangles++;
311
                    }
312
                    last_x = -1;
313
                }
314
            }
315
            if (last_x != -1) {
316
                int h = find_dirty_height(vs, y, last_x, x);
317
                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
318
                n_rectangles++;
319
            }
320
        }
321
        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
322
        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
323
        vnc_flush(vs);
324

    
325
    }
326
    qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
327
}
328

    
329
static void vnc_timer_init(VncState *vs)
330
{
331
    if (vs->timer == NULL) {
332
        vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
333
        qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
334
    }
335
}
336

    
337
static void vnc_dpy_refresh(DisplayState *ds)
338
{
339
    VncState *vs = ds->opaque;
340
    vnc_timer_init(vs);
341
    vga_hw_update();
342
}
343

    
344
static int vnc_listen_poll(void *opaque)
345
{
346
    VncState *vs = opaque;
347
    if (vs->csock == -1)
348
        return 1;
349
    return 0;
350
}
351

    
352
static void buffer_reserve(Buffer *buffer, size_t len)
353
{
354
    if ((buffer->capacity - buffer->offset) < len) {
355
        buffer->capacity += (len + 1024);
356
        buffer->buffer = realloc(buffer->buffer, buffer->capacity);
357
        if (buffer->buffer == NULL) {
358
            fprintf(stderr, "vnc: out of memory\n");
359
            exit(1);
360
        }
361
    }
362
}
363

    
364
static int buffer_empty(Buffer *buffer)
365
{
366
    return buffer->offset == 0;
367
}
368

    
369
static char *buffer_end(Buffer *buffer)
370
{
371
    return buffer->buffer + buffer->offset;
372
}
373

    
374
static void buffer_reset(Buffer *buffer)
375
{
376
        buffer->offset = 0;
377
}
378

    
379
static void buffer_append(Buffer *buffer, const void *data, size_t len)
380
{
381
    memcpy(buffer->buffer + buffer->offset, data, len);
382
    buffer->offset += len;
383
}
384

    
385
static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
386
{
387
    if (ret == 0 || ret == -1) {
388
        if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
389
            return 0;
390

    
391
        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
392
        closesocket(vs->csock);
393
        vs->csock = -1;
394
        buffer_reset(&vs->input);
395
        buffer_reset(&vs->output);
396
        vs->need_update = 0;
397
        return 0;
398
    }
399
    return ret;
400
}
401

    
402
static void vnc_client_error(VncState *vs)
403
{
404
    vnc_client_io_error(vs, -1, EINVAL);
405
}
406

    
407
static void vnc_client_write(void *opaque)
408
{
409
    ssize_t ret;
410
    VncState *vs = opaque;
411

    
412
    ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
413
    ret = vnc_client_io_error(vs, ret, socket_error());
414
    if (!ret)
415
        return;
416

    
417
    memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
418
    vs->output.offset -= ret;
419

    
420
    if (vs->output.offset == 0) {
421
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
422
    }
423
}
424

    
425
static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
426
{
427
    vs->read_handler = func;
428
    vs->read_handler_expect = expecting;
429
}
430

    
431
static void vnc_client_read(void *opaque)
432
{
433
    VncState *vs = opaque;
434
    ssize_t ret;
435

    
436
    buffer_reserve(&vs->input, 4096);
437

    
438
    ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
439
    ret = vnc_client_io_error(vs, ret, socket_error());
440
    if (!ret)
441
        return;
442

    
443
    vs->input.offset += ret;
444

    
445
    while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
446
        size_t len = vs->read_handler_expect;
447
        int ret;
448

    
449
        ret = vs->read_handler(vs, vs->input.buffer, len);
450
        if (vs->csock == -1)
451
            return;
452

    
453
        if (!ret) {
454
            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
455
            vs->input.offset -= len;
456
        } else {
457
            vs->read_handler_expect = ret;
458
        }
459
    }
460
}
461

    
462
static void vnc_write(VncState *vs, const void *data, size_t len)
463
{
464
    buffer_reserve(&vs->output, len);
465

    
466
    if (buffer_empty(&vs->output)) {
467
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
468
    }
469

    
470
    buffer_append(&vs->output, data, len);
471
}
472

    
473
static void vnc_write_s32(VncState *vs, int32_t value)
474
{
475
    vnc_write_u32(vs, *(uint32_t *)&value);
476
}
477

    
478
static void vnc_write_u32(VncState *vs, uint32_t value)
479
{
480
    uint8_t buf[4];
481

    
482
    buf[0] = (value >> 24) & 0xFF;
483
    buf[1] = (value >> 16) & 0xFF;
484
    buf[2] = (value >>  8) & 0xFF;
485
    buf[3] = value & 0xFF;
486

    
487
    vnc_write(vs, buf, 4);
488
}
489

    
490
static void vnc_write_u16(VncState *vs, uint16_t value)
491
{
492
    char buf[2];
493

    
494
    buf[0] = (value >> 8) & 0xFF;
495
    buf[1] = value & 0xFF;
496

    
497
    vnc_write(vs, buf, 2);
498
}
499

    
500
static void vnc_write_u8(VncState *vs, uint8_t value)
501
{
502
    vnc_write(vs, (char *)&value, 1);
503
}
504

    
505
static void vnc_flush(VncState *vs)
506
{
507
    if (vs->output.offset)
508
        vnc_client_write(vs);
509
}
510

    
511
static uint8_t read_u8(char *data, size_t offset)
512
{
513
    return data[offset];
514
}
515

    
516
static uint16_t read_u16(char *data, size_t offset)
517
{
518
    return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
519
}
520

    
521
static int32_t read_s32(char *data, size_t offset)
522
{
523
    return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
524
                     (data[offset + 2] << 8) | data[offset + 3]);
525
}
526

    
527
static uint32_t read_u32(char *data, size_t offset)
528
{
529
    return ((data[offset] << 24) | (data[offset + 1] << 16) |
530
            (data[offset + 2] << 8) | data[offset + 3]);
531
}
532

    
533
static void client_cut_text(VncState *vs, size_t len, char *text)
534
{
535
}
536

    
537
static void pointer_event(VncState *vs, int button_mask, int x, int y)
538
{
539
    int buttons = 0;
540
    int dz = 0;
541

    
542
    if (button_mask & 0x01)
543
        buttons |= MOUSE_EVENT_LBUTTON;
544
    if (button_mask & 0x02)
545
        buttons |= MOUSE_EVENT_MBUTTON;
546
    if (button_mask & 0x04)
547
        buttons |= MOUSE_EVENT_RBUTTON;
548
    if (button_mask & 0x08)
549
        dz = -1;
550
    if (button_mask & 0x10)
551
        dz = 1;
552
            
553
    if (kbd_mouse_is_absolute()) {
554
        kbd_mouse_event(x * 0x7FFF / vs->ds->width,
555
                        y * 0x7FFF / vs->ds->height,
556
                        dz, buttons);
557
    } else {
558
        static int last_x = -1;
559
        static int last_y = -1;
560

    
561
        if (last_x != -1)
562
            kbd_mouse_event(x - last_x, y - last_y, dz, buttons);
563

    
564
        last_x = x;
565
        last_y = y;
566
    }
567
}
568

    
569
static void key_event(VncState *vs, int down, uint32_t sym)
570
{
571
    int keycode;
572

    
573
    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
574

    
575
    if (keycode & 0x80)
576
        kbd_put_keycode(0xe0);
577
    if (down)
578
        kbd_put_keycode(keycode & 0x7f);
579
    else
580
        kbd_put_keycode(keycode | 0x80);
581
}
582

    
583
static void framebuffer_update_request(VncState *vs, int incremental,
584
                                       int x_position, int y_position,
585
                                       int w, int h)
586
{
587
    int i;
588
    vs->need_update = 1;
589
    if (!incremental) {
590
        char *old_row = vs->old_data + y_position * vs->ds->linesize;
591

    
592
        for (i = 0; i < h; i++) {
593
            vs->dirty_row[y_position + i] = (1ULL << (vs->ds->width / 16)) - 1;
594
            if (vs->ds->width == 1024) {
595
              vs->dirty_row[y_position + i] = ~(0ULL);
596
            }
597
            memset(old_row, 42, vs->ds->width * vs->depth);
598
            old_row += vs->ds->linesize;
599
        }
600
    }
601
}
602

    
603
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
604
{
605
    int i;
606

    
607
    vs->has_hextile = 0;
608
    vs->has_resize = 0;
609
    vs->ds->dpy_copy = NULL;
610

    
611
    for (i = n_encodings - 1; i >= 0; i--) {
612
        switch (encodings[i]) {
613
        case 0: /* Raw */
614
            vs->has_hextile = 0;
615
            break;
616
        case 1: /* CopyRect */
617
            vs->ds->dpy_copy = vnc_copy;
618
            break;
619
        case 5: /* Hextile */
620
            vs->has_hextile = 1;
621
            break;
622
        case -223: /* DesktopResize */
623
            vs->has_resize = 1;
624
            break;
625
        default:
626
            break;
627
        }
628
    }
629
}
630

    
631
static void set_pixel_format(VncState *vs,
632
                             int bits_per_pixel, int depth,
633
                             int big_endian_flag, int true_color_flag,
634
                             int red_max, int green_max, int blue_max,
635
                             int red_shift, int green_shift, int blue_shift)
636
{
637
    switch (bits_per_pixel) {
638
    case 32:
639
    case 24:
640
        vs->depth = 4;
641
        break;
642
    case 16:
643
        vs->depth = 2;
644
        break;
645
    case 8:
646
        vs->depth = 1;
647
        break;
648
    default:
649
        vnc_client_error(vs);
650
        break;
651
    }
652

    
653
    if (!true_color_flag)
654
        vnc_client_error(vs);
655

    
656
    vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
657
    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
658
    memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height);
659

    
660
    vga_hw_invalidate();
661
    vga_hw_update();
662
}
663

    
664
static int protocol_client_msg(VncState *vs, char *data, size_t len)
665
{
666
    int i;
667
    uint16_t limit;
668

    
669
    switch (data[0]) {
670
    case 0:
671
        if (len == 1)
672
            return 20;
673

    
674
        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
675
                         read_u8(data, 6), read_u8(data, 7),
676
                         read_u16(data, 8), read_u16(data, 10),
677
                         read_u16(data, 12), read_u8(data, 14),
678
                         read_u8(data, 15), read_u8(data, 16));
679
        break;
680
    case 2:
681
        if (len == 1)
682
            return 4;
683

    
684
        if (len == 4)
685
            return 4 + (read_u16(data, 2) * 4);
686

    
687
        limit = read_u16(data, 2);
688
        for (i = 0; i < limit; i++) {
689
            int32_t val = read_s32(data, 4 + (i * 4));
690
            memcpy(data + 4 + (i * 4), &val, sizeof(val));
691
        }
692

    
693
        set_encodings(vs, (int32_t *)(data + 4), limit);
694
        break;
695
    case 3:
696
        if (len == 1)
697
            return 10;
698

    
699
        framebuffer_update_request(vs,
700
                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
701
                                   read_u16(data, 6), read_u16(data, 8));
702
        break;
703
    case 4:
704
        if (len == 1)
705
            return 8;
706

    
707
        key_event(vs, read_u8(data, 1), read_u32(data, 4));
708
        break;
709
    case 5:
710
        if (len == 1)
711
            return 6;
712

    
713
        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
714
        break;
715
    case 6:
716
        if (len == 1)
717
            return 8;
718

    
719
        if (len == 8)
720
            return 8 + read_u32(data, 4);
721

    
722
        client_cut_text(vs, read_u32(data, 4), data + 8);
723
        break;
724
    default:
725
        printf("Msg: %d\n", data[0]);
726
        vnc_client_error(vs);
727
        break;
728
    }
729
        
730
    vnc_read_when(vs, protocol_client_msg, 1);
731
    return 0;
732
}
733

    
734
static int protocol_client_init(VncState *vs, char *data, size_t len)
735
{
736
    char pad[3] = { 0, 0, 0 };
737

    
738
    vs->width = vs->ds->width;
739
    vs->height = vs->ds->height;
740
    vnc_write_u16(vs, vs->ds->width);
741
    vnc_write_u16(vs, vs->ds->height);
742

    
743
    vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
744
    vnc_write_u8(vs, vs->depth * 8); /* depth */
745
    vnc_write_u8(vs, 0);             /* big-endian-flag */
746
    vnc_write_u8(vs, 1);             /* true-color-flag */
747
    if (vs->depth == 4) {
748
        vnc_write_u16(vs, 0xFF);     /* red-max */
749
        vnc_write_u16(vs, 0xFF);     /* green-max */
750
        vnc_write_u16(vs, 0xFF);     /* blue-max */
751
        vnc_write_u8(vs, 16);        /* red-shift */
752
        vnc_write_u8(vs, 8);         /* green-shift */
753
        vnc_write_u8(vs, 0);         /* blue-shift */
754
    } else if (vs->depth == 2) {
755
        vnc_write_u16(vs, 31);       /* red-max */
756
        vnc_write_u16(vs, 63);       /* green-max */
757
        vnc_write_u16(vs, 31);       /* blue-max */
758
        vnc_write_u8(vs, 11);        /* red-shift */
759
        vnc_write_u8(vs, 5);         /* green-shift */
760
        vnc_write_u8(vs, 0);         /* blue-shift */
761
    } else if (vs->depth == 1) {
762
        vnc_write_u16(vs, 3);        /* red-max */
763
        vnc_write_u16(vs, 7);        /* green-max */
764
        vnc_write_u16(vs, 3);        /* blue-max */
765
        vnc_write_u8(vs, 5);         /* red-shift */
766
        vnc_write_u8(vs, 2);         /* green-shift */
767
        vnc_write_u8(vs, 0);         /* blue-shift */
768
    }
769
        
770
    vnc_write(vs, pad, 3);           /* padding */
771

    
772
    vnc_write_u32(vs, 4);        
773
    vnc_write(vs, "QEMU", 4);
774
    vnc_flush(vs);
775

    
776
    vnc_read_when(vs, protocol_client_msg, 1);
777

    
778
    return 0;
779
}
780

    
781
static int protocol_version(VncState *vs, char *version, size_t len)
782
{
783
    char local[13];
784
    int maj, min;
785

    
786
    memcpy(local, version, 12);
787
    local[12] = 0;
788

    
789
    if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
790
        vnc_client_error(vs);
791
        return 0;
792
    }
793

    
794
    vnc_write_u32(vs, 1); /* None */
795
    vnc_flush(vs);
796

    
797
    vnc_read_when(vs, protocol_client_init, 1);
798

    
799
    return 0;
800
}
801

    
802
static void vnc_listen_read(void *opaque)
803
{
804
    VncState *vs = opaque;
805
    struct sockaddr_in addr;
806
    socklen_t addrlen = sizeof(addr);
807

    
808
    vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
809
    if (vs->csock != -1) {
810
        socket_set_nonblock(vs->csock);
811
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
812
        vnc_write(vs, "RFB 003.003\n", 12);
813
        vnc_flush(vs);
814
        vnc_read_when(vs, protocol_version, 12);
815
        memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
816
        memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
817
        vs->has_resize = 0;
818
        vs->has_hextile = 0;
819
        vs->ds->dpy_copy = NULL;
820
    }
821
}
822

    
823
void vnc_display_init(DisplayState *ds, int display)
824
{
825
    struct sockaddr_in addr;
826
    int reuse_addr, ret;
827
    VncState *vs;
828

    
829
    vs = qemu_mallocz(sizeof(VncState));
830
    if (!vs)
831
        exit(1);
832

    
833
    ds->opaque = vs;
834

    
835
    vs->lsock = -1;
836
    vs->csock = -1;
837
    vs->depth = 4;
838

    
839
    vs->ds = ds;
840

    
841
    if (!keyboard_layout)
842
        keyboard_layout = "en-us";
843

    
844
    vs->kbd_layout = init_keyboard_layout(keyboard_layout);
845
    if (!vs->kbd_layout)
846
        exit(1);
847

    
848
    vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
849
    if (vs->lsock == -1) {
850
        fprintf(stderr, "Could not create socket\n");
851
        exit(1);
852
    }
853

    
854
    addr.sin_family = AF_INET;
855
    addr.sin_port = htons(5900 + display);
856
    memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
857

    
858
    reuse_addr = 1;
859
    ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
860
                     (const char *)&reuse_addr, sizeof(reuse_addr));
861
    if (ret == -1) {
862
        fprintf(stderr, "setsockopt() failed\n");
863
        exit(1);
864
    }
865

    
866
    if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
867
        fprintf(stderr, "bind() failed\n");
868
        exit(1);
869
    }
870

    
871
    if (listen(vs->lsock, 1) == -1) {
872
        fprintf(stderr, "listen() failed\n");
873
        exit(1);
874
    }
875

    
876
    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
877
    if (ret == -1) {
878
        exit(1);
879
    }
880

    
881
    vs->ds->data = NULL;
882
    vs->ds->dpy_update = vnc_dpy_update;
883
    vs->ds->dpy_resize = vnc_dpy_resize;
884
    vs->ds->dpy_refresh = vnc_dpy_refresh;
885

    
886
    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
887

    
888
    vnc_dpy_resize(vs->ds, 640, 400);
889
}