The great UltraVNC Compatibility Commit

pull/1/head
steven_carr 17 years ago
parent 347c4a9847
commit ccdbe8f325

@ -1,3 +1,23 @@
2006-05-15 Steven Carr <scarr@jsa-usa.com>
* The great UltraVNC Compatibility Commit!
libvncserver now supports the following messages:
SetSingleWindow - Select a single window to be the source of the
framebuffer.
ServerInput - Disable and blank the servers display
TextChat - TextChat between the remote/local user
(Bandwidth friendly VS the Notepad approach)
FileTransfer - Emulates a Windows Filesystem to the viewer
(Currently does not support Delta Transfers)
(Currently does not support Sending Directories)
UltraZip - Improved UltraZip support
* Improved Statistics SubSystem, now supports all encodings
* RFB 3.8 support! Error Messages are a 'Good Thing' (tm)
* Default to identify as RFB 3.6 to emulate UltraVNC server
(Server now has the ability to set the RFB version reported)
(permits the viewer to identify the server has FileTransfer ability)
* Client Encoding AutoSelection Supported (UltraViewer is speed aware)
* libvncclient has improved server detection/capabilities logic!
2006-05-13 Karl Runge <runge@karlrunge.com>
* minilzo.c,minilzo.h,lzoconf.h: switch to non-CRLF versions.
* libvncclient/Makefile.am: add minilzo.c, minilzo.h, lzoconf.h

@ -150,6 +150,26 @@ static void kbd_leds(rfbClient* cl, int value, int pad) {
fflush(stderr);
}
/* trivial support for textchat */
static void text_chat(rfbClient* cl, int value, char *text) {
switch(value) {
case rfbTextChatOpen:
fprintf(stderr,"TextChat: We should open a textchat window!\n");
TextChatOpen(cl);
break;
case rfbTextChatClose:
fprintf(stderr,"TextChat: We should close our window!\n");
break;
case rfbTextChatFinished:
fprintf(stderr,"TextChat: We should close our window!\n");
break;
default:
fprintf(stderr,"TextChat: Received \"%s\"\n", text);
break;
}
fflush(stderr);
}
#ifdef __MINGW32__
#define LOG_TO_FILE
#endif
@ -212,7 +232,7 @@ int main(int argc,char** argv) {
cl->canHandleNewFBSize = TRUE;
cl->GotFrameBufferUpdate=update;
cl->HandleKeyboardLedState=kbd_leds;
cl->HandleTextChat=text_chat;
if(!rfbInitClient(cl,&argc,argv))
return 1;

@ -223,6 +223,99 @@ static rfbBool HandleZRLE24Down(rfbClient* client, int rx, int ry, int rw, int r
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);
}
/*
* ConnectToRFBServer.
*/
@ -310,26 +403,87 @@ InitialiseRFBConnection(rfbClient* client)
return FALSE;
}
#if rfbProtocolMinorVersion == 7
/* work around LibVNCClient not yet speaking RFB 3.7 */
#undef rfbProtocolMinorVersion
#define rfbProtocolMinorVersion 3
#endif
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)
client->minor=8;
rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n",
major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion);
major = rfbProtocolMajorVersion;
minor = rfbProtocolMinorVersion;
sprintf(pv,rfbProtocolVersionFormat,major,minor);
sprintf(pv,rfbProtocolVersionFormat,client->major,client->minor);
if (!WriteToRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE;
if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE;
authScheme = rfbClientSwap32IfLE(authScheme);
/* 3.7 and onwards sends a # of security types first */
if (client->major==3 && client->minor > 6)
{
uint8_t count=0;
uint8_t loop=0;
uint8_t flag=0;
uint8_t tAuth=0;
if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE;
if (count==0)
{
rfbClientLog("List of security types is ZERO, expecting an error to follow\n");
/* we have an error following */
if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
reasonLen = rfbClientSwap32IfLE(reasonLen);
reason = malloc(reasonLen);
if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
rfbClientLog("VNC connection failed: %.*s\n",(int)reasonLen, reason);
free(reason);
return FALSE;
}
rfbClientLog("We have %d security types to read\n", count);
/* now, we have a list of available security types to read ( uint8_t[] ) */
for (loop=0;loop<count;loop++)
{
if (!ReadFromRFBServer(client, (char *)&tAuth, 1)) return FALSE;
rfbClientLog("%d) Received security type %d\n", loop, tAuth);
if ((flag==0) && ((tAuth==rfbVncAuth) || (tAuth==rfbNoAuth)))
{
flag++;
authScheme=tAuth;
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, 1)) return FALSE;
}
}
}
else
{
if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE;
authScheme = rfbClientSwap32IfLE(authScheme);
}
rfbClientLog("Selected Security Scheme %d\n", authScheme);
switch (authScheme) {
case rfbConnFailed:
@ -338,9 +492,10 @@ InitialiseRFBConnection(rfbClient* client)
reason = malloc(reasonLen);
if (!ReadFromRFBServer(client, reason, reasonLen)) return FALSE;
if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
rfbClientLog("VNC connection failed: %.*s\n",(int)reasonLen, reason);
free(reason);
return FALSE;
case rfbNoAuth:
@ -382,6 +537,17 @@ InitialiseRFBConnection(rfbClient* client)
rfbClientLog("VNC authentication succeeded\n");
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);
if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
rfbClientLog("VNC connection failed: %.*s\n",(int)reasonLen, reason);
free(reason);
return FALSE;
}
rfbClientLog("VNC authentication failed\n");
return FALSE;
case rfbVncAuthTooMany:
@ -427,7 +593,7 @@ InitialiseRFBConnection(rfbClient* client)
rfbClientLog("Desktop name \"%s\"\n",client->desktopName);
rfbClientLog("Connected to VNC server, using protocol version %d.%d\n",
rfbProtocolMajorVersion, rfbProtocolMinorVersion);
client->major, client->minor);
rfbClientLog("VNC server default format:\n");
PrintPixelFormat(&client->si.format);
@ -445,6 +611,7 @@ 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;
@ -453,6 +620,8 @@ SetFormatAndEncodings(rfbClient* client)
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);
@ -462,6 +631,9 @@ SetFormatAndEncodings(rfbClient* client)
if (!WriteToRFBServer(client, (char *)&spf, sz_rfbSetPixelFormatMsg))
return FALSE;
if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE;
se->type = rfbSetEncodings;
se->nEncodings = 0;
@ -641,7 +813,7 @@ SetFormatAndEncodings(rfbClient* client)
rfbBool
SendIncrementalFramebufferUpdateRequest(rfbClient* client)
{
return SendFramebufferUpdateRequest(client, 0, 0, client->width,
return SendFramebufferUpdateRequest(client, 0, 0, client->width,
client->height, TRUE);
}
@ -655,6 +827,8 @@ SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbB
{
rfbFramebufferUpdateRequestMsg fur;
if (!SupportsClient2Server(client, rfbFramebufferUpdateRequest)) return TRUE;
fur.type = rfbFramebufferUpdateRequest;
fur.incremental = incremental ? 1 : 0;
fur.x = rfbClientSwap16IfLE(x);
@ -677,19 +851,105 @@ SendScaleSetting(rfbClient* client,int scaleSetting)
{
rfbSetScaleMsg ssm;
if (client->appData.palmVNC)
ssm.type = rfbPalmVNCSetScaleFactor;
else
ssm.type = rfbSetScale;
ssm.scale = scaleSetting;
ssm.pad = 0;
if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
return FALSE;
/* 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.
*/
@ -699,6 +959,8 @@ 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;
@ -719,6 +981,8 @@ 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);
@ -739,6 +1003,8 @@ SendClientCutText(rfbClient* client, char *str, int len)
free(client->serverCutText);
client->serverCutText = NULL;
if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE;
cct.type = rfbClientCutText;
cct.length = rfbClientSwap32IfLE(len);
return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) &&
@ -858,9 +1124,8 @@ HandleRFBServerMessage(rfbClient* client)
/* rect.r.w=byte count */
if (rect.encoding == rfbEncodingSupportedMessages) {
rfbSupportedMessages msgs;
int loop;
if (!ReadFromRFBServer(client, (char *)&msgs, sz_rfbSupportedMessages))
if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages))
return FALSE;
/* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */
@ -869,18 +1134,18 @@ HandleRFBServerMessage(rfbClient* client)
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,
msgs.client2server[loop], msgs.client2server[loop+1],
msgs.client2server[loop+2], msgs.client2server[loop+3],
msgs.client2server[loop+4], msgs.client2server[loop+5],
msgs.client2server[loop+6], msgs.client2server[loop+7]);
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,
msgs.server2client[loop], msgs.server2client[loop+1],
msgs.server2client[loop+2], msgs.server2client[loop+3],
msgs.server2client[loop+4], msgs.server2client[loop+5],
msgs.server2client[loop+6], msgs.server2client[loop+7]);
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;
}
@ -1217,6 +1482,47 @@ HandleRFBServerMessage(rfbClient* client)
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 <just in case> */
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,

@ -18,8 +18,6 @@
* USA.
*/
#ifdef LIBVNCSERVER_HAVE_LIBZ
/*
* ultrazip.c - handle ultrazip encoding.
*
@ -210,5 +208,3 @@ HandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh)
}
#undef CARDBPP
#endif

@ -377,7 +377,7 @@ static int HandleZRLETile(rfbClient* client,
#undef HandleZRLETile
#undef UncompressCPixel
#undef REALBPP
#undef UNCOMP
#endif
#undef UNCOMP

@ -317,7 +317,12 @@ rfbAuthProcessClientMessage(rfbClientPtr cl)
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
rfbLogPerror("rfbAuthProcessClientMessage: write");
}
rfbCloseClient(cl);
/* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
if (cl->protocolMinorVersion > 7) {
rfbClientConnFailed(cl, "password check failed!");
}
else
rfbCloseClient(cl);
return;
}

@ -41,7 +41,7 @@ static char *rreBeforeBuf = NULL;
static int rreAfterBufSize = 0;
static char *rreAfterBuf = NULL;
static int rreAfterBufLen;
static int rreAfterBufLen = 0;
static int subrectEncode8(uint8_t *data, int w, int h);
static int subrectEncode16(uint16_t *data, int w, int h);
@ -145,9 +145,9 @@ rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl,
return rfbSendRectEncodingRaw(cl, x, y, w, h);
}
cl->rectanglesSent[rfbEncodingCoRRE]++;
cl->bytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader
+ sz_rfbRREHeader + rreAfterBufLen);
rfbStatRecordEncodingSent(cl,rfbEncodingCoRRE,
sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + rreAfterBufLen,
sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
> UPDATE_BUF_SIZE)

@ -78,9 +78,6 @@ rfbSendCursorShape(rfbClientPtr cl)
sz_rfbFramebufferUpdateRectHeader);
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
cl->cursorShapeBytesSent += sz_rfbFramebufferUpdateRectHeader;
cl->cursorShapeUpdatesSent++;
if (!rfbSendUpdateBuf(cl))
return FALSE;
@ -167,9 +164,8 @@ rfbSendCursorShape(rfbClientPtr cl)
}
/* Send everything we have prepared in the cl->updateBuf[]. */
cl->cursorShapeBytesSent += (cl->ublen - saved_ublen);
cl->cursorShapeUpdatesSent++;
rfbStatRecordMessageSent(cl, (cl->useRichCursorEncoding ? rfbEncodingRichCursor : rfbEncodingXCursor),
sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen), sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen));
if (!rfbSendUpdateBuf(cl))
return FALSE;
@ -201,8 +197,7 @@ rfbSendCursorPos(rfbClientPtr cl)
sz_rfbFramebufferUpdateRectHeader);
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
cl->cursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader;
cl->cursorPosUpdatesSent++;
rfbStatRecordMessageSent(cl, rfbEncodingPointerPos, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
if (!rfbSendUpdateBuf(cl))
return FALSE;

@ -44,7 +44,7 @@ rfbSendRectEncodingHextile(rfbClientPtr cl,
int h)
{
rfbFramebufferUpdateRectHeader rect;
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
if (!rfbSendUpdateBuf(cl))
return FALSE;
@ -60,8 +60,9 @@ rfbSendRectEncodingHextile(rfbClientPtr cl,
sz_rfbFramebufferUpdateRectHeader);
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
cl->rectanglesSent[rfbEncodingHextile]++;
cl->bytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader;
rfbStatRecordEncodingSent(cl, rfbEncodingHextile,
sz_rfbFramebufferUpdateRectHeader,
sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h);
switch (cl->format.bitsPerPixel) {
case 8:
@ -136,6 +137,7 @@ sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) {
startUblen = cl->ublen; \
cl->updateBuf[startUblen] = 0; \
cl->ublen++; \
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
\
testColours##bpp(clientPixelData, w * h, \
&mono, &solid, &newBg, &newFg); \
@ -148,7 +150,6 @@ sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) {
} \
\
if (solid) { \
cl->bytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
continue; \
} \
\
@ -175,15 +176,15 @@ sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) {
(*cl->translateFn)(cl->translateLookupTable, \
&(cl->screen->serverFormat), &cl->format, fbptr, \
(char *)clientPixelData, \
cl->scaledScreen->paddedWidthInBytes, w, h); \
cl->scaledScreen->paddedWidthInBytes, w, h); \
\
memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
w * h * (bpp/8)); \
\
cl->ublen += w * h * (bpp/8); \
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \
w * h * (bpp/8)); \
} \
\
cl->bytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
} \
} \
\
@ -210,6 +211,7 @@ subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h,
\
nSubrectsUblen = cl->ublen; \
cl->ublen++; \
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
\
for (y=0; y<h; y++) { \
line = data+(y*w); \
@ -268,6 +270,7 @@ subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h,
\
cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
\
/* \
* Now mark the subrect as done. \

@ -495,22 +495,40 @@ clientInput(void *data)
pthread_create(&output_thread, NULL, clientOutput, (void *)cl);
while (1) {
fd_set fds;
fd_set rfds, wfds, efds;
struct timeval tv;
int n;
FD_ZERO(&fds);
FD_SET(cl->sock, &fds);
FD_ZERO(&rfds);
FD_SET(cl->sock, &rfds);
FD_ZERO(&efds);
FD_SET(cl->sock, &efds);
/* Are we transferring a file in the background? */
FD_ZERO(&wfds);
if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
FD_SET(cl->sock, &wfds);
tv.tv_sec = 60; /* 1 minute */
tv.tv_usec = 0;
n = select(cl->sock + 1, &fds, NULL, &fds, &tv);
n = select(cl->sock + 1, &rfds, &wfds, &efds, &tv);
if (n < 0) {
rfbLogPerror("ReadExact: select");
break;
}
if (n == 0) /* timeout */
{
rfbSendFileTransferChunk(cl);
continue;
rfbProcessClientMessage(cl);
}
/* We have some space on the transmit queue, send some data */
if (FD_ISSET(cl->sock, &wfds))
rfbSendFileTransferChunk(cl);
if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds))
rfbProcessClientMessage(cl);
if (cl->sock == -1) {
/* Client has disconnected. */
break;
@ -818,6 +836,10 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
screen->handleEventsEagerly = FALSE;
/* Emulate UltraVNC Server by default */
screen->protocolMajorVersion = 3;
screen->protocolMinorVersion = 6;
if(!rfbProcessArguments(screen,argc,argv)) {
free(screen);
return NULL;

File diff suppressed because it is too large Load Diff

@ -40,7 +40,7 @@ static char *rreBeforeBuf = NULL;
static int rreAfterBufSize = 0;
static char *rreAfterBuf = NULL;
static int rreAfterBufLen;
static int rreAfterBufLen=0;
static int subrectEncode8(uint8_t *data, int w, int h);
static int subrectEncode16(uint16_t *data, int w, int h);
@ -112,9 +112,9 @@ rfbSendRectEncodingRRE(rfbClientPtr cl,
return rfbSendRectEncodingRaw(cl, x, y, w, h);
}
cl->rectanglesSent[rfbEncodingRRE]++;
cl->bytesSent[rfbEncodingRRE] += (sz_rfbFramebufferUpdateRectHeader
+ sz_rfbRREHeader + rreAfterBufLen);
rfbStatRecordEncodingSent(cl, rfbEncodingRRE,
sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + rreAfterBufLen,
sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
> UPDATE_BUF_SIZE)

@ -128,8 +128,8 @@ void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int
*h = (int)h2;
/* Small changes for a thumbnail may be scaled to zero */
if (*w==0) *w++;
if (*h==0) *h++;
if (*w==0) (*w)++;
if (*h==0) (*h)++;
/* scaling from small to big may overstep the size a bit */
if (*x+*w > to->width) *w=to->width - *x;
if (*y+*h > to->height) *h=to->height - *y;
@ -212,7 +212,9 @@ void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, in
pixel_value += (srcptr2[z] << (8 * z));
break;
}
//srcptr2 += bytesPerPixel;
/*
srcptr2 += bytesPerPixel;
*/
red += ((pixel_value >> redShift) & redMax);
green += ((pixel_value >> greenShift) & greenMax);

@ -239,8 +239,18 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
tv.tv_usec = usec;
nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
if (nfds == 0) {
/* timed out, check for async events */
i = rfbGetClientIterator(rfbScreen);
while((cl = rfbClientIteratorNext(i))) {
if (cl->onHold)
continue;
if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
rfbSendFileTransferChunk(cl);
}
rfbReleaseClientIterator(i);
return result;
}
if (nfds < 0) {
#ifdef WIN32
errno = WSAGetLastError();
@ -332,11 +342,17 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
i = rfbGetClientIterator(rfbScreen);
while((cl = rfbClientIteratorNext(i))) {
if (cl->onHold)
continue;
if (FD_ISSET(cl->sock, &fds) &&
FD_ISSET(cl->sock, &(rfbScreen->allFds)))
rfbProcessClientMessage(cl);
if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
{
if (FD_ISSET(cl->sock, &fds))
rfbProcessClientMessage(cl);
else
rfbSendFileTransferChunk(cl);
}
}
rfbReleaseClientIterator(i);
} while(rfbScreen->handleEventsEagerly);

@ -26,90 +26,434 @@
#include <rfb/rfb.h>
static const char* encNames[] = {
"raw", "copyRect", "RRE", "[encoding 3]", "CoRRE", "hextile",
"zlib", "tight", "[encoding 8]", "ultra", "[encoding 10]",
"[encoding 11]", "[encoding 12]", "[encoding 13]", "[encoding 14]",
"[encoding 15]",
"ZRLE", "[encoding 17]", "[encoding 18]", "[encoding 19]", "[encoding 20]"
};
char *messageNameServer2Client(uint32_t type, char *buf, int len);
char *messageNameClient2Server(uint32_t type, char *buf, int len);
char *encodingName(uint32_t enc, char *buf, int len);
rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type);
rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type);
void
rfbResetStats(rfbClientPtr cl)
void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
void rfbResetStats(rfbClientPtr cl);
void rfbPrintStats(rfbClientPtr cl);
char *messageNameServer2Client(uint32_t type, char *buf, int len) {
if (buf==NULL) return "error";
switch (type) {
case rfbFramebufferUpdate: snprintf(buf, len, "FramebufferUpdate"); break;
case rfbSetColourMapEntries: snprintf(buf, len, "SetColourMapEntries"); break;
case rfbBell: snprintf(buf, len, "Bell"); break;
case rfbServerCutText: snprintf(buf, len, "ServerCutText"); break;
case rfbResizeFrameBuffer: snprintf(buf, len, "ResizeFrameBuffer"); break;
case rfbKeyFrameUpdate: snprintf(buf, len, "KeyFrameUpdate"); break;
case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break;
case rfbTextChat: snprintf(buf, len, "TextChat"); break;
case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break;
default:
snprintf(buf, len, "server2client(0x%04X)", type);
}
return buf;
}
char *messageNameClient2Server(uint32_t type, char *buf, int len) {
if (buf==NULL) return "error";
switch (type) {
case rfbSetPixelFormat: snprintf(buf, len, "SetPixelFormat"); break;
case rfbFixColourMapEntries: snprintf(buf, len, "FixColourMapEntries"); break;
case rfbSetEncodings: snprintf(buf, len, "SetEncodings"); break;
case rfbFramebufferUpdateRequest: snprintf(buf, len, "FramebufferUpdate"); break;
case rfbKeyEvent: snprintf(buf, len, "KeyEvent"); break;
case rfbPointerEvent: snprintf(buf, len, "PointerEvent"); break;
case rfbClientCutText: snprintf(buf, len, "ClientCutText"); break;
case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break;
case rfbSetScale: snprintf(buf, len, "SetScale"); break;
case rfbSetServerInput: snprintf(buf, len, "SetServerInput"); break;
case rfbSetSW: snprintf(buf, len, "SetSingleWindow"); break;
case rfbTextChat: snprintf(buf, len, "TextChat"); break;
case rfbKeyFrameRequest: snprintf(buf, len, "KeyFrameRequest"); break;
case rfbPalmVNCSetScaleFactor: snprintf(buf, len, "PalmVNCSetScale"); break;
default:
snprintf(buf, len, "client2server(0x%04X)", type);
}
return buf;
}
char *encodingName(uint32_t type, char *buf, int len) {
if (buf==NULL) return "error";
switch (type) {
case rfbEncodingRaw: snprintf(buf, len, "raw"); break;
case rfbEncodingCopyRect: snprintf(buf, len, "copyRect"); break;
case rfbEncodingRRE: snprintf(buf, len, "RRE"); break;
case rfbEncodingCoRRE: snprintf(buf, len, "CoRRE"); break;
case rfbEncodingHextile: snprintf(buf, len, "hextile"); break;
case rfbEncodingZlib: snprintf(buf, len, "zlib"); break;
case rfbEncodingTight: snprintf(buf, len, "tight"); break;
case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break;
case rfbEncodingUltra: snprintf(buf, len, "ultra"); break;
case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break;
case rfbEncodingCache: snprintf(buf, len, "cache"); break;
case rfbEncodingCacheEnable: snprintf(buf, len, "cacheEnable"); break;
case rfbEncodingXOR_Zlib: snprintf(buf, len, "xorZlib"); break;
case rfbEncodingXORMonoColor_Zlib: snprintf(buf, len, "xorMonoZlib"); break;
case rfbEncodingXORMultiColor_Zlib: snprintf(buf, len, "xorColorZlib"); break;
case rfbEncodingSolidColor: snprintf(buf, len, "solidColor"); break;
case rfbEncodingXOREnable: snprintf(buf, len, "xorEnable"); break;
case rfbEncodingCacheZip: snprintf(buf, len, "cacheZip"); break;
case rfbEncodingSolMonoZip: snprintf(buf, len, "monoZip"); break;
case rfbEncodingUltraZip: snprintf(buf, len, "ultraZip"); break;
case rfbEncodingXCursor: snprintf(buf, len, "Xcursor"); break;
case rfbEncodingRichCursor: snprintf(buf, len, "RichCursor"); break;
case rfbEncodingPointerPos: snprintf(buf, len, "PointerPos"); break;
case rfbEncodingLastRect: snprintf(buf, len, "LastRect"); break;
case rfbEncodingNewFBSize: snprintf(buf, len, "NewFBSize"); break;
case rfbEncodingKeyboardLedState: snprintf(buf, len, "LedState"); break;
case rfbEncodingSupportedMessages: snprintf(buf, len, "SupportedMessages"); break;
case rfbEncodingSupportedEncodings: snprintf(buf, len, "SupportedEncodings"); break;
case rfbEncodingServerIdentity: snprintf(buf, len, "ServerIdentity"); break;
case rfbEncodingCompressLevel0: snprintf(buf, len, "CompressLevel0"); break;
case rfbEncodingCompressLevel1: snprintf(buf, len, "CompressLevel1"); break;
case rfbEncodingCompressLevel2: snprintf(buf, len, "CompressLevel2"); break;
case rfbEncodingCompressLevel3: snprintf(buf, len, "CompressLevel3"); break;
case rfbEncodingCompressLevel4: snprintf(buf, len, "CompressLevel4"); break;
case rfbEncodingCompressLevel5: snprintf(buf, len, "CompressLevel5"); break;
case rfbEncodingCompressLevel6: snprintf(buf, len, "CompressLevel6"); break;
case rfbEncodingCompressLevel7: snprintf(buf, len, "CompressLevel7"); break;
case rfbEncodingCompressLevel8: snprintf(buf, len, "CompressLevel8"); break;
case rfbEncodingCompressLevel9: snprintf(buf, len, "CompressLevel9"); break;
case rfbEncodingQualityLevel0: snprintf(buf, len, "QualityLevel0"); break;
case rfbEncodingQualityLevel1: snprintf(buf, len, "QualityLevel1"); break;
case rfbEncodingQualityLevel2: snprintf(buf, len, "QualityLevel2"); break;
case rfbEncodingQualityLevel3: snprintf(buf, len, "QualityLevel3"); break;
case rfbEncodingQualityLevel4: snprintf(buf, len, "QualityLevel4"); break;
case rfbEncodingQualityLevel5: snprintf(buf, len, "QualityLevel5"); break;
case rfbEncodingQualityLevel6: snprintf(buf, len, "QualityLevel6"); break;
case rfbEncodingQualityLevel7: snprintf(buf, len, "QualityLevel7"); break;
case rfbEncodingQualityLevel8: snprintf(buf, len, "QualityLevel8"); break;
case rfbEncodingQualityLevel9: snprintf(buf, len, "QualityLevel9"); break;
default:
snprintf(buf, len, "encoding(0x%04X)", type);
}
return buf;
}
rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type)
{
int i;
for (i = 0; i < MAX_ENCODINGS; i++) {
cl->bytesSent[i] = 0;
cl->rectanglesSent[i] = 0;
rfbStatList *ptr;
if (cl==NULL) return NULL;
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
{
if (ptr->type==type) return ptr;
}
/* Well, we are here... need to *CREATE* an entry */
ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
if (ptr!=NULL)
{
memset((char *)ptr, 0, sizeof(rfbStatList));
ptr->type = type;
/* add to the top of the list */
ptr->Next = cl->statEncList;
cl->statEncList = ptr;
}
cl->lastRectMarkersSent = 0;
cl->lastRectBytesSent = 0;
cl->cursorShapeBytesSent = 0;
cl->cursorShapeUpdatesSent = 0;
cl->cursorPosBytesSent = 0;
cl->cursorPosUpdatesSent = 0;
cl->framebufferUpdateMessagesSent = 0;
cl->rawBytesEquivalent = 0;
cl->keyEventsRcvd = 0;
cl->pointerEventsRcvd = 0;
return ptr;
}
void
rfbPrintStats(rfbClientPtr cl)
rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type)
{
int i;
int totalRectanglesSent = 0;
int totalBytesSent = 0;
rfbStatList *ptr;
if (cl==NULL) return NULL;
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
{
if (ptr->type==type) return ptr;
}
/* Well, we are here... need to *CREATE* an entry */
ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
if (ptr!=NULL)
{
memset((char *)ptr, 0, sizeof(rfbStatList));
ptr->type = type;
/* add to the top of the list */
ptr->Next = cl->statMsgList;
cl->statMsgList = ptr;
}
return ptr;
}
rfbLog("Statistics:\n");
void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */
{
rfbStatList *ptr;
if ((cl->keyEventsRcvd != 0) || (cl->pointerEventsRcvd != 0))
rfbLog(" key events received %d, pointer events %d\n",
cl->keyEventsRcvd, cl->pointerEventsRcvd);
ptr = rfbStatLookupEncoding(cl, type);
if (ptr!=NULL)
ptr->bytesSent += byteCount;
}
for (i = 0; i < MAX_ENCODINGS; i++) {
totalRectanglesSent += cl->rectanglesSent[i];
totalBytesSent += cl->bytesSent[i];
void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
{
rfbStatList *ptr;
ptr = rfbStatLookupEncoding(cl, type);
if (ptr!=NULL)
{
ptr->sentCount++;
ptr->bytesSent += byteCount;
ptr->bytesSentIfRaw += byteIfRaw;
}
}
totalRectanglesSent += (cl->cursorShapeUpdatesSent +
cl->cursorPosUpdatesSent +
cl->lastRectMarkersSent);
totalBytesSent += (cl->cursorShapeBytesSent +
cl->cursorPosBytesSent +
cl->lastRectBytesSent);
void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
{
rfbStatList *ptr;
rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n",
cl->framebufferUpdateMessagesSent, totalRectanglesSent,
totalBytesSent);
ptr = rfbStatLookupEncoding(cl, type);
if (ptr!=NULL)
{
ptr->rcvdCount++;
ptr->bytesRcvd += byteCount;
ptr->bytesRcvdIfRaw += byteIfRaw;
}
}
if (cl->lastRectMarkersSent != 0)
rfbLog(" LastRect and NewFBSize markers %d, bytes %d\n",
cl->lastRectMarkersSent, cl->lastRectBytesSent);
void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
{
rfbStatList *ptr;
if (cl->cursorShapeUpdatesSent != 0)
rfbLog(" cursor shape updates %d, bytes %d\n",
cl->cursorShapeUpdatesSent, cl->cursorShapeBytesSent);
ptr = rfbStatLookupMessage(cl, type);
if (ptr!=NULL)
{
ptr->sentCount++;
ptr->bytesSent += byteCount;
ptr->bytesSentIfRaw += byteIfRaw;
}
}
if (cl->cursorPosUpdatesSent != 0)
rfbLog(" cursor position updates %d, bytes %d\n",
cl->cursorPosUpdatesSent, cl->cursorPosBytesSent);
void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
{
rfbStatList *ptr;
for (i = 0; i < MAX_ENCODINGS; i++) {
if (cl->rectanglesSent[i] != 0)
rfbLog(" %s rectangles %d, bytes %d\n",
encNames[i], cl->rectanglesSent[i], cl->bytesSent[i]);
ptr = rfbStatLookupMessage(cl, type);
if (ptr!=NULL)
{
ptr->rcvdCount++;
ptr->bytesRcvd += byteCount;
ptr->bytesRcvdIfRaw += byteIfRaw;
}
}
int rfbStatGetSentBytes(rfbClientPtr cl)
{
rfbStatList *ptr=NULL;
int bytes=0;
if (cl==NULL) return 0;
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
bytes += ptr->bytesSent;
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
bytes += ptr->bytesSent;
return bytes;
}
int rfbStatGetSentBytesIfRaw(rfbClientPtr cl)
{
rfbStatList *ptr=NULL;
int bytes=0;
if (cl==NULL) return 0;
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
bytes += ptr->bytesSentIfRaw;
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
bytes += ptr->bytesSentIfRaw;
return bytes;
}
int rfbStatGetRcvdBytes(rfbClientPtr cl)
{
rfbStatList *ptr=NULL;
int bytes=0;
if (cl==NULL) return 0;
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
bytes += ptr->bytesRcvd;
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
bytes += ptr->bytesRcvd;
return bytes;
}
int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl)
{
rfbStatList *ptr=NULL;
int bytes=0;
if (cl==NULL) return 0;
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
bytes += ptr->bytesRcvdIfRaw;
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
bytes += ptr->bytesRcvdIfRaw;
return bytes;
}
int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type)
{
rfbStatList *ptr=NULL;
if (cl==NULL) return 0;
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
if (ptr->type==type) return ptr->sentCount;
return 0;
}
int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type)
{
rfbStatList *ptr=NULL;
if (cl==NULL) return 0;
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
if (ptr->type==type) return ptr->rcvdCount;
return 0;
}
int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type)
{
rfbStatList *ptr=NULL;
if (cl==NULL) return 0;
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
if (ptr->type==type) return ptr->sentCount;
return 0;
}
int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type)
{
rfbStatList *ptr=NULL;
if (cl==NULL) return 0;
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
if (ptr->type==type) return ptr->rcvdCount;
return 0;
}
if ((totalBytesSent - cl->bytesSent[rfbEncodingCopyRect]) != 0) {
rfbLog(" raw bytes equivalent %d, compression ratio %f\n",
cl->rawBytesEquivalent,
(double)cl->rawBytesEquivalent
/ (double)(totalBytesSent
- cl->bytesSent[rfbEncodingCopyRect]-
cl->cursorShapeBytesSent -
cl->cursorPosBytesSent -
cl->lastRectBytesSent));