You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libtdevnc/rfbserver.c

1647 lines
43 KiB

22 years ago
/*
* rfbserver.c - deal with server-side of the RFB protocol.
*/
/*
* Copyright (C) 2002 RealVNC Ltd.
22 years ago
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rfb.h"
#include "sraRegion.h"
#ifdef WIN32
#define write(sock,buf,len) send(sock,buf,len,0)
#else
22 years ago
#include <unistd.h>
#include <pwd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
22 years ago
#include <arpa/inet.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
22 years ago
#ifdef CORBA
#include <vncserverctrl.h>
#endif
#ifdef DEBUGPROTO
#undef DEBUGPROTO
#define DEBUGPROTO(x) x
#else
#define DEBUGPROTO(x)
#endif
22 years ago
rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */
static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
static void rfbProcessClientNormalMessage(rfbClientPtr cl);
static void rfbProcessClientInitMessage(rfbClientPtr cl);
#ifdef HAVE_PTHREADS
void rfbIncrClientRef(rfbClientPtr cl)
{
LOCK(cl->refCountMutex);
cl->refCount++;
UNLOCK(cl->refCountMutex);
}
void rfbDecrClientRef(rfbClientPtr cl)
{
LOCK(cl->refCountMutex);
cl->refCount--;
if(cl->refCount<=0) /* just to be sure also < 0 */
TSIGNAL(cl->deleteCond);
UNLOCK(cl->refCountMutex);
}
22 years ago
#else
void rfbIncrClientRef(rfbClientPtr cl) {}
void rfbDecrClientRef(rfbClientPtr cl) {}
#endif
#ifdef HAVE_PTHREADS
MUTEX(rfbClientListMutex);
#endif
22 years ago
struct rfbClientIterator {
rfbClientPtr next;
rfbScreenInfoPtr screen;
22 years ago
};
void
rfbClientListInit(rfbScreenInfoPtr rfbScreen)
{
if(sizeof(Bool)!=1) {
/* a sanity check */
fprintf(stderr,"Bool's size is not 1 (%d)!\n",sizeof(Bool));
exit(1);
}
22 years ago
rfbScreen->rfbClientHead = NULL;
INIT_MUTEX(rfbClientListMutex);
22 years ago
}
rfbClientIteratorPtr
rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
{
rfbClientIteratorPtr i =
(rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
i->next = 0;
i->screen = rfbScreen;
return i;
22 years ago
}
rfbClientPtr
rfbClientIteratorNext(rfbClientIteratorPtr i)
22 years ago
{
if(i->next == 0) {
LOCK(rfbClientListMutex);
i->next = i->screen->rfbClientHead;
UNLOCK(rfbClientListMutex);
} else {
IF_PTHREADS(rfbClientPtr cl = i->next);
i->next = i->next->next;
IF_PTHREADS(rfbDecrClientRef(cl));
}
#ifdef HAVE_PTHREADS
while(i->next && i->next->sock<0)
i->next = i->next->next;
if(i->next)
rfbIncrClientRef(i->next);
#endif
return i->next;
22 years ago
}
void
rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
{
IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
22 years ago
free(iterator);
22 years ago
}
/*
* rfbNewClientConnection is called from sockets.c when a new connection
* comes in.
*/
void
rfbNewClientConnection(rfbScreen,sock)
rfbScreenInfoPtr rfbScreen;
int sock;
{
rfbClientPtr cl;
cl = rfbNewClient(rfbScreen,sock);
#ifdef CORBA
if(cl!=NULL)
newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1);
#endif
22 years ago
}
/*
* rfbReverseConnection is called by the CORBA stuff to make an outward
* connection to a "listening" RFB client.
*/
rfbClientPtr
rfbReverseConnection(rfbScreen,host, port)
rfbScreenInfoPtr rfbScreen;
22 years ago
char *host;
int port;
{
int sock;
rfbClientPtr cl;
if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
22 years ago
return (rfbClientPtr)NULL;
cl = rfbNewClient(rfbScreen, sock);
22 years ago
if (cl) {
cl->reverseConnection = TRUE;
}
return cl;
}
/*
* rfbNewClient is called when a new connection has been made by whatever
* means.
*/
rfbClientPtr
rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
22 years ago
rfbScreenInfoPtr rfbScreen;
int sock;
Bool isUDP;
22 years ago
{
rfbProtocolVersionMsg pv;
rfbClientIteratorPtr iterator;
rfbClientPtr cl,cl_;
22 years ago
struct sockaddr_in addr;
22 years ago
socklen_t addrlen = sizeof(struct sockaddr_in);
22 years ago
int i;
22 years ago
cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
22 years ago
cl->screen = rfbScreen;
cl->sock = sock;
rfbResetStats(cl);
22 years ago
if(isUDP) {
rfbLog(" accepted UDP client\n");
} else {
int one=1;
getpeername(sock, (struct sockaddr *)&addr, &addrlen);
cl->host = strdup(inet_ntoa(addr.sin_addr));
22 years ago
rfbLog(" other clients:\n");
iterator = rfbGetClientIterator(rfbScreen);
while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
rfbLog(" %s\n",cl_->host);
}
rfbReleaseClientIterator(iterator);
22 years ago
#ifndef WIN32
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
rfbLogPerror("fcntl failed");
close(sock);
return NULL;
}
#endif
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one)) < 0) {
rfbLogPerror("setsockopt failed");
close(sock);
return NULL;
}
FD_SET(sock,&(rfbScreen->allFds));
rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
INIT_MUTEX(cl->outputMutex);
INIT_MUTEX(cl->refCountMutex);
INIT_COND(cl->deleteCond);
22 years ago
cl->state = RFB_PROTOCOL_VERSION;
cl->reverseConnection = FALSE;
cl->readyForSetColourMapEntries = FALSE;
cl->useCopyRect = FALSE;
cl->preferredEncoding = rfbEncodingRaw;
cl->correMaxWidth = 48;
cl->correMaxHeight = 48;
cl->zrleData = 0;
cl->copyRegion = sraRgnCreate();
cl->copyDX = 0;
cl->copyDY = 0;
22 years ago
cl->modifiedRegion =
sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
22 years ago
INIT_MUTEX(cl->updateMutex);
INIT_COND(cl->updateCond);
22 years ago
cl->requestedRegion = sraRgnCreate();
22 years ago
cl->format = cl->screen->rfbServerFormat;
cl->translateFn = rfbTranslateNone;
cl->translateLookupTable = NULL;
22 years ago
LOCK(rfbClientListMutex);
IF_PTHREADS(cl->refCount = 0);
cl->next = rfbScreen->rfbClientHead;
cl->prev = NULL;
if (rfbScreen->rfbClientHead)
22 years ago
rfbScreen->rfbClientHead->prev = cl;
rfbScreen->rfbClientHead = cl;
UNLOCK(rfbClientListMutex);
22 years ago
cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
cl->tightQualityLevel = -1;
for (i = 0; i < 4; i++)
22 years ago
cl->zsActive[i] = FALSE;
cl->enableCursorShapeUpdates = FALSE;
cl->useRichCursorEncoding = FALSE;
cl->enableLastRectEncoding = FALSE;
cl->useNewFBSize = FALSE;
22 years ago
cl->compStreamInited = FALSE;
cl->compStream.total_in = 0;
cl->compStream.total_out = 0;
cl->compStream.zalloc = Z_NULL;
cl->compStream.zfree = Z_NULL;
cl->compStream.opaque = Z_NULL;
22 years ago
cl->zlibCompressLevel = 5;
22 years ago
sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion,
rfbProtocolMinorVersion);
22 years ago
if (WriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
22 years ago
rfbLogPerror("rfbNewClient: write");
rfbCloseClient(cl);
/* TODO: memory leak here (cl is never freed)
* can rfbClientConnectionGone called at this time?
* tim@tjansen.de
*/
22 years ago
return NULL;
}
22 years ago
}
cl->clientData = NULL;
cl->clientGoneHook = doNothingWithClient;
switch (cl->screen->newClientHook(cl)) {
case RFB_CLIENT_ON_HOLD:
cl->onHold = TRUE;
break;
case RFB_CLIENT_ACCEPT:
cl->onHold = FALSE;
break;
case RFB_CLIENT_REFUSE:
rfbCloseClient(cl);
rfbClientConnectionGone(cl);
cl = NULL;
break;
}
22 years ago
return cl;
}
rfbClientPtr
rfbNewClient(rfbScreen,sock)
rfbScreenInfoPtr rfbScreen;
int sock;
{
return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
}
rfbClientPtr
rfbNewUDPClient(rfbScreen)
rfbScreenInfoPtr rfbScreen;
{
return((rfbScreen->udpClient=
rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE)));
}
22 years ago
/*
* rfbClientConnectionGone is called from sockets.c just after a connection
* has gone away.
*/
void
rfbClientConnectionGone(cl)
rfbClientPtr cl;
{
int i;
LOCK(rfbClientListMutex);
if (cl->prev)
cl->prev->next = cl->next;
else
cl->screen->rfbClientHead = cl->next;
if (cl->next)
cl->next->prev = cl->prev;
#ifdef HAVE_ZRLE
FreeZrleData(cl);
#endif
22 years ago
#ifdef HAVE_PTHREADS
LOCK(cl->refCountMutex);
if(cl->refCount) {
UNLOCK(cl->refCountMutex);
WAIT(cl->deleteCond,cl->refCountMutex);
} else {
UNLOCK(cl->refCountMutex);
}
22 years ago
#endif
if(cl->sock>=0)
FD_CLR(cl->sock,&(cl->screen->allFds));
22 years ago
cl->clientGoneHook(cl);
22 years ago
rfbLog("Client %s gone\n",cl->host);
free(cl->host);
/* Release the compression state structures if any. */
if ( cl->compStreamInited ) {
22 years ago
deflateEnd( &(cl->compStream) );
}
for (i = 0; i < 4; i++) {
if (cl->zsActive[i])
deflateEnd(&cl->zsStruct[i]);
}
if (pointerClient == cl)
pointerClient = NULL;
sraRgnDestroy(cl->modifiedRegion);
22 years ago
sraRgnDestroy(cl->requestedRegion);
sraRgnDestroy(cl->copyRegion);
22 years ago
UNLOCK(rfbClientListMutex);
22 years ago
if (cl->translateLookupTable) free(cl->translateLookupTable);
TINI_COND(cl->updateCond);
TINI_MUTEX(cl->updateMutex);
LOCK(cl->outputMutex);
TINI_MUTEX(cl->outputMutex);
#ifdef CORBA
destroyConnection(cl);
#endif
rfbPrintStats(cl);
22 years ago
free(cl);
22 years ago
}
/*
* rfbProcessClientMessage is called when there is data to read from a client.
*/
void
rfbProcessClientMessage(cl)
rfbClientPtr cl;
{
switch (cl->state) {
case RFB_PROTOCOL_VERSION:
rfbProcessClientProtocolVersion(cl);
return;
case RFB_AUTHENTICATION:
rfbAuthProcessClientMessage(cl);
return;
case RFB_INITIALISATION:
rfbProcessClientInitMessage(cl);
return;
default:
rfbProcessClientNormalMessage(cl);
return;
}
}
/*
* rfbProcessClientProtocolVersion is called when the client sends its
* protocol version.
*/
static void
rfbProcessClientProtocolVersion(cl)
rfbClientPtr cl;
{
rfbProtocolVersionMsg pv;
22 years ago
int n, major_, minor_;
22 years ago
char failureReason[256];
if ((n = ReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
if (n == 0)
rfbLog("rfbProcessClientProtocolVersion: client gone\n");
else
rfbLogPerror("rfbProcessClientProtocolVersion: read");
rfbCloseClient(cl);
return;
}
pv[sz_rfbProtocolVersionMsg] = 0;
22 years ago
if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
22 years ago
char name[1024];
if(sscanf(pv,"RFB %03d.%03d %1024s\n",&major_,&minor_,name) != 3) {
rfbLog("rfbProcessClientProtocolVersion: not a valid RFB client\n");
rfbCloseClient(cl);
return;
}
free(cl->host);
cl->host=strdup(name);
22 years ago
}
22 years ago
rfbLog("Protocol version %d.%d\n", major_, minor_);
22 years ago
22 years ago
if (major_ != rfbProtocolMajorVersion) {
22 years ago
/* Major version mismatch - send a ConnFailed message */
rfbLog("Major version mismatch\n");
sprintf(failureReason,
"RFB protocol version mismatch - server %d.%d, client %d.%d",
22 years ago
rfbProtocolMajorVersion,rfbProtocolMinorVersion,major_,minor_);
22 years ago
rfbClientConnFailed(cl, failureReason);
return;
}
22 years ago
if (minor_ != rfbProtocolMinorVersion) {
22 years ago
/* Minor version mismatch - warn but try to continue */
rfbLog("Ignoring minor version mismatch\n");
}
rfbAuthNewClient(cl);
}
/*
* rfbClientConnFailed is called when a client connection has failed either
* because it talks the wrong protocol or it has failed authentication.
*/
void
rfbClientConnFailed(cl, reason)
rfbClientPtr cl;
char *reason;
{
char *buf;
int len = strlen(reason);
buf = (char *)malloc(8 + len);
22 years ago
((CARD32 *)buf)[0] = Swap32IfLE(rfbConnFailed);
((CARD32 *)buf)[1] = Swap32IfLE(len);
memcpy(buf + 8, reason, len);
if (WriteExact(cl, buf, 8 + len) < 0)
rfbLogPerror("rfbClientConnFailed: write");
free(buf);
22 years ago
rfbCloseClient(cl);
}
/*
* rfbProcessClientInitMessage is called when the client sends its
* initialisation message.
*/
static void
rfbProcessClientInitMessage(cl)
rfbClientPtr cl;
{
rfbClientInitMsg ci;
char buf[256];
rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
int len, n;
rfbClientIteratorPtr iterator;
rfbClientPtr otherCl;
if ((n = ReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
if (n == 0)
rfbLog("rfbProcessClientInitMessage: client gone\n");
else
rfbLogPerror("rfbProcessClientInitMessage: read");
rfbCloseClient(cl);
return;
}
si->framebufferWidth = Swap16IfLE(cl->screen->width);
si->framebufferHeight = Swap16IfLE(cl->screen->height);
si->format = cl->screen->rfbServerFormat;
si->format.redMax = Swap16IfLE(si->format.redMax);
si->format.greenMax = Swap16IfLE(si->format.greenMax);
si->format.blueMax = Swap16IfLE(si->format.blueMax);
if (strlen(cl->screen->desktopName) > 128) /* sanity check on desktop name len */
22 years ago
((char*)cl->screen->desktopName)[128] = 0;
22 years ago
strcpy(buf + sz_rfbServerInitMsg, cl->screen->desktopName);
len = strlen(buf + sz_rfbServerInitMsg);
si->nameLength = Swap32IfLE(len);
if (WriteExact(cl, buf, sz_rfbServerInitMsg + len) < 0) {
rfbLogPerror("rfbProcessClientInitMessage: write");
rfbCloseClient(cl);
return;
}
cl->state = RFB_NORMAL;
if (!cl->reverseConnection &&
(cl->screen->rfbNeverShared || (!cl->screen->rfbAlwaysShared && !ci.shared))) {
if (cl->screen->rfbDontDisconnect) {
iterator = rfbGetClientIterator(cl->screen);
while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
rfbLog("-dontdisconnect: Not shared & existing client\n");
rfbLog(" refusing new client %s\n", cl->host);
rfbCloseClient(cl);
rfbReleaseClientIterator(iterator);
return;
}
}
rfbReleaseClientIterator(iterator);
} else {
iterator = rfbGetClientIterator(cl->screen);
while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
rfbLog("Not shared - closing connection to client %s\n",
otherCl->host);
rfbCloseClient(otherCl);
}
}
rfbReleaseClientIterator(iterator);
}
}
}
/*
* rfbProcessClientNormalMessage is called when the client has sent a normal
* protocol message.
*/
static void
rfbProcessClientNormalMessage(cl)
rfbClientPtr cl;
{
int n=0;
rfbClientToServerMsg msg;
char *str;
if ((n = ReadExact(cl, (char *)&msg, 1)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
switch (msg.type) {
case rfbSetPixelFormat:
if ((n = ReadExact(cl, ((char *)&msg) + 1,
sz_rfbSetPixelFormatMsg - 1)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
cl->format.depth = msg.spf.format.depth;
cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
22 years ago
cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
cl->format.redShift = msg.spf.format.redShift;
cl->format.greenShift = msg.spf.format.greenShift;
cl->format.blueShift = msg.spf.format.blueShift;
cl->readyForSetColourMapEntries = TRUE;
cl->screen->setTranslateFunction(cl);
22 years ago
return;
case rfbFixColourMapEntries:
if ((n = ReadExact(cl, ((char *)&msg) + 1,
sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
rfbLog("rfbProcessClientNormalMessage: %s",
"FixColourMapEntries unsupported\n");
rfbCloseClient(cl);
return;
case rfbSetEncodings:
{
int i;
CARD32 enc;
if ((n = ReadExact(cl, ((char *)&msg) + 1,
sz_rfbSetEncodingsMsg - 1)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
cl->preferredEncoding = -1;
cl->useCopyRect = FALSE;
cl->enableCursorShapeUpdates = FALSE;
cl->enableLastRectEncoding = FALSE;
cl->useNewFBSize = FALSE;
22 years ago
for (i = 0; i < msg.se.nEncodings; i++) {
if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
enc = Swap32IfLE(enc);
switch (enc) {
case rfbEncodingCopyRect:
cl->useCopyRect = TRUE;
break;
case rfbEncodingRaw:
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = enc;
rfbLog("Using raw encoding for client %s\n",
cl->host);
}
break;
case rfbEncodingRRE:
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = enc;
rfbLog("Using rre encoding for client %s\n",
cl->host);
}
break;
case rfbEncodingCoRRE:
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = enc;
rfbLog("Using CoRRE encoding for client %s\n",
cl->host);
}
break;
case rfbEncodingHextile:
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = enc;
rfbLog("Using hextile encoding for client %s\n",
cl->host);
}
break;
case rfbEncodingZlib:
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = enc;
rfbLog("Using zlib encoding for client %s\n",
cl->host);
}
break;
case rfbEncodingTight:
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = enc;
rfbLog("Using tight encoding for client %s\n",
cl->host);
}
break;
case rfbEncodingXCursor:
if(!cl->screen->dontConvertRichCursorToXCursor) {
rfbLog("Enabling X-style cursor updates for client %s\n",
cl->host);
cl->enableCursorShapeUpdates = TRUE;
cl->cursorWasChanged = TRUE;
}
22 years ago
break;
case rfbEncodingRichCursor:
rfbLog("Enabling full-color cursor updates for client "
"%s\n", cl->host);
cl->enableCursorShapeUpdates = TRUE;
cl->useRichCursorEncoding = TRUE;
cl->cursorWasChanged = TRUE;
break;
22 years ago
case rfbEncodingLastRect:
if (!cl->enableLastRectEncoding) {
rfbLog("Enabling LastRect protocol extension for client "
"%s\n", cl->host);
cl->enableLastRectEncoding = TRUE;
}
break;
case rfbEncodingNewFBSize:
if (!cl->useNewFBSize) {
rfbLog("Enabling NewFBSize protocol extension for client "
"%s\n", cl->host);
cl->useNewFBSize = TRUE;
}
break;
#ifdef BACKCHANNEL
case rfbEncodingBackChannel:
if (!cl->enableBackChannel) {
rfbLog("Enabling BackChannel protocol extension for "
"client %s\n", cl->host);
cl->enableBackChannel = TRUE;
}
break;
#endif
#ifdef HAVE_ZRLE
case rfbEncodingZRLE:
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = enc;
rfbLog("Using ZRLE encoding for client %s\n",
cl->host);
}
break;
#endif
22 years ago
default:
if ( enc >= (CARD32)rfbEncodingCompressLevel0 &&
enc <= (CARD32)rfbEncodingCompressLevel9 ) {
cl->zlibCompressLevel = enc & 0x0F;
cl->tightCompressLevel = enc & 0x0F;
rfbLog("Using compression level %d for client %s\n",
cl->tightCompressLevel, cl->host);
} else if ( enc >= (CARD32)rfbEncodingQualityLevel0 &&
enc <= (CARD32)rfbEncodingQualityLevel9 ) {
cl->tightQualityLevel = enc & 0x0F;
rfbLog("Using image quality level %d for client %s\n",
cl->tightQualityLevel, cl->host);
} else
rfbLog("rfbProcessClientNormalMessage: ignoring unknown "
"encoding type %d\n", (int)enc);
}
}
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = rfbEncodingRaw;
}
return;
}
case rfbFramebufferUpdateRequest:
{
sraRegionPtr tmpRegion;
22 years ago
if ((n = ReadExact(cl, ((char *)&msg) + 1,
sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
tmpRegion =
sraRgnCreateRect(Swap16IfLE(msg.fur.x),
Swap16IfLE(msg.fur.y),
Swap16IfLE(msg.fur.x)+Swap16IfLE(msg.fur.w),
Swap16IfLE(msg.fur.y)+Swap16IfLE(msg.fur.h));
22 years ago
LOCK(cl->updateMutex);
sraRgnOr(cl->requestedRegion,tmpRegion);
22 years ago
if (!cl->readyForSetColourMapEntries) {
/* client hasn't sent a SetPixelFormat so is using server's */
cl->readyForSetColourMapEntries = TRUE;
if (!cl->format.trueColour) {
if (!rfbSetClientColourMap(cl, 0, 0)) {
sraRgnDestroy(tmpRegion);
UNLOCK(cl->updateMutex);
22 years ago
return;
}
}
}
if (!msg.fur.incremental) {
sraRgnOr(cl->modifiedRegion,tmpRegion);
sraRgnSubtract(cl->copyRegion,tmpRegion);
}
TSIGNAL(cl->updateCond);
UNLOCK(cl->updateMutex);
sraRgnDestroy(tmpRegion);
22 years ago
return;
22 years ago
}
case rfbKeyEvent:
cl->rfbKeyEventsRcvd++;
if ((n = ReadExact(cl, ((char *)&msg) + 1,
sz_rfbKeyEventMsg - 1)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
cl->screen->kbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl);
return;
case rfbPointerEvent:
cl->rfbPointerEventsRcvd++;
if ((n = ReadExact(cl, ((char *)&msg) + 1,
sz_rfbPointerEventMsg - 1)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
if (pointerClient && (pointerClient != cl))
return;
if (msg.pe.buttonMask == 0)
pointerClient = NULL;
else
pointerClient = cl;
cl->screen->ptrAddEvent(msg.pe.buttonMask,
Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
return;
case rfbClientCutText:
if ((n = ReadExact(cl, ((char *)&msg) + 1,
sz_rfbClientCutTextMsg - 1)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
rfbCloseClient(cl);
return;
}
msg.cct.length = Swap32IfLE(msg.cct.length);
str = (char *)malloc(msg.cct.length);
22 years ago
if ((n = ReadExact(cl, str, msg.cct.length)) <= 0) {
if (n != 0)
rfbLogPerror("rfbProcessClientNormalMessage: read");
free(str);
22 years ago
rfbCloseClient(cl);
return;
}
cl->screen->setXCutText(str, msg.cct.length, cl);
free(str);
22 years ago
return;
default:
rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
msg.type);
rfbLog(" ... closing connection\n");
rfbCloseClient(cl);
return;
}
}