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,
31
#include "rfb/rfbregion.h"
39
#define write(sock,buf,len) send(sock,buf,len,0)
45
#ifdef HAVE_SYS_SOCKET_H
46
#include <sys/socket.h>
48
#ifdef HAVE_NETINET_IN_H
49
#include <netinet/in.h>
50
#include <netinet/tcp.h>
51
#include <arpa/inet.h>
57
#define DEBUGPROTO(x) x
62
rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */
64
static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
65
static void rfbProcessClientNormalMessage(rfbClientPtr cl);
67
struct rfbClientIterator {
69
rfbScreenInfoPtr screen;
73
rfbClientListInit(rfbScreenInfoPtr rfbScreen)
75
if(sizeof(rfbBool)!=1) {
77
fprintf(stderr,"rfbBool's size is not 1 (%lu)!\n",(unsigned long)sizeof(rfbBool));
78
/* we cannot continue, because rfbBool is supposed to be char everywhere */
81
rfbScreen->rfbClientHead = NULL;
85
rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
87
rfbClientIteratorPtr i =
88
(rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
90
i->screen = rfbScreen;
95
rfbClientIteratorHead(rfbClientIteratorPtr i)
97
LOCK(rfbClientListMutex);
98
i->next = i->screen->rfbClientHead;
99
UNLOCK(rfbClientListMutex);
104
rfbClientIteratorNext(rfbClientIteratorPtr i)
107
LOCK(rfbClientListMutex);
108
i->next = i->screen->rfbClientHead;
109
UNLOCK(rfbClientListMutex);
111
i->next = i->next->next;
118
rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
124
* rfbNewClientConnection is called from sockets.c when a new connection
129
rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,
134
cl = rfbNewClient(rfbScreen,sock);
139
* rfbNewClient is called when a new connection has been made by whatever
144
rfbNewClient(rfbScreenInfoPtr rfbScreen,
147
rfbProtocolVersionMsg pv;
148
rfbClientIteratorPtr iterator;
150
struct sockaddr_storage addr;
151
socklen_t addrlen = sizeof(addr);
153
char host[NI_MAXHOST];
154
const char *prt = "unknown";
156
cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
158
cl->screen = rfbScreen;
160
cl->viewOnly = FALSE;
167
getpeername(sock, (struct sockaddr *)&addr, &addrlen);
169
getnameinfo((struct sockaddr *)&addr,
175
cl->host = strdup(host);
177
if (addr.ss_family == AF_INET)
179
else if (addr.ss_family == AF_INET6)
182
rfbLog("[%s] Got connection from client %s\n", prt, cl->host);
184
rfbLog(" other clients:\n");
185
iterator = rfbGetClientIterator(rfbScreen);
186
while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
187
rfbLog(" %s\n",cl_->host);
189
rfbReleaseClientIterator(iterator);
192
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
193
rfbLogPerror("fcntl failed");
199
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
200
(char *)&one, sizeof(one)) < 0) {
201
rfbLogPerror("setsockopt failed");
206
FD_SET(sock,&(rfbScreen->allFds));
207
rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
209
cl->state = RFB_PROTOCOL_VERSION;
211
cl->readyForSetColourMapEntries = FALSE;
212
cl->useCopyRect = FALSE;
213
cl->preferredEncoding = rfbEncodingRaw;
214
cl->correMaxWidth = 48;
215
cl->correMaxHeight = 48;
216
#ifdef VINO_HAVE_ZLIB
220
cl->copyRegion = sraRgnCreate();
225
sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
227
cl->requestedRegion = sraRgnCreate();
229
cl->format = cl->screen->rfbServerFormat;
230
cl->translateFn = rfbTranslateNone;
231
cl->translateLookupTable = NULL;
233
LOCK(rfbClientListMutex);
235
cl->next = rfbScreen->rfbClientHead;
237
if (rfbScreen->rfbClientHead)
238
rfbScreen->rfbClientHead->prev = cl;
240
rfbScreen->rfbClientHead = cl;
241
UNLOCK(rfbClientListMutex);
243
#ifdef VINO_HAVE_JPEG
244
cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
245
cl->tightQualityLevel = -1;
246
for (i = 0; i < 4; i++)
247
cl->zsActive[i] = FALSE;
250
cl->enableCursorUpdates = FALSE;
251
cl->useRichCursorEncoding = FALSE;
252
cl->enableLastRectEncoding = FALSE;
253
cl->useNewFBSize = FALSE;
255
#ifdef VINO_HAVE_ZLIB
256
cl->compStreamInited = FALSE;
257
cl->compStream.total_in = 0;
258
cl->compStream.total_out = 0;
259
cl->compStream.zalloc = Z_NULL;
260
cl->compStream.zfree = Z_NULL;
261
cl->compStream.opaque = Z_NULL;
263
cl->zlibCompressLevel = 5;
266
sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion,
267
rfbProtocolMinorVersion7);
269
if (WriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
270
rfbLogPerror("rfbNewClient: write");
272
rfbClientConnectionGone(cl);
277
cl->clientData = NULL;
278
cl->clientGoneHook = NULL;
280
if (cl->screen->newClientHook) {
281
switch (cl->screen->newClientHook(cl)) {
282
case RFB_CLIENT_ON_HOLD:
285
case RFB_CLIENT_ACCEPT:
287
case RFB_CLIENT_REFUSE:
289
rfbClientConnectionGone(cl);
299
* rfbClientConnectionGone is called from sockets.c just after a connection
304
rfbClientConnectionGone(rfbClientPtr cl)
308
LOCK(rfbClientListMutex);
311
cl->prev->next = cl->next;
313
cl->screen->rfbClientHead = cl->next;
315
cl->next->prev = cl->prev;
320
#ifdef VINO_HAVE_ZLIB
325
FD_CLR(cl->sock,&(cl->screen->allFds));
327
if (cl->clientGoneHook)
328
cl->clientGoneHook(cl);
330
rfbLog("Client %s gone\n",cl->host);
333
#ifdef VINO_HAVE_ZLIB
334
/* Release the compression state structures if any. */
335
if ( cl->compStreamInited ) {
336
deflateEnd( &(cl->compStream) );
339
#ifdef VINO_HAVE_JPEG
340
for (i = 0; i < 4; i++) {
342
deflateEnd(&cl->zsStruct[i]);
347
if (pointerClient == cl)
348
pointerClient = NULL;
350
sraRgnDestroy(cl->modifiedRegion);
351
sraRgnDestroy(cl->requestedRegion);
352
sraRgnDestroy(cl->copyRegion);
354
UNLOCK(rfbClientListMutex);
356
if (cl->translateLookupTable) free(cl->translateLookupTable);
365
* rfbProcessClientMessage is called when there is data to read from a client.
369
rfbProcessClientMessage(rfbClientPtr cl)
372
case RFB_PROTOCOL_VERSION:
373
rfbProcessClientProtocolVersion(cl);
375
case RFB_SECURITY_TYPE:
376
rfbAuthProcessSecurityTypeMessage(cl);
378
#ifdef VINO_HAVE_GNUTLS
379
case RFB_TLS_HANDSHAKE:
380
rfbAuthProcessTLSHandshake(cl);
384
rfbAuthProcessAuthTypeMessage(cl);
386
case RFB_AUTHENTICATION:
387
rfbAuthProcessClientMessage(cl);
389
case RFB_AUTH_DEFERRED:
390
rfbLog("Authentication deferred - ignoring client message\n");
392
case RFB_INITIALISATION:
393
rfbProcessClientInitMessage(cl);
396
rfbProcessClientNormalMessage(cl);
403
* rfbProcessClientProtocolVersion is called when the client sends its
408
rfbProcessClientProtocolVersion(rfbClientPtr cl)
410
rfbProtocolVersionMsg pv;
411
int n, major_, minor_;
413
if ((n = ReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
415
rfbLog("rfbProcessClientProtocolVersion: client gone\n");
417
rfbLogPerror("rfbProcessClientProtocolVersion: read");
422
pv[sz_rfbProtocolVersionMsg] = 0;
423
if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
425
if(sscanf(pv,"RFB %03d.%03d %1023s\n",&major_,&minor_,name) != 3) {
426
rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client\n");
431
cl->host=strdup(name);
433
rfbLog("Client Protocol Version %d.%d\n", major_, minor_);
435
if (major_ != rfbProtocolMajorVersion) {
436
rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d",
437
rfbProtocolMajorVersion, rfbProtocolMinorVersion7,
443
if (minor_ != rfbProtocolMinorVersion3 &&
444
minor_ != rfbProtocolMinorVersion7 &&
445
minor_ != rfbProtocolMinorVersion8) {
446
/* Minor version mismatch - warn but try to continue */
447
rfbLog("Ignoring minor version mismatch\n");
450
if (minor_ >= rfbProtocolMinorVersion8)
451
cl->minorVersion = rfbProtocolMinorVersion8;
452
else if (minor_ == rfbProtocolMinorVersion7)
453
cl->minorVersion = rfbProtocolMinorVersion7;
455
cl->minorVersion = rfbProtocolMinorVersion3;
457
rfbAuthNewClient(cl);
462
* rfbClientConnFailed is called when a client connection has failed either
463
* because it talks the wrong protocol or it has failed authentication.
467
rfbClientConnFailed(rfbClientPtr cl,
471
int len = strlen(reason);
473
rfbLog("rfbClientConnFailed(\"%s\")\n", reason);
475
buf = (char *)malloc(8 + len);
476
((uint32_t *)buf)[0] = 0;
477
((uint32_t *)buf)[1] = Swap32IfLE(len);
478
memcpy(buf + 8, reason, len);
480
if (WriteExact(cl, buf, 8 + len) < 0)
481
rfbLogPerror("rfbClientConnFailed: write");
489
* rfbProcessClientInitMessage is called when the client sends its
490
* initialisation message.
494
rfbProcessClientInitMessage(rfbClientPtr cl)
498
rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
500
rfbClientIteratorPtr iterator;
501
rfbClientPtr otherCl;
503
if ((n = ReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
505
rfbLog("rfbProcessClientInitMessage: client gone\n");
507
rfbLogPerror("rfbProcessClientInitMessage: read");
512
memset(buf,0,sizeof(buf));
514
si->framebufferWidth = Swap16IfLE(cl->screen->width);
515
si->framebufferHeight = Swap16IfLE(cl->screen->height);
516
si->format = cl->screen->rfbServerFormat;
517
si->format.redMax = Swap16IfLE(si->format.redMax);
518
si->format.greenMax = Swap16IfLE(si->format.greenMax);
519
si->format.blueMax = Swap16IfLE(si->format.blueMax);
521
strncpy(buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127);
522
len = strlen(buf + sz_rfbServerInitMsg);
523
si->nameLength = Swap32IfLE(len);
525
if (WriteExact(cl, buf, sz_rfbServerInitMsg + len) < 0) {
526
rfbLogPerror("rfbProcessClientInitMessage: write");
531
cl->state = RFB_NORMAL;
533
if (cl->screen->rfbNeverShared || (!cl->screen->rfbAlwaysShared && !ci.shared)) {
535
if (cl->screen->rfbDontDisconnect) {
536
iterator = rfbGetClientIterator(cl->screen);
537
while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
538
if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
539
rfbLog("-dontdisconnect: Not shared & existing client\n");
540
rfbLog(" refusing new client %s\n", cl->host);
542
rfbReleaseClientIterator(iterator);
546
rfbReleaseClientIterator(iterator);
548
iterator = rfbGetClientIterator(cl->screen);
549
while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
550
if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
551
rfbLog("Not shared - closing connection to client %s\n",
553
rfbCloseClient(otherCl);
556
rfbReleaseClientIterator(iterator);
563
* rfbProcessClientNormalMessage is called when the client has sent a normal
568
rfbProcessClientNormalMessage(rfbClientPtr cl)
571
rfbClientToServerMsg msg;
574
if ((n = ReadExact(cl, (char *)&msg, 1)) <= 0) {
576
rfbLogPerror("rfbProcessClientNormalMessage: read");
583
case rfbSetPixelFormat:
585
if ((n = ReadExact(cl, ((char *)&msg) + 1,
586
sz_rfbSetPixelFormatMsg - 1)) <= 0) {
588
rfbLogPerror("rfbProcessClientNormalMessage: read");
593
cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
594
cl->format.depth = msg.spf.format.depth;
595
cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
596
cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
597
cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
598
cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
599
cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
600
cl->format.redShift = msg.spf.format.redShift;
601
cl->format.greenShift = msg.spf.format.greenShift;
602
cl->format.blueShift = msg.spf.format.blueShift;
604
cl->readyForSetColourMapEntries = TRUE;
606
rfbSetTranslateFunction(cl);
611
case rfbFixColourMapEntries:
612
if ((n = ReadExact(cl, ((char *)&msg) + 1,
613
sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
615
rfbLogPerror("rfbProcessClientNormalMessage: read");
619
rfbLog("rfbProcessClientNormalMessage: %s",
620
"FixColourMapEntries unsupported\n");
625
case rfbSetEncodings:
629
rfbBool enableCursorShapeUpdates, enableCursorPosUpdates;
630
rfbBool useRichCursorEncoding;
632
if ((n = ReadExact(cl, ((char *)&msg) + 1,
633
sz_rfbSetEncodingsMsg - 1)) <= 0) {
635
rfbLogPerror("rfbProcessClientNormalMessage: read");
640
msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
642
enableCursorShapeUpdates = FALSE;
643
enableCursorPosUpdates = FALSE;
644
useRichCursorEncoding = FALSE;
646
cl->preferredEncoding = -1;
647
cl->useCopyRect = FALSE;
648
cl->enableLastRectEncoding = FALSE;
649
cl->useNewFBSize = FALSE;
650
#ifdef VINO_HAVE_JPEG
651
cl->tightQualityLevel = -1;
654
for (i = 0; i < msg.se.nEncodings; i++) {
655
if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
657
rfbLogPerror("rfbProcessClientNormalMessage: read");
661
enc = Swap32IfLE(enc);
665
case rfbEncodingCopyRect:
666
cl->useCopyRect = TRUE;
670
case rfbEncodingCoRRE:
671
case rfbEncodingHextile:
672
#ifdef VINO_HAVE_ZLIB
673
case rfbEncodingZlib:
674
case rfbEncodingZRLE:
675
#ifdef VINO_HAVE_JPEG
676
case rfbEncodingTight:
679
/* The first supported encoding is the 'preferred' encoding */
680
if (cl->preferredEncoding == -1)
681
cl->preferredEncoding = enc;
685
case rfbEncodingXCursor:
686
enableCursorShapeUpdates = TRUE;
688
case rfbEncodingRichCursor:
689
enableCursorShapeUpdates = TRUE;
690
useRichCursorEncoding = TRUE;
692
case rfbEncodingPointerPos:
693
enableCursorPosUpdates = TRUE;
695
case rfbEncodingLastRect:
696
if (!cl->enableLastRectEncoding) {
697
rfbLog("Enabling LastRect protocol extension for client "
699
cl->enableLastRectEncoding = TRUE;
702
case rfbEncodingNewFBSize:
703
if (!cl->useNewFBSize) {
704
rfbLog("Enabling NewFBSize protocol extension for client "
706
cl->useNewFBSize = TRUE;
710
#ifdef VINO_HAVE_ZLIB
711
if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
712
enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
713
cl->zlibCompressLevel = enc & 0x0F;
714
#ifdef VINO_HAVE_JPEG
715
cl->tightCompressLevel = enc & 0x0F;
716
rfbLog("Using compression level %d for client %s\n",
717
cl->tightCompressLevel, cl->host);
718
} else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 &&
719
enc <= (uint32_t)rfbEncodingQualityLevel9 ) {
720
cl->tightQualityLevel = enc & 0x0F;
721
rfbLog("Using image quality level %d for client %s\n",
722
cl->tightQualityLevel, cl->host);
726
rfbLog("rfbProcessClientNormalMessage: ignoring unknown "
727
"encoding type %d\n", (int)enc);
731
if (cl->preferredEncoding == -1) {
732
cl->preferredEncoding = rfbEncodingRaw;
735
if (enableCursorPosUpdates && enableCursorShapeUpdates) {
736
rfbLog("Enabling cursor position and shape (%s encoding) updates for client %s\n",
737
useRichCursorEncoding ? "rich" : "X", cl->host);
738
cl->enableCursorUpdates = TRUE;
739
cl->useRichCursorEncoding = useRichCursorEncoding;
741
cl->enableCursorUpdates = FALSE;
742
cl->useRichCursorEncoding = FALSE;
749
case rfbFramebufferUpdateRequest:
751
sraRegionPtr tmpRegion;
753
if ((n = ReadExact(cl, ((char *)&msg) + 1,
754
sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
756
rfbLogPerror("rfbProcessClientNormalMessage: read");
762
sraRgnCreateRect(Swap16IfLE(msg.fur.x),
763
Swap16IfLE(msg.fur.y),
764
Swap16IfLE(msg.fur.x)+Swap16IfLE(msg.fur.w),
765
Swap16IfLE(msg.fur.y)+Swap16IfLE(msg.fur.h));
767
LOCK(cl->updateMutex);
768
sraRgnOr(cl->requestedRegion,tmpRegion);
770
if (!cl->readyForSetColourMapEntries) {
771
/* client hasn't sent a SetPixelFormat so is using server's */
772
cl->readyForSetColourMapEntries = TRUE;
773
if (!cl->format.trueColour) {
774
if (!rfbSetClientColourMap(cl, 0, 0)) {
775
sraRgnDestroy(tmpRegion);
776
UNLOCK(cl->updateMutex);
782
if (!msg.fur.incremental) {
783
sraRgnOr(cl->modifiedRegion,tmpRegion);
784
sraRgnSubtract(cl->copyRegion,tmpRegion);
786
UNLOCK(cl->updateMutex);
788
sraRgnDestroy(tmpRegion);
795
cl->rfbKeyEventsRcvd++;
797
if ((n = ReadExact(cl, ((char *)&msg) + 1,
798
sz_rfbKeyEventMsg - 1)) <= 0) {
800
rfbLogPerror("rfbProcessClientNormalMessage: read");
805
if(!cl->viewOnly && cl->screen->kbdAddEvent) {
806
cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
812
case rfbPointerEvent:
814
cl->rfbPointerEventsRcvd++;
816
if ((n = ReadExact(cl, ((char *)&msg) + 1,
817
sz_rfbPointerEventMsg - 1)) <= 0) {
819
rfbLogPerror("rfbProcessClientNormalMessage: read");
824
if (pointerClient && (pointerClient != cl))
827
if (msg.pe.buttonMask == 0)
828
pointerClient = NULL;
833
cl->screen->ptrAddEvent(msg.pe.buttonMask,
834
Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
840
case rfbClientCutText:
842
if ((n = ReadExact(cl, ((char *)&msg) + 1,
843
sz_rfbClientCutTextMsg - 1)) <= 0) {
845
rfbLogPerror("rfbProcessClientNormalMessage: read");
850
msg.cct.length = Swap32IfLE(msg.cct.length);
852
str = (char *)malloc(msg.cct.length);
854
if ((n = ReadExact(cl, str, msg.cct.length)) <= 0) {
856
rfbLogPerror("rfbProcessClientNormalMessage: read");
863
if (cl->screen->setXCutText)
864
cl->screen->setXCutText(str, msg.cct.length, cl);
873
rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
875
rfbLog(" ... closing connection\n");
884
* rfbSendFramebufferUpdate - send the currently pending framebuffer update to
886
* givenUpdateRegion is not changed.
890
rfbSendFramebufferUpdate(rfbClientPtr cl,
891
sraRegionPtr givenUpdateRegion)
893
sraRectangleIterator* i=NULL;
895
int nUpdateRegionRects;
896
rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf;
897
sraRegionPtr updateRegion, updateCopyRegion, tmpRegion, cursorRegion;
898
sraRect cursorBounds = { 0, 0, 0, 0 };
900
rfbBool sendCursorShape = FALSE;
901
rfbBool sendCursorPos = FALSE;
902
rfbBool cursorIsDrawn = FALSE;
905
* If framebuffer size was changed and the client supports NewFBSize
906
* encoding, just send NewFBSize marker and return.
909
if (cl->useNewFBSize && cl->newFBSizePending) {
910
LOCK(cl->updateMutex);
911
cl->newFBSizePending = FALSE;
912
UNLOCK(cl->updateMutex);
913
cl->rfbFramebufferUpdateMessagesSent++;
914
fu->type = rfbFramebufferUpdate;
915
fu->nRects = Swap16IfLE(1);
916
cl->ublen = sz_rfbFramebufferUpdateMsg;
917
if (!rfbSendNewFBSize(cl, cl->screen->width, cl->screen->height)) {
920
return rfbSendUpdateBuf(cl);
923
LOCK(cl->updateMutex);
926
* The modifiedRegion may overlap the destination copyRegion. We remove
927
* any overlapping bits from the copyRegion (since they'd only be
928
* overwritten anyway).
931
sraRgnSubtract(cl->copyRegion,cl->modifiedRegion);
933
updateRegion = sraRgnCreateRgn(givenUpdateRegion);
934
sraRgnOr(updateRegion,cl->copyRegion);
937
* If the client doesn't support cursor updates, we want to draw
938
* the cursor locally, send the update and then undraw it.
939
* We only want to do this if the cursor has moved/changed or
940
* if it is contained in updateRegion
942
* We also want to send an update for the region where the cursor
943
* was last drawn, again only if the cursor has moved/changed.
946
LOCK(cl->screen->cursorMutex);
949
if (cl->enableCursorUpdates) {
950
sendCursorShape = cl->cursorWasChanged;
951
sendCursorPos = cl->cursorWasMoved;
953
sraRegionPtr lastDrawnCursorRegion;
955
if (rfbGetCursorBounds(cl->screen, &cursorBounds)) {
956
cursorRegion = sraRgnCreateRect(cursorBounds.x1, cursorBounds.y1,
957
cursorBounds.x2, cursorBounds.y2);
960
lastDrawnCursorRegion = sraRgnCreateRect(cl->lastDrawnCursorBounds.x1,
961
cl->lastDrawnCursorBounds.y1,
962
cl->lastDrawnCursorBounds.x2,
963
cl->lastDrawnCursorBounds.y2);
966
sraRgnOr(cursorRegion, lastDrawnCursorRegion);
967
sraRgnDestroy(lastDrawnCursorRegion);
969
cursorRegion = lastDrawnCursorRegion;
972
if (cl->cursorWasChanged || cl->cursorWasMoved)
973
sraRgnOr(updateRegion, cursorRegion);
977
* The client is interested in the region requestedRegion. The region
978
* which should be updated now is the intersection of requestedRegion
979
* and the union of modifiedRegion and copyRegion. If it's empty then
980
* no update is needed.
983
if (!sraRgnAnd(updateRegion, cl->requestedRegion) &&
984
!sendCursorShape && !sendCursorPos) {
985
sraRgnDestroy(updateRegion);
987
sraRgnDestroy(cursorRegion);
988
UNLOCK(cl->updateMutex);
989
UNLOCK(cl->cursorMutex);
994
* Put up the cursor if any part of it is in updateRegion.
998
tmpRegion = sraRgnCreateRgn(cursorRegion);
1000
if (sraRgnAnd(tmpRegion, updateRegion)) {
1001
rfbDrawCursor(cl->screen, &cursorBounds);
1002
cursorIsDrawn = TRUE;
1004
cl->cursorWasMoved = FALSE;
1005
cl->cursorWasChanged = FALSE;
1006
cl->lastDrawnCursorBounds = cursorBounds;
1008
sraRgnOr(cl->modifiedRegion, cursorRegion);
1010
sraRgnOr(updateRegion, cursorRegion);
1011
sraRgnAnd(updateRegion, cl->requestedRegion);
1014
sraRgnDestroy(tmpRegion);
1015
sraRgnDestroy(cursorRegion);
1019
* We assume that the client doesn't have any pixel data outside the
1020
* requestedRegion. In other words, both the source and destination of a
1021
* copy must lie within requestedRegion. So the region we can send as a
1022
* copy is the intersection of the copyRegion with both the requestedRegion
1023
* and the requestedRegion translated by the amount of the copy. We set
1024
* updateCopyRegion to this.
1027
updateCopyRegion = sraRgnCreateRgn(cl->copyRegion);
1028
sraRgnAnd(updateCopyRegion,cl->requestedRegion);
1029
tmpRegion = sraRgnCreateRgn(cl->requestedRegion);
1030
sraRgnOffset(tmpRegion,cl->copyDX,cl->copyDY);
1031
sraRgnAnd(updateCopyRegion,tmpRegion);
1032
sraRgnDestroy(tmpRegion);
1037
* Next we remove updateCopyRegion from updateRegion so that updateRegion
1038
* is the part of this update which is sent as ordinary pixel data (i.e not
1042
sraRgnSubtract(updateRegion,updateCopyRegion);
1045
* Finally we leave modifiedRegion to be the remainder (if any) of parts of
1046
* the screen which are modified but outside the requestedRegion. We also
1047
* empty both the requestedRegion and the copyRegion - note that we never
1048
* carry over a copyRegion for a future update.
1051
sraRgnOr(cl->modifiedRegion,cl->copyRegion);
1052
sraRgnSubtract(cl->modifiedRegion,updateRegion);
1053
sraRgnSubtract(cl->modifiedRegion,updateCopyRegion);
1055
sraRgnMakeEmpty(cl->requestedRegion);
1056
sraRgnMakeEmpty(cl->copyRegion);
1060
UNLOCK(cl->updateMutex);
1063
* Now send the update.
1066
cl->rfbFramebufferUpdateMessagesSent++;
1068
if (cl->preferredEncoding == rfbEncodingCoRRE) {
1069
nUpdateRegionRects = 0;
1071
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1074
int w = rect.x2 - x;
1075
int h = rect.y2 - y;
1076
nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1)
1077
* ((h-1) / cl->correMaxHeight + 1));
1079
sraRgnReleaseIterator(i);
1080
#ifdef VINO_HAVE_ZLIB
1081
} else if (cl->preferredEncoding == rfbEncodingZlib) {
1082
nUpdateRegionRects = 0;
1084
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1087
int w = rect.x2 - x;
1088
int h = rect.y2 - y;
1089
nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1);
1091
#ifdef VINO_HAVE_JPEG
1092
} else if (cl->preferredEncoding == rfbEncodingTight) {
1093
nUpdateRegionRects = 0;
1095
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1098
int w = rect.x2 - x;
1099
int h = rect.y2 - y;
1100
int n = rfbNumCodedRectsTight(cl, x, y, w, h);
1102
nUpdateRegionRects = 0xFFFF;
1105
nUpdateRegionRects += n;
1107
sraRgnReleaseIterator(i);
1111
nUpdateRegionRects = sraRgnCountRects(updateRegion);
1114
fu->type = rfbFramebufferUpdate;
1115
if (nUpdateRegionRects != 0xFFFF) {
1116
if(cl->screen->maxRectsPerUpdate>0
1117
/* CoRRE splits the screen into smaller squares */
1118
&& cl->preferredEncoding != rfbEncodingCoRRE
1119
#ifdef VINO_HAVE_ZLIB
1120
/* Zlib encoding splits rectangles up into smaller chunks */
1121
&& cl->preferredEncoding != rfbEncodingZlib
1122
#ifdef VINO_HAVE_JPEG
1123
/* Tight encoding counts the rectangles differently */
1124
&& cl->preferredEncoding != rfbEncodingTight
1126
#endif /* VINO_HAVE_ZLIB */
1127
&& nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
1128
sraRegion* newUpdateRegion = sraRgnBBox(updateRegion);
1129
sraRgnDestroy(updateRegion);
1130
updateRegion = newUpdateRegion;
1131
nUpdateRegionRects = sraRgnCountRects(updateRegion);
1133
fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
1134
nUpdateRegionRects +
1135
!!sendCursorShape + !!sendCursorPos));
1137
fu->nRects = 0xFFFF;
1139
cl->ublen = sz_rfbFramebufferUpdateMsg;
1141
UNLOCK(cl->cursorMutex);
1143
if (sendCursorShape) {
1144
cl->cursorWasChanged = FALSE;
1145
if (!rfbSendCursorShape(cl))
1149
if (sendCursorPos) {
1150
cl->cursorWasMoved = FALSE;
1151
if (!rfbSendCursorPos(cl))
1155
if (!sraRgnEmpty(updateCopyRegion)) {
1156
if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy))
1160
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
1163
int w = rect.x2 - x;
1164
int h = rect.y2 - y;
1166
cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader
1167
+ w * (cl->format.bitsPerPixel / 8) * h);
1169
/* Validate the rectangle given by the update packet. */
1170
if (w + x > cl->screen->width || h + y > cl->screen->height)
1173
switch (cl->preferredEncoding) {
1174
case rfbEncodingRaw:
1175
if (!rfbSendRectEncodingRaw(cl, x, y, w, h))
1178
case rfbEncodingRRE:
1179
if (!rfbSendRectEncodingRRE(cl, x, y, w, h))
1182
case rfbEncodingCoRRE:
1183
if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h))
1186
case rfbEncodingHextile:
1187
if (!rfbSendRectEncodingHextile(cl, x, y, w, h))
1190
#ifdef VINO_HAVE_ZLIB
1191
case rfbEncodingZlib:
1192
if (!rfbSendRectEncodingZlib(cl, x, y, w, h))
1195
#ifdef VINO_HAVE_JPEG
1196
case rfbEncodingTight:
1197
if (!rfbSendRectEncodingTight(cl, x, y, w, h))
1202
#ifdef VINO_HAVE_ZLIB
1203
case rfbEncodingZRLE:
1204
if (!rfbSendRectEncodingZRLE(cl, x, y, w, h))
1212
rfbUndrawCursor(cl->screen, &cursorBounds);
1214
if ( nUpdateRegionRects == 0xFFFF &&
1215
!rfbSendLastRectMarker(cl) )
1218
if (!rfbSendUpdateBuf(cl))
1221
sraRgnReleaseIterator(i);
1222
sraRgnDestroy(updateCopyRegion);
1223
sraRgnDestroy(updateRegion);
1229
rfbUndrawCursor(cl->screen, &cursorBounds);
1231
sraRgnReleaseIterator(i);
1233
sraRgnDestroy(updateCopyRegion);
1234
sraRgnDestroy(updateRegion);
1241
* Send the copy region as a string of CopyRect encoded rectangles.
1242
* The only slightly tricky thing is that we should send the messages in
1243
* the correct order so that an earlier CopyRect will not corrupt the source
1248
rfbSendCopyRegion(rfbClientPtr cl,
1254
rfbFramebufferUpdateRectHeader rect;
1256
sraRectangleIterator* i;
1259
/* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */
1260
i = sraRgnGetReverseIterator(reg,dx>0,dy>0);
1262
while(sraRgnIteratorNext(i,&rect1)) {
1268
rect.r.x = Swap16IfLE(x);
1269
rect.r.y = Swap16IfLE(y);
1270
rect.r.w = Swap16IfLE(w);
1271
rect.r.h = Swap16IfLE(h);
1272
rect.encoding = Swap32IfLE(rfbEncodingCopyRect);
1274
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1275
sz_rfbFramebufferUpdateRectHeader);
1276
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1278
cr.srcX = Swap16IfLE(x - dx);
1279
cr.srcY = Swap16IfLE(y - dy);
1281
memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect);
1282
cl->ublen += sz_rfbCopyRect;
1284
cl->rfbRectanglesSent[rfbEncodingCopyRect]++;
1285
cl->rfbBytesSent[rfbEncodingCopyRect]
1286
+= sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect;
1294
* Send a given rectangle in raw encoding (rfbEncodingRaw).
1298
rfbSendRectEncodingRaw(rfbClientPtr cl,
1304
rfbFramebufferUpdateRectHeader rect;
1306
int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
1307
char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
1308
+ (x * (cl->screen->bitsPerPixel / 8)));
1310
/* Flush the buffer to guarantee correct alignment for translateFn(). */
1311
if (cl->ublen > 0) {
1312
if (!rfbSendUpdateBuf(cl))
1316
rect.r.x = Swap16IfLE(x);
1317
rect.r.y = Swap16IfLE(y);
1318
rect.r.w = Swap16IfLE(w);
1319
rect.r.h = Swap16IfLE(h);
1320
rect.encoding = Swap32IfLE(rfbEncodingRaw);
1322
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
1323
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1325
cl->rfbRectanglesSent[rfbEncodingRaw]++;
1326
cl->rfbBytesSent[rfbEncodingRaw]
1327
+= sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h;
1329
nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
1335
(*cl->translateFn)(cl->translateLookupTable,
1336
&(cl->screen->rfbServerFormat),
1337
&cl->format, fbptr, &cl->updateBuf[cl->ublen],
1338
cl->screen->paddedWidthInBytes, w, nlines);
1340
cl->ublen += nlines * bytesPerLine;
1343
if (h == 0) /* rect fitted in buffer, do next one */
1346
/* buffer full - flush partial rect and do another nlines */
1348
if (!rfbSendUpdateBuf(cl))
1351
fbptr += (cl->screen->paddedWidthInBytes * nlines);
1353
nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
1355
rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d "
1356
"bytes per line\n", bytesPerLine);
1366
* Send an empty rectangle with encoding field set to value of
1367
* rfbEncodingLastRect to notify client that this is the last
1368
* rectangle in framebuffer update ("LastRect" extension of RFB
1373
rfbSendLastRectMarker(rfbClientPtr cl)
1375
rfbFramebufferUpdateRectHeader rect;
1377
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
1378
if (!rfbSendUpdateBuf(cl))
1382
rect.encoding = Swap32IfLE(rfbEncodingLastRect);
1388
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
1389
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1391
cl->rfbLastRectMarkersSent++;
1392
cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
1399
* Send NewFBSize pseudo-rectangle. This tells the client to change
1400
* its framebuffer size.
1404
rfbSendNewFBSize(rfbClientPtr cl,
1408
rfbFramebufferUpdateRectHeader rect;
1410
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
1411
if (!rfbSendUpdateBuf(cl))
1415
rect.encoding = Swap32IfLE(rfbEncodingNewFBSize);
1418
rect.r.w = Swap16IfLE(w);
1419
rect.r.h = Swap16IfLE(h);
1421
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1422
sz_rfbFramebufferUpdateRectHeader);
1423
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1425
cl->rfbLastRectMarkersSent++;
1426
cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
1433
* Send the contents of cl->updateBuf. Returns 1 if successful, -1 if
1434
* not (errno should be set).
1438
rfbSendUpdateBuf(rfbClientPtr cl)
1443
if (WriteExact(cl, cl->updateBuf, cl->ublen) < 0) {
1444
rfbLogPerror("rfbSendUpdateBuf: write");
1454
* rfbSendSetColourMapEntries sends a SetColourMapEntries message to the
1455
* client, using values from the currently installed colormap.
1459
rfbSendSetColourMapEntries(rfbClientPtr cl,
1463
char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
1464
rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
1465
uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]);
1466
rfbColourMap* cm = &cl->screen->colourMap;
1470
scme->type = rfbSetColourMapEntries;
1472
scme->firstColour = Swap16IfLE(firstColour);
1473
scme->nColours = Swap16IfLE(nColours);
1475
len = sz_rfbSetColourMapEntriesMsg;
1477
for (i = 0; i < nColours; i++) {
1478
if(i<(int)cm->count) {
1480
rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]);
1481
rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]);
1482
rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]);
1484
rgb[i*3] = Swap16IfLE(cm->data.bytes[i*3]);
1485
rgb[i*3+1] = Swap16IfLE(cm->data.bytes[i*3+1]);
1486
rgb[i*3+2] = Swap16IfLE(cm->data.bytes[i*3+2]);
1491
len += nColours * 3 * 2;
1493
if (WriteExact(cl, buf, len) < 0) {
1494
rfbLogPerror("rfbSendSetColourMapEntries: write");
1502
* rfbSendBell sends a Bell message to all the clients.
1506
rfbSendBell(rfbScreenInfoPtr rfbScreen)
1508
rfbClientIteratorPtr i;
1512
i = rfbGetClientIterator(rfbScreen);
1513
while((cl=rfbClientIteratorNext(i))) {
1515
if (WriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) {
1516
rfbLogPerror("rfbSendBell: write");
1520
rfbReleaseClientIterator(i);
1525
* rfbSendServerCutText sends a ServerCutText message to all the clients.
1529
rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
1532
rfbServerCutTextMsg sct;
1533
rfbClientIteratorPtr iterator;
1535
iterator = rfbGetClientIterator(rfbScreen);
1536
while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
1537
sct.type = rfbServerCutText;
1538
sct.length = Swap32IfLE(len);
1539
if (WriteExact(cl, (char *)&sct,
1540
sz_rfbServerCutTextMsg) < 0) {
1541
rfbLogPerror("rfbSendServerCutText: write");
1545
if (WriteExact(cl, str, len) < 0) {
1546
rfbLogPerror("rfbSendServerCutText: write");
1550
rfbReleaseClientIterator(iterator);