~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to common/ivs/libvncserver/rfbserver.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

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
 
#include <string.h>
28
 
#include <rfb/rfb.h>
29
 
#include <rfb/rfbregion.h>
30
 
 
31
 
#ifdef HAVE_FCNTL_H
32
 
#include <fcntl.h>
33
 
#endif
34
 
 
35
 
#ifdef WIN32
36
 
#define write(sock,buf,len) send(sock,buf,len,0)
37
 
#else
38
 
#ifdef HAVE_UNISTD_H
39
 
#include <unistd.h>
40
 
#endif
41
 
#include <pwd.h>
42
 
#ifdef HAVE_SYS_SOCKET_H
43
 
#include <sys/socket.h>
44
 
#endif
45
 
#ifdef HAVE_NETINET_IN_H
46
 
#include <netinet/in.h>
47
 
#include <netinet/tcp.h>
48
 
#include <arpa/inet.h>
49
 
#endif
50
 
#endif
51
 
 
52
 
#ifdef CORBA
53
 
#include <vncserverctrl.h>
54
 
#endif
55
 
 
56
 
#ifdef DEBUGPROTO
57
 
#undef DEBUGPROTO
58
 
#define DEBUGPROTO(x) x
59
 
#else
60
 
#define DEBUGPROTO(x)
61
 
#endif
62
 
 
63
 
 
64
 
 
65
 
#define ITALC_EXTENSIONS
66
 
 
67
 
#ifdef ITALC_EXTENSIONS
68
 
 
69
 
/* extensions for iTALC */
70
 
#include <italc_rfb_ext.h>
71
 
 
72
 
#define DEMO_VIEWER     "demoviewer "
73
 
#define SCREEN_LOCKER   "screenlocker &"
74
 
#define MESSAGE_VIEWER  "messageviewer "
75
 
#define SUPPORT_INVITOR "supportinvitor "
76
 
#define BUFFER_SIZE     1024
77
 
#define DEST_DIR        "/material/"
78
 
#define LIST_COMMAND    "ls -lf1 "
79
 
#define TMP_OUT_FILE    "/tmp/ivs_temp"
80
 
#define TMP_OUT_FILE_REDIR " > "TMP_OUT_FILE
81
 
#endif
82
 
 
83
 
 
84
 
 
85
 
 
86
 
rfbClientPtr pointerClient = NULL;  /* Mutex for pointer events */
87
 
 
88
 
static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
89
 
static void rfbProcessClientNormalMessage(rfbClientPtr cl);
90
 
static void rfbProcessClientInitMessage(rfbClientPtr cl);
91
 
 
92
 
#ifdef HAVE_LIBPTHREAD
93
 
void rfbIncrClientRef(rfbClientPtr cl)
94
 
{
95
 
  LOCK(cl->refCountMutex);
96
 
  cl->refCount++;
97
 
  UNLOCK(cl->refCountMutex);
98
 
}
99
 
 
100
 
void rfbDecrClientRef(rfbClientPtr cl)
101
 
{
102
 
  LOCK(cl->refCountMutex);
103
 
  cl->refCount--;
104
 
  if(cl->refCount<=0) /* just to be sure also < 0 */
105
 
    TSIGNAL(cl->deleteCond);
106
 
  UNLOCK(cl->refCountMutex);
107
 
}
108
 
#else
109
 
void rfbIncrClientRef(rfbClientPtr cl) {}
110
 
void rfbDecrClientRef(rfbClientPtr cl) {}
111
 
#endif
112
 
 
113
 
#ifdef HAVE_LIBPTHREAD
114
 
MUTEX(rfbClientListMutex);
115
 
#endif
116
 
 
117
 
struct rfbClientIterator {
118
 
  rfbClientPtr next;
119
 
  rfbScreenInfoPtr screen;
120
 
};
121
 
 
122
 
void
123
 
rfbClientListInit(rfbScreenInfoPtr rfbScreen)
124
 
{
125
 
    if(sizeof(rfbBool)!=1) {
126
 
        /* a sanity check */
127
 
        fprintf(stderr,"rfbBool's size is not 1 (%d)!\n",sizeof(rfbBool));
128
 
        /* we cannot continue, because rfbBool is supposed to be char everywhere */
129
 
        exit(1);
130
 
    }
131
 
    rfbScreen->rfbClientHead = NULL;
132
 
    INIT_MUTEX(rfbClientListMutex);
133
 
}
134
 
 
135
 
rfbClientIteratorPtr
136
 
rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
137
 
{
138
 
  rfbClientIteratorPtr i =
139
 
    (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
140
 
  i->next = 0;
141
 
  i->screen = rfbScreen;
142
 
  return i;
143
 
}
144
 
 
145
 
rfbClientPtr
146
 
rfbClientIteratorHead(rfbClientIteratorPtr i)
147
 
{
148
 
#ifdef HAVE_LIBPTHREAD
149
 
  if(i->next != 0) {
150
 
    rfbDecrClientRef(i->next);
151
 
    rfbIncrClientRef(i->screen->rfbClientHead);
152
 
  }
153
 
#endif
154
 
  LOCK(rfbClientListMutex);
155
 
  i->next = i->screen->rfbClientHead;
156
 
  UNLOCK(rfbClientListMutex);
157
 
  return i->next;
158
 
}
159
 
 
160
 
rfbClientPtr
161
 
rfbClientIteratorNext(rfbClientIteratorPtr i)
162
 
{
163
 
  if(i->next == 0) {
164
 
    LOCK(rfbClientListMutex);
165
 
    i->next = i->screen->rfbClientHead;
166
 
    UNLOCK(rfbClientListMutex);
167
 
  } else {
168
 
    IF_PTHREADS(rfbClientPtr cl = i->next);
169
 
    i->next = i->next->next;
170
 
    IF_PTHREADS(rfbDecrClientRef(cl));
171
 
  }
172
 
 
173
 
#ifdef HAVE_LIBPTHREAD
174
 
    while(i->next && i->next->sock<0)
175
 
      i->next = i->next->next;
176
 
    if(i->next)
177
 
      rfbIncrClientRef(i->next);
178
 
#endif
179
 
 
180
 
    return i->next;
181
 
}
182
 
 
183
 
void
184
 
rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
185
 
{
186
 
  IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
187
 
  free(iterator);
188
 
}
189
 
 
190
 
 
191
 
/*
192
 
 * rfbNewClientConnection is called from sockets.c when a new connection
193
 
 * comes in.
194
 
 */
195
 
 
196
 
void
197
 
rfbNewClientConnection(rfbScreen,sock)
198
 
    rfbScreenInfoPtr rfbScreen;
199
 
    int sock;
200
 
{
201
 
    rfbClientPtr cl;
202
 
 
203
 
    cl = rfbNewClient(rfbScreen,sock);
204
 
#ifdef CORBA
205
 
    if(cl!=NULL)
206
 
      newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1);
207
 
#endif
208
 
}
209
 
 
210
 
 
211
 
/*
212
 
 * rfbReverseConnection is called by the CORBA stuff to make an outward
213
 
 * connection to a "listening" RFB client.
214
 
 */
215
 
 
216
 
rfbClientPtr
217
 
rfbReverseConnection(rfbScreen,host, port)
218
 
    rfbScreenInfoPtr rfbScreen;
219
 
    char *host;
220
 
    int port;
221
 
{
222
 
    int sock;
223
 
    rfbClientPtr cl;
224
 
 
225
 
    if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
226
 
        return (rfbClientPtr)NULL;
227
 
 
228
 
    cl = rfbNewClient(rfbScreen, sock);
229
 
 
230
 
    if (cl) {
231
 
        cl->reverseConnection = TRUE;
232
 
    }
233
 
 
234
 
    return cl;
235
 
}
236
 
 
237
 
 
238
 
/*
239
 
 * rfbNewClient is called when a new connection has been made by whatever
240
 
 * means.
241
 
 */
242
 
 
243
 
rfbClientPtr
244
 
rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
245
 
    rfbScreenInfoPtr rfbScreen;
246
 
    int sock;
247
 
    rfbBool isUDP;
248
 
{
249
 
    rfbProtocolVersionMsg pv;
250
 
    rfbClientIteratorPtr iterator;
251
 
    rfbClientPtr cl,cl_;
252
 
    struct sockaddr_in addr;
253
 
    size_t addrlen = sizeof(struct sockaddr_in);
254
 
 
255
 
    cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
256
 
 
257
 
    cl->screen = rfbScreen;
258
 
    cl->sock = sock;
259
 
    cl->viewOnly = FALSE;
260
 
 
261
 
    rfbResetStats(cl);
262
 
 
263
 
    if(isUDP) {
264
 
      rfbLog(" accepted UDP client\n");
265
 
    } else {
266
 
      int one=1;
267
 
 
268
 
      getpeername(sock, (struct sockaddr *)&addr, &addrlen);
269
 
      cl->host = strdup(inet_ntoa(addr.sin_addr));
270
 
 
271
 
      rfbLog("  other clients:\n");
272
 
      iterator = rfbGetClientIterator(rfbScreen);
273
 
      while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
274
 
        rfbLog("     %s\n",cl_->host);
275
 
      }
276
 
      rfbReleaseClientIterator(iterator);
277
 
 
278
 
#ifndef WIN32
279
 
      if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
280
 
        rfbLogPerror("fcntl failed");
281
 
        close(sock);
282
 
        return NULL;
283
 
      }
284
 
#endif
285
 
 
286
 
      if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
287
 
                     (char *)&one, sizeof(one)) < 0) {
288
 
        rfbLogPerror("setsockopt failed");
289
 
        close(sock);
290
 
        return NULL;
291
 
      }
292
 
 
293
 
      FD_SET(sock,&(rfbScreen->allFds));
294
 
                rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
295
 
 
296
 
      INIT_MUTEX(cl->outputMutex);
297
 
      INIT_MUTEX(cl->refCountMutex);
298
 
      INIT_COND(cl->deleteCond);
299
 
 
300
 
      cl->state = RFB_PROTOCOL_VERSION;
301
 
 
302
 
      cl->reverseConnection = FALSE;
303
 
      cl->readyForSetColourMapEntries = FALSE;
304
 
      cl->useCopyRect = FALSE;
305
 
      cl->preferredEncoding = rfbEncodingRaw;
306
 
      cl->correMaxWidth = 48;
307
 
      cl->correMaxHeight = 48;
308
 
#ifdef HAVE_LIBZ
309
 
      cl->zrleData = 0;
310
 
#endif
311
 
 
312
 
      cl->copyRegion = sraRgnCreate();
313
 
      cl->copyDX = 0;
314
 
      cl->copyDY = 0;
315
 
   
316
 
      cl->modifiedRegion =
317
 
        sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
318
 
 
319
 
      INIT_MUTEX(cl->updateMutex);
320
 
      INIT_COND(cl->updateCond);
321
 
 
322
 
      cl->requestedRegion = sraRgnCreate();
323
 
 
324
 
      cl->format = cl->screen->rfbServerFormat;
325
 
      cl->translateFn = rfbTranslateNone;
326
 
      cl->translateLookupTable = NULL;
327
 
 
328
 
      LOCK(rfbClientListMutex);
329
 
 
330
 
      IF_PTHREADS(cl->refCount = 0);
331
 
      cl->next = rfbScreen->rfbClientHead;
332
 
      cl->prev = NULL;
333
 
      if (rfbScreen->rfbClientHead)
334
 
        rfbScreen->rfbClientHead->prev = cl;
335
 
 
336
 
      rfbScreen->rfbClientHead = cl;
337
 
      UNLOCK(rfbClientListMutex);
338
 
 
339
 
#ifdef HAVE_LIBJPEG
340
 
      cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
341
 
      cl->tightQualityLevel = -1;
342
 
      {
343
 
        int i;
344
 
        for (i = 0; i < 4; i++)
345
 
          cl->zsActive[i] = FALSE;
346
 
      }
347
 
#endif
348
 
 
349
 
      cl->enableCursorShapeUpdates = FALSE;
350
 
      cl->enableCursorPosUpdates = FALSE;
351
 
      cl->useRichCursorEncoding = FALSE;
352
 
      cl->enableLastRectEncoding = FALSE;
353
 
      cl->useNewFBSize = FALSE;
354
 
 
355
 
#ifdef HAVE_LIBZ
356
 
      cl->compStreamInited = FALSE;
357
 
      cl->compStream.total_in = 0;
358
 
      cl->compStream.total_out = 0;
359
 
      cl->compStream.zalloc = Z_NULL;
360
 
      cl->compStream.zfree = Z_NULL;
361
 
      cl->compStream.opaque = Z_NULL;
362
 
 
363
 
      cl->zlibCompressLevel = 5;
364
 
#endif
365
 
 
366
 
      cl->progressiveSliceY = 0;
367
 
 
368
 
      sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion,
369
 
              rfbProtocolMinorVersion);
370
 
 
371
 
      if (WriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
372
 
        rfbLogPerror("rfbNewClient: write");
373
 
        rfbCloseClient(cl);
374
 
        /* TODO: memory leak here (cl is never freed)
375
 
         * can rfbClientConnectionGone called at this time?
376
 
         * tim@tjansen.de
377
 
         */
378
 
        return NULL;
379
 
      }
380
 
    }
381
 
 
382
 
    cl->clientData = NULL;
383
 
    cl->clientGoneHook = doNothingWithClient;
384
 
    switch (cl->screen->newClientHook(cl)) {
385
 
    case RFB_CLIENT_ON_HOLD:
386
 
            cl->onHold = TRUE;
387
 
            break;
388
 
    case RFB_CLIENT_ACCEPT:
389
 
            cl->onHold = FALSE;
390
 
            break;
391
 
    case RFB_CLIENT_REFUSE:
392
 
            rfbCloseClient(cl);
393
 
            rfbClientConnectionGone(cl);
394
 
            cl = NULL;
395
 
            break;
396
 
    }
397
 
    return cl;
398
 
}
399
 
 
400
 
rfbClientPtr
401
 
rfbNewClient(rfbScreen,sock)
402
 
    rfbScreenInfoPtr rfbScreen;
403
 
    int sock;
404
 
{
405
 
  return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
406
 
}
407
 
 
408
 
rfbClientPtr
409
 
rfbNewUDPClient(rfbScreen)
410
 
     rfbScreenInfoPtr rfbScreen;
411
 
{
412
 
  return((rfbScreen->udpClient=
413
 
          rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE)));
414
 
}
415
 
 
416
 
/*
417
 
 * rfbClientConnectionGone is called from sockets.c just after a connection
418
 
 * has gone away.
419
 
 */
420
 
 
421
 
void
422
 
rfbClientConnectionGone(cl)
423
 
     rfbClientPtr cl;
424
 
{
425
 
    int i;
426
 
 
427
 
    LOCK(rfbClientListMutex);
428
 
 
429
 
    if (cl->prev)
430
 
        cl->prev->next = cl->next;
431
 
    else
432
 
        cl->screen->rfbClientHead = cl->next;
433
 
    if (cl->next)
434
 
        cl->next->prev = cl->prev;
435
 
 
436
 
#ifdef HAVE_LIBZ
437
 
    FreeZrleData(cl);
438
 
#endif
439
 
 
440
 
#ifdef HAVE_LIBPTHREAD
441
 
    if(cl->screen->backgroundLoop != FALSE)
442
 
      do {
443
 
        LOCK(cl->refCountMutex);
444
 
        i=cl->refCount;
445
 
        UNLOCK(cl->refCountMutex);
446
 
        if(i>0)
447
 
          WAIT(cl->deleteCond,cl->refCountMutex);
448
 
      } while(i>0);
449
 
#endif
450
 
 
451
 
    if(cl->sock>=0)
452
 
       FD_CLR(cl->sock,&(cl->screen->allFds));
453
 
 
454
 
    cl->clientGoneHook(cl);
455
 
 
456
 
    rfbLog("Client %s gone\n",cl->host);
457
 
    free(cl->host);
458
 
 
459
 
#ifdef HAVE_LIBZ
460
 
    /* Release the compression state structures if any. */
461
 
    if ( cl->compStreamInited ) {
462
 
        deflateEnd( &(cl->compStream) );
463
 
    }
464
 
 
465
 
#ifdef HAVE_LIBJPEG
466
 
    for (i = 0; i < 4; i++) {
467
 
        if (cl->zsActive[i])
468
 
            deflateEnd(&cl->zsStruct[i]);
469
 
    }
470
 
#endif
471
 
#endif
472
 
 
473
 
    if (pointerClient == cl)
474
 
        pointerClient = NULL;
475
 
 
476
 
    sraRgnDestroy(cl->modifiedRegion);
477
 
    sraRgnDestroy(cl->requestedRegion);
478
 
    sraRgnDestroy(cl->copyRegion);
479
 
 
480
 
    UNLOCK(rfbClientListMutex);
481
 
 
482
 
    if (cl->translateLookupTable) free(cl->translateLookupTable);
483
 
 
484
 
    TINI_COND(cl->updateCond);
485
 
    TINI_MUTEX(cl->updateMutex);
486
 
 
487
 
    LOCK(cl->outputMutex);
488
 
    TINI_MUTEX(cl->outputMutex);
489
 
 
490
 
#ifdef CORBA
491
 
    destroyConnection(cl);
492
 
#endif
493
 
 
494
 
    rfbPrintStats(cl);
495
 
 
496
 
    free(cl);
497
 
}
498
 
 
499
 
 
500
 
/*
501
 
 * rfbProcessClientMessage is called when there is data to read from a client.
502
 
 */
503
 
 
504
 
void
505
 
rfbProcessClientMessage(cl)
506
 
     rfbClientPtr cl;
507
 
{
508
 
    switch (cl->state) {
509
 
    case RFB_PROTOCOL_VERSION:
510
 
        rfbProcessClientProtocolVersion(cl);
511
 
        return;
512
 
    case RFB_AUTHENTICATION:
513
 
        rfbAuthProcessClientMessage(cl);
514
 
        return;
515
 
    case RFB_INITIALISATION:
516
 
        rfbProcessClientInitMessage(cl);
517
 
        return;
518
 
    default:
519
 
        rfbProcessClientNormalMessage(cl);
520
 
        return;
521
 
    }
522
 
}
523
 
 
524
 
 
525
 
/*
526
 
 * rfbProcessClientProtocolVersion is called when the client sends its
527
 
 * protocol version.
528
 
 */
529
 
 
530
 
static void
531
 
rfbProcessClientProtocolVersion(cl)
532
 
    rfbClientPtr cl;
533
 
{
534
 
    rfbProtocolVersionMsg pv;
535
 
    int n, major_, minor_;
536
 
    char failureReason[256];
537
 
 
538
 
    if ((n = ReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
539
 
        if (n == 0)
540
 
            rfbLog("rfbProcessClientProtocolVersion: client gone\n");
541
 
        else
542
 
            rfbLogPerror("rfbProcessClientProtocolVersion: read");
543
 
        rfbCloseClient(cl);
544
 
        return;
545
 
    }
546
 
 
547
 
    pv[sz_rfbProtocolVersionMsg] = 0;
548
 
    if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
549
 
        char name[1024]; 
550
 
        if(sscanf(pv,"RFB %03d.%03d %1024s\n",&major_,&minor_,name) != 3) {
551
 
            rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client\n");
552
 
            rfbCloseClient(cl);
553
 
            return;
554
 
        }
555
 
        free(cl->host);
556
 
        cl->host=strdup(name);
557
 
    }
558
 
    rfbLog("Protocol version %d.%d\n", major_, minor_);
559
 
 
560
 
    if (major_ != rfbProtocolMajorVersion) {
561
 
        /* Major version mismatch - send a ConnFailed message */
562
 
 
563
 
        rfbErr("Major version mismatch\n");
564
 
        sprintf(failureReason,
565
 
                "RFB protocol version mismatch - server %d.%d, client %d.%d",
566
 
                rfbProtocolMajorVersion,rfbProtocolMinorVersion,major_,minor_);
567
 
        rfbClientConnFailed(cl, failureReason);
568
 
        return;
569
 
    }
570
 
 
571
 
    if (minor_ != rfbProtocolMinorVersion) {
572
 
        /* Minor version mismatch - warn but try to continue */
573
 
        rfbLog("Ignoring minor version mismatch\n");
574
 
    }
575
 
 
576
 
    rfbAuthNewClient(cl);
577
 
}
578
 
 
579
 
 
580
 
/*
581
 
 * rfbClientConnFailed is called when a client connection has failed either
582
 
 * because it talks the wrong protocol or it has failed authentication.
583
 
 */
584
 
 
585
 
void
586
 
rfbClientConnFailed(cl, reason)
587
 
    rfbClientPtr cl;
588
 
    char *reason;
589
 
{
590
 
    char *buf;
591
 
    int len = strlen(reason);
592
 
 
593
 
    buf = (char *)malloc(8 + len);
594
 
    ((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed);
595
 
    ((uint32_t *)buf)[1] = Swap32IfLE(len);
596
 
    memcpy(buf + 8, reason, len);
597
 
 
598
 
    if (WriteExact(cl, buf, 8 + len) < 0)
599
 
        rfbLogPerror("rfbClientConnFailed: write");
600
 
    free(buf);
601
 
    rfbCloseClient(cl);
602
 
}
603
 
 
604
 
 
605
 
/*
606
 
 * rfbProcessClientInitMessage is called when the client sends its
607
 
 * initialisation message.
608
 
 */
609
 
 
610
 
static void
611
 
rfbProcessClientInitMessage(cl)
612
 
    rfbClientPtr cl;
613
 
{
614
 
    rfbClientInitMsg ci;
615
 
    char buf[256];
616
 
    rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
617
 
    int len, n;
618
 
    rfbClientIteratorPtr iterator;
619
 
    rfbClientPtr otherCl;
620
 
 
621
 
    if ((n = ReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
622
 
        if (n == 0)
623
 
            rfbLog("rfbProcessClientInitMessage: client gone\n");
624
 
        else
625
 
            rfbLogPerror("rfbProcessClientInitMessage: read");
626
 
        rfbCloseClient(cl);
627
 
        return;
628
 
    }
629
 
 
630
 
    si->framebufferWidth = Swap16IfLE(cl->screen->width);
631
 
    si->framebufferHeight = Swap16IfLE(cl->screen->height);
632
 
    si->format = cl->screen->rfbServerFormat;
633
 
    si->format.redMax = Swap16IfLE(si->format.redMax);
634
 
    si->format.greenMax = Swap16IfLE(si->format.greenMax);
635
 
    si->format.blueMax = Swap16IfLE(si->format.blueMax);
636
 
 
637
 
    if (strlen(cl->screen->desktopName) > 128)      /* sanity check on desktop name len */
638
 
        ((char*)cl->screen->desktopName)[128] = 0;
639
 
 
640
 
    strcpy(buf + sz_rfbServerInitMsg, cl->screen->desktopName);
641
 
    len = strlen(buf + sz_rfbServerInitMsg);
642
 
    si->nameLength = Swap32IfLE(len);
643
 
 
644
 
    if (WriteExact(cl, buf, sz_rfbServerInitMsg + len) < 0) {
645
 
        rfbLogPerror("rfbProcessClientInitMessage: write");
646
 
        rfbCloseClient(cl);
647
 
        return;
648
 
    }
649
 
 
650
 
    cl->state = RFB_NORMAL;
651
 
 
652
 
    if (!cl->reverseConnection &&
653
 
                        (cl->screen->rfbNeverShared || (!cl->screen->rfbAlwaysShared && !ci.shared))) {
654
 
 
655
 
        if (cl->screen->rfbDontDisconnect) {
656
 
            iterator = rfbGetClientIterator(cl->screen);
657
 
            while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
658
 
                if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
659
 
                    rfbLog("-dontdisconnect: Not shared & existing client\n");
660
 
                    rfbLog("  refusing new client %s\n", cl->host);
661
 
                    rfbCloseClient(cl);
662
 
                    rfbReleaseClientIterator(iterator);
663
 
                    return;
664
 
                }
665
 
            }
666
 
            rfbReleaseClientIterator(iterator);
667
 
        } else {
668
 
            iterator = rfbGetClientIterator(cl->screen);
669
 
            while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
670
 
                if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
671
 
                    rfbLog("Not shared - closing connection to client %s\n",
672
 
                           otherCl->host);
673
 
                    rfbCloseClient(otherCl);
674
 
                }
675
 
            }
676
 
            rfbReleaseClientIterator(iterator);
677
 
        }
678
 
    }
679
 
}
680
 
 
681
 
static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h,
682
 
                rfbScreenInfoPtr screen)
683
 
{
684
 
        *x=Swap16IfLE(*x);
685
 
        *y=Swap16IfLE(*y);
686
 
        *w=Swap16IfLE(*w);
687
 
        *h=Swap16IfLE(*h);
688
 
        if(*w>screen->width-*x)
689
 
                *w=screen->width-*x;
690
 
        /* possible underflow */
691
 
        if(*w>screen->width-*x)
692
 
                return FALSE;
693
 
        if(*h>screen->height-*y)
694
 
                *h=screen->height-*y;
695
 
        if(*h>screen->height-*y)
696
 
                return FALSE;
697
 
 
698
 
        return TRUE;
699
 
}
700
 
 
701
 
 
702
 
 
703
 
#ifdef ITALC_EXTENSIONS
704
 
char * readLine (int _fd) {
705
 
        char buf[BUFFER_SIZE];
706
 
        char *ptr = buf;
707
 
        int bytes_read = 0;
708
 
 
709
 
        if (_fd <= 0)
710
 
                return (NULL);
711
 
 
712
 
        while (read(_fd, ptr, 1) == 1) {
713
 
                if (*ptr == '\n' || bytes_read > BUFFER_SIZE-2)
714
 
                        break;
715
 
                ++ptr;
716
 
                ++bytes_read;
717
 
        }
718
 
        if (/* *ptr == '\n' && */bytes_read > 0) {
719
 
                char * line = malloc(bytes_read+1);
720
 
                *ptr = '\0';
721
 
                strcpy (line, buf);
722
 
                return (line);
723
 
        }
724
 
        return (NULL);
725
 
}
726
 
 
727
 
 
728
 
off_t getFileSize (int _fd) {
729
 
        off_t cur_pos = lseek(_fd, 0, SEEK_CUR);
730
 
        off_t end_pos = lseek(_fd, 0, SEEK_END);
731
 
        lseek(_fd, cur_pos, SEEK_SET);
732
 
        return (end_pos);
733
 
}
734
 
#endif
735
 
/*
736
 
 * rfbProcessClientNormalMessage is called when the client has sent a normal
737
 
 * protocol message.
738
 
 */
739
 
 
740
 
static void
741
 
rfbProcessClientNormalMessage(cl)
742
 
    rfbClientPtr cl;
743
 
{
744
 
    int n=0;
745
 
    rfbClientToServerMsg msg;
746
 
    char *str;
747
 
 
748
 
    if ((n = ReadExact(cl, (char *)&msg, 1)) <= 0) {
749
 
        if (n != 0)
750
 
            rfbLogPerror("rfbProcessClientNormalMessage: read");
751
 
        rfbCloseClient(cl);
752
 
        return;
753
 
    }
754
 
 
755
 
    switch (msg.type) {
756
 
 
757
 
    case rfbSetPixelFormat:
758
 
 
759
 
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
760
 
                           sz_rfbSetPixelFormatMsg - 1)) <= 0) {
761
 
            if (n != 0)
762
 
                rfbLogPerror("rfbProcessClientNormalMessage: read");
763
 
            rfbCloseClient(cl);
764
 
            return;
765
 
        }
766
 
 
767
 
        cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
768
 
        cl->format.depth = msg.spf.format.depth;
769
 
        cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
770
 
        cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
771
 
        cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
772
 
        cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
773
 
        cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
774
 
        cl->format.redShift = msg.spf.format.redShift;
775
 
        cl->format.greenShift = msg.spf.format.greenShift;
776
 
        cl->format.blueShift = msg.spf.format.blueShift;
777
 
 
778
 
        cl->readyForSetColourMapEntries = TRUE;
779
 
        cl->screen->setTranslateFunction(cl);
780
 
 
781
 
        return;
782
 
 
783
 
 
784
 
    case rfbFixColourMapEntries:
785
 
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
786
 
                           sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
787
 
            if (n != 0)
788
 
                rfbLogPerror("rfbProcessClientNormalMessage: read");
789
 
            rfbCloseClient(cl);
790
 
            return;
791
 
        }
792
 
        rfbLog("rfbProcessClientNormalMessage: %s",
793
 
                "FixColourMapEntries unsupported\n");
794
 
        rfbCloseClient(cl);
795
 
        return;
796
 
 
797
 
 
798
 
    case rfbSetEncodings:
799
 
    {
800
 
        int i;
801
 
        uint32_t enc;
802
 
 
803
 
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
804
 
                           sz_rfbSetEncodingsMsg - 1)) <= 0) {
805
 
            if (n != 0)
806
 
                rfbLogPerror("rfbProcessClientNormalMessage: read");
807
 
            rfbCloseClient(cl);
808
 
            return;
809
 
        }
810
 
 
811
 
        msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
812
 
 
813
 
        cl->preferredEncoding = -1;
814
 
        cl->useCopyRect = FALSE;
815
 
        cl->enableCursorShapeUpdates = FALSE;
816
 
        cl->enableCursorPosUpdates = FALSE;
817
 
        cl->enableLastRectEncoding = FALSE;
818
 
        cl->useNewFBSize = FALSE;
819
 
 
820
 
        for (i = 0; i < msg.se.nEncodings; i++) {
821
 
            if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
822
 
                if (n != 0)
823
 
                    rfbLogPerror("rfbProcessClientNormalMessage: read");
824
 
                rfbCloseClient(cl);
825
 
                return;
826
 
            }
827
 
            enc = Swap32IfLE(enc);
828
 
 
829
 
            switch (enc) {
830
 
 
831
 
            case rfbEncodingCopyRect:
832
 
                cl->useCopyRect = TRUE;
833
 
                break;
834
 
            case rfbEncodingRaw:
835
 
                if (cl->preferredEncoding == -1) {
836
 
                    cl->preferredEncoding = enc;
837
 
                    rfbLog("Using raw encoding for client %s\n",
838
 
                           cl->host);
839
 
                }
840
 
                break;
841
 
            case rfbEncodingRRE:
842
 
                if (cl->preferredEncoding == -1) {
843
 
                    cl->preferredEncoding = enc;
844
 
                    rfbLog("Using rre encoding for client %s\n",
845
 
                           cl->host);
846
 
                }
847
 
                break;
848
 
            case rfbEncodingCoRRE:
849
 
                if (cl->preferredEncoding == -1) {
850
 
                    cl->preferredEncoding = enc;
851
 
                    rfbLog("Using CoRRE encoding for client %s\n",
852
 
                           cl->host);
853
 
                }
854
 
                break;
855
 
            case rfbEncodingHextile:
856
 
                if (cl->preferredEncoding == -1) {
857
 
                    cl->preferredEncoding = enc;
858
 
                    rfbLog("Using hextile encoding for client %s\n",
859
 
                           cl->host);
860
 
                }
861
 
                break;
862
 
#ifdef HAVE_LIBZ
863
 
            case rfbEncodingZlib:
864
 
                if (cl->preferredEncoding == -1) {
865
 
                    cl->preferredEncoding = enc;
866
 
                    rfbLog("Using zlib encoding for client %s\n",
867
 
                           cl->host);
868
 
                }
869
 
              break;
870
 
#ifdef HAVE_LIBJPEG
871
 
            case rfbEncodingTight:
872
 
                if (cl->preferredEncoding == -1) {
873
 
                    cl->preferredEncoding = enc;
874
 
                    rfbLog("Using tight encoding for client %s\n",
875
 
                           cl->host);
876
 
                }
877
 
                break;
878
 
#endif
879
 
#endif
880
 
            case rfbEncodingXCursor:
881
 
                if(!cl->screen->dontConvertRichCursorToXCursor) {
882
 
                    rfbLog("Enabling X-style cursor updates for client %s\n",
883
 
                           cl->host);
884
 
                    cl->enableCursorShapeUpdates = TRUE;
885
 
                    cl->cursorWasChanged = TRUE;
886
 
                }
887
 
                break;
888
 
            case rfbEncodingRichCursor:
889
 
                rfbLog("Enabling full-color cursor updates for client %s\n",
890
 
                       cl->host);
891
 
                cl->enableCursorShapeUpdates = TRUE;
892
 
                cl->useRichCursorEncoding = TRUE;
893
 
                cl->cursorWasChanged = TRUE;
894
 
                break;
895
 
            case rfbEncodingPointerPos:
896
 
                if (!cl->enableCursorPosUpdates) {
897
 
                    rfbLog("Enabling cursor position updates for client %s\n",
898
 
                           cl->host);
899
 
                    cl->enableCursorPosUpdates = TRUE;
900
 
                    cl->cursorWasMoved = TRUE;
901
 
                }
902
 
                break;
903
 
            case rfbEncodingLastRect:
904
 
                if (!cl->enableLastRectEncoding) {
905
 
                    rfbLog("Enabling LastRect protocol extension for client "
906
 
                           "%s\n", cl->host);
907
 
                    cl->enableLastRectEncoding = TRUE;
908
 
                }
909
 
                break;
910
 
            case rfbEncodingNewFBSize:
911
 
                if (!cl->useNewFBSize) {
912
 
                    rfbLog("Enabling NewFBSize protocol extension for client "
913
 
                           "%s\n", cl->host);
914
 
                    cl->useNewFBSize = TRUE;
915
 
                }
916
 
                break;
917
 
#ifdef BACKCHANNEL
918
 
            case rfbEncodingBackChannel:
919
 
                if (!cl->enableBackChannel) {
920
 
                    rfbLog("Enabling BackChannel protocol extension for "
921
 
                           "client %s\n", cl->host);
922
 
                    cl->enableBackChannel = TRUE;
923
 
                }
924
 
                break;
925
 
#endif
926
 
#ifdef HAVE_LIBZ
927
 
           case rfbEncodingZRLE:
928
 
               if (cl->preferredEncoding == -1) {
929
 
                   cl->preferredEncoding = enc;
930
 
                   rfbLog("Using ZRLE encoding for client %s\n",
931
 
                          cl->host);
932
 
               }
933
 
               break;
934
 
#endif
935
 
            default:
936
 
#ifdef HAVE_LIBZ
937
 
                if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
938
 
                     enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
939
 
                    cl->zlibCompressLevel = enc & 0x0F;
940
 
#ifdef HAVE_LIBJPEG
941
 
                    cl->tightCompressLevel = enc & 0x0F;
942
 
                    rfbLog("Using compression level %d for client %s\n",
943
 
                           cl->tightCompressLevel, cl->host);
944
 
                } else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 &&
945
 
                            enc <= (uint32_t)rfbEncodingQualityLevel9 ) {
946
 
                    cl->tightQualityLevel = enc & 0x0F;
947
 
                    rfbLog("Using image quality level %d for client %s\n",
948
 
                           cl->tightQualityLevel, cl->host);
949
 
#endif
950
 
                } else
951
 
#endif
952
 
                 rfbLog("rfbProcessClientNormalMessage: ignoring unknown "
953
 
                       "encoding type %d\n", (int)enc);
954
 
            }
955
 
        }
956
 
 
957
 
        if (cl->preferredEncoding == -1) {
958
 
            cl->preferredEncoding = rfbEncodingRaw;
959
 
        }
960
 
 
961
 
        if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) {
962
 
          rfbLog("Disabling cursor position updates for client %s\n",
963
 
                 cl->host);
964
 
          cl->enableCursorPosUpdates = FALSE;
965
 
        }
966
 
 
967
 
        return;
968
 
    }
969
 
 
970
 
 
971
 
    case rfbFramebufferUpdateRequest:
972
 
    {
973
 
        sraRegionPtr tmpRegion;
974
 
 
975
 
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
976
 
                           sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
977
 
            if (n != 0)
978
 
                rfbLogPerror("rfbProcessClientNormalMessage: read");
979
 
            rfbCloseClient(cl);
980
 
            return;
981
 
        }
982
 
 
983
 
        if(!rectSwapIfLEAndClip(&msg.fur.x,&msg.fur.y,&msg.fur.w,&msg.fur.h,
984
 
                        cl->screen))
985
 
                return;
986
 
 
987
 
        tmpRegion =
988
 
          sraRgnCreateRect(msg.fur.x,
989
 
                           msg.fur.y,
990
 
                           msg.fur.x+msg.fur.w,
991
 
                           msg.fur.y+msg.fur.h);
992
 
 
993
 
        LOCK(cl->updateMutex);
994
 
        sraRgnOr(cl->requestedRegion,tmpRegion);
995
 
 
996
 
        if (!cl->readyForSetColourMapEntries) {
997
 
            /* client hasn't sent a SetPixelFormat so is using server's */
998
 
            cl->readyForSetColourMapEntries = TRUE;
999
 
            if (!cl->format.trueColour) {
1000
 
                if (!rfbSetClientColourMap(cl, 0, 0)) {
1001
 
                    sraRgnDestroy(tmpRegion);
1002
 
                    UNLOCK(cl->updateMutex);
1003
 
                    return;
1004
 
                }
1005
 
            }
1006
 
        }
1007
 
 
1008
 
       if (!msg.fur.incremental) {
1009
 
            sraRgnOr(cl->modifiedRegion,tmpRegion);
1010
 
            sraRgnSubtract(cl->copyRegion,tmpRegion);
1011
 
       }
1012
 
       TSIGNAL(cl->updateCond);
1013
 
       UNLOCK(cl->updateMutex);
1014
 
 
1015
 
       sraRgnDestroy(tmpRegion);
1016
 
 
1017
 
       return;
1018
 
    }
1019
 
 
1020
 
    case rfbKeyEvent:
1021
 
 
1022
 
        cl->rfbKeyEventsRcvd++;
1023
 
 
1024
 
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
1025
 
                           sz_rfbKeyEventMsg - 1)) <= 0) {
1026
 
            if (n != 0)
1027
 
                rfbLogPerror("rfbProcessClientNormalMessage: read");
1028
 
            rfbCloseClient(cl);
1029
 
            return;
1030
 
        }
1031
 
 
1032
 
        if(!cl->viewOnly) {
1033
 
            cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
1034
 
        }
1035
 
 
1036
 
        return;
1037
 
 
1038
 
 
1039
 
    case rfbPointerEvent:
1040
 
 
1041
 
        cl->rfbPointerEventsRcvd++;
1042
 
 
1043
 
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
1044
 
                           sz_rfbPointerEventMsg - 1)) <= 0) {
1045
 
            if (n != 0)
1046
 
                rfbLogPerror("rfbProcessClientNormalMessage: read");
1047
 
            rfbCloseClient(cl);
1048
 
            return;
1049
 
        }
1050
 
 
1051
 
        if (pointerClient && (pointerClient != cl))
1052
 
            return;
1053
 
 
1054
 
        if (msg.pe.buttonMask == 0)
1055
 
            pointerClient = NULL;
1056
 
        else
1057
 
            pointerClient = cl;
1058
 
 
1059
 
        if(!cl->viewOnly) {
1060
 
            cl->screen->ptrAddEvent(msg.pe.buttonMask,
1061
 
                                    Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
1062
 
        }
1063
 
 
1064
 
        return;
1065
 
 
1066
 
 
1067
 
    case rfbClientCutText:
1068
 
 
1069
 
        if ((n = ReadExact(cl, ((char *)&msg) + 1,
1070
 
                           sz_rfbClientCutTextMsg - 1)) <= 0) {
1071
 
            if (n != 0)
1072
 
                rfbLogPerror("rfbProcessClientNormalMessage: read");
1073
 
            rfbCloseClient(cl);
1074
 
            return;
1075
 
        }
1076
 
 
1077
 
        msg.cct.length = Swap32IfLE(msg.cct.length);
1078
 
 
1079
 
        str = (char *)malloc(msg.cct.length);
1080
 
 
1081
 
        if ((n = ReadExact(cl, str, msg.cct.length)) <= 0) {
1082
 
            if (n != 0)
1083
 
                rfbLogPerror("rfbProcessClientNormalMessage: read");
1084
 
            free(str);
1085
 
            rfbCloseClient(cl);
1086
 
            return;
1087
 
        }
1088
 
 
1089
 
        if(!cl->viewOnly) {
1090
 
            cl->screen->setXCutText(str, msg.cct.length, cl);
1091
 
        }
1092
 
        free(str);
1093
 
 
1094
 
        return;
1095
 
 
1096
 
 
1097
 
#ifdef ITALC_EXTENSIONS
1098
 
 
1099
 
        case RFB_ITALC_TO_SERVER_REQUEST: {
1100
 
                s_rfb_italc_request tr;
1101
 
                if (ReadExact(cl, &tr.italc_cmd, sizeof(tr.italc_cmd)) <= 0) {
1102
 
                        printf ("Got invalid italc-to-server-request from client %d...", (int) cl);
1103
 
                        rfbCloseClient(cl);
1104
 
                        return;
1105
 
                }
1106
 
                switch (tr.italc_cmd) {
1107
 
                        case ITALC_GET_USER: {
1108
 
                                char * user;
1109
 
                                s_rfb_post_user_msg post_user;
1110
 
                                user = getenv("USER");
1111
 
                                post_user.cmd = RFB_SERVER_TO_ITALC_RESPONSE;
1112
 
                                post_user.italc_cmd = ITALC_POST_USER;
1113
 
                                post_user.user_name_len = Swap16IfLE(strlen(user)+1);   /* send length of user-name including NULL-byte */
1114
 
                                if (WriteExact(cl, (char *) &post_user, sizeof(post_user)) < 0) {
1115
 
                                        printf ("Could not send user-name message\n");
1116
 
                                        rfbCloseClient(cl);
1117
 
                                        return;
1118
 
                                }
1119
 
                                if (WriteExact(cl, user, strlen(user)+1) < 0) {
1120
 
                                        printf ("Could not send user-name\n");
1121
 
                                        rfbCloseClient(cl);
1122
 
                                        return;
1123
 
                                }
1124
 
                                break;
1125
 
                        }
1126
 
                        case ITALC_EXEC_CMDS: {
1127
 
                                char * cmds;
1128
 
                                if (ReadExact(cl, (char *) &tr.exec_cmds.cmd_len, sizeof(s_rfb_exec_cmds_msg)-2) <= 0) {
1129
 
                                        printf ("Could not read header of Cmd-Exec-Message\n");
1130
 
                                        rfbCloseClient(cl);
1131
 
                                        return;
1132
 
                                }
1133
 
                                tr.exec_cmds.cmd_len = Swap16IfLE(tr.exec_cmds.cmd_len);
1134
 
                                cmds = (char *) malloc(tr.exec_cmds.cmd_len+1);
1135
 
                                if (ReadExact(cl, cmds, tr.exec_cmds.cmd_len) < 0) {
1136
 
                                        printf ("Could not read command-string of Cmd-Exec-Message\n");
1137
 
                                        rfbCloseClient(cl);
1138
 
                                        return;
1139
 
                                }
1140
 
                                strcat (cmds, "&");     /* make sure, cmds are executed in background... */
1141
 
                                system (cmds);
1142
 
                                free (cmds);
1143
 
                                break;
1144
 
                        }
1145
 
                        case ITALC_START_DEMO: {
1146
 
                                char * demo_master_ip;
1147
 
                                char * cmd_line;
1148
 
                                if (ReadExact(cl, (char *) &tr.start_demo.fullscreen, sizeof(s_rfb_start_demo_msg)-2) <= 0) {
1149
 
                                        printf ("Could not read header of Start-Demo-Message\n");
1150
 
                                        rfbCloseClient(cl);
1151
 
                                        return;
1152
 
                                }
1153
 
                                tr.start_demo.demo_master_ip_len = Swap16IfLE(tr.start_demo.demo_master_ip_len);
1154
 
                                demo_master_ip = (char *) malloc(tr.start_demo.demo_master_ip_len+1);
1155
 
                                if (ReadExact(cl, demo_master_ip, tr.start_demo.demo_master_ip_len) < 0) {
1156
 
                                        printf ("Could not read IP and display of Demo-Master\n");
1157
 
                                        rfbCloseClient(cl);
1158
 
                                        return;
1159
 
                                }
1160
 
                                cmd_line = (char *) malloc(strlen(DEMO_VIEWER)+tr.start_demo.demo_master_ip_len+5);
1161
 
                                strcpy (cmd_line, DEMO_VIEWER);
1162
 
                                strcat (cmd_line, demo_master_ip);
1163
 
                                if (tr.start_demo.fullscreen) {
1164
 
                                        strcat (cmd_line, " 1 &");
1165
 
                                } else {
1166
 
                                        strcat (cmd_line, " 0 &");
1167
 
                                }
1168
 
                                system (cmd_line);
1169
 
                                free (cmd_line);
1170
 
                                free (demo_master_ip);
1171
 
 
1172
 
                                break;
1173
 
                        }
1174
 
                        case ITALC_STOP_DEMO:
1175
 
                                system ("killall demoviewer");
1176
 
                                break;
1177
 
                        case ITALC_LOCK_DISPLAY:
1178
 
                                system (SCREEN_LOCKER);
1179
 
                                break;
1180
 
                        case ITALC_UNLOCK_DISPLAY:
1181
 
                                system ("killall screenlocker");
1182
 
                                break;
1183
 
                        case ITALC_SEND_MSG: {
1184
 
                                char * msg;
1185
 
                                char * cmd_line;
1186
 
                                if (ReadExact(cl, (char *) &tr.send_msg.msg_len, sizeof(s_rfb_send_msg_msg)-2) <= 0) {
1187
 
                                        printf ("Could not read header of Send-Message-Message\n");
1188
 
                                        rfbCloseClient(cl);
1189
 
                                        return;
1190
 
                                }
1191
 
                                msg = (char *) malloc(Swap16IfLE(tr.send_msg.msg_len));
1192
 
                                if (ReadExact(cl, msg, Swap16IfLE(tr.send_msg.msg_len)) < 0) {
1193
 
                                        printf ("Could not read message\n");
1194
 
                                        rfbCloseClient(cl);
1195
 
                                        return;
1196
 
                                }
1197
 
                                cmd_line = (char *) malloc(strlen(MESSAGE_VIEWER)+Swap16IfLE(tr.send_msg.msg_len)+4);
1198
 
                                strcpy (cmd_line, MESSAGE_VIEWER);
1199
 
                                strcat (cmd_line, "'");         /* add " because message could contain spaces */
1200
 
                                strcat (cmd_line, msg);
1201
 
                                strcat (cmd_line, "' &");
1202
 
                                system (cmd_line);
1203
 
                                free (cmd_line);
1204
 
                                free (msg);
1205
 
                                break;
1206
 
                        }
1207
 
#if 0                                     
1208
 
                        case ITALC_INVITE_SUPPORT: {
1209
 
                                char * uname;
1210
 
                                char * cmd_line;
1211
 
                                int result;
1212
 
                                s_rfb_invitation_result_msg inv_res;
1213
 
                                if (ReadExact(cl, (char *) &tr.invite_support_msg.uname_len, sizeof(s_rfb_invite_support_msg)-2) <= 0) {
1214
 
                                        printf ("Could not read header of Send-Message-Message\n");
1215
 
                                        rfbCloseClient(cl);
1216
 
                                        return;
1217
 
                                }
1218
 
                                uname = (char *) malloc(Swap16IfLE(tr.invite_support_msg.uname_len));
1219
 
                                if (ReadExact(cl, uname, Swap16IfLE(tr.invite_support_msg.uname_len)) < 0) {
1220
 
                                        printf ("Could not read message\n");
1221
 
                                        free (uname);
1222
 
                                        rfbCloseClient(cl);
1223
 
                                        return;
1224
 
                                }
1225
 
                                cmd_line = (char *) malloc(strlen(SUPPORT_INVITOR)+Swap16IfLE(tr.invite_support_msg.uname_len)+4);
1226
 
                                strcpy (cmd_line, SUPPORT_INVITOR);
1227
 
                                strcat (cmd_line, "'");         /* add " because user-name could contain spaces */
1228
 
                                strcat (cmd_line, uname);
1229
 
                                strcat (cmd_line, "'");
1230
 
                                result = system (cmd_line);
1231
 
                                free (cmd_line);
1232
 
                                free (uname);
1233
 
 
1234
 
                                inv_res.cmd = RFB_SERVER_TO_ITALC_RESPONSE;
1235
 
                                inv_res.italc_cmd = ITALC_INVITATION_RESULT;
1236
 
                                inv_res.inv_accepted = (result == 0);
1237
 
                                if (WriteExact(cl, (char *) &inv_res, sizeof(inv_res)) < 0) {
1238
 
                                        printf ("Could not send invitation-result\n");
1239
 
                                        rfbCloseClient(cl);
1240
 
                                        return;
1241
 
                                }
1242
 
                                break;
1243
 
                        }
1244
 
                        case ITALC_POST_FILE_REQ: {
1245
 
                                char * filename;
1246
 
                                Q_UINT32 total_bytes = 0;
1247
 
                                Q_UINT32 bytes_done = 0;
1248
 
                                int outfile_fd;
1249
 
                                if (ReadExact(cl, (char *) &tr.post_file_msg.fname_len, sizeof(s_rfb_post_file_msg)-2) <= 0) {
1250
 
                                        printf ("Could not read header of Post-File-Message\n");
1251
 
                                        rfbCloseClient(cl);
1252
 
                                        return;
1253
 
                                }
1254
 
                                filename = (char *) malloc(strlen(getenv("HOME"))+strlen(DEST_DIR) + Swap16IfLE(tr.post_file_msg.fname_len));
1255
 
                                strcpy (filename, getenv("HOME"));
1256
 
                                strcat (filename, DEST_DIR);
1257
 
                                if (ReadExact(cl, filename+strlen(filename), Swap16IfLE(tr.post_file_msg.fname_len)) < 0) {
1258
 
                                        printf ("Could not read file-name\n");
1259
 
                                        free (filename);
1260
 
                                        rfbCloseClient(cl);
1261
 
                                        return;
1262
 
                                }
1263
 
                                total_bytes = Swap32IfLE(tr.post_file_msg.fsize);
1264
 
                                outfile_fd = open (filename, O_CREAT|O_WRONLY, 0777);
1265
 
                                /* we check if open() failed when writ()ing, because we HAVE to read incoming data, so
1266
 
                                   just returning on error would be no solution... */
1267
 
                                while (bytes_done < total_bytes) {
1268
 
                                        char buffer[BUFFER_SIZE];
1269
 
                                        Q_UINT32 bytes_todo = BUFFER_SIZE;
1270
 
                                        if (total_bytes - bytes_done < bytes_todo)
1271
 
                                                bytes_todo = total_bytes - bytes_done;
1272
 
                                        if (ReadExact(cl, buffer, bytes_todo) < 0) {
1273
 
                                                printf ("Could not read binary file-data\n");
1274
 
                                                rfbCloseClient(cl);
1275
 
                                                break;
1276
 
                                        }
1277
 
                                        /* NOW check for valid FD */
1278
 
                                        if (outfile_fd > 0) {
1279
 
                                                write (outfile_fd, buffer, bytes_todo);
1280
 
                                        }
1281
 
                                        bytes_done += bytes_todo;
1282
 
                                }
1283
 
                                close (outfile_fd);
1284
 
                                free (filename);
1285
 
                                break;
1286
 
                        }
1287
 
                        case ITALC_GET_FILE: {
1288
 
                                char * filemask;
1289
 
                                char * line;
1290
 
                                int tmp_file_fd;
1291
 
                                if (ReadExact(cl, (char *) &tr.get_file_msg.fmask_len, sizeof(s_rfb_get_file_msg)-2) <= 0) {
1292
 
                                        printf ("Could not read header of Get-File-Message\n");
1293
 
                                        rfbCloseClient(cl);
1294
 
                                        return;
1295
 
                                }
1296
 
                                filemask = (char *) malloc(strlen(LIST_COMMAND)+strlen(getenv("HOME"))+1+ Swap16IfLE(tr.get_file_msg.fmask_len)+strlen(TMP_OUT_FILE));
1297
 
                                strcpy (filemask, LIST_COMMAND);
1298
 
                                strcat (filemask, getenv("HOME"));
1299
 
                                strcat (filemask, "/");         /* $HOME doesn't contain / at the end... */
1300
 
                                if (ReadExact(cl, filemask+strlen(filemask), Swap16IfLE(tr.get_file_msg.fmask_len)) < 0) {
1301
 
                                        printf ("Could not read file-mask\n");
1302
 
                                        free (filemask);
1303
 
                                        rfbCloseClient(cl);
1304
 
                                        return;
1305
 
                                }
1306
 
                                strcat (filemask, TMP_OUT_FILE_REDIR);
1307
 
                                system (filemask);
1308
 
                                tmp_file_fd = open(TMP_OUT_FILE, O_RDONLY);
1309
 
                                while ((line = readLine(tmp_file_fd)) != NULL) {
1310
 
                                        s_rfb_post_file_msg post_file;
1311
 
                                        int fd;
1312
 
                                        Q_UINT32 total_bytes = 0;
1313
 
                                        Q_UINT32 bytes_done = 0;
1314
 
 
1315
 
                                        fd = open(line, O_RDONLY);
1316
 
                                        if (fd <= 0)
1317
 
                                                continue;
1318
 
                                        total_bytes = getFileSize(fd);
1319
 
 
1320
 
                                        /*printf ("tb: %d\n", (int) total_bytes); */
1321
 
                                        post_file.cmd = RFB_SERVER_TO_ITALC_RESPONSE;
1322
 
                                        post_file.italc_cmd = ITALC_POST_FILE_RESP;
1323
 
                                        post_file.fname_len = Swap16IfLE(strlen(line)+1);
1324
 
                                        post_file.fsize = Swap32IfLE(total_bytes);
1325
 
                                        if (WriteExact(cl, (char *) &post_file, sizeof(post_file)) < 0) {
1326
 
                                                printf ("Could not send file-name in post-file-message\n");
1327
 
                                                rfbCloseClient(cl);
1328
 
                                                free (line);
1329
 
                                                break;
1330
 
                                        }
1331
 
                                        if (WriteExact(cl, line, strlen(line)+1) < 0) {
1332
 
                                                printf ("Could not send file-name\n");
1333
 
                                                rfbCloseClient(cl);
1334
 
                                                free (line);
1335
 
                                                break;
1336
 
                                        }
1337
 
                                        while (bytes_done < total_bytes) {
1338
 
                                                char buffer[BUFFER_SIZE];
1339
 
                                                Q_UINT32 bytes_todo = BUFFER_SIZE;
1340
 
                                                if (total_bytes - bytes_done < bytes_todo)
1341
 
                                                        bytes_todo = total_bytes - bytes_done;
1342
 
                                                read (fd, buffer, bytes_todo);
1343
 
                                                if (WriteExact(cl, buffer, bytes_todo) < 0) {
1344
 
                                                        printf ("Could not send binary file-data\n");
1345
 
                                                        rfbCloseClient(cl);
1346
 
                                                        break;
1347
 
                                                }
1348
 
                                                bytes_done += bytes_todo;
1349
 
                                                usleep(25);
1350
 
                                        }
1351
 
                                        close (fd);
1352
 
                                        free (line);
1353
 
                                }
1354
 
                                close (tmp_file_fd);
1355
 
                                unlink (TMP_OUT_FILE);
1356
 
                                free (filemask);
1357
 
                                break;
1358
 
                        }
1359
 
#endif
1360
 
                }
1361
 
 
1362
 
                return;
1363
 
        }
1364
 
#endif /* ITALC_EXTENSIONS */
1365
 
 
1366
 
    default:
1367
 
 
1368
 
        rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", msg.type);
1369
 
        rfbLog(" ... closing connection\n");
1370
 
        rfbCloseClient(cl);
1371
 
        return;
1372
 
    }
1373
 
}
1374
 
 
1375
 
 
1376
 
 
1377
 
/*
1378
 
 * rfbSendFramebufferUpdate - send the currently pending framebuffer update to
1379
 
 * the RFB client.
1380
 
 * givenUpdateRegion is not changed.
1381
 
 */
1382
 
 
1383
 
rfbBool
1384
 
rfbSendFramebufferUpdate(cl, givenUpdateRegion)
1385
 
     rfbClientPtr cl;
1386
 
     sraRegionPtr givenUpdateRegion;
1387
 
{
1388
 
    sraRectangleIterator* i;
1389
 
    sraRect rect;
1390
 
    int nUpdateRegionRects;
1391
 
    rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf;
1392
 
    sraRegionPtr updateRegion,updateCopyRegion,tmpRegion;
1393
 
    int dx, dy;
1394
 
    rfbBool sendCursorShape = FALSE;
1395
 
    rfbBool sendCursorPos = FALSE;
1396
 
 
1397
 
    if(cl->screen->displayHook)
1398
 
      cl->screen->displayHook(cl);
1399
 
 
1400
 
    /*
1401
 
     * If framebuffer size was changed and the client supports NewFBSize
1402
 
     * encoding, just send NewFBSize marker and return.
1403
 
     */
1404
 
 
1405
 
    if (cl->useNewFBSize && cl->newFBSizePending) {
1406
 
      LOCK(cl->updateMutex);
1407
 
      cl->newFBSizePending = FALSE;
1408
 
      UNLOCK(cl->updateMutex);
1409
 
      cl->rfbFramebufferUpdateMessagesSent++;
1410
 
      fu->type = rfbFramebufferUpdate;
1411
 
      fu->nRects = Swap16IfLE(1);
1412
 
      cl->ublen = sz_rfbFramebufferUpdateMsg;
1413
 
      if (!rfbSendNewFBSize(cl, cl->screen->width, cl->screen->height)) {
1414
 
        return FALSE;
1415
 
      }
1416
 
      return rfbSendUpdateBuf(cl);
1417
 
    }
1418
 
    
1419
 
    /*
1420
 
     * If this client understands cursor shape updates, cursor should be
1421
 
     * removed from the framebuffer. Otherwise, make sure it's put up.
1422
 
     */
1423
 
 
1424
 
    if (cl->enableCursorShapeUpdates) {
1425
 
      if (cl->screen->cursorIsDrawn) {
1426
 
        rfbUndrawCursor(cl->screen);
1427
 
      }
1428
 
      if (!cl->screen->cursorIsDrawn && cl->cursorWasChanged &&
1429
 
          cl->readyForSetColourMapEntries)
1430
 
          sendCursorShape = TRUE;
1431
 
    } else {
1432
 
      if (!cl->screen->cursorIsDrawn) {
1433
 
        rfbDrawCursor(cl->screen);
1434
 
      }
1435
 
    }
1436
 
 
1437
 
    /*
1438
 
     * Do we plan to send cursor position update?
1439
 
     */
1440
 
 
1441
 
    if (cl->enableCursorPosUpdates && cl->cursorWasMoved)
1442
 
      sendCursorPos = TRUE;
1443
 
 
1444
 
    LOCK(cl->updateMutex);
1445
 
 
1446
 
    /*
1447
 
     * The modifiedRegion may overlap the destination copyRegion.  We remove
1448
 
     * any overlapping bits from the copyRegion (since they'd only be
1449
 
     * overwritten anyway).
1450
 
     */
1451
 
    
1452
 
    sraRgnSubtract(cl->copyRegion,cl->modifiedRegion);
1453
 
 
1454
 
    /*
1455
 
     * The client is interested in the region requestedRegion.  The region
1456
 
     * which should be updated now is the intersection of requestedRegion
1457
 
     * and the union of modifiedRegion and copyRegion.  If it's empty then
1458
 
     * no update is needed.
1459
 
     */
1460
 
 
1461
 
    updateRegion = sraRgnCreateRgn(givenUpdateRegion);
1462
 
    if(cl->screen->progressiveSliceHeight>0) {
1463
 
            int height=cl->screen->progressiveSliceHeight,
1464
 
                y=cl->progressiveSliceY;
1465
 
            sraRegionPtr bbox=sraRgnBBox(updateRegion);
1466
 
            sraRect rect;
1467
 
            if(sraRgnPopRect(bbox,&rect,0)) {
1468
 
                sraRegionPtr slice;
1469
 
                if(y<rect.y1 || y>=rect.y2)
1470
 
                    y=rect.y1;
1471
 
                slice=sraRgnCreateRect(0,y,cl->screen->width,y+height);
1472
 
                sraRgnAnd(updateRegion,slice);
1473
 
                sraRgnDestroy(slice);
1474
 
            }
1475
 
            sraRgnDestroy(bbox);
1476
 
            y+=height;
1477
 
            if(y>=cl->screen->height)
1478
 
                    y=0;
1479
 
            cl->progressiveSliceY=y;
1480
 
    }
1481
 
 
1482
 
    sraRgnOr(updateRegion,cl->copyRegion);
1483
 
    if(!sraRgnAnd(updateRegion,cl->requestedRegion) &&
1484
 
       !sendCursorShape && !sendCursorPos) {
1485
 
      sraRgnDestroy(updateRegion);
1486
 
      UNLOCK(cl->updateMutex);
1487
 
      return TRUE;
1488
 
    }
1489
 
 
1490
 
    /*
1491
 
     * We assume that the client doesn't have any pixel data outside the
1492
 
     * requestedRegion.  In other words, both the source and destination of a
1493
 
     * copy must lie within requestedRegion.  So the region we can send as a
1494
 
     * copy is the intersection of the copyRegion with both the requestedRegion
1495
 
     * and the requestedRegion translated by the amount of the copy.  We set
1496
 
     * updateCopyRegion to this.
1497
 
     */
1498
 
 
1499
 
    updateCopyRegion = sraRgnCreateRgn(cl->copyRegion);
1500
 
    sraRgnAnd(updateCopyRegion,cl->requestedRegion);
1501
 
    tmpRegion = sraRgnCreateRgn(cl->requestedRegion);
1502
 
    sraRgnOffset(tmpRegion,cl->copyDX,cl->copyDY);
1503
 
    sraRgnAnd(updateCopyRegion,tmpRegion);
1504
 
    sraRgnDestroy(tmpRegion);
1505
 
    dx = cl->copyDX;
1506
 
    dy = cl->copyDY;
1507
 
 
1508
 
    /*
1509
 
     * Next we remove updateCopyRegion from updateRegion so that updateRegion
1510
 
     * is the part of this update which is sent as ordinary pixel data (i.e not
1511
 
     * a copy).
1512
 
     */
1513
 
 
1514
 
    sraRgnSubtract(updateRegion,updateCopyRegion);
1515
 
 
1516
 
    /*
1517
 
     * Finally we leave modifiedRegion to be the remainder (if any) of parts of
1518
 
     * the screen which are modified but outside the requestedRegion.  We also
1519
 
     * empty both the requestedRegion and the copyRegion - note that we never
1520
 
     * carry over a copyRegion for a future update.
1521
 
     */
1522
 
 
1523
 
 
1524
 
     sraRgnOr(cl->modifiedRegion,cl->copyRegion);
1525
 
     sraRgnSubtract(cl->modifiedRegion,updateRegion);
1526
 
     sraRgnSubtract(cl->modifiedRegion,updateCopyRegion);
1527
 
 
1528
 
     sraRgnMakeEmpty(cl->requestedRegion);
1529
 
     sraRgnMakeEmpty(cl->copyRegion);
1530
 
     cl->copyDX = 0;
1531
 
     cl->copyDY = 0;
1532
 
   
1533
 
     UNLOCK(cl->updateMutex);
1534
 
   
1535
 
   /*
1536
 
     * Now send the update.
1537
 
     */
1538
 
 
1539
 
    cl->rfbFramebufferUpdateMessagesSent++;
1540
 
 
1541
 
    if (cl->preferredEncoding == rfbEncodingCoRRE) {
1542
 
        nUpdateRegionRects = 0;
1543
 
 
1544
 
        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1545
 
            int x = rect.x1;
1546
 
            int y = rect.y1;
1547
 
            int w = rect.x2 - x;
1548
 
            int h = rect.y2 - y;
1549
 
            int rectsPerRow = (w-1)/cl->correMaxWidth+1;
1550
 
            int rows = (h-1)/cl->correMaxHeight+1;
1551
 
            nUpdateRegionRects += rectsPerRow*rows;
1552
 
        }
1553
 
        sraRgnReleaseIterator(i);
1554
 
#ifdef HAVE_LIBZ
1555
 
    } else if (cl->preferredEncoding == rfbEncodingZlib) {
1556
 
        nUpdateRegionRects = 0;
1557
 
 
1558
 
        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1559
 
            int x = rect.x1;
1560
 
            int y = rect.y1;
1561
 
            int w = rect.x2 - x;
1562
 
            int h = rect.y2 - y;
1563
 
            nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1);
1564
 
        }
1565
 
        sraRgnReleaseIterator(i);
1566
 
#ifdef HAVE_LIBJPEG
1567
 
    } else if (cl->preferredEncoding == rfbEncodingTight) {
1568
 
        nUpdateRegionRects = 0;
1569
 
 
1570
 
        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1571
 
            int x = rect.x1;
1572
 
            int y = rect.y1;
1573
 
            int w = rect.x2 - x;
1574
 
            int h = rect.y2 - y;
1575
 
            int n = rfbNumCodedRectsTight(cl, x, y, w, h);
1576
 
            if (n == 0) {
1577
 
                nUpdateRegionRects = 0xFFFF;
1578
 
                break;
1579
 
            }
1580
 
            nUpdateRegionRects += n;
1581
 
        }
1582
 
        sraRgnReleaseIterator(i);
1583
 
#endif
1584
 
#endif
1585
 
    } else {
1586
 
        nUpdateRegionRects = sraRgnCountRects(updateRegion);
1587
 
    }
1588
 
 
1589
 
    fu->type = rfbFramebufferUpdate;
1590
 
    if (nUpdateRegionRects != 0xFFFF) {
1591
 
        if(cl->screen->maxRectsPerUpdate>0
1592
 
#ifdef HAVE_LIBJPEG
1593
 
           /* Tight encoding counts the rectangles differently */
1594
 
           && cl->preferredEncoding != rfbEncodingTight
1595
 
           && cl->preferredEncoding != rfbEncodingCoRRE
1596
 
#endif
1597
 
           && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
1598
 
            sraRegion* newUpdateRegion = sraRgnBBox(updateRegion);
1599
 
            sraRgnDestroy(updateRegion);
1600
 
            updateRegion = newUpdateRegion;
1601
 
            nUpdateRegionRects = sraRgnCountRects(updateRegion);
1602
 
        }
1603
 
        fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
1604
 
                                           nUpdateRegionRects +
1605
 
                                           !!sendCursorShape + !!sendCursorPos));
1606
 
    } else {
1607
 
        fu->nRects = 0xFFFF;
1608
 
    }
1609
 
    cl->ublen = sz_rfbFramebufferUpdateMsg;
1610
 
 
1611
 
   if (sendCursorShape) {
1612
 
        cl->cursorWasChanged = FALSE;
1613
 
        if (!rfbSendCursorShape(cl)) {
1614
 
            sraRgnDestroy(updateRegion);
1615
 
            return FALSE;
1616
 
        }
1617
 
    }
1618
 
   
1619
 
   if (sendCursorPos) {
1620
 
        cl->cursorWasMoved = FALSE;
1621
 
        if (!rfbSendCursorPos(cl)) {
1622
 
            sraRgnDestroy(updateRegion);
1623
 
            return FALSE;
1624
 
        }
1625
 
    }
1626
 
   
1627
 
    if (!sraRgnEmpty(updateCopyRegion)) {
1628
 
        if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy)) {
1629
 
            sraRgnDestroy(updateRegion);
1630
 
            sraRgnDestroy(updateCopyRegion);
1631
 
            return FALSE;
1632
 
        }
1633
 
    }
1634
 
 
1635
 
    sraRgnDestroy(updateCopyRegion);
1636
 
 
1637
 
    for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1638
 
        int x = rect.x1;
1639
 
        int y = rect.y1;
1640
 
        int w = rect.x2 - x;
1641
 
        int h = rect.y2 - y;
1642
 
 
1643
 
        cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader
1644
 
                                      + w * (cl->format.bitsPerPixel / 8) * h);
1645
 
 
1646
 
        switch (cl->preferredEncoding) {
1647
 
        case rfbEncodingRaw:
1648
 
            if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) {
1649
 
                sraRgnDestroy(updateRegion);
1650
 
                sraRgnReleaseIterator(i);
1651
 
                return FALSE;
1652
 
            }
1653
 
            break;
1654
 
        case rfbEncodingRRE:
1655
 
            if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) {
1656
 
                sraRgnDestroy(updateRegion);
1657
 
                sraRgnReleaseIterator(i);
1658
 
                return FALSE;
1659
 
            }
1660
 
            break;
1661
 
        case rfbEncodingCoRRE:
1662
 
            if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) {
1663
 
                sraRgnDestroy(updateRegion);
1664
 
                sraRgnReleaseIterator(i);
1665
 
                return FALSE;
1666
 
            }
1667
 
            break;
1668
 
        case rfbEncodingHextile:
1669
 
            if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) {
1670
 
                sraRgnDestroy(updateRegion);
1671
 
                sraRgnReleaseIterator(i);
1672
 
                return FALSE;
1673
 
            }
1674
 
            break;
1675
 
#ifdef HAVE_LIBZ
1676
 
        case rfbEncodingZlib:
1677
 
            if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) {
1678
 
                sraRgnDestroy(updateRegion);
1679
 
                sraRgnReleaseIterator(i);
1680
 
                return FALSE;
1681
 
            }
1682
 
            break;
1683
 
#ifdef HAVE_LIBJPEG
1684
 
        case rfbEncodingTight:
1685
 
            if (!rfbSendRectEncodingTight(cl, x, y, w, h)) {
1686
 
                sraRgnDestroy(updateRegion);
1687
 
                sraRgnReleaseIterator(i);
1688
 
                return FALSE;
1689
 
            }
1690
 
            break;
1691
 
#endif
1692
 
#endif
1693
 
#ifdef HAVE_LIBZ
1694
 
       case rfbEncodingZRLE:
1695
 
           if (!rfbSendRectEncodingZRLE(cl, x, y, w, h)) {
1696
 
               sraRgnDestroy(updateRegion);
1697
 
                sraRgnReleaseIterator(i);
1698
 
               return FALSE;
1699
 
           }
1700
 
           break;
1701
 
#endif
1702
 
        }
1703
 
    }
1704
 
    sraRgnReleaseIterator(i);
1705
 
 
1706
 
    if ( nUpdateRegionRects == 0xFFFF &&
1707
 
         !rfbSendLastRectMarker(cl) ) {
1708
 
        sraRgnDestroy(updateRegion);
1709
 
        return FALSE;
1710
 
    }
1711
 
 
1712
 
    if (!rfbSendUpdateBuf(cl)) {
1713
 
        sraRgnDestroy(updateRegion);
1714
 
        return FALSE;
1715
 
    }
1716
 
 
1717
 
    sraRgnDestroy(updateRegion);
1718
 
    return TRUE;
1719
 
}
1720
 
 
1721
 
 
1722
 
/*
1723
 
 * Send the copy region as a string of CopyRect encoded rectangles.
1724
 
 * The only slightly tricky thing is that we should send the messages in
1725
 
 * the correct order so that an earlier CopyRect will not corrupt the source
1726
 
 * of a later one.
1727
 
 */
1728
 
 
1729
 
rfbBool
1730
 
rfbSendCopyRegion(cl, reg, dx, dy)
1731
 
    rfbClientPtr cl;
1732
 
    sraRegionPtr reg;
1733
 
    int dx, dy;
1734
 
{
1735
 
    int x, y, w, h;
1736
 
    rfbFramebufferUpdateRectHeader rect;
1737
 
    rfbCopyRect cr;
1738
 
    sraRectangleIterator* i;
1739
 
    sraRect rect1;
1740
 
 
1741
 
    /* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */
1742
 
    i = sraRgnGetReverseIterator(reg,dx>0,dy>0);
1743
 
 
1744
 
    while(sraRgnIteratorNext(i,&rect1)) {
1745
 
      x = rect1.x1;
1746
 
      y = rect1.y1;
1747
 
      w = rect1.x2 - x;
1748
 
      h = rect1.y2 - y;
1749
 
 
1750
 
      rect.r.x = Swap16IfLE(x);
1751
 
      rect.r.y = Swap16IfLE(y);
1752
 
      rect.r.w = Swap16IfLE(w);
1753
 
      rect.r.h = Swap16IfLE(h);
1754
 
      rect.encoding = Swap32IfLE(rfbEncodingCopyRect);
1755
 
 
1756
 
      memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1757
 
             sz_rfbFramebufferUpdateRectHeader);
1758
 
      cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1759
 
 
1760
 
      cr.srcX = Swap16IfLE(x - dx);
1761
 
      cr.srcY = Swap16IfLE(y - dy);
1762
 
 
1763
 
      memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect);
1764
 
      cl->ublen += sz_rfbCopyRect;
1765
 
 
1766
 
      cl->rfbRectanglesSent[rfbEncodingCopyRect]++;
1767
 
      cl->rfbBytesSent[rfbEncodingCopyRect]
1768
 
        += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect;
1769
 
 
1770
 
    }
1771
 
 
1772
 
    return TRUE;
1773
 
}
1774
 
 
1775
 
/*
1776
 
 * Send a given rectangle in raw encoding (rfbEncodingRaw).
1777
 
 */
1778
 
 
1779
 
rfbBool
1780
 
rfbSendRectEncodingRaw(cl, x, y, w, h)
1781
 
    rfbClientPtr cl;
1782
 
    int x, y, w, h;
1783
 
{
1784
 
    rfbFramebufferUpdateRectHeader rect;
1785
 
    int nlines;
1786
 
    int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
1787
 
    char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
1788
 
                   + (x * (cl->screen->bitsPerPixel / 8)));
1789
 
 
1790
 
    /* Flush the buffer to guarantee correct alignment for translateFn(). */
1791
 
    if (cl->ublen > 0) {
1792
 
        if (!rfbSendUpdateBuf(cl))
1793
 
            return FALSE;
1794
 
    }
1795
 
 
1796
 
    rect.r.x = Swap16IfLE(x);
1797
 
    rect.r.y = Swap16IfLE(y);
1798
 
    rect.r.w = Swap16IfLE(w);
1799
 
    rect.r.h = Swap16IfLE(h);
1800
 
    rect.encoding = Swap32IfLE(rfbEncodingRaw);
1801
 
 
1802
 
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
1803
 
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1804
 
 
1805
 
    cl->rfbRectanglesSent[rfbEncodingRaw]++;
1806
 
    cl->rfbBytesSent[rfbEncodingRaw]
1807
 
        += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h;
1808
 
 
1809
 
    nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
1810
 
 
1811
 
    while (TRUE) {
1812
 
        if (nlines > h)
1813
 
            nlines = h;
1814
 
 
1815
 
        (*cl->translateFn)(cl->translateLookupTable,
1816
 
                           &(cl->screen->rfbServerFormat),
1817
 
                           &cl->format, fbptr, &cl->updateBuf[cl->ublen],
1818
 
                           cl->screen->paddedWidthInBytes, w, nlines);
1819
 
 
1820
 
        cl->ublen += nlines * bytesPerLine;
1821
 
        h -= nlines;
1822
 
 
1823
 
        if (h == 0)     /* rect fitted in buffer, do next one */
1824
 
            return TRUE;
1825
 
 
1826
 
        /* buffer full - flush partial rect and do another nlines */
1827
 
 
1828
 
        if (!rfbSendUpdateBuf(cl))
1829
 
            return FALSE;
1830
 
 
1831
 
        fbptr += (cl->screen->paddedWidthInBytes * nlines);
1832
 
 
1833
 
        nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
1834
 
        if (nlines == 0) {
1835
 
            rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d "
1836
 
                   "bytes per line\n", bytesPerLine);
1837
 
            rfbCloseClient(cl);
1838
 
            return FALSE;
1839
 
        }
1840
 
    }
1841
 
}
1842
 
 
1843
 
 
1844
 
 
1845
 
/*
1846
 
 * Send an empty rectangle with encoding field set to value of
1847
 
 * rfbEncodingLastRect to notify client that this is the last
1848
 
 * rectangle in framebuffer update ("LastRect" extension of RFB
1849
 
 * protocol).
1850
 
 */
1851
 
 
1852
 
rfbBool
1853
 
rfbSendLastRectMarker(cl)
1854
 
    rfbClientPtr cl;
1855
 
{
1856
 
    rfbFramebufferUpdateRectHeader rect;
1857
 
 
1858
 
    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
1859
 
        if (!rfbSendUpdateBuf(cl))
1860
 
            return FALSE;
1861
 
    }
1862
 
 
1863
 
    rect.encoding = Swap32IfLE(rfbEncodingLastRect);
1864
 
    rect.r.x = 0;
1865
 
    rect.r.y = 0;
1866
 
    rect.r.w = 0;
1867
 
    rect.r.h = 0;
1868
 
 
1869
 
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
1870
 
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1871
 
 
1872
 
    cl->rfbLastRectMarkersSent++;
1873
 
    cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
1874
 
 
1875
 
    return TRUE;
1876
 
}
1877
 
 
1878
 
 
1879
 
/*
1880
 
 * Send NewFBSize pseudo-rectangle. This tells the client to change
1881
 
 * its framebuffer size.
1882
 
 */
1883
 
 
1884
 
rfbBool
1885
 
rfbSendNewFBSize(cl, w, h)
1886
 
    rfbClientPtr cl;
1887
 
    int w, h;
1888
 
{
1889
 
    rfbFramebufferUpdateRectHeader rect;
1890
 
 
1891
 
    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
1892
 
        if (!rfbSendUpdateBuf(cl))
1893
 
            return FALSE;
1894
 
    }
1895
 
 
1896
 
    rect.encoding = Swap32IfLE(rfbEncodingNewFBSize);
1897
 
    rect.r.x = 0;
1898
 
    rect.r.y = 0;
1899
 
    rect.r.w = Swap16IfLE(w);
1900
 
    rect.r.h = Swap16IfLE(h);
1901
 
 
1902
 
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1903
 
           sz_rfbFramebufferUpdateRectHeader);
1904
 
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1905
 
 
1906
 
    cl->rfbLastRectMarkersSent++;
1907
 
    cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
1908
 
 
1909
 
    return TRUE;
1910
 
}
1911
 
 
1912
 
 
1913
 
/*
1914
 
 * Send the contents of cl->updateBuf.  Returns 1 if successful, -1 if
1915
 
 * not (errno should be set).
1916
 
 */
1917
 
 
1918
 
rfbBool
1919
 
rfbSendUpdateBuf(cl)
1920
 
    rfbClientPtr cl;
1921
 
{
1922
 
    if(cl->sock<0)
1923
 
      return FALSE;
1924
 
 
1925
 
    if (WriteExact(cl, cl->updateBuf, cl->ublen) < 0) {
1926
 
        rfbLogPerror("rfbSendUpdateBuf: write");
1927
 
        rfbCloseClient(cl);
1928
 
        return FALSE;
1929
 
    }
1930
 
 
1931
 
    cl->ublen = 0;
1932
 
    return TRUE;
1933
 
}
1934
 
 
1935
 
/*
1936
 
 * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the
1937
 
 * client, using values from the currently installed colormap.
1938
 
 */
1939
 
 
1940
 
rfbBool
1941
 
rfbSendSetColourMapEntries(cl, firstColour, nColours)
1942
 
    rfbClientPtr cl;
1943
 
    int firstColour;
1944
 
    int nColours;
1945
 
{
1946
 
    char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
1947
 
    rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
1948
 
    uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]);
1949
 
    rfbColourMap* cm = &cl->screen->colourMap;
1950
 
    
1951
 
    int i, len;
1952
 
 
1953
 
    scme->type = rfbSetColourMapEntries;
1954
 
 
1955
 
    scme->firstColour = Swap16IfLE(firstColour);
1956
 
    scme->nColours = Swap16IfLE(nColours);
1957
 
 
1958
 
    len = sz_rfbSetColourMapEntriesMsg;
1959
 
 
1960
 
    for (i = 0; i < nColours; i++) {
1961
 
      if(i<(int)cm->count) {
1962
 
        if(cm->is16) {
1963
 
          rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]);
1964
 
          rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]);
1965
 
          rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]);
1966
 
        } else {
1967
 
          rgb[i*3] = Swap16IfLE(cm->data.bytes[i*3]);
1968
 
          rgb[i*3+1] = Swap16IfLE(cm->data.bytes[i*3+1]);
1969
 
          rgb[i*3+2] = Swap16IfLE(cm->data.bytes[i*3+2]);
1970
 
        }
1971
 
      }
1972
 
    }
1973
 
 
1974
 
    len += nColours * 3 * 2;
1975
 
 
1976
 
    if (WriteExact(cl, buf, len) < 0) {
1977
 
        rfbLogPerror("rfbSendSetColourMapEntries: write");
1978
 
        rfbCloseClient(cl);
1979
 
        return FALSE;
1980
 
    }
1981
 
    return TRUE;
1982
 
}
1983
 
 
1984
 
/*
1985
 
 * rfbSendBell sends a Bell message to all the clients.
1986
 
 */
1987
 
 
1988
 
void
1989
 
rfbSendBell(rfbScreenInfoPtr rfbScreen)
1990
 
{
1991
 
    rfbClientIteratorPtr i;
1992
 
    rfbClientPtr cl;
1993
 
    rfbBellMsg b;
1994
 
 
1995
 
    i = rfbGetClientIterator(rfbScreen);
1996
 
    while((cl=rfbClientIteratorNext(i))) {
1997
 
        b.type = rfbBell;
1998
 
        if (WriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) {
1999
 
            rfbLogPerror("rfbSendBell: write");
2000
 
            rfbCloseClient(cl);
2001
 
        }
2002
 
    }
2003
 
    rfbReleaseClientIterator(i);
2004
 
}
2005
 
 
2006
 
 
2007
 
/*
2008
 
 * rfbSendServerCutText sends a ServerCutText message to all the clients.
2009
 
 */
2010
 
 
2011
 
void
2012
 
rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
2013
 
{
2014
 
    rfbClientPtr cl;
2015
 
    rfbServerCutTextMsg sct;
2016
 
    rfbClientIteratorPtr iterator;
2017
 
 
2018
 
    iterator = rfbGetClientIterator(rfbScreen);
2019
 
    while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
2020
 
        sct.type = rfbServerCutText;
2021
 
        sct.length = Swap32IfLE(len);
2022
 
        if (WriteExact(cl, (char *)&sct,
2023
 
                       sz_rfbServerCutTextMsg) < 0) {
2024
 
            rfbLogPerror("rfbSendServerCutText: write");
2025
 
            rfbCloseClient(cl);
2026
 
            continue;
2027
 
        }
2028
 
        if (WriteExact(cl, str, len) < 0) {
2029
 
            rfbLogPerror("rfbSendServerCutText: write");
2030
 
            rfbCloseClient(cl);
2031
 
        }
2032
 
    }
2033
 
    rfbReleaseClientIterator(iterator);
2034
 
}
2035
 
 
2036
 
/*****************************************************************************
2037
 
 *
2038
 
 * UDP can be used for keyboard and pointer events when the underlying
2039
 
 * network is highly reliable.  This is really here to support ORL's
2040
 
 * videotile, whose TCP implementation doesn't like sending lots of small
2041
 
 * packets (such as 100s of pen readings per second!).
2042
 
 */
2043
 
 
2044
 
unsigned char ptrAcceleration = 50;
2045
 
 
2046
 
void
2047
 
rfbNewUDPConnection(rfbScreen,sock)
2048
 
    rfbScreenInfoPtr rfbScreen;
2049
 
    int sock;
2050
 
{
2051
 
    if (write(sock, &ptrAcceleration, 1) < 0) {
2052
 
        rfbLogPerror("rfbNewUDPConnection: write");
2053
 
    }
2054
 
}
2055
 
 
2056
 
/*
2057
 
 * Because UDP is a message based service, we can't read the first byte and
2058
 
 * then the rest of the packet separately like we do with TCP.  We will always
2059
 
 * get a whole packet delivered in one go, so we ask read() for the maximum
2060
 
 * number of bytes we can possibly get.
2061
 
 */
2062
 
 
2063
 
void
2064
 
rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen)
2065
 
{
2066
 
    int n;
2067
 
    rfbClientPtr cl=rfbScreen->udpClient;
2068
 
    rfbClientToServerMsg msg;
2069
 
 
2070
 
    if((!cl) || cl->onHold)
2071
 
      return;
2072
 
 
2073
 
    if ((n = read(rfbScreen->udpSock, (char *)&msg, sizeof(msg))) <= 0) {
2074
 
        if (n < 0) {
2075
 
            rfbLogPerror("rfbProcessUDPInput: read");
2076
 
        }
2077
 
        rfbDisconnectUDPSock(rfbScreen);
2078
 
        return;
2079
 
    }
2080
 
 
2081
 
    switch (msg.type) {
2082
 
 
2083
 
    case rfbKeyEvent:
2084
 
        if (n != sz_rfbKeyEventMsg) {
2085
 
            rfbErr("rfbProcessUDPInput: key event incorrect length\n");
2086
 
            rfbDisconnectUDPSock(rfbScreen);
2087
 
            return;
2088
 
        }
2089
 
        cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
2090
 
        break;
2091
 
 
2092
 
    case rfbPointerEvent:
2093
 
        if (n != sz_rfbPointerEventMsg) {
2094
 
            rfbErr("rfbProcessUDPInput: ptr event incorrect length\n");
2095
 
            rfbDisconnectUDPSock(rfbScreen);
2096
 
            return;
2097
 
        }
2098
 
        cl->screen->ptrAddEvent(msg.pe.buttonMask,
2099
 
                    Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
2100
 
        break;
2101
 
 
2102
 
    default:
2103
 
        rfbErr("rfbProcessUDPInput: unknown message type %d\n",
2104
 
               msg.type);
2105
 
        rfbDisconnectUDPSock(rfbScreen);
2106
 
    }
2107
 
}
2108
 
 
2109
 
#ifdef BACKCHANNEL
2110
 
void rfbSendBackChannel(rfbScreenInfoPtr rfbScreen,char* str,int len)
2111
 
{
2112
 
    rfbClientPtr cl;
2113
 
    rfbBackChannelMsg sct;
2114
 
    rfbClientIteratorPtr iterator;
2115
 
 
2116
 
    iterator = rfbGetClientIterator(rfbScreen);
2117
 
    while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
2118
 
        if (cl->enableBackChannel) {
2119
 
            sct.type = rfbBackChannel;
2120
 
            sct.length = Swap32IfLE(len);
2121
 
            if (WriteExact(cl, (char *)&sct,
2122
 
                           sz_rfbBackChannelMsg) < 0) {
2123
 
                rfbLogPerror("rfbSendBackChannel: write");
2124
 
                rfbCloseClient(cl);
2125
 
                continue;
2126
 
            }
2127
 
            if (WriteExact(cl, str, len) < 0) {
2128
 
                rfbLogPerror("rfbSendBackChannel: write");
2129
 
                rfbCloseClient(cl);
2130
 
            }
2131
 
        }
2132
 
    }
2133
 
    rfbReleaseClientIterator(iterator);
2134
 
}
2135
 
#endif