From 951cea590db4866188a1e372d6a966df7f0e79f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Tue, 1 Feb 2011 21:24:32 +0100 Subject: Import part of libvnc. diff --git a/3rdParty/LibVNC/SConscript b/3rdParty/LibVNC/SConscript new file mode 100644 index 0000000..046acd3 --- /dev/null +++ b/3rdParty/LibVNC/SConscript @@ -0,0 +1,36 @@ +Import(["env", "conf_env"]) + +if env.get("LIBVNC_BUNDLED", False) : + +################################################################################ +# Module flags +################################################################################ + + if env["SCONS_STAGE"] == "flags" : + env["LIBVNC_FLAGS"] = { + "CPPPATH": [Dir("src")], + "LIBPATH": [Dir(".")], + "LIBS": ["Swiften_VNC"], + } + +################################################################################ +# Build +################################################################################ + + if env["SCONS_STAGE"] == "build" : + myenv = env.Clone() + + # Remove warn flags + myenv.Replace(CCFLAGS = [flag for flag in env["CCFLAGS"] if flag not in ["-W", "-Wall"]]) + + myenv.Append(CPPPATH = ["src"]) + + myenv.StaticLibrary("Swiften_VNC", [ + "src/libvncclient/cursor.c", + "src/libvncclient/listen.c", + "src/libvncclient/rfbproto.c", + "src/libvncclient/sockets.c", + "src/libvncclient/vncviewer.c", + "src/libvncclient/minilzo.c", + "src/libvncclient/tls.c", + ]) diff --git a/3rdParty/LibVNC/src/libvncclient/corre.c b/3rdParty/LibVNC/src/libvncclient/corre.c new file mode 100644 index 0000000..baf91cc --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/corre.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * corre.c - handle CoRRE encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles a CoRRE + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleCoRREBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbRREHeader hdr; + int i; + CARDBPP pix; + uint8_t *ptr; + int x, y, w, h; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader)) + return FALSE; + + hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects); + + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + FillRectangle(client, rx, ry, rw, rh, pix); + + if (!ReadFromRFBServer(client, client->buffer, hdr.nSubrects * (4 + (BPP / 8)))) + return FALSE; + + ptr = (uint8_t *)client->buffer; + + for (i = 0; i < hdr.nSubrects; i++) { + pix = *(CARDBPP *)ptr; + ptr += BPP/8; + x = *ptr++; + y = *ptr++; + w = *ptr++; + h = *ptr++; + + FillRectangle(client, rx+x, ry+y, w, h, pix); + } + + return TRUE; +} + +#undef CARDBPP diff --git a/3rdParty/LibVNC/src/libvncclient/cursor.c b/3rdParty/LibVNC/src/libvncclient/cursor.c new file mode 100644 index 0000000..a48d7c5 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/cursor.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2001,2002 Constantin Kaplinsky. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * cursor.c - code to support cursor shape updates (XCursor and + * RichCursor preudo-encodings). + */ + +#include + + +#define OPER_SAVE 0 +#define OPER_RESTORE 1 + +#define RGB24_TO_PIXEL(bpp,r,g,b) \ + ((((uint##bpp##_t)(r) & 0xFF) * client->format.redMax + 127) / 255 \ + << client->format.redShift | \ + (((uint##bpp##_t)(g) & 0xFF) * client->format.greenMax + 127) / 255 \ + << client->format.greenShift | \ + (((uint##bpp##_t)(b) & 0xFF) * client->format.blueMax + 127) / 255 \ + << client->format.blueShift) + + +/********************************************************************* + * HandleCursorShape(). Support for XCursor and RichCursor shape + * updates. We emulate cursor operating on the frame buffer (that is + * why we call it "software cursor"). + ********************************************************************/ + +rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc) +{ + int bytesPerPixel; + size_t bytesPerRow, bytesMaskData; + rfbXCursorColors rgb; + uint32_t colors[2]; + char *buf; + uint8_t *ptr; + int x, y, b; + + bytesPerPixel = client->format.bitsPerPixel / 8; + bytesPerRow = (width + 7) / 8; + bytesMaskData = bytesPerRow * height; + + if (width * height == 0) + return TRUE; + + /* Allocate memory for pixel data and temporary mask data. */ + if(client->rcSource) + free(client->rcSource); + + client->rcSource = malloc(width * height * bytesPerPixel); + if (client->rcSource == NULL) + return FALSE; + + buf = malloc(bytesMaskData); + if (buf == NULL) { + free(client->rcSource); + client->rcSource = NULL; + return FALSE; + } + + /* Read and decode cursor pixel data, depending on the encoding type. */ + + if (enc == rfbEncodingXCursor) { + /* Read and convert background and foreground colors. */ + if (!ReadFromRFBServer(client, (char *)&rgb, sz_rfbXCursorColors)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); + colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); + + /* Read 1bpp pixel data into a temporary buffer. */ + if (!ReadFromRFBServer(client, buf, bytesMaskData)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + /* Convert 1bpp data to byte-wide color indices. */ + ptr = client->rcSource; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + for (b = 7; b >= 0; b--) { + *ptr = buf[y * bytesPerRow + x] >> b & 1; + ptr += bytesPerPixel; + } + } + for (b = 7; b > 7 - width % 8; b--) { + *ptr = buf[y * bytesPerRow + x] >> b & 1; + ptr += bytesPerPixel; + } + } + + /* Convert indices into the actual pixel values. */ + switch (bytesPerPixel) { + case 1: + for (x = 0; x < width * height; x++) + client->rcSource[x] = (uint8_t)colors[client->rcSource[x]]; + break; + case 2: + for (x = 0; x < width * height; x++) + ((uint16_t *)client->rcSource)[x] = (uint16_t)colors[client->rcSource[x * 2]]; + break; + case 4: + for (x = 0; x < width * height; x++) + ((uint32_t *)client->rcSource)[x] = colors[client->rcSource[x * 4]]; + break; + } + + } else { /* enc == rfbEncodingRichCursor */ + + if (!ReadFromRFBServer(client, (char *)client->rcSource, width * height * bytesPerPixel)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + } + + /* Read and decode mask data. */ + + if (!ReadFromRFBServer(client, buf, bytesMaskData)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + client->rcMask = malloc(width * height); + if (client->rcMask == NULL) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + ptr = client->rcMask; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + for (b = 7; b >= 0; b--) { + *ptr++ = buf[y * bytesPerRow + x] >> b & 1; + } + } + for (b = 7; b > 7 - width % 8; b--) { + *ptr++ = buf[y * bytesPerRow + x] >> b & 1; + } + } + + if (client->GotCursorShape != NULL) { + client->GotCursorShape(client, xhot, yhot, width, height, bytesPerPixel); + } + + free(buf); + + return TRUE; +} + + diff --git a/3rdParty/LibVNC/src/libvncclient/hextile.c b/3rdParty/LibVNC/src/libvncclient/hextile.c new file mode 100644 index 0000000..8698445 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/hextile.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * hextile.c - handle hextile encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles a hextile + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleHextileBPP CONCAT2E(HandleHextile,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleHextileBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + CARDBPP bg, fg; + int i; + uint8_t *ptr; + int x, y, w, h; + int sx, sy, sw, sh; + uint8_t subencoding; + uint8_t nSubrects; + + for (y = ry; y < ry+rh; y += 16) { + for (x = rx; x < rx+rw; x += 16) { + w = h = 16; + if (rx+rw - x < 16) + w = rx+rw - x; + if (ry+rh - y < 16) + h = ry+rh - y; + + if (!ReadFromRFBServer(client, (char *)&subencoding, 1)) + return FALSE; + + if (subencoding & rfbHextileRaw) { + if (!ReadFromRFBServer(client, client->buffer, w * h * (BPP / 8))) + return FALSE; + + CopyRectangle(client, (uint8_t *)client->buffer, x, y, w, h); + + continue; + } + + if (subencoding & rfbHextileBackgroundSpecified) + if (!ReadFromRFBServer(client, (char *)&bg, sizeof(bg))) + return FALSE; + + FillRectangle(client, x, y, w, h, bg); + + if (subencoding & rfbHextileForegroundSpecified) + if (!ReadFromRFBServer(client, (char *)&fg, sizeof(fg))) + return FALSE; + + if (!(subencoding & rfbHextileAnySubrects)) { + continue; + } + + if (!ReadFromRFBServer(client, (char *)&nSubrects, 1)) + return FALSE; + + ptr = (uint8_t*)client->buffer; + + if (subencoding & rfbHextileSubrectsColoured) { + if (!ReadFromRFBServer(client, client->buffer, nSubrects * (2 + (BPP / 8)))) + return FALSE; + + for (i = 0; i < nSubrects; i++) { +#if BPP==8 + GET_PIXEL8(fg, ptr); +#elif BPP==16 + GET_PIXEL16(fg, ptr); +#elif BPP==32 + GET_PIXEL32(fg, ptr); +#else +#error "Invalid BPP" +#endif + sx = rfbHextileExtractX(*ptr); + sy = rfbHextileExtractY(*ptr); + ptr++; + sw = rfbHextileExtractW(*ptr); + sh = rfbHextileExtractH(*ptr); + ptr++; + + FillRectangle(client, x+sx, y+sy, sw, sh, fg); + } + + } else { + if (!ReadFromRFBServer(client, client->buffer, nSubrects * 2)) + return FALSE; + + for (i = 0; i < nSubrects; i++) { + sx = rfbHextileExtractX(*ptr); + sy = rfbHextileExtractY(*ptr); + ptr++; + sw = rfbHextileExtractW(*ptr); + sh = rfbHextileExtractH(*ptr); + ptr++; + + FillRectangle(client, x+sx, y+sy, sw, sh, fg); + } + } + } + } + + return TRUE; +} + +#undef CARDBPP diff --git a/3rdParty/LibVNC/src/libvncclient/listen.c b/3rdParty/LibVNC/src/libvncclient/listen.c new file mode 100644 index 0000000..637abb1 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/listen.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * listen.c - listen for incoming connections + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#ifdef __MINGW32__ +#define close closesocket +#include +#else +#include +#include +#endif +#include +#include + +/* + * listenForIncomingConnections() - listen for incoming connections from + * servers, and fork a new process to deal with each connection. + */ + +void +listenForIncomingConnections(rfbClient* client) +{ +#ifdef __MINGW32__ + /* FIXME */ + rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n"); + return; +#else + int listenSocket; + fd_set fds; + + client->listenSpecified = TRUE; + + listenSocket = ListenAtTcpPort(client->listenPort); + + if ((listenSocket < 0)) + return; + + rfbClientLog("%s -listen: Listening on port %d\n", + client->programName,client->listenPort); + rfbClientLog("%s -listen: Command line errors are not reported until " + "a connection comes in.\n", client->programName); + + while (TRUE) { + + /* reap any zombies */ + int status, pid; + while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0); + + /* TODO: callback for discard any events (like X11 events) */ + + FD_ZERO(&fds); + + FD_SET(listenSocket, &fds); + + select(listenSocket+1, &fds, NULL, NULL, NULL); + + if (FD_ISSET(listenSocket, &fds)) { + client->sock = AcceptTcpConnection(listenSocket); + if (client->sock < 0) + return; + if (!SetNonBlocking(client->sock)) + return; + + /* Now fork off a new process to deal with it... */ + + switch (fork()) { + + case -1: + rfbClientErr("fork\n"); + return; + + case 0: + /* child - return to caller */ + close(listenSocket); + return; + + default: + /* parent - go round and listen again */ + close(client->sock); + break; + } + } + } +#endif +} + + + +/* + * listenForIncomingConnectionsNoFork() - listen for incoming connections + * from servers, but DON'T fork, instead just wait timeout microseconds. + * If timeout is negative, block indefinitly. + * Returns 1 on success (there was an incoming connection on the listen socket + * and we accepted it successfully), -1 on error, 0 on timeout. + */ + +int +listenForIncomingConnectionsNoFork(rfbClient* client, int timeout) +{ + fd_set fds; + struct timeval to; + int r; + + to.tv_sec= timeout / 1000000; + to.tv_usec= timeout % 1000000; + + client->listenSpecified = TRUE; + + if (client->listenSock < 0) + { + client->listenSock = ListenAtTcpPort(client->listenPort); + + if (client->listenSock < 0) + return -1; + + rfbClientLog("%s -listennofork: Listening on port %d\n", + client->programName,client->listenPort); + rfbClientLog("%s -listennofork: Command line errors are not reported until " + "a connection comes in.\n", client->programName); + } + + FD_ZERO(&fds); + + FD_SET(client->listenSock, &fds); + + if (timeout < 0) + r = select(client->listenSock+1, &fds, NULL, NULL, NULL); + else + r = select(client->listenSock+1, &fds, NULL, NULL, &to); + + if (r > 0) + { + client->sock = AcceptTcpConnection(client->listenSock); + if (client->sock < 0) + return -1; + if (!SetNonBlocking(client->sock)) + return -1; + + close(client->listenSock); + return r; + } + + /* r is now either 0 (timeout) or -1 (error) */ + return r; +} + + diff --git a/3rdParty/LibVNC/src/libvncclient/lzoconf.h b/3rdParty/LibVNC/src/libvncclient/lzoconf.h new file mode 100644 index 0000000..96db180 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/lzoconf.h @@ -0,0 +1,451 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H +#define __LZOCONF_H + +#define LZO_VERSION 0x1080 +#define LZO_VERSION_STRING "1.08" +#define LZO_VERSION_DATE "Jul 12 2002" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* workaround a cpp bug under hpux 10.20 */ +#define LZO_0xffffffffL 4294967295ul + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) c ## U +# endif +#endif + + +/*********************************************************************** +// architecture defines +************************************************************************/ + +#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2) +# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# define __LZO_WIN +# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) +# define __LZO_WIN +# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__) +# define __LZO_WIN +# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS) +# define __LZO_DOS +# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2) +# define __LZO_OS2 +# elif defined(__palmos__) +# define __LZO_PALMOS +# elif defined(__TOS__) || defined(__atarist__) +# define __LZO_TOS +# endif +#endif + +#if (UINT_MAX < LZO_0xffffffffL) +# if defined(__LZO_WIN) +# define __LZO_WIN16 +# elif defined(__LZO_DOS) +# define __LZO_DOS16 +# elif defined(__LZO_PALMOS) +# define __LZO_PALMOS16 +# elif defined(__LZO_TOS) +# define __LZO_TOS16 +# elif defined(__C166__) +# else + /* porting hint: for pure 16-bit architectures try compiling + * everything with -D__LZO_STRICT_16BIT */ +# error "16-bit target not supported - contact me for porting hints" +# endif +#endif + +#if !defined(__LZO_i386) +# if defined(__LZO_DOS) || defined(__LZO_WIN16) +# define __LZO_i386 +# elif defined(__i386__) || defined(__386__) || defined(_M_IX86) +# define __LZO_i386 +# endif +#endif + +#if defined(__LZO_STRICT_16BIT) +# if (UINT_MAX < LZO_0xffffffffL) +# include +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER +# elif defined(__CHECKER__) +# define __LZO_CHECKER +# elif defined(__INSURE__) +# define __LZO_CHECKER +# elif defined(__PURIFY__) +# define __LZO_CHECKER +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* Integral types with 32 bits or more */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* lzo_uint is used like size_t */ +#if !defined(LZO_UINT_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +typedef int lzo_bool; + + +/*********************************************************************** +// memory models +************************************************************************/ + +/* Memory model for the public code segment. */ +#if !defined(__LZO_CMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CMODEL __near +# else +# define __LZO_CMODEL +# endif +#endif + +/* Memory model for the public data segment. */ +#if !defined(__LZO_DMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_DMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_DMODEL __near +# else +# define __LZO_DMODEL +# endif +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_MMODEL __huge +# define LZO_999_UNSUPPORTED +# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16) +# define __LZO_MMODEL +# else +# error "__LZO_MMODEL" +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_byte unsigned char __LZO_MMODEL +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t sizeof(lzo_bytep) +#endif + + +/*********************************************************************** +// calling conventions and function types +************************************************************************/ + +/* linkage */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(_MSC_VER) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# else +# define __LZO_CDECL __LZO_CMODEL +# endif +#endif +#if !defined(__LZO_ENTRY) +# define __LZO_ENTRY __LZO_CDECL +#endif + +/* C++ exception specification for extern "C" function types */ +#if !defined(__cplusplus) +# undef LZO_NOTHROW +# define LZO_NOTHROW +#elif !defined(LZO_NOTHROW) +# define LZO_NOTHROW +#endif + + +typedef int +(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + +typedef int +(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + + +/* assembler versions always use __cdecl */ +typedef int +(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + + +/* a progress indicator callback function */ +typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); + + +/*********************************************************************** +// export information +************************************************************************/ + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* exported calling convention for C functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY +#endif + +/* exported __cdecl calling convention for assembler functions */ +#if !defined(LZO_PUBLIC_CDECL) +# define LZO_PUBLIC_CDECL(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN_CDECL) +# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype) +#endif + +/* exported global variables (LZO currently uses no static variables and + * is fully thread safe) */ +#if !defined(LZO_PUBLIC_VAR) +# define LZO_PUBLIC_VAR(_type) \ + __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL +#endif +#if !defined(LZO_EXTERN_VAR) +# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type) +#endif + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) + + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_compress_t)) +LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); + +/* misc. */ +LZO_EXTERN(lzo_bool) lzo_assert(int _expr); +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + +/* deprecated - only for backward compatibility */ +#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/3rdParty/LibVNC/src/libvncclient/minilzo.c b/3rdParty/LibVNC/src/libvncclient/minilzo.c new file mode 100644 index 0000000..85771eb --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/minilzo.c @@ -0,0 +1,2935 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#if !defined(LZO_NO_SYS_TYPES_H) +# include +#endif +#include + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +# ifndef __LZOCONF_H +# include +# endif +#endif + +#if defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(LZO_HAVE_CONFIG_H) +# include +# include +# if !defined(NO_STDLIB_H) +# include +# endif +# define HAVE_MEMCMP +# define HAVE_MEMCPY +# define HAVE_MEMMOVE +# define HAVE_MEMSET +#else +# include +# if defined(HAVE_STDDEF_H) +# include +# endif +# if defined(STDC_HEADERS) +# include +# include +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define HAVE_MALLOC_H +# define HAVE_HALLOC +#endif + +#undef NDEBUG +#if !defined(LZO_DEBUG) +# define NDEBUG +#endif +#if defined(LZO_DEBUG) || !defined(NDEBUG) +# if !defined(NO_STDIO_H) +# include +# endif +#endif +#include + +#if !defined(LZO_COMPILE_TIME_ASSERT) +# define LZO_COMPILE_TIME_ASSERT(expr) \ + { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; } +#endif + +#if !defined(LZO_UNUSED) +# if 1 +# define LZO_UNUSED(var) ((void)&var) +# elif 0 +# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; } +# else +# define LZO_UNUSED(parm) (parm = parm) +# endif +#endif + +#if !defined(__inline__) && !defined(__GNUC__) +# if defined(__cplusplus) +# define __inline__ inline +# else +# define __inline__ +# endif +#endif + +#if defined(NO_MEMCMP) +# undef HAVE_MEMCMP +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp lzo_memcmp +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy lzo_memcpy +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove lzo_memmove +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset lzo_memset +#endif + +#if 0 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2))) +#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1))) + +#if !defined(SIZEOF_UNSIGNED) +# if (UINT_MAX == 0xffff) +# define SIZEOF_UNSIGNED 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 4 +# elif (UINT_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 8 +# else +# error "SIZEOF_UNSIGNED" +# endif +#endif + +#if !defined(SIZEOF_UNSIGNED_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 4 +# elif (ULONG_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 8 +# else +# error "SIZEOF_UNSIGNED_LONG" +# endif +#endif + +#if !defined(SIZEOF_SIZE_T) +# define SIZEOF_SIZE_T SIZEOF_UNSIGNED +#endif +#if !defined(SIZE_T_MAX) +# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T) +#endif + +#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL) +# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff) +# define LZO_UNALIGNED_OK_2 +# endif +# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL) +# define LZO_UNALIGNED_OK_4 +# endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4) +# if !defined(LZO_UNALIGNED_OK) +# define LZO_UNALIGNED_OK +# endif +#endif + +#if defined(__LZO_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +#endif + +#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff) +# error "LZO_UNALIGNED_OK_2 must not be defined on this system" +#endif +#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_UNALIGNED_OK_4 must not be defined on this system" +#endif + +#if defined(__LZO_NO_ALIGNED) +# undef LZO_ALIGNED_OK_4 +#endif + +#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_ALIGNED_OK_4 must not be defined on this system" +#endif + +#define LZO_LITTLE_ENDIAN 1234 +#define LZO_BIG_ENDIAN 4321 +#define LZO_PDP_ENDIAN 3412 + +#if !defined(LZO_BYTE_ORDER) +# if defined(MFX_BYTE_ORDER) +# define LZO_BYTE_ORDER MFX_BYTE_ORDER +# elif defined(__LZO_i386) +# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN +# elif defined(BYTE_ORDER) +# define LZO_BYTE_ORDER BYTE_ORDER +# elif defined(__BYTE_ORDER) +# define LZO_BYTE_ORDER __BYTE_ORDER +# endif +#endif + +#if defined(LZO_BYTE_ORDER) +# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \ + (LZO_BYTE_ORDER != LZO_BIG_ENDIAN) +# error "invalid LZO_BYTE_ORDER" +# endif +#endif + +#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER) +# error "LZO_BYTE_ORDER is not defined" +#endif + +#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY + +#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER) +# if defined(__GNUC__) && defined(__i386__) +# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY) +# define LZO_OPTIMIZE_GNUC_i386 +# endif +# endif +#endif + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const lzo_byte __lzo_copyright[]; +LZO_EXTERN(const lzo_byte *) lzo_copyright(void); +__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256]; + +#define _LZO_STRINGIZE(x) #x +#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x) + +#define _LZO_CONCAT2(a,b) a ## b +#define _LZO_CONCAT3(a,b,c) a ## b ## c +#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d +#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e + +#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b) +#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c) +#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) +#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) + +#if 0 + +#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#endif + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# include +# if 1 && defined(__WATCOMC__) +# include + __LZO_EXTERN_C unsigned char _HShift; +# define __LZO_HShift _HShift +# elif 1 && defined(_MSC_VER) + __LZO_EXTERN_C unsigned short __near _AHSHIFT; +# define __LZO_HShift ((unsigned) &_AHSHIFT) +# elif defined(__LZO_WIN16) +# define __LZO_HShift 3 +# else +# define __LZO_HShift 12 +# endif +# if !defined(_FP_SEG) && defined(FP_SEG) +# define _FP_SEG FP_SEG +# endif +# if !defined(_FP_OFF) && defined(FP_OFF) +# define _FP_OFF FP_OFF +# endif +#endif + +#if !defined(lzo_ptrdiff_t) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef ptrdiff_t lzo_ptrdiff_t; +# else + typedef long lzo_ptrdiff_t; +# endif +#endif + +#if !defined(__LZO_HAVE_PTR_T) +# if defined(lzo_ptr_t) +# define __LZO_HAVE_PTR_T +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) + typedef unsigned int lzo_ptr_t; + typedef int lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) + typedef unsigned short lzo_ptr_t; + typedef short lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) +# error "no suitable type for lzo_ptr_t" +# else + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0) +#else +#define PTR(a) ((lzo_ptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_ptrdiff_t a_lzo_ptrdiff_t; + lzo_ptr_t a_lzo_ptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#if !defined(lzo_moff_t) +#define lzo_moff_t lzo_uint +#endif + +#endif + +LZO_PUBLIC(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_ptr_t p; + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) + p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr)); +#else + p = PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ + lzo_ptr_t p, s, n; + + assert(size > 0); + + p = __lzo_ptr_linear(ptr); + s = (lzo_ptr_t) (size - 1); +#if 0 + assert((size & (size - 1)) == 0); + n = ((p + s) & ~s) - p; +#else + n = (((p + s) / size) * size) - p; +#endif + + assert((long)n >= 0); + assert(n <= s); + + return (unsigned)n; +} + +#ifndef __LZO_UTIL_H +#define __LZO_UTIL_H + +#ifndef __LZO_CONF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 && defined(HAVE_MEMCPY) +#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16) + +#define MEMCPY8_DS(dest,src,len) \ + memcpy(dest,src,len); \ + dest += len; \ + src += len + +#endif +#endif + +#if 0 && !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + len -= 8; \ + } while (len > 0); } + +#endif + +#if !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { register lzo_uint __l = (len) / 8; \ + do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + } while (--__l > 0); } + +#endif + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#define MEMMOVE_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#if 0 && defined(LZO_OPTIMIZE_GNUC_i386) + +#define BZERO8_PTR(s,l,n) \ +__asm__ __volatile__( \ + "movl %0,%%eax \n" \ + "movl %1,%%edi \n" \ + "movl %2,%%ecx \n" \ + "cld \n" \ + "rep \n" \ + "stosl %%eax,(%%edi) \n" \ + : \ + :"g" (0),"g" (s),"g" (n) \ + :"eax","edi","ecx", "memory", "cc" \ +) + +#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + +#if 1 +#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) +#else +#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) +#endif + +#else + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#endif + +#if 0 +#if defined(__GNUC__) && defined(__i386__) + +unsigned char lzo_rotr8(unsigned char value, int shift); +extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) +{ + unsigned char result; + + __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +unsigned short lzo_rotr16(unsigned short value, int shift); +extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) +{ + unsigned short result; + + __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +LZO_PUBLIC(lzo_bool) +lzo_assert(int expr) +{ + return (expr) ? 1 : 0; +} + +/* If you use the LZO library in a product, you *must* keep this + * copyright string in the executable of your product. + */ + +const lzo_byte __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\n\n\n" + "LZO real-time data compression library.\n" + "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com/opensource/lzo/\n" + "\n" + "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n" + "LZO build date: " __DATE__ " " __TIME__ "\n\n" + "LZO special compilation options:\n" +#ifdef __cplusplus + " __cplusplus\n" +#endif +#if defined(__PIC__) + " __PIC__\n" +#elif defined(__pic__) + " __pic__\n" +#endif +#if (UINT_MAX < LZO_0xffffffffL) + " 16BIT\n" +#endif +#if defined(__LZO_STRICT_16BIT) + " __LZO_STRICT_16BIT\n" +#endif +#if (UINT_MAX > LZO_0xffffffffL) + " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n" +#endif +#if (ULONG_MAX > LZO_0xffffffffL) + " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n" +#endif +#if defined(LZO_BYTE_ORDER) + " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n" +#endif +#if defined(LZO_UNALIGNED_OK_2) + " LZO_UNALIGNED_OK_2\n" +#endif +#if defined(LZO_UNALIGNED_OK_4) + " LZO_UNALIGNED_OK_4\n" +#endif +#if defined(LZO_ALIGNED_OK_4) + " LZO_ALIGNED_OK_4\n" +#endif +#if defined(LZO_DICT_USE_PTR) + " LZO_DICT_USE_PTR\n" +#endif +#if defined(__LZO_QUERY_COMPRESS) + " __LZO_QUERY_COMPRESS\n" +#endif +#if defined(__LZO_QUERY_DECOMPRESS) + " __LZO_QUERY_DECOMPRESS\n" +#endif +#if defined(__LZO_IN_MINILZO) + " __LZO_IN_MINILZO\n" +#endif + "\n\n" + "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ +#if defined(__GNUC__) && defined(__VERSION__) + " by gcc " __VERSION__ +#elif defined(__BORLANDC__) + " by Borland C " _LZO_MEXPAND(__BORLANDC__) +#elif defined(_MSC_VER) + " by Microsoft C " _LZO_MEXPAND(_MSC_VER) +#elif defined(__PUREC__) + " by Pure C " _LZO_MEXPAND(__PUREC__) +#elif defined(__SC__) + " by Symantec C " _LZO_MEXPAND(__SC__) +#elif defined(__TURBOC__) + " by Turbo C " _LZO_MEXPAND(__TURBOC__) +#elif defined(__WATCOMC__) + " by Watcom C " _LZO_MEXPAND(__WATCOMC__) +#endif + " $\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n"; +#endif + +LZO_PUBLIC(const lzo_byte *) +lzo_copyright(void) +{ + return __lzo_copyright; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (int) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +LZO_PUBLIC(int) +lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP) + return memcmp(s1,s2,len); +#else + const lzo_byte *p1 = (const lzo_byte *) s1; + const lzo_byte *p2 = (const lzo_byte *) s2; + int d; + + if (len > 0) do + { + d = *p1 - *p2; + if (d != 0) + return d; + p1++; + p2++; + } + while (--len > 0); + return 0; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY) + return memcpy(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + do + *p1++ = *p2++; + while (--len > 0); + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE) + return memmove(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + + if (p1 < p2) + { + do + *p1++ = *p2++; + while (--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while (--len > 0); + } + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memset(lzo_voidp s, int c, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + return memset(s,c,len); +#else + lzo_byte *p = (lzo_byte *) s; + + if (len > 0) do + *p++ = LZO_BYTE(c); + while (--len > 0); + return s; +#endif +} + +#if 0 +# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) +# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) +#else +# define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) +# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) +#endif + +#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +static lzo_bool schedule_insns_bug(void); +static lzo_bool strength_reduce_bug(int *); + +#if 0 || defined(LZO_DEBUG) +#include +static lzo_bool __lzo_assert_fail(const char *s, unsigned line) +{ +#if defined(__palmos__) + printf("LZO assertion failed in line %u: '%s'\n",line,s); +#else + fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); +#endif + return 0; +} +# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) +#else +# define __lzo_assert(x) ((x) ? 1 : 0) +#endif + +#undef COMPILE_TIME_ASSERT +#if 0 +# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr) +#else +# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif + +static lzo_bool basic_integral_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(CHAR_BIT == 8); + COMPILE_TIME_ASSERT(sizeof(char) == 1); + COMPILE_TIME_ASSERT(sizeof(short) >= 2); + COMPILE_TIME_ASSERT(sizeof(long) >= 4); + COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short)); + COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned)); +#if defined(__LZO_STRICT_16BIT) + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2); +#else + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned)); +#endif + +#if (USHRT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(short) == 2); +#elif (USHRT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) == 4); +#elif (USHRT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) > 4); +#endif +#if (UINT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(int) == 2); +#elif (UINT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) == 4); +#elif (UINT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) > 4); +#endif +#if (ULONG_MAX == 65535ul) + COMPILE_TIME_ASSERT(sizeof(long) == 2); +#elif (ULONG_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) == 4); +#elif (ULONG_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) > 4); +#endif + +#if defined(SIZEOF_UNSIGNED) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned)); +#endif +#if defined(SIZEOF_UNSIGNED_LONG) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); +#endif +#if defined(SIZEOF_UNSIGNED_SHORT) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); +#endif +#if !defined(__LZO_IN_MINILZO) +#if defined(SIZEOF_SIZE_T) + COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t)); +#endif +#endif + + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long)); + COMPILE_TIME_ASSERT(IS_SIGNED(short)); + COMPILE_TIME_ASSERT(IS_SIGNED(int)); + COMPILE_TIME_ASSERT(IS_SIGNED(long)); + + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int)); + + COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int))); + COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); + COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); + COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); + COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); + COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); + COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32))); + COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); +#if !defined(__LZO_IN_MINILZO) + COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); +#endif + + r &= __lzo_assert(LZO_BYTE(257) == 1); + + return r; +} + +static lzo_bool basic_ptr_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int)); + COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *)); + + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); + + COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint)); + +#if defined(SIZEOF_CHAR_P) + COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *)); +#endif +#if defined(SIZEOF_PTRDIFF_T) + COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); +#endif + + COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t)); + + return r; +} + +static lzo_bool ptr_check(void) +{ + lzo_bool r = 1; + int i; + char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)]; + lzo_bytep wrkmem; + lzo_bytepp dict; + unsigned char x[4 * sizeof(lzo_full_align_t)]; + long d; + lzo_full_align_t a; + lzo_full_align_t u; + + for (i = 0; i < (int) sizeof(x); i++) + x[i] = LZO_BYTE(i); + + wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t)); + +#if 0 + dict = (lzo_bytepp) wrkmem; +#else + + u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp; +#endif + + d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem); + r &= __lzo_assert(d >= 0); + r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t)); + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_lzo_voidp == NULL); + + memset(&a,0xff,sizeof(a)); + r &= __lzo_assert(a.a_ushort == USHRT_MAX); + r &= __lzo_assert(a.a_uint == UINT_MAX); + r &= __lzo_assert(a.a_ulong == ULONG_MAX); + r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); + r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX); + + if (r == 1) + { + for (i = 0; i < 8; i++) + r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)])); + } + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_char_p == NULL); + r &= __lzo_assert(a.a_lzo_bytep == NULL); + r &= __lzo_assert(NULL == (void *)0); + if (r == 1) + { + for (i = 0; i < 10; i++) + dict[i] = wrkmem; + BZERO8_PTR(dict+1,sizeof(dict[0]),8); + r &= __lzo_assert(dict[0] == wrkmem); + for (i = 1; i < 9; i++) + r &= __lzo_assert(dict[i] == NULL); + r &= __lzo_assert(dict[9] == wrkmem); + } + + if (r == 1) + { + unsigned k = 1; + const unsigned n = (unsigned) sizeof(lzo_uint32); + lzo_byte *p0; + lzo_byte *p1; + + k += __lzo_align_gap(&x[k],n); + p0 = (lzo_bytep) &x[k]; +#if defined(PTR_LINEAR) + r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0); +#else + r &= __lzo_assert(n == 4); + r &= __lzo_assert(PTR_ALIGNED_4(p0)); +#endif + + r &= __lzo_assert(k >= 1); + p1 = (lzo_bytep) &x[1]; + r &= __lzo_assert(PTR_GE(p0,p1)); + + r &= __lzo_assert(k < 1+n); + p1 = (lzo_bytep) &x[1+n]; + r &= __lzo_assert(PTR_LT(p0,p1)); + + if (r == 1) + { + lzo_uint32 v0, v1; +#if 0 + v0 = * (lzo_uint32 *) &x[k]; + v1 = * (lzo_uint32 *) &x[k+n]; +#else + + u.a_uchar_p = &x[k]; + v0 = *u.a_lzo_uint32_p; + u.a_uchar_p = &x[k+n]; + v1 = *u.a_lzo_uint32_p; +#endif + r &= __lzo_assert(v0 > 0); + r &= __lzo_assert(v1 > 0); + } + } + + return r; +} + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + int i; + union { + lzo_uint32 a; + unsigned short b; + lzo_uint32 aa[4]; + unsigned char x[4*sizeof(lzo_full_align_t)]; + } u; + + COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255); + COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0); + +#if 0 + r &= __lzo_assert((const void *)&u == (const void *)&u.a); + r &= __lzo_assert((const void *)&u == (const void *)&u.b); + r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]); + r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]); +#endif + + r &= basic_integral_check(); + r &= basic_ptr_check(); + if (r != 1) + return LZO_E_ERROR; + + u.a = 0; u.b = 0; + for (i = 0; i < (int) sizeof(u.x); i++) + u.x[i] = LZO_BYTE(i); + +#if defined(LZO_BYTE_ORDER) + if (r == 1) + { +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); + unsigned short b = (unsigned short) (u.b & 0xffff); + r &= __lzo_assert(a == 0x03020100L); + r &= __lzo_assert(b == 0x0100); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); + unsigned short b = u.b >> (8 * sizeof(u.b) - 16); + r &= __lzo_assert(a == 0x00010203L); + r &= __lzo_assert(b == 0x0001); +# else +# error "invalid LZO_BYTE_ORDER" +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_2) + COMPILE_TIME_ASSERT(sizeof(short) == 2); + if (r == 1) + { + unsigned short b[4]; + + for (i = 0; i < 4; i++) + b[i] = * (const unsigned short *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(b[0] == 0x0100); + r &= __lzo_assert(b[1] == 0x0201); + r &= __lzo_assert(b[2] == 0x0302); + r &= __lzo_assert(b[3] == 0x0403); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(b[0] == 0x0001); + r &= __lzo_assert(b[1] == 0x0102); + r &= __lzo_assert(b[2] == 0x0203); + r &= __lzo_assert(b[3] == 0x0304); +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); + if (r == 1) + { + lzo_uint32 a[4]; + + for (i = 0; i < 4; i++) + a[i] = * (const lzo_uint32 *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(a[0] == 0x03020100L); + r &= __lzo_assert(a[1] == 0x04030201L); + r &= __lzo_assert(a[2] == 0x05040302L); + r &= __lzo_assert(a[3] == 0x06050403L); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(a[0] == 0x00010203L); + r &= __lzo_assert(a[1] == 0x01020304L); + r &= __lzo_assert(a[2] == 0x02030405L); + r &= __lzo_assert(a[3] == 0x03040506L); +# endif + } +#endif + +#if defined(LZO_ALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); +#endif + + COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); + +#if defined(__LZO_IN_MINLZO) + if (r == 1) + { + lzo_uint32 adler; + adler = lzo_adler32(0, NULL, 0); + adler = lzo_adler32(adler, lzo_copyright(), 200); + r &= __lzo_assert(adler == 0xc76f1751L); + } +#endif + + if (r == 1) + { + r &= __lzo_assert(!schedule_insns_bug()); + } + + if (r == 1) + { + static int x[3]; + static unsigned xn = 3; + register unsigned j; + + for (j = 0; j < xn; j++) + x[j] = (int)j - 3; + r &= __lzo_assert(!strength_reduce_bug(x)); + } + + if (r == 1) + { + r &= ptr_check(); + } + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +static lzo_bool schedule_insns_bug(void) +{ +#if defined(__LZO_CHECKER) + return 0; +#else + const int clone[] = {1, 2, 0}; + const int *q; + q = clone; + return (*q) ? 0 : 1; +#endif +} + +static lzo_bool strength_reduce_bug(int *x) +{ + return x[0] != -3 || x[1] != -2 || x[2] != -1; +} + +#undef COMPILE_TIME_ASSERT + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_compress_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +LZO_EXTERN(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7); + +LZO_PUBLIC(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7) +{ + if (v == 0 || v > 0x1010) + return LZO_E_ERROR; + return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7); +} + +#endif + +#define do_compress _lzo1x_1_do_compress + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_uint32)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_uint32)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) +{ + lzo_uint32 df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR( \ + (PTR_LT(m_pos,in) || \ + (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset) )) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + ((lzo_moff_t) ((ip)-(in)) <= m_off || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static +lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *ip __asm__("%esi"); +#else + register const lzo_byte *ip; +#endif + lzo_byte *op; + const lzo_byte * const in_end = in + in_len; + const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_byte *ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *m_pos __asm__("%edi"); +#else + register const lzo_byte *m_pos; +#endif + lzo_moff_t m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if (m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if (ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = ip - ii; + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_byte *end = in_end; + const lzo_byte *m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = (ip - ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if (ip >= ip_end) + break; + } + + *out_len = op - out; + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_byte *op = out; + lzo_uint t; + +#if defined(__LZO_QUERY_COMPRESS) + if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t)); +#endif + + if (in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_byte *ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_DECOMPRESS_OVERRUN +#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#define LZO_TEST_DECOMPRESS_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +/***** End of minilzo.c *****/ + diff --git a/3rdParty/LibVNC/src/libvncclient/minilzo.h b/3rdParty/LibVNC/src/libvncclient/minilzo.h new file mode 100644 index 0000000..e3270f9 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/minilzo.h @@ -0,0 +1,100 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x1080 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/3rdParty/LibVNC/src/libvncclient/rfbproto.c b/3rdParty/LibVNC/src/libvncclient/rfbproto.c new file mode 100644 index 0000000..33307d2 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/rfbproto.c @@ -0,0 +1,2123 @@ +/* + * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * rfbproto.c - functions to deal with client side of RFB protocol. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#endif +#ifndef WIN32 +#include +#include +#include +#else +#define strncasecmp _strnicmp +#endif +#include +#ifndef WIN32 +#include +#endif +#include +#ifdef LIBVNCSERVER_HAVE_LIBZ +#include +#ifdef __CHECKER__ +#undef Z_NULL +#define Z_NULL NULL +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +#include +#endif +#include +#include + +#include "minilzo.h" +#include "tls.h" + +/* + * rfbClientLog prints a time-stamped message to the log file (stderr). + */ + +rfbBool rfbEnableClientLogging=TRUE; + +static void +rfbDefaultClientLog(const char *format, ...) +{ + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableClientLogging) + return; + + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock)); + fprintf(stderr, "%s", buf); + + vfprintf(stderr, format, args); + fflush(stderr); + + va_end(args); +} + +rfbClientLogProc rfbClientLog=rfbDefaultClientLog; +rfbClientLogProc rfbClientErr=rfbDefaultClientLog; + +/* extensions */ + +rfbClientProtocolExtension* rfbClientExtensions = NULL; + +void rfbClientRegisterExtension(rfbClientProtocolExtension* e) +{ + e->next = rfbClientExtensions; + rfbClientExtensions = e; +} + +/* client data */ + +void rfbClientSetClientData(rfbClient* client, void* tag, void* data) +{ + rfbClientData* clientData = client->clientData; + + while(clientData && clientData->tag != tag) + clientData = clientData->next; + if(clientData == NULL) { + clientData = calloc(sizeof(rfbClientData), 1); + clientData->next = client->clientData; + client->clientData = clientData; + clientData->tag = tag; + } + + clientData->data = data; +} + +void* rfbClientGetClientData(rfbClient* client, void* tag) +{ + rfbClientData* clientData = client->clientData; + + while(clientData) { + if(clientData->tag == tag) + return clientData->data; + clientData = clientData->next; + } + + return NULL; +} + +/* messages */ + +static void FillRectangle(rfbClient* client, int x, int y, int w, int h, uint32_t colour) { + int i,j; + +#define FILL_RECT(BPP) \ + for(j=y*client->width;j<(y+h)*client->width;j+=client->width) \ + for(i=x;iframeBuffer)[j+i]=colour; + + switch(client->format.bitsPerPixel) { + case 8: FILL_RECT(8); break; + case 16: FILL_RECT(16); break; + case 32: FILL_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +static void CopyRectangle(rfbClient* client, uint8_t* buffer, int x, int y, int w, int h) { + int j; + +#define COPY_RECT(BPP) \ + { \ + int rs = w * BPP / 8, rs2 = client->width * BPP / 8; \ + for (j = ((x * (BPP / 8)) + (y * rs2)); j < (y + h) * rs2; j += rs2) { \ + memcpy(client->frameBuffer + j, buffer, rs); \ + buffer += rs; \ + } \ + } + + switch(client->format.bitsPerPixel) { + case 8: COPY_RECT(8); break; + case 16: COPY_RECT(16); break; + case 32: COPY_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +/* TODO: test */ +static void CopyRectangleFromRectangle(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { + int i,j; + +#define COPY_RECT_FROM_RECT(BPP) \ + { \ + uint##BPP##_t* _buffer=((uint##BPP##_t*)client->frameBuffer)+(src_y-dest_y)*client->width+src_x-dest_x; \ + if (dest_y < src_y) { \ + for(j = dest_y*client->width; j < (dest_y+h)*client->width; j += client->width) { \ + if (dest_x < src_x) { \ + for(i = dest_x; i < dest_x+w; i++) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } else { \ + for(i = dest_x+w-1; i >= dest_x; i--) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } \ + } \ + } else { \ + for(j = (dest_y+h-1)*client->width; j >= dest_y*client->width; j-=client->width) { \ + if (dest_x < src_x) { \ + for(i = dest_x; i < dest_x+w; i++) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } else { \ + for(i = dest_x+w-1; i >= dest_x; i--) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } \ + } \ + } \ + } + + switch(client->format.bitsPerPixel) { + case 8: COPY_RECT_FROM_RECT(8); break; + case 16: COPY_RECT_FROM_RECT(16); break; + case 32: COPY_RECT_FROM_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +static rfbBool HandleRRE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleRRE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleRRE32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip32(rfbClient* client, int rx, int ry, int rw, int rh); +#ifdef LIBVNCSERVER_HAVE_LIBZ +static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZlib32(rfbClient* client, int rx, int ry, int rw, int rh); +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +static rfbBool HandleTight8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTight16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTight32(rfbClient* client, int rx, int ry, int rw, int rh); + +static long ReadCompactLen (rfbClient* client); + +static void JpegInitSource(j_decompress_ptr cinfo); +static boolean JpegFillInputBuffer(j_decompress_ptr cinfo); +static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes); +static void JpegTermSource(j_decompress_ptr cinfo); +static void JpegSetSrcManager(j_decompress_ptr cinfo, uint8_t *compressedData, + int compressedLen); +#endif +static rfbBool HandleZRLE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE15(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24Up(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24Down(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE32(rfbClient* client, int rx, int ry, int rw, int rh); +#endif + +/* + * Server Capability Functions + */ +rfbBool +SupportsClient2Server(rfbClient* client, int messageType) +{ + return (client->supportedMessages.client2server[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE); +} + +rfbBool +SupportsServer2Client(rfbClient* client, int messageType) +{ + return (client->supportedMessages.server2client[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE); +} + +void +SetClient2Server(rfbClient* client, int messageType) +{ + client->supportedMessages.client2server[((messageType & 0xFF)/8)] |= (1<<(messageType % 8)); +} + +void +SetServer2Client(rfbClient* client, int messageType) +{ + client->supportedMessages.server2client[((messageType & 0xFF)/8)] |= (1<<(messageType % 8)); +} + +void +ClearClient2Server(rfbClient* client, int messageType) +{ + client->supportedMessages.client2server[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8))); +} + +void +ClearServer2Client(rfbClient* client, int messageType) +{ + client->supportedMessages.server2client[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8))); +} + + +void +DefaultSupportedMessages(rfbClient* client) +{ + memset((char *)&client->supportedMessages,0,sizeof(client->supportedMessages)); + + /* Default client supported messages (universal RFB 3.3 protocol) */ + SetClient2Server(client, rfbSetPixelFormat); + /* SetClient2Server(client, rfbFixColourMapEntries); Not currently supported */ + SetClient2Server(client, rfbSetEncodings); + SetClient2Server(client, rfbFramebufferUpdateRequest); + SetClient2Server(client, rfbKeyEvent); + SetClient2Server(client, rfbPointerEvent); + SetClient2Server(client, rfbClientCutText); + /* technically, we only care what we can *send* to the server + * but, we set Server2Client Just in case it ever becomes useful + */ + SetServer2Client(client, rfbFramebufferUpdate); + SetServer2Client(client, rfbSetColourMapEntries); + SetServer2Client(client, rfbBell); + SetServer2Client(client, rfbServerCutText); +} + +void +DefaultSupportedMessagesUltraVNC(rfbClient* client) +{ + DefaultSupportedMessages(client); + SetClient2Server(client, rfbFileTransfer); + SetClient2Server(client, rfbSetScale); + SetClient2Server(client, rfbSetServerInput); + SetClient2Server(client, rfbSetSW); + SetClient2Server(client, rfbTextChat); + SetClient2Server(client, rfbPalmVNCSetScaleFactor); + /* technically, we only care what we can *send* to the server */ + SetServer2Client(client, rfbResizeFrameBuffer); + SetServer2Client(client, rfbPalmVNCReSizeFrameBuffer); + SetServer2Client(client, rfbFileTransfer); + SetServer2Client(client, rfbTextChat); +} + + +void +DefaultSupportedMessagesTightVNC(rfbClient* client) +{ + DefaultSupportedMessages(client); + SetClient2Server(client, rfbFileTransfer); + SetClient2Server(client, rfbSetServerInput); + SetClient2Server(client, rfbSetSW); + /* SetClient2Server(client, rfbTextChat); */ + /* technically, we only care what we can *send* to the server */ + SetServer2Client(client, rfbFileTransfer); + SetServer2Client(client, rfbTextChat); +} + +#ifndef WIN32 +static rfbBool +IsUnixSocket(const char *name) +{ + struct stat sb; + if(stat(name, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFSOCK) + return TRUE; + return FALSE; +} +#endif + +/* + * ConnectToRFBServer. + */ + +rfbBool +ConnectToRFBServer(rfbClient* client,const char *hostname, int port) +{ + unsigned int host; + + if (client->serverPort==-1) { + /* serverHost is a file recorded by vncrec. */ + const char* magic="vncLog0.0"; + char buffer[10]; + rfbVNCRec* rec = (rfbVNCRec*)malloc(sizeof(rfbVNCRec)); + client->vncRec = rec; + + rec->file = fopen(client->serverHost,"rb"); + rec->tv.tv_sec = 0; + rec->readTimestamp = FALSE; + rec->doNotSleep = FALSE; + + if (!rec->file) { + rfbClientLog("Could not open %s.\n",client->serverHost); + return FALSE; + } + setbuf(rec->file,NULL); + fread(buffer,1,strlen(magic),rec->file); + if (strncmp(buffer,magic,strlen(magic))) { + rfbClientLog("File %s was not recorded by vncrec.\n",client->serverHost); + fclose(rec->file); + return FALSE; + } + client->sock = -1; + return TRUE; + } + +#ifndef WIN32 + if(IsUnixSocket(hostname)) + /* serverHost is a UNIX socket. */ + client->sock = ConnectClientToUnixSock(hostname); + else +#endif + { + /* serverHost is a hostname */ + if (!StringToIPAddr(hostname, &host)) { + rfbClientLog("Couldn't convert '%s' to host address\n", hostname); + return FALSE; + } + client->sock = ConnectClientToTcpAddr(host, port); + } + + if (client->sock < 0) { + rfbClientLog("Unable to connect to VNC server\n"); + return FALSE; + } + + return SetNonBlocking(client->sock); +} + +/* + * ConnectToRFBRepeater. + */ + +rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort) +{ + unsigned int host; + rfbProtocolVersionMsg pv; + int major,minor; + char tmphost[250]; + + if (!StringToIPAddr(repeaterHost, &host)) { + rfbClientLog("Couldn't convert '%s' to host address\n", repeaterHost); + return FALSE; + } + + client->sock = ConnectClientToTcpAddr(host, repeaterPort); + + if (client->sock < 0) { + rfbClientLog("Unable to connect to VNC repeater\n"); + return FALSE; + } + + if (!SetNonBlocking(client->sock)) + return FALSE; + + if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) + return FALSE; + pv[sz_rfbProtocolVersionMsg] = 0; + + /* UltraVNC repeater always report version 000.000 to identify itself */ + if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2 || major != 0 || minor != 0) { + rfbClientLog("Not a valid VNC repeater (%s)\n",pv); + return FALSE; + } + + rfbClientLog("Connected to VNC repeater, using protocol version %d.%d\n", major, minor); + + snprintf(tmphost, sizeof(tmphost), "%s:%d", destHost, destPort); + if (!WriteToRFBServer(client, tmphost, sizeof(tmphost))) + return FALSE; + + return TRUE; +} + +extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd); +extern void rfbClientEncryptBytes2(unsigned char *where, const int length, unsigned char *key); + +rfbBool +rfbHandleAuthResult(rfbClient* client) +{ + uint32_t authResult=0, reasonLen=0; + char *reason=NULL; + + if (!ReadFromRFBServer(client, (char *)&authResult, 4)) return FALSE; + + authResult = rfbClientSwap32IfLE(authResult); + + switch (authResult) { + case rfbVncAuthOK: + rfbClientLog("VNC authentication succeeded\n"); + return TRUE; + break; + case rfbVncAuthFailed: + if (client->major==3 && client->minor>7) + { + /* we have an error following */ + if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE; + reasonLen = rfbClientSwap32IfLE(reasonLen); + reason = malloc(reasonLen+1); + if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; } + reason[reasonLen]=0; + rfbClientLog("VNC connection failed: %s\n",reason); + free(reason); + return FALSE; + } + rfbClientLog("VNC authentication failed\n"); + return FALSE; + case rfbVncAuthTooMany: + rfbClientLog("VNC authentication failed - too many tries\n"); + return FALSE; + } + + rfbClientLog("Unknown VNC authentication result: %d\n", + (int)authResult); + return FALSE; +} + +static void +ReadReason(rfbClient* client) +{ + uint32_t reasonLen; + char *reason; + + /* we have an error following */ + if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return; + reasonLen = rfbClientSwap32IfLE(reasonLen); + reason = malloc(reasonLen+1); + if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return; } + reason[reasonLen]=0; + rfbClientLog("VNC connection failed: %s\n",reason); + free(reason); +} + +static rfbBool +ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth) +{ + uint8_t count=0; + uint8_t loop=0; + uint8_t flag=0; + uint8_t tAuth[256]; + char buf1[500],buf2[10]; + uint32_t authScheme; + + if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; + + if (count==0) + { + rfbClientLog("List of security types is ZERO, expecting an error to follow\n"); + ReadReason(client); + return FALSE; + } + if (count>sizeof(tAuth)) + { + rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth)); + return FALSE; + } + + rfbClientLog("We have %d security types to read\n", count); + authScheme=0; + /* now, we have a list of available security types to read ( uint8_t[] ) */ + for (loop=0;loopclientAuthSchemes) + { + int i; + for (i=0;client->clientAuthSchemes[i];i++) + { + if (client->clientAuthSchemes[i]==(uint32_t)tAuth[loop]) + { + flag++; + authScheme=tAuth[loop]; + break; + } + } + } + else + { + flag++; + authScheme=tAuth[loop]; + } + if (flag) + { + rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count); + /* send back a single byte indicating which security type to use */ + if (!WriteToRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE; + } + } + } + if (authScheme==0) + { + memset(buf1, 0, sizeof(buf1)); + for (loop=0;loop=sizeof(buf1)-1) break; + snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]); + strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1); + } + rfbClientLog("Unknown authentication scheme from VNC server: %s\n", + buf1); + return FALSE; + } + *result = authScheme; + return TRUE; +} + +static rfbBool +HandleVncAuth(rfbClient *client) +{ + uint8_t challenge[CHALLENGESIZE]; + char *passwd=NULL; + int i; + + if (!ReadFromRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE; + + if (client->serverPort!=-1) { /* if not playing a vncrec file */ + if (client->GetPassword) + passwd = client->GetPassword(client); + + if ((!passwd) || (strlen(passwd) == 0)) { + rfbClientLog("Reading password failed\n"); + return FALSE; + } + if (strlen(passwd) > 8) { + passwd[8] = '\0'; + } + + rfbClientEncryptBytes(challenge, passwd); + + /* Lose the password from memory */ + for (i = strlen(passwd); i >= 0; i--) { + passwd[i] = '\0'; + } + free(passwd); + + if (!WriteToRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE; + } + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +static void +FreeUserCredential(rfbCredential *cred) +{ + if (cred->userCredential.username) free(cred->userCredential.username); + if (cred->userCredential.password) free(cred->userCredential.password); + free(cred); +} + +static rfbBool +HandlePlainAuth(rfbClient *client) +{ + uint32_t ulen, ulensw; + uint32_t plen, plensw; + rfbCredential *cred; + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + cred = client->GetCredential(client, rfbCredentialTypeUser); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + ulen = (cred->userCredential.username ? strlen(cred->userCredential.username) : 0); + ulensw = rfbClientSwap32IfLE(ulen); + plen = (cred->userCredential.password ? strlen(cred->userCredential.password) : 0); + plensw = rfbClientSwap32IfLE(plen); + if (!WriteToRFBServer(client, (char *)&ulensw, 4) || + !WriteToRFBServer(client, (char *)&plensw, 4)) + { + FreeUserCredential(cred); + return FALSE; + } + if (ulen > 0) + { + if (!WriteToRFBServer(client, cred->userCredential.username, ulen)) + { + FreeUserCredential(cred); + return FALSE; + } + } + if (plen > 0) + { + if (!WriteToRFBServer(client, cred->userCredential.password, plen)) + { + FreeUserCredential(cred); + return FALSE; + } + } + + FreeUserCredential(cred); + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +/* Simple 64bit big integer arithmetic implementation */ +/* (x + y) % m, works even if (x + y) > 64bit */ +#define rfbAddM64(x,y,m) ((x+y)%m+(x+y0;x>>=1) + { + if (x&1) r=rfbAddM64(r,y,m); + y=rfbAddM64(y,y,m); + } + return r; +} +/* (x ^ y) % m */ +static uint64_t +rfbPowM64(uint64_t b, uint64_t e, uint64_t m) +{ + uint64_t r; + for(r=1;e>0;e>>=1) + { + if(e&1) r=rfbMulM64(r,b,m); + b=rfbMulM64(b,b,m); + } + return r; +} + +static rfbBool +HandleMSLogonAuth(rfbClient *client) +{ + uint64_t gen, mod, resp, priv, pub, key; + uint8_t username[256], password[64]; + rfbCredential *cred; + + if (!ReadFromRFBServer(client, (char *)&gen, 8)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&mod, 8)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&resp, 8)) return FALSE; + gen = rfbClientSwap64IfLE(gen); + mod = rfbClientSwap64IfLE(mod); + resp = rfbClientSwap64IfLE(resp); + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + rfbClientLog("WARNING! MSLogon security type has very low password encryption! "\ + "Use it only with SSH tunnel or trusted network.\n"); + cred = client->GetCredential(client, rfbCredentialTypeUser); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + memset(username, 0, sizeof(username)); + strncpy((char *)username, cred->userCredential.username, sizeof(username)); + memset(password, 0, sizeof(password)); + strncpy((char *)password, cred->userCredential.password, sizeof(password)); + FreeUserCredential(cred); + + srand(time(NULL)); + priv = ((uint64_t)rand())<<32; + priv |= (uint64_t)rand(); + + pub = rfbPowM64(gen, priv, mod); + key = rfbPowM64(resp, priv, mod); + pub = rfbClientSwap64IfLE(pub); + key = rfbClientSwap64IfLE(key); + + rfbClientEncryptBytes2(username, sizeof(username), (unsigned char *)&key); + rfbClientEncryptBytes2(password, sizeof(password), (unsigned char *)&key); + + if (!WriteToRFBServer(client, (char *)&pub, 8)) return FALSE; + if (!WriteToRFBServer(client, (char *)username, sizeof(username))) return FALSE; + if (!WriteToRFBServer(client, (char *)password, sizeof(password))) return FALSE; + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +/* + * SetClientAuthSchemes. + */ + +void +SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size) +{ + int i; + + if (client->clientAuthSchemes) + { + free(client->clientAuthSchemes); + client->clientAuthSchemes = NULL; + } + if (authSchemes) + { + if (size<0) + { + /* If size<0 we assume the passed-in list is also 0-terminate, so we + * calculate the size here */ + for (size=0;authSchemes[size];size++) ; + } + client->clientAuthSchemes = (uint32_t*)malloc(sizeof(uint32_t)*(size+1)); + for (i=0;iclientAuthSchemes[i] = authSchemes[i]; + client->clientAuthSchemes[size] = 0; + } +} + +/* + * InitialiseRFBConnection. + */ + +rfbBool +InitialiseRFBConnection(rfbClient* client) +{ + rfbProtocolVersionMsg pv; + int major,minor; + uint32_t authScheme; + uint32_t subAuthScheme; + rfbClientInitMsg ci; + + /* if the connection is immediately closed, don't report anything, so + that pmw's monitor can make test connections */ + + if (client->listenSpecified) + errorMessageOnReadFailure = FALSE; + + if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE; + pv[sz_rfbProtocolVersionMsg]=0; + + errorMessageOnReadFailure = TRUE; + + pv[sz_rfbProtocolVersionMsg] = 0; + + if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { + rfbClientLog("Not a valid VNC server (%s)\n",pv); + return FALSE; + } + + + DefaultSupportedMessages(client); + client->major = major; + client->minor = minor; + + /* fall back to viewer supported version */ + if ((major==rfbProtocolMajorVersion) && (minor>rfbProtocolMinorVersion)) + client->minor = rfbProtocolMinorVersion; + + /* UltraVNC uses minor codes 4 and 6 for the server */ + if (major==3 && (minor==4 || minor==6)) { + rfbClientLog("UltraVNC server detected, enabling UltraVNC specific messages\n",pv); + DefaultSupportedMessagesUltraVNC(client); + } + + /* TightVNC uses minor codes 5 for the server */ + if (major==3 && minor==5) { + rfbClientLog("TightVNC server detected, enabling TightVNC specific messages\n",pv); + DefaultSupportedMessagesTightVNC(client); + } + + /* we do not support > RFB3.8 */ + if ((major==3 && minor>8) || major>3) + { + client->major=3; + client->minor=8; + } + + rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n", + major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion); + + sprintf(pv,rfbProtocolVersionFormat,client->major,client->minor); + + if (!WriteToRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE; + + + /* 3.7 and onwards sends a # of security types first */ + if (client->major==3 && client->minor > 6) + { + if (!ReadSupportedSecurityType(client, &authScheme, FALSE)) return FALSE; + } + else + { + if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE; + authScheme = rfbClientSwap32IfLE(authScheme); + } + + rfbClientLog("Selected Security Scheme %d\n", authScheme); + client->authScheme = authScheme; + + switch (authScheme) { + + case rfbConnFailed: + ReadReason(client); + return FALSE; + + case rfbNoAuth: + rfbClientLog("No authentication needed\n"); + + /* 3.8 and upwards sends a Security Result for rfbNoAuth */ + if ((client->major==3 && client->minor > 7) || client->major>3) + if (!rfbHandleAuthResult(client)) return FALSE; + + break; + + case rfbVncAuth: + if (!HandleVncAuth(client)) return FALSE; + break; + + case rfbMSLogon: + if (!HandleMSLogonAuth(client)) return FALSE; + break; + + case rfbTLS: +#ifndef LIBVNCSERVER_WITH_CLIENT_TLS + rfbClientLog("TLS support was not compiled in\n"); + return FALSE; +#else + if (!HandleAnonTLSAuth(client)) return FALSE; + /* After the TLS session is established, sub auth types are expected. + * Note that all following reading/writing are through the TLS session from here. + */ + if (!ReadSupportedSecurityType(client, &subAuthScheme, TRUE)) return FALSE; + client->subAuthScheme = subAuthScheme; + + switch (subAuthScheme) { + + case rfbConnFailed: + ReadReason(client); + return FALSE; + + case rfbNoAuth: + rfbClientLog("No sub authentication needed\n"); + /* 3.8 and upwards sends a Security Result for rfbNoAuth */ + if ((client->major==3 && client->minor > 7) || client->major>3) + if (!rfbHandleAuthResult(client)) return FALSE; + break; + + case rfbVncAuth: + if (!HandleVncAuth(client)) return FALSE; + break; + + default: + rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n", + (int)subAuthScheme); + return FALSE; + } +#endif + + break; + + case rfbVeNCrypt: +#ifndef LIBVNCSERVER_WITH_CLIENT_TLS + rfbClientLog("TLS support was not compiled in\n"); + return FALSE; +#else + if (!HandleVeNCryptAuth(client)) return FALSE; + + switch (client->subAuthScheme) { + + case rfbVeNCryptTLSNone: + case rfbVeNCryptX509None: + rfbClientLog("No sub authentication needed\n"); + if (!rfbHandleAuthResult(client)) return FALSE; + break; + + case rfbVeNCryptTLSVNC: + case rfbVeNCryptX509VNC: + if (!HandleVncAuth(client)) return FALSE; + break; + + case rfbVeNCryptTLSPlain: + case rfbVeNCryptX509Plain: + if (!HandlePlainAuth(client)) return FALSE; + break; + + default: + rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n", + client->subAuthScheme); + return FALSE; + } +#endif + break; + + default: + rfbClientLog("Unknown authentication scheme from VNC server: %d\n", + (int)authScheme); + return FALSE; + } + + ci.shared = (client->appData.shareDesktop ? 1 : 0); + + if (!WriteToRFBServer(client, (char *)&ci, sz_rfbClientInitMsg)) return FALSE; + + if (!ReadFromRFBServer(client, (char *)&client->si, sz_rfbServerInitMsg)) return FALSE; + + client->si.framebufferWidth = rfbClientSwap16IfLE(client->si.framebufferWidth); + client->si.framebufferHeight = rfbClientSwap16IfLE(client->si.framebufferHeight); + client->si.format.redMax = rfbClientSwap16IfLE(client->si.format.redMax); + client->si.format.greenMax = rfbClientSwap16IfLE(client->si.format.greenMax); + client->si.format.blueMax = rfbClientSwap16IfLE(client->si.format.blueMax); + client->si.nameLength = rfbClientSwap32IfLE(client->si.nameLength); + + client->desktopName = malloc(client->si.nameLength + 1); + if (!client->desktopName) { + rfbClientLog("Error allocating memory for desktop name, %lu bytes\n", + (unsigned long)client->si.nameLength); + return FALSE; + } + + if (!ReadFromRFBServer(client, client->desktopName, client->si.nameLength)) return FALSE; + + client->desktopName[client->si.nameLength] = 0; + + rfbClientLog("Desktop name \"%s\"\n",client->desktopName); + + rfbClientLog("Connected to VNC server, using protocol version %d.%d\n", + client->major, client->minor); + + rfbClientLog("VNC server default format:\n"); + PrintPixelFormat(&client->si.format); + + return TRUE; +} + + +/* + * SetFormatAndEncodings. + */ + +rfbBool +SetFormatAndEncodings(rfbClient* client) +{ + rfbSetPixelFormatMsg spf; + char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4]; + + rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf; + uint32_t *encs = (uint32_t *)(&buf[sz_rfbSetEncodingsMsg]); + int len = 0; + rfbBool requestCompressLevel = FALSE; + rfbBool requestQualityLevel = FALSE; + rfbBool requestLastRectEncoding = FALSE; + rfbClientProtocolExtension* e; + + if (!SupportsClient2Server(client, rfbSetPixelFormat)) return TRUE; + + spf.type = rfbSetPixelFormat; + spf.format = client->format; + spf.format.redMax = rfbClientSwap16IfLE(spf.format.redMax); + spf.format.greenMax = rfbClientSwap16IfLE(spf.format.greenMax); + spf.format.blueMax = rfbClientSwap16IfLE(spf.format.blueMax); + + if (!WriteToRFBServer(client, (char *)&spf, sz_rfbSetPixelFormatMsg)) + return FALSE; + + + if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE; + + se->type = rfbSetEncodings; + se->nEncodings = 0; + + if (client->appData.encodingsString) { + const char *encStr = client->appData.encodingsString; + int encStrLen; + do { + const char *nextEncStr = strchr(encStr, ' '); + if (nextEncStr) { + encStrLen = nextEncStr - encStr; + nextEncStr++; + } else { + encStrLen = strlen(encStr); + } + + if (strncasecmp(encStr,"raw",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw); + } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect); +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + } else if (strncasecmp(encStr,"tight",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight); + requestLastRectEncoding = TRUE; + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + if (client->appData.enableJPEG) + requestQualityLevel = TRUE; +#endif +#endif + } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile); +#ifdef LIBVNCSERVER_HAVE_LIBZ + } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib); + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + } else if (strncasecmp(encStr,"zlibhex",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlibHex); + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); + } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE); + requestQualityLevel = TRUE; +#endif + } else if ((strncasecmp(encStr,"ultra",encStrLen) == 0) || (strncasecmp(encStr,"ultrazip",encStrLen) == 0)) { + /* There are 2 encodings used in 'ultra' */ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip); + } else if (strncasecmp(encStr,"corre",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE); + } else if (strncasecmp(encStr,"rre",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE); + } else { + rfbClientLog("Unknown encoding '%.*s'\n",encStrLen,encStr); + } + + encStr = nextEncStr; + } while (encStr && se->nEncodings < MAX_ENCODINGS); + + if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel + + rfbEncodingCompressLevel0); + } + + if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) { + if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9) + client->appData.qualityLevel = 5; + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel + + rfbEncodingQualityLevel0); + } + } + else { + if (SameMachine(client->sock)) { + /* TODO: + if (!tunnelSpecified) { + */ + rfbClientLog("Same machine: preferring raw encoding\n"); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw); + /* + } else { + rfbClientLog("Tunneling active: preferring tight encoding\n"); + } + */ + } + + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect); +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight); + requestLastRectEncoding = TRUE; +#endif +#endif + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile); +#ifdef LIBVNCSERVER_HAVE_LIBZ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE); +#endif + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE); + + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel + + rfbEncodingCompressLevel0); + } else /* if (!tunnelSpecified) */ { + /* If -tunnel option was provided, we assume that server machine is + not in the local network so we use default compression level for + tight encoding instead of fast compression. Thus we are + requesting level 1 compression only if tunneling is not used. */ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCompressLevel1); + } + + if (client->appData.enableJPEG) { + if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9) + client->appData.qualityLevel = 5; + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel + + rfbEncodingQualityLevel0); + } + } + + + + /* Remote Cursor Support (local to viewer) */ + if (client->appData.useRemoteCursor) { + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingXCursor); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRichCursor); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPointerPos); + } + + /* Keyboard State Encodings */ + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingKeyboardLedState); + + /* New Frame Buffer Size */ + if (se->nEncodings < MAX_ENCODINGS && client->canHandleNewFBSize) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingNewFBSize); + + /* Last Rect */ + if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect); + + /* Server Capabilities */ + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedMessages); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedEncodings); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingServerIdentity); + + + /* client extensions */ + for(e = rfbClientExtensions; e; e = e->next) + if(e->encodings) { + int* enc; + for(enc = e->encodings; *enc; enc++) + encs[se->nEncodings++] = rfbClientSwap32IfLE(*enc); + } + + len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; + + se->nEncodings = rfbClientSwap16IfLE(se->nEncodings); + + if (!WriteToRFBServer(client, buf, len)) return FALSE; + + return TRUE; +} + + +/* + * SendIncrementalFramebufferUpdateRequest. + */ + +rfbBool +SendIncrementalFramebufferUpdateRequest(rfbClient* client) +{ + return SendFramebufferUpdateRequest(client, + client->updateRect.x, client->updateRect.y, + client->updateRect.w, client->updateRect.h, TRUE); +} + + +/* + * SendFramebufferUpdateRequest. + */ + +rfbBool +SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbBool incremental) +{ + rfbFramebufferUpdateRequestMsg fur; + + if (!SupportsClient2Server(client, rfbFramebufferUpdateRequest)) return TRUE; + + fur.type = rfbFramebufferUpdateRequest; + fur.incremental = incremental ? 1 : 0; + fur.x = rfbClientSwap16IfLE(x); + fur.y = rfbClientSwap16IfLE(y); + fur.w = rfbClientSwap16IfLE(w); + fur.h = rfbClientSwap16IfLE(h); + + if (!WriteToRFBServer(client, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) + return FALSE; + + return TRUE; +} + + +/* + * SendScaleSetting. + */ +rfbBool +SendScaleSetting(rfbClient* client,int scaleSetting) +{ + rfbSetScaleMsg ssm; + + ssm.scale = scaleSetting; + ssm.pad = 0; + + /* favor UltraVNC SetScale if both are supported */ + if (SupportsClient2Server(client, rfbSetScale)) { + ssm.type = rfbSetScale; + if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg)) + return FALSE; + } + + if (SupportsClient2Server(client, rfbPalmVNCSetScaleFactor)) { + ssm.type = rfbPalmVNCSetScaleFactor; + if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg)) + return FALSE; + } + + return TRUE; +} + +/* + * TextChatFunctions (UltraVNC) + * Extremely bandwidth friendly method of communicating with a user + * (Think HelpDesk type applications) + */ + +rfbBool TextChatSend(rfbClient* client, char *text) +{ + rfbTextChatMsg chat; + int count = strlen(text); + + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = (uint32_t)count; + chat.length = rfbClientSwap32IfLE(chat.length); + + if (!WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg)) + return FALSE; + + if (count>0) { + if (!WriteToRFBServer(client, text, count)) + return FALSE; + } + return TRUE; +} + +rfbBool TextChatOpen(rfbClient* client) +{ + rfbTextChatMsg chat; + + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatOpen); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +rfbBool TextChatClose(rfbClient* client) +{ + rfbTextChatMsg chat; + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatClose); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +rfbBool TextChatFinish(rfbClient* client) +{ + rfbTextChatMsg chat; + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatFinished); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +/* + * UltraVNC Server Input Disable + * Apparently, the remote client can *prevent* the local user from interacting with the display + * I would think this is extremely helpful when used in a HelpDesk situation + */ +rfbBool PermitServerInput(rfbClient* client, int enabled) +{ + rfbSetServerInputMsg msg; + + if (!SupportsClient2Server(client, rfbSetServerInput)) return TRUE; + /* enabled==1, then server input from local keyboard is disabled */ + msg.type = rfbSetServerInput; + msg.status = (enabled ? 1 : 0); + msg.pad = 0; + return (WriteToRFBServer(client, (char *)&msg, sz_rfbSetServerInputMsg) ? TRUE : FALSE); +} + + +/* + * SendPointerEvent. + */ + +rfbBool +SendPointerEvent(rfbClient* client,int x, int y, int buttonMask) +{ + rfbPointerEventMsg pe; + + if (!SupportsClient2Server(client, rfbPointerEvent)) return TRUE; + + pe.type = rfbPointerEvent; + pe.buttonMask = buttonMask; + if (x < 0) x = 0; + if (y < 0) y = 0; + + pe.x = rfbClientSwap16IfLE(x); + pe.y = rfbClientSwap16IfLE(y); + return WriteToRFBServer(client, (char *)&pe, sz_rfbPointerEventMsg); +} + + +/* + * SendKeyEvent. + */ + +rfbBool +SendKeyEvent(rfbClient* client, uint32_t key, rfbBool down) +{ + rfbKeyEventMsg ke; + + if (!SupportsClient2Server(client, rfbKeyEvent)) return TRUE; + + ke.type = rfbKeyEvent; + ke.down = down ? 1 : 0; + ke.key = rfbClientSwap32IfLE(key); + return WriteToRFBServer(client, (char *)&ke, sz_rfbKeyEventMsg); +} + + +/* + * SendClientCutText. + */ + +rfbBool +SendClientCutText(rfbClient* client, char *str, int len) +{ + rfbClientCutTextMsg cct; + + if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE; + + cct.type = rfbClientCutText; + cct.length = rfbClientSwap32IfLE(len); + return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) && + WriteToRFBServer(client, str, len)); +} + + + +/* + * HandleRFBServerMessage. + */ + +rfbBool +HandleRFBServerMessage(rfbClient* client) +{ + rfbServerToClientMsg msg; + + if (client->serverPort==-1) + client->vncRec->readTimestamp = TRUE; + if (!ReadFromRFBServer(client, (char *)&msg, 1)) + return FALSE; + + switch (msg.type) { + + case rfbSetColourMapEntries: + { + /* TODO: + int i; + uint16_t rgb[3]; + XColor xc; + + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbSetColourMapEntriesMsg - 1)) + return FALSE; + + msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour); + msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours); + + for (i = 0; i < msg.scme.nColours; i++) { + if (!ReadFromRFBServer(client, (char *)rgb, 6)) + return FALSE; + xc.pixel = msg.scme.firstColour + i; + xc.red = rfbClientSwap16IfLE(rgb[0]); + xc.green = rfbClientSwap16IfLE(rgb[1]); + xc.blue = rfbClientSwap16IfLE(rgb[2]); + xc.flags = DoRed|DoGreen|DoBlue; + XStoreColor(dpy, cmap, &xc); + } + */ + + break; + } + + case rfbFramebufferUpdate: + { + rfbFramebufferUpdateRectHeader rect; + int linesToRead; + int bytesPerLine; + int i; + + if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1, + sz_rfbFramebufferUpdateMsg - 1)) + return FALSE; + + msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects); + + for (i = 0; i < msg.fu.nRects; i++) { + if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader)) + return FALSE; + + rect.encoding = rfbClientSwap32IfLE(rect.encoding); + if (rect.encoding == rfbEncodingLastRect) + break; + + rect.r.x = rfbClientSwap16IfLE(rect.r.x); + rect.r.y = rfbClientSwap16IfLE(rect.r.y); + rect.r.w = rfbClientSwap16IfLE(rect.r.w); + rect.r.h = rfbClientSwap16IfLE(rect.r.h); + + + if (rect.encoding == rfbEncodingXCursor || + rect.encoding == rfbEncodingRichCursor) { + + if (!HandleCursorShape(client, + rect.r.x, rect.r.y, rect.r.w, rect.r.h, + rect.encoding)) { + return FALSE; + } + continue; + } + + if (rect.encoding == rfbEncodingPointerPos) { + if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) { + return FALSE; + } + continue; + } + + if (rect.encoding == rfbEncodingKeyboardLedState) { + /* OK! We have received a keyboard state message!!! */ + client->KeyboardLedStateEnabled = 1; + if (client->HandleKeyboardLedState!=NULL) + client->HandleKeyboardLedState(client, rect.r.x, 0); + /* stash it for the future */ + client->CurrentKeyboardLedState = rect.r.x; + continue; + } + + if (rect.encoding == rfbEncodingNewFBSize) { + client->width = rect.r.w; + client->height = rect.r.h; + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h); + continue; + } + + /* rect.r.w=byte count */ + if (rect.encoding == rfbEncodingSupportedMessages) { + int loop; + if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages)) + return FALSE; + + /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */ + /* currently ignored by this library */ + + rfbClientLog("client2server supported messages (bit flags)\n"); + for (loop=0;loop<32;loop+=8) + rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop, + client->supportedMessages.client2server[loop], client->supportedMessages.client2server[loop+1], + client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3], + client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5], + client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]); + + rfbClientLog("server2client supported messages (bit flags)\n"); + for (loop=0;loop<32;loop+=8) + rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop, + client->supportedMessages.server2client[loop], client->supportedMessages.server2client[loop+1], + client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3], + client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5], + client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]); + continue; + } + + /* rect.r.w=byte count, rect.r.h=# of encodings */ + if (rect.encoding == rfbEncodingSupportedEncodings) { + char *buffer; + buffer = malloc(rect.r.w); + if (!ReadFromRFBServer(client, buffer, rect.r.w)) + { + free(buffer); + return FALSE; + } + + /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */ + /* currently ignored by this library */ + free(buffer); + continue; + } + + /* rect.r.w=byte count */ + if (rect.encoding == rfbEncodingServerIdentity) { + char *buffer; + buffer = malloc(rect.r.w+1); + if (!ReadFromRFBServer(client, buffer, rect.r.w)) + { + free(buffer); + return FALSE; + } + buffer[rect.r.w]=0; /* null terminate, just in case */ + rfbClientLog("Connected to Server \"%s\"\n", buffer); + free(buffer); + continue; + } + + /* rfbEncodingUltraZip is a collection of subrects. x = # of subrects, and h is always 0 */ + if (rect.encoding != rfbEncodingUltraZip) + { + if ((rect.r.x + rect.r.w > client->width) || + (rect.r.y + rect.r.h > client->height)) + { + rfbClientLog("Rect too large: %dx%d at (%d, %d)\n", + rect.r.w, rect.r.h, rect.r.x, rect.r.y); + return FALSE; + } + + /* UltraVNC with scaling, will send rectangles with a zero W or H + * + if ((rect.encoding != rfbEncodingTight) && + (rect.r.h * rect.r.w == 0)) + { + 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); + continue; + } + */ + + /* If RichCursor encoding is used, we should prevent collisions + between framebuffer updates and cursor drawing operations. */ + client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h); + } + + switch (rect.encoding) { + + case rfbEncodingRaw: { + int y=rect.r.y, h=rect.r.h; + + bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8; + linesToRead = RFB_BUFFER_SIZE / bytesPerLine; + + while (h > 0) { + if (linesToRead > h) + linesToRead = h; + + if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead)) + return FALSE; + + CopyRectangle(client, (uint8_t *)client->buffer, + rect.r.x, y, rect.r.w,linesToRead); + + h -= linesToRead; + y += linesToRead; + + } + } break; + + case rfbEncodingCopyRect: + { + rfbCopyRect cr; + + if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect)) + return FALSE; + + cr.srcX = rfbClientSwap16IfLE(cr.srcX); + cr.srcY = rfbClientSwap16IfLE(cr.srcY); + + /* If RichCursor encoding is used, we should extend our + "cursor lock area" (previously set to destination + rectangle) to the source rectangle as well. */ + client->SoftCursorLockArea(client, + cr.srcX, cr.srcY, rect.r.w, rect.r.h); + + if (client->GotCopyRect != NULL) { + client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h, + rect.r.x, rect.r.y); + } else + CopyRectangleFromRectangle(client, + cr.srcX, cr.srcY, rect.r.w, rect.r.h, + rect.r.x, rect.r.y); + + break; + } + + case rfbEncodingRRE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingCoRRE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingHextile: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingUltra: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + case rfbEncodingUltraZip: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZlib: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + case rfbEncodingTight: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } +#endif + case rfbEncodingZRLE: + /* Fail safe for ZYWRLE unsupport VNC server. */ + client->appData.qualityLevel = 9; + /* fall through */ + case rfbEncodingZYWRLE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (client->si.format.greenMax > 0x1F) { + if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else { + if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } + break; + case 32: + { + uint32_t maxColor=(client->format.redMax<format.redShift)| + (client->format.greenMax<format.greenShift)| + (client->format.blueMax<format.blueShift); + if ((client->format.bigEndian && (maxColor&0xff)==0) || + (!client->format.bigEndian && (maxColor&0xff000000)==0)) { + if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (!client->format.bigEndian && (maxColor&0xff)==0) { + if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (client->format.bigEndian && (maxColor&0xff000000)==0) { + if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + } + break; + } + +#endif + + default: + { + rfbBool handled = FALSE; + rfbClientProtocolExtension* e; + + for(e = rfbClientExtensions; !handled && e; e = e->next) + if(e->handleEncoding && e->handleEncoding(client, &rect)) + handled = TRUE; + + if(!handled) { + rfbClientLog("Unknown rect encoding %d\n", + (int)rect.encoding); + return FALSE; + } + } + } + + /* Now we may discard "soft cursor locks". */ + client->SoftCursorUnlockScreen(client); + + client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h); + } + + if (!SendIncrementalFramebufferUpdateRequest(client)) + return FALSE; + + if (client->FinishedFrameBufferUpdate) + client->FinishedFrameBufferUpdate(client); + + break; + } + + case rfbBell: + { + client->Bell(client); + + break; + } + + case rfbServerCutText: + { + char *buffer; + + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbServerCutTextMsg - 1)) + return FALSE; + + msg.sct.length = rfbClientSwap32IfLE(msg.sct.length); + + buffer = malloc(msg.sct.length+1); + + if (!ReadFromRFBServer(client, buffer, msg.sct.length)) + return FALSE; + + buffer[msg.sct.length] = 0; + + if (client->GotXCutText) + client->GotXCutText(client, buffer, msg.sct.length); + + free(buffer); + + break; + } + + case rfbTextChat: + { + char *buffer=NULL; + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbTextChatMsg- 1)) + return FALSE; + msg.tc.length = rfbClientSwap32IfLE(msg.sct.length); + switch(msg.tc.length) { + case rfbTextChatOpen: + rfbClientLog("Received TextChat Open\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatOpen, NULL); + break; + case rfbTextChatClose: + rfbClientLog("Received TextChat Close\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatClose, NULL); + break; + case rfbTextChatFinished: + rfbClientLog("Received TextChat Finished\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatFinished, NULL); + break; + default: + buffer=malloc(msg.tc.length+1); + if (!ReadFromRFBServer(client, buffer, msg.tc.length)) + { + free(buffer); + return FALSE; + } + /* Null Terminate */ + buffer[msg.tc.length]=0; + rfbClientLog("Received TextChat \"%s\"\n", buffer); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)msg.tc.length, buffer); + free(buffer); + break; + } + break; + } + + case rfbResizeFrameBuffer: + { + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbResizeFrameBufferMsg -1)) + return FALSE; + client->width = rfbClientSwap16IfLE(msg.rsfb.framebufferWidth); + client->height = rfbClientSwap16IfLE(msg.rsfb.framebufferHeigth); + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height); + break; + } + + case rfbPalmVNCReSizeFrameBuffer: + { + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbPalmVNCReSizeFrameBufferMsg -1)) + return FALSE; + client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w); + client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h); + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height); + break; + } + + default: + { + rfbBool handled = FALSE; + rfbClientProtocolExtension* e; + + for(e = rfbClientExtensions; !handled && e; e = e->next) + if(e->handleMessage && e->handleMessage(client, &msg)) + handled = TRUE; + + if(!handled) { + char buffer[256]; + rfbClientLog("Unknown message type %d from VNC server\n",msg.type); + ReadFromRFBServer(client, buffer, 256); + return FALSE; + } + } + } + + return TRUE; +} + + +#define GET_PIXEL8(pix, ptr) ((pix) = *(ptr)++) + +#define GET_PIXEL16(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \ + ((uint8_t*)&(pix))[1] = *(ptr)++) + +#define GET_PIXEL32(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \ + ((uint8_t*)&(pix))[1] = *(ptr)++, \ + ((uint8_t*)&(pix))[2] = *(ptr)++, \ + ((uint8_t*)&(pix))[3] = *(ptr)++) + +/* CONCAT2 concatenates its two arguments. CONCAT2E does the same but also + expands its arguments if they are macros */ + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) + +#define BPP 8 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#undef BPP +#define BPP 16 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#define REALBPP 15 +#include "zrle.c" +#undef BPP +#define BPP 32 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#define REALBPP 24 +#include "zrle.c" +#define REALBPP 24 +#define UNCOMP 8 +#include "zrle.c" +#define REALBPP 24 +#define UNCOMP -8 +#include "zrle.c" +#undef BPP + + +/* + * PrintPixelFormat. + */ + +void +PrintPixelFormat(rfbPixelFormat *format) +{ + if (format->bitsPerPixel == 1) { + rfbClientLog(" Single bit per pixel.\n"); + rfbClientLog( + " %s significant bit in each byte is leftmost on the screen.\n", + (format->bigEndian ? "Most" : "Least")); + } else { + rfbClientLog(" %d bits per pixel.\n",format->bitsPerPixel); + if (format->bitsPerPixel != 8) { + rfbClientLog(" %s significant byte first in each pixel.\n", + (format->bigEndian ? "Most" : "Least")); + } + if (format->trueColour) { + rfbClientLog(" TRUE colour: max red %d green %d blue %d" + ", shift red %d green %d blue %d\n", + format->redMax, format->greenMax, format->blueMax, + format->redShift, format->greenShift, format->blueShift); + } else { + rfbClientLog(" Colour map (not true colour).\n"); + } + } +} + +/* avoid name clashes with LibVNCServer */ + +#define rfbEncryptBytes rfbClientEncryptBytes +#define rfbEncryptBytes2 rfbClientEncryptBytes2 +#define rfbDes rfbClientDes +#define rfbDesKey rfbClientDesKey +#define rfbUseKey rfbClientUseKey +#define rfbCPKey rfbClientCPKey + +#include "../libvncserver/vncauth.c" +#include "../libvncserver/d3des.c" diff --git a/3rdParty/LibVNC/src/libvncclient/rre.c b/3rdParty/LibVNC/src/libvncclient/rre.c new file mode 100644 index 0000000..94158c9 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/rre.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * rre.c - handle RRE encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an RRE + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleRREBPP CONCAT2E(HandleRRE,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleRREBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbRREHeader hdr; + int i; + CARDBPP pix; + rfbRectangle subrect; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader)) + return FALSE; + + hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects); + + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + FillRectangle(client, rx, ry, rw, rh, pix); + + for (i = 0; i < hdr.nSubrects; i++) { + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + if (!ReadFromRFBServer(client, (char *)&subrect, sz_rfbRectangle)) + return FALSE; + + subrect.x = rfbClientSwap16IfLE(subrect.x); + subrect.y = rfbClientSwap16IfLE(subrect.y); + subrect.w = rfbClientSwap16IfLE(subrect.w); + subrect.h = rfbClientSwap16IfLE(subrect.h); + + FillRectangle(client, rx+subrect.x, ry+subrect.y, subrect.w, subrect.h, pix); + } + + return TRUE; +} + +#undef CARDBPP diff --git a/3rdParty/LibVNC/src/libvncclient/sockets.c b/3rdParty/LibVNC/src/libvncclient/sockets.c new file mode 100644 index 0000000..598dd39 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/sockets.c @@ -0,0 +1,616 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * sockets.c - functions to deal with sockets. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include +#include +#ifdef WIN32 +#undef SOCKET +#include +#define EWOULDBLOCK WSAEWOULDBLOCK +#define close closesocket +#define read(sock,buf,len) recv(sock,buf,len,0) +#define write(sock,buf,len) send(sock,buf,len,0) +#define socklen_t int +#else +#include +#include +#include +#include +#include +#include +#endif +#include "tls.h" + +void PrintInHex(char *buf, int len); + +rfbBool errorMessageOnReadFailure = TRUE; + +/* + * ReadFromRFBServer is called whenever we want to read some data from the RFB + * server. It is non-trivial for two reasons: + * + * 1. For efficiency it performs some intelligent buffering, avoiding invoking + * the read() system call too often. For small chunks of data, it simply + * copies the data out of an internal buffer. For large amounts of data it + * reads directly into the buffer provided by the caller. + * + * 2. Whenever read() would block, it invokes the Xt event dispatching + * mechanism to process X events. In fact, this is the only place these + * events are processed, as there is no XtAppMainLoop in the program. + */ + +rfbBool +ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) +{ +#undef DEBUG_READ_EXACT +#ifdef DEBUG_READ_EXACT + char* oout=out; + int nn=n; + rfbClientLog("ReadFromRFBServer %d bytes\n",n); +#endif + if (client->serverPort==-1) { + /* vncrec playing */ + rfbVNCRec* rec = client->vncRec; + struct timeval tv; + + if (rec->readTimestamp) { + rec->readTimestamp = FALSE; + if (!fread(&tv,sizeof(struct timeval),1,rec->file)) + return FALSE; + + tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec); + tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec); + + if (rec->tv.tv_sec!=0 && !rec->doNotSleep) { + struct timeval diff; + diff.tv_sec = tv.tv_sec - rec->tv.tv_sec; + diff.tv_usec = tv.tv_usec - rec->tv.tv_usec; + if(diff.tv_usec<0) { + diff.tv_sec--; + diff.tv_usec+=1000000; + } +#ifndef __MINGW32__ + sleep (diff.tv_sec); + usleep (diff.tv_usec); +#else + Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000); +#endif + } + + rec->tv=tv; + } + + return (fread(out,1,n,rec->file)<0?FALSE:TRUE); + } + + if (n <= client->buffered) { + memcpy(out, client->bufoutptr, n); + client->bufoutptr += n; + client->buffered -= n; +#ifdef DEBUG_READ_EXACT + goto hexdump; +#endif + return TRUE; + } + + memcpy(out, client->bufoutptr, client->buffered); + + out += client->buffered; + n -= client->buffered; + + client->bufoutptr = client->buf; + client->buffered = 0; + + if (n <= RFB_BUF_SIZE) { + + while (client->buffered < n) { + int i; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); + } else { +#endif + i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + } +#endif + if (i <= 0) { + if (i < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + if (errno == EWOULDBLOCK || errno == EAGAIN) { + /* TODO: + ProcessXtEvents(); + */ + i = 0; + } else { + rfbClientErr("read (%d: %s)\n",errno,strerror(errno)); + return FALSE; + } + } else { + if (errorMessageOnReadFailure) { + rfbClientLog("VNC server closed connection\n"); + } + return FALSE; + } + } + client->buffered += i; + } + + memcpy(out, client->bufoutptr, n); + client->bufoutptr += n; + client->buffered -= n; + + } else { + + while (n > 0) { + int i; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + i = ReadFromTLS(client, out, n); + } else { +#endif + i = read(client->sock, out, n); +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + } +#endif + if (i <= 0) { + if (i < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + if (errno == EWOULDBLOCK || errno == EAGAIN) { + /* TODO: + ProcessXtEvents(); + */ + i = 0; + } else { + rfbClientErr("read (%s)\n",strerror(errno)); + return FALSE; + } + } else { + if (errorMessageOnReadFailure) { + rfbClientLog("VNC server closed connection\n"); + } + return FALSE; + } + } + out += i; + n -= i; + } + } + +#ifdef DEBUG_READ_EXACT +hexdump: + { int ii; + for(ii=0;iiserverPort==-1) + return TRUE; /* vncrec playing */ + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + /* WriteToTLS() will guarantee either everything is written, or error/eof returns */ + i = WriteToTLS(client, buf, n); + if (i <= 0) return FALSE; + + return TRUE; + } +#endif + + while (i < n) { + j = write(client->sock, buf + i, (n - i)); + if (j <= 0) { + if (j < 0) { + if (errno == EWOULDBLOCK || +#ifdef LIBVNCSERVER_ENOENT_WORKAROUND + errno == ENOENT || +#endif + errno == EAGAIN) { + FD_ZERO(&fds); + FD_SET(client->sock,&fds); + + if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) { + rfbClientErr("select\n"); + return FALSE; + } + j = 0; + } else { + rfbClientErr("write\n"); + return FALSE; + } + } else { + rfbClientLog("write failed\n"); + return FALSE; + } + } + i += j; + } + return TRUE; +} + + + +static int initSockets() { +#ifdef WIN32 + WSADATA trash; + static rfbBool WSAinitted=FALSE; + if(!WSAinitted) { + int i=WSAStartup(MAKEWORD(2,0),&trash); + if(i!=0) { + rfbClientErr("Couldn't init Windows Sockets\n"); + return 0; + } + WSAinitted=TRUE; + } +#endif + return 1; +} + +/* + * ConnectToTcpAddr connects to the given TCP port. + */ + +int +ConnectClientToTcpAddr(unsigned int host, int port) +{ + int sock; + struct sockaddr_in addr; + int one = 1; + + if (!initSockets()) + return -1; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = host; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + rfbClientErr("ConnectToTcpAddr: socket (%s)\n",strerror(errno)); + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + rfbClientErr("ConnectToTcpAddr: connect\n"); + close(sock); + return -1; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbClientErr("ConnectToTcpAddr: setsockopt\n"); + close(sock); + return -1; + } + + return sock; +} + +int +ConnectClientToUnixSock(const char *sockFile) +{ +#ifdef WIN32 + rfbClientErr("Windows doesn't support UNIX sockets\n"); + return -1; +#else + int sock; + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, sockFile); + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr("ConnectToUnixSock: socket (%s)\n",strerror(errno)); + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr.sun_family) + strlen(addr.sun_path)) < 0) { + rfbClientErr("ConnectToUnixSock: connect\n"); + close(sock); + return -1; + } + + return sock; +#endif +} + + + +/* + * FindFreeTcpPort tries to find unused TCP port in the range + * (TUNNEL_PORT_OFFSET, TUNNEL_PORT_OFFSET + 99]. Returns 0 on failure. + */ + +int +FindFreeTcpPort(void) +{ + int sock, port; + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (!initSockets()) + return -1; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr(": FindFreeTcpPort: socket\n"); + return 0; + } + + for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { + addr.sin_port = htons((unsigned short)port); + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + close(sock); + return port; + } + } + + close(sock); + return 0; +} + + +/* + * ListenAtTcpPort starts listening at the given TCP port. + */ + +int +ListenAtTcpPort(int port) +{ + int sock; + struct sockaddr_in addr; + int one = 1; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (!initSockets()) + return -1; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr("ListenAtTcpPort: socket\n"); + return -1; + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (const char *)&one, sizeof(one)) < 0) { + rfbClientErr("ListenAtTcpPort: setsockopt\n"); + close(sock); + return -1; + } + + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + rfbClientErr("ListenAtTcpPort: bind\n"); + close(sock); + return -1; + } + + if (listen(sock, 5) < 0) { + rfbClientErr("ListenAtTcpPort: listen\n"); + close(sock); + return -1; + } + + return sock; +} + + +/* + * AcceptTcpConnection accepts a TCP connection. + */ + +int +AcceptTcpConnection(int listenSock) +{ + int sock; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + int one = 1; + + sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); + if (sock < 0) { + rfbClientErr("AcceptTcpConnection: accept\n"); + return -1; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbClientErr("AcceptTcpConnection: setsockopt\n"); + close(sock); + return -1; + } + + return sock; +} + + +/* + * SetNonBlocking sets a socket into non-blocking mode. + */ + +rfbBool +SetNonBlocking(int sock) +{ +#ifndef __MINGW32__ + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbClientErr("AcceptTcpConnection: fcntl\n"); + return FALSE; + } +#else + rfbClientErr("O_NONBLOCK on MinGW32 NOT IMPLEMENTED\n"); +#endif + return TRUE; +} + + +/* + * StringToIPAddr - convert a host string to an IP address. + */ + +rfbBool +StringToIPAddr(const char *str, unsigned int *addr) +{ + struct hostent *hp; + + if (strcmp(str,"") == 0) { + *addr = htonl(INADDR_LOOPBACK); /* local */ + return TRUE; + } + + *addr = inet_addr(str); + + if (*addr != -1) + return TRUE; + + if (!initSockets()) + return -1; + + hp = gethostbyname(str); + + if (hp) { + *addr = *(unsigned int *)hp->h_addr; + return TRUE; + } + + return FALSE; +} + + +/* + * Test if the other end of a socket is on the same machine. + */ + +rfbBool +SameMachine(int sock) +{ + struct sockaddr_in peeraddr, myaddr; + socklen_t addrlen = sizeof(struct sockaddr_in); + + getpeername(sock, (struct sockaddr *)&peeraddr, &addrlen); + getsockname(sock, (struct sockaddr *)&myaddr, &addrlen); + + return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr); +} + + +/* + * Print out the contents of a packet for debugging. + */ + +void +PrintInHex(char *buf, int len) +{ + int i, j; + char c, str[17]; + + str[16] = 0; + + rfbClientLog("ReadExact: "); + + for (i = 0; i < len; i++) + { + if ((i % 16 == 0) && (i != 0)) { + rfbClientLog(" "); + } + c = buf[i]; + str[i % 16] = (((c > 31) && (c < 127)) ? c : '.'); + rfbClientLog("%02x ",(unsigned char)c); + if ((i % 4) == 3) + rfbClientLog(" "); + if ((i % 16) == 15) + { + rfbClientLog("%s\n",str); + } + } + if ((i % 16) != 0) + { + for (j = i % 16; j < 16; j++) + { + rfbClientLog(" "); + if ((j % 4) == 3) rfbClientLog(" "); + } + str[i % 16] = 0; + rfbClientLog("%s\n",str); + } + + fflush(stderr); +} + +int WaitForMessage(rfbClient* client,unsigned int usecs) +{ + fd_set fds; + struct timeval timeout; + int num; + + if (client->serverPort==-1) + /* playing back vncrec file */ + return 1; + + timeout.tv_sec=(usecs/1000000); + timeout.tv_usec=(usecs%1000000); + + FD_ZERO(&fds); + FD_SET(client->sock,&fds); + + num=select(client->sock+1, &fds, NULL, NULL, &timeout); + if(num<0) + rfbClientLog("Waiting for message failed: %d (%s)\n",errno,strerror(errno)); + + return num; +} + + diff --git a/3rdParty/LibVNC/src/libvncclient/tight.c b/3rdParty/LibVNC/src/libvncclient/tight.c new file mode 100644 index 0000000..2f9fbab --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/tight.c @@ -0,0 +1,688 @@ +/* + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + +/* + * tight.c - handle ``tight'' encoding. + * + * This file shouldn't be compiled directly. It is included multiple + * times by rfbproto.c, each time with a different definition of the + * macro BPP. For each value of BPP, this file defines a function + * which handles a tight-encoded rectangle with BPP bits per pixel. + * + */ + +#define TIGHT_MIN_TO_COMPRESS 12 + +#define CARDBPP CONCAT3E(uint,BPP,_t) +#define filterPtrBPP CONCAT2E(filterPtr,BPP) + +#define HandleTightBPP CONCAT2E(HandleTight,BPP) +#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP) +#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP) +#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP) +#define FilterCopyBPP CONCAT2E(FilterCopy,BPP) +#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP) +#define FilterGradientBPP CONCAT2E(FilterGradient,BPP) + +#if BPP != 8 +#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP) +#endif + +#ifndef RGB_TO_PIXEL + +#define RGB_TO_PIXEL(bpp,r,g,b) \ + (((CARD##bpp)(r) & client->format.redMax) << client->format.redShift | \ + ((CARD##bpp)(g) & client->format.greenMax) << client->format.greenShift | \ + ((CARD##bpp)(b) & client->format.blueMax) << client->format.blueShift) + +#define RGB24_TO_PIXEL(bpp,r,g,b) \ + ((((CARD##bpp)(r) & 0xFF) * client->format.redMax + 127) / 255 \ + << client->format.redShift | \ + (((CARD##bpp)(g) & 0xFF) * client->format.greenMax + 127) / 255 \ + << client->format.greenShift | \ + (((CARD##bpp)(b) & 0xFF) * client->format.blueMax + 127) / 255 \ + << client->format.blueShift) + +#define RGB24_TO_PIXEL32(r,g,b) \ + (((uint32_t)(r) & 0xFF) << client->format.redShift | \ + ((uint32_t)(g) & 0xFF) << client->format.greenShift | \ + ((uint32_t)(b) & 0xFF) << client->format.blueShift) + +#endif + +/* Type declarations */ + +typedef void (*filterPtrBPP)(rfbClient* client, int, CARDBPP *); + +/* Prototypes */ + +static int InitFilterCopyBPP (rfbClient* client, int rw, int rh); +static int InitFilterPaletteBPP (rfbClient* client, int rw, int rh); +static int InitFilterGradientBPP (rfbClient* client, int rw, int rh); +static void FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); +static void FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); +static void FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); + +#if BPP != 8 +static rfbBool DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h); +#endif + +/* Definitions */ + +static rfbBool +HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + CARDBPP fill_colour; + uint8_t comp_ctl; + uint8_t filter_id; + filterPtrBPP filterFn; + z_streamp zs; + char *buffer2; + int err, stream_id, compressedLen, bitsPixel; + int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes; + + if (!ReadFromRFBServer(client, (char *)&comp_ctl, 1)) + return FALSE; + + /* Flush zlib streams if we are told by the server to do so. */ + for (stream_id = 0; stream_id < 4; stream_id++) { + if ((comp_ctl & 1) && client->zlibStreamActive[stream_id]) { + if (inflateEnd (&client->zlibStream[stream_id]) != Z_OK && + client->zlibStream[stream_id].msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->zlibStream[stream_id].msg); + client->zlibStreamActive[stream_id] = FALSE; + } + comp_ctl >>= 1; + } + + /* Handle solid rectangles. */ + if (comp_ctl == rfbTightFill) { +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + if (!ReadFromRFBServer(client, client->buffer, 3)) + return FALSE; + fill_colour = RGB24_TO_PIXEL32(client->buffer[0], client->buffer[1], client->buffer[2]); + } else { + if (!ReadFromRFBServer(client, (char*)&fill_colour, sizeof(fill_colour))) + return FALSE; + } +#else + if (!ReadFromRFBServer(client, (char*)&fill_colour, sizeof(fill_colour))) + return FALSE; +#endif + + FillRectangle(client, rx, ry, rw, rh, fill_colour); + + return TRUE; + } + +#if BPP == 8 + if (comp_ctl == rfbTightJpeg) { + rfbClientLog("Tight encoding: JPEG is not supported in 8 bpp mode.\n"); + return FALSE; + } +#else + if (comp_ctl == rfbTightJpeg) { + return DecompressJpegRectBPP(client, rx, ry, rw, rh); + } +#endif + + /* Quit on unsupported subencoding value. */ + if (comp_ctl > rfbTightMaxSubencoding) { + rfbClientLog("Tight encoding: bad subencoding value received.\n"); + return FALSE; + } + + /* + * Here primary compression mode handling begins. + * Data was processed with optional filter + zlib compression. + */ + + /* First, we should identify a filter to use. */ + if ((comp_ctl & rfbTightExplicitFilter) != 0) { + if (!ReadFromRFBServer(client, (char*)&filter_id, 1)) + return FALSE; + + switch (filter_id) { + case rfbTightFilterCopy: + filterFn = FilterCopyBPP; + bitsPixel = InitFilterCopyBPP(client, rw, rh); + break; + case rfbTightFilterPalette: + filterFn = FilterPaletteBPP; + bitsPixel = InitFilterPaletteBPP(client, rw, rh); + break; + case rfbTightFilterGradient: + filterFn = FilterGradientBPP; + bitsPixel = InitFilterGradientBPP(client, rw, rh); + break; + default: + rfbClientLog("Tight encoding: unknown filter code received.\n"); + return FALSE; + } + } else { + filterFn = FilterCopyBPP; + bitsPixel = InitFilterCopyBPP(client, rw, rh); + } + if (bitsPixel == 0) { + rfbClientLog("Tight encoding: error receiving palette.\n"); + return FALSE; + } + + /* Determine if the data should be decompressed or just copied. */ + rowSize = (rw * bitsPixel + 7) / 8; + if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) { + if (!ReadFromRFBServer(client, (char*)client->buffer, rh * rowSize)) + return FALSE; + + buffer2 = &client->buffer[TIGHT_MIN_TO_COMPRESS * 4]; + filterFn(client, rh, (CARDBPP *)buffer2); + + CopyRectangle(client, (uint8_t *)buffer2, rx, ry, rw, rh); + + return TRUE; + } + + /* Read the length (1..3 bytes) of compressed data following. */ + compressedLen = (int)ReadCompactLen(client); + if (compressedLen <= 0) { + rfbClientLog("Incorrect data received from the server.\n"); + return FALSE; + } + + /* Now let's initialize compression stream if needed. */ + stream_id = comp_ctl & 0x03; + zs = &client->zlibStream[stream_id]; + if (!client->zlibStreamActive[stream_id]) { + zs->zalloc = Z_NULL; + zs->zfree = Z_NULL; + zs->opaque = Z_NULL; + err = inflateInit(zs); + if (err != Z_OK) { + if (zs->msg != NULL) + rfbClientLog("InflateInit error: %s.\n", zs->msg); + return FALSE; + } + client->zlibStreamActive[stream_id] = TRUE; + } + + /* Read, decode and draw actual pixel data in a loop. */ + + bufferSize = RFB_BUFFER_SIZE * bitsPixel / (bitsPixel + BPP) & 0xFFFFFFFC; + buffer2 = &client->buffer[bufferSize]; + if (rowSize > bufferSize) { + /* Should be impossible when RFB_BUFFER_SIZE >= 16384 */ + rfbClientLog("Internal error: incorrect buffer size.\n"); + return FALSE; + } + + rowsProcessed = 0; + extraBytes = 0; + + while (compressedLen > 0) { + if (compressedLen > ZLIB_BUFFER_SIZE) + portionLen = ZLIB_BUFFER_SIZE; + else + portionLen = compressedLen; + + if (!ReadFromRFBServer(client, (char*)client->zlib_buffer, portionLen)) + return FALSE; + + compressedLen -= portionLen; + + zs->next_in = (Bytef *)client->zlib_buffer; + zs->avail_in = portionLen; + + do { + zs->next_out = (Bytef *)&client->buffer[extraBytes]; + zs->avail_out = bufferSize - extraBytes; + + err = inflate(zs, Z_SYNC_FLUSH); + if (err == Z_BUF_ERROR) /* Input exhausted -- no problem. */ + break; + if (err != Z_OK && err != Z_STREAM_END) { + if (zs->msg != NULL) { + rfbClientLog("Inflate error: %s.\n", zs->msg); + } else { + rfbClientLog("Inflate error: %d.\n", err); + } + return FALSE; + } + + numRows = (bufferSize - zs->avail_out) / rowSize; + + filterFn(client, numRows, (CARDBPP *)buffer2); + + extraBytes = bufferSize - zs->avail_out - numRows * rowSize; + if (extraBytes > 0) + memcpy(client->buffer, &client->buffer[numRows * rowSize], extraBytes); + + CopyRectangle(client, (uint8_t *)buffer2, rx, ry+rowsProcessed, rw, numRows); + + rowsProcessed += numRows; + } + while (zs->avail_out == 0); + } + + if (rowsProcessed != rh) { + rfbClientLog("Incorrect number of scan lines after decompression.\n"); + return FALSE; + } + + return TRUE; +} + +/*---------------------------------------------------------------------------- + * + * Filter stuff. + * + */ + +static int +InitFilterCopyBPP (rfbClient* client, int rw, int rh) +{ + client->rectWidth = rw; + +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + client->cutZeros = TRUE; + return 24; + } else { + client->cutZeros = FALSE; + } +#endif + + return BPP; +} + +static void +FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + +#if BPP == 32 + int x, y; + + if (client->cutZeros) { + for (y = 0; y < numRows; y++) { + for (x = 0; x < client->rectWidth; x++) { + dst[y*client->rectWidth+x] = + RGB24_TO_PIXEL32(client->buffer[(y*client->rectWidth+x)*3], + client->buffer[(y*client->rectWidth+x)*3+1], + client->buffer[(y*client->rectWidth+x)*3+2]); + } + } + return; + } +#endif + + memcpy (dst, client->buffer, numRows * client->rectWidth * (BPP / 8)); +} + +static int +InitFilterGradientBPP (rfbClient* client, int rw, int rh) +{ + int bits; + + bits = InitFilterCopyBPP(client, rw, rh); + if (client->cutZeros) + memset(client->tightPrevRow, 0, rw * 3); + else + memset(client->tightPrevRow, 0, rw * 3 * sizeof(uint16_t)); + + return bits; +} + +#if BPP == 32 + +static void +FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst) +{ + int x, y, c; + uint8_t thisRow[2048*3]; + uint8_t pix[3]; + int est[3]; + + for (y = 0; y < numRows; y++) { + + /* First pixel in a row */ + for (c = 0; c < 3; c++) { + pix[c] = client->tightPrevRow[c] + client->buffer[y*client->rectWidth*3+c]; + thisRow[c] = pix[c]; + } + dst[y*client->rectWidth] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); + + /* Remaining pixels of a row */ + for (x = 1; x < client->rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = (int)client->tightPrevRow[x*3+c] + (int)pix[c] - + (int)client->tightPrevRow[(x-1)*3+c]; + if (est[c] > 0xFF) { + est[c] = 0xFF; + } else if (est[c] < 0x00) { + est[c] = 0x00; + } + pix[c] = (uint8_t)est[c] + client->buffer[(y*client->rectWidth+x)*3+c]; + thisRow[x*3+c] = pix[c]; + } + dst[y*client->rectWidth+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); + } + + memcpy(client->tightPrevRow, thisRow, client->rectWidth * 3); + } +} + +#endif + +static void +FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + int x, y, c; + CARDBPP *src = (CARDBPP *)client->buffer; + uint16_t *thatRow = (uint16_t *)client->tightPrevRow; + uint16_t thisRow[2048*3]; + uint16_t pix[3]; + uint16_t max[3]; + int shift[3]; + int est[3]; + +#if BPP == 32 + if (client->cutZeros) { + FilterGradient24(client, numRows, dst); + return; + } +#endif + + max[0] = client->format.redMax; + max[1] = client->format.greenMax; + max[2] = client->format.blueMax; + + shift[0] = client->format.redShift; + shift[1] = client->format.greenShift; + shift[2] = client->format.blueShift; + + for (y = 0; y < numRows; y++) { + + /* First pixel in a row */ + for (c = 0; c < 3; c++) { + pix[c] = (uint16_t)(((src[y*client->rectWidth] >> shift[c]) + thatRow[c]) & max[c]); + thisRow[c] = pix[c]; + } + dst[y*client->rectWidth] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); + + /* Remaining pixels of a row */ + for (x = 1; x < client->rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c]; + if (est[c] > (int)max[c]) { + est[c] = (int)max[c]; + } else if (est[c] < 0) { + est[c] = 0; + } + pix[c] = (uint16_t)(((src[y*client->rectWidth+x] >> shift[c]) + est[c]) & max[c]); + thisRow[x*3+c] = pix[c]; + } + dst[y*client->rectWidth+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); + } + memcpy(thatRow, thisRow, client->rectWidth * 3 * sizeof(uint16_t)); + } +} + +static int +InitFilterPaletteBPP (rfbClient* client, int rw, int rh) +{ + uint8_t numColors; +#if BPP == 32 + int i; + CARDBPP *palette = (CARDBPP *)client->tightPalette; +#endif + + client->rectWidth = rw; + + if (!ReadFromRFBServer(client, (char*)&numColors, 1)) + return 0; + + client->rectColors = (int)numColors; + if (++client->rectColors < 2) + return 0; + +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + if (!ReadFromRFBServer(client, (char*)&client->tightPalette, client->rectColors * 3)) + return 0; + for (i = client->rectColors - 1; i >= 0; i--) { + palette[i] = RGB24_TO_PIXEL32(client->tightPalette[i*3], + client->tightPalette[i*3+1], + client->tightPalette[i*3+2]); + } + return (client->rectColors == 2) ? 1 : 8; + } +#endif + + if (!ReadFromRFBServer(client, (char*)&client->tightPalette, client->rectColors * (BPP / 8))) + return 0; + + return (client->rectColors == 2) ? 1 : 8; +} + +static void +FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + int x, y, b, w; + uint8_t *src = (uint8_t *)client->buffer; + CARDBPP *palette = (CARDBPP *)client->tightPalette; + + if (client->rectColors == 2) { + w = (client->rectWidth + 7) / 8; + for (y = 0; y < numRows; y++) { + for (x = 0; x < client->rectWidth / 8; x++) { + for (b = 7; b >= 0; b--) + dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; + } + for (b = 7; b >= 8 - client->rectWidth % 8; b--) { + dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; + } + } + } else { + for (y = 0; y < numRows; y++) + for (x = 0; x < client->rectWidth; x++) + dst[y*client->rectWidth+x] = palette[(int)src[y*client->rectWidth+x]]; + } +} + +#if BPP != 8 + +/*---------------------------------------------------------------------------- + * + * JPEG decompression. + * + */ + +static rfbBool +DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + int compressedLen; + uint8_t *compressedData; + CARDBPP *pixelPtr; + JSAMPROW rowPointer[1]; + int dx, dy; + + compressedLen = (int)ReadCompactLen(client); + if (compressedLen <= 0) { + rfbClientLog("Incorrect data received from the server.\n"); + return FALSE; + } + + compressedData = malloc(compressedLen); + if (compressedData == NULL) { + rfbClientLog("Memory allocation error.\n"); + return FALSE; + } + + if (!ReadFromRFBServer(client, (char*)compressedData, compressedLen)) { + free(compressedData); + return FALSE; + } + + cinfo.err = jpeg_std_error(&jerr); + cinfo.client_data = client; + jpeg_create_decompress(&cinfo); + + JpegSetSrcManager(&cinfo, compressedData, compressedLen); + + jpeg_read_header(&cinfo, TRUE); + cinfo.out_color_space = JCS_RGB; + + jpeg_start_decompress(&cinfo); + if (cinfo.output_width != w || cinfo.output_height != h || + cinfo.output_components != 3) { + rfbClientLog("Tight Encoding: Wrong JPEG data received.\n"); + jpeg_destroy_decompress(&cinfo); + free(compressedData); + return FALSE; + } + + rowPointer[0] = (JSAMPROW)client->buffer; + dy = 0; + while (cinfo.output_scanline < cinfo.output_height) { + jpeg_read_scanlines(&cinfo, rowPointer, 1); + if (client->jpegError) { + break; + } + pixelPtr = (CARDBPP *)&client->buffer[RFB_BUFFER_SIZE / 2]; + for (dx = 0; dx < w; dx++) { + *pixelPtr++ = + RGB24_TO_PIXEL(BPP, client->buffer[dx*3], client->buffer[dx*3+1], client->buffer[dx*3+2]); + } + CopyRectangle(client, (uint8_t *)&client->buffer[RFB_BUFFER_SIZE / 2], x, y + dy, w, 1); + dy++; + } + + if (!client->jpegError) + jpeg_finish_decompress(&cinfo); + + jpeg_destroy_decompress(&cinfo); + free(compressedData); + + return !client->jpegError; +} + +#else + +static long +ReadCompactLen (rfbClient* client) +{ + long len; + uint8_t b; + + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len = (int)b & 0x7F; + if (b & 0x80) { + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len |= ((int)b & 0x7F) << 7; + if (b & 0x80) { + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len |= ((int)b & 0xFF) << 14; + } + } + return len; +} + +/* + * JPEG source manager functions for JPEG decompression in Tight decoder. + */ + +static void +JpegInitSource(j_decompress_ptr cinfo) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegError = FALSE; +} + +static boolean +JpegFillInputBuffer(j_decompress_ptr cinfo) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegError = TRUE; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr; + + return TRUE; +} + +static void +JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + if (num_bytes < 0 || num_bytes > client->jpegSrcManager->bytes_in_buffer) { + client->jpegError = TRUE; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr; + } else { + client->jpegSrcManager->next_input_byte += (size_t) num_bytes; + client->jpegSrcManager->bytes_in_buffer -= (size_t) num_bytes; + } +} + +static void +JpegTermSource(j_decompress_ptr cinfo) +{ + /* nothing to do here. */ +} + +static void +JpegSetSrcManager(j_decompress_ptr cinfo, + uint8_t *compressedData, + int compressedLen) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegBufferPtr = compressedData; + client->jpegBufferLen = (size_t)compressedLen; + + if(client->jpegSrcManager == NULL) + client->jpegSrcManager = malloc(sizeof(struct jpeg_source_mgr)); + client->jpegSrcManager->init_source = JpegInitSource; + client->jpegSrcManager->fill_input_buffer = JpegFillInputBuffer; + client->jpegSrcManager->skip_input_data = JpegSkipInputData; + client->jpegSrcManager->resync_to_restart = jpeg_resync_to_restart; + client->jpegSrcManager->term_source = JpegTermSource; + client->jpegSrcManager->next_input_byte = (JOCTET*)client->jpegBufferPtr; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + + cinfo->src = client->jpegSrcManager; +} + +#endif + +#undef CARDBPP + +/* LIBVNCSERVER_HAVE_LIBZ and LIBVNCSERVER_HAVE_LIBJPEG */ +#endif +#endif + diff --git a/3rdParty/LibVNC/src/libvncclient/tls.c b/3rdParty/LibVNC/src/libvncclient/tls.c new file mode 100644 index 0000000..206dbda --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/tls.c @@ -0,0 +1,496 @@ +/* + * Copyright (C) 2009 Vic Lee. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include "tls.h" + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + +static const int rfbCertTypePriority[] = { GNUTLS_CRT_X509, 0 }; +static const int rfbProtoPriority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; +static const int rfbKXPriority[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0}; +static const int rfbKXAnon[] = {GNUTLS_KX_ANON_DH, 0}; + +#define DH_BITS 1024 +static gnutls_dh_params_t rfbDHParams; + +static rfbBool rfbTLSInitialized = FALSE; + +static rfbBool +InitializeTLS(void) +{ + int ret; + + if (rfbTLSInitialized) return TRUE; + if ((ret = gnutls_global_init()) < 0 || + (ret = gnutls_dh_params_init(&rfbDHParams)) < 0 || + (ret = gnutls_dh_params_generate2(rfbDHParams, DH_BITS)) < 0) + { + rfbClientLog("Failed to initialized GnuTLS: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + rfbClientLog("GnuTLS initialized.\n"); + rfbTLSInitialized = TRUE; + return TRUE; +} + +static ssize_t +PushTLS(gnutls_transport_ptr_t transport, const void *data, size_t len) +{ + rfbClient *client = (rfbClient*)transport; + int ret; + + while (1) + { + ret = write(client->sock, data, len); + if (ret < 0) + { + if (errno == EINTR) continue; + return -1; + } + return ret; + } +} + + +static ssize_t +PullTLS(gnutls_transport_ptr_t transport, void *data, size_t len) +{ + rfbClient *client = (rfbClient*)transport; + int ret; + + while (1) + { + ret = read(client->sock, data, len); + if (ret < 0) + { + if (errno == EINTR) continue; + return -1; + } + return ret; + } +} + +static rfbBool +InitializeTLSSession(rfbClient* client, rfbBool anonTLS) +{ + int ret; + + if (client->tlsSession) return TRUE; + + if ((ret = gnutls_init(&client->tlsSession, GNUTLS_CLIENT)) < 0) + { + rfbClientLog("Failed to initialized TLS session: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + + if ((ret = gnutls_set_default_priority(client->tlsSession)) < 0 || + (ret = gnutls_kx_set_priority(client->tlsSession, anonTLS ? rfbKXAnon : rfbKXPriority)) < 0 || + (ret = gnutls_certificate_type_set_priority(client->tlsSession, rfbCertTypePriority)) < 0 || + (ret = gnutls_protocol_set_priority(client->tlsSession, rfbProtoPriority)) < 0) + { + FreeTLS(client); + rfbClientLog("Failed to set TLS priority: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + + gnutls_transport_set_ptr(client->tlsSession, (gnutls_transport_ptr_t)client); + gnutls_transport_set_push_function(client->tlsSession, PushTLS); + gnutls_transport_set_pull_function(client->tlsSession, PullTLS); + + rfbClientLog("TLS session initialized.\n"); + + return TRUE; +} + +static rfbBool +SetTLSAnonCredential(rfbClient* client) +{ + gnutls_anon_client_credentials anonCred; + int ret; + + if ((ret = gnutls_anon_allocate_client_credentials(&anonCred)) < 0 || + (ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_ANON, anonCred)) < 0) + { + FreeTLS(client); + rfbClientLog("Failed to create anonymous credentials: %s", gnutls_strerror(ret)); + return FALSE; + } + rfbClientLog("TLS anonymous credential created.\n"); + return TRUE; +} + +static rfbBool +HandshakeTLS(rfbClient* client) +{ + int timeout = 15; + int ret; + + while (timeout > 0 && (ret = gnutls_handshake(client->tlsSession)) < 0) + { + if (!gnutls_error_is_fatal(ret)) + { + rfbClientLog("TLS handshake blocking.\n"); + sleep(1); + timeout--; + continue; + } + rfbClientLog("TLS handshake failed: %s.\n", gnutls_strerror(ret)); + FreeTLS(client); + return FALSE; + } + + if (timeout <= 0) + { + rfbClientLog("TLS handshake timeout.\n"); + FreeTLS(client); + return FALSE; + } + + rfbClientLog("TLS handshake done.\n"); + return TRUE; +} + +/* VeNCrypt sub auth. 1 byte auth count, followed by count * 4 byte integers */ +static rfbBool +ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result) +{ + uint8_t count=0; + uint8_t loop=0; + uint8_t flag=0; + uint32_t tAuth[256], t; + char buf1[500],buf2[10]; + uint32_t authScheme; + + if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; + + if (count==0) + { + rfbClientLog("List of security types is ZERO. Giving up.\n"); + return FALSE; + } + if (count>sizeof(tAuth)) + { + rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth)); + return FALSE; + } + + rfbClientLog("We have %d security types to read\n", count); + authScheme=0; + /* now, we have a list of available security types to read ( uint8_t[] ) */ + for (loop=0;loop=sizeof(buf1)-1) break; + snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]); + strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1); + } + rfbClientLog("Unknown VeNCrypt authentication scheme from VNC server: %s\n", + buf1); + return FALSE; + } + *result = authScheme; + return TRUE; +} + +static void +FreeX509Credential(rfbCredential *cred) +{ + if (cred->x509Credential.x509CACertFile) free(cred->x509Credential.x509CACertFile); + if (cred->x509Credential.x509CACrlFile) free(cred->x509Credential.x509CACrlFile); + if (cred->x509Credential.x509ClientCertFile) free(cred->x509Credential.x509ClientCertFile); + if (cred->x509Credential.x509ClientKeyFile) free(cred->x509Credential.x509ClientKeyFile); + free(cred); +} + +static gnutls_certificate_credentials_t +CreateX509CertCredential(rfbCredential *cred) +{ + gnutls_certificate_credentials_t x509_cred; + int ret; + + if (!cred->x509Credential.x509CACertFile) + { + rfbClientLog("No CA certificate provided.\n"); + return NULL; + } + + if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) + { + rfbClientLog("Cannot allocate credentials: %s.\n", gnutls_strerror(ret)); + return NULL; + } + if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, + cred->x509Credential.x509CACertFile, GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load CA credentials: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + if (cred->x509Credential.x509ClientCertFile && cred->x509Credential.x509ClientKeyFile) + { + if ((ret = gnutls_certificate_set_x509_key_file(x509_cred, + cred->x509Credential.x509ClientCertFile, cred->x509Credential.x509ClientKeyFile, + GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load client certificate or key: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + } else + { + rfbClientLog("No client certificate or key provided.\n"); + } + if (cred->x509Credential.x509CACrlFile) + { + if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, + cred->x509Credential.x509CACrlFile, GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load CRL: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + } else + { + rfbClientLog("No CRL provided.\n"); + } + gnutls_certificate_set_dh_params (x509_cred, rfbDHParams); + return x509_cred; +} + +#endif + +rfbBool +HandleAnonTLSAuth(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + + if (!InitializeTLS() || !InitializeTLSSession(client, TRUE)) return FALSE; + + if (!SetTLSAnonCredential(client)) return FALSE; + + if (!HandshakeTLS(client)) return FALSE; + + return TRUE; + +#else + rfbClientLog("TLS is not supported.\n"); + return FALSE; +#endif +} + +rfbBool +HandleVeNCryptAuth(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + uint8_t major, minor, status; + uint32_t authScheme; + rfbBool anonTLS; + gnutls_certificate_credentials_t x509_cred = NULL; + int ret; + + if (!InitializeTLS()) return FALSE; + + /* Read VeNCrypt version */ + if (!ReadFromRFBServer(client, (char *)&major, 1) || + !ReadFromRFBServer(client, (char *)&minor, 1)) + { + return FALSE; + } + rfbClientLog("Got VeNCrypt version %d.%d from server.\n", (int)major, (int)minor); + + if (major != 0 && minor != 2) + { + rfbClientLog("Unsupported VeNCrypt version.\n"); + return FALSE; + } + + if (!WriteToRFBServer(client, (char *)&major, 1) || + !WriteToRFBServer(client, (char *)&minor, 1) || + !ReadFromRFBServer(client, (char *)&status, 1)) + { + return FALSE; + } + + if (status != 0) + { + rfbClientLog("Server refused VeNCrypt version %d.%d.\n", (int)major, (int)minor); + return FALSE; + } + + if (!ReadVeNCryptSecurityType(client, &authScheme)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&status, 1) || status != 1) + { + rfbClientLog("Server refused VeNCrypt authentication %d (%d).\n", authScheme, (int)status); + return FALSE; + } + client->subAuthScheme = authScheme; + + /* Some VeNCrypt security types are anonymous TLS, others are X509 */ + switch (authScheme) + { + case rfbVeNCryptTLSNone: + case rfbVeNCryptTLSVNC: + case rfbVeNCryptTLSPlain: + anonTLS = TRUE; + break; + default: + anonTLS = FALSE; + break; + } + + /* Get X509 Credentials if it's not anonymous */ + if (!anonTLS) + { + rfbCredential *cred; + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + cred = client->GetCredential(client, rfbCredentialTypeX509); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + x509_cred = CreateX509CertCredential(cred); + FreeX509Credential(cred); + if (!x509_cred) return FALSE; + } + + /* Start up the TLS session */ + if (!InitializeTLSSession(client, anonTLS)) return FALSE; + + if (anonTLS) + { + if (!SetTLSAnonCredential(client)) return FALSE; + } + else + { + if ((ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_CERTIFICATE, x509_cred)) < 0) + { + rfbClientLog("Cannot set x509 credential: %s.\n", gnutls_strerror(ret)); + FreeTLS(client); + return FALSE; + } + } + + if (!HandshakeTLS(client)) return FALSE; + + /* TODO: validate certificate */ + + /* We are done here. The caller should continue with client->subAuthScheme + * to do actual sub authentication. + */ + return TRUE; + +#else + rfbClientLog("TLS is not supported.\n"); + return FALSE; +#endif +} + +int +ReadFromTLS(rfbClient* client, char *out, unsigned int n) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + ssize_t ret; + + ret = gnutls_record_recv(client->tlsSession, out, n); + if (ret >= 0) return ret; + if (ret == GNUTLS_E_REHANDSHAKE || ret == GNUTLS_E_AGAIN) + { + errno = EAGAIN; + } else + { + rfbClientLog("Error reading from TLS: %s.\n", gnutls_strerror(ret)); + errno = EINTR; + } + return -1; +#else + rfbClientLog("TLS is not supported.\n"); + errno = EINTR; + return -1; +#endif +} + +int +WriteToTLS(rfbClient* client, char *buf, unsigned int n) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + unsigned int offset = 0; + ssize_t ret; + + while (offset < n) + { + ret = gnutls_record_send(client->tlsSession, buf+offset, (size_t)(n-offset)); + if (ret == 0) continue; + if (ret < 0) + { + if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) continue; + rfbClientLog("Error writing to TLS: %s.\n", gnutls_strerror(ret)); + return -1; + } + offset += (unsigned int)ret; + } + return offset; +#else + rfbClientLog("TLS is not supported.\n"); + errno = EINTR; + return -1; +#endif +} + +void FreeTLS(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) + { + gnutls_deinit(client->tlsSession); + client->tlsSession = NULL; + } +#endif +} diff --git a/3rdParty/LibVNC/src/libvncclient/tls.h b/3rdParty/LibVNC/src/libvncclient/tls.h new file mode 100644 index 0000000..48d159b --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/tls.h @@ -0,0 +1,51 @@ +#ifndef TLS_H +#define TLS_H + +/* + * Copyright (C) 2009 Vic Lee. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* Handle Anonymous TLS Authentication (18) with the server. + * After authentication, client->tlsSession will be set. + */ +rfbBool HandleAnonTLSAuth(rfbClient* client); + +/* Handle VeNCrypt Authentication (19) with the server. + * The callback function GetX509Credential will be called. + * After authentication, client->tlsSession will be set. + */ +rfbBool HandleVeNCryptAuth(rfbClient* client); + +/* Read desired bytes from TLS session. + * It's a wrapper function over gnutls_record_recv() and return values + * are same as read(), that is, >0 for actual bytes read, 0 for EOF, + * or EAGAIN, EINTR. + * This should be a non-blocking call. Blocking is handled in sockets.c. + */ +int ReadFromTLS(rfbClient* client, char *out, unsigned int n); + +/* Write desired bytes to TLS session. + * It's a wrapper function over gnutls_record_send() and it will be + * blocking call, until all bytes are written or error returned. + */ +int WriteToTLS(rfbClient* client, char *buf, unsigned int n); + +/* Free TLS resources */ +void FreeTLS(rfbClient* client); + +#endif /* TLS_H */ diff --git a/3rdParty/LibVNC/src/libvncclient/ultra.c b/3rdParty/LibVNC/src/libvncclient/ultra.c new file mode 100644 index 0000000..3be150d --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/ultra.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * ultrazip.c - handle ultrazip encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zlib + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleUltraZipBPP CONCAT2E(HandleUltraZip,BPP) +#define HandleUltraBPP CONCAT2E(HandleUltra,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleUltraBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int toRead=0; + int inflateResult=0; + int uncompressedBytes = (( rw * rh ) * ( BPP / 8 )); + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + toRead = rfbClientSwap32IfLE(hdr.nBytes); + if (toRead==0) return TRUE; + + if (uncompressedBytes==0) + { + rfbClientLog("ultra error: rectangle has 0 uncomressed bytes ((%dw * %dh) * (%d / 8))\n", rw, rh, BPP); + return FALSE; + } + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < uncompressedBytes) { + if ( client->raw_buffer != NULL ) { + free( client->raw_buffer ); + } + client->raw_buffer_size = uncompressedBytes; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->raw_buffer_size % 4)!=0) + client->raw_buffer_size += (4-(client->raw_buffer_size % 4)); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + } + + /* allocate enough space to store the incoming compressed packet */ + if ( client->ultra_buffer_size < toRead ) { + if ( client->ultra_buffer != NULL ) { + free( client->ultra_buffer ); + } + client->ultra_buffer_size = toRead; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->ultra_buffer_size % 4)!=0) + client->ultra_buffer_size += (4-(client->ultra_buffer_size % 4)); + client->ultra_buffer = (char*) malloc( client->ultra_buffer_size ); + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->ultra_buffer, toRead)) + return FALSE; + + /* uncompress the data */ + uncompressedBytes = client->raw_buffer_size; + inflateResult = lzo1x_decompress( + (lzo_byte *)client->ultra_buffer, toRead, + (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, + NULL); + + + if ((rw * rh * (BPP / 8)) != uncompressedBytes) + rfbClientLog("Ultra decompressed too little (%d < %d)", (rw * rh * (BPP / 8)), uncompressedBytes); + + /* Put the uncompressed contents of the update on the screen. */ + if ( inflateResult == LZO_E_OK ) + { + CopyRectangle(client, (unsigned char *)client->raw_buffer, rx, ry, rw, rh); + } + else + { + rfbClientLog("ultra decompress returned error: %d\n", + inflateResult); + return FALSE; + } + return TRUE; +} + + +/* UltraZip is like rre in that it is composed of subrects */ +static rfbBool +HandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int i=0; + int toRead=0; + int inflateResult=0; + unsigned char *ptr=NULL; + int uncompressedBytes = ry + (rw * 65535); + unsigned int numCacheRects = rx; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + toRead = rfbClientSwap32IfLE(hdr.nBytes); + + if (toRead==0) return TRUE; + + if (uncompressedBytes==0) + { + rfbClientLog("ultrazip error: rectangle has 0 uncomressed bytes (%dy + (%dw * 65535)) (%d rectangles)\n", ry, rw, rx); + return FALSE; + } + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < (uncompressedBytes + 500)) { + if ( client->raw_buffer != NULL ) { + free( client->raw_buffer ); + } + client->raw_buffer_size = uncompressedBytes + 500; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->raw_buffer_size % 4)!=0) + client->raw_buffer_size += (4-(client->raw_buffer_size % 4)); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + } + + + /* allocate enough space to store the incoming compressed packet */ + if ( client->ultra_buffer_size < toRead ) { + if ( client->ultra_buffer != NULL ) { + free( client->ultra_buffer ); + } + client->ultra_buffer_size = toRead; + client->ultra_buffer = (char*) malloc( client->ultra_buffer_size ); + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->ultra_buffer, toRead)) + return FALSE; + + /* uncompress the data */ + uncompressedBytes = client->raw_buffer_size; + inflateResult = lzo1x_decompress( + (lzo_byte *)client->ultra_buffer, toRead, + (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, NULL); + if ( inflateResult != LZO_E_OK ) + { + rfbClientLog("ultra decompress returned error: %d\n", + inflateResult); + return FALSE; + } + + /* Put the uncompressed contents of the update on the screen. */ + ptr = (unsigned char *)client->raw_buffer; + for (i=0; i +#include +#include +#include +#include +#include "tls.h" + +static void Dummy(rfbClient* client) { +} +static rfbBool DummyPoint(rfbClient* client, int x, int y) { + return TRUE; +} +static void DummyRect(rfbClient* client, int x, int y, int w, int h) { +} + +#ifdef __MINGW32__ +static char* NoPassword(rfbClient* client) { + return strdup(""); +} +#undef SOCKET +#include +#define close closesocket +#else +#include +#include +#endif + +static char* ReadPassword(rfbClient* client) { +#ifdef __MINGW32__ + /* FIXME */ + rfbClientErr("ReadPassword on MinGW32 NOT IMPLEMENTED\n"); + return NoPassword(client); +#else + int i; + char* p=malloc(9); + struct termios save,noecho; + p[0]=0; + if(tcgetattr(fileno(stdin),&save)!=0) return p; + noecho=save; noecho.c_lflag &= ~ECHO; + if(tcsetattr(fileno(stdin),TCSAFLUSH,&noecho)!=0) return p; + fprintf(stderr,"Password: "); + i=0; + while(1) { + int c=fgetc(stdin); + if(c=='\n') + break; + if(i<8) { + p[i]=c; + i++; + p[i]=0; + } + } + tcsetattr(fileno(stdin),TCSAFLUSH,&save); + return p; +#endif +} +static rfbBool MallocFrameBuffer(rfbClient* client) { + if(client->frameBuffer) + free(client->frameBuffer); + client->frameBuffer=malloc(client->width*client->height*client->format.bitsPerPixel/8); + return client->frameBuffer?TRUE:FALSE; +} + +static void initAppData(AppData* data) { + data->shareDesktop=TRUE; + data->viewOnly=FALSE; + data->encodingsString="tight zrle ultra copyrect hextile zlib corre rre raw"; + data->useBGR233=FALSE; + data->nColours=0; + data->forceOwnCmap=FALSE; + data->forceTrueColour=FALSE; + data->requestedDepth=0; + data->compressLevel=3; + data->qualityLevel=5; +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + data->enableJPEG=TRUE; +#else + data->enableJPEG=FALSE; +#endif + data->useRemoteCursor=FALSE; +} + +rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel, + int bytesPerPixel) { + rfbClient* client=(rfbClient*)calloc(sizeof(rfbClient),1); + if(!client) { + rfbClientErr("Couldn't allocate client structure!\n"); + return NULL; + } + initAppData(&client->appData); + client->endianTest = 1; + client->programName=""; + client->serverHost=strdup(""); + client->serverPort=5900; + + client->destHost = NULL; + client->destPort = 5900; + + client->CurrentKeyboardLedState = 0; + client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint; + + /* default: use complete frame buffer */ + client->updateRect.x = -1; + + client->format.bitsPerPixel = bytesPerPixel*8; + client->format.depth = bitsPerSample*samplesPerPixel; + client->appData.requestedDepth=client->format.depth; + client->format.bigEndian = *(char *)&client->endianTest?FALSE:TRUE; + client->format.trueColour = TRUE; + + if (client->format.bitsPerPixel == 8) { + client->format.redMax = 7; + client->format.greenMax = 7; + client->format.blueMax = 3; + client->format.redShift = 0; + client->format.greenShift = 3; + client->format.blueShift = 6; + } else { + client->format.redMax = (1 << bitsPerSample) - 1; + client->format.greenMax = (1 << bitsPerSample) - 1; + client->format.blueMax = (1 << bitsPerSample) - 1; + if(!client->format.bigEndian) { + client->format.redShift = 0; + client->format.greenShift = bitsPerSample; + client->format.blueShift = bitsPerSample * 2; + } else { + if(client->format.bitsPerPixel==8*3) { + client->format.redShift = bitsPerSample*2; + client->format.greenShift = bitsPerSample*1; + client->format.blueShift = 0; + } else { + client->format.redShift = bitsPerSample*3; + client->format.greenShift = bitsPerSample*2; + client->format.blueShift = bitsPerSample; + } + } + } + + client->bufoutptr=client->buf; + client->buffered=0; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + client->raw_buffer_size = -1; + client->decompStreamInited = FALSE; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + memset(client->zlibStreamActive,0,sizeof(rfbBool)*4); + client->jpegSrcManager = NULL; +#endif +#endif + + client->HandleCursorPos = DummyPoint; + client->SoftCursorLockArea = DummyRect; + client->SoftCursorUnlockScreen = Dummy; + client->GotFrameBufferUpdate = DummyRect; + client->FinishedFrameBufferUpdate = NULL; + client->GetPassword = ReadPassword; + client->MallocFrameBuffer = MallocFrameBuffer; + client->Bell = Dummy; + client->CurrentKeyboardLedState = 0; + client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint; + + client->authScheme = 0; + client->subAuthScheme = 0; + client->GetCredential = NULL; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + client->tlsSession = NULL; +#endif + client->sock = -1; + client->listenSock = -1; + client->clientAuthSchemes = NULL; + return client; +} + +static rfbBool rfbInitConnection(rfbClient* client) +{ + /* Unless we accepted an incoming connection, make a TCP connection to the + given VNC server */ + + if (!client->listenSpecified) { + if (!client->serverHost) + return FALSE; + if (client->destHost) { + if (!ConnectToRFBRepeater(client,client->serverHost,client->serverPort,client->destHost,client->destPort)) + return FALSE; + } else { + if (!ConnectToRFBServer(client,client->serverHost,client->serverPort)) + return FALSE; + } + } + + /* Initialise the VNC connection, including reading the password */ + + if (!InitialiseRFBConnection(client)) + return FALSE; + + if (!SetFormatAndEncodings(client)) + return FALSE; + + client->width=client->si.framebufferWidth; + client->height=client->si.framebufferHeight; + client->MallocFrameBuffer(client); + + if (client->updateRect.x < 0) { + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + } + + if (client->appData.scaleSetting>1) + { + if (!SendScaleSetting(client, client->appData.scaleSetting)) + return FALSE; + if (!SendFramebufferUpdateRequest(client, + client->updateRect.x / client->appData.scaleSetting, + client->updateRect.y / client->appData.scaleSetting, + client->updateRect.w / client->appData.scaleSetting, + client->updateRect.h / client->appData.scaleSetting, + FALSE)) + return FALSE; + } + else + { + if (!SendFramebufferUpdateRequest(client, + client->updateRect.x, client->updateRect.y, + client->updateRect.w, client->updateRect.h, + FALSE)) + return FALSE; + } + + return TRUE; +} + +rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv) { + int i,j; + + if(argv && argc && *argc) { + if(client->programName==0) + client->programName=argv[0]; + + for (i = 1; i < *argc; i++) { + j = i; + if (strcmp(argv[i], "-listen") == 0) { + listenForIncomingConnections(client); + break; + } else if (strcmp(argv[i], "-listennofork") == 0) { + listenForIncomingConnectionsNoFork(client, -1); + break; + } else if (strcmp(argv[i], "-play") == 0) { + client->serverPort = -1; + j++; + } else if (i+1<*argc && strcmp(argv[i], "-encodings") == 0) { + client->appData.encodingsString = argv[i+1]; + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-compress") == 0) { + client->appData.compressLevel = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-quality") == 0) { + client->appData.qualityLevel = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-scale") == 0) { + client->appData.scaleSetting = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-repeaterdest") == 0) { + char* colon=strchr(argv[i+1],':'); + + if(client->destHost) + free(client->destHost); + client->destPort = 5900; + + client->destHost = strdup(argv[i+1]); + if(colon) { + client->destHost[(int)(colon-argv[i+1])] = '\0'; + client->destPort = atoi(colon+1); + } + j+=2; + } else { + char* colon=strchr(argv[i],':'); + + if(client->serverHost) + free(client->serverHost); + + if(colon) { + client->serverHost = strdup(argv[i]); + client->serverHost[(int)(colon-argv[i])] = '\0'; + client->serverPort = atoi(colon+1); + } else { + client->serverHost = strdup(argv[i]); + } + if(client->serverPort >= 0 && client->serverPort < 5900) + client->serverPort += 5900; + } + /* purge arguments */ + if (j>i) { + *argc-=j-i; + memmove(argv+i,argv+j,(*argc-i)*sizeof(char*)); + i--; + } + } + } + + if(!rfbInitConnection(client)) { + rfbClientCleanup(client); + return FALSE; + } + + return TRUE; +} + +void rfbClientCleanup(rfbClient* client) { +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + int i; + + for ( i = 0; i < 4; i++ ) { + if (client->zlibStreamActive[i] == TRUE ) { + if (inflateEnd (&client->zlibStream[i]) != Z_OK && + client->zlibStream[i].msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->zlibStream[i].msg); + } + } + + if ( client->decompStreamInited == TRUE ) { + if (inflateEnd (&client->decompStream) != Z_OK && + client->decompStream.msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->decompStream.msg ); + } + + if (client->jpegSrcManager) + free(client->jpegSrcManager); +#endif +#endif + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + FreeTLS(client); +#endif + if (client->sock >= 0) + close(client->sock); + if (client->listenSock >= 0) + close(client->listenSock); + free(client->desktopName); + free(client->serverHost); + if (client->destHost) + free(client->destHost); + if (client->clientAuthSchemes) + free(client->clientAuthSchemes); + free(client); +} diff --git a/3rdParty/LibVNC/src/libvncclient/zlib.c b/3rdParty/LibVNC/src/libvncclient/zlib.c new file mode 100644 index 0000000..e872d40 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/zlib.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/* + * zlib.c - handle zlib encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zlib + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleZlibBPP CONCAT2E(HandleZlib,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleZlibBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int remaining; + int inflateResult; + int toRead; + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) { + + if ( client->raw_buffer != NULL ) { + + free( client->raw_buffer ); + + } + + client->raw_buffer_size = (( rw * rh ) * ( BPP / 8 )); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + + } + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + remaining = rfbClientSwap32IfLE(hdr.nBytes); + + /* Need to initialize the decompressor state. */ + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = 0; + client->decompStream.next_out = ( Bytef * )client->raw_buffer; + client->decompStream.avail_out = client->raw_buffer_size; + client->decompStream.data_type = Z_BINARY; + + /* Initialize the decompression stream structures on the first invocation. */ + if ( client->decompStreamInited == FALSE ) { + + inflateResult = inflateInit( &client->decompStream ); + + if ( inflateResult != Z_OK ) { + rfbClientLog( + "inflateInit returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + client->decompStreamInited = TRUE; + + } + + inflateResult = Z_OK; + + /* Process buffer full of data until no more to process, or + * some type of inflater error, or Z_STREAM_END. + */ + while (( remaining > 0 ) && + ( inflateResult == Z_OK )) { + + if ( remaining > RFB_BUFFER_SIZE ) { + toRead = RFB_BUFFER_SIZE; + } + else { + toRead = remaining; + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->buffer,toRead)) + return FALSE; + + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = toRead; + + /* Need to uncompress buffer full. */ + inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH ); + + /* We never supply a dictionary for compression. */ + if ( inflateResult == Z_NEED_DICT ) { + rfbClientLog("zlib inflate needs a dictionary!\n"); + return FALSE; + } + if ( inflateResult < 0 ) { + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + /* Result buffer allocated to be at least large enough. We should + * never run out of space! + */ + if (( client->decompStream.avail_in > 0 ) && + ( client->decompStream.avail_out <= 0 )) { + rfbClientLog("zlib inflate ran out of space!\n"); + return FALSE; + } + + remaining -= toRead; + + } /* while ( remaining > 0 ) */ + + if ( inflateResult == Z_OK ) { + + /* Put the uncompressed contents of the update on the screen. */ + CopyRectangle(client, (uint8_t *)client->raw_buffer, rx, ry, rw, rh); + } + else { + + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + + } + + return TRUE; +} + +#undef CARDBPP + +#endif diff --git a/3rdParty/LibVNC/src/libvncclient/zrle.c b/3rdParty/LibVNC/src/libvncclient/zrle.c new file mode 100644 index 0000000..da2db4b --- /dev/null +++ b/3rdParty/LibVNC/src/libvncclient/zrle.c @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2005 Johannes E. Schindelin. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/* + * zrle.c - handle zrle encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zrle + * encoded rectangle with BPP bits per pixel. + */ + +#ifndef REALBPP +#define REALBPP BPP +#endif + +#if !defined(UNCOMP) || UNCOMP==0 +#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP) +#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP) +#elif UNCOMP>0 +#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down) +#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down) +#else +#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up) +#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up) +#endif +#define CARDBPP CONCAT3E(uint,BPP,_t) +#define CARDREALBPP CONCAT3E(uint,REALBPP,_t) + +#define ENDIAN_LITTLE 0 +#define ENDIAN_BIG 1 +#define ENDIAN_NO 2 +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#undef END_FIX +#if ZYWRLE_ENDIAN == ENDIAN_LITTLE +# define END_FIX LE +#elif ZYWRLE_ENDIAN == ENDIAN_BIG +# define END_FIX BE +#else +# define END_FIX NE +#endif +#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c) +#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b) +#undef CPIXEL +#if REALBPP != BPP +#if UNCOMP == 0 +#define CPIXEL REALBPP +#elif UNCOMP>0 +#define CPIXEL CONCAT2E(REALBPP,Down) +#else +#define CPIXEL CONCAT2E(REALBPP,Up) +#endif +#endif +#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t) +#if BPP!=8 +#define ZYWRLE_DECODE 1 +#include "../libvncserver/zywrletemplate.c" +#endif +#undef CPIXEL + +static int HandleZRLETile(rfbClient* client, + uint8_t* buffer,size_t buffer_length, + int x,int y,int w,int h); + +static rfbBool +HandleZRLE (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZRLEHeader header; + int remaining; + int inflateResult; + int toRead; + int min_buffer_size = rw * rh * (REALBPP / 8) * 2; + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed REALBPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < min_buffer_size) { + + if ( client->raw_buffer != NULL ) { + + free( client->raw_buffer ); + + } + + client->raw_buffer_size = min_buffer_size; + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + + } + + if (!ReadFromRFBServer(client, (char *)&header, sz_rfbZRLEHeader)) + return FALSE; + + remaining = rfbClientSwap32IfLE(header.length); + + /* Need to initialize the decompressor state. */ + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = 0; + client->decompStream.next_out = ( Bytef * )client->raw_buffer; + client->decompStream.avail_out = client->raw_buffer_size; + client->decompStream.data_type = Z_BINARY; + + /* Initialize the decompression stream structures on the first invocation. */ + if ( client->decompStreamInited == FALSE ) { + + inflateResult = inflateInit( &client->decompStream ); + + if ( inflateResult != Z_OK ) { + rfbClientLog( + "inflateInit returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + client->decompStreamInited = TRUE; + + } + + inflateResult = Z_OK; + + /* Process buffer full of data until no more to process, or + * some type of inflater error, or Z_STREAM_END. + */ + while (( remaining > 0 ) && + ( inflateResult == Z_OK )) { + + if ( remaining > RFB_BUFFER_SIZE ) { + toRead = RFB_BUFFER_SIZE; + } + else { + toRead = remaining; + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->buffer,toRead)) + return FALSE; + + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = toRead; + + /* Need to uncompress buffer full. */ + inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH ); + + /* We never supply a dictionary for compression. */ + if ( inflateResult == Z_NEED_DICT ) { + rfbClientLog("zlib inflate needs a dictionary!\n"); + return FALSE; + } + if ( inflateResult < 0 ) { + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + /* Result buffer allocated to be at least large enough. We should + * never run out of space! + */ + if (( client->decompStream.avail_in > 0 ) && + ( client->decompStream.avail_out <= 0 )) { + rfbClientLog("zlib inflate ran out of space!\n"); + return FALSE; + } + + remaining -= toRead; + + } /* while ( remaining > 0 ) */ + + if ( inflateResult == Z_OK ) { + void* buf=client->raw_buffer; + int i,j; + + remaining = client->raw_buffer_size-client->decompStream.avail_out; + + for(j=0; jrw)?rw-i:rfbZRLETileWidth; + int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight; + int result=HandleZRLETile(client,buf,remaining,rx+i,ry+j,subWidth,subHeight); + + if(result<0) { + rfbClientLog("ZRLE decoding failed (%d)\n",result); +return TRUE; + return FALSE; + } + + buf+=result; + remaining-=result; + } + } + else { + + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + + } + + return TRUE; +} + +#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0 +#if UNCOMP>0 +#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP) +#else +#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP))) +#endif +#else +#define UncompressCPixel(pointer) (*(CARDBPP*)pointer) +#endif + +static int HandleZRLETile(rfbClient* client, + uint8_t* buffer,size_t buffer_length, + int x,int y,int w,int h) { + uint8_t* buffer_copy = buffer; + uint8_t* buffer_end = buffer+buffer_length; + uint8_t type; +#if BPP!=8 + uint8_t zywrle_level = (client->appData.qualityLevel & 0x80) ? + 0 : (3 - client->appData.qualityLevel / 3); +#endif + + if(buffer_length<1) + return -2; + + type = *buffer; + buffer++; + { + if( type == 0 ) /* raw */ +#if BPP!=8 + if( zywrle_level > 0 ){ + CARDBPP* pFrame = (CARDBPP*)client->frameBuffer + y*client->width+x; + int ret; + client->appData.qualityLevel |= 0x80; + ret = HandleZRLETile(client, buffer, buffer_end-buffer, x, y, w, h); + client->appData.qualityLevel &= 0x7F; + if( ret < 0 ){ + return ret; + } + ZYWRLE_SYNTHESIZE( pFrame, pFrame, w, h, client->width, zywrle_level, (int*)client->zlib_buffer ); + buffer += ret; + }else +#endif + { +#if REALBPP!=BPP + int i,j; + + if(1+w*h*REALBPP/8>buffer_length) { + rfbClientLog("expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h); + return -3; + } + + for(j=y*client->width; j<(y+h)*client->width; j+=client->width) + for(i=x; iframeBuffer)[j+i] = UncompressCPixel(buffer); +#else + CopyRectangle(client, buffer, x, y, w, h); + buffer+=w*h*REALBPP/8; +#endif + } + else if( type == 1 ) /* solid */ + { + CARDBPP color = UncompressCPixel(buffer); + + if(1+REALBPP/8>buffer_length) + return -4; + + FillRectangle(client, x, y, w, h, color); + + buffer+=REALBPP/8; + + } + else if( (type >= 2)&&(type <= 127) ) /* packed Palette */ + { + CARDBPP palette[16]; + int i,j,shift, + bpp=(type>4?(type>16?8:4):(type>2?2:1)), + mask=(1<buffer_length) + return -5; + + /* read palette */ + for(i=0; iwidth; j<(y+h)*client->width; j+=client->width) { + for(i=x,shift=8-bpp; iframeBuffer)[j+i] = palette[((*buffer)>>shift)&mask]; + shift-=bpp; + if(shift<0) { + shift=8-bpp; + buffer++; + } + } + if(shift<8-bpp) + buffer++; + } + + } + /* case 17 ... 127: not used, but valid */ + else if( type == 128 ) /* plain RLE */ + { + int i=0,j=0; + while(jbuffer_end) + return -7; + color = UncompressCPixel(buffer); + buffer+=REALBPP/8; + /* read run length */ + length=1; + while(*buffer==0xff) { + if(buffer+1>=buffer_end) + return -8; + length+=*buffer; + buffer++; + } + length+=*buffer; + buffer++; + while(j0) { + ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color; + length--; + i++; + if(i>=w) { + i=0; + j++; + } + } + if(length>0) + rfbClientLog("Warning: possible ZRLE corruption\n"); + } + + } + else if( type == 129 ) /* unused */ + { + return -8; + } + else if( (type >= 130)&&(type <= 255) ) /* palette RLE */ + { + CARDBPP palette[128]; + int i,j; + + if(2+(type-128)*REALBPP/8>buffer_length) + return -9; + + /* read palette */ + for(i=0; i=buffer_end) + return -10; + color = palette[(*buffer)&0x7f]; + length=1; + if(*buffer&0x80) { + if(buffer+1>=buffer_end) + return -11; + buffer++; + /* read run length */ + while(*buffer==0xff) { + if(buffer+1>=buffer_end) + return -8; + length+=*buffer; + buffer++; + } + length+=*buffer; + } + buffer++; + while(j0) { + ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color; + length--; + i++; + if(i>=w) { + i=0; + j++; + } + } + if(length>0) + rfbClientLog("Warning: possible ZRLE corruption\n"); + } + } + } + + return buffer-buffer_copy; +} + +#undef CARDBPP +#undef CARDREALBPP +#undef HandleZRLE +#undef HandleZRLETile +#undef UncompressCPixel +#undef REALBPP + +#endif + +#undef UNCOMP diff --git a/3rdParty/LibVNC/src/libvncserver/d3des.c b/3rdParty/LibVNC/src/libvncserver/d3des.c new file mode 100755 index 0000000..2df1aab --- /dev/null +++ b/3rdParty/LibVNC/src/libvncserver/d3des.c @@ -0,0 +1,436 @@ +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. Also the bytebit[] array + * has been reversed so that the most significant bit in each byte of the + * key is ignored, not the least significant. + * + * These changes are: + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* D3DES (V5.09) - + * + * A portable, public domain, version of the Data Encryption Standard. + * + * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. + * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation + * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis + * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, + * for humouring me on. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. + * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. + */ + +#include "d3des.h" + +static void scrunch(unsigned char *, unsigned long *); +static void unscrun(unsigned long *, unsigned char *); +static void desfunc(unsigned long *, unsigned long *); +static void cookey(unsigned long *); + +static unsigned long KnL[32] = { 0L }; +/* +static unsigned long KnR[32] = { 0L }; +static unsigned long Kn3[32] = { 0L }; +static unsigned char Df_Key[24] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; +*/ + +static unsigned short bytebit[8] = { + 01, 02, 04, 010, 020, 040, 0100, 0200 }; + +static unsigned long bigbyte[24] = { + 0x800000L, 0x400000L, 0x200000L, 0x100000L, + 0x80000L, 0x40000L, 0x20000L, 0x10000L, + 0x8000L, 0x4000L, 0x2000L, 0x1000L, + 0x800L, 0x400L, 0x200L, 0x100L, + 0x80L, 0x40L, 0x20L, 0x10L, + 0x8L, 0x4L, 0x2L, 0x1L }; + +/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ + +static unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; + +static unsigned char totrot[16] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; + +static unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; + +void rfbDesKey(unsigned char *key, + int edf) +{ + register int i, j, l, m, n; + unsigned char pc1m[56], pcr[56]; + unsigned long kn[32]; + + for ( j = 0; j < 56; j++ ) { + l = pc1[j]; + m = l & 07; + pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; + } + for( i = 0; i < 16; i++ ) { + if( edf == DE1 ) m = (15 - i) << 1; + else m = i << 1; + n = m + 1; + kn[m] = kn[n] = 0L; + for( j = 0; j < 28; j++ ) { + l = j + totrot[i]; + if( l < 28 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 28; j < 56; j++ ) { + l = j + totrot[i]; + if( l < 56 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 0; j < 24; j++ ) { + if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; + if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; + } + } + cookey(kn); + return; + } + +static void cookey(register unsigned long *raw1) +{ + register unsigned long *cook, *raw0; + unsigned long dough[32]; + register int i; + + cook = dough; + for( i = 0; i < 16; i++, raw1++ ) { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + rfbUseKey(dough); + return; + } + +void rfbCPKey(register unsigned long *into) +{ + register unsigned long *from, *endp; + + from = KnL, endp = &KnL[32]; + while( from < endp ) *into++ = *from++; + return; + } + +void rfbUseKey(register unsigned long *from) +{ + register unsigned long *to, *endp; + + to = KnL, endp = &KnL[32]; + while( to < endp ) *to++ = *from++; + return; + } + +void rfbDes(unsigned char *inblock, + unsigned char *outblock) +{ + unsigned long work[2]; + + scrunch(inblock, work); + desfunc(work, KnL); + unscrun(work, outblock); + return; + } + +static void scrunch(register unsigned char *outof, + register unsigned long *into) +{ + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into++ |= (*outof++ & 0xffL); + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into |= (*outof & 0xffL); + return; + } + +static void unscrun(register unsigned long *outof, + register unsigned char *into) +{ + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into++ = (unsigned char)( *outof++ & 0xffL); + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into = (unsigned char)( *outof & 0xffL); + return; + } + +static unsigned long SP1[64] = { + 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, + 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, + 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, + 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, + 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, + 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, + 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, + 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, + 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, + 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, + 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, + 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, + 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, + 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; + +static unsigned long SP2[64] = { + 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, + 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, + 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, + 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, + 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, + 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, + 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, + 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, + 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, + 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, + 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, + 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, + 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, + 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, + 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, + 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; + +static unsigned long SP3[64] = { + 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, + 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, + 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, + 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, + 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, + 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, + 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, + 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, + 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, + 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, + 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, + 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, + 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, + 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, + 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, + 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; + +static unsigned long SP4[64] = { + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, + 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, + 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, + 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, + 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, + 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, + 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, + 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, + 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; + +static unsigned long SP5[64] = { + 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, + 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, + 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, + 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, + 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, + 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, + 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, + 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, + 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, + 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, + 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, + 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, + 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, + 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, + 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, + 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; + +static unsigned long SP6[64] = { + 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, + 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, + 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, + 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, + 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, + 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, + 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, + 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, + 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, + 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, + 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, + 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, + 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, + 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; + +static unsigned long SP7[64] = { + 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, + 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, + 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, + 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, + 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, + 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, + 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, + 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, + 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, + 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, + 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, + 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, + 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, + 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, + 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, + 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; + +static unsigned long SP8[64] = { + 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, + 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, + 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, + 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, + 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, + 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, + 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, + 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, + 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, + 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, + 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, + 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, + 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, + 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, + 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, + 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; + +static void desfunc(register unsigned long *block, + register unsigned long *keys) +{ + register unsigned long fval, work, right, leftt; + register int round; + + leftt = block[0]; + right = block[1]; + work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; + right ^= work; + leftt ^= (work << 4); + work = ((leftt >> 16) ^ right) & 0x0000ffffL; + right ^= work; + leftt ^= (work << 16); + work = ((right >> 2) ^ leftt) & 0x33333333L; + leftt ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ leftt) & 0x00ff00ffL; + leftt ^= work; + right ^= (work << 8); + right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; + + for( round = 0; round < 8; round++ ) { + work = (right << 28) | (right >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + leftt ^= fval; + work = (leftt << 28) | (leftt >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + right ^= fval; + } + + right = (right << 31) | (right >> 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = (leftt << 31) | (leftt >> 1); + work = ((leftt >> 8) ^ right) & 0x00ff00ffL; + right ^= work; + leftt ^= (work << 8); + work = ((leftt >> 2) ^ right) & 0x33333333L; + right ^= work; + leftt ^= (work << 2); + work = ((right >> 16) ^ leftt) & 0x0000ffffL; + leftt ^= work; + right ^= (work << 16); + work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; + leftt ^= work; + right ^= (work << 4); + *block++ = right; + *block = leftt; + return; + } + +/* Validation sets: + * + * Single-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef + * Plain : 0123 4567 89ab cde7 + * Cipher : c957 4425 6a5e d31d + * + * Double-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cde7 + * Cipher : 7f1d 0a77 826b 8aff + * + * Double-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 + * + * Triple-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cde7 + * Cipher : de0b 7c06 ae5e 0ed5 + * + * Triple-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 + * + * d3des V5.0a rwo 9208.07 18:44 Graven Imagery + **********************************************************************/ diff --git a/3rdParty/LibVNC/src/libvncserver/d3des.h b/3rdParty/LibVNC/src/libvncserver/d3des.h new file mode 100755 index 0000000..e3761ca --- /dev/null +++ b/3rdParty/LibVNC/src/libvncserver/d3des.h @@ -0,0 +1,56 @@ +#ifndef D3DES_H +#define D3DES_H + +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. + * + * These changes are: + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* d3des.h - + * + * Headers and defines for d3des.c + * Graven Imagery, 1992. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge + * (GEnie : OUTER; CIS : [71755,204]) + */ + +#define EN0 0 /* MODE == encrypt */ +#define DE1 1 /* MODE == decrypt */ + +extern void rfbDesKey(unsigned char *, int); +/* hexkey[8] MODE + * Sets the internal key register according to the hexadecimal + * key contained in the 8 bytes of hexkey, according to the DES, + * for encryption or decryption according to MODE. + */ + +extern void rfbUseKey(unsigned long *); +/* cookedkey[32] + * Loads the internal key register with the data in cookedkey. + */ + +extern void rfbCPKey(unsigned long *); +/* cookedkey[32] + * Copies the contents of the internal key register into the storage + * located at &cookedkey[0]. + */ + +extern void rfbDes(unsigned char *, unsigned char *); +/* from[8] to[8] + * Encrypts/Decrypts (according to the key currently loaded in the + * internal key register) one block of eight bytes at address 'from' + * into the block at address 'to'. They can be the same. + */ + +/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery + ********************************************************************/ + +#endif diff --git a/3rdParty/LibVNC/src/libvncserver/vncauth.c b/3rdParty/LibVNC/src/libvncserver/vncauth.c new file mode 100644 index 0000000..0b73531 --- /dev/null +++ b/3rdParty/LibVNC/src/libvncserver/vncauth.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * vncauth.c - Functions for VNC password management and authentication. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif +#include +#include +#include +#include +#include "d3des.h" + +#include +#include + +#ifdef LIBVNCSERVER_HAVE_SYS_STAT_H +#include +#endif + +#include + +#ifdef WIN32 +#define srandom srand +#define random rand +#else +#include +#endif + + +/* libvncclient does not need this */ +#ifndef rfbEncryptBytes + +/* + * We use a fixed key to store passwords, since we assume that our local + * file system is secure but nonetheless don't want to store passwords + * as plaintext. + */ + +static unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7}; + + +/* + * Encrypt a password and store it in a file. Returns 0 if successful, + * 1 if the file could not be written. + */ + +int +rfbEncryptAndStorePasswd(char *passwd, char *fname) +{ + FILE *fp; + unsigned int i; + unsigned char encryptedPasswd[8]; + + if ((fp = fopen(fname,"w")) == NULL) return 1; + + /* windows security sux */ +#ifndef WIN32 + fchmod(fileno(fp), S_IRUSR|S_IWUSR); +#endif + + /* pad password with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + encryptedPasswd[i] = passwd[i]; + } else { + encryptedPasswd[i] = 0; + } + } + + /* Do encryption in-place - this way we overwrite our copy of the plaintext + password */ + + rfbDesKey(fixedkey, EN0); + rfbDes(encryptedPasswd, encryptedPasswd); + + for (i = 0; i < 8; i++) { + putc(encryptedPasswd[i], fp); + } + + fclose(fp); + return 0; +} + + +/* + * Decrypt a password from a file. Returns a pointer to a newly allocated + * string containing the password or a null pointer if the password could + * not be retrieved for some reason. + */ + +char * +rfbDecryptPasswdFromFile(char *fname) +{ + FILE *fp; + int i, ch; + unsigned char *passwd = (unsigned char *)malloc(9); + + if ((fp = fopen(fname,"r")) == NULL) return NULL; + + for (i = 0; i < 8; i++) { + ch = getc(fp); + if (ch == EOF) { + fclose(fp); + return NULL; + } + passwd[i] = ch; + } + + fclose(fp); + + rfbDesKey(fixedkey, DE1); + rfbDes(passwd, passwd); + + passwd[8] = 0; + + return (char *)passwd; +} + + +/* + * Generate CHALLENGESIZE random bytes for use in challenge-response + * authentication. + */ + +void +rfbRandomBytes(unsigned char *bytes) +{ + int i; + static rfbBool s_srandom_called = FALSE; + + if (!s_srandom_called) { + srandom((unsigned int)time(NULL) ^ (unsigned int)getpid()); + s_srandom_called = TRUE; + } + + for (i = 0; i < CHALLENGESIZE; i++) { + bytes[i] = (unsigned char)(random() & 255); + } +} + +#endif + +/* + * Encrypt CHALLENGESIZE bytes in memory using a password. + */ + +void +rfbEncryptBytes(unsigned char *bytes, char *passwd) +{ + unsigned char key[8]; + unsigned int i; + + /* key is simply password padded with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + key[i] = passwd[i]; + } else { + key[i] = 0; + } + } + + rfbDesKey(key, EN0); + + for (i = 0; i < CHALLENGESIZE; i += 8) { + rfbDes(bytes+i, bytes+i); + } +} + +void +rfbEncryptBytes2(unsigned char *where, const int length, unsigned char *key) { + int i, j; + rfbDesKey(key, EN0); + for (i = 0; i< 8; i++) + where[i] ^= key[i]; + rfbDes(where, where); + for (i = 8; i < length; i += 8) { + for (j = 0; j < 8; j++) + where[i + j] ^= where[i + j - 8]; + rfbDes(where + i, where + i); + } +} + diff --git a/3rdParty/LibVNC/src/libvncserver/zywrletemplate.c b/3rdParty/LibVNC/src/libvncserver/zywrletemplate.c new file mode 100644 index 0000000..52b2b0b --- /dev/null +++ b/3rdParty/LibVNC/src/libvncserver/zywrletemplate.c @@ -0,0 +1,824 @@ + +/******************************************************************** + * * + * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE. * + * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006 * + * BY Hitachi Systems & Services, Ltd. * + * (Noriaki Yamazaki, Research & Developement Center) * * + * * + ******************************************************************** +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Hitachi Systems & Services, Ltd. nor +the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************/ + +/* Change Log: + V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline + (Thanks Johannes Schindelin, author of LibVNC + Server/Client) + V0.01 : 2007/02/06 : Initial release +*/ + +/* #define ZYWRLE_ENCODE */ +/* #define ZYWRLE_DECODE */ +#define ZYWRLE_QUANTIZE + +/* +[References] + PLHarr: + Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380. + EZW: + Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993). +*/ + + +/* Template Macro stuffs. */ +#undef ZYWRLE_ANALYZE +#undef ZYWRLE_SYNTHESIZE +#define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX) +#define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX) + +#define ZYWRLE_RGBYUV __RFB_CONCAT3E(zywrleRGBYUV,BPP,END_FIX) +#define ZYWRLE_YUVRGB __RFB_CONCAT3E(zywrleYUVRGB,BPP,END_FIX) +#define ZYWRLE_YMASK __RFB_CONCAT2E(ZYWRLE_YMASK,BPP) +#define ZYWRLE_UVMASK __RFB_CONCAT2E(ZYWRLE_UVMASK,BPP) +#define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP) +#define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP) + +/* Packing/Unpacking pixel stuffs. + Endian conversion stuffs. */ +#undef S_0 +#undef S_1 +#undef L_0 +#undef L_1 +#undef L_2 +#if ZYWRLE_ENDIAN == ENDIAN_BIG +# define S_0 1 +# define S_1 0 +# define L_0 3 +# define L_1 2 +# define L_2 1 +#else +# define S_0 0 +# define S_1 1 +# define L_0 0 +# define L_1 1 +# define L_2 2 +#endif + +/* Load/Save pixel stuffs. */ +#define ZYWRLE_YMASK15 0xFFFFFFF8 +#define ZYWRLE_UVMASK15 0xFFFFFFF8 +#define ZYWRLE_LOAD_PIXEL15(pSrc,R,G,B) { \ + R = (((unsigned char*)pSrc)[S_1]<< 1)& 0xF8; \ + G = ((((unsigned char*)pSrc)[S_1]<< 6)|(((unsigned char*)pSrc)[S_0]>> 2))& 0xF8; \ + B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \ +} +#define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \ + R &= 0xF8; \ + G &= 0xF8; \ + B &= 0xF8; \ + ((unsigned char*)pDst)[S_1] = (unsigned char)( (R>>1)|(G>>6) ); \ + ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<2))& 0xFF); \ +} +#define ZYWRLE_YMASK16 0xFFFFFFFC +#define ZYWRLE_UVMASK16 0xFFFFFFF8 +#define ZYWRLE_LOAD_PIXEL16(pSrc,R,G,B) { \ + R = ((unsigned char*)pSrc)[S_1] & 0xF8; \ + G = ((((unsigned char*)pSrc)[S_1]<< 5)|(((unsigned char*)pSrc)[S_0]>> 3))& 0xFC; \ + B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \ +} +#define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \ + R &= 0xF8; \ + G &= 0xFC; \ + B &= 0xF8; \ + ((unsigned char*)pDst)[S_1] = (unsigned char)( R |(G>>5) ); \ + ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF); \ +} +#define ZYWRLE_YMASK32 0xFFFFFFFF +#define ZYWRLE_UVMASK32 0xFFFFFFFF +#define ZYWRLE_LOAD_PIXEL32(pSrc,R,G,B) { \ + R = ((unsigned char*)pSrc)[L_2]; \ + G = ((unsigned char*)pSrc)[L_1]; \ + B = ((unsigned char*)pSrc)[L_0]; \ +} +#define ZYWRLE_SAVE_PIXEL32(pDst,R,G,B) { \ + ((unsigned char*)pDst)[L_2] = (unsigned char)R; \ + ((unsigned char*)pDst)[L_1] = (unsigned char)G; \ + ((unsigned char*)pDst)[L_0] = (unsigned char)B; \ +} + +#ifndef ZYWRLE_ONCE +#define ZYWRLE_ONCE + +#ifdef WIN32 +#define InlineX __inline +#else +#define InlineX inline +#endif + +#ifdef ZYWRLE_ENCODE +/* Tables for Coefficients filtering. */ +# ifndef ZYWRLE_QUANTIZE +/* Type A:lower bit omitting of EZW style. */ +const static unsigned int zywrleParam[3][3]={ + {0x0000F000,0x00000000,0x00000000}, + {0x0000C000,0x00F0F0F0,0x00000000}, + {0x0000C000,0x00C0C0C0,0x00F0F0F0}, +/* {0x0000FF00,0x00000000,0x00000000}, + {0x0000FF00,0x00FFFFFF,0x00000000}, + {0x0000FF00,0x00FFFFFF,0x00FFFFFF}, */ +}; +# else +/* Type B:Non liner quantization filter. */ +static const signed char zywrleConv[4][256]={ +{ /* bi=5, bo=5 r=0.0:PSNR=24.849 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=5 r=2.0:PSNR=74.031 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 64, 64, 64, 64, + 64, 64, 64, 64, 72, 72, 72, 72, + 72, 72, 72, 72, 80, 80, 80, 80, + 80, 80, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 96, 96, + 96, 96, 96, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 0, -120, -120, -120, -120, -120, -120, -120, + -120, -120, -120, -112, -112, -112, -112, -112, + -112, -112, -112, -112, -104, -104, -104, -104, + -104, -104, -104, -104, -104, -104, -96, -96, + -96, -96, -96, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -80, + -80, -80, -80, -80, -80, -72, -72, -72, + -72, -72, -72, -72, -72, -64, -64, -64, + -64, -64, -64, -64, -64, -56, -56, -56, + -56, -56, -56, -56, -56, -56, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=4 r=2.0:PSNR=64.441 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 0, -120, -120, -120, -120, -120, -120, -120, + -120, -120, -120, -120, -120, -112, -112, -112, + -112, -112, -112, -112, -112, -112, -104, -104, + -104, -104, -104, -104, -104, -104, -104, -104, + -104, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, + -80, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, + -64, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=2 r=2.0:PSNR=43.175 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 0, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +} +}; +const static signed char* zywrleParam[3][3][3]={ + {{zywrleConv[0],zywrleConv[2],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}}, + {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}}, + {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[2],zywrleConv[2],zywrleConv[2]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]}}, +}; +# endif +#endif + +static InlineX void Harr(signed char* pX0, signed char* pX1) +{ + /* Piecewise-Linear Harr(PLHarr) */ + int X0 = (int)*pX0, X1 = (int)*pX1; + int orgX0 = X0, orgX1 = X1; + if ((X0 ^ X1) & 0x80) { + /* differ sign */ + X1 += X0; + if (((X1^orgX1)&0x80)==0) { + /* |X1| > |X0| */ + X0 -= X1; /* H = -B */ + } + } else { + /* same sign */ + X0 -= X1; + if (((X0 ^ orgX0) & 0x80) == 0) { + /* |X0| > |X1| */ + X1 += X0; /* L = A */ + } + } + *pX0 = (signed char)X1; + *pX1 = (signed char)X0; +} +/* + 1D-Wavelet transform. + + In coefficients array, the famous 'pyramid' decomposition is well used. + + 1D Model: + |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0 + |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1 + + But this method needs line buffer because H/L is different position from X0/X1. + So, I used 'interleave' decomposition instead of it. + + 1D Model: + |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0 + |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1 + + In this method, H/L and X0/X1 is always same position. + This lead us to more speed and less memory. + Of cause, the result of both method is quite same + because it's only difference that coefficient position. +*/ +static InlineX void WaveletLevel(int* data, int size, int l, int SkipPixel) +{ + int s, ofs; + signed char* pX0; + signed char* end; + + pX0 = (signed char*)data; + s = (8<>(l+1))*s; + s -= 2; + ofs = (4<>1; + if (r & 0x02) + pH += (s>>1)*width; + for (y = 0; y < height / s; y++) { + for (x = 0; x < width / s; x++) { + /* + these are same following code. + pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1); + ( round pH[x] with pM[x] bit ) + '&' operator isn't 'round' but is 'floor'. + So, we must offset when pH[x] is negative. + */ + if (((signed char*)pH)[0] & 0x80) + ((signed char*)pH)[0] += ~((signed char*)pM)[0]; + if (((signed char*)pH)[1] & 0x80) + ((signed char*)pH)[1] += ~((signed char*)pM)[1]; + if (((signed char*)pH)[2] & 0x80) + ((signed char*)pH)[2] += ~((signed char*)pM)[2]; + *pH &= *pM; + pH += s; + } + pH += (s-1)*width; + } + } +} +# else +/* + Type B:Non liner quantization filter. + + Coefficients have Gaussian curve and smaller value which is + large part of coefficients isn't more important than larger value. + So, I use filter of Non liner quantize/dequantize table. + In general, Non liner quantize formula is explained as following. + + y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo) + x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi) + ( r:power coefficient bi:effective MSB in input bo:effective MSB in output ) + + r < 1.0 : Smaller value is more important than larger value. + r > 1.0 : Larger value is more important than smaller value. + r = 1.0 : Liner quantization which is same with EZW style. + + r = 0.75 is famous non liner quantization used in MP3 audio codec. + In contrast to audio data, larger value is important in wavelet coefficients. + So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ). + + As compared with EZW style liner quantization, this filter tended to be + more sharp edge and be more compression rate but be more blocking noise and be less quality. + Especially, the surface of graphic objects has distinguishable noise in middle quality mode. + + We need only quantized-dequantized(filtered) value rather than quantized value itself + because all values are packed or palette-lized in later ZRLE section. + This lead us not to need to modify client decoder when we change + the filtering procedure in future. + Client only decodes coefficients given by encoder. +*/ +static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l) +{ + int r, s; + int x, y; + int* pH; + const signed char** pM; + + pM = zywrleParam[level-1][l]; + s = 2<>1; + if (r & 0x02) + pH += (s>>1)*width; + for (y = 0; y < height / s; y++) { + for (x = 0; x < width / s; x++) { + ((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]]; + ((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]]; + ((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]]; + pH += s; + } + pH += (s-1)*width; + } + } +} +# endif + +static InlineX void Wavelet(int* pBuf, int width, int height, int level) +{ + int l, s; + int* pTop; + int* pEnd; + + for (l = 0; l < level; l++) { + pTop = pBuf; + pEnd = pBuf+height*width; + s = width<= 0; l--) { + pTop = pBuf; + pEnd = pBuf+width; + s = 1< YUV conversion stuffs. + YUV coversion is explained as following formula in strict meaning: + Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255) + U = -0.169R - 0.331G + 0.500B (-128<=U<=127) + V = 0.500R - 0.419G - 0.081B (-128<=V<=127) + + I use simple conversion RCT(reversible color transform) which is described + in JPEG-2000 specification. + Y = (R + 2G + B)/4 ( 0<=Y<=255) + U = B-G (-256<=U<=255) + V = R-G (-256<=V<=255) +*/ +#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x))) + /* RCT is N-bit RGB to N-bit Y and N+1-bit UV. + For make Same N-bit, UV is lossy. + More exact PLHarr, we reduce to odd range(-127<=x<=127). */ +#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \ + Y = (R+(G<<1)+B)>>2; \ + U = B-G; \ + V = R-G; \ + Y -= 128; \ + U >>= 1; \ + V >>= 1; \ + Y &= ymask; \ + U &= uvmask; \ + V &= uvmask; \ + if (Y == -128) \ + Y += (0xFFFFFFFF-ymask+1); \ + if (U == -128) \ + U += (0xFFFFFFFF-uvmask+1); \ + if (V == -128) \ + V += (0xFFFFFFFF-uvmask+1); \ +} +#define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \ + Y += 128; \ + U <<= 1; \ + V <<= 1; \ + G = Y-((U+V)>>2); \ + B = U+G; \ + R = V+G; \ + G = ROUND(G); \ + B = ROUND(B); \ + R = ROUND(R); \ +} + +/* + coefficient packing/unpacking stuffs. + Wavelet transform makes 4 sub coefficient image from 1 original image. + + model with pyramid decomposition: + +------+------+ + | | | + | L | Hx | + | | | + +------+------+ + | | | + | H | Hxy | + | | | + +------+------+ + + So, we must transfer each sub images individually in strict meaning. + But at least ZRLE meaning, following one decompositon image is same as + avobe individual sub image. I use this format. + (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L) + for simplified procedure for any wavelet level.) + + +------+------+ + | L | + +------+------+ + | Hx | + +------+------+ + | Hy | + +------+------+ + | Hxy | + +------+------+ +*/ +#define INC_PTR(data) \ + data++; \ + if( data-pData >= (w+uw) ){ \ + data += scanline-(w+uw); \ + pData = data; \ + } + +#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS) \ + pH = pBuf; \ + s = 2<>1; \ + if (r & 0x02) \ + pH += (s>>1)*w; \ + pEnd = pH+h*w; \ + while (pH < pEnd) { \ + pLine = pH+w; \ + while (pH < pLine) { \ + TRANS \ + INC_PTR(data) \ + pH += s; \ + } \ + pH += (s-1)*w; \ + } + +#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,scanline,level) \ + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);) + +#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,scanline,level) \ + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);) + +#define ZYWRLE_SAVE_UNALIGN(data,TRANS) \ + pTop = pBuf+w*h; \ + pEnd = pBuf + (w+uw)*(h+uh); \ + while (pTop < pEnd) { \ + TRANS \ + INC_PTR(data) \ + pTop++; \ + } + +#define ZYWRLE_LOAD_UNALIGN(data,TRANS) \ + pTop = pBuf+w*h; \ + if (uw) { \ + pData= data + w; \ + pEnd = (int*)(pData+ h*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + uw); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-uw; \ + } \ + } \ + if (uh) { \ + pData= data + h*scanline; \ + pEnd = (int*)(pData+ uh*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + w); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-w; \ + } \ + } \ + if (uw && uh) { \ + pData= data + w+ h*scanline; \ + pEnd = (int*)(pData+ uh*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + uw); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-uw; \ + } \ + } + +static InlineX void zywrleCalcSize(int* pW, int* pH, int level) +{ + *pW &= ~((1<Hanja Conversion */ +#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */ +#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */ +#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */ +#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */ +#define XK_Hangul_Banja 0xff39 /* Banja mode */ +#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */ +#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */ +#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */ +#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */ +#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */ +#define XK_Hangul_Special 0xff3f /* Special symbols */ +#define XK_Hangul_switch 0xFF7E /* Alias for mode_switch */ + +/* Hangul Consonant Characters */ +#define XK_Hangul_Kiyeog 0xea1 +#define XK_Hangul_SsangKiyeog 0xea2 +#define XK_Hangul_KiyeogSios 0xea3 +#define XK_Hangul_Nieun 0xea4 +#define XK_Hangul_NieunJieuj 0xea5 +#define XK_Hangul_NieunHieuh 0xea6 +#define XK_Hangul_Dikeud 0xea7 +#define XK_Hangul_SsangDikeud 0xea8 +#define XK_Hangul_Rieul 0xea9 +#define XK_Hangul_RieulKiyeog 0xeaa +#define XK_Hangul_RieulMieum 0xeab +#define XK_Hangul_RieulPieub 0xeac +#define XK_Hangul_RieulSios 0xead +#define XK_Hangul_RieulTieut 0xeae +#define XK_Hangul_RieulPhieuf 0xeaf +#define XK_Hangul_RieulHieuh 0xeb0 +#define XK_Hangul_Mieum 0xeb1 +#define XK_Hangul_Pieub 0xeb2 +#define XK_Hangul_SsangPieub 0xeb3 +#define XK_Hangul_PieubSios 0xeb4 +#define XK_Hangul_Sios 0xeb5 +#define XK_Hangul_SsangSios 0xeb6 +#define XK_Hangul_Ieung 0xeb7 +#define XK_Hangul_Jieuj 0xeb8 +#define XK_Hangul_SsangJieuj 0xeb9 +#define XK_Hangul_Cieuc 0xeba +#define XK_Hangul_Khieuq 0xebb +#define XK_Hangul_Tieut 0xebc +#define XK_Hangul_Phieuf 0xebd +#define XK_Hangul_Hieuh 0xebe + +/* Hangul Vowel Characters */ +#define XK_Hangul_A 0xebf +#define XK_Hangul_AE 0xec0 +#define XK_Hangul_YA 0xec1 +#define XK_Hangul_YAE 0xec2 +#define XK_Hangul_EO 0xec3 +#define XK_Hangul_E 0xec4 +#define XK_Hangul_YEO 0xec5 +#define XK_Hangul_YE 0xec6 +#define XK_Hangul_O 0xec7 +#define XK_Hangul_WA 0xec8 +#define XK_Hangul_WAE 0xec9 +#define XK_Hangul_OE 0xeca +#define XK_Hangul_YO 0xecb +#define XK_Hangul_U 0xecc +#define XK_Hangul_WEO 0xecd +#define XK_Hangul_WE 0xece +#define XK_Hangul_WI 0xecf +#define XK_Hangul_YU 0xed0 +#define XK_Hangul_EU 0xed1 +#define XK_Hangul_YI 0xed2 +#define XK_Hangul_I 0xed3 + +/* Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_Kiyeog 0xed4 +#define XK_Hangul_J_SsangKiyeog 0xed5 +#define XK_Hangul_J_KiyeogSios 0xed6 +#define XK_Hangul_J_Nieun 0xed7 +#define XK_Hangul_J_NieunJieuj 0xed8 +#define XK_Hangul_J_NieunHieuh 0xed9 +#define XK_Hangul_J_Dikeud 0xeda +#define XK_Hangul_J_Rieul 0xedb +#define XK_Hangul_J_RieulKiyeog 0xedc +#define XK_Hangul_J_RieulMieum 0xedd +#define XK_Hangul_J_RieulPieub 0xede +#define XK_Hangul_J_RieulSios 0xedf +#define XK_Hangul_J_RieulTieut 0xee0 +#define XK_Hangul_J_RieulPhieuf 0xee1 +#define XK_Hangul_J_RieulHieuh 0xee2 +#define XK_Hangul_J_Mieum 0xee3 +#define XK_Hangul_J_Pieub 0xee4 +#define XK_Hangul_J_PieubSios 0xee5 +#define XK_Hangul_J_Sios 0xee6 +#define XK_Hangul_J_SsangSios 0xee7 +#define XK_Hangul_J_Ieung 0xee8 +#define XK_Hangul_J_Jieuj 0xee9 +#define XK_Hangul_J_Cieuc 0xeea +#define XK_Hangul_J_Khieuq 0xeeb +#define XK_Hangul_J_Tieut 0xeec +#define XK_Hangul_J_Phieuf 0xeed +#define XK_Hangul_J_Hieuh 0xeee + +/* Ancient Hangul Consonant Characters */ +#define XK_Hangul_RieulYeorinHieuh 0xeef +#define XK_Hangul_SunkyeongeumMieum 0xef0 +#define XK_Hangul_SunkyeongeumPieub 0xef1 +#define XK_Hangul_PanSios 0xef2 +#define XK_Hangul_KkogjiDalrinIeung 0xef3 +#define XK_Hangul_SunkyeongeumPhieuf 0xef4 +#define XK_Hangul_YeorinHieuh 0xef5 + +/* Ancient Hangul Vowel Characters */ +#define XK_Hangul_AraeA 0xef6 +#define XK_Hangul_AraeAE 0xef7 + +/* Ancient Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_PanSios 0xef8 +#define XK_Hangul_J_KkogjiDalrinIeung 0xef9 +#define XK_Hangul_J_YeorinHieuh 0xefa + +/* Korean currency symbol */ +#define XK_Korean_Won 0xeff + +#endif /* XK_KOREAN */ + +/* Euro currency symbol */ +#define XK_EuroSign 0x20ac + +#endif diff --git a/3rdParty/LibVNC/src/rfb/rfb.h b/3rdParty/LibVNC/src/rfb/rfb.h new file mode 100644 index 0000000..a03ab21 --- /dev/null +++ b/3rdParty/LibVNC/src/rfb/rfb.h @@ -0,0 +1,989 @@ +#ifndef RFB_H +#define RFB_H + +/* + * rfb.h - header file for RFB DDX implementation. + */ + +/* + * Copyright (C) 2005 Rohit Kumar , + * Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#if(defined __cplusplus) +extern "C" +{ +#endif + +#include +#include +#include +#include + +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif + +#ifdef __MINGW32__ +#undef SOCKET +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#include +#if 0 /* debugging */ +#define LOCK(mutex) (rfbLog("%s:%d LOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_lock(&(mutex))) +#define UNLOCK(mutex) (rfbLog("%s:%d UNLOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_unlock(&(mutex))) +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define INIT_MUTEX(mutex) (rfbLog("%s:%d INIT_MUTEX(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_init(&(mutex),NULL)) +#define TINI_MUTEX(mutex) (rfbLog("%s:%d TINI_MUTEX(%s)\n",__FILE__,__LINE__,#mutex), pthread_mutex_destroy(&(mutex))) +#define TSIGNAL(cond) (rfbLog("%s:%d TSIGNAL(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_signal(&(cond))) +#define WAIT(cond,mutex) (rfbLog("%s:%d WAIT(%s,%s)\n",__FILE__,__LINE__,#cond,#mutex), pthread_cond_wait(&(cond),&(mutex))) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) (rfbLog("%s:%d INIT_COND(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_init(&(cond),NULL)) +#define TINI_COND(cond) (rfbLog("%s:%d TINI_COND(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_destroy(&(cond))) +#define IF_PTHREADS(x) x +#else +#if !NONETWORK +#define LOCK(mutex) pthread_mutex_lock(&(mutex)); +#define UNLOCK(mutex) pthread_mutex_unlock(&(mutex)); +#endif +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define INIT_MUTEX(mutex) pthread_mutex_init(&(mutex),NULL) +#define TINI_MUTEX(mutex) pthread_mutex_destroy(&(mutex)) +#define TSIGNAL(cond) pthread_cond_signal(&(cond)) +#define WAIT(cond,mutex) pthread_cond_wait(&(cond),&(mutex)) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) pthread_cond_init(&(cond),NULL) +#define TINI_COND(cond) pthread_cond_destroy(&(cond)) +#define IF_PTHREADS(x) x +#endif +#else +#define LOCK(mutex) +#define UNLOCK(mutex) +#define MUTEX(mutex) +#define INIT_MUTEX(mutex) +#define TINI_MUTEX(mutex) +#define TSIGNAL(cond) +#define WAIT(cond,mutex) this_is_unsupported +#define COND(cond) +#define INIT_COND(cond) +#define TINI_COND(cond) +#define IF_PTHREADS(x) +#endif + +/* end of stuff for autoconf */ + +/* if you use pthreads, but don't define LIBVNCSERVER_HAVE_LIBPTHREAD, the structs + get all mixed up. So this gives a linker error reminding you to compile + the library and your application (at least the parts including rfb.h) + with the same support for pthreads. */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#ifdef LIBVNCSERVER_HAVE_LIBZ +#define rfbInitServer rfbInitServerWithPthreadsAndZRLE +#else +#define rfbInitServer rfbInitServerWithPthreadsButWithoutZRLE +#endif +#else +#ifdef LIBVNCSERVER_HAVE_LIBZ +#define rfbInitServer rfbInitServerWithoutPthreadsButWithZRLE +#else +#define rfbInitServer rfbInitServerWithoutPthreadsAndZRLE +#endif +#endif + +struct _rfbClientRec; +struct _rfbScreenInfo; +struct rfbCursor; + +enum rfbNewClientAction { + RFB_CLIENT_ACCEPT, + RFB_CLIENT_ON_HOLD, + RFB_CLIENT_REFUSE +}; + +enum rfbSocketState { + RFB_SOCKET_INIT, + RFB_SOCKET_READY, + RFB_SOCKET_SHUTDOWN +}; + +typedef void (*rfbKbdAddEventProcPtr) (rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl); +typedef void (*rfbKbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl); +typedef void (*rfbPtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl); +typedef void (*rfbSetXCutTextProcPtr) (char* str,int len, struct _rfbClientRec* cl); +typedef struct rfbCursor* (*rfbGetCursorProcPtr) (struct _rfbClientRec* pScreen); +typedef rfbBool (*rfbSetTranslateFunctionProcPtr)(struct _rfbClientRec* cl); +typedef rfbBool (*rfbPasswordCheckProcPtr)(struct _rfbClientRec* cl,const char* encryptedPassWord,int len); +typedef enum rfbNewClientAction (*rfbNewClientHookPtr)(struct _rfbClientRec* cl); +typedef void (*rfbDisplayHookPtr)(struct _rfbClientRec* cl); +/* support the capability to view the caps/num/scroll states of the X server */ +typedef int (*rfbGetKeyboardLedStateHookPtr)(struct _rfbScreenInfo* screen); +/* If x==1 and y==1 then set the whole display + * else find the window underneath x and y and set the framebuffer to the dimensions + * of that window + */ +typedef void (*rfbSetSingleWindowProcPtr) (struct _rfbClientRec* cl, int x, int y); +/* Status determines if the X11 server permits input from the local user + * status==0 or 1 + */ +typedef void (*rfbSetServerInputProcPtr) (struct _rfbClientRec* cl, int status); +/* Permit the server to allow or deny filetransfers. This is defaulted to deny + * It is called when a client initiates a connection to determine if it is permitted. + */ +typedef int (*rfbFileTransferPermitted) (struct _rfbClientRec* cl); +/* Handle the textchat messages */ +typedef void (*rfbSetTextChat) (struct _rfbClientRec* cl, int length, char *string); + +typedef struct { + uint32_t count; + rfbBool is16; /* is the data format short? */ + union { + uint8_t* bytes; + uint16_t* shorts; + } data; /* there have to be count*3 entries */ +} rfbColourMap; + +/* + * Security handling (RFB protocol version 3.7) + */ + +typedef struct _rfbSecurity { + uint8_t type; + void (*handler)(struct _rfbClientRec* cl); + struct _rfbSecurity* next; +} rfbSecurityHandler; + +/* + * Protocol extension handling. + */ + +typedef struct _rfbProtocolExtension { + /* returns FALSE if extension should be deactivated for client. + if newClient == NULL, it is always deactivated. */ + rfbBool (*newClient)(struct _rfbClientRec* client, void** data); + /* returns FALSE if extension should be deactivated for client. + if init == NULL, it stays activated. */ + rfbBool (*init)(struct _rfbClientRec* client, void* data); + /* if pseudoEncodings is not NULL, it contains a 0 terminated + list of the pseudo encodings handled by this extension. */ + int *pseudoEncodings; + /* returns TRUE if that pseudo encoding is handled by the extension. + encodingNumber==0 means "reset encodings". */ + rfbBool (*enablePseudoEncoding)(struct _rfbClientRec* client, + void** data, int encodingNumber); + /* returns TRUE if message was handled */ + rfbBool (*handleMessage)(struct _rfbClientRec* client, + void* data, + const rfbClientToServerMsg* message); + void (*close)(struct _rfbClientRec* client, void* data); + void (*usage)(void); + /* processArguments returns the number of handled arguments */ + int (*processArgument)(int argc, char *argv[]); + struct _rfbProtocolExtension* next; +} rfbProtocolExtension; + +typedef struct _rfbExtensionData { + rfbProtocolExtension* extension; + void* data; + struct _rfbExtensionData* next; +} rfbExtensionData; + +/* + * Per-screen (framebuffer) structure. There can be as many as you wish, + * each serving different clients. However, you have to call + * rfbProcessEvents for each of these. + */ + +typedef struct _rfbScreenInfo +{ + /* this structure has children that are scaled versions of this screen */ + struct _rfbScreenInfo *scaledScreenNext; + int scaledScreenRefCount; + + int width; + int paddedWidthInBytes; + int height; + int depth; + int bitsPerPixel; + int sizeInBytes; + + rfbPixel blackPixel; + rfbPixel whitePixel; + + /* some screen specific data can be put into a struct where screenData + * points to. You need this if you have more than one screen at the + * same time while using the same functions. + */ + void* screenData; + + /* additions by libvncserver */ + + rfbPixelFormat serverFormat; + rfbColourMap colourMap; /* set this if rfbServerFormat.trueColour==FALSE */ + const char* desktopName; + char thisHost[255]; + + rfbBool autoPort; + int port; + SOCKET listenSock; + int maxSock; + int maxFd; +#ifdef __MINGW32__ + struct fd_set allFds; +#else + fd_set allFds; +#endif + + enum rfbSocketState socketState; + SOCKET inetdSock; + rfbBool inetdInitDone; + + int udpPort; + SOCKET udpSock; + struct _rfbClientRec* udpClient; + rfbBool udpSockConnected; + struct sockaddr_in udpRemoteAddr; + + int maxClientWait; + + /* http stuff */ + rfbBool httpInitDone; + rfbBool httpEnableProxyConnect; + int httpPort; + char* httpDir; + SOCKET httpListenSock; + SOCKET httpSock; + + rfbPasswordCheckProcPtr passwordCheck; + void* authPasswdData; + /* If rfbAuthPasswdData is given a list, this is the first + view only password. */ + int authPasswdFirstViewOnly; + + /* send only this many rectangles in one update */ + int maxRectsPerUpdate; + /* this is the amount of milliseconds to wait at least before sending + * an update. */ + int deferUpdateTime; +#ifdef TODELETE + char* screen; +#endif + rfbBool alwaysShared; + rfbBool neverShared; + rfbBool dontDisconnect; + struct _rfbClientRec* clientHead; + struct _rfbClientRec* pointerClient; /* "Mutex" for pointer events */ + + + /* cursor */ + int cursorX, cursorY,underCursorBufferLen; + char* underCursorBuffer; + rfbBool dontConvertRichCursorToXCursor; + struct rfbCursor* cursor; + + /* the frameBufferhas to be supplied by the serving process. + * The buffer will not be freed by + */ + char* frameBuffer; + rfbKbdAddEventProcPtr kbdAddEvent; + rfbKbdReleaseAllKeysProcPtr kbdReleaseAllKeys; + rfbPtrAddEventProcPtr ptrAddEvent; + rfbSetXCutTextProcPtr setXCutText; + rfbGetCursorProcPtr getCursorPtr; + rfbSetTranslateFunctionProcPtr setTranslateFunction; + rfbSetSingleWindowProcPtr setSingleWindow; + rfbSetServerInputProcPtr setServerInput; + rfbFileTransferPermitted getFileTransferPermission; + rfbSetTextChat setTextChat; + + /* newClientHook is called just after a new client is created */ + rfbNewClientHookPtr newClientHook; + /* displayHook is called just before a frame buffer update */ + rfbDisplayHookPtr displayHook; + + /* These hooks are called to pass keyboard state back to the client */ + rfbGetKeyboardLedStateHookPtr getKeyboardLedStateHook; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + MUTEX(cursorMutex); + rfbBool backgroundLoop; +#endif + + /* if TRUE, an ignoring signal handler is installed for SIGPIPE */ + rfbBool ignoreSIGPIPE; + + /* if not zero, only a slice of this height is processed every time + * an update should be sent. This should make working on a slow + * link more interactive. */ + int progressiveSliceHeight; + + in_addr_t listenInterface; + int deferPtrUpdateTime; + + /* handle as many input events as possible (default off) */ + rfbBool handleEventsEagerly; + + /* rfbEncodingServerIdentity */ + char *versionString; + + /* What does the server tell the new clients which version it supports */ + int protocolMajorVersion; + int protocolMinorVersion; + + /* command line authorization of file transfers */ + rfbBool permitFileTransfer; +} rfbScreenInfo, *rfbScreenInfoPtr; + + +/* + * rfbTranslateFnType is the type of translation functions. + */ + +typedef void (*rfbTranslateFnType)(char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height); + + +/* region stuff */ + +struct sraRegion; +typedef struct sraRegion* sraRegionPtr; + +/* + * Per-client structure. + */ + +typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl); + +typedef struct _rfbFileTransferData { + int fd; + int compressionEnabled; + int fileSize; + int numPackets; + int receiving; + int sending; +} rfbFileTransferData; + + +typedef struct _rfbStatList { + uint32_t type; + uint32_t sentCount; + uint32_t bytesSent; + uint32_t bytesSentIfRaw; + uint32_t rcvdCount; + uint32_t bytesRcvd; + uint32_t bytesRcvdIfRaw; + struct _rfbStatList *Next; +} rfbStatList; + +typedef struct _rfbClientRec { + + /* back pointer to the screen */ + rfbScreenInfoPtr screen; + + /* points to a scaled version of the screen buffer in cl->scaledScreenList */ + rfbScreenInfoPtr scaledScreen; + /* how did the client tell us it wanted the screen changed? Ultra style or palm style? */ + rfbBool PalmVNC; + + + /* private data. You should put any application client specific data + * into a struct and let clientData point to it. Don't forget to + * free the struct via clientGoneHook! + * + * This is useful if the IO functions have to behave client specific. + */ + void* clientData; + ClientGoneHookPtr clientGoneHook; + + SOCKET sock; + char *host; + + /* RFB protocol minor version number */ + int protocolMajorVersion; + int protocolMinorVersion; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + pthread_t client_thread; +#endif + /* Possible client states: */ + enum { + RFB_PROTOCOL_VERSION, /* establishing protocol version */ + RFB_SECURITY_TYPE, /* negotiating security (RFB v.3.7) */ + RFB_AUTHENTICATION, /* authenticating */ + RFB_INITIALISATION, /* sending initialisation messages */ + RFB_NORMAL /* normal protocol messages */ + } state; + + rfbBool reverseConnection; + rfbBool onHold; + rfbBool readyForSetColourMapEntries; + rfbBool useCopyRect; + int preferredEncoding; + int correMaxWidth, correMaxHeight; + + rfbBool viewOnly; + + /* The following member is only used during VNC authentication */ + uint8_t authChallenge[CHALLENGESIZE]; + + /* The following members represent the update needed to get the client's + framebuffer from its present state to the current state of our + framebuffer. + + If the client does not accept CopyRect encoding then the update is + simply represented as the region of the screen which has been modified + (modifiedRegion). + + If the client does accept CopyRect encoding, then the update consists of + two parts. First we have a single copy from one region of the screen to + another (the destination of the copy is copyRegion), and second we have + the region of the screen which has been modified in some other way + (modifiedRegion). + + Although the copy is of a single region, this region may have many + rectangles. When sending an update, the copyRegion is always sent + before the modifiedRegion. This is because the modifiedRegion may + overlap parts of the screen which are in the source of the copy. + + In fact during normal processing, the modifiedRegion may even overlap + the destination copyRegion. Just before an update is sent we remove + from the copyRegion anything in the modifiedRegion. */ + + sraRegionPtr copyRegion; /* the destination region of the copy */ + int copyDX, copyDY; /* the translation by which the copy happens */ + + sraRegionPtr modifiedRegion; + + /* As part of the FramebufferUpdateRequest, a client can express interest + in a subrectangle of the whole framebuffer. This is stored in the + requestedRegion member. In the normal case this is the whole + framebuffer if the client is ready, empty if it's not. */ + + sraRegionPtr requestedRegion; + + /* The following member represents the state of the "deferred update" timer + - when the framebuffer is modified and the client is ready, in most + cases it is more efficient to defer sending the update by a few + milliseconds so that several changes to the framebuffer can be combined + into a single update. */ + + struct timeval startDeferring; + struct timeval startPtrDeferring; + int lastPtrX; + int lastPtrY; + int lastPtrButtons; + + /* translateFn points to the translation function which is used to copy + and translate a rectangle from the framebuffer to an output buffer. */ + + rfbTranslateFnType translateFn; + char *translateLookupTable; + rfbPixelFormat format; + + /* + * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the + * framebuffer. So for a max screen width of say 2K with 32-bit pixels this + * means 8K minimum. + */ + +#define UPDATE_BUF_SIZE 30000 + + char updateBuf[UPDATE_BUF_SIZE]; + int ublen; + + /* statistics */ + struct _rfbStatList *statEncList; + struct _rfbStatList *statMsgList; + int rawBytesEquivalent; + int bytesSent; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* zlib encoding -- necessary compression state info per client */ + + struct z_stream_s compStream; + rfbBool compStreamInited; + uint32_t zlibCompressLevel; + /* the quality level is also used by ZYWRLE */ + int tightQualityLevel; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* tight encoding -- preserve zlib streams' state for each client */ + z_stream zsStruct[4]; + rfbBool zsActive[4]; + int zsLevel[4]; + int tightCompressLevel; +#endif +#endif + + /* Ultra Encoding support */ + rfbBool compStreamInitedLZO; + char *lzoWrkMem; + + rfbFileTransferData fileTransfer; + + int lastKeyboardLedState; /* keep track of last value so we can send *change* events */ + rfbBool enableSupportedMessages; /* client supports SupportedMessages encoding */ + rfbBool enableSupportedEncodings; /* client supports SupportedEncodings encoding */ + rfbBool enableServerIdentity; /* client supports ServerIdentity encoding */ + rfbBool enableKeyboardLedState; /* client supports KeyboardState encoding */ + rfbBool enableLastRectEncoding; /* client supports LastRect encoding */ + rfbBool enableCursorShapeUpdates; /* client supports cursor shape updates */ + rfbBool enableCursorPosUpdates; /* client supports cursor position updates */ + rfbBool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */ + rfbBool cursorWasChanged; /* cursor shape update should be sent */ + rfbBool cursorWasMoved; /* cursor position update should be sent */ + int cursorX,cursorY; /* the coordinates of the cursor, + if enableCursorShapeUpdates = FALSE */ + + rfbBool useNewFBSize; /* client supports NewFBSize encoding */ + rfbBool newFBSizePending; /* framebuffer size was changed */ + + struct _rfbClientRec *prev; + struct _rfbClientRec *next; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + /* whenever a client is referenced, the refCount has to be incremented + and afterwards decremented, so that the client is not cleaned up + while being referenced. + Use the functions rfbIncrClientRef(cl) and rfbDecrClientRef(cl); + */ + int refCount; + MUTEX(refCountMutex); + COND(deleteCond); + + MUTEX(outputMutex); + MUTEX(updateMutex); + COND(updateCond); +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBZ + void* zrleData; + int zywrleLevel; + int zywrleBuf[rfbZRLETileWidth * rfbZRLETileHeight]; +#endif + + /* if progressive updating is on, this variable holds the current + * y coordinate of the progressive slice. */ + int progressiveSliceY; + + rfbExtensionData* extensions; + + /* for threaded zrle */ + char *zrleBeforeBuf; + void *paletteHelper; + + /* for thread safety for rfbSendFBUpdate() */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#define LIBVNCSERVER_SEND_MUTEX + MUTEX(sendMutex); +#endif + +} rfbClientRec, *rfbClientPtr; + +/* + * This macro is used to test whether there is a framebuffer update needing to + * be sent to the client. + */ + +#define FB_UPDATE_PENDING(cl) \ + (((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ + (((cl)->enableCursorShapeUpdates == FALSE && \ + ((cl)->cursorX != (cl)->screen->cursorX || \ + (cl)->cursorY != (cl)->screen->cursorY))) || \ + ((cl)->useNewFBSize && (cl)->newFBSizePending) || \ + ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \ + !sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion)) + +/* + * Macros for endian swapping. + */ + +#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) + +#define Swap24(l) ((((l) & 0xff) << 16) | (((l) >> 16) & 0xff) | \ + (((l) & 0x00ff00))) + +#define Swap32(l) (((l) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + ((l) << 24)) + + +extern char rfbEndianTest; + +#define Swap16IfLE(s) (rfbEndianTest ? Swap16(s) : (s)) +#define Swap24IfLE(l) (rfbEndianTest ? Swap24(l) : (l)) +#define Swap32IfLE(l) (rfbEndianTest ? Swap32(l) : (l)) + +/* UltraVNC uses some windows structures unmodified, so the viewer expects LittleEndian Data */ +#define Swap16IfBE(s) (rfbEndianTest ? (s) : Swap16(s)) +#define Swap24IfBE(l) (rfbEndianTest ? (l) : Swap24(l)) +#define Swap32IfBE(l) (rfbEndianTest ? (l) : Swap32(l)) + +/* sockets.c */ + +extern int rfbMaxClientWait; + +extern void rfbInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen); +extern void rfbCloseClient(rfbClientPtr cl); +extern int rfbReadExact(rfbClientPtr cl, char *buf, int len); +extern int rfbReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout); +extern int rfbWriteExact(rfbClientPtr cl, const char *buf, int len); +extern int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec); +extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port); +extern int rfbConnectToTcpAddr(char* host, int port); +extern int rfbListenOnTCPPort(int port, in_addr_t iface); +extern int rfbListenOnUDPPort(int port, in_addr_t iface); +extern int rfbStringToAddr(char* string,in_addr_t* addr); + +/* rfbserver.c */ + +/* Routines to iterate over the client list in a thread-safe way. + Only a single iterator can be in use at a time process-wide. */ +typedef struct rfbClientIterator *rfbClientIteratorPtr; + +extern void rfbClientListInit(rfbScreenInfoPtr rfbScreen); +extern rfbClientIteratorPtr rfbGetClientIterator(rfbScreenInfoPtr rfbScreen); +extern rfbClientPtr rfbClientIteratorNext(rfbClientIteratorPtr iterator); +extern void rfbReleaseClientIterator(rfbClientIteratorPtr iterator); +extern void rfbIncrClientRef(rfbClientPtr cl); +extern void rfbDecrClientRef(rfbClientPtr cl); + +extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,int sock); +extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,int sock); +extern rfbClientPtr rfbNewUDPClient(rfbScreenInfoPtr rfbScreen); +extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port); +extern void rfbClientConnectionGone(rfbClientPtr cl); +extern void rfbProcessClientMessage(rfbClientPtr cl); +extern void rfbClientConnFailed(rfbClientPtr cl, char *reason); +extern void rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,int sock); +extern void rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen); +extern rfbBool rfbSendFramebufferUpdate(rfbClientPtr cl, sraRegionPtr updateRegion); +extern rfbBool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h); +extern rfbBool rfbSendUpdateBuf(rfbClientPtr cl); +extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len); +extern rfbBool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy); +extern rfbBool rfbSendLastRectMarker(rfbClientPtr cl); +extern rfbBool rfbSendNewFBSize(rfbClientPtr cl, int w, int h); +extern rfbBool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours); +extern void rfbSendBell(rfbScreenInfoPtr rfbScreen); + +extern char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length); +extern rfbBool rfbSendFileTransferChunk(rfbClientPtr cl); +extern rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer); +extern rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, char *buffer); +extern char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length); +extern rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length); + +void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len); + +/* translate.c */ + +extern rfbBool rfbEconomicTranslate; + +extern void rfbTranslateNone(char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height); +extern rfbBool rfbSetTranslateFunction(rfbClientPtr cl); +extern rfbBool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours); +extern void rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours); + +/* httpd.c */ + +extern void rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen); + + + +/* auth.c */ + +extern void rfbAuthNewClient(rfbClientPtr cl); +extern void rfbProcessClientSecurityType(rfbClientPtr cl); +extern void rfbAuthProcessClientMessage(rfbClientPtr cl); +extern void rfbRegisterSecurityHandler(rfbSecurityHandler* handler); +extern void rfbUnregisterSecurityHandler(rfbSecurityHandler* handler); + +/* rre.c */ + +extern rfbBool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h); + + +/* corre.c */ + +extern rfbBool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h); + + +/* hextile.c */ + +extern rfbBool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, + int h); + +/* ultra.c */ + +/* Set maximum ultra rectangle size in pixels. Always allow at least + * two scan lines. + */ +#define ULTRA_MAX_RECT_SIZE (128*256) +#define ULTRA_MAX_SIZE(min) ((( min * 2 ) > ULTRA_MAX_RECT_SIZE ) ? \ + ( min * 2 ) : ULTRA_MAX_RECT_SIZE ) + +extern rfbBool rfbSendRectEncodingUltra(rfbClientPtr cl, int x,int y,int w,int h); + + +#ifdef LIBVNCSERVER_HAVE_LIBZ +/* zlib.c */ + +/* Minimum zlib rectangle size in bytes. Anything smaller will + * not compress well due to overhead. + */ +#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17) + +/* Set maximum zlib rectangle size in pixels. Always allow at least + * two scan lines. + */ +#define ZLIB_MAX_RECT_SIZE (128*256) +#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \ + ( min * 2 ) : ZLIB_MAX_RECT_SIZE ) + +extern rfbBool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, + int h); + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +/* tight.c */ + +#define TIGHT_DEFAULT_COMPRESSION 6 + +extern rfbBool rfbTightDisableGradient; + +extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); +extern rfbBool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); + +#endif +#endif + + +/* cursor.c */ + +typedef struct rfbCursor { + /* set this to true if LibVNCServer has to free this cursor */ + rfbBool cleanup, cleanupSource, cleanupMask, cleanupRichSource; + unsigned char *source; /* points to bits */ + unsigned char *mask; /* points to bits */ + unsigned short width, height, xhot, yhot; /* metrics */ + unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */ + unsigned short backRed, backGreen, backBlue; /* device-independent colour */ + unsigned char *richSource; /* source bytes for a rich cursor */ + unsigned char *alphaSource; /* source for alpha blending info */ + rfbBool alphaPreMultiplied; /* if richSource already has alpha applied */ +} rfbCursor, *rfbCursorPtr; +extern unsigned char rfbReverseByte[0x100]; + +extern rfbBool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/); +extern rfbBool rfbSendCursorPos(rfbClientPtr cl); +extern void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap); +extern rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString); +extern char* rfbMakeMaskForXCursor(int width,int height,char* cursorString); +extern char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource); +extern void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor); +extern void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor); +extern void rfbFreeCursor(rfbCursorPtr cursor); +extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c); + +/* cursor handling for the pointer */ +extern void rfbDefaultPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl); + +/* zrle.c */ +#ifdef LIBVNCSERVER_HAVE_LIBZ +extern rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w,int h); +#endif + +/* stats.c */ + +extern void rfbResetStats(rfbClientPtr cl); +extern void rfbPrintStats(rfbClientPtr cl); + +/* font.c */ + +typedef struct rfbFontData { + unsigned char* data; + /* + metaData is a 256*5 array: + for each character + (offset,width,height,x,y) + */ + int* metaData; +} rfbFontData,* rfbFontDataPtr; + +int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,rfbPixel colour); +void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,rfbPixel colour); +/* if colour==backColour, background is transparent */ +int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour); +void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour); +int rfbWidthOfString(rfbFontDataPtr font,const char* string); +int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c); +void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2); +/* this returns the smallest box enclosing any character of font. */ +void rfbWholeFontBBox(rfbFontDataPtr font,int *x1, int *y1, int *x2, int *y2); + +/* dynamically load a linux console font (4096 bytes, 256 glyphs a 8x16 */ +rfbFontDataPtr rfbLoadConsoleFont(char *filename); +/* free a dynamically loaded font */ +void rfbFreeFont(rfbFontDataPtr font); + +/* draw.c */ + +void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col); +void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,rfbPixel col); +void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col); + +/* selbox.c */ + +/* this opens a modal select box. list is an array of strings, the end marked + with a NULL. + It returns the index in the list or -1 if cancelled or something else + wasn't kosher. */ +typedef void (*SelectionChangedHookPtr)(int _index); +extern int rfbSelectBox(rfbScreenInfoPtr rfbScreen, + rfbFontDataPtr font, char** list, + int x1, int y1, int x2, int y2, + rfbPixel foreColour, rfbPixel backColour, + int border,SelectionChangedHookPtr selChangedHook); + +/* cargs.c */ + +extern void rfbUsage(void); +extern void rfbPurgeArguments(int* argc,int* position,int count,char *argv[]); +extern rfbBool rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]); +extern rfbBool rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[]); + +/* main.c */ + +extern void rfbLogEnable(int enabled); +typedef void (*rfbLogProc)(const char *format, ...); +extern rfbLogProc rfbLog, rfbErr; +extern void rfbLogPerror(const char *str); + +void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy); +void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy); + +void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy); +void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy); + +void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2); +void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion); +void rfbDoNothingWithClient(rfbClientPtr cl); +enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl); +void rfbRegisterProtocolExtension(rfbProtocolExtension* extension); +void rfbUnregisterProtocolExtension(rfbProtocolExtension* extension); +struct _rfbProtocolExtension* rfbGetExtensionIterator(); +void rfbReleaseExtensionIterator(); +rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension, + void* data); +rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension); +void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension); + +/* to check against plain passwords */ +rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len); + +/* functions to make a vnc server */ +extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, + int width,int height,int bitsPerSample,int samplesPerPixel, + int bytesPerPixel); +extern void rfbInitServer(rfbScreenInfoPtr rfbScreen); +extern void rfbShutdownServer(rfbScreenInfoPtr rfbScreen,rfbBool disconnectClients); +extern void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen,char *framebuffer, + int width,int height, int bitsPerSample,int samplesPerPixel, + int bytesPerPixel); + +extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo); +extern void rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...); + +/* functions to accept/refuse a client that has been put on hold + by a NewClientHookPtr function. Must not be called in other + situations. */ +extern void rfbStartOnHoldClient(rfbClientPtr cl); +extern void rfbRefuseOnHoldClient(rfbClientPtr cl); + +/* call one of these two functions to service the vnc clients. + usec are the microseconds the select on the fds waits. + if you are using the event loop, set this to some value > 0, so the + server doesn't get a high load just by listening. + rfbProcessEvents() returns TRUE if an update was pending. */ + +extern void rfbRunEventLoop(rfbScreenInfoPtr screenInfo, long usec, rfbBool runInBackground); +extern rfbBool rfbProcessEvents(rfbScreenInfoPtr screenInfo,long usec); +extern rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo); + +/* TightVNC file transfer extension */ +void rfbRegisterTightVNCFileTransferExtension(); +void rfbUnregisterTightVNCFileTransferExtension(); + +/* Statistics */ +extern char *messageNameServer2Client(uint32_t type, char *buf, int len); +extern char *messageNameClient2Server(uint32_t type, char *buf, int len); +extern char *encodingName(uint32_t enc, char *buf, int len); + +extern rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type); +extern rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type); + +/* Each call to rfbStatRecord* adds one to the rect count for that type */ +extern void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount); /* Specifically for tight encoding */ +extern void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbResetStats(rfbClientPtr cl); +extern void rfbPrintStats(rfbClientPtr cl); + +extern int rfbStatGetSentBytes(rfbClientPtr cl); +extern int rfbStatGetSentBytesIfRaw(rfbClientPtr cl); +extern int rfbStatGetRcvdBytes(rfbClientPtr cl); +extern int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl); +extern int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type); + +/* Set which version you want to advertise 3.3, 3.6, 3.7 and 3.8 are currently supported*/ +extern void rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_); + +/* send a TextChat message to a client */ +extern rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer); + + + + +#if(defined __cplusplus) +} +#endif + +#endif + diff --git a/3rdParty/LibVNC/src/rfb/rfbclient.h b/3rdParty/LibVNC/src/rfb/rfbclient.h new file mode 100644 index 0000000..bc4ec14 --- /dev/null +++ b/3rdParty/LibVNC/src/rfb/rfbclient.h @@ -0,0 +1,406 @@ +#ifndef RFBCLIENT_H +#define RFBCLIENT_H + +/* + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * vncviewer.h + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS +#include +#endif + +#define rfbClientSwap16IfLE(s) \ + (*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) + +#define rfbClientSwap32IfLE(l) \ + (*(char *)&client->endianTest ? ((((l) & 0xff000000) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + (((l) & 0x000000ff) << 24)) : (l)) + +#define rfbClientSwap64IfLE(l) \ + (*(char *)&client->endianTest ? ((((l) & 0xff00000000000000ULL) >> 56) | \ + (((l) & 0x00ff000000000000ULL) >> 40) | \ + (((l) & 0x0000ff0000000000ULL) >> 24) | \ + (((l) & 0x000000ff00000000ULL) >> 8) | \ + (((l) & 0x00000000ff000000ULL) << 8) | \ + (((l) & 0x0000000000ff0000ULL) << 24) | \ + (((l) & 0x000000000000ff00ULL) << 40) | \ + (((l) & 0x00000000000000ffULL) << 56)) : (l)) + +#define FLASH_PORT_OFFSET 5400 +#define LISTEN_PORT_OFFSET 5500 +#define TUNNEL_PORT_OFFSET 5500 +#define SERVER_PORT_OFFSET 5900 + +#define DEFAULT_SSH_CMD "/usr/bin/ssh" +#define DEFAULT_TUNNEL_CMD \ + (DEFAULT_SSH_CMD " -f -L %L:localhost:%R %H sleep 20") +#define DEFAULT_VIA_CMD \ + (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20") + +#if(defined __cplusplus) +extern "C" +{ +#endif + +/* vncrec */ + +typedef struct { + FILE* file; + struct timeval tv; + rfbBool readTimestamp; + rfbBool doNotSleep; +} rfbVNCRec; + +/* client data */ + +typedef struct rfbClientData { + void* tag; + void* data; + struct rfbClientData* next; +} rfbClientData; + +/* app data (belongs into rfbClient?) */ + +typedef struct { + rfbBool shareDesktop; + rfbBool viewOnly; + + const char* encodingsString; + + rfbBool useBGR233; + int nColours; + rfbBool forceOwnCmap; + rfbBool forceTrueColour; + int requestedDepth; + + int compressLevel; + int qualityLevel; + rfbBool enableJPEG; + rfbBool useRemoteCursor; + rfbBool palmVNC; /* use palmvnc specific SetScale (vs ultravnc) */ + int scaleSetting; /* 0 means no scale set, else 1/scaleSetting */ +} AppData; + +/* For GetCredentialProc callback function to return */ +typedef union _rfbCredential +{ + /* X509 (VeNCrypt) */ + struct + { + char *x509CACertFile; + char *x509CACrlFile; + char *x509ClientCertFile; + char *x509ClientKeyFile; + } x509Credential; + /* Plain (VeNCrypt), MSLogon (UltraVNC) */ + struct + { + char *username; + char *password; + } userCredential; +} rfbCredential; + +#define rfbCredentialTypeX509 1 +#define rfbCredentialTypeUser 2 + +struct _rfbClient; + +typedef void (*HandleTextChatProc)(struct _rfbClient* client, int value, char *text); +typedef void (*HandleKeyboardLedStateProc)(struct _rfbClient* client, int value, int pad); +typedef rfbBool (*HandleCursorPosProc)(struct _rfbClient* client, int x, int y); +typedef void (*SoftCursorLockAreaProc)(struct _rfbClient* client, int x, int y, int w, int h); +typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client); +typedef void (*GotFrameBufferUpdateProc)(struct _rfbClient* client, int x, int y, int w, int h); +typedef void (*FinishedFrameBufferUpdateProc)(struct _rfbClient* client); +typedef char* (*GetPasswordProc)(struct _rfbClient* client); +typedef rfbCredential* (*GetCredentialProc)(struct _rfbClient* client, int credentialType); +typedef rfbBool (*MallocFrameBufferProc)(struct _rfbClient* client); +typedef void (*GotXCutTextProc)(struct _rfbClient* client, const char *text, int textlen); +typedef void (*BellProc)(struct _rfbClient* client); + +typedef void (*GotCursorShapeProc)(struct _rfbClient* client, int xhot, int yhot, int width, int height, int bytesPerPixel); +typedef void (*GotCopyRectProc)(struct _rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y); + +typedef struct _rfbClient { + uint8_t* frameBuffer; + int width, height; + + int endianTest; + + AppData appData; + + const char* programName; + char* serverHost; + int serverPort; /* if -1, then use file recorded by vncrec */ + rfbBool listenSpecified; + int listenPort, flashPort; + + struct { + int x, y, w, h; + } updateRect; + + /* Note that the CoRRE encoding uses this buffer and assumes it is big enough + to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes. + Hextile also assumes it is big enough to hold 16 * 16 * 32 bits. + Tight encoding assumes BUFFER_SIZE is at least 16384 bytes. */ + +#define RFB_BUFFER_SIZE (640*480) + char buffer[RFB_BUFFER_SIZE]; + + /* rfbproto.c */ + + int sock; + rfbBool canUseCoRRE; + rfbBool canUseHextile; + char *desktopName; + rfbPixelFormat format; + rfbServerInitMsg si; + + /* listen.c */ + int listenSock; + + /* sockets.c */ +#define RFB_BUF_SIZE 8192 + char buf[RFB_BUF_SIZE]; + char *bufoutptr; + int buffered; + + /* The zlib encoding requires expansion/decompression/deflation of the + compressed data in the "buffer" above into another, result buffer. + However, the size of the result buffer can be determined precisely + based on the bitsPerPixel, height and width of the rectangle. We + allocate this buffer one time to be the full size of the buffer. */ + + /* Ultra Encoding uses this buffer too */ + + int ultra_buffer_size; + char *ultra_buffer; + + int raw_buffer_size; + char *raw_buffer; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + z_stream decompStream; + rfbBool decompStreamInited; +#endif + + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* + * Variables for the ``tight'' encoding implementation. + */ + + /* Separate buffer for compressed data. */ +#define ZLIB_BUFFER_SIZE 30000 + char zlib_buffer[ZLIB_BUFFER_SIZE]; + + /* Four independent compression streams for zlib library. */ + z_stream zlibStream[4]; + rfbBool zlibStreamActive[4]; + + /* Filter stuff. Should be initialized by filter initialization code. */ + rfbBool cutZeros; + int rectWidth, rectColors; + char tightPalette[256*4]; + uint8_t tightPrevRow[2048*3*sizeof(uint16_t)]; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* JPEG decoder state. */ + rfbBool jpegError; + + struct jpeg_source_mgr* jpegSrcManager; + void* jpegBufferPtr; + size_t jpegBufferLen; + +#endif +#endif + + + /* cursor.c */ + uint8_t *rcSource, *rcMask; + + /* private data pointer */ + rfbClientData* clientData; + + rfbVNCRec* vncRec; + + /* Keyboard State support (is 'Caps Lock' set on the remote display???) */ + int KeyboardLedStateEnabled; + int CurrentKeyboardLedState; + + int canHandleNewFBSize; + + /* hooks */ + HandleTextChatProc HandleTextChat; + HandleKeyboardLedStateProc HandleKeyboardLedState; + HandleCursorPosProc HandleCursorPos; + SoftCursorLockAreaProc SoftCursorLockArea; + SoftCursorUnlockScreenProc SoftCursorUnlockScreen; + GotFrameBufferUpdateProc GotFrameBufferUpdate; + FinishedFrameBufferUpdateProc FinishedFrameBufferUpdate; + /* the pointer returned by GetPassword will be freed after use! */ + GetPasswordProc GetPassword; + MallocFrameBufferProc MallocFrameBuffer; + GotXCutTextProc GotXCutText; + BellProc Bell; + + GotCursorShapeProc GotCursorShape; + GotCopyRectProc GotCopyRect; + + /* Which messages are supported by the server + * This is a *guess* for most servers. + * (If we can even detect the type of server) + * + * If the server supports the "rfbEncodingSupportedMessages" + * then this will be updated when the encoding is received to + * accurately reflect the servers capabilities. + */ + rfbSupportedMessages supportedMessages; + + /* negotiated protocol version */ + int major, minor; + + /* The selected security types */ + uint32_t authScheme, subAuthScheme; + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + /* The TLS session for Anonymous TLS and VeNCrypt */ + gnutls_session_t tlsSession; +#endif + + /* To support security types that requires user input (except VNC password + * authentication), for example VeNCrypt and MSLogon, this callback function + * must be set before the authentication. Otherwise, it implicates that the + * caller application does not support it and related security types should + * be bypassed. + */ + GetCredentialProc GetCredential; + + /* The 0-terminated security types supported by the client. + * Set by function SetClientAuthSchemes() */ + uint32_t *clientAuthSchemes; + + /* When the server is a repeater, this specifies the final destination */ + char *destHost; + int destPort; +} rfbClient; + +/* cursor.c */ + +extern rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc); + +/* listen.c */ + +extern void listenForIncomingConnections(rfbClient* viewer); +extern int listenForIncomingConnectionsNoFork(rfbClient* viewer, int usec_timeout); + +/* rfbproto.c */ + +extern rfbBool rfbEnableClientLogging; +typedef void (*rfbClientLogProc)(const char *format, ...); +extern rfbClientLogProc rfbClientLog,rfbClientErr; +extern rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port); +extern rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort); +extern void SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size); +extern rfbBool InitialiseRFBConnection(rfbClient* client); +extern rfbBool SetFormatAndEncodings(rfbClient* client); +extern rfbBool SendIncrementalFramebufferUpdateRequest(rfbClient* client); +extern rfbBool SendFramebufferUpdateRequest(rfbClient* client, + int x, int y, int w, int h, + rfbBool incremental); +extern rfbBool SendScaleSetting(rfbClient* client,int scaleSetting); +extern rfbBool SendPointerEvent(rfbClient* client,int x, int y, int buttonMask); +extern rfbBool SendKeyEvent(rfbClient* client,uint32_t key, rfbBool down); +extern rfbBool SendClientCutText(rfbClient* client,char *str, int len); +extern rfbBool HandleRFBServerMessage(rfbClient* client); + +extern rfbBool TextChatSend(rfbClient* client, char *text); +extern rfbBool TextChatOpen(rfbClient* client); +extern rfbBool TextChatClose(rfbClient* client); +extern rfbBool TextChatFinish(rfbClient* client); +extern rfbBool PermitServerInput(rfbClient* client, int enabled); + +extern void PrintPixelFormat(rfbPixelFormat *format); + +extern rfbBool SupportsClient2Server(rfbClient* client, int messageType); +extern rfbBool SupportsServer2Client(rfbClient* client, int messageType); + +/* client data */ + +void rfbClientSetClientData(rfbClient* client, void* tag, void* data); +void* rfbClientGetClientData(rfbClient* client, void* tag); + +/* protocol extensions */ + +typedef struct _rfbClientProtocolExtension { + int* encodings; + /* returns TRUE if the encoding was handled */ + rfbBool (*handleEncoding)(rfbClient* cl, + rfbFramebufferUpdateRectHeader* rect); + /* returns TRUE if it handled the message */ + rfbBool (*handleMessage)(rfbClient* cl, + rfbServerToClientMsg* message); + struct _rfbClientProtocolExtension* next; +} rfbClientProtocolExtension; + +void rfbClientRegisterExtension(rfbClientProtocolExtension* e); + +/* sockets.c */ + +extern rfbBool errorMessageOnReadFailure; + +extern rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n); +extern rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n); +extern int FindFreeTcpPort(void); +extern int ListenAtTcpPort(int port); +extern int ConnectClientToTcpAddr(unsigned int host, int port); +extern int ConnectClientToUnixSock(const char *sockFile); +extern int AcceptTcpConnection(int listenSock); +extern rfbBool SetNonBlocking(int sock); + +extern rfbBool StringToIPAddr(const char *str, unsigned int *addr); +extern rfbBool SameMachine(int sock); +extern int WaitForMessage(rfbClient* client,unsigned int usecs); + +/* vncviewer.c */ +rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,int bytesPerPixel); +rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv); +/* rfbClientCleanup() does not touch client->frameBuffer */ +void rfbClientCleanup(rfbClient* client); + +#if(defined __cplusplus) +} +#endif + +#endif + diff --git a/3rdParty/LibVNC/src/rfb/rfbconfig.h b/3rdParty/LibVNC/src/rfb/rfbconfig.h new file mode 100644 index 0000000..1d06196 --- /dev/null +++ b/3rdParty/LibVNC/src/rfb/rfbconfig.h @@ -0,0 +1,557 @@ +#ifndef _RFB_RFBCONFIG_H +#define _RFB_RFBCONFIG_H 1 + +/* rfb/rfbconfig.h. Generated automatically at end of configure. */ +/* rfbconfig.h. Generated by configure. */ +/* rfbconfig.h.in. Generated from configure.ac by autoheader. */ + +/* Enable 24 bit per pixel in native framebuffer */ +#ifndef LIBVNCSERVER_ALLOW24BPP +#define LIBVNCSERVER_ALLOW24BPP 1 +#endif + +/* work around when write() returns ENOENT but does not mean it */ +/* #undef LIBVNCSERVER_ENOENT_WORKAROUND */ + +/* Use ffmpeg (for vnc2mpg) */ +/* #undef LIBVNCSERVER_FFMPEG */ + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_ARPA_INET_H +#define LIBVNCSERVER_HAVE_ARPA_INET_H 1 +#endif + +/* Avahi/mDNS client build environment present */ +#ifndef LIBVNCSERVER_HAVE_AVAHI +#define LIBVNCSERVER_HAVE_AVAHI 1 +#endif + +/* Define to 1 if you have the `crypt' function. */ +#ifndef LIBVNCSERVER_HAVE_CRYPT +#define LIBVNCSERVER_HAVE_CRYPT 1 +#endif + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef LIBVNCSERVER_HAVE_DOPRNT */ + +/* DPMS extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_DPMS */ + +/* FBPM extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_FBPM */ + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_FCNTL_H +#define LIBVNCSERVER_HAVE_FCNTL_H 1 +#endif + +/* Define to 1 if you have the `fork' function. */ +#ifndef LIBVNCSERVER_HAVE_FORK +#define LIBVNCSERVER_HAVE_FORK 1 +#endif + +/* Define to 1 if you have the `ftime' function. */ +#ifndef LIBVNCSERVER_HAVE_FTIME +#define LIBVNCSERVER_HAVE_FTIME 1 +#endif + +/* Define to 1 if you have the `geteuid' function. */ +#ifndef LIBVNCSERVER_HAVE_GETEUID +#define LIBVNCSERVER_HAVE_GETEUID 1 +#endif + +/* Define to 1 if you have the `gethostbyname' function. */ +#ifndef LIBVNCSERVER_HAVE_GETHOSTBYNAME +#define LIBVNCSERVER_HAVE_GETHOSTBYNAME 1 +#endif + +/* Define to 1 if you have the `gethostname' function. */ +#ifndef LIBVNCSERVER_HAVE_GETHOSTNAME +#define LIBVNCSERVER_HAVE_GETHOSTNAME 1 +#endif + +/* Define to 1 if you have the `getpwnam' function. */ +#ifndef LIBVNCSERVER_HAVE_GETPWNAM +#define LIBVNCSERVER_HAVE_GETPWNAM 1 +#endif + +/* Define to 1 if you have the `getpwuid' function. */ +#ifndef LIBVNCSERVER_HAVE_GETPWUID +#define LIBVNCSERVER_HAVE_GETPWUID 1 +#endif + +/* Define to 1 if you have the `getspnam' function. */ +/* #undef LIBVNCSERVER_HAVE_GETSPNAM */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#ifndef LIBVNCSERVER_HAVE_GETTIMEOFDAY +#define LIBVNCSERVER_HAVE_GETTIMEOFDAY 1 +#endif + +/* Define to 1 if you have the `getuid' function. */ +#ifndef LIBVNCSERVER_HAVE_GETUID +#define LIBVNCSERVER_HAVE_GETUID 1 +#endif + +/* Define to 1 if you have the `grantpt' function. */ +#ifndef LIBVNCSERVER_HAVE_GRANTPT +#define LIBVNCSERVER_HAVE_GRANTPT 1 +#endif + +/* Define to 1 if you have the `inet_ntoa' function. */ +#ifndef LIBVNCSERVER_HAVE_INET_NTOA +#define LIBVNCSERVER_HAVE_INET_NTOA 1 +#endif + +/* Define to 1 if you have the `initgroups' function. */ +#ifndef LIBVNCSERVER_HAVE_INITGROUPS +#define LIBVNCSERVER_HAVE_INITGROUPS 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_INTTYPES_H +#define LIBVNCSERVER_HAVE_INTTYPES_H 1 +#endif + +/* IRIX XReadDisplay available */ +/* #undef LIBVNCSERVER_HAVE_IRIX_XREADDISPLAY */ + +/* libcrypt library present */ +/* #undef LIBVNCSERVER_HAVE_LIBCRYPT */ + +/* openssl libcrypto library present */ +#ifndef LIBVNCSERVER_HAVE_LIBCRYPTO +#define LIBVNCSERVER_HAVE_LIBCRYPTO 1 +#endif + +/* Define to 1 if you have the `cygipc' library (-lcygipc). */ +/* #undef LIBVNCSERVER_HAVE_LIBCYGIPC */ + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +/* #undef LIBVNCSERVER_HAVE_LIBJPEG */ + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +/* #undef LIBVNCSERVER_HAVE_LIBNSL */ + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#ifndef LIBVNCSERVER_HAVE_LIBPTHREAD +#define LIBVNCSERVER_HAVE_LIBPTHREAD 1 +#endif + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef LIBVNCSERVER_HAVE_LIBSOCKET */ + +/* openssl libssl library present */ +#ifndef LIBVNCSERVER_HAVE_LIBSSL +#define LIBVNCSERVER_HAVE_LIBSSL 1 +#endif + +/* XDAMAGE extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_LIBXDAMAGE */ + +/* XFIXES extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_LIBXFIXES */ + +/* XINERAMA extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_LIBXINERAMA */ + +/* XRANDR extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_LIBXRANDR */ + +/* DEC-XTRAP extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_LIBXTRAP */ + +/* Define to 1 if you have the `z' library (-lz). */ +#ifndef LIBVNCSERVER_HAVE_LIBZ +#define LIBVNCSERVER_HAVE_LIBZ 1 +#endif + +/* linux fb device build environment present */ +/* #undef LIBVNCSERVER_HAVE_LINUX_FB_H */ + +/* linux/input.h present */ +/* #undef LIBVNCSERVER_HAVE_LINUX_INPUT_H */ + +/* linux uinput device build environment present */ +/* #undef LIBVNCSERVER_HAVE_LINUX_UINPUT_H */ + +/* video4linux build environment present */ +/* #undef LIBVNCSERVER_HAVE_LINUX_VIDEODEV_H */ + +/* build MacOS X native display support */ +#ifndef LIBVNCSERVER_HAVE_MACOSX_NATIVE_DISPLAY +#define LIBVNCSERVER_HAVE_MACOSX_NATIVE_DISPLAY 1 +#endif + +/* Define to 1 if you have the `memmove' function. */ +#ifndef LIBVNCSERVER_HAVE_MEMMOVE +#define LIBVNCSERVER_HAVE_MEMMOVE 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_MEMORY_H +#define LIBVNCSERVER_HAVE_MEMORY_H 1 +#endif + +/* Define to 1 if you have the `memset' function. */ +#ifndef LIBVNCSERVER_HAVE_MEMSET +#define LIBVNCSERVER_HAVE_MEMSET 1 +#endif + +/* Define to 1 if you have the `mkfifo' function. */ +#ifndef LIBVNCSERVER_HAVE_MKFIFO +#define LIBVNCSERVER_HAVE_MKFIFO 1 +#endif + +/* Define to 1 if you have the `mmap' function. */ +#ifndef LIBVNCSERVER_HAVE_MMAP +#define LIBVNCSERVER_HAVE_MMAP 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_NETDB_H +#define LIBVNCSERVER_HAVE_NETDB_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_NETINET_IN_H +#define LIBVNCSERVER_HAVE_NETINET_IN_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_PWD_H +#define LIBVNCSERVER_HAVE_PWD_H 1 +#endif + +/* RECORD extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_RECORD */ + +/* Define to 1 if you have the `select' function. */ +#ifndef LIBVNCSERVER_HAVE_SELECT +#define LIBVNCSERVER_HAVE_SELECT 1 +#endif + +/* Define to 1 if you have the `setegid' function. */ +#ifndef LIBVNCSERVER_HAVE_SETEGID +#define LIBVNCSERVER_HAVE_SETEGID 1 +#endif + +/* Define to 1 if you have the `seteuid' function. */ +#ifndef LIBVNCSERVER_HAVE_SETEUID +#define LIBVNCSERVER_HAVE_SETEUID 1 +#endif + +/* Define to 1 if you have the `setgid' function. */ +#ifndef LIBVNCSERVER_HAVE_SETGID +#define LIBVNCSERVER_HAVE_SETGID 1 +#endif + +/* Define to 1 if you have the `setpgrp' function. */ +#ifndef LIBVNCSERVER_HAVE_SETPGRP +#define LIBVNCSERVER_HAVE_SETPGRP 1 +#endif + +/* Define to 1 if you have the `setsid' function. */ +#ifndef LIBVNCSERVER_HAVE_SETSID +#define LIBVNCSERVER_HAVE_SETSID 1 +#endif + +/* Define to 1 if you have the `setuid' function. */ +#ifndef LIBVNCSERVER_HAVE_SETUID +#define LIBVNCSERVER_HAVE_SETUID 1 +#endif + +/* Define to 1 if you have the `setutxent' function. */ +#ifndef LIBVNCSERVER_HAVE_SETUTXENT +#define LIBVNCSERVER_HAVE_SETUTXENT 1 +#endif + +/* Define to 1 if you have the `shmat' function. */ +#ifndef LIBVNCSERVER_HAVE_SHMAT +#define LIBVNCSERVER_HAVE_SHMAT 1 +#endif + +/* Define to 1 if you have the `socket' function. */ +#ifndef LIBVNCSERVER_HAVE_SOCKET +#define LIBVNCSERVER_HAVE_SOCKET 1 +#endif + +/* Solaris XReadScreen available */ +/* #undef LIBVNCSERVER_HAVE_SOLARIS_XREADSCREEN */ + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +/* #undef LIBVNCSERVER_HAVE_STAT_EMPTY_STRING_BUG */ + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_STDINT_H +#define LIBVNCSERVER_HAVE_STDINT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_STDLIB_H +#define LIBVNCSERVER_HAVE_STDLIB_H 1 +#endif + +/* Define to 1 if you have the `strchr' function. */ +#ifndef LIBVNCSERVER_HAVE_STRCHR +#define LIBVNCSERVER_HAVE_STRCHR 1 +#endif + +/* Define to 1 if you have the `strcspn' function. */ +#ifndef LIBVNCSERVER_HAVE_STRCSPN +#define LIBVNCSERVER_HAVE_STRCSPN 1 +#endif + +/* Define to 1 if you have the `strdup' function. */ +#ifndef LIBVNCSERVER_HAVE_STRDUP +#define LIBVNCSERVER_HAVE_STRDUP 1 +#endif + +/* Define to 1 if you have the `strerror' function. */ +#ifndef LIBVNCSERVER_HAVE_STRERROR +#define LIBVNCSERVER_HAVE_STRERROR 1 +#endif + +/* Define to 1 if you have the `strftime' function. */ +#ifndef LIBVNCSERVER_HAVE_STRFTIME +#define LIBVNCSERVER_HAVE_STRFTIME 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_STRINGS_H +#define LIBVNCSERVER_HAVE_STRINGS_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_STRING_H +#define LIBVNCSERVER_HAVE_STRING_H 1 +#endif + +/* Define to 1 if you have the `strstr' function. */ +#ifndef LIBVNCSERVER_HAVE_STRSTR +#define LIBVNCSERVER_HAVE_STRSTR 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_SYSLOG_H +#define LIBVNCSERVER_HAVE_SYSLOG_H 1 +#endif + +/* Use the system libvncserver build environment for x11vnc. */ +/* #undef LIBVNCSERVER_HAVE_SYSTEM_LIBVNCSERVER */ + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_SYS_IOCTL_H +#define LIBVNCSERVER_HAVE_SYS_IOCTL_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#define LIBVNCSERVER_HAVE_SYS_SOCKET_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_SYS_STAT_H +#define LIBVNCSERVER_HAVE_SYS_STAT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef LIBVNCSERVER_HAVE_SYS_STROPTS_H */ + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_SYS_TIMEB_H +#define LIBVNCSERVER_HAVE_SYS_TIMEB_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_SYS_TIME_H +#define LIBVNCSERVER_HAVE_SYS_TIME_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_SYS_TYPES_H +#define LIBVNCSERVER_HAVE_SYS_TYPES_H 1 +#endif + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#ifndef LIBVNCSERVER_HAVE_SYS_WAIT_H +#define LIBVNCSERVER_HAVE_SYS_WAIT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_TERMIOS_H +#define LIBVNCSERVER_HAVE_TERMIOS_H 1 +#endif + +/* Define to 1 if compiler supports __thread */ +/* #undef LIBVNCSERVER_HAVE_TLS */ + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_UNISTD_H +#define LIBVNCSERVER_HAVE_UNISTD_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef LIBVNCSERVER_HAVE_UTMPX_H +#define LIBVNCSERVER_HAVE_UTMPX_H 1 +#endif + +/* Define to 1 if you have the `vfork' function. */ +#ifndef LIBVNCSERVER_HAVE_VFORK +#define LIBVNCSERVER_HAVE_VFORK 1 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef LIBVNCSERVER_HAVE_VFORK_H */ + +/* Define to 1 if you have the `vprintf' function. */ +#ifndef LIBVNCSERVER_HAVE_VPRINTF +#define LIBVNCSERVER_HAVE_VPRINTF 1 +#endif + +/* Define to 1 if you have the `waitpid' function. */ +#ifndef LIBVNCSERVER_HAVE_WAITPID +#define LIBVNCSERVER_HAVE_WAITPID 1 +#endif + +/* Define to 1 if `fork' works. */ +#ifndef LIBVNCSERVER_HAVE_WORKING_FORK +#define LIBVNCSERVER_HAVE_WORKING_FORK 1 +#endif + +/* Define to 1 if `vfork' works. */ +#ifndef LIBVNCSERVER_HAVE_WORKING_VFORK +#define LIBVNCSERVER_HAVE_WORKING_VFORK 1 +#endif + +/* X11 build environment present */ +/* #undef LIBVNCSERVER_HAVE_X11 */ + +/* open ssl X509_print_ex_fp available */ +#ifndef LIBVNCSERVER_HAVE_X509_PRINT_EX_FP +#define LIBVNCSERVER_HAVE_X509_PRINT_EX_FP 1 +#endif + +/* XKEYBOARD extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_XKEYBOARD */ + +/* MIT-SHM extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_XSHM */ + +/* XTEST extension build environment present */ +/* #undef LIBVNCSERVER_HAVE_XTEST */ + +/* XTEST extension has XTestGrabControl */ +/* #undef LIBVNCSERVER_HAVE_XTESTGRABCONTROL */ + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +/* #undef LIBVNCSERVER_LSTAT_FOLLOWS_SLASHED_SYMLINK */ + +/* Need a typedef for in_addr_t */ +/* #undef LIBVNCSERVER_NEED_INADDR_T */ + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef LIBVNCSERVER_NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#ifndef LIBVNCSERVER_PACKAGE +#define LIBVNCSERVER_PACKAGE "x11vnc" +#endif + +/* Define to the address where bug reports for this package should be sent. */ +#ifndef LIBVNCSERVER_PACKAGE_BUGREPORT +#define LIBVNCSERVER_PACKAGE_BUGREPORT "http://sourceforge.net/projects/libvncserver" +#endif + +/* Define to the full name of this package. */ +#ifndef LIBVNCSERVER_PACKAGE_NAME +#define LIBVNCSERVER_PACKAGE_NAME "x11vnc" +#endif + +/* Define to the full name and version of this package. */ +#ifndef LIBVNCSERVER_PACKAGE_STRING +#define LIBVNCSERVER_PACKAGE_STRING "x11vnc 0.9.12" +#endif + +/* Define to the one symbol short name of this package. */ +#ifndef LIBVNCSERVER_PACKAGE_TARNAME +#define LIBVNCSERVER_PACKAGE_TARNAME "x11vnc" +#endif + +/* Define to the version of this package. */ +#ifndef LIBVNCSERVER_PACKAGE_VERSION +#define LIBVNCSERVER_PACKAGE_VERSION "0.9.12" +#endif + +/* The number of bytes in type char */ +/* #undef LIBVNCSERVER_SIZEOF_CHAR */ + +/* The number of bytes in type int */ +/* #undef LIBVNCSERVER_SIZEOF_INT */ + +/* The number of bytes in type long */ +/* #undef LIBVNCSERVER_SIZEOF_LONG */ + +/* The number of bytes in type short */ +/* #undef LIBVNCSERVER_SIZEOF_SHORT */ + +/* The number of bytes in type void* */ +/* #undef LIBVNCSERVER_SIZEOF_VOIDP */ + +/* Define to 1 if you have the ANSI C header files. */ +#ifndef LIBVNCSERVER_STDC_HEADERS +#define LIBVNCSERVER_STDC_HEADERS 1 +#endif + +/* Define to 1 if you can safely include both and . */ +#ifndef LIBVNCSERVER_TIME_WITH_SYS_TIME +#define LIBVNCSERVER_TIME_WITH_SYS_TIME 1 +#endif + +/* Version number of package */ +#ifndef LIBVNCSERVER_VERSION +#define LIBVNCSERVER_VERSION "0.9.12" +#endif + +/* Enable support for gnutls in libvncclient */ +/* #undef LIBVNCSERVER_WITH_CLIENT_TLS */ + +/* Disable TightVNCFileTransfer protocol */ +#ifndef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER +#define LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER 1 +#endif + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef LIBVNCSERVER_WORDS_BIGENDIAN */ + +/* Define to 1 if the X Window System is missing or not being used. */ +#ifndef LIBVNCSERVER_X_DISPLAY_MISSING +#define LIBVNCSERVER_X_DISPLAY_MISSING 1 +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* The type for socklen */ +/* #undef socklen_t */ + +/* Define as `fork' if `vfork' does not work. */ +/* #undef vfork */ + +/* once: _RFB_RFBCONFIG_H */ +#endif diff --git a/3rdParty/LibVNC/src/rfb/rfbint.h b/3rdParty/LibVNC/src/rfb/rfbint.h new file mode 100644 index 0000000..f9816a0 --- /dev/null +++ b/3rdParty/LibVNC/src/rfb/rfbint.h @@ -0,0 +1,17 @@ +#ifndef _RFB_RFBINT_H +#define _RFB_RFBINT_H 1 +#ifndef _GENERATED_STDINT_H +#define _GENERATED_STDINT_H "x11vnc 0.9.12" +/* generated using a gnu compiler version i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664) Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ + +#include + + +/* system headers have good uint64_t */ +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +#endif + + /* once */ +#endif +#endif diff --git a/3rdParty/LibVNC/src/rfb/rfbproto.h b/3rdParty/LibVNC/src/rfb/rfbproto.h new file mode 100644 index 0000000..b6f201c --- /dev/null +++ b/3rdParty/LibVNC/src/rfb/rfbproto.h @@ -0,0 +1,1377 @@ +#ifndef RFBPROTO_H +#define RFBPROTO_H + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * rfbproto.h - header file for the RFB protocol version 3.3 + * + * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed + * integer (for n = 8, 16 and 32). + * + * All multiple byte integers are in big endian (network) order (most + * significant byte first). Unless noted otherwise there is no special + * alignment of protocol structures. + * + * + * Once the initial handshaking is done, all messages start with a type byte, + * (usually) followed by message-specific data. The order of definitions in + * this file is as follows: + * + * (1) Structures used in several types of message. + * (2) Structures used in the initial handshaking. + * (3) Message types. + * (4) Encoding types. + * (5) For each message type, the form of the data following the type byte. + * Sometimes this is defined by a single structure but the more complex + * messages have to be explained by comments. + */ + + +#if defined(WIN32) && !defined(__MINGW32__) +#define LIBVNCSERVER_WORDS_BIGENDIAN +#define rfbBool int +#include +#include +#undef SOCKET +#define SOCKET int +#else +#include +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#include +#ifdef __CHECKER__ +#undef Z_NULL +#define Z_NULL NULL +#endif +#endif + + +#if !defined(WIN32) || defined(__MINGW32__) +#define max(a,b) (((a)>(b))?(a):(b)) +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#endif +#define SOCKET int +typedef int8_t rfbBool; +#undef FALSE +#define FALSE 0 +#undef TRUE +#define TRUE -1 +#endif + +typedef uint32_t rfbKeySym; +typedef uint32_t rfbPixel; + +#ifdef LIBVNCSERVER_NEED_INADDR_T +typedef uint32_t in_addr_t; +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE ((in_addr_t) 0xffffffff) +#endif + +#define MAX_ENCODINGS 20 + +/***************************************************************************** + * + * Structures used in several messages + * + *****************************************************************************/ + +/*----------------------------------------------------------------------------- + * Structure used to specify a rectangle. This structure is a multiple of 4 + * bytes so that it can be interspersed with 32-bit pixel data without + * affecting alignment. + */ + +typedef struct { + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} rfbRectangle; + +#define sz_rfbRectangle 8 + + +/*----------------------------------------------------------------------------- + * Structure used to specify pixel format. + */ + +typedef struct { + + uint8_t bitsPerPixel; /* 8,16,32 only */ + + uint8_t depth; /* 8 to 32 */ + + uint8_t bigEndian; /* True if multi-byte pixels are interpreted + as big endian, or if single-bit-per-pixel + has most significant bit of the byte + corresponding to first (leftmost) pixel. Of + course this is meaningless for 8 bits/pix */ + + uint8_t trueColour; /* If false then we need a "colour map" to + convert pixels to RGB. If true, xxxMax and + xxxShift specify bits used for red, green + and blue */ + + /* the following fields are only meaningful if trueColour is true */ + + uint16_t redMax; /* maximum red value (= 2^n - 1 where n is the + number of bits used for red). Note this + value is always in big endian order. */ + + uint16_t greenMax; /* similar for green */ + + uint16_t blueMax; /* and blue */ + + uint8_t redShift; /* number of shifts needed to get the red + value in a pixel to the least significant + bit. To find the red value from a given + pixel, do the following: + 1) Swap pixel value according to bigEndian + (e.g. if bigEndian is false and host byte + order is big endian, then swap). + 2) Shift right by redShift. + 3) AND with redMax (in host byte order). + 4) You now have the red value between 0 and + redMax. */ + + uint8_t greenShift; /* similar for green */ + + uint8_t blueShift; /* and blue */ + + uint8_t pad1; + uint16_t pad2; + +} rfbPixelFormat; + +#define sz_rfbPixelFormat 16 + +/* UltraVNC: Color settings values */ +#define rfbPFFullColors 0 +#define rfbPF256Colors 1 +#define rfbPF64Colors 2 +#define rfbPF8Colors 3 +#define rfbPF8GreyColors 4 +#define rfbPF4GreyColors 5 +#define rfbPF2GreyColors 6 + + +/***************************************************************************** + * + * Initial handshaking messages + * + *****************************************************************************/ + +/*----------------------------------------------------------------------------- + * Protocol Version + * + * The server always sends 12 bytes to start which identifies the latest RFB + * protocol version number which it supports. These bytes are interpreted + * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where + * xxx and yyy are the major and minor version numbers (for version 3.3 + * this is "RFB 003.003\n"). + * + * The client then replies with a similar 12-byte message giving the version + * number of the protocol which should actually be used (which may be different + * to that quoted by the server). + * + * It is intended that both clients and servers may provide some level of + * backwards compatibility by this mechanism. Servers in particular should + * attempt to provide backwards compatibility, and even forwards compatibility + * to some extent. For example if a client demands version 3.1 of the + * protocol, a 3.0 server can probably assume that by ignoring requests for + * encoding types it doesn't understand, everything will still work OK. This + * will probably not be the case for changes in the major version number. + * + * The format string below can be used in sprintf or sscanf to generate or + * decode the version string respectively. + */ + +#define rfbProtocolVersionFormat "RFB %03d.%03d\n" +#define rfbProtocolMajorVersion 3 +#define rfbProtocolMinorVersion 8 +/* UltraVNC Viewer examines rfbProtocolMinorVersion number (4, and 6) + * to identify if the server supports File Transfer + */ + +typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ + +#define sz_rfbProtocolVersionMsg 12 + +/* + * Negotiation of the security type (protocol version 3.7) + * + * Once the protocol version has been decided, the server either sends a list + * of supported security types, or informs the client about an error (when the + * number of security types is 0). Security type rfbSecTypeTight is used to + * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth + * stands for classic VNC authentication. + * + * The client selects a particular security type from the list provided by the + * server. + */ + +#define rfbSecTypeInvalid 0 +#define rfbSecTypeNone 1 +#define rfbSecTypeVncAuth 2 + + +/*----------------------------------------------------------------------------- + * Authentication + * + * Once the protocol version has been decided, the server then sends a 32-bit + * word indicating whether any authentication is needed on the connection. + * The value of this word determines the authentication scheme in use. For + * version 3.0 of the protocol this may have one of the following values: + */ + +#define rfbConnFailed 0 +#define rfbNoAuth 1 +#define rfbVncAuth 2 + +#define rfbRA2 5 +#define rfbRA2ne 6 +#define rfbSSPI 7 +#define rfbSSPIne 8 +#define rfbTight 16 +#define rfbUltra 17 +#define rfbTLS 18 +#define rfbVeNCrypt 19 +#define rfbMSLogon 0xfffffffa + +#define rfbVeNCryptPlain 256 +#define rfbVeNCryptTLSNone 257 +#define rfbVeNCryptTLSVNC 258 +#define rfbVeNCryptTLSPlain 259 +#define rfbVeNCryptX509None 260 +#define rfbVeNCryptX509VNC 261 +#define rfbVeNCryptX509Plain 262 +#define rfbVeNCryptX509SASL 263 +#define rfbVeNCryptTLSSASL 264 + +/* + * rfbConnFailed: For some reason the connection failed (e.g. the server + * cannot support the desired protocol version). This is + * followed by a string describing the reason (where a + * string is specified as a 32-bit length followed by that + * many ASCII characters). + * + * rfbNoAuth: No authentication is needed. + * + * rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte + * challenge follows, which the client encrypts as + * appropriate using the password and sends the resulting + * 16-byte response. If the response is correct, the + * server sends the 32-bit word rfbVncAuthOK. If a simple + * failure happens, the server sends rfbVncAuthFailed and + * closes the connection. If the server decides that too + * many failures have occurred, it sends rfbVncAuthTooMany + * and closes the connection. In the latter case, the + * server should not allow an immediate reconnection by + * the client. + */ + +#define rfbVncAuthOK 0 +#define rfbVncAuthFailed 1 +#define rfbVncAuthTooMany 2 + + +/*----------------------------------------------------------------------------- + * Client Initialisation Message + * + * Once the client and server are sure that they're happy to talk to one + * another, the client sends an initialisation message. At present this + * message only consists of a boolean indicating whether the server should try + * to share the desktop by leaving other clients connected, or give exclusive + * access to this client by disconnecting all other clients. + */ + +typedef struct { + uint8_t shared; +} rfbClientInitMsg; + +#define sz_rfbClientInitMsg 1 + + +/*----------------------------------------------------------------------------- + * Server Initialisation Message + * + * After the client initialisation message, the server sends one of its own. + * This tells the client the width and height of the server's framebuffer, + * its pixel format and the name associated with the desktop. + */ + +typedef struct { + uint16_t framebufferWidth; + uint16_t framebufferHeight; + rfbPixelFormat format; /* the server's preferred pixel format */ + uint32_t nameLength; + /* followed by char name[nameLength] */ +} rfbServerInitMsg; + +#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) + + +/* + * Following the server initialisation message it's up to the client to send + * whichever protocol messages it wants. Typically it will send a + * SetPixelFormat message and a SetEncodings message, followed by a + * FramebufferUpdateRequest. From then on the server will send + * FramebufferUpdate messages in response to the client's + * FramebufferUpdateRequest messages. The client should send + * FramebufferUpdateRequest messages with incremental set to true when it has + * finished processing one FramebufferUpdate and is ready to process another. + * With a fast client, the rate at which FramebufferUpdateRequests are sent + * should be regulated to avoid hogging the network. + */ + + + +/***************************************************************************** + * + * Message types + * + *****************************************************************************/ + +/* server -> client */ + +#define rfbFramebufferUpdate 0 +#define rfbSetColourMapEntries 1 +#define rfbBell 2 +#define rfbServerCutText 3 +/* Modif sf@2002 */ +#define rfbResizeFrameBuffer 4 +#define rfbKeyFrameUpdate 5 +#define rfbPalmVNCReSizeFrameBuffer 0xF + +/* client -> server */ + +#define rfbSetPixelFormat 0 +#define rfbFixColourMapEntries 1 /* not currently supported */ +#define rfbSetEncodings 2 +#define rfbFramebufferUpdateRequest 3 +#define rfbKeyEvent 4 +#define rfbPointerEvent 5 +#define rfbClientCutText 6 +/* Modif sf@2002 - actually bidirectionnal */ +#define rfbFileTransfer 7 +/* Modif sf@2002 */ +#define rfbSetScale 8 +/* Modif rdv@2002 */ +#define rfbSetServerInput 9 +/* Modif rdv@2002 */ +#define rfbSetSW 10 +/* Modif sf@2002 - TextChat - Bidirectionnal */ +#define rfbTextChat 11 +/* Modif cs@2005 */ +#define rfbKeyFrameRequest 12 +/* PalmVNC 1.4 & 2.0 SetScale Factor message */ +#define rfbPalmVNCSetScaleFactor 0xF + + + + +/***************************************************************************** + * + * Encoding types + * + *****************************************************************************/ + +#define rfbEncodingRaw 0 +#define rfbEncodingCopyRect 1 +#define rfbEncodingRRE 2 +#define rfbEncodingCoRRE 4 +#define rfbEncodingHextile 5 +#define rfbEncodingZlib 6 +#define rfbEncodingTight 7 +#define rfbEncodingZlibHex 8 +#define rfbEncodingUltra 9 +#define rfbEncodingZRLE 16 +#define rfbEncodingZYWRLE 17 + +/* Cache & XOR-Zlib - rdv@2002 */ +#define rfbEncodingCache 0xFFFF0000 +#define rfbEncodingCacheEnable 0xFFFF0001 +#define rfbEncodingXOR_Zlib 0xFFFF0002 +#define rfbEncodingXORMonoColor_Zlib 0xFFFF0003 +#define rfbEncodingXORMultiColor_Zlib 0xFFFF0004 +#define rfbEncodingSolidColor 0xFFFF0005 +#define rfbEncodingXOREnable 0xFFFF0006 +#define rfbEncodingCacheZip 0xFFFF0007 +#define rfbEncodingSolMonoZip 0xFFFF0008 +#define rfbEncodingUltraZip 0xFFFF0009 + +/* + * Special encoding numbers: + * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; + * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; + * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; + * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; + * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; + * 0xFFFFFFF0 .. 0xFFFFFFFF -- cross-encoding compression levels. + */ + +#define rfbEncodingCompressLevel0 0xFFFFFF00 +#define rfbEncodingCompressLevel1 0xFFFFFF01 +#define rfbEncodingCompressLevel2 0xFFFFFF02 +#define rfbEncodingCompressLevel3 0xFFFFFF03 +#define rfbEncodingCompressLevel4 0xFFFFFF04 +#define rfbEncodingCompressLevel5 0xFFFFFF05 +#define rfbEncodingCompressLevel6 0xFFFFFF06 +#define rfbEncodingCompressLevel7 0xFFFFFF07 +#define rfbEncodingCompressLevel8 0xFFFFFF08 +#define rfbEncodingCompressLevel9 0xFFFFFF09 + +#define rfbEncodingXCursor 0xFFFFFF10 +#define rfbEncodingRichCursor 0xFFFFFF11 +#define rfbEncodingPointerPos 0xFFFFFF18 + +#define rfbEncodingLastRect 0xFFFFFF20 +#define rfbEncodingNewFBSize 0xFFFFFF21 + +#define rfbEncodingQualityLevel0 0xFFFFFFE0 +#define rfbEncodingQualityLevel1 0xFFFFFFE1 +#define rfbEncodingQualityLevel2 0xFFFFFFE2 +#define rfbEncodingQualityLevel3 0xFFFFFFE3 +#define rfbEncodingQualityLevel4 0xFFFFFFE4 +#define rfbEncodingQualityLevel5 0xFFFFFFE5 +#define rfbEncodingQualityLevel6 0xFFFFFFE6 +#define rfbEncodingQualityLevel7 0xFFFFFFE7 +#define rfbEncodingQualityLevel8 0xFFFFFFE8 +#define rfbEncodingQualityLevel9 0xFFFFFFE9 + + +/* LibVNCServer additions. We claim 0xFFFE0000 - 0xFFFE00FF */ +#define rfbEncodingKeyboardLedState 0xFFFE0000 +#define rfbEncodingSupportedMessages 0xFFFE0001 +#define rfbEncodingSupportedEncodings 0xFFFE0002 +#define rfbEncodingServerIdentity 0xFFFE0003 + + +/***************************************************************************** + * + * Server -> client message definitions + * + *****************************************************************************/ + + +/*----------------------------------------------------------------------------- + * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. + * + * This message consists of a header giving the number of rectangles of pixel + * data followed by the rectangles themselves. The header is padded so that + * together with the type byte it is an exact multiple of 4 bytes (to help + * with alignment of 32-bit pixels): + */ + +typedef struct { + uint8_t type; /* always rfbFramebufferUpdate */ + uint8_t pad; + uint16_t nRects; + /* followed by nRects rectangles */ +} rfbFramebufferUpdateMsg; + +#define sz_rfbFramebufferUpdateMsg 4 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * KeyFrameUpdate - Acknowledgment of a key frame request, it tells the client + * that the next update received will be a key frame. + */ + +typedef struct { + uint8_t type; +} rfbKeyFrameUpdateMsg; + +#define sz_rfbKeyFrameUpdateMsg 1 + + +/* + * Each rectangle of pixel data consists of a header describing the position + * and size of the rectangle and a type word describing the encoding of the + * pixel data, followed finally by the pixel data. Note that if the client has + * not sent a SetEncodings message then it will only receive raw pixel data. + * Also note again that this structure is a multiple of 4 bytes. + */ + +typedef struct { + rfbRectangle r; + uint32_t encoding; /* one of the encoding types rfbEncoding... */ +} rfbFramebufferUpdateRectHeader; + +#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Supported Messages Encoding. This encoding does not contain any pixel data. + * Instead, it contains 2 sets of bitflags. These bitflags indicate what messages + * are supported by the server. + * rect->w contains byte count + */ + +typedef struct { + uint8_t client2server[32]; /* maximum of 256 message types (256/8)=32 */ + uint8_t server2client[32]; /* maximum of 256 message types (256/8)=32 */ +} rfbSupportedMessages; + +#define sz_rfbSupportedMessages 64 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Supported Encodings Encoding. This encoding does not contain any pixel data. + * Instead, it contains a list of (uint32_t) Encodings supported by this server. + * rect->w contains byte count + * rect->h contains encoding count + */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Server Identity Encoding. This encoding does not contain any pixel data. + * Instead, it contains a text string containing information about the server. + * ie: "x11vnc: 0.8.1 lastmod: 2006-04-25 (libvncserver 0.9pre)\0" + * rect->w contains byte count + */ + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Raw Encoding. Pixels are sent in top-to-bottom scanline order, + * left-to-right within a scanline with no padding in between. + */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * KeyboardLedState Encoding. The X coordinate contains the Locked Modifiers + * so that a remote troubleshooter can identify that the users 'Caps Lock' + * is set... (It helps a *lot* when the users are untrained) + */ +#define rfbKeyboardMaskShift 1 +#define rfbKeyboardMaskCapsLock 2 +#define rfbKeyboardMaskControl 4 +#define rfbKeyboardMaskAlt 8 +#define rfbKeyboardMaskMeta 16 +#define rfbKeyboardMaskSuper 32 +#define rfbKeyboardMaskHyper 64 +#define rfbKeyboardMaskNumLock 128 +#define rfbKeyboardMaskScrollLock 256 +#define rfbKeyboardMaskAltGraph 512 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CopyRect Encoding. The pixels are specified simply by the x and y position + * of the source rectangle. + */ + +typedef struct { + uint16_t srcX; + uint16_t srcY; +} rfbCopyRect; + +#define sz_rfbCopyRect 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure + * giving the number of subrectangles following. Finally the data follows in + * the form [...] where each is + * []. + */ + +typedef struct { + uint32_t nSubrects; +} rfbRREHeader; + +#define sz_rfbRREHeader 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving + * the number of subrectangles following. Finally the data follows in the form + * [...] where each is + * []. This means that + * the whole rectangle must be at most 255x255 pixels. + */ + +typedef struct { + uint8_t x; + uint8_t y; + uint8_t w; + uint8_t h; +} rfbCoRRERectangle; + +#define sz_rfbCoRRERectangle 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, + * starting at the top left going in left-to-right, top-to-bottom order. If + * the width of the rectangle is not an exact multiple of 16 then the width of + * the last tile in each row will be correspondingly smaller. Similarly if the + * height is not an exact multiple of 16 then the height of each tile in the + * final row will also be smaller. Each tile begins with a "subencoding" type + * byte, which is a mask made up of a number of bits. If the Raw bit is set + * then the other bits are irrelevant; w*h pixel values follow (where w and h + * are the width and height of the tile). Otherwise the tile is encoded in a + * similar way to RRE, except that the position and size of each subrectangle + * can be specified in just two bytes. The other bits in the mask are as + * follows: + * + * BackgroundSpecified - if set, a pixel value follows which specifies + * the background colour for this tile. The first non-raw tile in a + * rectangle must have this bit set. If this bit isn't set then the + * background is the same as the last tile. + * + * ForegroundSpecified - if set, a pixel value follows which specifies + * the foreground colour to be used for all subrectangles in this tile. + * If this bit is set then the SubrectsColoured bit must be zero. + * + * AnySubrects - if set, a single byte follows giving the number of + * subrectangles following. If not set, there are no subrectangles (i.e. + * the whole tile is just solid background colour). + * + * SubrectsColoured - if set then each subrectangle is preceded by a pixel + * value giving the colour of that subrectangle. If not set, all + * subrectangles are the same colour, the foreground colour; if the + * ForegroundSpecified bit wasn't set then the foreground is the same as + * the last tile. + * + * The position and size of each subrectangle is specified in two bytes. The + * Pack macros below can be used to generate the two bytes from x, y, w, h, + * and the Extract macros can be used to extract the x, y, w, h values from + * the two bytes. + */ + +#define rfbHextileRaw (1 << 0) +#define rfbHextileBackgroundSpecified (1 << 1) +#define rfbHextileForegroundSpecified (1 << 2) +#define rfbHextileAnySubrects (1 << 3) +#define rfbHextileSubrectsColoured (1 << 4) + +#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) +#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) +#define rfbHextileExtractX(byte) ((byte) >> 4) +#define rfbHextileExtractY(byte) ((byte) & 0xf) +#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) +#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * zlib - zlib compressed Encoding. We have an rfbZlibHeader structure + * giving the number of bytes following. Finally the data follows is + * zlib compressed version of the raw pixel data as negotiated. + * (NOTE: also used by Ultra Encoding) + */ + +typedef struct { + uint32_t nBytes; +} rfbZlibHeader; + +#define sz_rfbZlibHeader 4 + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Tight Encoding. + * + *-- The first byte of each Tight-encoded rectangle is a "compression control + * byte". Its format is as follows (bit 0 is the least significant one): + * + * bit 0: if 1, then compression stream 0 should be reset; + * bit 1: if 1, then compression stream 1 should be reset; + * bit 2: if 1, then compression stream 2 should be reset; + * bit 3: if 1, then compression stream 3 should be reset; + * bits 7-4: if 1000 (0x08), then the compression type is "fill", + * if 1001 (0x09), then the compression type is "jpeg", + * if 0xxx, then the compression type is "basic", + * values greater than 1001 are not valid. + * + * If the compression type is "basic", then bits 6..4 of the + * compression control byte (those xxx in 0xxx) specify the following: + * + * bits 5-4: decimal representation is the index of a particular zlib + * stream which should be used for decompressing the data; + * bit 6: if 1, then a "filter id" byte is following this byte. + * + *-- The data that follows after the compression control byte described + * above depends on the compression type ("fill", "jpeg" or "basic"). + * + *-- If the compression type is "fill", then the only pixel value follows, in + * client pixel format (see NOTE 1). This value applies to all pixels of the + * rectangle. + * + *-- If the compression type is "jpeg", the following data stream looks like + * this: + * + * 1..3 bytes: data size (N) in compact representation; + * N bytes: JPEG image. + * + * Data size is compactly represented in one, two or three bytes, according + * to the following scheme: + * + * 0xxxxxxx (for values 0..127) + * 1xxxxxxx 0yyyyyyy (for values 128..16383) + * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303) + * + * Here each character denotes one bit, xxxxxxx are the least significant 7 + * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the + * most significant 8 bits (bits 14-21). For example, decimal value 10000 + * should be represented as two bytes: binary 10010000 01001110, or + * hexadecimal 90 4E. + * + *-- If the compression type is "basic" and bit 6 of the compression control + * byte was set to 1, then the next (second) byte specifies "filter id" which + * tells the decoder what filter type was used by the encoder to pre-process + * pixel data before the compression. The "filter id" byte can be one of the + * following: + * + * 0: no filter ("copy" filter); + * 1: "palette" filter; + * 2: "gradient" filter. + * + *-- If bit 6 of the compression control byte is set to 0 (no "filter id" + * byte), or if the filter id is 0, then raw pixel values in the client + * format (see NOTE 1) will be compressed. See below details on the + * compression. + * + *-- The "gradient" filter pre-processes pixel data with a simple algorithm + * which converts each color component to a difference between a "predicted" + * intensity and the actual intensity. Such a technique does not affect + * uncompressed data size, but helps to compress photo-like images better. + * Pseudo-code for converting intensities to differences is the following: + * + * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; + * if (P[i,j] < 0) then P[i,j] := 0; + * if (P[i,j] > MAX) then P[i,j] := MAX; + * D[i,j] := V[i,j] - P[i,j]; + * + * Here V[i,j] is the intensity of a color component for a pixel at + * coordinates (i,j). MAX is the maximum value of intensity for a color + * component. + * + *-- The "palette" filter converts true-color pixel data to indexed colors + * and a palette which can consist of 2..256 colors. If the number of colors + * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to + * encode one pixel. 1-bit encoding is performed such way that the most + * significant bits correspond to the leftmost pixels, and each raw of pixels + * is aligned to the byte boundary. When "palette" filter is used, the + * palette is sent before the pixel data. The palette begins with an unsigned + * byte which value is the number of colors in the palette minus 1 (i.e. 1 + * means 2 colors, 255 means 256 colors in the palette). Then follows the + * palette itself which consist of pixel values in client pixel format (see + * NOTE 1). + * + *-- The pixel data is compressed using the zlib library. But if the data + * size after applying the filter but before the compression is less then 12, + * then the data is sent as is, uncompressed. Four separate zlib streams + * (0..3) can be used and the decoder should read the actual stream id from + * the compression control byte (see NOTE 2). + * + * If the compression is not used, then the pixel data is sent as is, + * otherwise the data stream looks like this: + * + * 1..3 bytes: data size (N) in compact representation; + * N bytes: zlib-compressed data. + * + * Data size is compactly represented in one, two or three bytes, just like + * in the "jpeg" compression method (see above). + * + *-- NOTE 1. If the color depth is 24, and all three color components are + * 8-bit wide, then one pixel in Tight encoding is always represented by + * three bytes, where the first byte is red component, the second byte is + * green component, and the third byte is blue component of the pixel color + * value. This applies to colors in palettes as well. + * + *-- NOTE 2. The decoder must reset compression streams' states before + * decoding the rectangle, if some of bits 0,1,2,3 in the compression control + * byte are set to 1. Note that the decoder must reset zlib streams even if + * the compression type is "fill" or "jpeg". + * + *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only + * when bits-per-pixel value is either 16 or 32, not 8. + * + *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048 + * pixels. If a rectangle is wider, it must be split into several rectangles + * and each one should be encoded separately. + * + */ + +#define rfbTightExplicitFilter 0x04 +#define rfbTightFill 0x08 +#define rfbTightJpeg 0x09 +#define rfbTightMaxSubencoding 0x09 + +/* Filters to improve compression efficiency */ +#define rfbTightFilterCopy 0x00 +#define rfbTightFilterPalette 0x01 +#define rfbTightFilterGradient 0x02 + +#endif + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * XCursor encoding. This is a special encoding used to transmit X-style + * cursor shapes from server to clients. Note that for this encoding, + * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot + * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB + * samples are sent after header in the rfbXCursorColors structure. They + * denote foreground and background colors of the cursor. If a client + * supports only black-and-white cursors, it should ignore these colors and + * assume that foreground is black and background is white. Next, two bitmaps + * (1 bits per pixel) follow: first one with actual data (value 0 denotes + * background color, value 1 denotes foreground color), second one with + * transparency data (bits with zero value mean that these pixels are + * transparent). Both bitmaps represent cursor data in a byte stream, from + * left to right, from top to bottom, and each row is byte-aligned. Most + * significant bits correspond to leftmost pixels. The number of bytes in + * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor + * should be hidden (or default local cursor should be set by the client). + */ + +typedef struct { + uint8_t foreRed; + uint8_t foreGreen; + uint8_t foreBlue; + uint8_t backRed; + uint8_t backGreen; + uint8_t backBlue; +} rfbXCursorColors; + +#define sz_rfbXCursorColors 6 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RichCursor encoding. This is a special encoding used to transmit cursor + * shapes from server to clients. It is similar to the XCursor encoding but + * uses client pixel format instead of two RGB colors to represent cursor + * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader + * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h). + * After header, two pixmaps follow: first one with cursor image in current + * client pixel format (like in raw encoding), second with transparency data + * (1 bit per pixel, exactly the same format as used for transparency bitmap + * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or + * default local cursor should be set by the client). + */ + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ZRLE - encoding combining Zlib compression, tiling, palettisation and + * run-length encoding. + */ + +typedef struct { + uint32_t length; +} rfbZRLEHeader; + +#define sz_rfbZRLEHeader 4 + +#define rfbZRLETileWidth 64 +#define rfbZRLETileHeight 64 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the + * hextile encoding with zlib compression on the tiles that can not be + * efficiently encoded with one of the other hextile subencodings. The + * new zlib subencoding uses two bytes to specify the length of the + * compressed tile and then the compressed data follows. As with the + * raw sub-encoding, the zlib subencoding invalidates the other + * values, if they are also set. + */ + +#define rfbHextileZlibRaw (1 << 5) +#define rfbHextileZlibHex (1 << 6) +#define rfbHextileZlibMono (1 << 7) + + +/*----------------------------------------------------------------------------- + * SetColourMapEntries - these messages are only sent if the pixel + * format uses a "colour map" (i.e. trueColour false) and the client has not + * fixed the entire colour map using FixColourMapEntries. In addition they + * will only start being sent after the client has sent its first + * FramebufferUpdateRequest. So if the client always tells the server to use + * trueColour then it never needs to process this type of message. + */ + +typedef struct { + uint8_t type; /* always rfbSetColourMapEntries */ + uint8_t pad; + uint16_t firstColour; + uint16_t nColours; + + /* Followed by nColours * 3 * uint16_t + r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ + +} rfbSetColourMapEntriesMsg; + +#define sz_rfbSetColourMapEntriesMsg 6 + + + +/*----------------------------------------------------------------------------- + * Bell - ring a bell on the client if it has one. + */ + +typedef struct { + uint8_t type; /* always rfbBell */ +} rfbBellMsg; + +#define sz_rfbBellMsg 1 + + + +/*----------------------------------------------------------------------------- + * ServerCutText - the server has new text in its cut buffer. + */ + +typedef struct { + uint8_t type; /* always rfbServerCutText */ + uint8_t pad1; + uint16_t pad2; + uint32_t length; + /* followed by char text[length] */ +} rfbServerCutTextMsg; + +#define sz_rfbServerCutTextMsg 8 + + +/*----------------------------------------------------------------------------- + * // Modif sf@2002 + * FileTransferMsg - The client sends FileTransfer message. + * Bidirectional message - Files can be sent from client to server & vice versa + */ + +typedef struct _rfbFileTransferMsg { + uint8_t type; /* always rfbFileTransfer */ + uint8_t contentType; /* See defines below */ + uint8_t contentParam;/* Other possible content classification (Dir or File name, etc..) */ + uint8_t pad; /* It appears that UltraVNC *forgot* to Swap16IfLE(contentParam) */ + uint32_t size; /* FileSize or packet index or error or other */ +/* uint32_t sizeH; Additional 32Bits params to handle big values. Only for V2 (we want backward compatibility between all V1 versions) */ + uint32_t length; + /* followed by data char text[length] */ +} rfbFileTransferMsg; + +#define sz_rfbFileTransferMsg 12 + +#define rfbFileTransferVersion 2 /* v1 is the old FT version ( <= 1.0.0 RC18 versions) */ + +/* FileTransfer Content types and Params defines */ +#define rfbDirContentRequest 1 /* Client asks for the content of a given Server directory */ +#define rfbDirPacket 2 /* Full directory name or full file name. */ + /* Null content means end of Directory */ +#define rfbFileTransferRequest 3 /* Client asks the server for the transfer of a given file */ +#define rfbFileHeader 4 /* First packet of a file transfer, containing file's features */ +#define rfbFilePacket 5 /* One chunk of the file */ +#define rfbEndOfFile 6 /* End of file transfer (the file has been received or error) */ +#define rfbAbortFileTransfer 7 /* The file transfer must be aborted, whatever the state */ +#define rfbFileTransferOffer 8 /* The client offers to send a file to the server */ +#define rfbFileAcceptHeader 9 /* The server accepts or rejects the file */ +#define rfbCommand 10 /* The Client sends a simple command (File Delete, Dir create etc...) */ +#define rfbCommandReturn 11 /* The Client receives the server's answer about a simple command */ +#define rfbFileChecksums 12 /* The zipped checksums of the destination file (Delta Transfer) */ +#define rfbFileTransferAccess 14 /* Request FileTransfer authorization */ + + /* rfbDirContentRequest client Request - content params */ +#define rfbRDirContent 1 /* Request a Server Directory contents */ +#define rfbRDrivesList 2 /* Request the server's drives list */ +#define rfbRDirRecursiveList 3 /* Request a server directory content recursive sorted list */ +#define rfbRDirRecursiveSize 4 /* Request a server directory content recursive size */ + + /* rfbDirPacket & rfbCommandReturn server Answer - content params */ +#define rfbADirectory 1 /* Reception of a directory name */ +#define rfbAFile 2 /* Reception of a file name */ +#define rfbADrivesList 3 /* Reception of a list of drives */ +#define rfbADirCreate 4 /* Response to a create dir command */ +#define rfbADirDelete 5 /* Response to a delete dir command */ +#define rfbAFileCreate 6 /* Response to a create file command */ +#define rfbAFileDelete 7 /* Response to a delete file command */ +#define rfbAFileRename 8 /* Response to a rename file command */ +#define rfbADirRename 9 /* Response to a rename dir command */ +#define rfbADirRecursiveListItem 10 +#define rfbADirRecursiveSize 11 + + /* rfbCommand Command - content params */ +#define rfbCDirCreate 1 /* Request the server to create the given directory */ +#define rfbCDirDelete 2 /* Request the server to delete the given directory */ +#define rfbCFileCreate 3 /* Request the server to create the given file */ +#define rfbCFileDelete 4 /* Request the server to delete the given file */ +#define rfbCFileRename 5 /* Request the server to rename the given file */ +#define rfbCDirRename 6 /* Request the server to rename the given directory */ + + /* Errors - content params or "size" field */ +#define rfbRErrorUnknownCmd 1 /* Unknown FileTransfer command. */ +#define rfbRErrorCmd 0xFFFFFFFF/* Error when a command fails on remote side (ret in "size" field) */ + +#define sz_rfbBlockSize 8192 /* Size of a File Transfer packet (before compression) */ +#define rfbZipDirectoryPrefix "!UVNCDIR-\0" /* Transfered directory are zipped in a file with this prefix. Must end with "-" */ +#define sz_rfbZipDirectoryPrefix 9 +#define rfbDirPrefix "[ " +#define rfbDirSuffix " ]" + + + +/*----------------------------------------------------------------------------- + * Modif sf@2002 + * TextChatMsg - Utilized to order the TextChat mode on server or client + * Bidirectional message + */ + +typedef struct _rfbTextChatMsg { + uint8_t type; /* always rfbTextChat */ + uint8_t pad1; /* Could be used later as an additionnal param */ + uint16_t pad2; /* Could be used later as text offset, for instance */ + uint32_t length; /* Specific values for Open, close, finished (-1, -2, -3) */ + /* followed by char text[length] */ +} rfbTextChatMsg; + +#define sz_rfbTextChatMsg 8 + +#define rfbTextMaxSize 4096 +#define rfbTextChatOpen 0xFFFFFFFF +#define rfbTextChatClose 0xFFFFFFFE +#define rfbTextChatFinished 0xFFFFFFFD + + + +/*----------------------------------------------------------------------------- + * Modif sf@2002 + * ResizeFrameBuffer - The Client must change the size of its framebuffer + */ + +typedef struct _rfbResizeFrameBufferMsg { + uint8_t type; /* always rfbResizeFrameBuffer */ + uint8_t pad1; + uint16_t framebufferWidth; /* FrameBuffer width */ + uint16_t framebufferHeigth; /* FrameBuffer height */ +} rfbResizeFrameBufferMsg; + +#define sz_rfbResizeFrameBufferMsg 6 + + +/*----------------------------------------------------------------------------- + * Copyright (C) 2001 Harakan Software + * PalmVNC 1.4 & 2.? ResizeFrameBuffer message + * ReSizeFrameBuffer - tell the RFB client to alter its framebuffer, either + * due to a resize of the server desktop or a client-requested scaling factor. + * The pixel format remains unchanged. + */ + +typedef struct { + uint8_t type; /* always rfbReSizeFrameBuffer */ + uint8_t pad1; + uint16_t desktop_w; /* Desktop width */ + uint16_t desktop_h; /* Desktop height */ + uint16_t buffer_w; /* FrameBuffer width */ + uint16_t buffer_h; /* Framebuffer height */ + uint16_t pad2; + +} rfbPalmVNCReSizeFrameBufferMsg; + +#define sz_rfbPalmVNCReSizeFrameBufferMsg (12) + + + + +/*----------------------------------------------------------------------------- + * Union of all server->client messages. + */ + +typedef union { + uint8_t type; + rfbFramebufferUpdateMsg fu; + rfbSetColourMapEntriesMsg scme; + rfbBellMsg b; + rfbServerCutTextMsg sct; + rfbResizeFrameBufferMsg rsfb; + rfbPalmVNCReSizeFrameBufferMsg prsfb; + rfbFileTransferMsg ft; + rfbTextChatMsg tc; +} rfbServerToClientMsg; + + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RDV Cache Encoding. + * special is not used at this point, can be used to reset cache or other specials + * just put it to make sure we don't have to change the encoding again. + */ + +typedef struct { + uint16_t special; +} rfbCacheRect; + +#define sz_rfbCacheRect 2 + + + + +/***************************************************************************** + * + * Message definitions (client -> server) + * + *****************************************************************************/ + + +/*----------------------------------------------------------------------------- + * SetPixelFormat - tell the RFB server the format in which the client wants + * pixels sent. + */ + +typedef struct { + uint8_t type; /* always rfbSetPixelFormat */ + uint8_t pad1; + uint16_t pad2; + rfbPixelFormat format; +} rfbSetPixelFormatMsg; + +#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) + + +/*----------------------------------------------------------------------------- + * FixColourMapEntries - when the pixel format uses a "colour map", fix + * read-only colour map entries. + * + * ***************** NOT CURRENTLY SUPPORTED ***************** + */ + +typedef struct { + uint8_t type; /* always rfbFixColourMapEntries */ + uint8_t pad; + uint16_t firstColour; + uint16_t nColours; + + /* Followed by nColours * 3 * uint16_t + r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ + +} rfbFixColourMapEntriesMsg; + +#define sz_rfbFixColourMapEntriesMsg 6 + + +/*----------------------------------------------------------------------------- + * SetEncodings - tell the RFB server which encoding types we accept. Put them + * in order of preference, if we have any. We may always receive raw + * encoding, even if we don't specify it here. + */ + +typedef struct { + uint8_t type; /* always rfbSetEncodings */ + uint8_t pad; + uint16_t nEncodings; + /* followed by nEncodings * uint32_t encoding types */ +} rfbSetEncodingsMsg; + +#define sz_rfbSetEncodingsMsg 4 + + +/*----------------------------------------------------------------------------- + * FramebufferUpdateRequest - request for a framebuffer update. If incremental + * is true then the client just wants the changes since the last update. If + * false then it wants the whole of the specified rectangle. + */ + +typedef struct { + uint8_t type; /* always rfbFramebufferUpdateRequest */ + uint8_t incremental; + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} rfbFramebufferUpdateRequestMsg; + +#define sz_rfbFramebufferUpdateRequestMsg 10 + + +/*----------------------------------------------------------------------------- + * KeyEvent - key press or release + * + * Keys are specified using the "keysym" values defined by the X Window System. + * For most ordinary keys, the keysym is the same as the corresponding ASCII + * value. Other common keys are: + * + * BackSpace 0xff08 + * Tab 0xff09 + * Return or Enter 0xff0d + * Escape 0xff1b + * Insert 0xff63 + * Delete 0xffff + * Home 0xff50 + * End 0xff57 + * Page Up 0xff55 + * Page Down 0xff56 + * Left 0xff51 + * Up 0xff52 + * Right 0xff53 + * Down 0xff54 + * F1 0xffbe + * F2 0xffbf + * ... ... + * F12 0xffc9 + * Shift 0xffe1 + * Control 0xffe3 + * Meta 0xffe7 + * Alt 0xffe9 + */ + +typedef struct { + uint8_t type; /* always rfbKeyEvent */ + uint8_t down; /* true if down (press), false if up */ + uint16_t pad; + uint32_t key; /* key is specified as an X keysym */ +} rfbKeyEventMsg; + +#define sz_rfbKeyEventMsg 8 + + +/*----------------------------------------------------------------------------- + * PointerEvent - mouse/pen move and/or button press. + */ + +typedef struct { + uint8_t type; /* always rfbPointerEvent */ + uint8_t buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ + uint16_t x; + uint16_t y; +} rfbPointerEventMsg; + +#define rfbButton1Mask 1 +#define rfbButton2Mask 2 +#define rfbButton3Mask 4 +#define rfbButton4Mask 8 +#define rfbButton5Mask 16 +/* RealVNC 335 method */ +#define rfbWheelUpMask rfbButton4Mask +#define rfbWheelDownMask rfbButton5Mask + +#define sz_rfbPointerEventMsg 6 + + + +/*----------------------------------------------------------------------------- + * ClientCutText - the client has new text in its cut buffer. + */ + +typedef struct { + uint8_t type; /* always rfbClientCutText */ + uint8_t pad1; + uint16_t pad2; + uint32_t length; + /* followed by char text[length] */ +} rfbClientCutTextMsg; + +#define sz_rfbClientCutTextMsg 8 + + + +/*----------------------------------------------------------------------------- + * sf@2002 - Set Server Scale + * SetServerScale - Server must change the scale of the client buffer. + */ + +typedef struct _rfbSetScaleMsg { + uint8_t type; /* always rfbSetScale */ + uint8_t scale; /* Scale value 1server messages. + */ + +typedef union { + uint8_t type; + rfbSetPixelFormatMsg spf; + rfbFixColourMapEntriesMsg fcme; + rfbSetEncodingsMsg se; + rfbFramebufferUpdateRequestMsg fur; + rfbKeyEventMsg ke; + rfbPointerEventMsg pe; + rfbClientCutTextMsg cct; + rfbSetScaleMsg ssc; + rfbPalmVNCSetScaleFactorMsg pssf; + rfbSetServerInputMsg sim; + rfbFileTransferMsg ft; + rfbSetSWMsg sw; + rfbTextChatMsg tc; +} rfbClientToServerMsg; + +/* + * vncauth.h - describes the functions provided by the vncauth library. + */ + +#define MAXPWLEN 8 +#define CHALLENGESIZE 16 + +extern int rfbEncryptAndStorePasswd(char *passwd, char *fname); +extern char *rfbDecryptPasswdFromFile(char *fname); +extern void rfbRandomBytes(unsigned char *bytes); +extern void rfbEncryptBytes(unsigned char *bytes, char *passwd); + + +#endif diff --git a/3rdParty/LibVNC/src/rfb/rfbregion.h b/3rdParty/LibVNC/src/rfb/rfbregion.h new file mode 100755 index 0000000..53da667 --- /dev/null +++ b/3rdParty/LibVNC/src/rfb/rfbregion.h @@ -0,0 +1,65 @@ +#ifndef SRAREGION_H +#define SRAREGION_H + +/* -=- SRA - Simple Region Algorithm + * A simple rectangular region implementation. + * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin + */ + +/* -=- sraRect */ + +typedef struct _rect { + int x1; + int y1; + int x2; + int y2; +} sraRect; + +typedef struct sraRegion sraRegion; + +/* -=- Region manipulation functions */ + +extern sraRegion *sraRgnCreate(); +extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2); +extern sraRegion *sraRgnCreateRgn(const sraRegion *src); + +extern void sraRgnDestroy(sraRegion *rgn); +extern void sraRgnMakeEmpty(sraRegion *rgn); +extern rfbBool sraRgnAnd(sraRegion *dst, const sraRegion *src); +extern void sraRgnOr(sraRegion *dst, const sraRegion *src); +extern rfbBool sraRgnSubtract(sraRegion *dst, const sraRegion *src); + +extern void sraRgnOffset(sraRegion *dst, int dx, int dy); + +extern rfbBool sraRgnPopRect(sraRegion *region, sraRect *rect, + unsigned long flags); + +extern unsigned long sraRgnCountRects(const sraRegion *rgn); +extern rfbBool sraRgnEmpty(const sraRegion *rgn); + +extern sraRegion *sraRgnBBox(const sraRegion *src); + +/* -=- rectangle iterator */ + +typedef struct sraRectangleIterator { + rfbBool reverseX,reverseY; + int ptrSize,ptrPos; + struct sraSpan** sPtrs; +} sraRectangleIterator; + +extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s); +extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY); +extern rfbBool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r); +extern void sraRgnReleaseIterator(sraRectangleIterator *i); + +void sraRgnPrint(const sraRegion *s); + +/* -=- Rectangle clipper (for speed) */ + +extern rfbBool sraClipRect(int *x, int *y, int *w, int *h, + int cx, int cy, int cw, int ch); + +extern rfbBool sraClipRect2(int *x, int *y, int *x2, int *y2, + int cx, int cy, int cx2, int cy2); + +#endif diff --git a/BuildTools/SCons/SConstruct b/BuildTools/SCons/SConstruct index b3d3c8f..f205577 100644 --- a/BuildTools/SCons/SConstruct +++ b/BuildTools/SCons/SConstruct @@ -377,6 +377,9 @@ if conf.CheckCHeader("avahi-client/client.h") and conf.CheckLib("avahi-client") env["AVAHI_FLAGS"].update(avahi_flags) conf.Finish() +# VNC +env["LIBVNC_BUNDLED"] = 1 + # Qt if env["qt"] : env["QTDIR"] = env["qt"] -- cgit v0.10.2-6-g49f6