/* * stats.c */ /* * 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. */ #include #ifdef _MSC_VER #define snprintf _snprintf /* Missing in MSVC */ #endif 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 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 rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break; case rfbTextChat: snprintf(buf, len, "TextChat"); break; case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break; case rfbXvp: snprintf(buf, len, "XvpServerMessage"); break; default: snprintf(buf, len, "svr2cli-0x%08X", 0xFF); } 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 rfbPalmVNCSetScaleFactor: snprintf(buf, len, "PalmVNCSetScale"); break; case rfbXvp: snprintf(buf, len, "XvpClientMessage"); break; default: snprintf(buf, len, "cli2svr-0x%08X", type); } return buf; } /* Encoding name must be <=16 characters to fit nicely on the status output in * an 80 column terminal window */ 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 rfbEncodingTightPng: snprintf(buf, len, "tightPng"); break; case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break; case rfbEncodingUltra: snprintf(buf, len, "ultra"); break; case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break; case rfbEncodingZYWRLE: snprintf(buf, len, "ZYWRLE"); 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, "SupportedMessage"); break; case rfbEncodingSupportedEncodings: snprintf(buf, len, "SupportedEncoding"); break; case rfbEncodingServerIdentity: snprintf(buf, len, "ServerIdentify"); break; /* The following lookups do not report in stats */ 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, "Enc(0x%08X)", type); } return buf; } rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type) { 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; } return ptr; } rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type) { 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; } void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */ { rfbStatList *ptr; ptr = rfbStatLookupEncoding(cl, type); if (ptr!=NULL) ptr->bytesSent += byteCount; } 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; } } void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) { rfbStatList *ptr; ptr = rfbStatLookupEncoding(cl, type); if (ptr!=NULL) { ptr->rcvdCount++; ptr->bytesRcvd += byteCount; ptr->bytesRcvdIfRaw += byteIfRaw; } } void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) { rfbStatList *ptr; ptr = rfbStatLookupMessage(cl, type); if (ptr!=NULL) { ptr->sentCount++; ptr->bytesSent += byteCount; ptr->bytesSentIfRaw += byteIfRaw; } } void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) { rfbStatList *ptr; 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; } void rfbResetStats(rfbClientPtr cl) { rfbStatList *ptr; if (cl==NULL) return; while (cl->statEncList!=NULL) { ptr = cl->statEncList; cl->statEncList = ptr->Next; free(ptr); } while (cl->statMsgList!=NULL) { ptr = cl->statMsgList; cl->statMsgList = ptr->Next; free(ptr); } } void rfbPrintStats(rfbClientPtr cl) { rfbStatList *ptr=NULL; char encBuf[64]; double savings=0.0; int totalRects=0; double totalBytes=0.0; double totalBytesIfRaw=0.0; char *name=NULL; int bytes=0; int bytesIfRaw=0; int count=0; if (cl==NULL) return; rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Transmit","RawEquiv","saved"); for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) { name = messageNameServer2Client(ptr->type, encBuf, sizeof(encBuf)); count = ptr->sentCount; bytes = ptr->bytesSent; bytesIfRaw = ptr->bytesSentIfRaw; savings = 0.0; if (bytesIfRaw>0.0) savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); if ((bytes>0) || (count>0) || (bytesIfRaw>0)) rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", name, count, bytes, bytesIfRaw, savings); totalRects += count; totalBytes += bytes; totalBytesIfRaw += bytesIfRaw; } for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) { name = encodingName(ptr->type, encBuf, sizeof(encBuf)); count = ptr->sentCount; bytes = ptr->bytesSent; bytesIfRaw = ptr->bytesSentIfRaw; savings = 0.0; if (bytesIfRaw>0.0) savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); if ((bytes>0) || (count>0) || (bytesIfRaw>0)) rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", name, count, bytes, bytesIfRaw, savings); totalRects += count; totalBytes += bytes; totalBytesIfRaw += bytesIfRaw; } savings=0.0; if (totalBytesIfRaw>0.0) savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0); rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n", "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings); totalRects=0.0; totalBytes=0.0; totalBytesIfRaw=0.0; rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Received","RawEquiv","saved"); for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) { name = messageNameClient2Server(ptr->type, encBuf, sizeof(encBuf)); count = ptr->rcvdCount; bytes = ptr->bytesRcvd; bytesIfRaw = ptr->bytesRcvdIfRaw; savings = 0.0; if (bytesIfRaw>0.0) savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); if ((bytes>0) || (count>0) || (bytesIfRaw>0)) rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", name, count, bytes, bytesIfRaw, savings); totalRects += count; totalBytes += bytes; totalBytesIfRaw += bytesIfRaw; } for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) { name = encodingName(ptr->type, encBuf, sizeof(encBuf)); count = ptr->rcvdCount; bytes = ptr->bytesRcvd; bytesIfRaw = ptr->bytesRcvdIfRaw; savings = 0.0; if (bytesIfRaw>0.0) savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); if ((bytes>0) || (count>0) || (bytesIfRaw>0)) rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", name, count, bytes, bytesIfRaw, savings); totalRects += count; totalBytes += bytes; totalBytesIfRaw += bytesIfRaw; } savings=0.0; if (totalBytesIfRaw>0.0) savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0); rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n", "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings); }