2
* rfbserver.c - deal with server-side of the RFB protocol.
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.
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.
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.
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,
29
#include <rfb/rfbregion.h>
36
#define write(sock,buf,len) send(sock,buf,len,0)
42
#ifdef HAVE_SYS_SOCKET_H
43
#include <sys/socket.h>
45
#ifdef HAVE_NETINET_IN_H
46
#include <netinet/in.h>
47
#include <netinet/tcp.h>
48
#include <arpa/inet.h>
53
#include <vncserverctrl.h>
58
#define DEBUGPROTO(x) x
65
#define ITALC_EXTENSIONS
67
#ifdef ITALC_EXTENSIONS
69
/* extensions for iTALC */
70
#include <italc_rfb_ext.h>
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
86
rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */
88
static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
89
static void rfbProcessClientNormalMessage(rfbClientPtr cl);
90
static void rfbProcessClientInitMessage(rfbClientPtr cl);
92
#ifdef HAVE_LIBPTHREAD
93
void rfbIncrClientRef(rfbClientPtr cl)
95
LOCK(cl->refCountMutex);
97
UNLOCK(cl->refCountMutex);
100
void rfbDecrClientRef(rfbClientPtr cl)
102
LOCK(cl->refCountMutex);
104
if(cl->refCount<=0) /* just to be sure also < 0 */
105
TSIGNAL(cl->deleteCond);
106
UNLOCK(cl->refCountMutex);
109
void rfbIncrClientRef(rfbClientPtr cl) {}
110
void rfbDecrClientRef(rfbClientPtr cl) {}
113
#ifdef HAVE_LIBPTHREAD
114
MUTEX(rfbClientListMutex);
117
struct rfbClientIterator {
119
rfbScreenInfoPtr screen;
123
rfbClientListInit(rfbScreenInfoPtr rfbScreen)
125
if(sizeof(rfbBool)!=1) {
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 */
131
rfbScreen->rfbClientHead = NULL;
132
INIT_MUTEX(rfbClientListMutex);
136
rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
138
rfbClientIteratorPtr i =
139
(rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
141
i->screen = rfbScreen;
146
rfbClientIteratorHead(rfbClientIteratorPtr i)
148
#ifdef HAVE_LIBPTHREAD
150
rfbDecrClientRef(i->next);
151
rfbIncrClientRef(i->screen->rfbClientHead);
154
LOCK(rfbClientListMutex);
155
i->next = i->screen->rfbClientHead;
156
UNLOCK(rfbClientListMutex);
161
rfbClientIteratorNext(rfbClientIteratorPtr i)
164
LOCK(rfbClientListMutex);
165
i->next = i->screen->rfbClientHead;
166
UNLOCK(rfbClientListMutex);
168
IF_PTHREADS(rfbClientPtr cl = i->next);
169
i->next = i->next->next;
170
IF_PTHREADS(rfbDecrClientRef(cl));
173
#ifdef HAVE_LIBPTHREAD
174
while(i->next && i->next->sock<0)
175
i->next = i->next->next;
177
rfbIncrClientRef(i->next);
184
rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
186
IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
192
* rfbNewClientConnection is called from sockets.c when a new connection
197
rfbNewClientConnection(rfbScreen,sock)
198
rfbScreenInfoPtr rfbScreen;
203
cl = rfbNewClient(rfbScreen,sock);
206
newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1);
212
* rfbReverseConnection is called by the CORBA stuff to make an outward
213
* connection to a "listening" RFB client.
217
rfbReverseConnection(rfbScreen,host, port)
218
rfbScreenInfoPtr rfbScreen;
225
if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
226
return (rfbClientPtr)NULL;
228
cl = rfbNewClient(rfbScreen, sock);
231
cl->reverseConnection = TRUE;
239
* rfbNewClient is called when a new connection has been made by whatever
244
rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
245
rfbScreenInfoPtr rfbScreen;
249
rfbProtocolVersionMsg pv;
250
rfbClientIteratorPtr iterator;
252
struct sockaddr_in addr;
253
size_t addrlen = sizeof(struct sockaddr_in);
255
cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
257
cl->screen = rfbScreen;
259
cl->viewOnly = FALSE;
264
rfbLog(" accepted UDP client\n");
268
getpeername(sock, (struct sockaddr *)&addr, &addrlen);
269
cl->host = strdup(inet_ntoa(addr.sin_addr));
271
rfbLog(" other clients:\n");
272
iterator = rfbGetClientIterator(rfbScreen);
273
while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
274
rfbLog(" %s\n",cl_->host);
276
rfbReleaseClientIterator(iterator);
279
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
280
rfbLogPerror("fcntl failed");
286
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
287
(char *)&one, sizeof(one)) < 0) {
288
rfbLogPerror("setsockopt failed");
293
FD_SET(sock,&(rfbScreen->allFds));
294
rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
296
INIT_MUTEX(cl->outputMutex);
297
INIT_MUTEX(cl->refCountMutex);
298
INIT_COND(cl->deleteCond);
300
cl->state = RFB_PROTOCOL_VERSION;
302
cl->reverseConnection = FALSE;
303
cl->readyForSetColourMapEntries = FALSE;
304
cl->useCopyRect = FALSE;
305
cl->preferredEncoding = rfbEncodingRaw;
306
cl->correMaxWidth = 48;
307
cl->correMaxHeight = 48;
312
cl->copyRegion = sraRgnCreate();
317
sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
319
INIT_MUTEX(cl->updateMutex);
320
INIT_COND(cl->updateCond);
322
cl->requestedRegion = sraRgnCreate();
324
cl->format = cl->screen->rfbServerFormat;
325
cl->translateFn = rfbTranslateNone;
326
cl->translateLookupTable = NULL;
328
LOCK(rfbClientListMutex);
330
IF_PTHREADS(cl->refCount = 0);
331
cl->next = rfbScreen->rfbClientHead;
333
if (rfbScreen->rfbClientHead)
334
rfbScreen->rfbClientHead->prev = cl;
336
rfbScreen->rfbClientHead = cl;
337
UNLOCK(rfbClientListMutex);
340
cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
341
cl->tightQualityLevel = -1;
344
for (i = 0; i < 4; i++)
345
cl->zsActive[i] = FALSE;
349
cl->enableCursorShapeUpdates = FALSE;
350
cl->enableCursorPosUpdates = FALSE;
351
cl->useRichCursorEncoding = FALSE;
352
cl->enableLastRectEncoding = FALSE;
353
cl->useNewFBSize = FALSE;
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;
363
cl->zlibCompressLevel = 5;
366
cl->progressiveSliceY = 0;
368
sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion,
369
rfbProtocolMinorVersion);
371
if (WriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
372
rfbLogPerror("rfbNewClient: write");
374
/* TODO: memory leak here (cl is never freed)
375
* can rfbClientConnectionGone called at this time?
382
cl->clientData = NULL;
383
cl->clientGoneHook = doNothingWithClient;
384
switch (cl->screen->newClientHook(cl)) {
385
case RFB_CLIENT_ON_HOLD:
388
case RFB_CLIENT_ACCEPT:
391
case RFB_CLIENT_REFUSE:
393
rfbClientConnectionGone(cl);
401
rfbNewClient(rfbScreen,sock)
402
rfbScreenInfoPtr rfbScreen;
405
return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
409
rfbNewUDPClient(rfbScreen)
410
rfbScreenInfoPtr rfbScreen;
412
return((rfbScreen->udpClient=
413
rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE)));
417
* rfbClientConnectionGone is called from sockets.c just after a connection
422
rfbClientConnectionGone(cl)
427
LOCK(rfbClientListMutex);
430
cl->prev->next = cl->next;
432
cl->screen->rfbClientHead = cl->next;
434
cl->next->prev = cl->prev;
440
#ifdef HAVE_LIBPTHREAD
441
if(cl->screen->backgroundLoop != FALSE)
443
LOCK(cl->refCountMutex);
445
UNLOCK(cl->refCountMutex);
447
WAIT(cl->deleteCond,cl->refCountMutex);
452
FD_CLR(cl->sock,&(cl->screen->allFds));
454
cl->clientGoneHook(cl);
456
rfbLog("Client %s gone\n",cl->host);
460
/* Release the compression state structures if any. */
461
if ( cl->compStreamInited ) {
462
deflateEnd( &(cl->compStream) );
466
for (i = 0; i < 4; i++) {
468
deflateEnd(&cl->zsStruct[i]);
473
if (pointerClient == cl)
474
pointerClient = NULL;
476
sraRgnDestroy(cl->modifiedRegion);
477
sraRgnDestroy(cl->requestedRegion);
478
sraRgnDestroy(cl->copyRegion);
480
UNLOCK(rfbClientListMutex);
482
if (cl->translateLookupTable) free(cl->translateLookupTable);
484
TINI_COND(cl->updateCond);
485
TINI_MUTEX(cl->updateMutex);
487
LOCK(cl->outputMutex);
488
TINI_MUTEX(cl->outputMutex);
491
destroyConnection(cl);
501
* rfbProcessClientMessage is called when there is data to read from a client.
505
rfbProcessClientMessage(cl)
509
case RFB_PROTOCOL_VERSION:
510
rfbProcessClientProtocolVersion(cl);
512
case RFB_AUTHENTICATION:
513
rfbAuthProcessClientMessage(cl);
515
case RFB_INITIALISATION:
516
rfbProcessClientInitMessage(cl);
519
rfbProcessClientNormalMessage(cl);
526
* rfbProcessClientProtocolVersion is called when the client sends its
531
rfbProcessClientProtocolVersion(cl)
534
rfbProtocolVersionMsg pv;
535
int n, major_, minor_;
536
char failureReason[256];
538
if ((n = ReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
540
rfbLog("rfbProcessClientProtocolVersion: client gone\n");
542
rfbLogPerror("rfbProcessClientProtocolVersion: read");
547
pv[sz_rfbProtocolVersionMsg] = 0;
548
if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
550
if(sscanf(pv,"RFB %03d.%03d %1024s\n",&major_,&minor_,name) != 3) {
551
rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client\n");
556
cl->host=strdup(name);
558
rfbLog("Protocol version %d.%d\n", major_, minor_);
560
if (major_ != rfbProtocolMajorVersion) {
561
/* Major version mismatch - send a ConnFailed message */
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);
571
if (minor_ != rfbProtocolMinorVersion) {
572
/* Minor version mismatch - warn but try to continue */
573
rfbLog("Ignoring minor version mismatch\n");
576
rfbAuthNewClient(cl);
581
* rfbClientConnFailed is called when a client connection has failed either
582
* because it talks the wrong protocol or it has failed authentication.
586
rfbClientConnFailed(cl, reason)
591
int len = strlen(reason);
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);
598
if (WriteExact(cl, buf, 8 + len) < 0)
599
rfbLogPerror("rfbClientConnFailed: write");
606
* rfbProcessClientInitMessage is called when the client sends its
607
* initialisation message.
611
rfbProcessClientInitMessage(cl)
616
rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
618
rfbClientIteratorPtr iterator;
619
rfbClientPtr otherCl;
621
if ((n = ReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
623
rfbLog("rfbProcessClientInitMessage: client gone\n");
625
rfbLogPerror("rfbProcessClientInitMessage: read");
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);
637
if (strlen(cl->screen->desktopName) > 128) /* sanity check on desktop name len */
638
((char*)cl->screen->desktopName)[128] = 0;
640
strcpy(buf + sz_rfbServerInitMsg, cl->screen->desktopName);
641
len = strlen(buf + sz_rfbServerInitMsg);
642
si->nameLength = Swap32IfLE(len);
644
if (WriteExact(cl, buf, sz_rfbServerInitMsg + len) < 0) {
645
rfbLogPerror("rfbProcessClientInitMessage: write");
650
cl->state = RFB_NORMAL;
652
if (!cl->reverseConnection &&
653
(cl->screen->rfbNeverShared || (!cl->screen->rfbAlwaysShared && !ci.shared))) {
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);
662
rfbReleaseClientIterator(iterator);
666
rfbReleaseClientIterator(iterator);
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",
673
rfbCloseClient(otherCl);
676
rfbReleaseClientIterator(iterator);
681
static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h,
682
rfbScreenInfoPtr screen)
688
if(*w>screen->width-*x)
690
/* possible underflow */
691
if(*w>screen->width-*x)
693
if(*h>screen->height-*y)
694
*h=screen->height-*y;
695
if(*h>screen->height-*y)
703
#ifdef ITALC_EXTENSIONS
704
char * readLine (int _fd) {
705
char buf[BUFFER_SIZE];
712
while (read(_fd, ptr, 1) == 1) {
713
if (*ptr == '\n' || bytes_read > BUFFER_SIZE-2)
718
if (/* *ptr == '\n' && */bytes_read > 0) {
719
char * line = malloc(bytes_read+1);
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);
736
* rfbProcessClientNormalMessage is called when the client has sent a normal
741
rfbProcessClientNormalMessage(cl)
745
rfbClientToServerMsg msg;
748
if ((n = ReadExact(cl, (char *)&msg, 1)) <= 0) {
750
rfbLogPerror("rfbProcessClientNormalMessage: read");
757
case rfbSetPixelFormat:
759
if ((n = ReadExact(cl, ((char *)&msg) + 1,
760
sz_rfbSetPixelFormatMsg - 1)) <= 0) {
762
rfbLogPerror("rfbProcessClientNormalMessage: read");
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;
778
cl->readyForSetColourMapEntries = TRUE;
779
cl->screen->setTranslateFunction(cl);
784
case rfbFixColourMapEntries:
785
if ((n = ReadExact(cl, ((char *)&msg) + 1,
786
sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
788
rfbLogPerror("rfbProcessClientNormalMessage: read");
792
rfbLog("rfbProcessClientNormalMessage: %s",
793
"FixColourMapEntries unsupported\n");
798
case rfbSetEncodings:
803
if ((n = ReadExact(cl, ((char *)&msg) + 1,
804
sz_rfbSetEncodingsMsg - 1)) <= 0) {
806
rfbLogPerror("rfbProcessClientNormalMessage: read");
811
msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
813
cl->preferredEncoding = -1;
814
cl->useCopyRect = FALSE;
815
cl->enableCursorShapeUpdates = FALSE;
816
cl->enableCursorPosUpdates = FALSE;
817
cl->enableLastRectEncoding = FALSE;
818
cl->useNewFBSize = FALSE;
820
for (i = 0; i < msg.se.nEncodings; i++) {
821
if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
823
rfbLogPerror("rfbProcessClientNormalMessage: read");
827
enc = Swap32IfLE(enc);
831
case rfbEncodingCopyRect:
832
cl->useCopyRect = TRUE;
835
if (cl->preferredEncoding == -1) {
836
cl->preferredEncoding = enc;
837
rfbLog("Using raw encoding for client %s\n",
842
if (cl->preferredEncoding == -1) {
843
cl->preferredEncoding = enc;
844
rfbLog("Using rre encoding for client %s\n",
848
case rfbEncodingCoRRE:
849
if (cl->preferredEncoding == -1) {
850
cl->preferredEncoding = enc;
851
rfbLog("Using CoRRE encoding for client %s\n",
855
case rfbEncodingHextile:
856
if (cl->preferredEncoding == -1) {
857
cl->preferredEncoding = enc;
858
rfbLog("Using hextile encoding for client %s\n",
863
case rfbEncodingZlib:
864
if (cl->preferredEncoding == -1) {
865
cl->preferredEncoding = enc;
866
rfbLog("Using zlib encoding for client %s\n",
871
case rfbEncodingTight:
872
if (cl->preferredEncoding == -1) {
873
cl->preferredEncoding = enc;
874
rfbLog("Using tight encoding for client %s\n",
880
case rfbEncodingXCursor:
881
if(!cl->screen->dontConvertRichCursorToXCursor) {
882
rfbLog("Enabling X-style cursor updates for client %s\n",
884
cl->enableCursorShapeUpdates = TRUE;
885
cl->cursorWasChanged = TRUE;
888
case rfbEncodingRichCursor:
889
rfbLog("Enabling full-color cursor updates for client %s\n",
891
cl->enableCursorShapeUpdates = TRUE;
892
cl->useRichCursorEncoding = TRUE;
893
cl->cursorWasChanged = TRUE;
895
case rfbEncodingPointerPos:
896
if (!cl->enableCursorPosUpdates) {
897
rfbLog("Enabling cursor position updates for client %s\n",
899
cl->enableCursorPosUpdates = TRUE;
900
cl->cursorWasMoved = TRUE;
903
case rfbEncodingLastRect:
904
if (!cl->enableLastRectEncoding) {
905
rfbLog("Enabling LastRect protocol extension for client "
907
cl->enableLastRectEncoding = TRUE;
910
case rfbEncodingNewFBSize:
911
if (!cl->useNewFBSize) {
912
rfbLog("Enabling NewFBSize protocol extension for client "
914
cl->useNewFBSize = TRUE;
918
case rfbEncodingBackChannel:
919
if (!cl->enableBackChannel) {
920
rfbLog("Enabling BackChannel protocol extension for "
921
"client %s\n", cl->host);
922
cl->enableBackChannel = TRUE;
927
case rfbEncodingZRLE:
928
if (cl->preferredEncoding == -1) {
929
cl->preferredEncoding = enc;
930
rfbLog("Using ZRLE encoding for client %s\n",
937
if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
938
enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
939
cl->zlibCompressLevel = enc & 0x0F;
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);
952
rfbLog("rfbProcessClientNormalMessage: ignoring unknown "
953
"encoding type %d\n", (int)enc);
957
if (cl->preferredEncoding == -1) {
958
cl->preferredEncoding = rfbEncodingRaw;
961
if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) {
962
rfbLog("Disabling cursor position updates for client %s\n",
964
cl->enableCursorPosUpdates = FALSE;
971
case rfbFramebufferUpdateRequest:
973
sraRegionPtr tmpRegion;
975
if ((n = ReadExact(cl, ((char *)&msg) + 1,
976
sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
978
rfbLogPerror("rfbProcessClientNormalMessage: read");
983
if(!rectSwapIfLEAndClip(&msg.fur.x,&msg.fur.y,&msg.fur.w,&msg.fur.h,
988
sraRgnCreateRect(msg.fur.x,
991
msg.fur.y+msg.fur.h);
993
LOCK(cl->updateMutex);
994
sraRgnOr(cl->requestedRegion,tmpRegion);
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);
1008
if (!msg.fur.incremental) {
1009
sraRgnOr(cl->modifiedRegion,tmpRegion);
1010
sraRgnSubtract(cl->copyRegion,tmpRegion);
1012
TSIGNAL(cl->updateCond);
1013
UNLOCK(cl->updateMutex);
1015
sraRgnDestroy(tmpRegion);
1022
cl->rfbKeyEventsRcvd++;
1024
if ((n = ReadExact(cl, ((char *)&msg) + 1,
1025
sz_rfbKeyEventMsg - 1)) <= 0) {
1027
rfbLogPerror("rfbProcessClientNormalMessage: read");
1033
cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
1039
case rfbPointerEvent:
1041
cl->rfbPointerEventsRcvd++;
1043
if ((n = ReadExact(cl, ((char *)&msg) + 1,
1044
sz_rfbPointerEventMsg - 1)) <= 0) {
1046
rfbLogPerror("rfbProcessClientNormalMessage: read");
1051
if (pointerClient && (pointerClient != cl))
1054
if (msg.pe.buttonMask == 0)
1055
pointerClient = NULL;
1060
cl->screen->ptrAddEvent(msg.pe.buttonMask,
1061
Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
1067
case rfbClientCutText:
1069
if ((n = ReadExact(cl, ((char *)&msg) + 1,
1070
sz_rfbClientCutTextMsg - 1)) <= 0) {
1072
rfbLogPerror("rfbProcessClientNormalMessage: read");
1077
msg.cct.length = Swap32IfLE(msg.cct.length);
1079
str = (char *)malloc(msg.cct.length);
1081
if ((n = ReadExact(cl, str, msg.cct.length)) <= 0) {
1083
rfbLogPerror("rfbProcessClientNormalMessage: read");
1090
cl->screen->setXCutText(str, msg.cct.length, cl);
1097
#ifdef ITALC_EXTENSIONS
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);
1106
switch (tr.italc_cmd) {
1107
case ITALC_GET_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");
1119
if (WriteExact(cl, user, strlen(user)+1) < 0) {
1120
printf ("Could not send user-name\n");
1126
case ITALC_EXEC_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");
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");
1140
strcat (cmds, "&"); /* make sure, cmds are executed in background... */
1145
case ITALC_START_DEMO: {
1146
char * demo_master_ip;
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");
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");
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 &");
1166
strcat (cmd_line, " 0 &");
1170
free (demo_master_ip);
1174
case ITALC_STOP_DEMO:
1175
system ("killall demoviewer");
1177
case ITALC_LOCK_DISPLAY:
1178
system (SCREEN_LOCKER);
1180
case ITALC_UNLOCK_DISPLAY:
1181
system ("killall screenlocker");
1183
case ITALC_SEND_MSG: {
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");
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");
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, "' &");
1208
case ITALC_INVITE_SUPPORT: {
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");
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");
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);
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");
1244
case ITALC_POST_FILE_REQ: {
1246
Q_UINT32 total_bytes = 0;
1247
Q_UINT32 bytes_done = 0;
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");
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");
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");
1277
/* NOW check for valid FD */
1278
if (outfile_fd > 0) {
1279
write (outfile_fd, buffer, bytes_todo);
1281
bytes_done += bytes_todo;
1287
case ITALC_GET_FILE: {
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");
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");
1306
strcat (filemask, TMP_OUT_FILE_REDIR);
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;
1312
Q_UINT32 total_bytes = 0;
1313
Q_UINT32 bytes_done = 0;
1315
fd = open(line, O_RDONLY);
1318
total_bytes = getFileSize(fd);
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");
1331
if (WriteExact(cl, line, strlen(line)+1) < 0) {
1332
printf ("Could not send file-name\n");
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");
1348
bytes_done += bytes_todo;
1354
close (tmp_file_fd);
1355
unlink (TMP_OUT_FILE);
1364
#endif /* ITALC_EXTENSIONS */
1368
rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", msg.type);
1369
rfbLog(" ... closing connection\n");
1378
* rfbSendFramebufferUpdate - send the currently pending framebuffer update to
1380
* givenUpdateRegion is not changed.
1384
rfbSendFramebufferUpdate(cl, givenUpdateRegion)
1386
sraRegionPtr givenUpdateRegion;
1388
sraRectangleIterator* i;
1390
int nUpdateRegionRects;
1391
rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf;
1392
sraRegionPtr updateRegion,updateCopyRegion,tmpRegion;
1394
rfbBool sendCursorShape = FALSE;
1395
rfbBool sendCursorPos = FALSE;
1397
if(cl->screen->displayHook)
1398
cl->screen->displayHook(cl);
1401
* If framebuffer size was changed and the client supports NewFBSize
1402
* encoding, just send NewFBSize marker and return.
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)) {
1416
return rfbSendUpdateBuf(cl);
1420
* If this client understands cursor shape updates, cursor should be
1421
* removed from the framebuffer. Otherwise, make sure it's put up.
1424
if (cl->enableCursorShapeUpdates) {
1425
if (cl->screen->cursorIsDrawn) {
1426
rfbUndrawCursor(cl->screen);
1428
if (!cl->screen->cursorIsDrawn && cl->cursorWasChanged &&
1429
cl->readyForSetColourMapEntries)
1430
sendCursorShape = TRUE;
1432
if (!cl->screen->cursorIsDrawn) {
1433
rfbDrawCursor(cl->screen);
1438
* Do we plan to send cursor position update?
1441
if (cl->enableCursorPosUpdates && cl->cursorWasMoved)
1442
sendCursorPos = TRUE;
1444
LOCK(cl->updateMutex);
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).
1452
sraRgnSubtract(cl->copyRegion,cl->modifiedRegion);
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.
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);
1467
if(sraRgnPopRect(bbox,&rect,0)) {
1469
if(y<rect.y1 || y>=rect.y2)
1471
slice=sraRgnCreateRect(0,y,cl->screen->width,y+height);
1472
sraRgnAnd(updateRegion,slice);
1473
sraRgnDestroy(slice);
1475
sraRgnDestroy(bbox);
1477
if(y>=cl->screen->height)
1479
cl->progressiveSliceY=y;
1482
sraRgnOr(updateRegion,cl->copyRegion);
1483
if(!sraRgnAnd(updateRegion,cl->requestedRegion) &&
1484
!sendCursorShape && !sendCursorPos) {
1485
sraRgnDestroy(updateRegion);
1486
UNLOCK(cl->updateMutex);
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.
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);
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
1514
sraRgnSubtract(updateRegion,updateCopyRegion);
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.
1524
sraRgnOr(cl->modifiedRegion,cl->copyRegion);
1525
sraRgnSubtract(cl->modifiedRegion,updateRegion);
1526
sraRgnSubtract(cl->modifiedRegion,updateCopyRegion);
1528
sraRgnMakeEmpty(cl->requestedRegion);
1529
sraRgnMakeEmpty(cl->copyRegion);
1533
UNLOCK(cl->updateMutex);
1536
* Now send the update.
1539
cl->rfbFramebufferUpdateMessagesSent++;
1541
if (cl->preferredEncoding == rfbEncodingCoRRE) {
1542
nUpdateRegionRects = 0;
1544
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
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;
1553
sraRgnReleaseIterator(i);
1555
} else if (cl->preferredEncoding == rfbEncodingZlib) {
1556
nUpdateRegionRects = 0;
1558
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1561
int w = rect.x2 - x;
1562
int h = rect.y2 - y;
1563
nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1);
1565
sraRgnReleaseIterator(i);
1567
} else if (cl->preferredEncoding == rfbEncodingTight) {
1568
nUpdateRegionRects = 0;
1570
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1573
int w = rect.x2 - x;
1574
int h = rect.y2 - y;
1575
int n = rfbNumCodedRectsTight(cl, x, y, w, h);
1577
nUpdateRegionRects = 0xFFFF;
1580
nUpdateRegionRects += n;
1582
sraRgnReleaseIterator(i);
1586
nUpdateRegionRects = sraRgnCountRects(updateRegion);
1589
fu->type = rfbFramebufferUpdate;
1590
if (nUpdateRegionRects != 0xFFFF) {
1591
if(cl->screen->maxRectsPerUpdate>0
1593
/* Tight encoding counts the rectangles differently */
1594
&& cl->preferredEncoding != rfbEncodingTight
1595
&& cl->preferredEncoding != rfbEncodingCoRRE
1597
&& nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
1598
sraRegion* newUpdateRegion = sraRgnBBox(updateRegion);
1599
sraRgnDestroy(updateRegion);
1600
updateRegion = newUpdateRegion;
1601
nUpdateRegionRects = sraRgnCountRects(updateRegion);
1603
fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
1604
nUpdateRegionRects +
1605
!!sendCursorShape + !!sendCursorPos));
1607
fu->nRects = 0xFFFF;
1609
cl->ublen = sz_rfbFramebufferUpdateMsg;
1611
if (sendCursorShape) {
1612
cl->cursorWasChanged = FALSE;
1613
if (!rfbSendCursorShape(cl)) {
1614
sraRgnDestroy(updateRegion);
1619
if (sendCursorPos) {
1620
cl->cursorWasMoved = FALSE;
1621
if (!rfbSendCursorPos(cl)) {
1622
sraRgnDestroy(updateRegion);
1627
if (!sraRgnEmpty(updateCopyRegion)) {
1628
if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy)) {
1629
sraRgnDestroy(updateRegion);
1630
sraRgnDestroy(updateCopyRegion);
1635
sraRgnDestroy(updateCopyRegion);
1637
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1640
int w = rect.x2 - x;
1641
int h = rect.y2 - y;
1643
cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader
1644
+ w * (cl->format.bitsPerPixel / 8) * h);
1646
switch (cl->preferredEncoding) {
1647
case rfbEncodingRaw:
1648
if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) {
1649
sraRgnDestroy(updateRegion);
1650
sraRgnReleaseIterator(i);
1654
case rfbEncodingRRE:
1655
if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) {
1656
sraRgnDestroy(updateRegion);
1657
sraRgnReleaseIterator(i);
1661
case rfbEncodingCoRRE:
1662
if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) {
1663
sraRgnDestroy(updateRegion);
1664
sraRgnReleaseIterator(i);
1668
case rfbEncodingHextile:
1669
if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) {
1670
sraRgnDestroy(updateRegion);
1671
sraRgnReleaseIterator(i);
1676
case rfbEncodingZlib:
1677
if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) {
1678
sraRgnDestroy(updateRegion);
1679
sraRgnReleaseIterator(i);
1684
case rfbEncodingTight:
1685
if (!rfbSendRectEncodingTight(cl, x, y, w, h)) {
1686
sraRgnDestroy(updateRegion);
1687
sraRgnReleaseIterator(i);
1694
case rfbEncodingZRLE:
1695
if (!rfbSendRectEncodingZRLE(cl, x, y, w, h)) {
1696
sraRgnDestroy(updateRegion);
1697
sraRgnReleaseIterator(i);
1704
sraRgnReleaseIterator(i);
1706
if ( nUpdateRegionRects == 0xFFFF &&
1707
!rfbSendLastRectMarker(cl) ) {
1708
sraRgnDestroy(updateRegion);
1712
if (!rfbSendUpdateBuf(cl)) {
1713
sraRgnDestroy(updateRegion);
1717
sraRgnDestroy(updateRegion);
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
1730
rfbSendCopyRegion(cl, reg, dx, dy)
1736
rfbFramebufferUpdateRectHeader rect;
1738
sraRectangleIterator* i;
1741
/* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */
1742
i = sraRgnGetReverseIterator(reg,dx>0,dy>0);
1744
while(sraRgnIteratorNext(i,&rect1)) {
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);
1756
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1757
sz_rfbFramebufferUpdateRectHeader);
1758
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1760
cr.srcX = Swap16IfLE(x - dx);
1761
cr.srcY = Swap16IfLE(y - dy);
1763
memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect);
1764
cl->ublen += sz_rfbCopyRect;
1766
cl->rfbRectanglesSent[rfbEncodingCopyRect]++;
1767
cl->rfbBytesSent[rfbEncodingCopyRect]
1768
+= sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect;
1776
* Send a given rectangle in raw encoding (rfbEncodingRaw).
1780
rfbSendRectEncodingRaw(cl, x, y, w, h)
1784
rfbFramebufferUpdateRectHeader rect;
1786
int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
1787
char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
1788
+ (x * (cl->screen->bitsPerPixel / 8)));
1790
/* Flush the buffer to guarantee correct alignment for translateFn(). */
1791
if (cl->ublen > 0) {
1792
if (!rfbSendUpdateBuf(cl))
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);
1802
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
1803
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1805
cl->rfbRectanglesSent[rfbEncodingRaw]++;
1806
cl->rfbBytesSent[rfbEncodingRaw]
1807
+= sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h;
1809
nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
1815
(*cl->translateFn)(cl->translateLookupTable,
1816
&(cl->screen->rfbServerFormat),
1817
&cl->format, fbptr, &cl->updateBuf[cl->ublen],
1818
cl->screen->paddedWidthInBytes, w, nlines);
1820
cl->ublen += nlines * bytesPerLine;
1823
if (h == 0) /* rect fitted in buffer, do next one */
1826
/* buffer full - flush partial rect and do another nlines */
1828
if (!rfbSendUpdateBuf(cl))
1831
fbptr += (cl->screen->paddedWidthInBytes * nlines);
1833
nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
1835
rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d "
1836
"bytes per line\n", bytesPerLine);
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
1853
rfbSendLastRectMarker(cl)
1856
rfbFramebufferUpdateRectHeader rect;
1858
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
1859
if (!rfbSendUpdateBuf(cl))
1863
rect.encoding = Swap32IfLE(rfbEncodingLastRect);
1869
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
1870
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1872
cl->rfbLastRectMarkersSent++;
1873
cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
1880
* Send NewFBSize pseudo-rectangle. This tells the client to change
1881
* its framebuffer size.
1885
rfbSendNewFBSize(cl, w, h)
1889
rfbFramebufferUpdateRectHeader rect;
1891
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
1892
if (!rfbSendUpdateBuf(cl))
1896
rect.encoding = Swap32IfLE(rfbEncodingNewFBSize);
1899
rect.r.w = Swap16IfLE(w);
1900
rect.r.h = Swap16IfLE(h);
1902
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1903
sz_rfbFramebufferUpdateRectHeader);
1904
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1906
cl->rfbLastRectMarkersSent++;
1907
cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
1914
* Send the contents of cl->updateBuf. Returns 1 if successful, -1 if
1915
* not (errno should be set).
1919
rfbSendUpdateBuf(cl)
1925
if (WriteExact(cl, cl->updateBuf, cl->ublen) < 0) {
1926
rfbLogPerror("rfbSendUpdateBuf: write");
1936
* rfbSendSetColourMapEntries sends a SetColourMapEntries message to the
1937
* client, using values from the currently installed colormap.
1941
rfbSendSetColourMapEntries(cl, firstColour, nColours)
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;
1953
scme->type = rfbSetColourMapEntries;
1955
scme->firstColour = Swap16IfLE(firstColour);
1956
scme->nColours = Swap16IfLE(nColours);
1958
len = sz_rfbSetColourMapEntriesMsg;
1960
for (i = 0; i < nColours; i++) {
1961
if(i<(int)cm->count) {
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]);
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]);
1974
len += nColours * 3 * 2;
1976
if (WriteExact(cl, buf, len) < 0) {
1977
rfbLogPerror("rfbSendSetColourMapEntries: write");
1985
* rfbSendBell sends a Bell message to all the clients.
1989
rfbSendBell(rfbScreenInfoPtr rfbScreen)
1991
rfbClientIteratorPtr i;
1995
i = rfbGetClientIterator(rfbScreen);
1996
while((cl=rfbClientIteratorNext(i))) {
1998
if (WriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) {
1999
rfbLogPerror("rfbSendBell: write");
2003
rfbReleaseClientIterator(i);
2008
* rfbSendServerCutText sends a ServerCutText message to all the clients.
2012
rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
2015
rfbServerCutTextMsg sct;
2016
rfbClientIteratorPtr iterator;
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");
2028
if (WriteExact(cl, str, len) < 0) {
2029
rfbLogPerror("rfbSendServerCutText: write");
2033
rfbReleaseClientIterator(iterator);
2036
/*****************************************************************************
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!).
2044
unsigned char ptrAcceleration = 50;
2047
rfbNewUDPConnection(rfbScreen,sock)
2048
rfbScreenInfoPtr rfbScreen;
2051
if (write(sock, &ptrAcceleration, 1) < 0) {
2052
rfbLogPerror("rfbNewUDPConnection: write");
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.
2064
rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen)
2067
rfbClientPtr cl=rfbScreen->udpClient;
2068
rfbClientToServerMsg msg;
2070
if((!cl) || cl->onHold)
2073
if ((n = read(rfbScreen->udpSock, (char *)&msg, sizeof(msg))) <= 0) {
2075
rfbLogPerror("rfbProcessUDPInput: read");
2077
rfbDisconnectUDPSock(rfbScreen);
2084
if (n != sz_rfbKeyEventMsg) {
2085
rfbErr("rfbProcessUDPInput: key event incorrect length\n");
2086
rfbDisconnectUDPSock(rfbScreen);
2089
cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
2092
case rfbPointerEvent:
2093
if (n != sz_rfbPointerEventMsg) {
2094
rfbErr("rfbProcessUDPInput: ptr event incorrect length\n");
2095
rfbDisconnectUDPSock(rfbScreen);
2098
cl->screen->ptrAddEvent(msg.pe.buttonMask,
2099
Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
2103
rfbErr("rfbProcessUDPInput: unknown message type %d\n",
2105
rfbDisconnectUDPSock(rfbScreen);
2110
void rfbSendBackChannel(rfbScreenInfoPtr rfbScreen,char* str,int len)
2113
rfbBackChannelMsg sct;
2114
rfbClientIteratorPtr iterator;
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");
2127
if (WriteExact(cl, str, len) < 0) {
2128
rfbLogPerror("rfbSendBackChannel: write");
2133
rfbReleaseClientIterator(iterator);