~vcs-imports/gtk-vnc/trunk

« back to all changes in this revision

Viewing changes to src/gvnc.c

  • Committer: anthony@rhesus
  • Date: 2007-01-06 05:24:48 UTC
  • Revision ID: git-v1:1b37b85e6ab9f2c7660814051b1a6886f9a3290d
Reorganize repo and create a proper setup.py

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2006  Anthony Liguori <anthony@codemonkey.ws>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU Lesser General Public License version 2 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 *  GTK VNC Widget
 
9
 */
 
10
 
 
11
#include "gvnc.h"
 
12
 
 
13
#include <sys/socket.h>
 
14
#include <netinet/in.h>
 
15
#include <arpa/inet.h>
 
16
 
 
17
#include <netdb.h>
 
18
#include <string.h>
 
19
#include <malloc.h>
 
20
#include <unistd.h>
 
21
#include <stdio.h>
 
22
#include <errno.h>
 
23
#include <fcntl.h>
 
24
#include <string.h>
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
 
 
28
#include "coroutine.h"
 
29
#include "d3des.h"
 
30
 
 
31
static gboolean g_io_wait_helper(GIOChannel *channel, GIOCondition cond,
 
32
                                 gpointer data)
 
33
{
 
34
        struct coroutine *to = data;
 
35
        yieldto(to, &cond);
 
36
        return FALSE;
 
37
}
 
38
 
 
39
GIOCondition g_io_wait(GIOChannel *channel, GIOCondition cond)
 
40
{
 
41
        GIOCondition *ret;
 
42
 
 
43
        g_io_add_watch(channel, cond, g_io_wait_helper, coroutine_self());
 
44
        ret = yield(NULL);
 
45
 
 
46
        return *ret;
 
47
}
 
48
 
 
49
typedef void gvnc_blt_func(struct gvnc *, uint8_t *, int, int, int, int, int);
 
50
 
 
51
typedef void gvnc_hextile_func(struct gvnc *gvnc, uint8_t flags,
 
52
                               uint16_t x, uint16_t y,
 
53
                               uint16_t width, uint16_t height,
 
54
                               uint8_t *fg, uint8_t *bg);
 
55
 
 
56
struct gvnc
 
57
{
 
58
        GIOChannel *channel;
 
59
        struct vnc_pixel_format fmt;
 
60
        gboolean has_error;
 
61
        int width;
 
62
        int height;
 
63
        char *name;
 
64
 
 
65
        char read_buffer[4096];
 
66
        int read_offset;
 
67
        int read_size;
 
68
 
 
69
        gboolean perfect_match;
 
70
        struct framebuffer local;
 
71
 
 
72
        int rp, gp, bp;
 
73
        int rm, gm, bm;
 
74
 
 
75
        gvnc_blt_func *blt;
 
76
        gvnc_hextile_func *hextile;
 
77
 
 
78
        struct vnc_ops ops;
 
79
 
 
80
        int absolute;
 
81
};
 
82
 
 
83
#if 0
 
84
#define GVNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
 
85
#else
 
86
#define GVNC_DEBUG(fmt, ...) do { } while (0)
 
87
#endif
 
88
 
 
89
#define nibhi(a) (((a) >> 4) & 0x0F)
 
90
#define niblo(a) ((a) & 0x0F)
 
91
 
 
92
/* IO functions */
 
93
 
 
94
static void gvnc_read(struct gvnc *gvnc, void *data, size_t len)
 
95
{
 
96
        int fd = g_io_channel_unix_get_fd(gvnc->channel);
 
97
        char *ptr = data;
 
98
        size_t offset = 0;
 
99
 
 
100
        if (gvnc->has_error) return;
 
101
        
 
102
        while (offset < len) {
 
103
                size_t tmp;
 
104
 
 
105
                if (gvnc->read_offset == gvnc->read_size) {
 
106
                        ssize_t ret;
 
107
 
 
108
                        ret = read(fd, gvnc->read_buffer, 4096);
 
109
                        if (ret == -1) {
 
110
                                switch (errno) {
 
111
                                case EAGAIN:
 
112
                                        g_io_wait(gvnc->channel, G_IO_IN);
 
113
                                case EINTR:
 
114
                                        continue;
 
115
                                default:
 
116
                                        gvnc->has_error = TRUE;
 
117
                                        return;
 
118
                                }
 
119
                        }
 
120
                        if (ret == 0) {
 
121
                                gvnc->has_error = TRUE;
 
122
                                return;
 
123
                        }
 
124
 
 
125
                        gvnc->read_offset = 0;
 
126
                        gvnc->read_size = ret;
 
127
                }
 
128
 
 
129
                tmp = MIN(gvnc->read_size - gvnc->read_offset, len - offset);
 
130
 
 
131
                memcpy(ptr + offset, gvnc->read_buffer + gvnc->read_offset, tmp);
 
132
 
 
133
                gvnc->read_offset += tmp;
 
134
                offset += tmp;
 
135
        }
 
136
}
 
137
 
 
138
void gvnc_write(struct gvnc *gvnc, const void *data, size_t len)
 
139
{
 
140
        int fd = g_io_channel_unix_get_fd(gvnc->channel);
 
141
        const char *ptr = data;
 
142
        size_t offset = 0;
 
143
 
 
144
        while (offset < len) {
 
145
                ssize_t ret;
 
146
 
 
147
                ret = write(fd, ptr + offset, len - offset);
 
148
                if (ret == -1) {
 
149
                        switch (errno) {
 
150
                        case EAGAIN:
 
151
                                g_io_wait(gvnc->channel, G_IO_OUT);
 
152
                        case EINTR:
 
153
                                continue;
 
154
                        default:
 
155
                                gvnc->has_error = TRUE;
 
156
                                return;
 
157
                        }
 
158
                }
 
159
 
 
160
                if (ret == 0) {
 
161
                        gvnc->has_error = TRUE;
 
162
                        return;
 
163
                }
 
164
 
 
165
                offset += ret;
 
166
        }
 
167
}
 
168
 
 
169
static uint8_t gvnc_read_u8(struct gvnc *gvnc)
 
170
{
 
171
        uint8_t value = 0;
 
172
        gvnc_read(gvnc, &value, sizeof(value));
 
173
        return value;
 
174
}
 
175
 
 
176
static uint16_t gvnc_read_u16(struct gvnc *gvnc)
 
177
{
 
178
        uint16_t value = 0;
 
179
        gvnc_read(gvnc, &value, sizeof(value));
 
180
        return ntohs(value);
 
181
}
 
182
 
 
183
static uint32_t gvnc_read_u32(struct gvnc *gvnc)
 
184
{
 
185
        uint32_t value = 0;
 
186
        gvnc_read(gvnc, &value, sizeof(value));
 
187
        return ntohl(value);
 
188
}
 
189
 
 
190
static int32_t gvnc_read_s32(struct gvnc *gvnc)
 
191
{
 
192
        int32_t value = 0;
 
193
        gvnc_read(gvnc, &value, sizeof(value));
 
194
        return ntohl(value);
 
195
}
 
196
 
 
197
static void gvnc_write_u8(struct gvnc *gvnc, uint8_t value)
 
198
{
 
199
        gvnc_write(gvnc, &value, sizeof(value));
 
200
}
 
201
 
 
202
static void gvnc_write_u16(struct gvnc *gvnc, uint16_t value)
 
203
{
 
204
        value = htons(value);
 
205
        gvnc_write(gvnc, &value, sizeof(value));
 
206
}
 
207
 
 
208
static void gvnc_write_u32(struct gvnc *gvnc, uint32_t value)
 
209
{
 
210
        value = htonl(value);
 
211
        gvnc_write(gvnc, &value, sizeof(value));
 
212
}
 
213
 
 
214
static void gvnc_write_s32(struct gvnc *gvnc, int32_t value)
 
215
{
 
216
        value = htonl(value);
 
217
        gvnc_write(gvnc, &value, sizeof(value));
 
218
}
 
219
 
 
220
static void gvnc_read_pixel_format(struct gvnc *gvnc, struct vnc_pixel_format *fmt)
 
221
{
 
222
        uint8_t pad[3];
 
223
 
 
224
        fmt->bits_per_pixel  = gvnc_read_u8(gvnc);
 
225
        fmt->depth           = gvnc_read_u8(gvnc);
 
226
        fmt->big_endian_flag = gvnc_read_u8(gvnc);
 
227
        fmt->true_color_flag = gvnc_read_u8(gvnc);
 
228
 
 
229
        fmt->red_max         = gvnc_read_u16(gvnc);
 
230
        fmt->green_max       = gvnc_read_u16(gvnc);
 
231
        fmt->blue_max        = gvnc_read_u16(gvnc);
 
232
 
 
233
        fmt->red_shift       = gvnc_read_u8(gvnc);
 
234
        fmt->green_shift     = gvnc_read_u8(gvnc);
 
235
        fmt->blue_shift      = gvnc_read_u8(gvnc);
 
236
 
 
237
        gvnc_read(gvnc, pad, 3);
 
238
}
 
239
 
 
240
/* initialize function */
 
241
 
 
242
gboolean gvnc_has_error(struct gvnc *gvnc)
 
243
{
 
244
        return gvnc->has_error;
 
245
}
 
246
 
 
247
gboolean gvnc_set_pixel_format(struct gvnc *gvnc,
 
248
                               const struct vnc_pixel_format *fmt)
 
249
{
 
250
        uint8_t pad[3] = {0};
 
251
 
 
252
        gvnc_write_u8(gvnc, 0);
 
253
        gvnc_write(gvnc, pad, 3);
 
254
 
 
255
        gvnc_write_u8(gvnc, fmt->bits_per_pixel);
 
256
        gvnc_write_u8(gvnc, fmt->depth);
 
257
        gvnc_write_u8(gvnc, fmt->big_endian_flag);
 
258
        gvnc_write_u8(gvnc, fmt->true_color_flag);
 
259
 
 
260
        gvnc_write_u16(gvnc, fmt->red_max);
 
261
        gvnc_write_u16(gvnc, fmt->green_max);
 
262
        gvnc_write_u16(gvnc, fmt->blue_max);
 
263
 
 
264
        gvnc_write_u8(gvnc, fmt->red_shift);
 
265
        gvnc_write_u8(gvnc, fmt->green_shift);
 
266
        gvnc_write_u8(gvnc, fmt->blue_shift);
 
267
 
 
268
        gvnc_write(gvnc, pad, 3);
 
269
 
 
270
        memcpy(&gvnc->fmt, fmt, sizeof(*fmt));
 
271
 
 
272
        return gvnc_has_error(gvnc);
 
273
}
 
274
 
 
275
gboolean gvnc_set_encodings(struct gvnc *gvnc, int n_encoding, int32_t *encoding)
 
276
{
 
277
        uint8_t pad[1] = {0};
 
278
        int i;
 
279
 
 
280
        gvnc_write_u8(gvnc, 2);
 
281
        gvnc_write(gvnc, pad, 1);
 
282
        gvnc_write_u16(gvnc, n_encoding);
 
283
        for (i = 0; i < n_encoding; i++)
 
284
                gvnc_write_s32(gvnc, encoding[i]);
 
285
 
 
286
        return gvnc_has_error(gvnc);
 
287
}
 
288
 
 
289
gboolean gvnc_framebuffer_update_request(struct gvnc *gvnc,
 
290
                                         uint8_t incremental,
 
291
                                         uint16_t x, uint16_t y,
 
292
                                         uint16_t width, uint16_t height)
 
293
{
 
294
        gvnc_write_u8(gvnc, 3);
 
295
        gvnc_write_u8(gvnc, incremental);
 
296
        gvnc_write_u16(gvnc, x);
 
297
        gvnc_write_u16(gvnc, y);
 
298
        gvnc_write_u16(gvnc, width);
 
299
        gvnc_write_u16(gvnc, height);
 
300
 
 
301
        return gvnc_has_error(gvnc);
 
302
}
 
303
 
 
304
gboolean gvnc_key_event(struct gvnc *gvnc, uint8_t down_flag, uint32_t key)
 
305
{
 
306
        uint8_t pad[2] = {0};
 
307
 
 
308
        gvnc_write_u8(gvnc, 4);
 
309
        gvnc_write_u8(gvnc, down_flag);
 
310
        gvnc_write(gvnc, pad, 2);
 
311
        gvnc_write_u32(gvnc, key);
 
312
 
 
313
        return gvnc_has_error(gvnc);
 
314
}
 
315
 
 
316
gboolean gvnc_pointer_event(struct gvnc *gvnc, uint8_t button_mask,
 
317
                            uint16_t x, uint16_t y)
 
318
{
 
319
        gvnc_write_u8(gvnc, 5);
 
320
        gvnc_write_u8(gvnc, button_mask);
 
321
        gvnc_write_u16(gvnc, x);
 
322
        gvnc_write_u16(gvnc, y);
 
323
 
 
324
        return gvnc_has_error(gvnc);    
 
325
}
 
326
 
 
327
gboolean gvnc_client_cut_text(struct gvnc *gvnc,
 
328
                              const void *data, size_t length)
 
329
{
 
330
        uint8_t pad[3] = {0};
 
331
 
 
332
        gvnc_write_u8(gvnc, 6);
 
333
        gvnc_write(gvnc, pad, 3);
 
334
        gvnc_write_u32(gvnc, length);
 
335
        gvnc_write(gvnc, data, length);
 
336
 
 
337
        return gvnc_has_error(gvnc);
 
338
}
 
339
 
 
340
static inline uint8_t *gvnc_get_local(struct gvnc *gvnc, int x, int y)
 
341
{
 
342
        return gvnc->local.data +
 
343
                (y * gvnc->local.linesize) +
 
344
                (x * gvnc->local.bpp);
 
345
}
 
346
 
 
347
#define SPLICE_I(a, b) a ## b
 
348
#define SPLICE(a, b) SPLICE_I(a, b)
 
349
 
 
350
#define SRC 8
 
351
#include "blt1.h"
 
352
#undef SRC
 
353
 
 
354
#define SRC 16
 
355
#include "blt1.h"
 
356
#undef SRC
 
357
 
 
358
#define SRC 32
 
359
#include "blt1.h"
 
360
#undef SRC
 
361
 
 
362
static gvnc_blt_func *gvnc_blt_table[3][3] = {
 
363
        {  gvnc_blt_8x8,  gvnc_blt_8x16,  gvnc_blt_8x32 },
 
364
        { gvnc_blt_16x8, gvnc_blt_16x16, gvnc_blt_16x32 },
 
365
        { gvnc_blt_32x8, gvnc_blt_32x16, gvnc_blt_32x32 },
 
366
};
 
367
 
 
368
static gvnc_hextile_func *gvnc_hextile_table[3][3] = {
 
369
        { (gvnc_hextile_func *)gvnc_hextile_8x8,
 
370
          (gvnc_hextile_func *)gvnc_hextile_8x16,
 
371
          (gvnc_hextile_func *)gvnc_hextile_8x32 },
 
372
        { (gvnc_hextile_func *)gvnc_hextile_16x8,
 
373
          (gvnc_hextile_func *)gvnc_hextile_16x16,
 
374
          (gvnc_hextile_func *)gvnc_hextile_16x32 },
 
375
        { (gvnc_hextile_func *)gvnc_hextile_32x8,
 
376
          (gvnc_hextile_func *)gvnc_hextile_32x16,
 
377
          (gvnc_hextile_func *)gvnc_hextile_32x32 },
 
378
};
 
379
 
 
380
/* a fast blit for the perfect match scenario */
 
381
static void gvnc_blt_fast(struct gvnc *gvnc, uint8_t *src, int pitch,
 
382
                          int x, int y, int width, int height)
 
383
{
 
384
        uint8_t *dst = gvnc_get_local(gvnc, x, y);
 
385
        int i;
 
386
        for (i = 0; i < height; i++) {
 
387
                memcpy(dst, src, width * gvnc->local.bpp);
 
388
                dst += gvnc->local.linesize;
 
389
                src += pitch;
 
390
        }
 
391
}
 
392
 
 
393
static void gvnc_blt(struct gvnc *gvnc, uint8_t *src, int pitch,
 
394
                     int x, int y, int width, int height)
 
395
{
 
396
        gvnc->blt(gvnc, src, pitch, x, y, width, height);
 
397
}
 
398
 
 
399
static void gvnc_raw_update(struct gvnc *gvnc,
 
400
                            uint16_t x, uint16_t y,
 
401
                            uint16_t width, uint16_t height)
 
402
{
 
403
        uint8_t *dst;
 
404
        int i;
 
405
 
 
406
        /* optimize for perfect match between server/client
 
407
           FWIW, in the local case, we ought to be doing a write
 
408
           directly from the source framebuffer and a read directly
 
409
           into the client framebuffer
 
410
         */
 
411
        if (gvnc->perfect_match) {
 
412
                dst = gvnc_get_local(gvnc, x, y);
 
413
                for (i = 0; i < height; i++) {
 
414
                        gvnc_read(gvnc, dst, width * gvnc->local.bpp);
 
415
                        dst += gvnc->local.linesize;
 
416
                }
 
417
                return;
 
418
        }
 
419
 
 
420
        dst = malloc(width * (gvnc->fmt.bits_per_pixel / 8));
 
421
        if (dst == NULL) {
 
422
                gvnc->has_error = TRUE;
 
423
                return;
 
424
        }
 
425
        
 
426
        for (i = 0; i < height; i++) {
 
427
                gvnc_read(gvnc, dst, width * (gvnc->fmt.bits_per_pixel / 8));
 
428
                gvnc_blt(gvnc, dst, 0, x, y + i, width, 1);
 
429
        }
 
430
        
 
431
        free(dst);
 
432
}
 
433
 
 
434
static void gvnc_copyrect_update(struct gvnc *gvnc,
 
435
                                 uint16_t dst_x, uint16_t dst_y,
 
436
                                 uint16_t width, uint16_t height)
 
437
{
 
438
        int src_x, src_y;
 
439
        uint8_t *dst, *src;
 
440
        int pitch = gvnc->local.linesize;
 
441
        int i;
 
442
        
 
443
        src_x = gvnc_read_u16(gvnc);
 
444
        src_y = gvnc_read_u16(gvnc);
 
445
        
 
446
        if (src_y < dst_y) {
 
447
                pitch = -pitch;
 
448
                src_y += (height - 1);
 
449
                dst_y += (height - 1);
 
450
        }
 
451
        
 
452
        dst = gvnc_get_local(gvnc, dst_x, dst_y);
 
453
        src = gvnc_get_local(gvnc, src_x, src_y);
 
454
        for (i = 0; i < height; i++) {
 
455
                memmove(dst, src, width * gvnc->local.bpp);
 
456
                dst += pitch;
 
457
                src += pitch;
 
458
        }
 
459
}
 
460
 
 
461
static void gvnc_hextile_update(struct gvnc *gvnc,
 
462
                                uint16_t x, uint16_t y,
 
463
                                uint16_t width, uint16_t height)
 
464
{
 
465
        uint8_t fg[4];
 
466
        uint8_t bg[4];
 
467
 
 
468
        int j;
 
469
        for (j = 0; j < height; j += 16) {
 
470
                int i;
 
471
                for (i = 0; i < width; i += 16) {
 
472
                        uint8_t flags;
 
473
                        int w = MIN(16, width - i);
 
474
                        int h = MIN(16, height - j);
 
475
 
 
476
                        flags = gvnc_read_u8(gvnc);
 
477
                        gvnc->hextile(gvnc, flags, x + i, y + j, w, h, fg, bg);
 
478
                }
 
479
        }
 
480
}
 
481
 
 
482
static void gvnc_update(struct gvnc *gvnc, int x, int y, int width, int height)
 
483
{
 
484
        if (gvnc->has_error || !gvnc->ops.update)
 
485
                return;
 
486
        gvnc->has_error = !gvnc->ops.update(gvnc->ops.user, x, y, width, height);
 
487
}
 
488
 
 
489
static void gvnc_set_color_map_entry(struct gvnc *gvnc, uint16_t color,
 
490
                                     uint16_t red, uint16_t green,
 
491
                                     uint16_t blue)
 
492
{
 
493
        if (gvnc->has_error || !gvnc->ops.set_color_map_entry)
 
494
                return;
 
495
        gvnc->has_error = !gvnc->ops.set_color_map_entry(gvnc->ops.user, color,
 
496
                                                         red, green, blue);
 
497
}
 
498
 
 
499
static void gvnc_bell(struct gvnc *gvnc)
 
500
{
 
501
        if (gvnc->has_error || !gvnc->ops.bell)
 
502
                return;
 
503
        gvnc->has_error = !gvnc->ops.bell(gvnc->ops.user);
 
504
}
 
505
 
 
506
static void gvnc_server_cut_text(struct gvnc *gvnc, const void *data,
 
507
                                 size_t len)
 
508
{
 
509
        if (gvnc->has_error || !gvnc->ops.server_cut_text)
 
510
                return;
 
511
        gvnc->has_error = !gvnc->ops.server_cut_text(gvnc->ops.user, data, len);
 
512
}
 
513
 
 
514
static void gvnc_resize(struct gvnc *gvnc, int width, int height)
 
515
{
 
516
        if (gvnc->has_error || !gvnc->ops.resize)
 
517
                return;
 
518
        gvnc->has_error = !gvnc->ops.resize(gvnc->ops.user, width, height);
 
519
}
 
520
 
 
521
static void gvnc_pointer_type_change(struct gvnc *gvnc, int absolute)
 
522
{
 
523
        if (gvnc->has_error || !gvnc->ops.pointer_type_change)
 
524
                return;
 
525
        gvnc->has_error = !gvnc->ops.pointer_type_change(gvnc->ops.user, absolute);
 
526
}
 
527
 
 
528
static void gvnc_framebuffer_update(struct gvnc *gvnc, int32_t etype,
 
529
                                    uint16_t x, uint16_t y,
 
530
                                    uint16_t width, uint16_t height)
 
531
{
 
532
        GVNC_DEBUG("FramebufferUpdate(%d, %d, %d, %d, %d)\n",
 
533
                   etype, x, y, width, height);
 
534
 
 
535
        switch (etype) {
 
536
        case 0: /* Raw */
 
537
                gvnc_raw_update(gvnc, x, y, width, height);
 
538
                break;
 
539
        case 1: /* CopyRect */
 
540
                gvnc_copyrect_update(gvnc, x, y, width, height);
 
541
                break;
 
542
        case 5: /* Hextile */
 
543
                gvnc_hextile_update(gvnc, x, y, width, height);
 
544
                break;
 
545
        case -223: /* DesktopResize */
 
546
                gvnc_resize(gvnc, width, height);
 
547
                break;
 
548
        case -257: /* PointerChangeType */
 
549
                gvnc_pointer_type_change(gvnc, x);
 
550
                break;
 
551
        default:
 
552
                gvnc->has_error = TRUE;
 
553
                break;
 
554
        }
 
555
 
 
556
        gvnc_update(gvnc, x, y, width, height);
 
557
}
 
558
 
 
559
gboolean gvnc_server_message(struct gvnc *gvnc)
 
560
{
 
561
        uint8_t msg;
 
562
 
 
563
        /* NB: make sure that all server message functions
 
564
           handle has_error appropriately */
 
565
 
 
566
        msg = gvnc_read_u8(gvnc);
 
567
        switch (msg) {
 
568
        case 0: { /* FramebufferUpdate */
 
569
                uint8_t pad[1];
 
570
                uint16_t n_rects;
 
571
                int i;
 
572
 
 
573
                gvnc_read(gvnc, pad, 1);
 
574
                n_rects = gvnc_read_u16(gvnc);
 
575
                for (i = 0; i < n_rects; i++) {
 
576
                        uint16_t x, y, w, h;
 
577
                        int32_t etype;
 
578
 
 
579
                        x = gvnc_read_u16(gvnc);
 
580
                        y = gvnc_read_u16(gvnc);
 
581
                        w = gvnc_read_u16(gvnc);
 
582
                        h = gvnc_read_u16(gvnc);
 
583
                        etype = gvnc_read_s32(gvnc);
 
584
 
 
585
                        gvnc_framebuffer_update(gvnc, etype, x, y, w, h);
 
586
                }
 
587
        }       break;
 
588
        case 1: { /* SetColorMapEntries */
 
589
                uint16_t first_color;
 
590
                uint16_t n_colors;
 
591
                uint8_t pad[1];
 
592
                int i;
 
593
 
 
594
                gvnc_read(gvnc, pad, 1);
 
595
                first_color = gvnc_read_u16(gvnc);
 
596
                n_colors = gvnc_read_u16(gvnc);
 
597
 
 
598
                for (i = 0; i < n_colors; i++) {
 
599
                        uint16_t red, green, blue;
 
600
 
 
601
                        red = gvnc_read_u16(gvnc);
 
602
                        green = gvnc_read_u16(gvnc);
 
603
                        blue = gvnc_read_u16(gvnc);
 
604
 
 
605
                        gvnc_set_color_map_entry(gvnc,
 
606
                                                 i + first_color,
 
607
                                                 red, green, blue);
 
608
                }
 
609
        }       break;
 
610
        case 2: /* Bell */
 
611
                gvnc_bell(gvnc);
 
612
                break;
 
613
        case 3: { /* ServerCutText */
 
614
                uint8_t pad[3];
 
615
                uint32_t n_text;
 
616
                char *data;
 
617
 
 
618
                gvnc_read(gvnc, pad, 3);
 
619
                n_text = gvnc_read_u32(gvnc);
 
620
                if (n_text > (32 << 20)) {
 
621
                        gvnc->has_error = TRUE;
 
622
                        break;
 
623
                }
 
624
 
 
625
                data = malloc(n_text + 1);
 
626
                if (data == NULL) {
 
627
                        gvnc->has_error = TRUE;
 
628
                        break;
 
629
                }
 
630
 
 
631
                gvnc_read(gvnc, data, n_text);
 
632
                data[n_text] = 0;
 
633
 
 
634
                gvnc_server_cut_text(gvnc, data, n_text);
 
635
                free(data);
 
636
        }       break;
 
637
        default:
 
638
                gvnc->has_error = TRUE;
 
639
                break;
 
640
        }
 
641
 
 
642
        return gvnc_has_error(gvnc);
 
643
}
 
644
 
 
645
struct gvnc *gvnc_connect(GIOChannel *channel, gboolean shared_flag, const char *password)
 
646
{
 
647
        int s;
 
648
        int ret;
 
649
        char version[13];
 
650
        int major, minor;
 
651
        uint32_t auth;
 
652
        uint32_t n_name;
 
653
        struct gvnc *gvnc = NULL;
 
654
 
 
655
        s = g_io_channel_unix_get_fd(channel);
 
656
 
 
657
        if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
 
658
                goto error;
 
659
 
 
660
        gvnc = malloc(sizeof(*gvnc));
 
661
        if (gvnc == NULL)
 
662
                goto error;
 
663
 
 
664
        memset(gvnc, 0, sizeof(*gvnc));
 
665
 
 
666
        gvnc->channel = channel;
 
667
        gvnc->absolute = 1;
 
668
 
 
669
        gvnc_read(gvnc, version, 12);
 
670
        version[12] = 0;
 
671
 
 
672
        ret = sscanf(version, "RFB %03d.%03d\n", &major, &minor);
 
673
        if (ret != 2)
 
674
                goto error;
 
675
 
 
676
        gvnc_write(gvnc, "RFB 003.003\n", 12);
 
677
 
 
678
        auth = gvnc_read_u32(gvnc);
 
679
        switch (auth) {
 
680
        case 1:
 
681
                break;
 
682
        case 2: {
 
683
                uint8_t challenge[16];
 
684
                uint8_t key[8];
 
685
                uint32_t result;
 
686
 
 
687
                gvnc_read(gvnc, challenge, 16);
 
688
 
 
689
                memset(key, 0, 8);
 
690
                strncpy((char*)key, (char*)password, 8);
 
691
 
 
692
                deskey(key, EN0);
 
693
                des(challenge, challenge);
 
694
                des(challenge + 8, challenge + 8);
 
695
 
 
696
                gvnc_write(gvnc, challenge, 16);
 
697
 
 
698
                result = gvnc_read_u32(gvnc);
 
699
                if (result != 0) {
 
700
                        goto error;
 
701
                }
 
702
        }       break;
 
703
        default:
 
704
                break;
 
705
        }
 
706
 
 
707
        gvnc_write_u8(gvnc, shared_flag); /* shared flag */
 
708
 
 
709
        gvnc->width = gvnc_read_u16(gvnc);
 
710
        gvnc->height = gvnc_read_u16(gvnc);
 
711
 
 
712
        gvnc_read_pixel_format(gvnc, &gvnc->fmt);
 
713
 
 
714
        n_name = gvnc_read_u32(gvnc);
 
715
        if (n_name > 4096)
 
716
                goto error;
 
717
 
 
718
        gvnc->name = malloc(n_name + 1);
 
719
        if (gvnc->name == NULL)
 
720
                goto error;
 
721
 
 
722
        gvnc_read(gvnc, gvnc->name, n_name);
 
723
        gvnc->name[n_name] = 0;
 
724
 
 
725
        gvnc_resize(gvnc, gvnc->width, gvnc->height);
 
726
 
 
727
        return gvnc;
 
728
 
 
729
 error:
 
730
        free(gvnc);
 
731
        return NULL;
 
732
}
 
733
 
 
734
gboolean gvnc_set_local(struct gvnc *gvnc, struct framebuffer *fb)
 
735
{
 
736
        int i, j;
 
737
        int depth;
 
738
 
 
739
        memcpy(&gvnc->local, fb, sizeof(*fb));
 
740
 
 
741
        if (fb->bpp == (gvnc->fmt.bits_per_pixel / 8) &&
 
742
            fb->red_mask == gvnc->fmt.red_max &&
 
743
            fb->green_mask == gvnc->fmt.green_max &&
 
744
            fb->blue_mask == gvnc->fmt.blue_max &&
 
745
            fb->red_shift == gvnc->fmt.red_shift &&
 
746
            fb->green_shift == gvnc->fmt.green_shift &&
 
747
            fb->blue_shift == gvnc->fmt.blue_shift)
 
748
                gvnc->perfect_match = TRUE;
 
749
        else
 
750
                gvnc->perfect_match = FALSE;
 
751
 
 
752
        depth = gvnc->fmt.depth;
 
753
        if (depth == 32)
 
754
                depth = 24;
 
755
 
 
756
        gvnc->rp =  (gvnc->local.depth - gvnc->local.red_shift);
 
757
        gvnc->rp -= (depth - gvnc->fmt.red_shift);
 
758
        gvnc->gp =  (gvnc->local.red_shift - gvnc->local.green_shift);
 
759
        gvnc->gp -= (gvnc->fmt.red_shift - gvnc->fmt.green_shift);
 
760
        gvnc->bp =  (gvnc->local.green_shift - gvnc->local.blue_shift);
 
761
        gvnc->bp -= (gvnc->fmt.green_shift - gvnc->fmt.blue_shift);
 
762
 
 
763
        gvnc->rp = gvnc->local.red_shift + gvnc->rp;
 
764
        gvnc->gp = gvnc->local.green_shift + gvnc->gp;
 
765
        gvnc->bp = gvnc->local.blue_shift + gvnc->bp;
 
766
 
 
767
        gvnc->rm = gvnc->local.red_mask & gvnc->fmt.red_max;
 
768
        gvnc->gm = gvnc->local.green_mask & gvnc->fmt.green_max;
 
769
        gvnc->bm = gvnc->local.blue_mask & gvnc->fmt.blue_max;
 
770
 
 
771
        i = gvnc->fmt.bits_per_pixel / 8;
 
772
        j = gvnc->local.bpp;
 
773
 
 
774
        if (i == 4) i = 3;
 
775
        if (j == 4) j = 3;
 
776
 
 
777
        gvnc->blt = gvnc_blt_table[i - 1][j - 1];
 
778
        gvnc->hextile = gvnc_hextile_table[i - 1][j - 1];
 
779
 
 
780
        if (gvnc->perfect_match)
 
781
                gvnc->blt = gvnc_blt_fast;
 
782
 
 
783
        return gvnc_has_error(gvnc);
 
784
}
 
785
 
 
786
gboolean gvnc_set_vnc_ops(struct gvnc *gvnc, struct vnc_ops *ops)
 
787
{
 
788
        memcpy(&gvnc->ops, ops, sizeof(*ops));
 
789
        gvnc_resize(gvnc, gvnc->width, gvnc->height);
 
790
        return gvnc_has_error(gvnc);
 
791
}
 
792
 
 
793
const char *gvnc_get_name(struct gvnc *gvnc)
 
794
{
 
795
        return gvnc->name;
 
796
}