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) || major>3)
501 rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n",
502 major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion);
504 sprintf(pv,rfbProtocolVersionFormat,client->major,client->minor);
506 if (!WriteToRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE;
509 /* 3.7 and onwards sends a # of security types first */
510 if (client->major==3 && client->minor > 6)
517 if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE;
521 rfbClientLog("List of security types is ZERO, expecting an error to follow\n");
523 /* we have an error following */
524 if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
525 reasonLen = rfbClientSwap32IfLE(reasonLen);
526 reason = malloc(reasonLen+1);
527 if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
529 rfbClientLog("VNC connection failed: %s\n",reason);
534 rfbClientLog("We have %d security types to read\n", count);
535 /* now, we have a list of available security types to read ( uint8_t[] ) */
536 for (loop=0;loop<count;loop++)
538 if (!ReadFromRFBServer(client, (char *)&tAuth, 1)) return FALSE;
539 rfbClientLog("%d) Received security type %d\n", loop, tAuth);
540 if ((flag==0) && ((tAuth==rfbVncAuth) || (tAuth==rfbNoAuth)))
544 rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count);
545 /* send back a single byte indicating which security type to use */
546 if (!WriteToRFBServer(client, (char *)&tAuth, 1)) return FALSE;
553 if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE;
554 authScheme = rfbClientSwap32IfLE(authScheme);
557 rfbClientLog("Selected Security Scheme %d\n", authScheme);
559 switch (authScheme) {
562 if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
563 reasonLen = rfbClientSwap32IfLE(reasonLen);
565 reason = malloc(reasonLen+1);
567 if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
569 rfbClientLog("VNC connection failed: %s\n", reason);
574 rfbClientLog("No authentication needed\n");
576 /* 3.8 and upwards sends a Security Result for rfbNoAuth */
577 if ((client->major==3 && client->minor > 7) || client->major>3)
578 if (!rfbHandleAuthResult(client)) return FALSE;
583 if (!ReadFromRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
585 if (client->serverPort!=-1) { /* if not playing a vncrec file */
586 if (client->GetPassword)
587 passwd = client->GetPassword(client);
589 if ((!passwd) || (strlen(passwd) == 0)) {
590 rfbClientLog("Reading password failed\n");
593 if (strlen(passwd) > 8) {
597 rfbClientEncryptBytes(challenge, passwd);
599 /* Lose the password from memory */
600 for (i = strlen(passwd); i >= 0; i--) {
605 if (!WriteToRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
608 /* Handle the SecurityResult message */
609 if (!rfbHandleAuthResult(client)) return FALSE;
613 rfbClientLog("Unknown authentication scheme from VNC server: %d\n",
618 ci.shared = (client->appData.shareDesktop ? 1 : 0);
620 if (!WriteToRFBServer(client, (char *)&ci, sz_rfbClientInitMsg)) return FALSE;
622 if (!ReadFromRFBServer(client, (char *)&client->si, sz_rfbServerInitMsg)) return FALSE;
624 client->si.framebufferWidth = rfbClientSwap16IfLE(client->si.framebufferWidth);
625 client->si.framebufferHeight = rfbClientSwap16IfLE(client->si.framebufferHeight);
626 client->si.format.redMax = rfbClientSwap16IfLE(client->si.format.redMax);
627 client->si.format.greenMax = rfbClientSwap16IfLE(client->si.format.greenMax);
628 client->si.format.blueMax = rfbClientSwap16IfLE(client->si.format.blueMax);
629 client->si.nameLength = rfbClientSwap32IfLE(client->si.nameLength);
631 client->desktopName = malloc(client->si.nameLength + 1);
632 if (!client->desktopName) {
633 rfbClientLog("Error allocating memory for desktop name, %lu bytes\n",
634 (unsigned long)client->si.nameLength);
638 if (!ReadFromRFBServer(client, client->desktopName, client->si.nameLength)) return FALSE;
640 client->desktopName[client->si.nameLength] = 0;
642 rfbClientLog("Desktop name \"%s\"\n",client->desktopName);
644 rfbClientLog("Connected to VNC server, using protocol version %d.%d\n",
645 client->major, client->minor);
647 rfbClientLog("VNC server default format:\n");
648 PrintPixelFormat(&client->si.format);
655 * SetFormatAndEncodings.
659 SetFormatAndEncodings(rfbClient* client)
661 rfbSetPixelFormatMsg spf;
662 char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
664 rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf;
665 uint32_t *encs = (uint32_t *)(&buf[sz_rfbSetEncodingsMsg]);
667 rfbBool requestCompressLevel = FALSE;
668 rfbBool requestQualityLevel = FALSE;
669 rfbBool requestLastRectEncoding = FALSE;
670 rfbClientProtocolExtension* e;
672 if (!SupportsClient2Server(client, rfbSetPixelFormat)) return TRUE;
674 spf.type = rfbSetPixelFormat;
675 spf.format = client->format;
676 spf.format.redMax = rfbClientSwap16IfLE(spf.format.redMax);
677 spf.format.greenMax = rfbClientSwap16IfLE(spf.format.greenMax);
678 spf.format.blueMax = rfbClientSwap16IfLE(spf.format.blueMax);
680 if (!WriteToRFBServer(client, (char *)&spf, sz_rfbSetPixelFormatMsg))
684 if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE;
686 se->type = rfbSetEncodings;
689 if (client->appData.encodingsString) {
690 const char *encStr = client->appData.encodingsString;
693 const char *nextEncStr = strchr(encStr, ' ');
695 encStrLen = nextEncStr - encStr;
698 encStrLen = strlen(encStr);
701 if (strncasecmp(encStr,"raw",encStrLen) == 0) {
702 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw);
703 } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
704 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect);
705 #ifdef LIBVNCSERVER_HAVE_LIBZ
706 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
707 } else if (strncasecmp(encStr,"tight",encStrLen) == 0) {
708 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight);
709 requestLastRectEncoding = TRUE;
710 if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
711 requestCompressLevel = TRUE;
712 if (client->appData.enableJPEG)
713 requestQualityLevel = TRUE;
716 } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) {
717 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile);
718 #ifdef LIBVNCSERVER_HAVE_LIBZ
719 } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) {
720 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib);
721 if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
722 requestCompressLevel = TRUE;
723 } else if (strncasecmp(encStr,"zlibhex",encStrLen) == 0) {
724 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlibHex);
725 if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
726 requestCompressLevel = TRUE;
727 } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) {
728 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE);
729 } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) {
730 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE);
731 requestQualityLevel = TRUE;
733 } else if ((strncasecmp(encStr,"ultra",encStrLen) == 0) || (strncasecmp(encStr,"ultrazip",encStrLen) == 0)) {
734 /* There are 2 encodings used in 'ultra' */
735 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra);
736 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip);
737 } else if (strncasecmp(encStr,"corre",encStrLen) == 0) {
738 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE);
739 } else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
740 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE);
742 rfbClientLog("Unknown encoding '%.*s'\n",encStrLen,encStr);
746 } while (encStr && se->nEncodings < MAX_ENCODINGS);
748 if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) {
749 encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel +
750 rfbEncodingCompressLevel0);
753 if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) {
754 if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9)
755 client->appData.qualityLevel = 5;
756 encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel +
757 rfbEncodingQualityLevel0);
761 if (SameMachine(client->sock)) {
763 if (!tunnelSpecified) {
765 rfbClientLog("Same machine: preferring raw encoding\n");
766 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw);
769 rfbClientLog("Tunneling active: preferring tight encoding\n");
774 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect);
775 #ifdef LIBVNCSERVER_HAVE_LIBZ
776 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
777 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight);
778 requestLastRectEncoding = TRUE;
781 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile);
782 #ifdef LIBVNCSERVER_HAVE_LIBZ
783 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib);
784 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE);
785 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE);
787 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra);
788 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip);
789 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE);
790 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE);
792 if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) {
793 encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel +
794 rfbEncodingCompressLevel0);
795 } else /* if (!tunnelSpecified) */ {
796 /* If -tunnel option was provided, we assume that server machine is
797 not in the local network so we use default compression level for
798 tight encoding instead of fast compression. Thus we are
799 requesting level 1 compression only if tunneling is not used. */
800 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCompressLevel1);
803 if (client->appData.enableJPEG) {
804 if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9)
805 client->appData.qualityLevel = 5;
806 encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel +
807 rfbEncodingQualityLevel0);
813 /* Remote Cursor Support (local to viewer) */
814 if (client->appData.useRemoteCursor) {
815 if (se->nEncodings < MAX_ENCODINGS)
816 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingXCursor);
817 if (se->nEncodings < MAX_ENCODINGS)
818 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRichCursor);
819 if (se->nEncodings < MAX_ENCODINGS)
820 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPointerPos);
823 /* Keyboard State Encodings */
824 if (se->nEncodings < MAX_ENCODINGS)
825 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingKeyboardLedState);
827 /* New Frame Buffer Size */
828 if (se->nEncodings < MAX_ENCODINGS && client->canHandleNewFBSize)
829 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingNewFBSize);
832 if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding)
833 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect);
835 /* Server Capabilities */
836 if (se->nEncodings < MAX_ENCODINGS)
837 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedMessages);
838 if (se->nEncodings < MAX_ENCODINGS)
839 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedEncodings);
840 if (se->nEncodings < MAX_ENCODINGS)
841 encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingServerIdentity);
844 /* client extensions */
845 for(e = rfbClientExtensions; e; e = e->next)
848 for(enc = e->encodings; *enc; enc++)
849 encs[se->nEncodings++] = rfbClientSwap32IfLE(*enc);
852 len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
854 se->nEncodings = rfbClientSwap16IfLE(se->nEncodings);
856 if (!WriteToRFBServer(client, buf, len)) return FALSE;
863 * SendIncrementalFramebufferUpdateRequest.
867 SendIncrementalFramebufferUpdateRequest(rfbClient* client)
869 return SendFramebufferUpdateRequest(client,
870 client->updateRect.x, client->updateRect.y,
871 client->updateRect.w, client->updateRect.h, TRUE);
876 * SendFramebufferUpdateRequest.
880 SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbBool incremental)
882 rfbFramebufferUpdateRequestMsg fur;
884 if (!SupportsClient2Server(client, rfbFramebufferUpdateRequest)) return TRUE;
886 fur.type = rfbFramebufferUpdateRequest;
887 fur.incremental = incremental ? 1 : 0;
888 fur.x = rfbClientSwap16IfLE(x);
889 fur.y = rfbClientSwap16IfLE(y);
890 fur.w = rfbClientSwap16IfLE(w);
891 fur.h = rfbClientSwap16IfLE(h);
893 if (!WriteToRFBServer(client, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg))
904 SendScaleSetting(rfbClient* client,int scaleSetting)
908 ssm.scale = scaleSetting;
911 /* favor UltraVNC SetScale if both are supported */
912 if (SupportsClient2Server(client, rfbSetScale)) {
913 ssm.type = rfbSetScale;
914 if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
918 if (SupportsClient2Server(client, rfbPalmVNCSetScaleFactor)) {
919 ssm.type = rfbPalmVNCSetScaleFactor;
920 if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
928 * TextChatFunctions (UltraVNC)
929 * Extremely bandwidth friendly method of communicating with a user
930 * (Think HelpDesk type applications)
933 rfbBool TextChatSend(rfbClient* client, char *text)
936 int count = strlen(text);
938 if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
939 chat.type = rfbTextChat;
942 chat.length = (uint32_t)count;
943 chat.length = rfbClientSwap32IfLE(chat.length);
945 if (!WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg))
949 if (!WriteToRFBServer(client, text, count))
955 rfbBool TextChatOpen(rfbClient* client)
959 if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
960 chat.type = rfbTextChat;
963 chat.length = rfbClientSwap32IfLE(rfbTextChatOpen);
964 return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
967 rfbBool TextChatClose(rfbClient* client)
970 if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
971 chat.type = rfbTextChat;
974 chat.length = rfbClientSwap32IfLE(rfbTextChatClose);
975 return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
978 rfbBool TextChatFinish(rfbClient* client)
981 if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
982 chat.type = rfbTextChat;
985 chat.length = rfbClientSwap32IfLE(rfbTextChatFinished);
986 return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
990 * UltraVNC Server Input Disable
991 * Apparently, the remote client can *prevent* the local user from interacting with the display
992 * I would think this is extremely helpful when used in a HelpDesk situation
994 rfbBool PermitServerInput(rfbClient* client, int enabled)
996 rfbSetServerInputMsg msg;
998 if (!SupportsClient2Server(client, rfbSetServerInput)) return TRUE;
999 /* enabled==1, then server input from local keyboard is disabled */
1000 msg.type = rfbSetServerInput;
1001 msg.status = (enabled ? 1 : 0);
1003 return (WriteToRFBServer(client, (char *)&msg, sz_rfbSetServerInputMsg) ? TRUE : FALSE);
1012 SendPointerEvent(rfbClient* client,int x, int y, int buttonMask)
1014 rfbPointerEventMsg pe;
1016 if (!SupportsClient2Server(client, rfbPointerEvent)) return TRUE;
1018 pe.type = rfbPointerEvent;
1019 pe.buttonMask = buttonMask;
1023 pe.x = rfbClientSwap16IfLE(x);
1024 pe.y = rfbClientSwap16IfLE(y);
1025 return WriteToRFBServer(client, (char *)&pe, sz_rfbPointerEventMsg);
1034 SendKeyEvent(rfbClient* client, uint32_t key, rfbBool down)
1038 if (!SupportsClient2Server(client, rfbKeyEvent)) return TRUE;
1040 ke.type = rfbKeyEvent;
1041 ke.down = down ? 1 : 0;
1042 ke.key = rfbClientSwap32IfLE(key);
1043 return WriteToRFBServer(client, (char *)&ke, sz_rfbKeyEventMsg);
1048 * SendClientCutText.
1052 SendClientCutText(rfbClient* client, char *str, int len)
1054 rfbClientCutTextMsg cct;
1056 if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE;
1058 cct.type = rfbClientCutText;
1059 cct.length = rfbClientSwap32IfLE(len);
1060 return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) &&
1061 WriteToRFBServer(client, str, len));
1067 * HandleRFBServerMessage.
1071 HandleRFBServerMessage(rfbClient* client)
1073 rfbServerToClientMsg msg;
1075 if (client->serverPort==-1)
1076 client->vncRec->readTimestamp = TRUE;
1077 if (!ReadFromRFBServer(client, (char *)&msg, 1))
1082 case rfbSetColourMapEntries:
1089 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1090 sz_rfbSetColourMapEntriesMsg - 1))
1093 msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour);
1094 msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours);
1096 for (i = 0; i < msg.scme.nColours; i++) {
1097 if (!ReadFromRFBServer(client, (char *)rgb, 6))
1099 xc.pixel = msg.scme.firstColour + i;
1100 xc.red = rfbClientSwap16IfLE(rgb[0]);
1101 xc.green = rfbClientSwap16IfLE(rgb[1]);
1102 xc.blue = rfbClientSwap16IfLE(rgb[2]);
1103 xc.flags = DoRed|DoGreen|DoBlue;
1104 XStoreColor(dpy, cmap, &xc);
1111 case rfbFramebufferUpdate:
1113 rfbFramebufferUpdateRectHeader rect;
1118 if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1,
1119 sz_rfbFramebufferUpdateMsg - 1))
1122 msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects);
1124 for (i = 0; i < msg.fu.nRects; i++) {
1125 if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader))
1128 rect.encoding = rfbClientSwap32IfLE(rect.encoding);
1129 if (rect.encoding == rfbEncodingLastRect)
1132 rect.r.x = rfbClientSwap16IfLE(rect.r.x);
1133 rect.r.y = rfbClientSwap16IfLE(rect.r.y);
1134 rect.r.w = rfbClientSwap16IfLE(rect.r.w);
1135 rect.r.h = rfbClientSwap16IfLE(rect.r.h);
1138 if (rect.encoding == rfbEncodingXCursor ||
1139 rect.encoding == rfbEncodingRichCursor) {
1141 if (!HandleCursorShape(client,
1142 rect.r.x, rect.r.y, rect.r.w, rect.r.h,
1149 if (rect.encoding == rfbEncodingPointerPos) {
1150 if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) {
1156 if (rect.encoding == rfbEncodingKeyboardLedState) {
1157 /* OK! We have received a keyboard state message!!! */
1158 client->KeyboardLedStateEnabled = 1;
1159 if (client->HandleKeyboardLedState!=NULL)
1160 client->HandleKeyboardLedState(client, rect.r.x, 0);
1161 /* stash it for the future */
1162 client->CurrentKeyboardLedState = rect.r.x;
1166 if (rect.encoding == rfbEncodingNewFBSize) {
1167 client->width = rect.r.w;
1168 client->height = rect.r.h;
1169 client->MallocFrameBuffer(client);
1170 SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE);
1171 rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h);
1175 /* rect.r.w=byte count */
1176 if (rect.encoding == rfbEncodingSupportedMessages) {
1178 if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages))
1181 /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */
1182 /* currently ignored by this library */
1184 rfbClientLog("client2server supported messages (bit flags)\n");
1185 for (loop=0;loop<32;loop+=8)
1186 rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
1187 client->supportedMessages.client2server[loop], client->supportedMessages.client2server[loop+1],
1188 client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3],
1189 client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5],
1190 client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]);
1192 rfbClientLog("server2client supported messages (bit flags)\n");
1193 for (loop=0;loop<32;loop+=8)
1194 rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
1195 client->supportedMessages.server2client[loop], client->supportedMessages.server2client[loop+1],
1196 client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3],
1197 client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5],
1198 client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]);
1202 /* rect.r.w=byte count, rect.r.h=# of encodings */
1203 if (rect.encoding == rfbEncodingSupportedEncodings) {
1205 buffer = malloc(rect.r.w);
1206 if (!ReadFromRFBServer(client, buffer, rect.r.w))
1212 /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */
1213 /* currently ignored by this library */
1218 /* rect.r.w=byte count */
1219 if (rect.encoding == rfbEncodingServerIdentity) {
1221 buffer = malloc(rect.r.w+1);
1222 if (!ReadFromRFBServer(client, buffer, rect.r.w))
1227 buffer[rect.r.w]=0; /* null terminate, just in case */
1228 rfbClientLog("Connected to Server \"%s\"\n", buffer);
1233 /* rfbEncodingUltraZip is a collection of subrects. x = # of subrects, and h is always 0 */
1234 if (rect.encoding != rfbEncodingUltraZip)
1236 if ((rect.r.x + rect.r.w > client->width) ||
1237 (rect.r.y + rect.r.h > client->height))
1239 rfbClientLog("Rect too large: %dx%d at (%d, %d)\n",
1240 rect.r.w, rect.r.h, rect.r.x, rect.r.y);
1244 /* UltraVNC with scaling, will send rectangles with a zero W or H
1246 if ((rect.encoding != rfbEncodingTight) &&
1247 (rect.r.h * rect.r.w == 0))
1249 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);
1254 /* If RichCursor encoding is used, we should prevent collisions
1255 between framebuffer updates and cursor drawing operations. */
1256 client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
1259 switch (rect.encoding) {
1261 case rfbEncodingRaw: {
1262 int y=rect.r.y, h=rect.r.h;
1264 bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8;
1265 linesToRead = RFB_BUFFER_SIZE / bytesPerLine;
1268 if (linesToRead > h)
1271 if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead))
1274 CopyRectangle(client, (uint8_t *)client->buffer,
1275 rect.r.x, y, rect.r.w,linesToRead);
1283 case rfbEncodingCopyRect:
1287 if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect))
1290 cr.srcX = rfbClientSwap16IfLE(cr.srcX);
1291 cr.srcY = rfbClientSwap16IfLE(cr.srcY);
1293 /* If RichCursor encoding is used, we should extend our
1294 "cursor lock area" (previously set to destination
1295 rectangle) to the source rectangle as well. */
1296 client->SoftCursorLockArea(client,
1297 cr.srcX, cr.srcY, rect.r.w, rect.r.h);
1299 if (client->GotCopyRect != NULL) {
1300 client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h,
1301 rect.r.x, rect.r.y);
1303 CopyRectangleFromRectangle(client,
1304 cr.srcX, cr.srcY, rect.r.w, rect.r.h,
1305 rect.r.x, rect.r.y);
1310 case rfbEncodingRRE:
1312 switch (client->format.bitsPerPixel) {
1314 if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1318 if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1322 if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1329 case rfbEncodingCoRRE:
1331 switch (client->format.bitsPerPixel) {
1333 if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1337 if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1341 if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1348 case rfbEncodingHextile:
1350 switch (client->format.bitsPerPixel) {
1352 if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1356 if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1360 if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1367 case rfbEncodingUltra:
1369 switch (client->format.bitsPerPixel) {
1371 if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1375 if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1379 if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1385 case rfbEncodingUltraZip:
1387 switch (client->format.bitsPerPixel) {
1389 if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1393 if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1397 if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1404 #ifdef LIBVNCSERVER_HAVE_LIBZ
1405 case rfbEncodingZlib:
1407 switch (client->format.bitsPerPixel) {
1409 if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1413 if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1417 if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1424 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
1425 case rfbEncodingTight:
1427 switch (client->format.bitsPerPixel) {
1429 if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1433 if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1437 if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1444 case rfbEncodingZRLE:
1445 /* Fail safe for ZYWRLE unsupport VNC server. */
1446 client->appData.qualityLevel = 9;
1448 case rfbEncodingZYWRLE:
1450 switch (client->format.bitsPerPixel) {
1452 if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1456 if (client->si.format.greenMax > 0x1F) {
1457 if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1460 if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1466 uint32_t maxColor=(client->format.redMax<<client->format.redShift)|
1467 (client->format.greenMax<<client->format.greenShift)|
1468 (client->format.blueMax<<client->format.blueShift);
1469 if ((client->format.bigEndian && (maxColor&0xff)==0) ||
1470 (!client->format.bigEndian && (maxColor&0xff000000)==0)) {
1471 if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1473 } else if (!client->format.bigEndian && (maxColor&0xff)==0) {
1474 if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1476 } else if (client->format.bigEndian && (maxColor&0xff000000)==0) {
1477 if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1479 } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
1491 rfbBool handled = FALSE;
1492 rfbClientProtocolExtension* e;
1494 for(e = rfbClientExtensions; !handled && e; e = e->next)
1495 if(e->handleEncoding && e->handleEncoding(client, &rect))
1499 rfbClientLog("Unknown rect encoding %d\n",
1500 (int)rect.encoding);
1506 /* Now we may discard "soft cursor locks". */
1507 client->SoftCursorUnlockScreen(client);
1509 client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
1512 if (!SendIncrementalFramebufferUpdateRequest(client))
1520 client->Bell(client);
1525 case rfbServerCutText:
1529 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1530 sz_rfbServerCutTextMsg - 1))
1533 msg.sct.length = rfbClientSwap32IfLE(msg.sct.length);
1535 buffer = malloc(msg.sct.length+1);
1537 if (!ReadFromRFBServer(client, buffer, msg.sct.length))
1540 buffer[msg.sct.length] = 0;
1542 if (client->GotXCutText)
1543 client->GotXCutText(client, buffer, msg.sct.length);
1553 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1554 sz_rfbTextChatMsg- 1))
1556 msg.tc.length = rfbClientSwap32IfLE(msg.sct.length);
1557 switch(msg.tc.length) {
1558 case rfbTextChatOpen:
1559 rfbClientLog("Received TextChat Open\n");
1560 if (client->HandleTextChat!=NULL)
1561 client->HandleTextChat(client, (int)rfbTextChatOpen, NULL);
1563 case rfbTextChatClose:
1564 rfbClientLog("Received TextChat Close\n");
1565 if (client->HandleTextChat!=NULL)
1566 client->HandleTextChat(client, (int)rfbTextChatClose, NULL);
1568 case rfbTextChatFinished:
1569 rfbClientLog("Received TextChat Finished\n");
1570 if (client->HandleTextChat!=NULL)
1571 client->HandleTextChat(client, (int)rfbTextChatFinished, NULL);
1574 buffer=malloc(msg.tc.length+1);
1575 if (!ReadFromRFBServer(client, buffer, msg.tc.length))
1580 /* Null Terminate <just in case> */
1581 buffer[msg.tc.length]=0;
1582 rfbClientLog("Received TextChat \"%s\"\n", buffer);
1583 if (client->HandleTextChat!=NULL)
1584 client->HandleTextChat(client, (int)msg.tc.length, buffer);
1591 case rfbResizeFrameBuffer:
1593 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1594 sz_rfbResizeFrameBufferMsg -1))
1596 client->width = rfbClientSwap16IfLE(msg.rsfb.framebufferWidth);
1597 client->height = rfbClientSwap16IfLE(msg.rsfb.framebufferHeigth);
1598 client->MallocFrameBuffer(client);
1599 SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
1600 rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
1604 case rfbPalmVNCReSizeFrameBuffer:
1606 if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
1607 sz_rfbPalmVNCReSizeFrameBufferMsg -1))
1609 client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w);
1610 client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h);
1611 client->MallocFrameBuffer(client);
1612 SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
1613 rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
1619 rfbBool handled = FALSE;
1620 rfbClientProtocolExtension* e;
1622 for(e = rfbClientExtensions; !handled && e; e = e->next)
1623 if(e->handleMessage && e->handleMessage(client, &msg))
1628 rfbClientLog("Unknown message type %d from VNC server\n",msg.type);
1629 ReadFromRFBServer(client, buffer, 256);
1639 #define GET_PIXEL8(pix, ptr) ((pix) = *(ptr)++)
1641 #define GET_PIXEL16(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \
1642 ((uint8_t*)&(pix))[1] = *(ptr)++)
1644 #define GET_PIXEL32(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \
1645 ((uint8_t*)&(pix))[1] = *(ptr)++, \
1646 ((uint8_t*)&(pix))[2] = *(ptr)++, \
1647 ((uint8_t*)&(pix))[3] = *(ptr)++)
1649 /* CONCAT2 concatenates its two arguments. CONCAT2E does the same but also
1650 expands its arguments if they are macros */
1652 #define CONCAT2(a,b) a##b
1653 #define CONCAT2E(a,b) CONCAT2(a,b)
1654 #define CONCAT3(a,b,c) a##b##c
1655 #define CONCAT3E(a,b,c) CONCAT3(a,b,c)
1660 #include "hextile.c"
1669 #include "hextile.c"
1680 #include "hextile.c"
1701 PrintPixelFormat(rfbPixelFormat *format)
1703 if (format->bitsPerPixel == 1) {
1704 rfbClientLog(" Single bit per pixel.\n");
1706 " %s significant bit in each byte is leftmost on the screen.\n",
1707 (format->bigEndian ? "Most" : "Least"));
1709 rfbClientLog(" %d bits per pixel.\n",format->bitsPerPixel);
1710 if (format->bitsPerPixel != 8) {
1711 rfbClientLog(" %s significant byte first in each pixel.\n",
1712 (format->bigEndian ? "Most" : "Least"));
1714 if (format->trueColour) {
1715 rfbClientLog(" TRUE colour: max red %d green %d blue %d"
1716 ", shift red %d green %d blue %d\n",
1717 format->redMax, format->greenMax, format->blueMax,
1718 format->redShift, format->greenShift, format->blueShift);
1720 rfbClientLog(" Colour map (not true colour).\n");
1725 /* avoid name clashes with LibVNCServer */
1727 #define rfbEncryptBytes rfbClientEncryptBytes
1728 #define rfbDes rfbClientDes
1729 #define rfbDesKey rfbClientDesKey
1730 #define rfbUseKey rfbClientUseKey
1731 #define rfbCPKey rfbClientCPKey
1733 #include "../libvncserver/vncauth.c"
1734 #include "../libvncserver/d3des.c"