2 * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved.
3 * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
4 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
6 * This is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this software; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23 * rfbproto.c - functions to deal with client side of RFB protocol.
26 #ifdef __STRICT_ANSI__
33 #define strncasecmp _strnicmp
39 #include <rfb/rfbclient.h>
40 #ifdef LIBVNCSERVER_HAVE_LIBZ
47 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
56 * rfbClientLog prints a time-stamped message to the log file (stderr).
59 rfbBool rfbEnableClientLogging=TRUE;
62 rfbDefaultClientLog(const char *format, ...)
68 if(!rfbEnableClientLogging)
71 va_start(args, format);
74 strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock));
77 vfprintf(stderr, format, args);
83 rfbClientLogProc rfbClientLog=rfbDefaultClientLog;
84 rfbClientLogProc rfbClientErr=rfbDefaultClientLog;
88 rfbClientProtocolExtension* rfbClientExtensions = NULL;
90 void rfbClientRegisterExtension(rfbClientProtocolExtension* e)
92 e->next = rfbClientExtensions;
93 rfbClientExtensions = e;
98 void rfbClientSetClientData(rfbClient* client, void* tag, void* data)
100 rfbClientData* clientData = client->clientData;
102 while(clientData && clientData->tag != tag)
103 clientData = clientData->next;
104 if(clientData == NULL) {
105 clientData = calloc(sizeof(rfbClientData), 1);
106 clientData->next = client->clientData;
107 client->clientData = clientData;
108 clientData->tag = tag;
111 clientData->data = data;
114 void* rfbClientGetClientData(rfbClient* client, void* tag)
116 rfbClientData* clientData = client->clientData;
119 if(clientData->tag == tag)
120 return clientData->data;
121 clientData = clientData->next;
129 static void FillRectangle(rfbClient* client, int x, int y, int w, int h, uint32_t colour) {
132 #define FILL_RECT(BPP) \
133 for(j=y*client->width;j<(y+h)*client->width;j+=client->width) \
135 ((uint##BPP##_t*)client->frameBuffer)[j+i]=colour;
137 switch(client->format.bitsPerPixel) {
138 case 8: FILL_RECT(8); break;
139 case 16: FILL_RECT(16); break;
140 case 32: FILL_RECT(32); break;
142 rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
146 static void CopyRectangle(rfbClient* client, uint8_t* buffer, int x, int y, int w, int h) {
149 #define COPY_RECT(BPP) \
151 int rs = w * BPP / 8, rs2 = client->width * BPP / 8; \
152 for (j = ((x * (BPP / 8)) + (y * rs2)); j < (y + h) * rs2; j += rs2) { \
153 memcpy(client->frameBuffer + j, buffer, rs); \
158 switch(client->format.bitsPerPixel) {
159 case 8: COPY_RECT(8); break;
160 case 16: COPY_RECT(16); break;
161 case 32: COPY_RECT(32); break;
163 rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
168 static void CopyRectangleFromRectangle(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) {
171 #define COPY_RECT_FROM_RECT(BPP) \
173 uint##BPP##_t* _buffer=((uint##BPP##_t*)client->frameBuffer)+(src_y-dest_y)*client->width+src_x-dest_x; \
174 if (dest_y < src_y) { \
175 for(j = dest_y*client->width; j < (dest_y+h)*client->width; j += client->width) { \
176 if (dest_x < src_x) { \
177 for(i = dest_x; i < dest_x+w; i++) { \
178 ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
181 for(i = dest_x+w-1; i >= dest_x; i--) { \
182 ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
187 for(j = (dest_y+h-1)*client->width; j >= dest_y*client->width; j-=client->width) { \
188 if (dest_x < src_x) { \
189 for(i = dest_x; i < dest_x+w; i++) { \
190 ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
193 for(i = dest_x+w-1; i >= dest_x; i--) { \
194 ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
201 switch(client->format.bitsPerPixel) {
202 case 8: COPY_RECT_FROM_RECT(8); break;
203 case 16: COPY_RECT_FROM_RECT(16); break;
204 case 32: COPY_RECT_FROM_RECT(32); break;
206 rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
210 static rfbBool HandleRRE8(rfbClient* client, int rx, int ry, int rw, int rh);
211 static rfbBool HandleRRE16(rfbClient* client, int rx, int ry, int rw, int rh);
212 static rfbBool HandleRRE32(rfbClient* client, int rx, int ry, int rw, int rh);
213 static rfbBool HandleCoRRE8(rfbClient* client, int rx, int ry, int rw, int rh);
214 static rfbBool HandleCoRRE16(rfbClient* client, int rx, int ry, int rw, int rh);
215 static rfbBool HandleCoRRE32(rfbClient* client, int rx, int ry, int rw, int rh);
216 static rfbBool HandleHextile8(rfbClient* client, int rx, int ry, int rw, int rh);
217 static rfbBool HandleHextile16(rfbClient* client, int rx, int ry, int rw, int rh);
218 static rfbBool HandleHextile32(rfbClient* client, int rx, int ry, int rw, int rh);
219 static rfbBool HandleUltra8(rfbClient* client, int rx, int ry, int rw, int rh);
220 static rfbBool HandleUltra16(rfbClient* client, int rx, int ry, int rw, int rh);
221 static rfbBool HandleUltra32(rfbClient* client, int rx, int ry, int rw, int rh);
222 static rfbBool HandleUltraZip8(rfbClient* client, int rx, int ry, int rw, int rh);
223 static rfbBool HandleUltraZip16(rfbClient* client, int rx, int ry, int rw, int rh);
224 static rfbBool HandleUltraZip32(rfbClient* client, int rx, int ry, int rw, int rh);
225 #ifdef LIBVNCSERVER_HAVE_LIBZ
226 static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh);
227 static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh);
228 static rfbBool HandleZlib32(rfbClient* client, int rx, int ry, int rw, int rh);
229 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
230 static rfbBool HandleTight8(rfbClient* client, int rx, int ry, int rw, int rh);
231 static rfbBool HandleTight16(rfbClient* client, int rx, int ry, int rw, int rh);
232 static rfbBool HandleTight32(rfbClient* client, int rx, int ry, int rw, int rh);
234 static long ReadCompactLen (rfbClient* client);
236 static void JpegInitSource(j_decompress_ptr cinfo);
237 static boolean JpegFillInputBuffer(j_decompress_ptr cinfo);
238 static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes);
239 static void JpegTermSource(j_decompress_ptr cinfo);
240 static void JpegSetSrcManager(j_decompress_ptr cinfo, uint8_t *compressedData,
243 static rfbBool HandleZRLE8(rfbClient* client, int rx, int ry, int rw, int rh);
244 static rfbBool HandleZRLE15(rfbClient* client, int rx, int ry, int rw, int rh);
245 static rfbBool HandleZRLE16(rfbClient* client, int rx, int ry, int rw, int rh);
246 static rfbBool HandleZRLE24(rfbClient* client, int rx, int ry, int rw, int rh);
247 static rfbBool HandleZRLE24Up(rfbClient* client, int rx, int ry, int rw, int rh);
248 static rfbBool HandleZRLE24Down(rfbClient* client, int rx, int ry, int rw, int rh);
249 static rfbBool HandleZRLE32(rfbClient* client, int rx, int ry, int rw, int rh);
253 * Server Capability Functions
256 SupportsClient2Server(rfbClient* client, int messageType)
258 return (client->supportedMessages.client2server[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE);
262 SupportsServer2Client(rfbClient* client, int messageType)
264 return (client->supportedMessages.server2client[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE);
268 SetClient2Server(rfbClient* client, int messageType)
270 client->supportedMessages.client2server[((messageType & 0xFF)/8)] |= (1<<(messageType % 8));
274 SetServer2Client(rfbClient* client, int messageType)
276 client->supportedMessages.server2client[((messageType & 0xFF)/8)] |= (1<<(messageType % 8));
280 ClearClient2Server(rfbClient* client, int messageType)
282 client->supportedMessages.client2server[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8)));
286 ClearServer2Client(rfbClient* client, int messageType)
288 client->supportedMessages.server2client[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8)));
293 DefaultSupportedMessages(rfbClient* client)
295 memset((char *)&client->supportedMessages,0,sizeof(client->supportedMessages));
297 /* Default client supported messages (universal RFB 3.3 protocol) */
298 SetClient2Server(client, rfbSetPixelFormat);
299 /* SetClient2Server(client, rfbFixColourMapEntries); Not currently supported */
300 SetClient2Server(client, rfbSetEncodings);
301 SetClient2Server(client, rfbFramebufferUpdateRequest);
302 SetClient2Server(client, rfbKeyEvent);
303 SetClient2Server(client, rfbPointerEvent);
304 SetClient2Server(client, rfbClientCutText);
305 /* technically, we only care what we can *send* to the server
306 * but, we set Server2Client Just in case it ever becomes useful
308 SetServer2Client(client, rfbFramebufferUpdate);
309 SetServer2Client(client, rfbSetColourMapEntries);
310 SetServer2Client(client, rfbBell);
311 SetServer2Client(client, rfbServerCutText);
315 DefaultSupportedMessagesUltraVNC(rfbClient* client)
317 DefaultSupportedMessages(client);
318 SetClient2Server(client, rfbFileTransfer);
319 SetClient2Server(client, rfbSetScale);
320 SetClient2Server(client, rfbSetServerInput);
321 SetClient2Server(client, rfbSetSW);
322 SetClient2Server(client, rfbTextChat);
323 SetClient2Server(client, rfbPalmVNCSetScaleFactor);
324 /* technically, we only care what we can *send* to the server */
325 SetServer2Client(client, rfbResizeFrameBuffer);
326 SetServer2Client(client, rfbPalmVNCReSizeFrameBuffer);
327 SetServer2Client(client, rfbFileTransfer);
328 SetServer2Client(client, rfbTextChat);
333 DefaultSupportedMessagesTightVNC(rfbClient* client)
335 DefaultSupportedMessages(client);
336 SetClient2Server(client, rfbFileTransfer);
337 SetClient2Server(client, rfbSetServerInput);
338 SetClient2Server(client, rfbSetSW);
339 /* SetClient2Server(client, rfbTextChat); */
340 /* technically, we only care what we can *send* to the server */
341 SetServer2Client(client, rfbFileTransfer);
342 SetServer2Client(client, rfbTextChat);
346 * ConnectToRFBServer.
350 ConnectToRFBServer(rfbClient* client,const char *hostname, int port)
354 if (client->serverPort==-1) {
355 /* serverHost is a file recorded by vncrec. */
356 const char* magic="vncLog0.0";
358 rfbVNCRec* rec = (rfbVNCRec*)malloc(sizeof(rfbVNCRec));
359 client->vncRec = rec;
361 rec->file = fopen(client->serverHost,"rb");
363 rec->readTimestamp = FALSE;
364 rec->doNotSleep = FALSE;
367 rfbClientLog("Could not open %s.\n",client->serverHost);
370 setbuf(rec->file,NULL);
371 fread(buffer,1,strlen(magic),rec->file);
372 if (strncmp(buffer,magic,strlen(magic))) {
373 rfbClientLog("File %s was not recorded by vncrec.\n",client->serverHost);
381 if (!StringToIPAddr(hostname, &host)) {
382 rfbClientLog("Couldn't convert '%s' to host address\n", hostname);
386 client->sock = ConnectClientToTcpAddr(host, port);
388 if (client->sock < 0) {
389 rfbClientLog("Unable to connect to VNC server\n");
393 return SetNonBlocking(client->sock);
396 extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd);
399 rfbHandleAuthResult(rfbClient* client)
401 uint32_t authResult=0, reasonLen=0;
404 if (!ReadFromRFBServer(client, (char *)&authResult, 4)) return FALSE;
406 authResult = rfbClientSwap32IfLE(authResult);
408 switch (authResult) {
410 rfbClientLog("VNC authentication succeeded\n");
413 case rfbVncAuthFailed:
414 if (client->major==3 && client->minor>7)
416 /* we have an error following */
417 if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
418 reasonLen = rfbClientSwap32IfLE(reasonLen);
419 reason = malloc(reasonLen+1);
420 if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
422 rfbClientLog("VNC connection failed: %s\n",reason);
426 rfbClientLog("VNC authentication failed\n");
428 case rfbVncAuthTooMany:
429 rfbClientLog("VNC authentication failed - too many tries\n");
433 rfbClientLog("Unknown VNC authentication result: %d\n",
440 * InitialiseRFBConnection.
444 InitialiseRFBConnection(rfbClient* client)
446 rfbProtocolVersionMsg pv;
448 uint32_t authScheme, reasonLen;
450 uint8_t challenge[CHALLENGESIZE];
455 /* if the connection is immediately closed, don't report anything, so
456 that pmw's monitor can make test connections */
458 if (client->listenSpecified)
459 errorMessageOnReadFailure = FALSE;
461 if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE;
462 pv[sz_rfbProtocolVersionMsg]=0;
464 errorMessageOnReadFailure = TRUE;
466 pv[sz_rfbProtocolVersionMsg] = 0;
468 if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) {
469 rfbClientLog("Not a valid VNC server (%s)\n",pv);
474 DefaultSupportedMessages(client);
475 client->major = major;
476 client->minor = minor;
478 /* fall back to viewer supported version */
479 if ((major==rfbProtocolMajorVersion) && (minor>rfbProtocolMinorVersion))
480 client->minor = rfbProtocolMinorVersion;
482 /* UltraVNC uses minor codes 4 and 6 for the server */
483 if (major==3 && (minor==4 || minor==6)) {
484 rfbClientLog("UltraVNC server detected, enabling UltraVNC specific messages\n",pv);
485 DefaultSupportedMessagesUltraVNC(client);
488 /* TightVNC uses minor codes 5 for the server */
489 if (major==3 && minor==5) {
490 rfbClientLog("TightVNC server detected, enabling TightVNC specific messages\n",pv);
491 DefaultSupportedMessagesTightVNC(client);
494 /* we do not support > RFB3.8 */
495 if (major==3 && minor>8)
498 rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n",
499 major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion);
501 sprintf(pv,rfbProtocolVersionFormat,client->major,client->minor);
503 if (!WriteToRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE;
506 /* 3.7 and onwards sends a # of security types first */
507 if (client->major==3 && client->minor > 6)
514 if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE;
518 rfbClientLog("List of security types is ZERO, expecting an error to follow\n");
520 /* we have an error following */
521 if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
522 reasonLen = rfbClientSwap32IfLE(reasonLen);
523 reason = malloc(reasonLen+1);
524 if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
526 rfbClientLog("VNC connection failed: %s\n",reason);
531 rfbClientLog("We have %d security types to read\n", count);
532 /* now, we have a list of available security types to read ( uint8_t[] ) */
533 for (loop=0;loop<count;loop++)
535 if (!ReadFromRFBServer(client, (char *)&tAuth, 1)) return FALSE;
536 rfbClientLog("%d) Received security type %d\n", loop, tAuth);
537 if ((flag==0) && ((tAuth==rfbVncAuth) || (tAuth==rfbNoAuth)))
541 rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count);
542 /* send back a single byte indicating which security type to use */
543 if (!WriteToRFBServer(client, (char *)&tAuth, 1)) return FALSE;
550 if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE;
551 authScheme = rfbClientSwap32IfLE(authScheme);
554 rfbClientLog("Selected Security Scheme %d\n", authScheme);
556 switch (authScheme) {
559 if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
560 reasonLen = rfbClientSwap32IfLE(reasonLen);
562 reason = malloc(reasonLen+1);
564 if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
566 rfbClientLog("VNC connection failed: %s\n", reason);
571 rfbClientLog("No authentication needed\n");
573 /* 3.8 and upwards sends a Security Result for rfbNoAuth */
574 if (client->major==3 && client->minor > 7)
575 if (!rfbHandleAuthResult(client)) return FALSE;
580 if (!ReadFromRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
582 if (client->serverPort!=-1) { /* if not playing a vncrec file */
583 if (client->GetPassword)
584 passwd = client->GetPassword(client);
586 if ((!passwd) || (strlen(passwd) == 0)) {
587 rfbClientLog("Reading password failed\n");
590 if (strlen(passwd) > 8) {
594 rfbClientEncryptBytes(challenge, passwd);
596 /* Lose the password from memory */
597 for (i = strlen(passwd); i >= 0; i--) {
602 if (!WriteToRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
605 /* Handle the SecurityResult message */
606 if (!rfbHandleAuthResult(client)) return FALSE;
610 rfbClientLog("Unknown authentication scheme from VNC server: %d\n",
615 ci.shared = (client->appData.shareDesktop ? 1 : 0);
617 if (!WriteToRFBServer(client, (char *)&ci, sz_rfbClientInitMsg)) return FALSE;
619 if (!ReadFromRFBServer(client, (char *)&client->si, sz_rfbServerInitMsg)) return FALSE;
621 client->si.framebufferWidth = rfbClientSwap16IfLE(client->si.framebufferWidth);
622 client->si.framebufferHeight = rfbClientSwap16IfLE(client->si.framebufferHeight);
623 client->si.format.redMax = rfbClientSwap16IfLE(client->si.format.redMax);
624 client->si.format.greenMax = rfbClientSwap16IfLE(client->si.format.greenMax);
625 client->si.format.blueMax = rfbClientSwap16IfLE(client->si.format.blueMax);
626 client->si.nameLength = rfbClientSwap32IfLE(client->si.nameLength);
628 client->desktopName = malloc(client->si.nameLength + 1);
629 if (!client->desktopName) {
630 rfbClientLog("Error allocating memory for desktop name, %lu bytes\n",
631 (unsigned long)client->si.nameLength);
635 if (!ReadFromRFBServer(client, client->desktopName, client->si.nameLength)) return FALSE;
637 client->desktopName[client->si.nameLength] = 0;
639 rfbClientLog("Desktop name \"%s\"\n",client->desktopName);
641 rfbClientLog("Connected to VNC server, using protocol version %d.%d\n",
642 client->major, client->minor);
644 rfbClientLog("VNC server default format:\n");
645 PrintPixelFormat(&client->si.format);
652 * SetFormatAndEncodings.
656 SetFormatAndEncodings(rfbClient* client)
658 rfbSetPixelFormatMsg spf;
659 char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
661 rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf;
662 uint32_t *encs = (uint32_t *)(&buf[sz_rfbSetEncodingsMsg]);
664 rfbBool requestCompressLevel = FALSE;
665 rfbBool requestQualityLevel = FALSE;
666 rfbBool requestLastRectEncoding = FALSE;
667 rfbClientProtocolExtension* e;
669 if (!SupportsClient2Server(client, rfbSetPixelFormat)) return TRUE;
671 spf.type = rfbSetPixelFormat;
672 spf.format = client->format;
673 spf.format.redMax = rfbClientSwap16IfLE(spf.format.redMax);
674 spf.format.greenMax = rfbClientSwap16IfLE(spf.format.greenMax);
675 spf.format.blueMax = rfbClientSwap16IfLE(spf.format.blueMax);
677 if (!WriteToRFBServer(client, (char *)&spf, sz_rfbSetPixelFormatMsg))
681 if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE;
683 se->type = rfbSetEncodings;
686 if (client->appData.encodingsString) {
687 const char *encStr = client->appData.encodingsString;
690 const char *nextEncStr = strchr(encStr, ' ');
692 encStrLen = nextEncStr - encStr;
695 encStrLen = strlen(encStr);
698 if (strncasecmp(encStr,"raw",encStrLen) == 0) {
699 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw);
700 } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
701 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect);
702 #ifdef LIBVNCSERVER_HAVE_LIBZ
703 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
704 } else if (strncasecmp(encStr,"tight",encStrLen) == 0) {
705 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight);
706 requestLastRectEncoding = TRUE;
707 if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
708 requestCompressLevel = TRUE;
709 if (client->appData.enableJPEG)
710 requestQualityLevel = TRUE;
713 } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) {
714 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile);
715 #ifdef LIBVNCSERVER_HAVE_LIBZ
716 } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) {
717 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib);
718 if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
719 requestCompressLevel = TRUE;
720 } else if (strncasecmp(encStr,"zlibhex",encStrLen) == 0) {
721 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlibHex);
722 if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
723 requestCompressLevel = TRUE;
724 } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) {
725 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE);
726 } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) {
727 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE);
728 requestQualityLevel = TRUE;
730 } else if ((strncasecmp(encStr,"ultra",encStrLen) == 0) || (strncasecmp(encStr,"ultrazip",encStrLen) == 0)) {
731 /* There are 2 encodings used in 'ultra' */
732 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra);
733 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip);
734 } else if (strncasecmp(encStr,"corre",encStrLen) == 0) {
735 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE);
736 } else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
737 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE);
739 rfbClientLog("Unknown encoding '%.*s'\n",encStrLen,encStr);
743 } while (encStr && se->nEncodings < MAX_ENCODINGS);
745 if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) {
746 encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel +
747 rfbEncodingCompressLevel0);
750 if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) {
751 if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9)
752 client->appData.qualityLevel = 5;
753 encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel +
754 rfbEncodingQualityLevel0);
758 if (SameMachine(client->sock)) {
760 if (!tunnelSpecified) {
762 rfbClientLog("Same machine: preferring raw encoding\n");
763 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw);
766 rfbClientLog("Tunneling active: preferring tight encoding\n");
771 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect);
772 #ifdef LIBVNCSERVER_HAVE_LIBZ
773 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
774 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight);
775 requestLastRectEncoding = TRUE;
778 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile);
779 #ifdef LIBVNCSERVER_HAVE_LIBZ
780 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib);
781 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE);
782 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE);
784 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra);
785 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip);
786 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE);
787 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE);
789 if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) {
790 encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel +
791 rfbEncodingCompressLevel0);
792 } else /* if (!tunnelSpecified) */ {
793 /* If -tunnel option was provided, we assume that server machine is
794 not in the local network so we use default compression level for
795 tight encoding instead of fast compression. Thus we are
796 requesting level 1 compression only if tunneling is not used. */
797 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCompressLevel1);
800 if (client->appData.enableJPEG) {
801 if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9)
802 client->appData.qualityLevel = 5;
803 encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel +
804 rfbEncodingQualityLevel0);
810 /* Remote Cursor Support (local to viewer) */
811 if (client->appData.useRemoteCursor) {
812 if (se->nEncodings < MAX_ENCODINGS)
813 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingXCursor);
814 if (se->nEncodings < MAX_ENCODINGS)
815 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRichCursor);
816 if (se->nEncodings < MAX_ENCODINGS)
817 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPointerPos);
820 /* Keyboard State Encodings */
821 if (se->nEncodings < MAX_ENCODINGS)
822 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingKeyboardLedState);
824 /* New Frame Buffer Size */
825 if (se->nEncodings < MAX_ENCODINGS && client->canHandleNewFBSize)
826 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingNewFBSize);
829 if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding)
830 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect);
832 /* Server Capabilities */
833 if (se->nEncodings < MAX_ENCODINGS)
834 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedMessages);
835 if (se->nEncodings < MAX_ENCODINGS)
836 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedEncodings);
837 if (se->nEncodings < MAX_ENCODINGS)
838 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingServerIdentity);
841 /* client extensions */
842 for(e = rfbClientExtensions; e; e = e->next)
845 for(enc = e->encodings; *enc; enc++)
846 encs[se->nEncodings++] = rfbClientSwap32IfLE(*enc);
849 len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
851 se->nEncodings = rfbClientSwap16IfLE(se->nEncodings);
853 if (!WriteToRFBServer(client, buf, len)) return FALSE;
860 * SendIncrementalFramebufferUpdateRequest.
864 SendIncrementalFramebufferUpdateRequest(rfbClient* client)
866 return SendFramebufferUpdateRequest(client,
867 client->updateRect.x, client->updateRect.y,
868 client->updateRect.w, client->updateRect.h, TRUE);
873 * SendFramebufferUpdateRequest.
877 SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbBool incremental)
879 rfbFramebufferUpdateRequestMsg fur;
881 if (!SupportsClient2Server(client, rfbFramebufferUpdateRequest)) return TRUE;
883 fur.type = rfbFramebufferUpdateRequest;
884 fur.incremental = incremental ? 1 : 0;
885 fur.x = rfbClientSwap16IfLE(x);
886 fur.y = rfbClientSwap16IfLE(y);
887 fur.w = rfbClientSwap16IfLE(w);
888 fur.h = rfbClientSwap16IfLE(h);
890 if (!WriteToRFBServer(client, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg))
901 SendScaleSetting(rfbClient* client,int scaleSetting)
905 ssm.scale = scaleSetting;
908 /* favor UltraVNC SetScale if both are supported */
909 if (SupportsClient2Server(client, rfbSetScale)) {
910 ssm.type = rfbSetScale;
911 if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
915 if (SupportsClient2Server(client, rfbPalmVNCSetScaleFactor)) {
916 ssm.type = rfbPalmVNCSetScaleFactor;
917 if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
925 * TextChatFunctions (UltraVNC)
926 * Extremely bandwidth friendly method of communicating with a user
927 * (Think HelpDesk type applications)
930 rfbBool TextChatSend(rfbClient* client, char *text)
933 int count = strlen(text);
935 if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
936 chat.type = rfbTextChat;
939 chat.length = (uint32_t)count;
940 chat.length = rfbClientSwap32IfLE(chat.length);
942 if (!WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg))
946 if (!WriteToRFBServer(client, text, count))
952 rfbBool TextChatOpen(rfbClient* client)
956 if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
957 chat.type = rfbTextChat;
960 chat.length = rfbClientSwap32IfLE(rfbTextChatOpen);
961 return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
964 rfbBool TextChatClose(rfbClient* client)
967 if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
968 chat.type = rfbTextChat;
971 chat.length = rfbClientSwap32IfLE(rfbTextChatClose);
972 return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
975 rfbBool TextChatFinish(rfbClient* client)
978 if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
979 chat.type = rfbTextChat;
982 chat.length = rfbClientSwap32IfLE(rfbTextChatFinished);
983 return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
987 * UltraVNC Server Input Disable
988 * Apparently, the remote client can *prevent* the local user from interacting with the display
989 * I would think this is extremely helpful when used in a HelpDesk situation
991 rfbBool PermitServerInput(rfbClient* client, int enabled)
993 rfbSetServerInputMsg msg;
995 if (!SupportsClient2Server(client, rfbSetServerInput)) return TRUE;
996 /* enabled==1, then server input from local keyboard is disabled */
997 msg.type = rfbSetServerInput;
998 msg.status = (enabled ? 1 : 0);
1000 return (WriteToRFBServer(client, (char *)&msg, sz_rfbSetServerInputMsg) ? TRUE : FALSE);
1009 SendPointerEvent(rfbClient* client,int x, int y, int buttonMask)
1011 rfbPointerEventMsg pe;
1013 if (!SupportsClient2Server(client, rfbPointerEvent)) return TRUE;
1015 pe.type = rfbPointerEvent;
1016 pe.buttonMask = buttonMask;
1020 pe.x = rfbClientSwap16IfLE(x);
1021 pe.y = rfbClientSwap16IfLE(y);
1022 return WriteToRFBServer(client, (char *)&pe, sz_rfbPointerEventMsg);
1031 SendKeyEvent(rfbClient* client, uint32_t key, rfbBool down)
1035 if (!SupportsClient2Server(client, rfbKeyEvent)) return TRUE;
1037 ke.type = rfbKeyEvent;
1038 ke.down = down ? 1 : 0;
1039 ke.key = rfbClientSwap32IfLE(key);
1040 return WriteToRFBServer(client, (char *)&ke, sz_rfbKeyEventMsg);
1045 * SendClientCutText.
1049 SendClientCutText(rfbClient* client, char *str, int len)
1051 rfbClientCutTextMsg cct;
1053 if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE;
1055 cct.type = rfbClientCutText;
1056 cct.length = rfbClientSwap32IfLE(len);
1057 return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) &&
1058 WriteToRFBServer(client, str, len));
1064 * HandleRFBServerMessage.
1068 HandleRFBServerMessage(rfbClient* client)
1070 rfbServerToClientMsg msg;
1072 if (client->serverPort==-1)
1073 client->vncRec->readTimestamp = TRUE;
1074 if (!ReadFromRFBServer(client, (char *)&msg, 1))
1079 case rfbSetColourMapEntries:
1086 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1087 sz_rfbSetColourMapEntriesMsg - 1))
1090 msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour);
1091 msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours);
1093 for (i = 0; i < msg.scme.nColours; i++) {
1094 if (!ReadFromRFBServer(client, (char *)rgb, 6))
1096 xc.pixel = msg.scme.firstColour + i;
1097 xc.red = rfbClientSwap16IfLE(rgb[0]);
1098 xc.green = rfbClientSwap16IfLE(rgb[1]);
1099 xc.blue = rfbClientSwap16IfLE(rgb[2]);
1100 xc.flags = DoRed|DoGreen|DoBlue;
1101 XStoreColor(dpy, cmap, &xc);
1108 case rfbFramebufferUpdate:
1110 rfbFramebufferUpdateRectHeader rect;
1115 if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1,
1116 sz_rfbFramebufferUpdateMsg - 1))
1119 msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects);
1121 for (i = 0; i < msg.fu.nRects; i++) {
1122 if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader))
1125 rect.encoding = rfbClientSwap32IfLE(rect.encoding);
1126 if (rect.encoding == rfbEncodingLastRect)
1129 rect.r.x = rfbClientSwap16IfLE(rect.r.x);
1130 rect.r.y = rfbClientSwap16IfLE(rect.r.y);
1131 rect.r.w = rfbClientSwap16IfLE(rect.r.w);
1132 rect.r.h = rfbClientSwap16IfLE(rect.r.h);
1135 if (rect.encoding == rfbEncodingXCursor ||
1136 rect.encoding == rfbEncodingRichCursor) {
1138 if (!HandleCursorShape(client,
1139 rect.r.x, rect.r.y, rect.r.w, rect.r.h,
1146 if (rect.encoding == rfbEncodingPointerPos) {
1147 if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) {
1153 if (rect.encoding == rfbEncodingKeyboardLedState) {
1154 /* OK! We have received a keyboard state message!!! */
1155 client->KeyboardLedStateEnabled = 1;
1156 if (client->HandleKeyboardLedState!=NULL)
1157 client->HandleKeyboardLedState(client, rect.r.x, 0);
1158 /* stash it for the future */
1159 client->CurrentKeyboardLedState = rect.r.x;
1163 if (rect.encoding == rfbEncodingNewFBSize) {
1164 client->width = rect.r.w;
1165 client->height = rect.r.h;
1166 client->MallocFrameBuffer(client);
1167 SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE);
1168 rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h);
1172 /* rect.r.w=byte count */
1173 if (rect.encoding == rfbEncodingSupportedMessages) {
1175 if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages))
1178 /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */
1179 /* currently ignored by this library */
1181 rfbClientLog("client2server supported messages (bit flags)\n");
1182 for (loop=0;loop<32;loop+=8)
1183 rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
1184 client->supportedMessages.client2server[loop], client->supportedMessages.client2server[loop+1],
1185 client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3],
1186 client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5],
1187 client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]);
1189 rfbClientLog("server2client supported messages (bit flags)\n");
1190 for (loop=0;loop<32;loop+=8)
1191 rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
1192 client->supportedMessages.server2client[loop], client->supportedMessages.server2client[loop+1],
1193 client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3],
1194 client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5],
1195 client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]);
1199 /* rect.r.w=byte count, rect.r.h=# of encodings */
1200 if (rect.encoding == rfbEncodingSupportedEncodings) {
1202 buffer = malloc(rect.r.w);
1203 if (!ReadFromRFBServer(client, buffer, rect.r.w))
1209 /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */
1210 /* currently ignored by this library */
1215 /* rect.r.w=byte count */
1216 if (rect.encoding == rfbEncodingServerIdentity) {
1218 buffer = malloc(rect.r.w+1);
1219 if (!ReadFromRFBServer(client, buffer, rect.r.w))
1224 buffer[rect.r.w]=0; /* null terminate, just in case */
1225 rfbClientLog("Connected to Server \"%s\"\n", buffer);
1230 /* rfbEncodingUltraZip is a collection of subrects. x = # of subrects, and h is always 0 */
1231 if (rect.encoding != rfbEncodingUltraZip)
1233 if ((rect.r.x + rect.r.w > client->width) ||
1234 (rect.r.y + rect.r.h > client->height))
1236 rfbClientLog("Rect too large: %dx%d at (%d, %d)\n",
1237 rect.r.w, rect.r.h, rect.r.x, rect.r.y);
1241 /* UltraVNC with scaling, will send rectangles with a zero W or H
1243 if ((rect.encoding != rfbEncodingTight) &&
1244 (rect.r.h * rect.r.w == 0))
1246 rfbClientLog("Zero size rect - ignoring (encoding=%d (0x%08x) %dx, %dy, %dw, %dh)\n", rect.encoding, rect.encoding, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
1251 /* If RichCursor encoding is used, we should prevent collisions
1252 between framebuffer updates and cursor drawing operations. */
1253 client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
1256 switch (rect.encoding) {
1258 case rfbEncodingRaw: {
1259 int y=rect.r.y, h=rect.r.h;
1261 bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8;
1262 linesToRead = RFB_BUFFER_SIZE / bytesPerLine;
1265 if (linesToRead > h)
1268 if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead))
1271 CopyRectangle(client, (uint8_t *)client->buffer,
1272 rect.r.x, y, rect.r.w,linesToRead);
1280 case rfbEncodingCopyRect:
1284 if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect))
1287 cr.srcX = rfbClientSwap16IfLE(cr.srcX);
1288 cr.srcY = rfbClientSwap16IfLE(cr.srcY);
1290 /* If RichCursor encoding is used, we should extend our
1291 "cursor lock area" (previously set to destination
1292 rectangle) to the source rectangle as well. */
1293 client->SoftCursorLockArea(client,
1294 cr.srcX, cr.srcY, rect.r.w, rect.r.h);
1296 if (client->GotCopyRect != NULL) {
1297 client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h,
1298 rect.r.x, rect.r.y);
1300 CopyRectangleFromRectangle(client,
1301 cr.srcX, cr.srcY, rect.r.w, rect.r.h,
1302 rect.r.x, rect.r.y);
1307 case rfbEncodingRRE:
1309 switch (client->format.bitsPerPixel) {
1311 if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1315 if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1319 if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1326 case rfbEncodingCoRRE:
1328 switch (client->format.bitsPerPixel) {
1330 if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1334 if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1338 if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1345 case rfbEncodingHextile:
1347 switch (client->format.bitsPerPixel) {
1349 if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1353 if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1357 if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1364 case rfbEncodingUltra:
1366 switch (client->format.bitsPerPixel) {
1368 if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1372 if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1376 if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1382 case rfbEncodingUltraZip:
1384 switch (client->format.bitsPerPixel) {
1386 if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1390 if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1394 if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1401 #ifdef LIBVNCSERVER_HAVE_LIBZ
1402 case rfbEncodingZlib:
1404 switch (client->format.bitsPerPixel) {
1406 if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1410 if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1414 if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1421 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
1422 case rfbEncodingTight:
1424 switch (client->format.bitsPerPixel) {
1426 if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1430 if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1434 if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1441 case rfbEncodingZRLE:
1442 /* Fail safe for ZYWRLE unsupport VNC server. */
1443 client->appData.qualityLevel = 9;
1445 case rfbEncodingZYWRLE:
1447 switch (client->format.bitsPerPixel) {
1449 if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1453 if (client->si.format.greenMax > 0x1F) {
1454 if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1457 if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1463 uint32_t maxColor=(client->format.redMax<<client->format.redShift)|
1464 (client->format.greenMax<<client->format.greenShift)|
1465 (client->format.blueMax<<client->format.blueShift);
1466 if ((client->format.bigEndian && (maxColor&0xff)==0) ||
1467 (!client->format.bigEndian && (maxColor&0xff000000)==0)) {
1468 if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1470 } else if (!client->format.bigEndian && (maxColor&0xff)==0) {
1471 if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1473 } else if (client->format.bigEndian && (maxColor&0xff000000)==0) {
1474 if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1476 } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1488 rfbBool handled = FALSE;
1489 rfbClientProtocolExtension* e;
1491 for(e = rfbClientExtensions; !handled && e; e = e->next)
1492 if(e->handleEncoding && e->handleEncoding(client, &rect))
1496 rfbClientLog("Unknown rect encoding %d\n",
1497 (int)rect.encoding);
1503 /* Now we may discard "soft cursor locks". */
1504 client->SoftCursorUnlockScreen(client);
1506 client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
1509 if (!SendIncrementalFramebufferUpdateRequest(client))
1517 client->Bell(client);
1522 case rfbServerCutText:
1526 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1527 sz_rfbServerCutTextMsg - 1))
1530 msg.sct.length = rfbClientSwap32IfLE(msg.sct.length);
1532 buffer = malloc(msg.sct.length+1);
1534 if (!ReadFromRFBServer(client, buffer, msg.sct.length))
1537 buffer[msg.sct.length] = 0;
1539 if (client->GotXCutText)
1540 client->GotXCutText(client, buffer, msg.sct.length);
1550 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1551 sz_rfbTextChatMsg- 1))
1553 msg.tc.length = rfbClientSwap32IfLE(msg.sct.length);
1554 switch(msg.tc.length) {
1555 case rfbTextChatOpen:
1556 rfbClientLog("Received TextChat Open\n");
1557 if (client->HandleTextChat!=NULL)
1558 client->HandleTextChat(client, (int)rfbTextChatOpen, NULL);
1560 case rfbTextChatClose:
1561 rfbClientLog("Received TextChat Close\n");
1562 if (client->HandleTextChat!=NULL)
1563 client->HandleTextChat(client, (int)rfbTextChatClose, NULL);
1565 case rfbTextChatFinished:
1566 rfbClientLog("Received TextChat Finished\n");
1567 if (client->HandleTextChat!=NULL)
1568 client->HandleTextChat(client, (int)rfbTextChatFinished, NULL);
1571 buffer=malloc(msg.tc.length+1);
1572 if (!ReadFromRFBServer(client, buffer, msg.tc.length))
1577 /* Null Terminate <just in case> */
1578 buffer[msg.tc.length]=0;
1579 rfbClientLog("Received TextChat \"%s\"\n", buffer);
1580 if (client->HandleTextChat!=NULL)
1581 client->HandleTextChat(client, (int)msg.tc.length, buffer);
1588 case rfbResizeFrameBuffer:
1590 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1591 sz_rfbResizeFrameBufferMsg -1))
1593 client->width = rfbClientSwap16IfLE(msg.rsfb.framebufferWidth);
1594 client->height = rfbClientSwap16IfLE(msg.rsfb.framebufferHeigth);
1595 client->MallocFrameBuffer(client);
1596 SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
1597 rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
1601 case rfbPalmVNCReSizeFrameBuffer:
1603 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1604 sz_rfbPalmVNCReSizeFrameBufferMsg -1))
1606 client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w);
1607 client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h);
1608 client->MallocFrameBuffer(client);
1609 SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
1610 rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
1616 rfbBool handled = FALSE;
1617 rfbClientProtocolExtension* e;
1619 for(e = rfbClientExtensions; !handled && e; e = e->next)
1620 if(e->handleMessage && e->handleMessage(client, &msg))
1625 rfbClientLog("Unknown message type %d from VNC server\n",msg.type);
1626 ReadFromRFBServer(client, buffer, 256);
1636 #define GET_PIXEL8(pix, ptr) ((pix) = *(ptr)++)
1638 #define GET_PIXEL16(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \
1639 ((uint8_t*)&(pix))[1] = *(ptr)++)
1641 #define GET_PIXEL32(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \
1642 ((uint8_t*)&(pix))[1] = *(ptr)++, \
1643 ((uint8_t*)&(pix))[2] = *(ptr)++, \
1644 ((uint8_t*)&(pix))[3] = *(ptr)++)
1646 /* CONCAT2 concatenates its two arguments. CONCAT2E does the same but also
1647 expands its arguments if they are macros */
1649 #define CONCAT2(a,b) a##b
1650 #define CONCAT2E(a,b) CONCAT2(a,b)
1651 #define CONCAT3(a,b,c) a##b##c
1652 #define CONCAT3E(a,b,c) CONCAT3(a,b,c)
1657 #include "hextile.c"
1666 #include "hextile.c"
1677 #include "hextile.c"
1698 PrintPixelFormat(rfbPixelFormat *format)
1700 if (format->bitsPerPixel == 1) {
1701 rfbClientLog(" Single bit per pixel.\n");
1703 " %s significant bit in each byte is leftmost on the screen.\n",
1704 (format->bigEndian ? "Most" : "Least"));
1706 rfbClientLog(" %d bits per pixel.\n",format->bitsPerPixel);
1707 if (format->bitsPerPixel != 8) {
1708 rfbClientLog(" %s significant byte first in each pixel.\n",
1709 (format->bigEndian ? "Most" : "Least"));
1711 if (format->trueColour) {
1712 rfbClientLog(" TRUE colour: max red %d green %d blue %d"
1713 ", shift red %d green %d blue %d\n",
1714 format->redMax, format->greenMax, format->blueMax,
1715 format->redShift, format->greenShift, format->blueShift);
1717 rfbClientLog(" Colour map (not true colour).\n");
1722 /* avoid name clashes with LibVNCServer */
1724 #define rfbEncryptBytes rfbClientEncryptBytes
1725 #define rfbDes rfbClientDes
1726 #define rfbDesKey rfbClientDesKey
1727 #define rfbUseKey rfbClientUseKey
1728 #define rfbCPKey rfbClientCPKey
1730 #include "../libvncserver/vncauth.c"
1731 #include "../libvncserver/d3des.c"