~ubuntu-branches/ubuntu/vivid/vino/vivid-proposed

« back to all changes in this revision

Viewing changes to .pc/CVE-2012-4429.patch/server/libvncserver/rfbserver.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-01-18 11:23:12 UTC
  • Revision ID: package-import@ubuntu.com-20130118112312-qisprkvun8b72xk8
Tags: 3.6.2-0ubuntu2
* SECURITY UPDATE: clipboard leak to unauthenticated clients
  - debian/patches/CVE-2012-4429.patch: make sure client is authenticated
    in server/libvncserver/rfbserver.c.
  - CVE-2012-4429

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * rfbserver.c - deal with server-side of the RFB protocol.
 
3
 */
 
4
 
 
5
/*
 
6
 *  Copyright (C) 2002 RealVNC Ltd.
 
7
 *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
 
8
 *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.  
 
9
 *  All Rights Reserved.
 
10
 *
 
11
 *  This is free software; you can redistribute it and/or modify
 
12
 *  it under the terms of the GNU General Public License as published by
 
13
 *  the Free Software Foundation; either version 2 of the License, or
 
14
 *  (at your option) any later version.
 
15
 *
 
16
 *  This software is distributed in the hope that it will be useful,
 
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 *  GNU General Public License for more details.
 
20
 *
 
21
 *  You should have received a copy of the GNU General Public License
 
22
 *  along with this software; if not, write to the Free Software
 
23
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 
24
 *  USA.
 
25
 */
 
26
 
 
27
#define _GNU_SOURCE 1
 
28
 
 
29
#include <string.h>
 
30
#include "rfb/rfb.h"
 
31
#include "rfb/rfbregion.h"
 
32
#include <netdb.h>
 
33
 
 
34
#ifdef HAVE_FCNTL_H
 
35
#include <fcntl.h>
 
36
#endif
 
37
 
 
38
#ifdef WIN32
 
39
#define write(sock,buf,len) send(sock,buf,len,0)
 
40
#else
 
41
#ifdef HAVE_UNISTD_H
 
42
#include <unistd.h>
 
43
#endif
 
44
#include <pwd.h>
 
45
#ifdef HAVE_SYS_SOCKET_H
 
46
#include <sys/socket.h>
 
47
#endif
 
48
#ifdef HAVE_NETINET_IN_H
 
49
#include <netinet/in.h>
 
50
#include <netinet/tcp.h>
 
51
#include <arpa/inet.h>
 
52
#endif
 
53
#endif
 
54
 
 
55
#ifdef DEBUGPROTO
 
56
#undef DEBUGPROTO
 
57
#define DEBUGPROTO(x) x
 
58
#else
 
59
#define DEBUGPROTO(x)
 
60
#endif
 
61
 
 
62
rfbClientPtr pointerClient = NULL;  /* Mutex for pointer events */
 
63
 
 
64
static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
 
65
static void rfbProcessClientNormalMessage(rfbClientPtr cl);
 
66
 
 
67
struct rfbClientIterator {
 
68
  rfbClientPtr next;
 
69
  rfbScreenInfoPtr screen;
 
70
};
 
71
 
 
72
void
 
73
rfbClientListInit(rfbScreenInfoPtr rfbScreen)
 
74
{
 
75
    if(sizeof(rfbBool)!=1) {
 
76
        /* a sanity check */
 
77
        fprintf(stderr,"rfbBool's size is not 1 (%lu)!\n",(unsigned long)sizeof(rfbBool));
 
78
        /* we cannot continue, because rfbBool is supposed to be char everywhere */
 
79
        exit(1);
 
80
    }
 
81
    rfbScreen->rfbClientHead = NULL;
 
82
}
 
83
 
 
84
rfbClientIteratorPtr
 
85
rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
 
86
{
 
87
  rfbClientIteratorPtr i =
 
88
    (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
 
89
  i->next = 0;
 
90
  i->screen = rfbScreen;
 
91
  return i;
 
92
}
 
93
 
 
94
rfbClientPtr
 
95
rfbClientIteratorHead(rfbClientIteratorPtr i)
 
96
{
 
97
  LOCK(rfbClientListMutex);
 
98
  i->next = i->screen->rfbClientHead;
 
99
  UNLOCK(rfbClientListMutex);
 
100
  return i->next;
 
101
}
 
102
 
 
103
rfbClientPtr
 
104
rfbClientIteratorNext(rfbClientIteratorPtr i)
 
105
{
 
106
  if(i->next == 0) {
 
107
    LOCK(rfbClientListMutex);
 
108
    i->next = i->screen->rfbClientHead;
 
109
    UNLOCK(rfbClientListMutex);
 
110
  } else {
 
111
    i->next = i->next->next;
 
112
  }
 
113
 
 
114
    return i->next;
 
115
}
 
116
 
 
117
void
 
118
rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
 
119
{
 
120
  free(iterator);
 
121
}
 
122
 
 
123
/*
 
124
 * rfbNewClientConnection is called from sockets.c when a new connection
 
125
 * comes in.
 
126
 */
 
127
 
 
128
void
 
129
rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,
 
130
                       int sock)
 
131
{
 
132
    rfbClientPtr cl;
 
133
 
 
134
    cl = rfbNewClient(rfbScreen,sock);
 
135
}
 
136
 
 
137
 
 
138
/*
 
139
 * rfbNewClient is called when a new connection has been made by whatever
 
140
 * means.
 
141
 */
 
142
 
 
143
rfbClientPtr
 
144
rfbNewClient(rfbScreenInfoPtr rfbScreen,
 
145
             int sock)
 
146
{
 
147
    rfbProtocolVersionMsg pv;
 
148
    rfbClientIteratorPtr iterator;
 
149
    rfbClientPtr cl,cl_;
 
150
    struct sockaddr_storage addr;
 
151
    socklen_t addrlen = sizeof(addr);
 
152
    int i;
 
153
    char host[NI_MAXHOST];
 
154
    const char *prt = "unknown";
 
155
 
 
156
    cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
 
157
 
 
158
    cl->screen = rfbScreen;
 
159
    cl->sock = sock;
 
160
    cl->viewOnly = FALSE;
 
161
 
 
162
    rfbResetStats(cl);
 
163
 
 
164
    {
 
165
      int one=1;
 
166
 
 
167
      getpeername(sock, (struct sockaddr *)&addr, &addrlen);
 
168
 
 
169
      getnameinfo((struct sockaddr *)&addr,
 
170
                  addrlen,
 
171
                  host, sizeof(host),
 
172
                  NULL, 0,
 
173
                  0);
 
174
 
 
175
      cl->host = strdup(host);
 
176
 
 
177
      if (addr.ss_family == AF_INET)
 
178
        prt = "IPv4";
 
179
      else if (addr.ss_family == AF_INET6)
 
180
        prt = "IPv6";
 
181
 
 
182
      rfbLog("[%s] Got connection from client %s\n", prt, cl->host);
 
183
 
 
184
      rfbLog("  other clients:\n");
 
185
      iterator = rfbGetClientIterator(rfbScreen);
 
186
      while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
 
187
        rfbLog("     %s\n",cl_->host);
 
188
      }
 
189
      rfbReleaseClientIterator(iterator);
 
190
 
 
191
#ifndef WIN32
 
192
      if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
 
193
        rfbLogPerror("fcntl failed");
 
194
        close(sock);
 
195
        return NULL;
 
196
      }
 
197
#endif
 
198
 
 
199
      if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
 
200
                     (char *)&one, sizeof(one)) < 0) {
 
201
        rfbLogPerror("setsockopt failed");
 
202
        close(sock);
 
203
        return NULL;
 
204
      }
 
205
 
 
206
      FD_SET(sock,&(rfbScreen->allFds));
 
207
                rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
 
208
 
 
209
      cl->state = RFB_PROTOCOL_VERSION;
 
210
 
 
211
      cl->readyForSetColourMapEntries = FALSE;
 
212
      cl->useCopyRect = FALSE;
 
213
      cl->preferredEncoding = rfbEncodingRaw;
 
214
      cl->correMaxWidth = 48;
 
215
      cl->correMaxHeight = 48;
 
216
#ifdef VINO_HAVE_ZLIB
 
217
      cl->zrleData = NULL;
 
218
#endif
 
219
 
 
220
      cl->copyRegion = sraRgnCreate();
 
221
      cl->copyDX = 0;
 
222
      cl->copyDY = 0;
 
223
   
 
224
      cl->modifiedRegion =
 
225
        sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
 
226
 
 
227
      cl->requestedRegion = sraRgnCreate();
 
228
 
 
229
      cl->format = cl->screen->rfbServerFormat;
 
230
      cl->translateFn = rfbTranslateNone;
 
231
      cl->translateLookupTable = NULL;
 
232
 
 
233
      LOCK(rfbClientListMutex);
 
234
 
 
235
      cl->next = rfbScreen->rfbClientHead;
 
236
      cl->prev = NULL;
 
237
      if (rfbScreen->rfbClientHead)
 
238
        rfbScreen->rfbClientHead->prev = cl;
 
239
 
 
240
      rfbScreen->rfbClientHead = cl;
 
241
      UNLOCK(rfbClientListMutex);
 
242
 
 
243
#ifdef VINO_HAVE_JPEG
 
244
      cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
 
245
      cl->tightQualityLevel = -1;
 
246
      for (i = 0; i < 4; i++)
 
247
        cl->zsActive[i] = FALSE;
 
248
#endif
 
249
 
 
250
      cl->enableCursorUpdates = FALSE;
 
251
      cl->useRichCursorEncoding = FALSE;
 
252
      cl->enableLastRectEncoding = FALSE;
 
253
      cl->useNewFBSize = FALSE;
 
254
 
 
255
#ifdef VINO_HAVE_ZLIB
 
256
      cl->compStreamInited = FALSE;
 
257
      cl->compStream.total_in = 0;
 
258
      cl->compStream.total_out = 0;
 
259
      cl->compStream.zalloc = Z_NULL;
 
260
      cl->compStream.zfree = Z_NULL;
 
261
      cl->compStream.opaque = Z_NULL;
 
262
 
 
263
      cl->zlibCompressLevel = 5;
 
264
#endif
 
265
 
 
266
      sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion,
 
267
              rfbProtocolMinorVersion7);
 
268
 
 
269
      if (WriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
 
270
        rfbLogPerror("rfbNewClient: write");
 
271
        rfbCloseClient(cl);
 
272
        rfbClientConnectionGone(cl);
 
273
        return NULL;
 
274
      }
 
275
    }
 
276
 
 
277
    cl->clientData = NULL;
 
278
    cl->clientGoneHook = NULL;
 
279
    cl->onHold = FALSE;
 
280
    if (cl->screen->newClientHook) {
 
281
        switch (cl->screen->newClientHook(cl)) {
 
282
        case RFB_CLIENT_ON_HOLD:
 
283
            cl->onHold = TRUE;
 
284
            break;
 
285
        case RFB_CLIENT_ACCEPT:
 
286
            break;
 
287
        case RFB_CLIENT_REFUSE:
 
288
            rfbCloseClient(cl);
 
289
            rfbClientConnectionGone(cl);
 
290
            cl = NULL;
 
291
            break;
 
292
        }
 
293
    }
 
294
 
 
295
    return cl;
 
296
}
 
297
 
 
298
/*
 
299
 * rfbClientConnectionGone is called from sockets.c just after a connection
 
300
 * has gone away.
 
301
 */
 
302
 
 
303
void
 
304
rfbClientConnectionGone(rfbClientPtr cl)
 
305
{
 
306
    int i;
 
307
 
 
308
    LOCK(rfbClientListMutex);
 
309
 
 
310
    if (cl->prev)
 
311
        cl->prev->next = cl->next;
 
312
    else
 
313
        cl->screen->rfbClientHead = cl->next;
 
314
    if (cl->next)
 
315
        cl->next->prev = cl->prev;
 
316
 
 
317
    if(cl->sock>0)
 
318
        close(cl->sock);
 
319
 
 
320
#ifdef VINO_HAVE_ZLIB
 
321
    FreeZrleData(cl);
 
322
#endif
 
323
 
 
324
    if(cl->sock>=0)
 
325
       FD_CLR(cl->sock,&(cl->screen->allFds));
 
326
 
 
327
    if (cl->clientGoneHook)
 
328
      cl->clientGoneHook(cl);
 
329
 
 
330
    rfbLog("Client %s gone\n",cl->host);
 
331
    free(cl->host);
 
332
 
 
333
#ifdef VINO_HAVE_ZLIB
 
334
    /* Release the compression state structures if any. */
 
335
    if ( cl->compStreamInited ) {
 
336
        deflateEnd( &(cl->compStream) );
 
337
    }
 
338
 
 
339
#ifdef VINO_HAVE_JPEG
 
340
    for (i = 0; i < 4; i++) {
 
341
        if (cl->zsActive[i])
 
342
            deflateEnd(&cl->zsStruct[i]);
 
343
    }
 
344
#endif
 
345
#endif
 
346
 
 
347
    if (pointerClient == cl)
 
348
        pointerClient = NULL;
 
349
 
 
350
    sraRgnDestroy(cl->modifiedRegion);
 
351
    sraRgnDestroy(cl->requestedRegion);
 
352
    sraRgnDestroy(cl->copyRegion);
 
353
 
 
354
    UNLOCK(rfbClientListMutex);
 
355
 
 
356
    if (cl->translateLookupTable) free(cl->translateLookupTable);
 
357
 
 
358
    rfbPrintStats(cl);
 
359
 
 
360
    free(cl);
 
361
}
 
362
 
 
363
 
 
364
/*
 
365
 * rfbProcessClientMessage is called when there is data to read from a client.
 
366
 */
 
367
 
 
368
void
 
369
rfbProcessClientMessage(rfbClientPtr cl)
 
370
{
 
371
    switch (cl->state) {
 
372
    case RFB_PROTOCOL_VERSION:
 
373
        rfbProcessClientProtocolVersion(cl);
 
374
        return;
 
375
    case RFB_SECURITY_TYPE:
 
376
        rfbAuthProcessSecurityTypeMessage(cl);
 
377
        return;
 
378
#ifdef VINO_HAVE_GNUTLS
 
379
    case RFB_TLS_HANDSHAKE:
 
380
        rfbAuthProcessTLSHandshake(cl);
 
381
        return;
 
382
#endif
 
383
    case RFB_AUTH_TYPE:
 
384
        rfbAuthProcessAuthTypeMessage(cl);
 
385
        return;
 
386
    case RFB_AUTHENTICATION:
 
387
        rfbAuthProcessClientMessage(cl);
 
388
        return;
 
389
    case RFB_AUTH_DEFERRED:
 
390
        rfbLog("Authentication deferred - ignoring client message\n");
 
391
        return;
 
392
    case RFB_INITIALISATION:
 
393
        rfbProcessClientInitMessage(cl);
 
394
        return;
 
395
    default:
 
396
        rfbProcessClientNormalMessage(cl);
 
397
        return;
 
398
    }
 
399
}
 
400
 
 
401
 
 
402
/*
 
403
 * rfbProcessClientProtocolVersion is called when the client sends its
 
404
 * protocol version.
 
405
 */
 
406
 
 
407
static void
 
408
rfbProcessClientProtocolVersion(rfbClientPtr cl)
 
409
{
 
410
    rfbProtocolVersionMsg pv;
 
411
    int n, major_, minor_;
 
412
 
 
413
    if ((n = ReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
 
414
        if (n == 0)
 
415
            rfbLog("rfbProcessClientProtocolVersion: client gone\n");
 
416
        else
 
417
            rfbLogPerror("rfbProcessClientProtocolVersion: read");
 
418
        rfbCloseClient(cl);
 
419
        return;
 
420
    }
 
421
 
 
422
    pv[sz_rfbProtocolVersionMsg] = 0;
 
423
    if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
 
424
        char name[1024]; 
 
425
        if(sscanf(pv,"RFB %03d.%03d %1023s\n",&major_,&minor_,name) != 3) {
 
426
            rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client\n");
 
427
            rfbCloseClient(cl);
 
428
            return;
 
429
        }
 
430
        free(cl->host);
 
431
        cl->host=strdup(name);
 
432
    }
 
433
    rfbLog("Client Protocol Version %d.%d\n", major_, minor_);
 
434
 
 
435
    if (major_ != rfbProtocolMajorVersion) {
 
436
        rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d",
 
437
                rfbProtocolMajorVersion, rfbProtocolMinorVersion7,
 
438
                major_,minor_);
 
439
        rfbCloseClient(cl);
 
440
        return;
 
441
    }
 
442
 
 
443
    if (minor_ != rfbProtocolMinorVersion3 &&
 
444
        minor_ != rfbProtocolMinorVersion7 &&
 
445
        minor_ != rfbProtocolMinorVersion8) {
 
446
        /* Minor version mismatch - warn but try to continue */
 
447
        rfbLog("Ignoring minor version mismatch\n");
 
448
    }
 
449
 
 
450
    if (minor_ >= rfbProtocolMinorVersion8)
 
451
      cl->minorVersion = rfbProtocolMinorVersion8;
 
452
    else if (minor_ == rfbProtocolMinorVersion7)
 
453
      cl->minorVersion = rfbProtocolMinorVersion7;
 
454
    else
 
455
      cl->minorVersion = rfbProtocolMinorVersion3;
 
456
 
 
457
    rfbAuthNewClient(cl);
 
458
}
 
459
 
 
460
 
 
461
/*
 
462
 * rfbClientConnFailed is called when a client connection has failed either
 
463
 * because it talks the wrong protocol or it has failed authentication.
 
464
 */
 
465
 
 
466
void
 
467
rfbClientConnFailed(rfbClientPtr cl,
 
468
                    char *reason)
 
469
{
 
470
    char *buf;
 
471
    int len = strlen(reason);
 
472
 
 
473
    rfbLog("rfbClientConnFailed(\"%s\")\n", reason);
 
474
 
 
475
    buf = (char *)malloc(8 + len);
 
476
    ((uint32_t *)buf)[0] = 0;
 
477
    ((uint32_t *)buf)[1] = Swap32IfLE(len);
 
478
    memcpy(buf + 8, reason, len);
 
479
 
 
480
    if (WriteExact(cl, buf, 8 + len) < 0)
 
481
        rfbLogPerror("rfbClientConnFailed: write");
 
482
    free(buf);
 
483
 
 
484
    rfbCloseClient(cl);
 
485
}
 
486
 
 
487
 
 
488
/*
 
489
 * rfbProcessClientInitMessage is called when the client sends its
 
490
 * initialisation message.
 
491
 */
 
492
 
 
493
void
 
494
rfbProcessClientInitMessage(rfbClientPtr cl)
 
495
{
 
496
    rfbClientInitMsg ci;
 
497
    char buf[256];
 
498
    rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
 
499
    int len, n;
 
500
    rfbClientIteratorPtr iterator;
 
501
    rfbClientPtr otherCl;
 
502
 
 
503
    if ((n = ReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
 
504
        if (n == 0)
 
505
            rfbLog("rfbProcessClientInitMessage: client gone\n");
 
506
        else
 
507
            rfbLogPerror("rfbProcessClientInitMessage: read");
 
508
        rfbCloseClient(cl);
 
509
        return;
 
510
    }
 
511
 
 
512
    memset(buf,0,sizeof(buf));
 
513
 
 
514
    si->framebufferWidth = Swap16IfLE(cl->screen->width);
 
515
    si->framebufferHeight = Swap16IfLE(cl->screen->height);
 
516
    si->format = cl->screen->rfbServerFormat;
 
517
    si->format.redMax = Swap16IfLE(si->format.redMax);
 
518
    si->format.greenMax = Swap16IfLE(si->format.greenMax);
 
519
    si->format.blueMax = Swap16IfLE(si->format.blueMax);
 
520
 
 
521
    strncpy(buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127);
 
522
    len = strlen(buf + sz_rfbServerInitMsg);
 
523
    si->nameLength = Swap32IfLE(len);
 
524
 
 
525
    if (WriteExact(cl, buf, sz_rfbServerInitMsg + len) < 0) {
 
526
        rfbLogPerror("rfbProcessClientInitMessage: write");
 
527
        rfbCloseClient(cl);
 
528
        return;
 
529
    }
 
530
 
 
531
    cl->state = RFB_NORMAL;
 
532
 
 
533
    if (cl->screen->rfbNeverShared || (!cl->screen->rfbAlwaysShared && !ci.shared)) {
 
534
 
 
535
        if (cl->screen->rfbDontDisconnect) {
 
536
            iterator = rfbGetClientIterator(cl->screen);
 
537
            while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
 
538
                if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
 
539
                    rfbLog("-dontdisconnect: Not shared & existing client\n");
 
540
                    rfbLog("  refusing new client %s\n", cl->host);
 
541
                    rfbCloseClient(cl);
 
542
                    rfbReleaseClientIterator(iterator);
 
543
                    return;
 
544
                }
 
545
            }
 
546
            rfbReleaseClientIterator(iterator);
 
547
        } else {
 
548
            iterator = rfbGetClientIterator(cl->screen);
 
549
            while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
 
550
                if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
 
551
                    rfbLog("Not shared - closing connection to client %s\n",
 
552
                           otherCl->host);
 
553
                    rfbCloseClient(otherCl);
 
554
                }
 
555
            }
 
556
            rfbReleaseClientIterator(iterator);
 
557
        }
 
558
    }
 
559
}
 
560
 
 
561
 
 
562
/*
 
563
 * rfbProcessClientNormalMessage is called when the client has sent a normal
 
564
 * protocol message.
 
565
 */
 
566
 
 
567
static void
 
568
rfbProcessClientNormalMessage(rfbClientPtr cl)
 
569
{
 
570
    int n=0;
 
571
    rfbClientToServerMsg msg;
 
572
    char *str;
 
573
 
 
574
    if ((n = ReadExact(cl, (char *)&msg, 1)) <= 0) {
 
575
        if (n != 0)
 
576
            rfbLogPerror("rfbProcessClientNormalMessage: read");
 
577
        rfbCloseClient(cl);
 
578
        return;
 
579
    }
 
580
 
 
581
    switch (msg.type) {
 
582
 
 
583
    case rfbSetPixelFormat:
 
584
 
 
585
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
 
586
                           sz_rfbSetPixelFormatMsg - 1)) <= 0) {
 
587
            if (n != 0)
 
588
                rfbLogPerror("rfbProcessClientNormalMessage: read");
 
589
            rfbCloseClient(cl);
 
590
            return;
 
591
        }
 
592
 
 
593
        cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
 
594
        cl->format.depth = msg.spf.format.depth;
 
595
        cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
 
596
        cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
 
597
        cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
 
598
        cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
 
599
        cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
 
600
        cl->format.redShift = msg.spf.format.redShift;
 
601
        cl->format.greenShift = msg.spf.format.greenShift;
 
602
        cl->format.blueShift = msg.spf.format.blueShift;
 
603
 
 
604
        cl->readyForSetColourMapEntries = TRUE;
 
605
 
 
606
        rfbSetTranslateFunction(cl);
 
607
 
 
608
        return;
 
609
 
 
610
 
 
611
    case rfbFixColourMapEntries:
 
612
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
 
613
                           sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
 
614
            if (n != 0)
 
615
                rfbLogPerror("rfbProcessClientNormalMessage: read");
 
616
            rfbCloseClient(cl);
 
617
            return;
 
618
        }
 
619
        rfbLog("rfbProcessClientNormalMessage: %s",
 
620
                "FixColourMapEntries unsupported\n");
 
621
        rfbCloseClient(cl);
 
622
        return;
 
623
 
 
624
 
 
625
    case rfbSetEncodings:
 
626
    {
 
627
        int i;
 
628
        uint32_t enc;
 
629
        rfbBool enableCursorShapeUpdates, enableCursorPosUpdates;
 
630
        rfbBool useRichCursorEncoding;
 
631
 
 
632
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
 
633
                           sz_rfbSetEncodingsMsg - 1)) <= 0) {
 
634
            if (n != 0)
 
635
                rfbLogPerror("rfbProcessClientNormalMessage: read");
 
636
            rfbCloseClient(cl);
 
637
            return;
 
638
        }
 
639
 
 
640
        msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
 
641
 
 
642
        enableCursorShapeUpdates = FALSE;
 
643
        enableCursorPosUpdates = FALSE;
 
644
        useRichCursorEncoding = FALSE;
 
645
 
 
646
        cl->preferredEncoding = -1;
 
647
        cl->useCopyRect = FALSE;
 
648
        cl->enableLastRectEncoding = FALSE;
 
649
        cl->useNewFBSize = FALSE;
 
650
#ifdef VINO_HAVE_JPEG
 
651
        cl->tightQualityLevel = -1;
 
652
#endif
 
653
 
 
654
        for (i = 0; i < msg.se.nEncodings; i++) {
 
655
            if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
 
656
                if (n != 0)
 
657
                    rfbLogPerror("rfbProcessClientNormalMessage: read");
 
658
                rfbCloseClient(cl);
 
659
                return;
 
660
            }
 
661
            enc = Swap32IfLE(enc);
 
662
 
 
663
            switch (enc) {
 
664
 
 
665
            case rfbEncodingCopyRect:
 
666
                cl->useCopyRect = TRUE;
 
667
                break;
 
668
            case rfbEncodingRaw:
 
669
            case rfbEncodingRRE:
 
670
            case rfbEncodingCoRRE:
 
671
            case rfbEncodingHextile:
 
672
#ifdef VINO_HAVE_ZLIB
 
673
            case rfbEncodingZlib:
 
674
            case rfbEncodingZRLE:
 
675
#ifdef VINO_HAVE_JPEG
 
676
            case rfbEncodingTight:
 
677
#endif
 
678
#endif
 
679
            /* The first supported encoding is the 'preferred' encoding */
 
680
                if (cl->preferredEncoding == -1)
 
681
                    cl->preferredEncoding = enc;
 
682
 
 
683
 
 
684
                break;
 
685
            case rfbEncodingXCursor:
 
686
                enableCursorShapeUpdates = TRUE;
 
687
                break;
 
688
            case rfbEncodingRichCursor:
 
689
                enableCursorShapeUpdates = TRUE;
 
690
                useRichCursorEncoding = TRUE;
 
691
                break;
 
692
            case rfbEncodingPointerPos:
 
693
                enableCursorPosUpdates = TRUE;
 
694
                break;
 
695
            case rfbEncodingLastRect:
 
696
                if (!cl->enableLastRectEncoding) {
 
697
                    rfbLog("Enabling LastRect protocol extension for client "
 
698
                           "%s\n", cl->host);
 
699
                    cl->enableLastRectEncoding = TRUE;
 
700
                }
 
701
                break;
 
702
            case rfbEncodingNewFBSize:
 
703
                if (!cl->useNewFBSize) {
 
704
                    rfbLog("Enabling NewFBSize protocol extension for client "
 
705
                           "%s\n", cl->host);
 
706
                    cl->useNewFBSize = TRUE;
 
707
                }
 
708
                break;
 
709
            default:
 
710
#ifdef VINO_HAVE_ZLIB
 
711
                if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
 
712
                     enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
 
713
                    cl->zlibCompressLevel = enc & 0x0F;
 
714
#ifdef VINO_HAVE_JPEG
 
715
                    cl->tightCompressLevel = enc & 0x0F;
 
716
                    rfbLog("Using compression level %d for client %s\n",
 
717
                           cl->tightCompressLevel, cl->host);
 
718
                } else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 &&
 
719
                            enc <= (uint32_t)rfbEncodingQualityLevel9 ) {
 
720
                    cl->tightQualityLevel = enc & 0x0F;
 
721
                    rfbLog("Using image quality level %d for client %s\n",
 
722
                           cl->tightQualityLevel, cl->host);
 
723
#endif
 
724
                } else
 
725
#endif
 
726
                 rfbLog("rfbProcessClientNormalMessage: ignoring unknown "
 
727
                       "encoding type %d\n", (int)enc);
 
728
            }
 
729
        }
 
730
 
 
731
        if (cl->preferredEncoding == -1) {
 
732
            cl->preferredEncoding = rfbEncodingRaw;
 
733
        }
 
734
 
 
735
        if (enableCursorPosUpdates && enableCursorShapeUpdates) {
 
736
          rfbLog("Enabling cursor position and shape (%s encoding) updates for client %s\n",
 
737
                 useRichCursorEncoding ? "rich" : "X", cl->host);
 
738
          cl->enableCursorUpdates = TRUE;
 
739
          cl->useRichCursorEncoding = useRichCursorEncoding;
 
740
        } else {
 
741
          cl->enableCursorUpdates = FALSE;
 
742
          cl->useRichCursorEncoding = FALSE;
 
743
        }
 
744
 
 
745
        return;
 
746
    }
 
747
 
 
748
 
 
749
    case rfbFramebufferUpdateRequest:
 
750
    {
 
751
        sraRegionPtr tmpRegion;
 
752
 
 
753
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
 
754
                           sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
 
755
            if (n != 0)
 
756
                rfbLogPerror("rfbProcessClientNormalMessage: read");
 
757
            rfbCloseClient(cl);
 
758
            return;
 
759
        }
 
760
 
 
761
        tmpRegion =
 
762
          sraRgnCreateRect(Swap16IfLE(msg.fur.x),
 
763
                           Swap16IfLE(msg.fur.y),
 
764
                           Swap16IfLE(msg.fur.x)+Swap16IfLE(msg.fur.w),
 
765
                           Swap16IfLE(msg.fur.y)+Swap16IfLE(msg.fur.h));
 
766
 
 
767
        LOCK(cl->updateMutex);
 
768
        sraRgnOr(cl->requestedRegion,tmpRegion);
 
769
 
 
770
        if (!cl->readyForSetColourMapEntries) {
 
771
            /* client hasn't sent a SetPixelFormat so is using server's */
 
772
            cl->readyForSetColourMapEntries = TRUE;
 
773
            if (!cl->format.trueColour) {
 
774
                if (!rfbSetClientColourMap(cl, 0, 0)) {
 
775
                    sraRgnDestroy(tmpRegion);
 
776
                    UNLOCK(cl->updateMutex);
 
777
                    return;
 
778
                }
 
779
            }
 
780
        }
 
781
 
 
782
       if (!msg.fur.incremental) {
 
783
            sraRgnOr(cl->modifiedRegion,tmpRegion);
 
784
            sraRgnSubtract(cl->copyRegion,tmpRegion);
 
785
       }
 
786
       UNLOCK(cl->updateMutex);
 
787
 
 
788
       sraRgnDestroy(tmpRegion);
 
789
 
 
790
       return;
 
791
    }
 
792
 
 
793
    case rfbKeyEvent:
 
794
 
 
795
        cl->rfbKeyEventsRcvd++;
 
796
 
 
797
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
 
798
                           sz_rfbKeyEventMsg - 1)) <= 0) {
 
799
            if (n != 0)
 
800
                rfbLogPerror("rfbProcessClientNormalMessage: read");
 
801
            rfbCloseClient(cl);
 
802
            return;
 
803
        }
 
804
 
 
805
        if(!cl->viewOnly && cl->screen->kbdAddEvent) {
 
806
            cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
 
807
        }
 
808
 
 
809
        return;
 
810
 
 
811
 
 
812
    case rfbPointerEvent:
 
813
 
 
814
        cl->rfbPointerEventsRcvd++;
 
815
 
 
816
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
 
817
                           sz_rfbPointerEventMsg - 1)) <= 0) {
 
818
            if (n != 0)
 
819
                rfbLogPerror("rfbProcessClientNormalMessage: read");
 
820
            rfbCloseClient(cl);
 
821
            return;
 
822
        }
 
823
 
 
824
        if (pointerClient && (pointerClient != cl))
 
825
            return;
 
826
 
 
827
        if (msg.pe.buttonMask == 0)
 
828
            pointerClient = NULL;
 
829
        else
 
830
            pointerClient = cl;
 
831
 
 
832
        if(!cl->viewOnly) {
 
833
            cl->screen->ptrAddEvent(msg.pe.buttonMask,
 
834
                                    Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
 
835
        }
 
836
 
 
837
        return;
 
838
 
 
839
 
 
840
    case rfbClientCutText:
 
841
 
 
842
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
 
843
                           sz_rfbClientCutTextMsg - 1)) <= 0) {
 
844
            if (n != 0)
 
845
                rfbLogPerror("rfbProcessClientNormalMessage: read");
 
846
            rfbCloseClient(cl);
 
847
            return;
 
848
        }
 
849
 
 
850
        msg.cct.length = Swap32IfLE(msg.cct.length);
 
851
 
 
852
        str = (char *)malloc(msg.cct.length);
 
853
 
 
854
        if ((n = ReadExact(cl, str, msg.cct.length)) <= 0) {
 
855
            if (n != 0)
 
856
                rfbLogPerror("rfbProcessClientNormalMessage: read");
 
857
            free(str);
 
858
            rfbCloseClient(cl);
 
859
            return;
 
860
        }
 
861
 
 
862
        if(!cl->viewOnly) {
 
863
            if (cl->screen->setXCutText)
 
864
              cl->screen->setXCutText(str, msg.cct.length, cl);
 
865
        }
 
866
        free(str);
 
867
 
 
868
        return;
 
869
 
 
870
 
 
871
    default:
 
872
 
 
873
        rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
 
874
                msg.type);
 
875
        rfbLog(" ... closing connection\n");
 
876
        rfbCloseClient(cl);
 
877
        return;
 
878
    }
 
879
}
 
880
 
 
881
 
 
882
 
 
883
/*
 
884
 * rfbSendFramebufferUpdate - send the currently pending framebuffer update to
 
885
 * the RFB client.
 
886
 * givenUpdateRegion is not changed.
 
887
 */
 
888
 
 
889
rfbBool
 
890
rfbSendFramebufferUpdate(rfbClientPtr cl,
 
891
                         sraRegionPtr givenUpdateRegion)
 
892
{
 
893
    sraRectangleIterator* i=NULL;
 
894
    sraRect rect;
 
895
    int nUpdateRegionRects;
 
896
    rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf;
 
897
    sraRegionPtr updateRegion, updateCopyRegion, tmpRegion, cursorRegion;
 
898
    sraRect cursorBounds = { 0, 0, 0, 0 };
 
899
    int dx, dy;
 
900
    rfbBool sendCursorShape = FALSE;
 
901
    rfbBool sendCursorPos = FALSE;
 
902
    rfbBool cursorIsDrawn = FALSE;
 
903
 
 
904
    /*
 
905
     * If framebuffer size was changed and the client supports NewFBSize
 
906
     * encoding, just send NewFBSize marker and return.
 
907
     */
 
908
 
 
909
    if (cl->useNewFBSize && cl->newFBSizePending) {
 
910
      LOCK(cl->updateMutex);
 
911
      cl->newFBSizePending = FALSE;
 
912
      UNLOCK(cl->updateMutex);
 
913
      cl->rfbFramebufferUpdateMessagesSent++;
 
914
      fu->type = rfbFramebufferUpdate;
 
915
      fu->nRects = Swap16IfLE(1);
 
916
      cl->ublen = sz_rfbFramebufferUpdateMsg;
 
917
      if (!rfbSendNewFBSize(cl, cl->screen->width, cl->screen->height)) {
 
918
        return FALSE;
 
919
      }
 
920
      return rfbSendUpdateBuf(cl);
 
921
    }
 
922
 
 
923
    LOCK(cl->updateMutex);
 
924
 
 
925
    /*
 
926
     * The modifiedRegion may overlap the destination copyRegion.  We remove
 
927
     * any overlapping bits from the copyRegion (since they'd only be
 
928
     * overwritten anyway).
 
929
     */
 
930
    
 
931
    sraRgnSubtract(cl->copyRegion,cl->modifiedRegion);
 
932
 
 
933
    updateRegion = sraRgnCreateRgn(givenUpdateRegion);
 
934
    sraRgnOr(updateRegion,cl->copyRegion);
 
935
 
 
936
    /*
 
937
     * If the client doesn't support cursor updates, we want to draw
 
938
     * the cursor locally, send the update and then undraw it.
 
939
     * We only want to do this if the cursor has moved/changed or
 
940
     * if it is contained in updateRegion
 
941
     *
 
942
     * We also want to send an update for the region where the cursor
 
943
     * was last drawn, again only if the cursor has moved/changed.
 
944
     */
 
945
 
 
946
    LOCK(cl->screen->cursorMutex);
 
947
 
 
948
    cursorRegion = NULL;
 
949
    if (cl->enableCursorUpdates) {
 
950
        sendCursorShape = cl->cursorWasChanged;
 
951
        sendCursorPos   = cl->cursorWasMoved;
 
952
    } else {
 
953
        sraRegionPtr lastDrawnCursorRegion;
 
954
 
 
955
        if (rfbGetCursorBounds(cl->screen, &cursorBounds)) {
 
956
            cursorRegion = sraRgnCreateRect(cursorBounds.x1, cursorBounds.y1,
 
957
                                            cursorBounds.x2, cursorBounds.y2);
 
958
        }
 
959
        
 
960
        lastDrawnCursorRegion = sraRgnCreateRect(cl->lastDrawnCursorBounds.x1,
 
961
                                                 cl->lastDrawnCursorBounds.y1,
 
962
                                                 cl->lastDrawnCursorBounds.x2,
 
963
                                                 cl->lastDrawnCursorBounds.y2);
 
964
 
 
965
        if (cursorRegion) {
 
966
            sraRgnOr(cursorRegion, lastDrawnCursorRegion);
 
967
            sraRgnDestroy(lastDrawnCursorRegion);
 
968
        } else {
 
969
            cursorRegion = lastDrawnCursorRegion;
 
970
        }
 
971
 
 
972
        if (cl->cursorWasChanged || cl->cursorWasMoved)
 
973
            sraRgnOr(updateRegion, cursorRegion);
 
974
    }
 
975
 
 
976
    /*
 
977
     * The client is interested in the region requestedRegion.  The region
 
978
     * which should be updated now is the intersection of requestedRegion
 
979
     * and the union of modifiedRegion and copyRegion.  If it's empty then
 
980
     * no update is needed.
 
981
     */
 
982
 
 
983
    if (!sraRgnAnd(updateRegion, cl->requestedRegion) &&
 
984
        !sendCursorShape && !sendCursorPos) {
 
985
        sraRgnDestroy(updateRegion);
 
986
        if (cursorRegion)
 
987
            sraRgnDestroy(cursorRegion);
 
988
        UNLOCK(cl->updateMutex);
 
989
        UNLOCK(cl->cursorMutex);
 
990
        return TRUE;
 
991
    }
 
992
 
 
993
    /*
 
994
     * Put up the cursor if any part of it is in updateRegion.
 
995
     */
 
996
 
 
997
    if (cursorRegion) {
 
998
        tmpRegion = sraRgnCreateRgn(cursorRegion);
 
999
 
 
1000
        if (sraRgnAnd(tmpRegion, updateRegion)) {
 
1001
            rfbDrawCursor(cl->screen, &cursorBounds);
 
1002
            cursorIsDrawn = TRUE;
 
1003
 
 
1004
            cl->cursorWasMoved = FALSE;
 
1005
            cl->cursorWasChanged = FALSE;
 
1006
            cl->lastDrawnCursorBounds = cursorBounds;
 
1007
 
 
1008
            sraRgnOr(cl->modifiedRegion, cursorRegion);
 
1009
            
 
1010
            sraRgnOr(updateRegion, cursorRegion);
 
1011
            sraRgnAnd(updateRegion, cl->requestedRegion);
 
1012
        }
 
1013
 
 
1014
        sraRgnDestroy(tmpRegion);
 
1015
        sraRgnDestroy(cursorRegion);
 
1016
    }
 
1017
 
 
1018
    /*
 
1019
     * We assume that the client doesn't have any pixel data outside the
 
1020
     * requestedRegion.  In other words, both the source and destination of a
 
1021
     * copy must lie within requestedRegion.  So the region we can send as a
 
1022
     * copy is the intersection of the copyRegion with both the requestedRegion
 
1023
     * and the requestedRegion translated by the amount of the copy.  We set
 
1024
     * updateCopyRegion to this.
 
1025
     */
 
1026
 
 
1027
    updateCopyRegion = sraRgnCreateRgn(cl->copyRegion);
 
1028
    sraRgnAnd(updateCopyRegion,cl->requestedRegion);
 
1029
    tmpRegion = sraRgnCreateRgn(cl->requestedRegion);
 
1030
    sraRgnOffset(tmpRegion,cl->copyDX,cl->copyDY);
 
1031
    sraRgnAnd(updateCopyRegion,tmpRegion);
 
1032
    sraRgnDestroy(tmpRegion);
 
1033
    dx = cl->copyDX;
 
1034
    dy = cl->copyDY;
 
1035
 
 
1036
    /*
 
1037
     * Next we remove updateCopyRegion from updateRegion so that updateRegion
 
1038
     * is the part of this update which is sent as ordinary pixel data (i.e not
 
1039
     * a copy).
 
1040
     */
 
1041
 
 
1042
    sraRgnSubtract(updateRegion,updateCopyRegion);
 
1043
 
 
1044
    /*
 
1045
     * Finally we leave modifiedRegion to be the remainder (if any) of parts of
 
1046
     * the screen which are modified but outside the requestedRegion.  We also
 
1047
     * empty both the requestedRegion and the copyRegion - note that we never
 
1048
     * carry over a copyRegion for a future update.
 
1049
     */
 
1050
 
 
1051
     sraRgnOr(cl->modifiedRegion,cl->copyRegion);
 
1052
     sraRgnSubtract(cl->modifiedRegion,updateRegion);
 
1053
     sraRgnSubtract(cl->modifiedRegion,updateCopyRegion);
 
1054
 
 
1055
     sraRgnMakeEmpty(cl->requestedRegion);
 
1056
     sraRgnMakeEmpty(cl->copyRegion);
 
1057
     cl->copyDX = 0;
 
1058
     cl->copyDY = 0;
 
1059
   
 
1060
     UNLOCK(cl->updateMutex);
 
1061
   
 
1062
   /*
 
1063
     * Now send the update.
 
1064
     */
 
1065
 
 
1066
    cl->rfbFramebufferUpdateMessagesSent++;
 
1067
 
 
1068
    if (cl->preferredEncoding == rfbEncodingCoRRE) {
 
1069
        nUpdateRegionRects = 0;
 
1070
 
 
1071
        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
 
1072
            int x = rect.x1;
 
1073
            int y = rect.y1;
 
1074
            int w = rect.x2 - x;
 
1075
            int h = rect.y2 - y;
 
1076
            nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1)
 
1077
                                     * ((h-1) / cl->correMaxHeight + 1));
 
1078
        }
 
1079
        sraRgnReleaseIterator(i);
 
1080
#ifdef VINO_HAVE_ZLIB
 
1081
    } else if (cl->preferredEncoding == rfbEncodingZlib) {
 
1082
        nUpdateRegionRects = 0;
 
1083
 
 
1084
        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
 
1085
            int x = rect.x1;
 
1086
            int y = rect.y1;
 
1087
            int w = rect.x2 - x;
 
1088
            int h = rect.y2 - y;
 
1089
            nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1);
 
1090
        }
 
1091
#ifdef VINO_HAVE_JPEG
 
1092
    } else if (cl->preferredEncoding == rfbEncodingTight) {
 
1093
        nUpdateRegionRects = 0;
 
1094
 
 
1095
        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
 
1096
            int x = rect.x1;
 
1097
            int y = rect.y1;
 
1098
            int w = rect.x2 - x;
 
1099
            int h = rect.y2 - y;
 
1100
            int n = rfbNumCodedRectsTight(cl, x, y, w, h);
 
1101
            if (n == 0) {
 
1102
                nUpdateRegionRects = 0xFFFF;
 
1103
                break;
 
1104
            }
 
1105
            nUpdateRegionRects += n;
 
1106
        }
 
1107
        sraRgnReleaseIterator(i);
 
1108
#endif
 
1109
#endif
 
1110
    } else {
 
1111
        nUpdateRegionRects = sraRgnCountRects(updateRegion);
 
1112
    }
 
1113
 
 
1114
    fu->type = rfbFramebufferUpdate;
 
1115
    if (nUpdateRegionRects != 0xFFFF) {
 
1116
        if(cl->screen->maxRectsPerUpdate>0
 
1117
           /* CoRRE splits the screen into smaller squares */
 
1118
           && cl->preferredEncoding != rfbEncodingCoRRE
 
1119
#ifdef VINO_HAVE_ZLIB
 
1120
           /* Zlib encoding splits rectangles up into smaller chunks */
 
1121
           && cl->preferredEncoding != rfbEncodingZlib
 
1122
#ifdef VINO_HAVE_JPEG
 
1123
           /* Tight encoding counts the rectangles differently */
 
1124
           && cl->preferredEncoding != rfbEncodingTight
 
1125
#endif
 
1126
#endif /* VINO_HAVE_ZLIB */
 
1127
           && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
 
1128
            sraRegion* newUpdateRegion = sraRgnBBox(updateRegion);
 
1129
            sraRgnDestroy(updateRegion);
 
1130
            updateRegion = newUpdateRegion;
 
1131
            nUpdateRegionRects = sraRgnCountRects(updateRegion);
 
1132
        }
 
1133
        fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
 
1134
                                           nUpdateRegionRects +
 
1135
                                           !!sendCursorShape + !!sendCursorPos));
 
1136
    } else {
 
1137
        fu->nRects = 0xFFFF;
 
1138
    }
 
1139
    cl->ublen = sz_rfbFramebufferUpdateMsg;
 
1140
 
 
1141
    UNLOCK(cl->cursorMutex);
 
1142
 
 
1143
   if (sendCursorShape) {
 
1144
        cl->cursorWasChanged = FALSE;
 
1145
        if (!rfbSendCursorShape(cl))
 
1146
            goto tx_error;
 
1147
    }
 
1148
   
 
1149
   if (sendCursorPos) {
 
1150
        cl->cursorWasMoved = FALSE;
 
1151
        if (!rfbSendCursorPos(cl))
 
1152
            goto tx_error;
 
1153
    }
 
1154
   
 
1155
    if (!sraRgnEmpty(updateCopyRegion)) {
 
1156
        if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy))
 
1157
            goto tx_error;
 
1158
    }
 
1159
 
 
1160
    for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
 
1161
        int x = rect.x1;
 
1162
        int y = rect.y1;
 
1163
        int w = rect.x2 - x;
 
1164
        int h = rect.y2 - y;
 
1165
 
 
1166
        cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader
 
1167
                                      + w * (cl->format.bitsPerPixel / 8) * h);
 
1168
 
 
1169
        /* Validate the rectangle given by the update packet. */
 
1170
        if (w + x > cl->screen->width || h + y > cl->screen->height)
 
1171
            goto tx_error;
 
1172
 
 
1173
        switch (cl->preferredEncoding) {
 
1174
        case rfbEncodingRaw:
 
1175
            if (!rfbSendRectEncodingRaw(cl, x, y, w, h))
 
1176
                goto tx_error;
 
1177
            break;
 
1178
        case rfbEncodingRRE:
 
1179
            if (!rfbSendRectEncodingRRE(cl, x, y, w, h))
 
1180
                goto tx_error;
 
1181
            break;
 
1182
        case rfbEncodingCoRRE:
 
1183
            if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h))
 
1184
                goto tx_error;
 
1185
            break;
 
1186
        case rfbEncodingHextile:
 
1187
            if (!rfbSendRectEncodingHextile(cl, x, y, w, h))
 
1188
                goto tx_error;
 
1189
            break;
 
1190
#ifdef VINO_HAVE_ZLIB
 
1191
        case rfbEncodingZlib:
 
1192
            if (!rfbSendRectEncodingZlib(cl, x, y, w, h))
 
1193
                goto tx_error;
 
1194
            break;
 
1195
#ifdef VINO_HAVE_JPEG
 
1196
        case rfbEncodingTight:
 
1197
            if (!rfbSendRectEncodingTight(cl, x, y, w, h))
 
1198
                goto tx_error;
 
1199
            break;
 
1200
#endif
 
1201
#endif
 
1202
#ifdef VINO_HAVE_ZLIB
 
1203
       case rfbEncodingZRLE:
 
1204
           if (!rfbSendRectEncodingZRLE(cl, x, y, w, h))
 
1205
               goto tx_error;
 
1206
           break;
 
1207
#endif
 
1208
        }
 
1209
    }
 
1210
 
 
1211
    if (cursorIsDrawn)
 
1212
        rfbUndrawCursor(cl->screen, &cursorBounds);
 
1213
 
 
1214
    if ( nUpdateRegionRects == 0xFFFF &&
 
1215
         !rfbSendLastRectMarker(cl) )
 
1216
        goto tx_error;
 
1217
 
 
1218
    if (!rfbSendUpdateBuf(cl))
 
1219
        goto tx_error;
 
1220
 
 
1221
    sraRgnReleaseIterator(i);
 
1222
    sraRgnDestroy(updateCopyRegion);
 
1223
    sraRgnDestroy(updateRegion);
 
1224
    
 
1225
    return TRUE;
 
1226
 
 
1227
 tx_error:
 
1228
    if (cursorIsDrawn)
 
1229
        rfbUndrawCursor(cl->screen, &cursorBounds);
 
1230
    if (i)
 
1231
        sraRgnReleaseIterator(i);
 
1232
 
 
1233
    sraRgnDestroy(updateCopyRegion);
 
1234
    sraRgnDestroy(updateRegion);
 
1235
 
 
1236
    return FALSE;
 
1237
}
 
1238
 
 
1239
 
 
1240
/*
 
1241
 * Send the copy region as a string of CopyRect encoded rectangles.
 
1242
 * The only slightly tricky thing is that we should send the messages in
 
1243
 * the correct order so that an earlier CopyRect will not corrupt the source
 
1244
 * of a later one.
 
1245
 */
 
1246
 
 
1247
rfbBool
 
1248
rfbSendCopyRegion(rfbClientPtr cl,
 
1249
                  sraRegionPtr reg,
 
1250
                  int dx,
 
1251
                  int dy)
 
1252
{
 
1253
    int x, y, w, h;
 
1254
    rfbFramebufferUpdateRectHeader rect;
 
1255
    rfbCopyRect cr;
 
1256
    sraRectangleIterator* i;
 
1257
    sraRect rect1;
 
1258
 
 
1259
    /* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */
 
1260
    i = sraRgnGetReverseIterator(reg,dx>0,dy>0);
 
1261
 
 
1262
    while(sraRgnIteratorNext(i,&rect1)) {
 
1263
      x = rect1.x1;
 
1264
      y = rect1.y1;
 
1265
      w = rect1.x2 - x;
 
1266
      h = rect1.y2 - y;
 
1267
 
 
1268
      rect.r.x = Swap16IfLE(x);
 
1269
      rect.r.y = Swap16IfLE(y);
 
1270
      rect.r.w = Swap16IfLE(w);
 
1271
      rect.r.h = Swap16IfLE(h);
 
1272
      rect.encoding = Swap32IfLE(rfbEncodingCopyRect);
 
1273
 
 
1274
      memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
 
1275
             sz_rfbFramebufferUpdateRectHeader);
 
1276
      cl->ublen += sz_rfbFramebufferUpdateRectHeader;
 
1277
 
 
1278
      cr.srcX = Swap16IfLE(x - dx);
 
1279
      cr.srcY = Swap16IfLE(y - dy);
 
1280
 
 
1281
      memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect);
 
1282
      cl->ublen += sz_rfbCopyRect;
 
1283
 
 
1284
      cl->rfbRectanglesSent[rfbEncodingCopyRect]++;
 
1285
      cl->rfbBytesSent[rfbEncodingCopyRect]
 
1286
        += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect;
 
1287
 
 
1288
    }
 
1289
 
 
1290
    return TRUE;
 
1291
}
 
1292
 
 
1293
/*
 
1294
 * Send a given rectangle in raw encoding (rfbEncodingRaw).
 
1295
 */
 
1296
 
 
1297
rfbBool
 
1298
rfbSendRectEncodingRaw(rfbClientPtr cl,
 
1299
                       int x,
 
1300
                       int y,
 
1301
                       int w,
 
1302
                       int h)
 
1303
{
 
1304
    rfbFramebufferUpdateRectHeader rect;
 
1305
    int nlines;
 
1306
    int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
 
1307
    char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
 
1308
                   + (x * (cl->screen->bitsPerPixel / 8)));
 
1309
 
 
1310
    /* Flush the buffer to guarantee correct alignment for translateFn(). */
 
1311
    if (cl->ublen > 0) {
 
1312
        if (!rfbSendUpdateBuf(cl))
 
1313
            return FALSE;
 
1314
    }
 
1315
 
 
1316
    rect.r.x = Swap16IfLE(x);
 
1317
    rect.r.y = Swap16IfLE(y);
 
1318
    rect.r.w = Swap16IfLE(w);
 
1319
    rect.r.h = Swap16IfLE(h);
 
1320
    rect.encoding = Swap32IfLE(rfbEncodingRaw);
 
1321
 
 
1322
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
 
1323
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
 
1324
 
 
1325
    cl->rfbRectanglesSent[rfbEncodingRaw]++;
 
1326
    cl->rfbBytesSent[rfbEncodingRaw]
 
1327
        += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h;
 
1328
 
 
1329
    nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
 
1330
 
 
1331
    while (TRUE) {
 
1332
        if (nlines > h)
 
1333
            nlines = h;
 
1334
 
 
1335
        (*cl->translateFn)(cl->translateLookupTable,
 
1336
                           &(cl->screen->rfbServerFormat),
 
1337
                           &cl->format, fbptr, &cl->updateBuf[cl->ublen],
 
1338
                           cl->screen->paddedWidthInBytes, w, nlines);
 
1339
 
 
1340
        cl->ublen += nlines * bytesPerLine;
 
1341
        h -= nlines;
 
1342
 
 
1343
        if (h == 0)     /* rect fitted in buffer, do next one */
 
1344
            return TRUE;
 
1345
 
 
1346
        /* buffer full - flush partial rect and do another nlines */
 
1347
 
 
1348
        if (!rfbSendUpdateBuf(cl))
 
1349
            return FALSE;
 
1350
 
 
1351
        fbptr += (cl->screen->paddedWidthInBytes * nlines);
 
1352
 
 
1353
        nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
 
1354
        if (nlines == 0) {
 
1355
            rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d "
 
1356
                   "bytes per line\n", bytesPerLine);
 
1357
            rfbCloseClient(cl);
 
1358
            return FALSE;
 
1359
        }
 
1360
    }
 
1361
}
 
1362
 
 
1363
 
 
1364
 
 
1365
/*
 
1366
 * Send an empty rectangle with encoding field set to value of
 
1367
 * rfbEncodingLastRect to notify client that this is the last
 
1368
 * rectangle in framebuffer update ("LastRect" extension of RFB
 
1369
 * protocol).
 
1370
 */
 
1371
 
 
1372
rfbBool
 
1373
rfbSendLastRectMarker(rfbClientPtr cl)
 
1374
{
 
1375
    rfbFramebufferUpdateRectHeader rect;
 
1376
 
 
1377
    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
 
1378
        if (!rfbSendUpdateBuf(cl))
 
1379
            return FALSE;
 
1380
    }
 
1381
 
 
1382
    rect.encoding = Swap32IfLE(rfbEncodingLastRect);
 
1383
    rect.r.x = 0;
 
1384
    rect.r.y = 0;
 
1385
    rect.r.w = 0;
 
1386
    rect.r.h = 0;
 
1387
 
 
1388
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
 
1389
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
 
1390
 
 
1391
    cl->rfbLastRectMarkersSent++;
 
1392
    cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
 
1393
 
 
1394
    return TRUE;
 
1395
}
 
1396
 
 
1397
 
 
1398
/*
 
1399
 * Send NewFBSize pseudo-rectangle. This tells the client to change
 
1400
 * its framebuffer size.
 
1401
 */
 
1402
 
 
1403
rfbBool
 
1404
rfbSendNewFBSize(rfbClientPtr cl,
 
1405
                 int w,
 
1406
                 int h)
 
1407
{
 
1408
    rfbFramebufferUpdateRectHeader rect;
 
1409
 
 
1410
    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
 
1411
        if (!rfbSendUpdateBuf(cl))
 
1412
            return FALSE;
 
1413
    }
 
1414
 
 
1415
    rect.encoding = Swap32IfLE(rfbEncodingNewFBSize);
 
1416
    rect.r.x = 0;
 
1417
    rect.r.y = 0;
 
1418
    rect.r.w = Swap16IfLE(w);
 
1419
    rect.r.h = Swap16IfLE(h);
 
1420
 
 
1421
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
 
1422
           sz_rfbFramebufferUpdateRectHeader);
 
1423
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
 
1424
 
 
1425
    cl->rfbLastRectMarkersSent++;
 
1426
    cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
 
1427
 
 
1428
    return TRUE;
 
1429
}
 
1430
 
 
1431
 
 
1432
/*
 
1433
 * Send the contents of cl->updateBuf.  Returns 1 if successful, -1 if
 
1434
 * not (errno should be set).
 
1435
 */
 
1436
 
 
1437
rfbBool
 
1438
rfbSendUpdateBuf(rfbClientPtr cl)
 
1439
{
 
1440
    if(cl->sock<0)
 
1441
      return FALSE;
 
1442
 
 
1443
    if (WriteExact(cl, cl->updateBuf, cl->ublen) < 0) {
 
1444
        rfbLogPerror("rfbSendUpdateBuf: write");
 
1445
        rfbCloseClient(cl);
 
1446
        return FALSE;
 
1447
    }
 
1448
 
 
1449
    cl->ublen = 0;
 
1450
    return TRUE;
 
1451
}
 
1452
 
 
1453
/*
 
1454
 * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the
 
1455
 * client, using values from the currently installed colormap.
 
1456
 */
 
1457
 
 
1458
rfbBool
 
1459
rfbSendSetColourMapEntries(rfbClientPtr cl,
 
1460
                           int firstColour,
 
1461
                           int nColours)
 
1462
{
 
1463
    char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
 
1464
    rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
 
1465
    uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]);
 
1466
    rfbColourMap* cm = &cl->screen->colourMap;
 
1467
    
 
1468
    int i, len;
 
1469
 
 
1470
    scme->type = rfbSetColourMapEntries;
 
1471
 
 
1472
    scme->firstColour = Swap16IfLE(firstColour);
 
1473
    scme->nColours = Swap16IfLE(nColours);
 
1474
 
 
1475
    len = sz_rfbSetColourMapEntriesMsg;
 
1476
 
 
1477
    for (i = 0; i < nColours; i++) {
 
1478
      if(i<(int)cm->count) {
 
1479
        if(cm->is16) {
 
1480
          rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]);
 
1481
          rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]);
 
1482
          rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]);
 
1483
        } else {
 
1484
          rgb[i*3] = Swap16IfLE(cm->data.bytes[i*3]);
 
1485
          rgb[i*3+1] = Swap16IfLE(cm->data.bytes[i*3+1]);
 
1486
          rgb[i*3+2] = Swap16IfLE(cm->data.bytes[i*3+2]);
 
1487
        }
 
1488
      }
 
1489
    }
 
1490
 
 
1491
    len += nColours * 3 * 2;
 
1492
 
 
1493
    if (WriteExact(cl, buf, len) < 0) {
 
1494
        rfbLogPerror("rfbSendSetColourMapEntries: write");
 
1495
        rfbCloseClient(cl);
 
1496
        return FALSE;
 
1497
    }
 
1498
    return TRUE;
 
1499
}
 
1500
 
 
1501
/*
 
1502
 * rfbSendBell sends a Bell message to all the clients.
 
1503
 */
 
1504
 
 
1505
void
 
1506
rfbSendBell(rfbScreenInfoPtr rfbScreen)
 
1507
{
 
1508
    rfbClientIteratorPtr i;
 
1509
    rfbClientPtr cl;
 
1510
    rfbBellMsg b;
 
1511
 
 
1512
    i = rfbGetClientIterator(rfbScreen);
 
1513
    while((cl=rfbClientIteratorNext(i))) {
 
1514
        b.type = rfbBell;
 
1515
        if (WriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) {
 
1516
            rfbLogPerror("rfbSendBell: write");
 
1517
            rfbCloseClient(cl);
 
1518
        }
 
1519
    }
 
1520
    rfbReleaseClientIterator(i);
 
1521
}
 
1522
 
 
1523
 
 
1524
/*
 
1525
 * rfbSendServerCutText sends a ServerCutText message to all the clients.
 
1526
 */
 
1527
 
 
1528
void
 
1529
rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
 
1530
{
 
1531
    rfbClientPtr cl;
 
1532
    rfbServerCutTextMsg sct;
 
1533
    rfbClientIteratorPtr iterator;
 
1534
 
 
1535
    iterator = rfbGetClientIterator(rfbScreen);
 
1536
    while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
 
1537
        sct.type = rfbServerCutText;
 
1538
        sct.length = Swap32IfLE(len);
 
1539
        if (WriteExact(cl, (char *)&sct,
 
1540
                       sz_rfbServerCutTextMsg) < 0) {
 
1541
            rfbLogPerror("rfbSendServerCutText: write");
 
1542
            rfbCloseClient(cl);
 
1543
            continue;
 
1544
        }
 
1545
        if (WriteExact(cl, str, len) < 0) {
 
1546
            rfbLogPerror("rfbSendServerCutText: write");
 
1547
            rfbCloseClient(cl);
 
1548
        }
 
1549
    }
 
1550
    rfbReleaseClientIterator(iterator);
 
1551
}